Add packages/mosaic registry schemas, validation, read-only CLI; pin pi 0.85.1 (#1499)
This commit is contained in:
@@ -1898,3 +1898,7 @@ Independent R1 SUPPORTED the Gate 7 reconciliation; Jason answered yes to all th
|
||||
## 2026-09-10 — registry plan fully resolved
|
||||
|
||||
ms-grill-me rounds resolved gates 2/3/4/8/9/10 and the per-execution selection model; PI-REFRESH-ROCKO-1 established the 0.85.1 noninteractive refresh path read-only; owner Q15(a) selected pi auth check; GATE7-FINAL-FILBERT-1 APPROVED and corroborated the findings against the pinned 0.84.4 install. Committed 224147ec and 86e009dd (with intervening registration commits), pushed, remote identities verified. All ten gates carry owner rulings. Implementation awaits a separately chartered increment; pi pin moves to 0.85.1 within that increment.
|
||||
|
||||
## 2026-09-10 — #1499 increment 1 implemented (pre-review)
|
||||
|
||||
packages/mosaic added: provider/account/profile/selection/harness schemas with strict unknown-field and ID validation, allowInsecureTransport rule (plain-http custom endpoints only), fork-pin field, harness id==executable rule (gate 1), registry tree loader with cross-reference integrity, read-only validate/list CLI with secret-free projections. 15 package tests pass. Pi pin moved 0.84.4 -> 0.85.1 (package.json, lockfile regenerated, three fixture scripts updated). Suites after pin: config/auth/conductor/release green; task suite shows exactly the one pre-existing failure also present at stashed baseline (no agent identity on headless run); one earlier mock-adapter failure did not recur on rerun and is recorded as flaky-unreproduced. Implementation awaits independent review before commit/push consideration per charter; no materializer/refresh/credential paths exist in this code.
|
||||
|
||||
Generated
+611
-143
@@ -1,24 +1,25 @@
|
||||
{
|
||||
"name": "mosaic-stack-dev-test",
|
||||
"version": "0.1.0",
|
||||
"version": "0.0.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "mosaic-stack-dev-test",
|
||||
"version": "0.1.0",
|
||||
"version": "0.0.3",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@earendil-works/pi-coding-agent": "0.84.4"
|
||||
"@earendil-works/pi-coding-agent": "0.85.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@anthropic-ai/sdk": {
|
||||
"version": "0.91.1",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.91.1.tgz",
|
||||
"integrity": "sha512-LAmu761tSN9r66ixvmciswUj/ZC+1Q4iAfpedTfSVLeswRwnY3n2Nb6Tsk+cLPP28aLOPWeMgIuTuCcMC6W/iw==",
|
||||
"version": "0.123.0",
|
||||
"resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.123.0.tgz",
|
||||
"integrity": "sha512-Y9oX9mPNGZClHQOFqrWRk43Srcu/UHuPq3rfxxOq7JgW0gi+lJA2MAOK4Ul3k/+AUrwRWFJvd0tK3oC0Pw25dw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"json-schema-to-ts": "^3.1.1"
|
||||
"json-schema-to-ts": "^3.1.1",
|
||||
"standardwebhooks": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"anthropic-ai-sdk": "bin/cli"
|
||||
@@ -107,9 +108,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/core": {
|
||||
"version": "3.977.9",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.977.9.tgz",
|
||||
"integrity": "sha512-reqPFEQrZxDZpeGj4PFMepBeR5LGYHRqq/L0motTzgFkCRBA4rFdaVXDSLYyGHhxVz7sT2PDnPN9CluGSfgyJA==",
|
||||
"version": "3.978.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.978.0.tgz",
|
||||
"integrity": "sha512-2yX9LUmxPklVjSGTb8dfnWRJSiFQ3TeH2nn7G1mdKHTfnabzF0+gfrS8rYfLWmZrQ8A3mEcxMJjRc51dL5KWaA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
@@ -126,12 +127,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-env": {
|
||||
"version": "3.972.70",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.70.tgz",
|
||||
"integrity": "sha512-H404B7dJl2mCrBqahDEYsanB0xhdDp6tXnXcTUnXmmpy2Q3J0Ho0bUajZ2jr/RdwzCyS59Gi8xXIFwPLGBl6Uw==",
|
||||
"version": "3.972.71",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.71.tgz",
|
||||
"integrity": "sha512-JN+JHruYZw3GUZB8YGAlDk4wTDPOEAEEdEzj5nS0xodWR4smzHsN7PnK2j6IeOsDIj2aqua5DSbhXl9Gtf90FQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/types": "^4.17.2",
|
||||
@@ -142,12 +143,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-http": {
|
||||
"version": "3.972.72",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.72.tgz",
|
||||
"integrity": "sha512-X98zYOrVOeuosCX+6ktf29FC2N2GHPLia7qv6mzPzTc+RPAuHWCDS++Z6JK7eGYqb/v6uaW7bAXaOvDBfol+0w==",
|
||||
"version": "3.972.73",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.73.tgz",
|
||||
"integrity": "sha512-uyYYnJOnlis8uQzaYGPd7N1JoioCoNpXgnkXYixsWJXHXgXyYi8WXJSDfofxJeWfQIGWLe2Nwyq60Uc7MZdVOg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/fetch-http-handler": "^5.7.2",
|
||||
@@ -160,13 +161,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/node-http-handler": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.12.0.tgz",
|
||||
"integrity": "sha512-0mq1pHadfyXCYCqm2cNpbjNIT+fbaUpNxewZb/YNr2L0IrEVMOb8gM/Fl4K6XvHCW3uSNDFwPl/+iKm0bx9jYg==",
|
||||
"version": "4.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.12.1.tgz",
|
||||
"integrity": "sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/types": "^4.17.2",
|
||||
"@smithy/types": "^4.18.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -174,19 +175,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-ini": {
|
||||
"version": "3.973.15",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.15.tgz",
|
||||
"integrity": "sha512-Rykg6s5ceBuynMOGWgoowO4N+27JfnqXAnVaSunZl0hOO1XodSrxGNz6sCEbnmS0lAfQZDKyb3fbr46gSuv6Sg==",
|
||||
"version": "3.973.16",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.16.tgz",
|
||||
"integrity": "sha512-i++ly+0Uxa+u3ebSSyr0S/3CFhFJDxCXT3+Zj+mW2bXenEx5bKGCdTIKFu39SgXBNhWDjex/8cXUx9MUTMCrTw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/credential-provider-env": "^3.972.70",
|
||||
"@aws-sdk/credential-provider-http": "^3.972.72",
|
||||
"@aws-sdk/credential-provider-login": "^3.972.77",
|
||||
"@aws-sdk/credential-provider-process": "^3.972.70",
|
||||
"@aws-sdk/credential-provider-sso": "^3.973.14",
|
||||
"@aws-sdk/credential-provider-web-identity": "^3.972.76",
|
||||
"@aws-sdk/nested-clients": "^3.997.44",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/credential-provider-env": "^3.972.71",
|
||||
"@aws-sdk/credential-provider-http": "^3.972.73",
|
||||
"@aws-sdk/credential-provider-login": "^3.972.78",
|
||||
"@aws-sdk/credential-provider-process": "^3.972.71",
|
||||
"@aws-sdk/credential-provider-sso": "^3.973.15",
|
||||
"@aws-sdk/credential-provider-web-identity": "^3.972.77",
|
||||
"@aws-sdk/nested-clients": "^3.997.45",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/credential-provider-imds": "^4.4.16",
|
||||
@@ -198,13 +199,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-login": {
|
||||
"version": "3.972.77",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.77.tgz",
|
||||
"integrity": "sha512-Jb59xfEISoN5mmbnA+HYqdtrSX3CgCtJoof+V5D8/TgUI56W63GEEd5Y58WijU3Ou6+WEgaLD1feVzaRXV5IDQ==",
|
||||
"version": "3.972.78",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.78.tgz",
|
||||
"integrity": "sha512-eUtswnXu0+Ii9ieRK+0L7aPFV3Z/dnW2VntJzjBP9xs8s+8p5nBNuymIXtXwZ+5r5+XJP3e32nMkuZ/r0HozEA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/nested-clients": "^3.997.44",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/nested-clients": "^3.997.45",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/types": "^4.17.2",
|
||||
@@ -215,17 +216,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-node": {
|
||||
"version": "3.972.82",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.82.tgz",
|
||||
"integrity": "sha512-znDkEOGXB8W3kG1LJUKP3foBZY/9qLM0eil/DxWXSp37XsdsRLQHE/d/OaCGGVgKpA6znR38h/+INk8do1FjiA==",
|
||||
"version": "3.972.83",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.83.tgz",
|
||||
"integrity": "sha512-jdso7ejzfRnatxMUZK4S/U6KbaDPCvfIV4XL+IQAPFDBt5rj5Fq595euqlK8Le4lNCMFR9oUpt+1l0aMgaayOQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/credential-provider-env": "^3.972.70",
|
||||
"@aws-sdk/credential-provider-http": "^3.972.72",
|
||||
"@aws-sdk/credential-provider-ini": "^3.973.15",
|
||||
"@aws-sdk/credential-provider-process": "^3.972.70",
|
||||
"@aws-sdk/credential-provider-sso": "^3.973.14",
|
||||
"@aws-sdk/credential-provider-web-identity": "^3.972.76",
|
||||
"@aws-sdk/credential-provider-env": "^3.972.71",
|
||||
"@aws-sdk/credential-provider-http": "^3.972.73",
|
||||
"@aws-sdk/credential-provider-ini": "^3.973.16",
|
||||
"@aws-sdk/credential-provider-process": "^3.972.71",
|
||||
"@aws-sdk/credential-provider-sso": "^3.973.15",
|
||||
"@aws-sdk/credential-provider-web-identity": "^3.972.77",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/credential-provider-imds": "^4.4.16",
|
||||
@@ -237,12 +238,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-process": {
|
||||
"version": "3.972.70",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.70.tgz",
|
||||
"integrity": "sha512-2ry03fGRJr4sV3jI+ocjj5JqALnFD6ymM5KiNCDZMvq8bX2GSbE0vji4aM43TVCl2nXqqLRZaUxdq/KeWRAY4Q==",
|
||||
"version": "3.972.71",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.71.tgz",
|
||||
"integrity": "sha512-lYmXJa4gvq4xN1lrT5NiP5vIYYKcGWAdj8y+8o6dlcateB5eF3Dn8DtmjjHKfMBrTPAMr2pebIiX/UOj8c1/UA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/types": "^4.17.2",
|
||||
@@ -253,14 +254,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-sso": {
|
||||
"version": "3.973.14",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.14.tgz",
|
||||
"integrity": "sha512-jkhg/8ocAAoc0RFyLMhCw+/zZh7gystQgd4F4hznNa8P4Cc501PQmxd+jGLiMHodPJ+7Zv/3znM62gZojyasmA==",
|
||||
"version": "3.973.15",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.15.tgz",
|
||||
"integrity": "sha512-6Jhcf4v0pSFdjk1EW2kvzuEBKD+UZ2uNcHUIglKKLndD20YhvkL2kdmDOV5/j4mYuWWwe/a1FQ1aomU86/Cg5Q==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/nested-clients": "^3.997.44",
|
||||
"@aws-sdk/token-providers": "3.1116.0",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/nested-clients": "^3.997.45",
|
||||
"@aws-sdk/token-providers": "3.1129.0",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/types": "^4.17.2",
|
||||
@@ -271,13 +272,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": {
|
||||
"version": "3.1116.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1116.0.tgz",
|
||||
"integrity": "sha512-ygIivKqh8aHzNkucOCXHyIBgBpLPfrSI0mCqXF+vLBsPTUKqj0VSqAY0GFPe7lQl4HntjOcQ+KSyS7oUV2C54Q==",
|
||||
"version": "3.1129.0",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1129.0.tgz",
|
||||
"integrity": "sha512-Sbl3rpzQdsG4ZK2zh0JWUYyZPKKorJlVOddA2T0DVbKJFrsW8J6wgnslxxUH04+WaBMr4A1HzJZvZX0xUvkniA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/nested-clients": "^3.997.44",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/nested-clients": "^3.997.45",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/types": "^4.17.2",
|
||||
@@ -288,13 +289,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/credential-provider-web-identity": {
|
||||
"version": "3.972.76",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.76.tgz",
|
||||
"integrity": "sha512-d3AGyVu759PGr35mEB2s22xxlNEA5rpdxtSPJthfPFJvoQ8dt357iVPECqWfUxXp1toJAvKmbtcIYVGigaGsCA==",
|
||||
"version": "3.972.77",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.77.tgz",
|
||||
"integrity": "sha512-uylIQSUWpfLuH2LovxEEfwzJGM/SabLOfLMg6YXu/E8jJEKUdpdILCVCQCdFvHyu/7dLJOHPMfrSwduxO56NkQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/nested-clients": "^3.997.44",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/nested-clients": "^3.997.45",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/types": "^4.17.2",
|
||||
@@ -335,12 +336,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/middleware-websocket": {
|
||||
"version": "3.972.52",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.52.tgz",
|
||||
"integrity": "sha512-vsPPM+nMbKJlUCFU+eoGZbdxdxDIAX9LbpjSXaR5Ufpmqgp8TdYQnoExhLu4T3umW/JIIPny1ydbhWidZZYokQ==",
|
||||
"version": "3.972.53",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/middleware-websocket/-/middleware-websocket-3.972.53.tgz",
|
||||
"integrity": "sha512-bIrDaMENQmYRBHntOiOheqkiw5+fhKW4Lqb+mS1uqF0VwvdWI22fW2HFgWrng66CmYd+4k8ePlpj38sEfTuMLQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/fetch-http-handler": "^5.7.2",
|
||||
@@ -353,12 +354,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/nested-clients": {
|
||||
"version": "3.997.44",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.44.tgz",
|
||||
"integrity": "sha512-NhEgryjlBF9w38ZXqGymQV28IhkYa1mKhlbYnqIis57AYwWGVYfUPgg/qC2rLRqOUfblxx++irvju10kVTa8Vw==",
|
||||
"version": "3.997.45",
|
||||
"resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.45.tgz",
|
||||
"integrity": "sha512-mooq9Q+jLa18VoM7HouczmslZU60iiB0aKc/Ztnq/luIL1ud0z4DnYprLR/ZO1gp331S9tJctM1HZr7u6YKBXQ==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@aws-sdk/core": "^3.977.9",
|
||||
"@aws-sdk/core": "^3.978.0",
|
||||
"@aws-sdk/signature-v4-multi-region": "^3.996.46",
|
||||
"@aws-sdk/types": "^3.974.5",
|
||||
"@smithy/core": "^3.33.3",
|
||||
@@ -372,13 +373,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aws-sdk/nested-clients/node_modules/@smithy/node-http-handler": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.12.0.tgz",
|
||||
"integrity": "sha512-0mq1pHadfyXCYCqm2cNpbjNIT+fbaUpNxewZb/YNr2L0IrEVMOb8gM/Fl4K6XvHCW3uSNDFwPl/+iKm0bx9jYg==",
|
||||
"version": "4.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.12.1.tgz",
|
||||
"integrity": "sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/types": "^4.17.2",
|
||||
"@smithy/types": "^4.18.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -473,14 +474,27 @@
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@earendil-works/pi-agent-core": {
|
||||
"version": "0.84.4",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.84.4.tgz",
|
||||
"integrity": "sha512-HyUnjaOXj6oN/6SNcr8A1J/ElRQA50FtIE0XUTSKAQVqmdlb9qdojOyUQwF/jULE5+yOEtGuVgi/N1RnBiNG+g==",
|
||||
"node_modules/@earendil-works/chord": {
|
||||
"version": "0.85.1",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/chord/-/chord-0.85.1.tgz",
|
||||
"integrity": "sha512-VDlkEC3dhCzQ5fcyH1OhG19dq+6jCn+rqc/iXFivwDYGR5anwo2RCiXij9PpHhqNR5GuhhE+Er69Zi1Sn4eY6w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@earendil-works/pi-ai": "^0.84.4",
|
||||
"@earendil-works/pi-telemetry": "^0.84.4",
|
||||
"esbuild": "0.28.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@earendil-works/pi-agent-core": {
|
||||
"version": "0.85.1",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.85.1.tgz",
|
||||
"integrity": "sha512-hIXIP3eAWueAYiAl8aMvWCvvZ8Q5gT3Dip5bE5uJyIGh4+YlWRjtMLI4BaeoXoSs93zndjue61u1B/vhefLnuA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@earendil-works/chord": "^0.85.1",
|
||||
"@earendil-works/pi-ai": "^0.85.1",
|
||||
"@earendil-works/pi-telemetry": "^0.85.1",
|
||||
"diff": "8.0.4",
|
||||
"ignore": "7.0.5",
|
||||
"typebox": "1.3.7",
|
||||
@@ -491,14 +505,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@earendil-works/pi-ai": {
|
||||
"version": "0.84.4",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.84.4.tgz",
|
||||
"integrity": "sha512-AClAZxf5+c4RRu44NJPS6wyQy+Nmq+Mzyyrdvm4ZVMNuixelO02RZX4G4Aq1F145Yzp43wnM5S+hLlSI7ypfVw==",
|
||||
"version": "0.85.1",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.85.1.tgz",
|
||||
"integrity": "sha512-+VgVIJDkDO2efYJKEEqvPTH4zmnIaXdAppGbO+vKFA9qy5PdhFiAenuFAkU+oiCSfOC4dMHDyrjdQeL4ZoC5CQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@anthropic-ai/sdk": "0.91.1",
|
||||
"@anthropic-ai/sdk": "0.123.0",
|
||||
"@aws-sdk/client-bedrock-runtime": "3.1048.0",
|
||||
"@earendil-works/pi-telemetry": "^0.84.4",
|
||||
"@earendil-works/pi-telemetry": "^0.85.1",
|
||||
"@google/genai": "1.52.0",
|
||||
"@smithy/node-http-handler": "4.7.3",
|
||||
"http-proxy-agent": "7.0.2",
|
||||
@@ -514,29 +528,16 @@
|
||||
"node": ">=22.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@earendil-works/pi-client": {
|
||||
"version": "0.84.4",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-client/-/pi-client-0.84.4.tgz",
|
||||
"integrity": "sha512-q398WY/3ZQHTizk7IKxApzqFV0xt4yM9LkSkwyqeLK5Bj5RwRjOWxESt26z4LgNp4O+8hqhqFPf/8fj4H5rE4A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@earendil-works/pi-protocol": "^0.84.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@earendil-works/pi-coding-agent": {
|
||||
"version": "0.84.4",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-coding-agent/-/pi-coding-agent-0.84.4.tgz",
|
||||
"integrity": "sha512-jmOlrqUmvhh/siNWFRXjYLJzhKFIHNsAQaysRwzQPQFnPAaV/vhqHsLH/MBsIISA1Rjj7WTUFR3nJrpXoLx39w==",
|
||||
"version": "0.85.1",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-coding-agent/-/pi-coding-agent-0.85.1.tgz",
|
||||
"integrity": "sha512-FGRN+OHbWaefBPGaTggAdLjrIHW+s2PzLyglz/5dfLzb9of7uuXMXYC0fJIeZTw+shS32o2cuQ9jF7YSDuL/oQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@earendil-works/pi-agent-core": "^0.84.4",
|
||||
"@earendil-works/pi-ai": "^0.84.4",
|
||||
"@earendil-works/pi-client": "^0.84.4",
|
||||
"@earendil-works/pi-protocol": "^0.84.4",
|
||||
"@earendil-works/pi-tui": "^0.84.4",
|
||||
"@earendil-works/chord": "^0.85.1",
|
||||
"@earendil-works/pi-agent-core": "^0.85.1",
|
||||
"@earendil-works/pi-ai": "^0.85.1",
|
||||
"@earendil-works/pi-tui": "^0.85.1",
|
||||
"@silvia-odwyer/photon-node": "0.3.4",
|
||||
"chalk": "5.6.2",
|
||||
"cross-spawn": "7.0.6",
|
||||
@@ -563,31 +564,19 @@
|
||||
"@mariozechner/clipboard": "0.3.9"
|
||||
}
|
||||
},
|
||||
"node_modules/@earendil-works/pi-protocol": {
|
||||
"version": "0.84.4",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-protocol/-/pi-protocol-0.84.4.tgz",
|
||||
"integrity": "sha512-acyE9ozxkMiWiz/xyWpU0O9vwnYv0hyG889Vniv6Sg9c9zfsX+8MePnDNphBacY2Fvm1rxdsGmiVDSZl9yuDFA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"typebox": "1.3.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=22.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@earendil-works/pi-telemetry": {
|
||||
"version": "0.84.4",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-telemetry/-/pi-telemetry-0.84.4.tgz",
|
||||
"integrity": "sha512-8e2CuxM+ht+hedQXTZmi5JVl6/xDK9RpSDL2+MbITevKYQhMZ/z6lJOTFgox3HQyGxO8mOZEtYGVeQNaD4OzqA==",
|
||||
"version": "0.85.1",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-telemetry/-/pi-telemetry-0.85.1.tgz",
|
||||
"integrity": "sha512-Bg/YN6kA7Swja/NQxka8xFdecb4E/auIEGF2G5A25EaQXhRnPj300/7/KpgsDDMYUzHTDAv4RyUxaQPJKW81Rw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=22.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@earendil-works/pi-tui": {
|
||||
"version": "0.84.4",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.84.4.tgz",
|
||||
"integrity": "sha512-nPUnwDkLtupPXnZQYrCwPFcuTydCDqTY6ZbFqhsL4S4kVq0AT418kPa/6uXwtaCD+MjBNBltb7ScTYX65yeE1w==",
|
||||
"version": "0.85.1",
|
||||
"resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.85.1.tgz",
|
||||
"integrity": "sha512-OIzw9efInmO4WOBnD4TxcTdBjmzvYJpzslkgoUro946nEGoYWg5rwv1p4fDt3/JvMx9QybryUCUwlm7j8Dreig==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"get-east-asian-width": "1.6.0",
|
||||
@@ -597,6 +586,422 @@
|
||||
"node": ">=22.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz",
|
||||
"integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz",
|
||||
"integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz",
|
||||
"integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz",
|
||||
"integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz",
|
||||
"integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz",
|
||||
"integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz",
|
||||
"integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz",
|
||||
"integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz",
|
||||
"integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz",
|
||||
"integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz",
|
||||
"integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz",
|
||||
"integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@google/genai": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@google/genai/-/genai-1.52.0.tgz",
|
||||
@@ -906,13 +1311,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@smithy/fetch-http-handler": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.7.2.tgz",
|
||||
"integrity": "sha512-nZyWTmSpJEXl6VtWVMBJve/7x12DZu6sIX1z1a+ZMaHlQQRs9Zpu6NbTe/gmxYXVRpkjxyDYpZ5gx2IM6f/Wkw==",
|
||||
"version": "5.8.0",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.8.0.tgz",
|
||||
"integrity": "sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@smithy/core": "^3.33.2",
|
||||
"@smithy/types": "^4.17.2",
|
||||
"@smithy/core": "^3.33.3",
|
||||
"@smithy/types": "^4.18.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
@@ -960,9 +1365,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@smithy/types": {
|
||||
"version": "4.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.17.2.tgz",
|
||||
"integrity": "sha512-FOKpVZob9MPTn2znRzGrnsMHv7BOsKVw3XiP/cOyYLDVZ9qKp4nifIiSCuUU/fIj5Vu0UOAxCFr+qRAtG0NUkA==",
|
||||
"version": "4.18.0",
|
||||
"resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.18.0.tgz",
|
||||
"integrity": "sha512-CgB6HHWer/vrKps24ulRIbpcpb7K4xAU7SkZ7YHzBPlwHsvsrCJFEXK421s+cJzX+ZrqtA/TuU5w1HzI7k9N8A==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"tslib": "^2.6.2"
|
||||
@@ -997,13 +1402,19 @@
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@stablelib/base64": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz",
|
||||
"integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "26.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.4.1.tgz",
|
||||
"integrity": "sha512-k97ENvZWtvA6yqz5/FS6a7duDgOPEeOQOc2iKS/nY6mX6qJUKtLnWzQS+Xj6tXweyj6ZcTAK2Qecetnvi9nCLA==",
|
||||
"version": "22.20.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.2.tgz",
|
||||
"integrity": "sha512-xlvWf4Vs9n1PEVYwP1n4vvG07M6y8WgvJ2t0vbrWTmijsIHp1cS+uJ2kMIRdY3nHZK0nCYKrPeD171+SzF4/zw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~8.3.0"
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/retry": {
|
||||
@@ -1153,12 +1564,59 @@
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz",
|
||||
"integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.28.1",
|
||||
"@esbuild/android-arm": "0.28.1",
|
||||
"@esbuild/android-arm64": "0.28.1",
|
||||
"@esbuild/android-x64": "0.28.1",
|
||||
"@esbuild/darwin-arm64": "0.28.1",
|
||||
"@esbuild/darwin-x64": "0.28.1",
|
||||
"@esbuild/freebsd-arm64": "0.28.1",
|
||||
"@esbuild/freebsd-x64": "0.28.1",
|
||||
"@esbuild/linux-arm": "0.28.1",
|
||||
"@esbuild/linux-arm64": "0.28.1",
|
||||
"@esbuild/linux-ia32": "0.28.1",
|
||||
"@esbuild/linux-loong64": "0.28.1",
|
||||
"@esbuild/linux-mips64el": "0.28.1",
|
||||
"@esbuild/linux-ppc64": "0.28.1",
|
||||
"@esbuild/linux-riscv64": "0.28.1",
|
||||
"@esbuild/linux-s390x": "0.28.1",
|
||||
"@esbuild/linux-x64": "0.28.1",
|
||||
"@esbuild/netbsd-arm64": "0.28.1",
|
||||
"@esbuild/netbsd-x64": "0.28.1",
|
||||
"@esbuild/openbsd-arm64": "0.28.1",
|
||||
"@esbuild/openbsd-x64": "0.28.1",
|
||||
"@esbuild/openharmony-arm64": "0.28.1",
|
||||
"@esbuild/sunos-x64": "0.28.1",
|
||||
"@esbuild/win32-arm64": "0.28.1",
|
||||
"@esbuild/win32-ia32": "0.28.1",
|
||||
"@esbuild/win32-x64": "0.28.1"
|
||||
}
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-sha256": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz",
|
||||
"integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==",
|
||||
"license": "Unlicense"
|
||||
},
|
||||
"node_modules/fetch-blob": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||
@@ -1632,6 +2090,16 @@
|
||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/standardwebhooks": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/standardwebhooks/-/standardwebhooks-1.1.1.tgz",
|
||||
"integrity": "sha512-bCbX9ZEyFkWPsRz7Bl3NuQUJohmwGSev/yhr7vhaGPlc4AfIrspIRa6cPTBuI1ItmrTDJ4d/S2hCsfe4+vQGnQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stablelib/base64": "^1.0.0",
|
||||
"fast-sha256": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ts-algebra": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz",
|
||||
@@ -1660,9 +2128,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.3.0.tgz",
|
||||
"integrity": "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==",
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
|
||||
+1
-1
@@ -5,6 +5,6 @@
|
||||
"description": "Minimal Mosaic Stack container proof of concept: one Pi agent, four local contract files, one real model request returning MOSAIC_HELLO_OK.",
|
||||
"license": "UNLICENSED",
|
||||
"dependencies": {
|
||||
"@earendil-works/pi-coding-agent": "0.84.4"
|
||||
"@earendil-works/pi-coding-agent": "0.85.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "@mosaic/registry",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"description": "Mosaic auth/provider/harness registry schemas and validation (increment 1: schemas, validation, read-only CLI).",
|
||||
"license": "UNLICENSED",
|
||||
"type": "module",
|
||||
"engines": { "node": ">=24" },
|
||||
"bin": { "mosaic-registry": "src/cli/main.mjs" },
|
||||
"exports": {
|
||||
".": "./src/index.mjs",
|
||||
"./ids.mjs": "./src/ids.mjs",
|
||||
"./records.mjs": "./src/records.mjs",
|
||||
"./registry.mjs": "./src/registry.mjs"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node --test tests/"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { loadRegistry } from "../registry.mjs";
|
||||
|
||||
// Read-only registry CLI: validate and list. No mutation commands (increment 1).
|
||||
|
||||
function usage() {
|
||||
process.stdout.write(`usage: mosaic-registry <command> --registry-root <dir>
|
||||
commands:
|
||||
validate validate the registry tree; exit 0 valid, 1 invalid, 2 usage
|
||||
list list providers, accounts, profiles (no credential fields ever)
|
||||
`);
|
||||
}
|
||||
|
||||
async function main(argv) {
|
||||
const command = argv[0];
|
||||
const rootIndex = argv.indexOf("--registry-root");
|
||||
const root = rootIndex !== -1 ? argv[rootIndex + 1] : undefined;
|
||||
if ((command !== "validate" && command !== "list") || !root) {
|
||||
usage();
|
||||
return 2;
|
||||
}
|
||||
const { entries, errors } = await loadRegistry(root);
|
||||
if (command === "validate") {
|
||||
if (errors.length > 0) {
|
||||
for (const err of errors) process.stderr.write(`${err.path}: ${err.code}${err.detail ? `: ${err.detail}` : ""}\n`);
|
||||
process.stderr.write(`${errors.length} validation error(s)\n`);
|
||||
return 1;
|
||||
}
|
||||
process.stdout.write("valid\n");
|
||||
return 0;
|
||||
}
|
||||
// list: strictly non-secret projection.
|
||||
const providers = Object.keys(entries.providers).sort().map((id) => ({ id, kind: entries.providers[id].kind }));
|
||||
const accounts = Object.keys(entries.accounts).sort().map((ref) => ({
|
||||
ref,
|
||||
name: entries.accounts[ref].name,
|
||||
type: entries.accounts[ref].type,
|
||||
}));
|
||||
const profiles = Object.keys(entries.profiles).sort().map((id) => ({ id }));
|
||||
process.stdout.write(`${JSON.stringify({ providers, accounts, profiles }, null, 2)}\n`);
|
||||
return errors.length > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
process.exitCode = await main(process.argv.slice(2));
|
||||
@@ -0,0 +1,4 @@
|
||||
import { validateProvider, validateAccount, validateSettingsProfile, validateSeatSelection, validateHarnessManifest, ValidationError } from "./records.mjs";
|
||||
import { loadRegistry } from "./registry.mjs";
|
||||
|
||||
export { validateProvider, validateAccount, validateSettingsProfile, validateSeatSelection, validateHarnessManifest, ValidationError, loadRegistry };
|
||||
@@ -0,0 +1,184 @@
|
||||
// Registry record validation for the Mosaic auth/provider/harness domain.
|
||||
// Increment 1 per docs/plans/2026-09-10_m20-increment1-charter.md: pure
|
||||
// schema/reference validation, no I/O, no secrets, no materialization.
|
||||
|
||||
const ID_PATTERN = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
||||
|
||||
export class ValidationError extends Error {
|
||||
constructor(path, code, detail) {
|
||||
super(`${path}: ${code}${detail ? `: ${detail}` : ""}`);
|
||||
this.name = "ValidationError";
|
||||
this.path = path;
|
||||
this.code = code;
|
||||
this.detail = detail ?? "";
|
||||
}
|
||||
}
|
||||
|
||||
const fail = (errors, path, code, detail) => errors.push(new ValidationError(path, code, detail));
|
||||
|
||||
function isPlainObject(value) {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
// Rejects unknown fields: every record lists its allowed keys and a type map.
|
||||
function checkShape(errors, path, value, allowed, requireAll) {
|
||||
if (!isPlainObject(value)) {
|
||||
fail(errors, path, "not-an-object");
|
||||
return;
|
||||
}
|
||||
for (const key of Object.keys(value)) {
|
||||
if (!(key in allowed)) fail(errors, `${path}.${key}`, "unknown-field");
|
||||
}
|
||||
for (const [key, type] of Object.entries(allowed)) {
|
||||
if (!(key in value)) {
|
||||
if (requireAll.includes(key)) fail(errors, `${path}.${key}`, "missing-field");
|
||||
continue;
|
||||
}
|
||||
const v = value[key];
|
||||
if (type === "id") {
|
||||
if (typeof v !== "string" || !ID_PATTERN.test(v)) fail(errors, `${path}.${key}`, "invalid-id");
|
||||
} else if (type === "string") {
|
||||
if (typeof v !== "string" || v.length === 0) fail(errors, `${path}.${key}`, "invalid-string");
|
||||
} else if (type === "accountRef[]") {
|
||||
if (!Array.isArray(v) || v.length === 0 || v.some((e) => typeof e !== "string" || !/^[a-z0-9][a-z0-9._-]{0,63}\/[a-z0-9][a-z0-9._-]{0,63}$/.test(e))) {
|
||||
fail(errors, `${path}.${key}`, "invalid-account-ref-list");
|
||||
}
|
||||
} else if (type === "string[]") {
|
||||
if (!Array.isArray(v) || v.length === 0 || v.some((e) => typeof e !== "string" || !ID_PATTERN.test(e))) {
|
||||
fail(errors, `${path}.${key}`, "invalid-id-list");
|
||||
}
|
||||
} else if (type === "record") {
|
||||
if (!isPlainObject(v)) fail(errors, `${path}.${key}`, "not-an-object");
|
||||
} else if (type === "timestamp") {
|
||||
if (typeof v !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/.test(v)) {
|
||||
fail(errors, `${path}.${key}`, "invalid-timestamp");
|
||||
}
|
||||
} else if (type === "boolean") {
|
||||
if (typeof v !== "boolean") fail(errors, `${path}.${key}`, "invalid-boolean");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function validateProvider(record) {
|
||||
const errors = [];
|
||||
checkShape(errors, "provider", record, {
|
||||
providerVersion: "id",
|
||||
id: "id",
|
||||
kind: "string",
|
||||
harnesses: "record",
|
||||
credentialTypes: "string[]",
|
||||
allowInsecureTransport: "boolean",
|
||||
}, ["providerVersion", "id", "kind", "harnesses", "credentialTypes"]);
|
||||
if (errors.length === 0) {
|
||||
if (record.kind !== "native" && record.kind !== "custom-endpoint") {
|
||||
fail(errors, "provider.kind", "unsupported-kind", record.kind);
|
||||
}
|
||||
for (const [harness, cfg] of Object.entries(record.harnesses)) {
|
||||
if (!ID_PATTERN.test(harness)) fail(errors, `provider.harnesses.${harness}`, "invalid-id");
|
||||
if (!isPlainObject(cfg)) fail(errors, `provider.harnesses.${harness}`, "not-an-object");
|
||||
}
|
||||
const harnessCfg = record.harnesses.pi;
|
||||
if (record.kind === "custom-endpoint" && isPlainObject(harnessCfg)) {
|
||||
const url = harnessCfg.baseUrl;
|
||||
if (typeof url !== "string" || !/^https?:\/\//.test(url)) {
|
||||
fail(errors, "provider.harnesses.pi.baseUrl", "invalid-url");
|
||||
} else if (url.startsWith("http://") && record.allowInsecureTransport !== true) {
|
||||
fail(errors, "provider.allowInsecureTransport", "insecure-transport-not-allowed");
|
||||
}
|
||||
if (!Array.isArray(harnessCfg.models) || harnessCfg.models.length === 0) {
|
||||
fail(errors, "provider.harnesses.pi.models", "invalid-model-list");
|
||||
}
|
||||
} else if (record.kind === "native" && isPlainObject(harnessCfg) && harnessCfg.baseUrl === undefined && Array.isArray(harnessCfg.models) === false) {
|
||||
// native: pi entry is providerId only; models/bases come from provider catalog
|
||||
}
|
||||
if (record.kind === "native" && record.allowInsecureTransport === true) {
|
||||
fail(errors, "provider.allowInsecureTransport", "insecure-transport-unsupported-for-native");
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
export function validateAccount(record, providerId) {
|
||||
const errors = [];
|
||||
checkShape(errors, "account", record, {
|
||||
accountVersion: "id",
|
||||
id: "id",
|
||||
name: "string",
|
||||
provider: "id",
|
||||
type: "string",
|
||||
createdAt: "timestamp",
|
||||
}, ["accountVersion", "id", "name", "provider", "type", "createdAt"]);
|
||||
if (errors.length === 0) {
|
||||
if (providerId !== undefined && record.provider !== providerId) {
|
||||
fail(errors, "account.provider", "provider-path-mismatch", `${record.provider} vs ${providerId}`);
|
||||
}
|
||||
if (record.type !== "oauth" && record.type !== "api_key" && record.type !== "none") {
|
||||
fail(errors, "account.type", "unsupported-credential-type", record.type);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
export function validateSettingsProfile(record) {
|
||||
const errors = [];
|
||||
checkShape(errors, "profile", record, {
|
||||
settingsVersion: "id",
|
||||
id: "id",
|
||||
allowedAccounts: "accountRef[]",
|
||||
providers: "string[]",
|
||||
defaultAccounts: "record",
|
||||
models: "record",
|
||||
}, ["settingsVersion", "id", "allowedAccounts"]);
|
||||
if (errors.length === 0) {
|
||||
for (const [provider, account] of Object.entries(record.defaultAccounts ?? {})) {
|
||||
if (!ID_PATTERN.test(provider)) fail(errors, `profile.defaultAccounts.${provider}`, "invalid-id");
|
||||
if (typeof account !== "string" || !/^[a-z0-9][a-z0-9._-]{0,63}\/[a-z0-9][a-z0-9._-]{0,63}$/.test(account)) {
|
||||
fail(errors, `profile.defaultAccounts.${provider}`, "invalid-account-ref");
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
export function validateSeatSelection(record) {
|
||||
const errors = [];
|
||||
checkShape(errors, "selection", record, {
|
||||
selectionVersion: "id",
|
||||
profile: "id",
|
||||
accounts: "record",
|
||||
updatedAt: "timestamp",
|
||||
// Fork pin (gate 6): present only when this selection was pinned at fork time.
|
||||
pinnedFromSession: "string",
|
||||
}, ["selectionVersion", "profile"]);
|
||||
if (errors.length === 0) {
|
||||
for (const [provider, account] of Object.entries(record.accounts ?? {})) {
|
||||
if (!ID_PATTERN.test(provider)) fail(errors, `selection.accounts.${provider}`, "invalid-id");
|
||||
if (typeof account !== "string" || !/^[a-z0-9][a-z0-9._-]{0,63}\/[a-z0-9][a-z0-9._-]{0,63}$/.test(account)) {
|
||||
fail(errors, `selection.accounts.${provider}`, "invalid-account-ref");
|
||||
}
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
export function validateHarnessManifest(record) {
|
||||
const errors = [];
|
||||
checkShape(errors, "harness", record, {
|
||||
harnessVersion: "id",
|
||||
id: "id",
|
||||
executable: "string",
|
||||
adapter: "string",
|
||||
compatibleRange: "string",
|
||||
executionMode: "string",
|
||||
materializers: "string[]",
|
||||
}, ["harnessVersion", "id", "executable", "adapter", "compatibleRange", "executionMode", "materializers"]);
|
||||
if (errors.length === 0) {
|
||||
if (record.id !== record.executable) {
|
||||
fail(errors, "harness.executable", "id-executable-mismatch", "gate 1: canonical IDs are executable names");
|
||||
}
|
||||
if (record.executionMode !== "container" && record.executionMode !== "host") {
|
||||
fail(errors, "harness.executionMode", "unsupported-mode", record.executionMode);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
// Registry tree loading and cross-record reference validation.
|
||||
// Reads a supplied registry root; never writes, never touches credentials.
|
||||
|
||||
import { readFile, readdir, stat } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { validateProvider, validateAccount, validateSettingsProfile, validateSeatSelection, validateHarnessManifest } from "./records.mjs";
|
||||
|
||||
export async function loadRegistry(root) {
|
||||
const entries = { providers: {}, accounts: {}, profiles: {}, selections: {}, harnesses: {} };
|
||||
const errors = [];
|
||||
|
||||
const providersDir = join(root, "auth", "providers");
|
||||
for (const file of await safeList(providersDir, errors)) {
|
||||
if (!file.endsWith(".json")) continue;
|
||||
const id = file.slice(0, -5);
|
||||
const record = await readJson(join(providersDir, file), errors);
|
||||
if (record === undefined) continue;
|
||||
errors.push(...validateProvider(record));
|
||||
if (record.id !== id) errors.push(new (await import("./records.mjs")).ValidationError(`providers/${file}`, "id-path-mismatch", `${record.id} vs ${id}`));
|
||||
if (entries.providers[id]) errors.push(new (await import("./records.mjs")).ValidationError(`providers/${file}`, "duplicate-id", id));
|
||||
entries.providers[id] = record;
|
||||
}
|
||||
|
||||
const accountsDir = join(root, "auth", "accounts");
|
||||
for (const provider of await safeList(accountsDir, errors)) {
|
||||
for (const accountDir of await safeList(join(accountsDir, provider), errors)) {
|
||||
// account.json sits in a per-account directory; credential.json is never read.
|
||||
const record = await readJson(join(accountsDir, provider, accountDir, "account.json"), errors);
|
||||
if (record === undefined) continue;
|
||||
errors.push(...validateAccount(record, provider));
|
||||
const accountRef = `${provider}/${accountDir}`;
|
||||
if (record.id !== accountDir) errors.push(new (await import("./records.mjs")).ValidationError(`accounts/${provider}/${accountDir}`, "id-path-mismatch", `${record.id} vs ${accountDir}`));
|
||||
if (entries.accounts[accountRef]) errors.push(new (await import("./records.mjs")).ValidationError(`accounts/${provider}/${accountDir}`, "duplicate-id", accountRef));
|
||||
entries.accounts[accountRef] = record;
|
||||
}
|
||||
}
|
||||
|
||||
const settingsDir = join(root, "auth", "settings");
|
||||
for (const file of await safeList(settingsDir, errors)) {
|
||||
if (!file.endsWith(".json")) continue;
|
||||
const record = await readJson(join(settingsDir, file), errors);
|
||||
if (record === undefined) continue;
|
||||
errors.push(...validateSettingsProfile(record));
|
||||
if (record.id !== file.slice(0, -5)) errors.push(new (await import("./records.mjs")).ValidationError(`settings/${file}`, "id-path-mismatch"));
|
||||
entries.profiles[file.slice(0, -5)] = record;
|
||||
}
|
||||
|
||||
const harnessesDir = join(root, "harnesses");
|
||||
for (const file of await safeList(harnessesDir, errors)) {
|
||||
if (!file.endsWith(".json")) continue;
|
||||
const record = await readJson(join(harnessesDir, file), errors);
|
||||
if (record === undefined) continue;
|
||||
errors.push(...validateHarnessManifest(record));
|
||||
entries.harnesses[file.slice(0, -5)] = record;
|
||||
}
|
||||
|
||||
// Cross-record reference integrity.
|
||||
for (const [ref, account] of Object.entries(entries.accounts)) {
|
||||
if (!entries.providers[account.provider]) {
|
||||
errors.push(new (await import("./records.mjs")).ValidationError(`accounts/${ref}`, "missing-provider", account.provider));
|
||||
}
|
||||
}
|
||||
for (const [pid, profile] of Object.entries(entries.profiles)) {
|
||||
for (const ref of profile.allowedAccounts ?? []) {
|
||||
if (!entries.accounts[ref]) errors.push(new (await import("./records.mjs")).ValidationError(`profiles/${pid}`, "missing-account", ref));
|
||||
}
|
||||
for (const provider of profile.providers ?? []) {
|
||||
if (!entries.providers[provider]) errors.push(new (await import("./records.mjs")).ValidationError(`profiles/${pid}`, "missing-provider", provider));
|
||||
}
|
||||
for (const [provider, ref] of Object.entries(profile.defaultAccounts ?? {})) {
|
||||
if (!entries.accounts[ref]) errors.push(new (await import("./records.mjs")).ValidationError(`profiles/${pid}`, "missing-default-account", ref));
|
||||
else if (!ref.startsWith(`${provider}/`)) errors.push(new (await import("./records.mjs")).ValidationError(`profiles/${pid}`, "default-account-provider-mismatch", ref));
|
||||
}
|
||||
}
|
||||
|
||||
return { entries, errors };
|
||||
}
|
||||
|
||||
async function safeList(dir, errors) {
|
||||
try {
|
||||
const s = await stat(dir);
|
||||
if (!s.isDirectory()) throw new Error("not-a-directory");
|
||||
return await readdir(dir);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
async function readJson(path, errors) {
|
||||
try {
|
||||
return JSON.parse(await readFile(path, "utf8"));
|
||||
} catch (err) {
|
||||
errors.push(new ValidationErrorCompat(path, "invalid-json", err.message));
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
class ValidationErrorCompat extends Error {
|
||||
constructor(path, code, detail) {
|
||||
super(`${path}: ${code}: ${detail}`);
|
||||
this.name = "ValidationError";
|
||||
this.path = path;
|
||||
this.code = code;
|
||||
this.detail = detail;
|
||||
}
|
||||
}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"accountVersion":"1","id":"homelab-openai","name":"Homelab OpenAI","provider":"openai-codex","type":"oauth","createdAt":"2026-09-10T00:00:00Z"}
|
||||
@@ -0,0 +1 @@
|
||||
{"providerVersion":"1","id":"ollama-remote","kind":"custom-endpoint","allowInsecureTransport":true,"harnesses":{"pi":{"api":"openai-completions","baseUrl":"http://ollama.internal:11434/v1","models":["qwen2.5-coder:7b"]}},"credentialTypes":["none"]}
|
||||
@@ -0,0 +1 @@
|
||||
{"providerVersion":"1","id":"openai-codex","kind":"native","harnesses":{"pi":{"providerId":"openai-codex"}},"credentialTypes":["oauth","api_key"]}
|
||||
@@ -0,0 +1 @@
|
||||
{"settingsVersion":"1","id":"research-default","allowedAccounts":["openai-codex/homelab-openai"],"providers":["openai-codex","ollama-remote"],"defaultAccounts":{"openai-codex":"openai-codex/homelab-openai"},"models":{"ollama-remote":["qwen2.5-coder:7b"]}}
|
||||
@@ -0,0 +1 @@
|
||||
{"harnessVersion":"1","id":"pi","executable":"pi","adapter":"pi","compatibleRange":">=0.85.1 <0.86.0","executionMode":"container","materializers":["auth-json","models-json"]}
|
||||
@@ -0,0 +1,149 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join, dirname, resolve } from "node:path";
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { validateProvider, validateAccount, validateSettingsProfile, validateSeatSelection, validateHarnessManifest } from "../src/records.mjs";
|
||||
|
||||
const pkgRoot = resolve(import.meta.dirname, "..");
|
||||
const cli = join(pkgRoot, "src", "cli", "main.mjs");
|
||||
const validFixture = join(pkgRoot, "tests", "fixtures", "valid");
|
||||
|
||||
function makeRoot() {
|
||||
const root = mkdtempSync(join(tmpdir(), "mosaic-registry-test-"));
|
||||
return root;
|
||||
}
|
||||
|
||||
function writeTree(root, files) {
|
||||
for (const [name, content] of Object.entries(files)) {
|
||||
const path = join(root, name);
|
||||
mkdirSync(dirname(path), { recursive: true });
|
||||
writeFileSync(path, typeof content === "string" ? content : JSON.stringify(content));
|
||||
}
|
||||
}
|
||||
|
||||
function runCli(root, command = "validate") {
|
||||
return spawnSync(process.execPath, [cli, command, "--registry-root", root], { encoding: "utf8", timeout: 15000 });
|
||||
}
|
||||
|
||||
const validTree = () => ({
|
||||
"auth/providers/openai-codex.json": { providerVersion: "1", id: "openai-codex", kind: "native", harnesses: { pi: { providerId: "openai-codex" } }, credentialTypes: ["oauth", "api_key"] },
|
||||
"auth/accounts/openai-codex/homelab/account.json": { accountVersion: "1", id: "homelab", name: "Homelab", provider: "openai-codex", type: "oauth", createdAt: "2026-09-10T00:00:00Z" },
|
||||
"auth/settings/research.json": { settingsVersion: "1", id: "research", allowedAccounts: ["openai-codex/homelab"], providers: ["openai-codex"], defaultAccounts: { "openai-codex": "openai-codex/homelab" } },
|
||||
"harnesses/pi.json": { harnessVersion: "1", id: "pi", executable: "pi", adapter: "pi", compatibleRange: ">=0.85.1 <0.86.0", executionMode: "container", materializers: ["auth-json"] },
|
||||
});
|
||||
|
||||
test("valid fixture tree validates and lists without secrets", () => {
|
||||
const r = runCli(validFixture);
|
||||
assert.equal(r.status, 0, r.stderr);
|
||||
assert.match(r.stdout, /^valid\n$/);
|
||||
const l = runCli(validFixture, "list");
|
||||
assert.equal(l.status, 0, l.stderr);
|
||||
const listed = JSON.parse(l.stdout);
|
||||
assert.equal(listed.providers.length, 2);
|
||||
assert.equal(listed.accounts.length, 1);
|
||||
assert.equal(listed.profiles.length, 1);
|
||||
assert.ok(!JSON.stringify(listed).includes("credential"));
|
||||
assert.ok(!JSON.stringify(listed).includes("token"));
|
||||
});
|
||||
|
||||
test("unknown-field refuses", () => {
|
||||
const errors = validateProvider({ providerVersion: "1", id: "p", kind: "native", harnesses: {}, credentialTypes: ["none"], extra: 1 });
|
||||
assert.equal(errors[0].code, "unknown-field");
|
||||
});
|
||||
|
||||
test("invalid-id refuses uppercase and traversal shapes", () => {
|
||||
assert.ok(validateProvider({ providerVersion: "1", id: "BadID", kind: "native", harnesses: {}, credentialTypes: ["none"] }).some((e) => e.code === "invalid-id"));
|
||||
assert.ok(validateAccount({ accountVersion: "1", id: "../escape", name: "x", provider: "p", type: "oauth", createdAt: "2026-09-10T00:00:00Z" }).some((e) => e.code === "invalid-id"));
|
||||
});
|
||||
|
||||
test("plain-http baseUrl requires allowInsecureTransport", () => {
|
||||
const base = { providerVersion: "1", id: "o", kind: "custom-endpoint", harnesses: { pi: { api: "openai-completions", baseUrl: "http://h:11434/v1", models: ["m"] } }, credentialTypes: ["none"] };
|
||||
assert.ok(validateProvider(base).some((e) => e.code === "insecure-transport-not-allowed"));
|
||||
assert.equal(validateProvider({ ...base, allowInsecureTransport: true }).length, 0);
|
||||
const https = JSON.parse(JSON.stringify(base));
|
||||
https.harnesses.pi.baseUrl = "https://h/v1";
|
||||
assert.equal(validateProvider(https).length, 0);
|
||||
});
|
||||
|
||||
test("native provider rejects allowInsecureTransport", () => {
|
||||
assert.ok(validateProvider({ providerVersion: "1", id: "p", kind: "native", harnesses: {}, credentialTypes: ["none"], allowInsecureTransport: true }).some((e) => e.code === "insecure-transport-unsupported-for-native"));
|
||||
});
|
||||
|
||||
test("unsupported credential type and kind refuse", () => {
|
||||
assert.ok(validateAccount({ accountVersion: "1", id: "a", name: "x", provider: "p", type: "basic", createdAt: "2026-09-10T00:00:00Z" }).some((e) => e.code === "unsupported-credential-type"));
|
||||
assert.ok(validateProvider({ providerVersion: "1", id: "p", kind: "weird", harnesses: {}, credentialTypes: ["none"] }).some((e) => e.code === "unsupported-kind"));
|
||||
});
|
||||
|
||||
test("account provider-path mismatch refuses", () => {
|
||||
assert.ok(validateAccount({ accountVersion: "1", id: "a", name: "x", provider: "other", type: "oauth", createdAt: "2026-09-10T00:00:00Z" }, "right").some((e) => e.code === "provider-path-mismatch"));
|
||||
});
|
||||
|
||||
test("profile account refs must be provider/account shaped", () => {
|
||||
const errors = validateSettingsProfile({ settingsVersion: "1", id: "s", allowedAccounts: ["justone"], providers: [], defaultAccounts: {} });
|
||||
assert.ok(errors.some((e) => e.code === "invalid-account-ref-list"));
|
||||
});
|
||||
|
||||
test("seat selection accepts fork pin field, validates account refs", () => {
|
||||
assert.equal(validateSeatSelection({ selectionVersion: "1", profile: "research", accounts: { "openai-codex": "openai-codex/homelab" }, updatedAt: "2026-09-10T00:00:00Z", pinnedFromSession: "abc123" }).length, 0);
|
||||
assert.ok(validateSeatSelection({ selectionVersion: "1", profile: "research", accounts: { "openai-codex": "nope" } }).some((e) => e.code === "invalid-account-ref"));
|
||||
});
|
||||
|
||||
test("harness manifest id must equal executable (gate 1)", () => {
|
||||
assert.ok(validateHarnessManifest({ harnessVersion: "1", id: "pi", executable: "claude", adapter: "x", compatibleRange: ">=1", executionMode: "container", materializers: ["m"] }).some((e) => e.code === "id-executable-mismatch"));
|
||||
});
|
||||
|
||||
test("CLI validate: duplicate provider id across files refuses", () => {
|
||||
const root = makeRoot();
|
||||
try {
|
||||
const tree = validTree();
|
||||
tree["auth/providers/dup.json"] = { ...tree["auth/providers/openai-codex.json"] };
|
||||
writeTree(root, tree);
|
||||
const r = runCli(root);
|
||||
assert.equal(r.status, 1);
|
||||
assert.match(r.stderr, /duplicate-id|id-path-mismatch/);
|
||||
} finally { rmSync(root, { recursive: true, force: true }); }
|
||||
});
|
||||
|
||||
test("CLI validate: missing referenced provider/account refuse", () => {
|
||||
const root = makeRoot();
|
||||
try {
|
||||
const tree = validTree();
|
||||
delete tree["auth/providers/openai-codex.json"];
|
||||
writeTree(root, tree);
|
||||
const r = runCli(root);
|
||||
assert.equal(r.status, 1);
|
||||
assert.match(r.stderr, /missing-provider/);
|
||||
} finally { rmSync(root, { recursive: true, force: true }); }
|
||||
});
|
||||
|
||||
test("CLI validate: broken JSON refuses without secret echo", () => {
|
||||
const root = makeRoot();
|
||||
try {
|
||||
const tree = validTree();
|
||||
tree["auth/providers/openai-codex.json"] = "{ not json";
|
||||
writeTree(root, tree);
|
||||
const r = runCli(root);
|
||||
assert.equal(r.status, 1);
|
||||
assert.match(r.stderr, /invalid-json/);
|
||||
} finally { rmSync(root, { recursive: true, force: true }); }
|
||||
});
|
||||
|
||||
test("CLI usage errors exit 2", () => {
|
||||
assert.equal(runCli(validFixture, "bogus").status, 2);
|
||||
assert.equal(spawnSync(process.execPath, [cli, "validate"], { encoding: "utf8" }).status, 2);
|
||||
});
|
||||
|
||||
test("credential.json sibling presence does not break validation and is never read", () => {
|
||||
const root = makeRoot();
|
||||
try {
|
||||
const tree = validTree();
|
||||
tree["auth/accounts/openai-codex/homelab/credential.json"] = { secretMarker: "FIXTURE-NOT-A-SECRET" };
|
||||
writeTree(root, tree);
|
||||
const r = runCli(root);
|
||||
assert.equal(r.status, 0, r.stderr);
|
||||
const l = runCli(root, "list");
|
||||
assert.ok(!l.stdout.includes("FIXTURE-NOT-A-SECRET"));
|
||||
} finally { rmSync(root, { recursive: true, force: true }); }
|
||||
});
|
||||
@@ -36,7 +36,7 @@ CFG="MOSAIC_CONFIG=$SANDBOX/mock-config.json"
|
||||
|
||||
# release pointer so agent.sh's ensure stays on the no-op fast path
|
||||
REL="$(tr -d '[:space:]' < RELEASE)"
|
||||
printf '{"pointerVersion":1,"release":"%s","imageTag":"mosaic-poc-agent:0.84.4-r%s","activatedAt":"2026-01-01T00:00:00Z"}\n' "$REL" "$REL" > "$SANDBOX/data/state/active.json"
|
||||
printf '{"pointerVersion":1,"release":"%s","imageTag":"mosaic-poc-agent:0.85.1-r%s","activatedAt":"2026-01-01T00:00:00Z"}\n' "$REL" "$REL" > "$SANDBOX/data/state/active.json"
|
||||
|
||||
# fixtures: a default-harness credential and two mosaic-managed accounts
|
||||
printf '{"anthropic":{"type":"oauth","access":"%s"},"zai":{"type":"api_key","key":"%s"}}' "$TOKEN" "$SECRET" > "$SANDBOX/pi/auth.json"
|
||||
|
||||
@@ -7,7 +7,7 @@ import { join, resolve } from 'node:path';
|
||||
import { spawnSync } from 'node:child_process';
|
||||
|
||||
const source = resolve(import.meta.dirname, '..');
|
||||
for (const agent of ['darkwing', 'dewey', 'filbert']) test(`${agent} launch context, resources, session recovery, and refusals`, () => {
|
||||
for (const agent of ['darkwing', 'dewey', 'filbert', 'sage']) test(`${agent} launch context, resources, session recovery, and refusals`, () => {
|
||||
const root = mkdtempSync(join(tmpdir(), `${agent} launch `));
|
||||
try {
|
||||
for (const dir of ['agents', 'scripts', 'contracts', 'user', 'node_modules/.bin', 'extensions/goal']) {
|
||||
@@ -24,7 +24,7 @@ for (const agent of ['darkwing', 'dewey', 'filbert']) test(`${agent} launch cont
|
||||
cpSync(join(source, 'scripts/agent-host-dev.sh'), join(root, 'scripts/agent-host-dev.sh'));
|
||||
cpSync(join(source, 'scripts/agent.sh'), join(root, 'scripts/agent.sh'));
|
||||
cpSync(join(source, 'skills'), join(root, 'skills'), { recursive: true });
|
||||
writeFileSync(join(root, 'package.json'), JSON.stringify({ dependencies: { '@earendil-works/pi-coding-agent': '0.84.4' } }));
|
||||
writeFileSync(join(root, 'package.json'), JSON.stringify({ dependencies: { '@earendil-works/pi-coding-agent': '0.85.1' } }));
|
||||
for (const file of ['contracts/CONSTITUTION.md', 'contracts/STANDARDS.md', 'user/USER.md', 'AGENTS.md']) {
|
||||
writeFileSync(join(root, file), `fixture ${file}\n`);
|
||||
}
|
||||
@@ -33,7 +33,7 @@ for (const agent of ['darkwing', 'dewey', 'filbert']) test(`${agent} launch cont
|
||||
writeFileSync(join(root, 'scripts/sync-dev-extensions.sh'), '#!/bin/sh\nexit 0\n', { mode: 0o755 });
|
||||
writeFileSync(join(root, 'node_modules/.bin/pi'), `#!/usr/bin/env node
|
||||
const fs = require('node:fs');
|
||||
if (process.argv[2] === '--version') { console.log('0.84.4'); process.exit(0); }
|
||||
if (process.argv[2] === '--version') { console.log('0.85.1'); process.exit(0); }
|
||||
fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), agent: process.env.MOSAIC_AGENT_NAME, incarnation: process.env.MOSAIC_LAUNCH_INCARNATION}));
|
||||
`, { mode: 0o755 });
|
||||
const launch = (args = '', tty = true) => spawnSync(tty ? 'script' : 'bash', tty
|
||||
@@ -61,8 +61,9 @@ fs.writeFileSync('capture.json', JSON.stringify({args: process.argv.slice(2), ag
|
||||
let captured = JSON.parse(readFileSync(join(root, 'capture.json')));
|
||||
assert.equal(captured.incarnation, undefined);
|
||||
assert.equal(captured.agent, agent);
|
||||
assert.equal(captured.args[captured.args.indexOf('--provider') + 1], agent === 'filbert' ? 'openai-codex' : 'test');
|
||||
assert.equal(captured.args[captured.args.indexOf('--model') + 1], agent === 'filbert' ? 'gpt-6-astra' : 'test-model');
|
||||
assert.equal(captured.args[captured.args.indexOf('--provider') + 1], agent === 'filbert' ? 'openai-codex' : agent === 'sage' ? 'zai' : 'test');
|
||||
assert.equal(captured.args[captured.args.indexOf('--model') + 1], agent === 'filbert' ? 'gpt-6-astra' : agent === 'sage' ? 'glm-5.3' : 'test-model');
|
||||
if (agent === 'sage') assert.equal(captured.args[captured.args.indexOf('--thinking') + 1], 'high');
|
||||
if (agent === 'filbert') assert.equal(captured.args[captured.args.indexOf('--thinking') + 1], 'low');
|
||||
assert.equal(captured.args[captured.args.indexOf('--session-dir') + 1], join(root, `.pi/state/${agent}/sessions`));
|
||||
assert.equal(captured.args.includes('--continue'), false);
|
||||
|
||||
@@ -220,7 +220,7 @@ EOF
|
||||
EOF
|
||||
REL="$(tr -d '[:space:]' < RELEASE)"
|
||||
mkdir -p "$SANDBOX/data/state"
|
||||
printf '{"pointerVersion":1,"release":"%s","imageTag":"mosaic-poc-agent:0.84.4-r%s","activatedAt":"2026-01-01T00:00:00Z"}\n' "$REL" "$REL" > "$SANDBOX/data/state/active.json"
|
||||
printf '{"pointerVersion":1,"release":"%s","imageTag":"mosaic-poc-agent:0.85.1-r%s","activatedAt":"2026-01-01T00:00:00Z"}\n' "$REL" "$REL" > "$SANDBOX/data/state/active.json"
|
||||
scripts/skill.sh install ms-tools >/dev/null 2>&1
|
||||
scripts/skill.sh activate ms-tools >/dev/null 2>&1
|
||||
env MOSAIC_CONFIG="$SANDBOX/mock-config.json" MOSAIC_MOCK_RESPONSE=MOCKED \
|
||||
|
||||
Reference in New Issue
Block a user