From 175d200e5310712033cbb3b009780f7994770386 Mon Sep 17 00:00:00 2001 From: Simon Klee Date: Mon, 6 Jul 2026 15:34:57 +0200 Subject: [PATCH 01/46] V2 opentui upgrade (#35544) Co-authored-by: opencode-agent[bot] --- bun.lock | 1088 +++++++++++++++------------------- package.json | 6 +- packages/plugin/package.json | 6 +- 3 files changed, 477 insertions(+), 623 deletions(-) diff --git a/bun.lock b/bun.lock index a692e1119f1..c6862dc4bda 100644 --- a/bun.lock +++ b/bun.lock @@ -722,9 +722,9 @@ "typescript": "catalog:", }, "peerDependencies": { - "@opentui/core": ">=0.3.4", - "@opentui/keymap": ">=0.3.4", - "@opentui/solid": ">=0.3.4", + "@opentui/core": ">=0.4.3", + "@opentui/keymap": ">=0.4.3", + "@opentui/solid": ">=0.4.3", }, "optionalPeers": [ "@opentui/core", @@ -1108,7 +1108,6 @@ "patchedDependencies": { "@pierre/trees@1.0.0-beta.4": "patches/@pierre%2Ftrees@1.0.0-beta.4.patch", "@modelcontextprotocol/sdk@1.29.0": "patches/@modelcontextprotocol%2Fsdk@1.29.0.patch", - "gcp-metadata@8.1.2": "patches/gcp-metadata@8.1.2.patch", "@standard-community/standard-openapi@0.2.9": "patches/@standard-community%2Fstandard-openapi@0.2.9.patch", "effect@4.0.0-beta.83": "patches/effect@4.0.0-beta.83.patch", "@npmcli/agent@4.0.2": "patches/@npmcli%2Fagent@4.0.2.patch", @@ -1118,7 +1117,6 @@ "@ai-sdk/google@3.0.73": "patches/@ai-sdk%2Fgoogle@3.0.73.patch", "@ai-sdk/xai@3.0.82": "patches/@ai-sdk%2Fxai@3.0.82.patch", "@tanstack/virtual-core@3.17.0": "patches/@tanstack%2Fvirtual-core@3.17.0.patch", - "pacote@21.5.0": "patches/pacote@21.5.0.patch", }, "overrides": { "@opentui/core": "catalog:", @@ -1139,9 +1137,9 @@ "@npmcli/arborist": "9.4.0", "@octokit/rest": "22.0.0", "@openauthjs/openauth": "0.0.0-20250322224806", - "@opentui/core": "0.3.4", - "@opentui/keymap": "0.3.4", - "@opentui/solid": "0.3.4", + "@opentui/core": "0.4.3", + "@opentui/keymap": "0.4.3", + "@opentui/solid": "0.4.3", "@pierre/diffs": "1.2.10", "@playwright/test": "1.59.1", "@sentry/solid": "10.36.0", @@ -1190,8 +1188,6 @@ "zod": "4.1.8", }, "packages": { - "7zip-bin": ["7zip-bin@5.2.0", "", {}, "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A=="], - "@actions/artifact": ["@actions/artifact@5.0.1", "", { "dependencies": { "@actions/core": "^2.0.0", "@actions/github": "^6.0.1", "@actions/http-client": "^3.0.0", "@azure/storage-blob": "^12.29.1", "@octokit/core": "^5.2.1", "@octokit/plugin-request-log": "^1.0.4", "@octokit/plugin-retry": "^3.0.9", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@protobuf-ts/plugin": "^2.2.3-alpha.1", "archiver": "^7.0.1", "jwt-decode": "^3.1.2", "unzip-stream": "^0.3.1" } }, "sha512-dHJ5rHduhCKUikKTT9eXeWoUvfKia3IjR1sO/VTAV3DVAL4yMTRnl2iO5mcfiBjySHLwPNezwENAVskKYU5ymw=="], "@actions/core": ["@actions/core@1.11.1", "", { "dependencies": { "@actions/exec": "^1.1.1", "@actions/http-client": "^2.0.1" } }, "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A=="], @@ -1220,15 +1216,15 @@ "@ai-sdk/cohere": ["@ai-sdk/cohere@3.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-OqcCq2PiFY1dbK/0Ck45KuvE8jfdxRuuAE9Y5w46dAk6U+9vPOeg1CDcmR+ncqmrYrhRl3nmyDttyDahyjCzAw=="], - "@ai-sdk/deepgram": ["@ai-sdk/deepgram@2.0.33", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-VscTV68g6sXRY4O1yl72/O8y6+tBDvSQax6bqX06hRKWBGxsJ8Jr3LZsNmZnK9Od5Icx565ijK0QgrlNaN4TdQ=="], + "@ai-sdk/deepgram": ["@ai-sdk/deepgram@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@ai-sdk/provider-utils": "4.0.35" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-k2TXhPiQ920n9xXrQhHEzUV8SDCZy5YqAhRFE7t5YU+RlTTPAwFEukWG9pmZGArfPqDYuu7PomnSzYFtpZBocA=="], "@ai-sdk/deepinfra": ["@ai-sdk/deepinfra@2.0.41", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.37", "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.21" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-y6RoOP7DGWmDSiSxrUSt5p18sbz+Ixe5lMVPmdE7x+Tr5rlrzvftyHhjWHfqlAtoYERZTGFbP6tPW1OfQcrb4A=="], - "@ai-sdk/deepseek": ["@ai-sdk/deepseek@2.0.35", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-9DhYurbAvcurOEGN6u2myYDybrrzGfcrkG8hwmFjwTrePW6KCMggm0YxP7e8RkLYcQKqCEMgFlyEB4BM6EmiKg=="], + "@ai-sdk/deepseek": ["@ai-sdk/deepseek@2.0.44", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@ai-sdk/provider-utils": "4.0.35" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-xM2Dr6KuMt80UvpJGq1KSM+GNbRD/QytzSCUEYrM39TsJjm3jYs+WM/U9u+TZH7yIDItZyyfMZS6IRxEHt8i7w=="], - "@ai-sdk/elevenlabs": ["@ai-sdk/elevenlabs@2.0.33", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-EtvsWfGrqx3OhzJdoi82qH+4yzEPPKZr2utyQ+w8cHKoFeg0+8Lou9Z3uixy73WEwz8Z1+AR8QT9fZ64AWGYPA=="], + "@ai-sdk/elevenlabs": ["@ai-sdk/elevenlabs@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@ai-sdk/provider-utils": "4.0.35" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZCNXXl2BejtwUyCy3tZ7fMaylgbEwnYTRNrAHyPMukyuLfSHZwdpVrBpJbeTNMRZ8E7sLvIqdeCt0Avgmr/HyQ=="], - "@ai-sdk/fireworks": ["@ai-sdk/fireworks@2.0.53", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.48", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-HjeiGsdxSzrCkOf2l2V+K+opzlqxBtduBq6BCiohAdgQk2KdZmI/67SMkBM6Kdze/BjUXiZlv0d7zNICPhxVDA=="], + "@ai-sdk/fireworks": ["@ai-sdk/fireworks@2.0.64", "", { "dependencies": { "@ai-sdk/openai-compatible": "2.0.56", "@ai-sdk/provider": "3.0.13", "@ai-sdk/provider-utils": "4.0.35" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-n8QLwW1Iv77Z8H5yHQ7PUx7UFa+iZncGUMJTFAtXG89FbLLCdJg7ZC0shUBV1Ch2zlw7aD7zClE8QkoH/5HKnQ=="], "@ai-sdk/gateway": ["@ai-sdk/gateway@3.0.104", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ZKX5n74io8VIRlhIMSLWVlvT3sXC8Z7cZ9GHuWBWZDVi96+62AIsWuLGvMfcBA1STYuSoDrp6rIziZmvrTq0TA=="], @@ -1288,7 +1284,7 @@ "@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.1", "", {}, "sha512-7dwEVigz9vUWDw3nRwLQ/yH/xYovlUA0ZD86xoeKEBmkz9O6iELG1yri67PgAPW6VLL/xInA4t7H0CK6VmtkKQ=="], - "@astrojs/language-server": ["@astrojs/language-server@2.16.10", "", { "dependencies": { "@astrojs/compiler": "^2.13.1", "@astrojs/yaml2ts": "^0.2.4", "@jridgewell/sourcemap-codec": "^1.5.5", "@volar/kit": "~2.4.28", "@volar/language-core": "~2.4.28", "@volar/language-server": "~2.4.28", "@volar/language-service": "~2.4.28", "muggle-string": "^0.4.1", "tinyglobby": "^0.2.16", "volar-service-css": "0.0.70", "volar-service-emmet": "0.0.70", "volar-service-html": "0.0.70", "volar-service-prettier": "0.0.70", "volar-service-typescript": "0.0.70", "volar-service-typescript-twoslash-queries": "0.0.70", "volar-service-yaml": "0.0.70", "vscode-html-languageservice": "^5.6.2", "vscode-uri": "^3.1.0" }, "peerDependencies": { "prettier": "^3.0.0", "prettier-plugin-astro": ">=0.11.0" }, "optionalPeers": ["prettier", "prettier-plugin-astro"], "bin": { "astro-ls": "./bin/nodeServer.js" } }, "sha512-87VQ/5GSdHlRnUA+hGuerYyIGAj+9RbZmATyuKLEUePinUXhQ5YkRnRrHhOD9sSi5JOErLjrLkHnfZFEvGrV8w=="], + "@astrojs/language-server": ["@astrojs/language-server@2.16.11", "", { "dependencies": { "@astrojs/compiler": "^2.13.1", "@astrojs/yaml2ts": "^0.2.4", "@jridgewell/sourcemap-codec": "^1.5.5", "@volar/kit": "~2.4.28", "@volar/language-core": "~2.4.28", "@volar/language-server": "~2.4.28", "@volar/language-service": "~2.4.28", "muggle-string": "^0.4.1", "tinyglobby": "^0.2.16", "volar-service-css": "0.0.71", "volar-service-emmet": "0.0.71", "volar-service-html": "0.0.71", "volar-service-prettier": "0.0.71", "volar-service-typescript": "0.0.71", "volar-service-typescript-twoslash-queries": "0.0.71", "volar-service-yaml": "0.0.71", "vscode-html-languageservice": "^5.6.2", "vscode-uri": "^3.1.0" }, "peerDependencies": { "prettier": "^3.0.0", "prettier-plugin-astro": ">=0.11.0" }, "optionalPeers": ["prettier", "prettier-plugin-astro"], "bin": { "astro-ls": "./bin/nodeServer.js" } }, "sha512-sJ/EfnFp0+gurTrkvONtd9qRqmMZLT9bHelfI1SA35CaQVTrRrA74qteOcNT/al1b9Atg3IiH1Jk/qfckyC+fg=="], "@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.1", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.2.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.1", "remark-smartypants": "^3.0.2", "shiki": "^3.0.0", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg=="], @@ -1328,7 +1324,7 @@ "@aws-sdk/client-firehose": ["@aws-sdk/client-firehose@3.933.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.932.0", "@aws-sdk/credential-provider-node": "3.933.0", "@aws-sdk/middleware-host-header": "3.930.0", "@aws-sdk/middleware-logger": "3.930.0", "@aws-sdk/middleware-recursion-detection": "3.933.0", "@aws-sdk/middleware-user-agent": "3.932.0", "@aws-sdk/region-config-resolver": "3.930.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@aws-sdk/util-user-agent-browser": "3.930.0", "@aws-sdk/util-user-agent-node": "3.932.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.2", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.9", "@smithy/middleware-retry": "^4.4.9", "@smithy/middleware-serde": "^4.2.5", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.8", "@smithy/util-defaults-mode-node": "^4.2.11", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-tDrtgczN2lQsflLDPYu/wdOoyCZLVYtgzmWnYzSEOBWd/cp2AbuQ7D+FemSwUTzyoMTuhhIevyEJKzqsF+QYxA=="], - "@aws-sdk/client-lambda": ["@aws-sdk/client-lambda@3.1057.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.15", "@aws-sdk/credential-provider-node": "^3.972.47", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/fetch-http-handler": "^5.4.5", "@smithy/node-http-handler": "^4.7.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-JoaE3QNvPqOSHJtcAFfza7BRoGUNerIKlSVhsKCBsa1i54Vto1YWUS7itkUELK2rpvS8kNZMPliPxDdi/oV5dw=="], + "@aws-sdk/client-lambda": ["@aws-sdk/client-lambda@3.1079.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/credential-provider-node": "^3.972.62", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/fetch-http-handler": "^5.6.2", "@smithy/node-http-handler": "^4.9.2", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-+OT6gfX+seDw4fuKnXNlYLvmtessZpnr7DczK507mX48uQlZbHrRObu7zL5PLNdUiNomlNR/mOz9i+TY28GY8Q=="], "@aws-sdk/client-s3": ["@aws-sdk/client-s3@3.933.0", "", { "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.932.0", "@aws-sdk/credential-provider-node": "3.933.0", "@aws-sdk/middleware-bucket-endpoint": "3.930.0", "@aws-sdk/middleware-expect-continue": "3.930.0", "@aws-sdk/middleware-flexible-checksums": "3.932.0", "@aws-sdk/middleware-host-header": "3.930.0", "@aws-sdk/middleware-location-constraint": "3.930.0", "@aws-sdk/middleware-logger": "3.930.0", "@aws-sdk/middleware-recursion-detection": "3.933.0", "@aws-sdk/middleware-sdk-s3": "3.932.0", "@aws-sdk/middleware-ssec": "3.930.0", "@aws-sdk/middleware-user-agent": "3.932.0", "@aws-sdk/region-config-resolver": "3.930.0", "@aws-sdk/signature-v4-multi-region": "3.932.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@aws-sdk/util-user-agent-browser": "3.930.0", "@aws-sdk/util-user-agent-node": "3.932.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.2", "@smithy/eventstream-serde-browser": "^4.2.5", "@smithy/eventstream-serde-config-resolver": "^4.3.5", "@smithy/eventstream-serde-node": "^4.2.5", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-blob-browser": "^4.2.6", "@smithy/hash-node": "^4.2.5", "@smithy/hash-stream-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/md5-js": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.9", "@smithy/middleware-retry": "^4.4.9", "@smithy/middleware-serde": "^4.2.5", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.8", "@smithy/util-defaults-mode-node": "^4.2.11", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-stream": "^4.5.6", "@smithy/util-utf8": "^4.2.0", "@smithy/util-waiter": "^4.2.5", "tslib": "^2.6.2" } }, "sha512-KxwZvdxdCeWK6o8mpnb+kk7Kgb8V+8AjTwSXUWH1UAD85B0tjdo1cSfE5zoR5fWGol4Ml5RLez12a6LPhsoTqA=="], @@ -1338,23 +1334,23 @@ "@aws-sdk/core": ["@aws-sdk/core@3.932.0", "", { "dependencies": { "@aws-sdk/types": "3.930.0", "@aws-sdk/xml-builder": "3.930.0", "@smithy/core": "^3.18.2", "@smithy/node-config-provider": "^4.3.5", "@smithy/property-provider": "^4.2.5", "@smithy/protocol-http": "^5.3.5", "@smithy/signature-v4": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-AS8gypYQCbNojwgjvZGkJocC2CoEICDx9ZJ15ILsv+MlcCVLtUJSRSx3VzJOUY2EEIaGLRrPNlIqyn/9/fySvA=="], - "@aws-sdk/credential-provider-cognito-identity": ["@aws-sdk/credential-provider-cognito-identity@3.972.38", "", { "dependencies": { "@aws-sdk/nested-clients": "^3.997.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-OHkK6xOx/IHkSbQdDWxnVCLU+j28EFl8wyWgBILQDFAPY8n240C/O4gjmFx+zFU12lL8njgJQ5GWAIWq88CnSQ=="], + "@aws-sdk/credential-provider-cognito-identity": ["@aws-sdk/credential-provider-cognito-identity@3.972.52", "", { "dependencies": { "@aws-sdk/nested-clients": "^3.997.27", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-m+akZFJsghShferf2xsMw0Hogl1jNIJl2zUoZBNTFyWvlaOj1aK5sMTzcnw8m1dICvlQ+lC4T1OPGGsmZ+ezXA=="], - "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.41", "", { "dependencies": { "@aws-sdk/core": "^3.974.15", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-n1EbJ98yvPWWdHZZv8bRBMqqDQJrtgtxyJ4xLy2Uqrh25BCOZQ7nnS1CsFXvuH8r0b0KVHDZEGEH5FxmEMP8jg=="], + "@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.53", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-+KDA3uc/HZ1vIneGu5QMQb0gAXDYrm2vOE60+BJ7lS0YinMQ5i2oV4PR1A16XkF6K1IbSwjEHd1hQIIgMsK48w=="], - "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.43", "", { "dependencies": { "@aws-sdk/core": "^3.974.15", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/fetch-http-handler": "^5.4.5", "@smithy/node-http-handler": "^4.7.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-TT76RN1NkI9WoyZqCNxOw6/WBMF7pYOTJcXbMokNFU+euSG40Kaf/t/FhDACVZWP+43wEM6ZynIPIkzS1wR1iA=="], + "@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.55", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/fetch-http-handler": "^5.6.2", "@smithy/node-http-handler": "^4.9.2", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-1gBfkWY3RWeBlCoB9lIJjXMx45/54wxcgfzv6BY9otTmMrZPcNPi1v+MwZxxaCUg441NV3jsr1efnFNCXiW70g=="], - "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.46", "", { "dependencies": { "@aws-sdk/core": "^3.974.15", "@aws-sdk/credential-provider-env": "^3.972.41", "@aws-sdk/credential-provider-http": "^3.972.43", "@aws-sdk/credential-provider-login": "^3.972.45", "@aws-sdk/credential-provider-process": "^3.972.41", "@aws-sdk/credential-provider-sso": "^3.972.45", "@aws-sdk/credential-provider-web-identity": "^3.972.45", "@aws-sdk/nested-clients": "^3.997.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/credential-provider-imds": "^4.3.6", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-hvcgcwOiS0nb2XFb5Op1Pz/vYaWz5K8kKullziGpdNRuG0NwzRXseuPt2CoBqknHGaSPVesu1aOn2OcctEYdCA=="], + "@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.972.60", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/credential-provider-env": "^3.972.53", "@aws-sdk/credential-provider-http": "^3.972.55", "@aws-sdk/credential-provider-login": "^3.972.59", "@aws-sdk/credential-provider-process": "^3.972.53", "@aws-sdk/credential-provider-sso": "^3.972.59", "@aws-sdk/credential-provider-web-identity": "^3.972.59", "@aws-sdk/nested-clients": "^3.997.27", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/credential-provider-imds": "^4.4.5", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-CV2md+PXvABwRjApWGhQ0wACy9WSFIhnUGrovLcjnjBCd/46TbuivLADtkF8IWNjtCQmQ+2IagSaxqBYqXBNAQ=="], - "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.45", "", { "dependencies": { "@aws-sdk/core": "^3.974.15", "@aws-sdk/nested-clients": "^3.997.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-MZQv4SNjByk1iOKmrqmzcUF/uCB05wjvEHyXKxmGQTUANTIVayX6HPUF0bzkWLvtnkH7sAn9kUCfkXbSpj9sDA=="], + "@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.59", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/nested-clients": "^3.997.27", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-JG4S9yyA1GFzJdJXqLKrUzZbyK+VDp2QIsJD7YOicJHAhqymfHpDJIok2dLnhOdVB0I37RjdC53uOwCMVS00gw=="], "@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.933.0", "", { "dependencies": { "@aws-sdk/credential-provider-env": "3.932.0", "@aws-sdk/credential-provider-http": "3.932.0", "@aws-sdk/credential-provider-ini": "3.933.0", "@aws-sdk/credential-provider-process": "3.932.0", "@aws-sdk/credential-provider-sso": "3.933.0", "@aws-sdk/credential-provider-web-identity": "3.933.0", "@aws-sdk/types": "3.930.0", "@smithy/credential-provider-imds": "^4.2.5", "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-L2dE0Y7iMLammQewPKNeEh1z/fdJyYEU+/QsLBD9VEh+SXcN/FIyTi21Isw8wPZN6lMB9PDVtISzBnF8HuSFrw=="], - "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.41", "", { "dependencies": { "@aws-sdk/core": "^3.974.15", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-7I/n1zkysouLOWvkEhjNEP4vMnD2v4kzzr3/3QBdrripEpn7ap1/I5DF3Hou1SUqkKWo1f3oPGMyFAA1FAMvsQ=="], + "@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.53", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-EhfH+MQlqOMCkXIVa8MMObPzAQqwTTtxA7KhEJiyPeuNVA8PLOOUpgK7nBrgaDaGiIDLN/9LpGdaHuDjomeRTw=="], - "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.45", "", { "dependencies": { "@aws-sdk/core": "^3.974.15", "@aws-sdk/nested-clients": "^3.997.13", "@aws-sdk/token-providers": "3.1056.0", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-oHgbz/eFD8IKiksqDsz9ZMU4A59BpQq4QwJedBnGD80ZqYcHPPHZBwjBnxLVkB7iRVVHWpDclR8yWdD2PkQIUA=="], + "@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.972.59", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/nested-clients": "^3.997.27", "@aws-sdk/token-providers": "3.1079.0", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-h8793pOjcImx0SB+VcLONcaQQ57VAvKVuqyewQMRKqqH+CSXsG2dwOeLMUJPMxLdNvL7dXOM0ueTukyNUnu5mA=="], - "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.45", "", { "dependencies": { "@aws-sdk/core": "^3.974.15", "@aws-sdk/nested-clients": "^3.997.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-CDhzKdb2onv5bpnjn/acgdNmJOQthPDLsPizU7rZflsEcgMMp8Mlri+U5hdxf8ldvZJpvM3vLU6D56vfJm5AMQ=="], + "@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.59", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/nested-clients": "^3.997.27", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-VoyO9+vl3XVmpZwn4obskrWIkrA/Jf3lSe1E3ZERlaN9u0D4YZ6+HywC3+L98QOXqZesEfedk67gRER8tK8+8w=="], "@aws-sdk/credential-providers": ["@aws-sdk/credential-providers@3.1057.0", "", { "dependencies": { "@aws-sdk/client-cognito-identity": "3.1057.0", "@aws-sdk/core": "^3.974.15", "@aws-sdk/credential-provider-cognito-identity": "^3.972.38", "@aws-sdk/credential-provider-env": "^3.972.41", "@aws-sdk/credential-provider-http": "^3.972.43", "@aws-sdk/credential-provider-ini": "^3.972.46", "@aws-sdk/credential-provider-login": "^3.972.45", "@aws-sdk/credential-provider-node": "^3.972.47", "@aws-sdk/credential-provider-process": "^3.972.41", "@aws-sdk/credential-provider-sso": "^3.972.45", "@aws-sdk/credential-provider-web-identity": "^3.972.45", "@aws-sdk/nested-clients": "^3.997.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/credential-provider-imds": "^4.3.6", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-rbrEHtz11g0kxsSkYr3fx2HABNNblp4AhB2MgPvJHgYOWfJ2eBviU7Mvoaef0PW8QH6lbZDfJcnM7eKvtvz3sw=="], @@ -1378,13 +1374,13 @@ "@aws-sdk/middleware-user-agent": ["@aws-sdk/middleware-user-agent@3.932.0", "", { "dependencies": { "@aws-sdk/core": "3.932.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@smithy/core": "^3.18.2", "@smithy/protocol-http": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-9BGTbJyA/4PTdwQWE9hAFIJGpsYkyEW20WON3i15aDqo5oRZwZmqaVageOD57YYqG8JDJjvcwKyDdR4cc38dvg=="], - "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.13", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.15", "@aws-sdk/signature-v4-multi-region": "^3.996.30", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/fetch-http-handler": "^5.4.5", "@smithy/node-http-handler": "^4.7.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-2pA6eyb5nSo/ZD2cayhOTEMoGQYgspq0RI05GDLkzQ3ajZ6isS6waV6E92Am/hz4LIlLUTrbwPLurJ/fuiHvkg=="], + "@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.27", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/signature-v4-multi-region": "^3.996.38", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/fetch-http-handler": "^5.6.2", "@smithy/node-http-handler": "^4.9.2", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-A8PIePF9NIIOJ/4Lg1rl9xm/+QaKkHGetq+Z9wb5B+3Da31YYXRo8n7IDMh5C+HQI5eyEmjrwkGWVdYtnLtbXQ=="], "@aws-sdk/region-config-resolver": ["@aws-sdk/region-config-resolver@3.930.0", "", { "dependencies": { "@aws-sdk/types": "3.930.0", "@smithy/config-resolver": "^4.4.3", "@smithy/node-config-provider": "^4.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-KL2JZqH6aYeQssu1g1KuWsReupdfOoxD6f1as2VC+rdwYFUu4LfzMsFfXnBvvQWWqQ7rZHWOw1T+o5gJmg7Dzw=="], "@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.932.0", "", { "dependencies": { "@aws-sdk/middleware-sdk-s3": "3.932.0", "@aws-sdk/types": "3.930.0", "@smithy/protocol-http": "^5.3.5", "@smithy/signature-v4": "^5.3.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-NCIRJvoRc9246RZHIusY1+n/neeG2yGhBGdKhghmrNdM+mLLN6Ii7CKFZjx3DhxtpHMpl1HWLTMhdVrGwP2upw=="], - "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1056.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.15", "@aws-sdk/nested-clients": "^3.997.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-81duvlltQlsfn5K+o8zILcystBRdbT1G2JJYVCML5NZHBz4CL/zf+sAemCtBh/uh6RQUMyInGeZLQ7/8igZhbA=="], + "@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1079.0", "", { "dependencies": { "@aws-sdk/core": "^3.974.27", "@aws-sdk/nested-clients": "^3.997.27", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-cbietrLlHPhhmbnMPTuDS4Zj/KNGhY+3vVhn6dwjO6Dqzrwothzg2srtcY34T9mlICsTXn34avDoWLHSntP54A=="], "@aws-sdk/types": ["@aws-sdk/types@3.930.0", "", { "dependencies": { "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-we/vaAgwlEFW7IeftmCLlLMw+6hFs3DzZPJw7lVHbj/5HJ0bz9gndxEsS2lQoeJ1zhiiLqAqvXxmM43s0MBg0A=="], @@ -1392,7 +1388,7 @@ "@aws-sdk/util-endpoints": ["@aws-sdk/util-endpoints@3.930.0", "", { "dependencies": { "@aws-sdk/types": "3.930.0", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-endpoints": "^3.2.5", "tslib": "^2.6.2" } }, "sha512-M2oEKBzzNAYr136RRc6uqw3aWlwCxqTP1Lawps9E1d2abRPvl1p1ztQmmXp1Ak4rv8eByIZ+yQyKQ3zPdRG5dw=="], - "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.5", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ=="], + "@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.8", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-uUbMs1cBZPafD0ohUj6EwNf0fPZ534NvBxHox4hjX+0Rxq5paSYUem7+hi833pYrzrcnBATKIYpR02MDXT5M9g=="], "@aws-sdk/util-user-agent-browser": ["@aws-sdk/util-user-agent-browser@3.930.0", "", { "dependencies": { "@aws-sdk/types": "3.930.0", "@smithy/types": "^4.9.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-q6lCRm6UAe+e1LguM5E4EqM9brQlDem4XDcQ87NzEvlTW6GzmNCO0w1jS0XgCFXQHjDxjdlNFX+5sRbHijwklg=="], @@ -1408,7 +1404,7 @@ "@azure/core-auth": ["@azure/core-auth@1.10.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-util": "^1.13.0", "tslib": "^2.6.2" } }, "sha512-ykRMW8PjVAn+RS6ww5cmK9U2CyH9p4Q88YJwvUslfuMmN98w/2rdGRLPqJYObapBCdzBVeDgYWdJnFPFb7qzpg=="], - "@azure/core-client": ["@azure/core-client@1.10.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-rest-pipeline": "^1.22.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "tslib": "^2.6.2" } }, "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w=="], + "@azure/core-client": ["@azure/core-client@1.10.2", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-rest-pipeline": "^1.22.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "tslib": "^2.6.2" } }, "sha512-1D2LpsU7y9xrqKjdIbsB7PlrRePw0xsVV8p+AKTlzITrWmscajryfJCdDJB/oGwvDI5HmRo04eMMADB67uwAwQ=="], "@azure/core-http": ["@azure/core-http@3.0.5", "", { "dependencies": { "@azure/abort-controller": "^1.0.0", "@azure/core-auth": "^1.3.0", "@azure/core-tracing": "1.0.0-preview.13", "@azure/core-util": "^1.1.1", "@azure/logger": "^1.0.0", "@types/node-fetch": "^2.5.0", "@types/tunnel": "^0.0.3", "form-data": "^4.0.0", "node-fetch": "^2.6.7", "process": "^0.11.10", "tslib": "^2.2.0", "tunnel": "^0.0.6", "uuid": "^8.3.0", "xml2js": "^0.5.0" } }, "sha512-T8r2q/c3DxNu6mEJfPuJtptUVqwchxzjj32gKcnMi06rdiVONS9rar7kT9T2Am+XvER7uOzpsP79WsqNbdgdWg=="], @@ -1418,7 +1414,7 @@ "@azure/core-paging": ["@azure/core-paging@1.6.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-YKWi9YuCU04B55h25cnOYZHxXYtEvQEbKST5vqRga7hWY9ydd3FZHdeQF8pyh+acWZvppw13M/LMGx0LABUVMA=="], - "@azure/core-rest-pipeline": ["@azure/core-rest-pipeline@1.23.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "@typespec/ts-http-runtime": "^0.3.4", "tslib": "^2.6.2" } }, "sha512-Evs1INHo+jUjwHi1T6SG6Ua/LHOQBCLuKEEE6efIpt4ZOoNonaT1kP32GoOcdNDbfqsD2445CPri3MubBy5DEQ=="], + "@azure/core-rest-pipeline": ["@azure/core-rest-pipeline@1.24.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.10.0", "@azure/core-tracing": "^1.3.0", "@azure/core-util": "^1.13.0", "@azure/logger": "^1.3.0", "@typespec/ts-http-runtime": "^0.3.4", "tslib": "^2.6.2" } }, "sha512-PpLsoDQ3AMmKZ0VU+0GrmqMxgp/sExjlVm4R+nLWngeoEGAzOIPVifaxKGU5gMv+nWELUoHfvrolWD+ZS/nFJg=="], "@azure/core-tracing": ["@azure/core-tracing@1.3.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-9MWKevR7Hz8kNzzPLfX4EAtGM2b8mr50HPDBvio96bURP/9C+HjdH3sBlLSNNrvRAr5/k/svoH457gB5IKpmwQ=="], @@ -1428,9 +1424,9 @@ "@azure/logger": ["@azure/logger@1.3.0", "", { "dependencies": { "@typespec/ts-http-runtime": "^0.3.0", "tslib": "^2.6.2" } }, "sha512-fCqPIfOcLE+CGqGPd66c8bZpwAji98tZ4JI9i/mlTNTlsIWslCfpg48s/ypyLxZTump5sypjrKn2/kY7q8oAbA=="], - "@azure/storage-blob": ["@azure/storage-blob@12.31.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-client": "^1.9.3", "@azure/core-http-compat": "^2.2.0", "@azure/core-lro": "^2.2.0", "@azure/core-paging": "^1.6.2", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/core-xml": "^1.4.5", "@azure/logger": "^1.1.4", "@azure/storage-common": "^12.3.0", "events": "^3.0.0", "tslib": "^2.8.1" } }, "sha512-DBgNv10aCSxopt92DkTDD0o9xScXeBqPKGmR50FPZQaEcH4JLQ+GEOGEDv19V5BMkB7kxr+m4h6il/cCDPvmHg=="], + "@azure/storage-blob": ["@azure/storage-blob@12.33.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-client": "^1.9.3", "@azure/core-http-compat": "^2.2.0", "@azure/core-lro": "^2.2.0", "@azure/core-paging": "^1.6.2", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/core-xml": "^1.4.5", "@azure/logger": "^1.1.4", "@azure/storage-common": "^12.4.1", "events": "^3.0.0", "tslib": "^2.8.1" } }, "sha512-2SX8oP8PyblUcAFZSg39c8Ls+tFjavM6sBeV+qpw33mRzRhI/5hrFJmJ/x0H9xx5l6ECPvgSP8uPxqTeVbHNIA=="], - "@azure/storage-common": ["@azure/storage-common@12.3.0", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-http-compat": "^2.2.0", "@azure/core-rest-pipeline": "^1.19.1", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/logger": "^1.1.4", "events": "^3.3.0", "tslib": "^2.8.1" } }, "sha512-/OFHhy86aG5Pe8dP5tsp+BuJ25JOAl9yaMU3WZbkeoiFMHFtJ7tu5ili7qEdBXNW9G5lDB19trwyI6V49F/8iQ=="], + "@azure/storage-common": ["@azure/storage-common@12.4.1", "", { "dependencies": { "@azure/abort-controller": "^2.1.2", "@azure/core-auth": "^1.9.0", "@azure/core-http-compat": "^2.2.0", "@azure/core-rest-pipeline": "^1.24.0", "@azure/core-tracing": "^1.2.0", "@azure/core-util": "^1.11.0", "@azure/logger": "^1.1.4", "events": "^3.3.0", "tslib": "^2.8.1" } }, "sha512-t14unw/WofGDUi7TKJrsyXyPsN+NLgRm7hMaq0llxNmTIzt7f257+6LE6FKIJPh88zLj6M7LPvzve0fEYg/L3A=="], "@babel/code-frame": ["@babel/code-frame@7.29.7", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.29.7", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw=="], @@ -1496,11 +1492,9 @@ "@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="], - "@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="], + "@bufbuild/protobuf": ["@bufbuild/protobuf@2.12.1", "", {}, "sha512-BvAMfS6LrgZiryOAZ4pBYucu4wG/Ei/9o9DZ9akbREnMLbPJiom2i8b9C8IsKErQoiKqVhrerzt3kOT/RrzLHg=="], - "@bufbuild/protobuf": ["@bufbuild/protobuf@2.12.0", "", {}, "sha512-B/XlCaFIP8LOwzo+bz5uFzATYokcwCKQcghqnlfwSmM5eX/qTkvDBnDPs+gXtX/RyjxJ4DRikECcPJbyALA8FA=="], - - "@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.12.0", "", { "dependencies": { "@bufbuild/protobuf": "2.12.0", "@typescript/vfs": "^1.6.2", "typescript": "5.4.5" } }, "sha512-ORlDITp8AFUXzIhLRoMCG+ud+D3MPKWb5HQXBoskMMnjeyEjE1H1qLonVNPyOr8lkx3xSfYUo8a0dvOZJVAzow=="], + "@bufbuild/protoplugin": ["@bufbuild/protoplugin@2.12.1", "", { "dependencies": { "@bufbuild/protobuf": "2.12.1", "@typescript/vfs": "^1.6.2", "typescript": "5.4.5" } }, "sha512-PY58KxQVAD1BnnKtStOctsMoegEVGfBnY5AOqVQOIu711nA13oYtTqJM8df5lUQg2J1DR3XxUXptE+fWX5oLdA=="], "@capsizecss/unpack": ["@capsizecss/unpack@2.4.0", "", { "dependencies": { "blob-to-buffer": "^1.2.8", "cross-fetch": "^3.0.4", "fontkit": "^2.0.2" } }, "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q=="], @@ -1532,8 +1526,6 @@ "@ctrl/tinycolor": ["@ctrl/tinycolor@4.2.0", "", {}, "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A=="], - "@develar/schema-utils": ["@develar/schema-utils@2.6.5", "", { "dependencies": { "ajv": "^6.12.0", "ajv-keywords": "^3.4.1" } }, "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig=="], - "@dnd-kit/abstract": ["@dnd-kit/abstract@0.5.0", "", { "dependencies": { "@dnd-kit/geometry": "^0.5.0", "@dnd-kit/state": "^0.5.0", "tslib": "^2.6.2" } }, "sha512-hi13iMJgjPX/KDYVKg5VeDIhmYiV6buc9bAX+tCLYf4QdyYjPbsXjn2sPo6m7fQ6SGJBEFgHJ2PemeKDUbwBaA=="], "@dnd-kit/collision": ["@dnd-kit/collision@0.5.0", "", { "dependencies": { "@dnd-kit/abstract": "^0.5.0", "@dnd-kit/geometry": "^0.5.0", "tslib": "^2.6.2" } }, "sha512-xUqRn3lS7oqLkT0AnnHS/STh/Czvwe1UapZFYiLbsUGxopMsQd4teaPCzPouOThoMdGEe+dHWjfqJl6t9iG4mQ=="], @@ -1570,7 +1562,7 @@ "@electron/osx-sign": ["@electron/osx-sign@1.3.3", "", { "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", "fs-extra": "^10.0.0", "isbinaryfile": "^4.0.8", "minimist": "^1.2.6", "plist": "^3.0.5" }, "bin": { "electron-osx-flat": "bin/electron-osx-flat.js", "electron-osx-sign": "bin/electron-osx-sign.js" } }, "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg=="], - "@electron/rebuild": ["@electron/rebuild@4.0.4", "", { "dependencies": { "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.1.1", "node-abi": "^4.2.0", "node-api-version": "^0.2.1", "node-gyp": "^12.2.0", "read-binary-file-arch": "^1.0.6" }, "bin": { "electron-rebuild": "lib/cli.js" } }, "sha512-Rzc39XPdk/+/wBG8MfwAHohXflep0ITUfulb6Rgz3R0NeSB1noE+E9/M/cb8ftCAiyDD9PPhLuuWgE1GaInbKg=="], + "@electron/rebuild": ["@electron/rebuild@4.1.0", "", { "dependencies": { "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.1.1", "node-abi": "^4.2.0", "node-api-version": "^0.2.1", "node-gyp": "^12.2.0", "read-binary-file-arch": "^1.0.6" }, "bin": { "electron-rebuild": "lib/cli.js" } }, "sha512-GFky+1JeO8fpSqtZCh+2wFRN/MVbAhm7tXI2M7BA1Os79OR8LEoxRtAbRPyxvmKWhEMF/p10rNJkkgP1klI13g=="], "@electron/universal": ["@electron/universal@2.0.3", "", { "dependencies": { "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", "fs-extra": "^11.1.1", "minimatch": "^9.0.3", "plist": "^3.1.0" } }, "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g=="], @@ -1784,8 +1776,6 @@ "@isaacs/string-locale-compare": ["@isaacs/string-locale-compare@1.1.0", "", {}, "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ=="], - "@joshwooding/vite-plugin-react-docgen-typescript": ["@joshwooding/vite-plugin-react-docgen-typescript@0.7.0", "", { "dependencies": { "glob": "^13.0.1", "react-docgen-typescript": "^2.2.2" }, "peerDependencies": { "typescript": ">= 4.3.x", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["typescript"] }, "sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ=="], - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], @@ -1846,7 +1836,7 @@ "@kobalte/core": ["@kobalte/core@0.13.11", "", { "dependencies": { "@floating-ui/dom": "^1.5.1", "@internationalized/date": "^3.4.0", "@internationalized/number": "^3.2.1", "@kobalte/utils": "^0.9.1", "@solid-primitives/props": "^3.1.8", "@solid-primitives/resize-observer": "^2.0.26", "solid-presence": "^0.1.8", "solid-prevent-scroll": "^0.1.4" }, "peerDependencies": { "solid-js": "^1.8.15" } }, "sha512-hK7TYpdib/XDb/r/4XDBFaO9O+3ZHz4ZWryV4/3BfES+tSQVgg2IJupDnztKXB0BqbSRy/aWlHKw1SPtNPYCFQ=="], - "@kobalte/utils": ["@kobalte/utils@0.9.1", "", { "dependencies": { "@solid-primitives/event-listener": "^2.2.14", "@solid-primitives/keyed": "^1.2.0", "@solid-primitives/map": "^0.4.7", "@solid-primitives/media": "^2.2.4", "@solid-primitives/props": "^3.1.8", "@solid-primitives/refs": "^1.0.5", "@solid-primitives/utils": "^6.2.1" }, "peerDependencies": { "solid-js": "^1.8.8" } }, "sha512-eeU60A3kprIiBDAfv9gUJX1tXGLuZiKMajUfSQURAF2pk4ZoMYiqIzmrMBvzcxP39xnYttgTyQEVLwiTZnrV4w=="], + "@kobalte/utils": ["@kobalte/utils@0.9.2", "", { "dependencies": { "@solid-primitives/event-listener": "^2.2.14", "@solid-primitives/keyed": "^1.2.0", "@solid-primitives/map": "^0.4.7", "@solid-primitives/media": "^2.2.4", "@solid-primitives/props": "^3.1.8", "@solid-primitives/refs": "^1.0.5", "@solid-primitives/utils": "^6.2.1" }, "peerDependencies": { "solid-js": "^1.8.8" } }, "sha512-jRVXr+zsVHxzDXRoh+CDeXzvCsFJ6uiHhqqNQ26Cw9ZsZ3D6nqPUBt1gGVtj2ZPmRL3a9Uk1v8D1aJ8/I12Dow=="], "@kurkle/color": ["@kurkle/color@0.3.4", "", {}, "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w=="], @@ -1904,11 +1894,11 @@ "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="], - "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.4", "", { "dependencies": { "@tybys/wasm-util": "^0.10.1" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow=="], + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.6", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1" } }, "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg=="], "@noble/hashes": ["@noble/hashes@2.2.0", "", {}, "sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg=="], - "@nodable/entities": ["@nodable/entities@2.1.1", "", {}, "sha512-Pig3HxDIoMgjdEH8OCf/dkcTmLFjJRjWuq8jSnklu284/TKOPibSRERmOykiwmyXTtv61mP+44f3GMx0tLAyjg=="], + "@nodable/entities": ["@nodable/entities@2.2.0", "", {}, "sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -2092,27 +2082,27 @@ "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.41.1", "", {}, "sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA=="], - "@opentui/core": ["@opentui/core@0.3.4", "", { "dependencies": { "bun-ffi-structs": "0.2.2", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2", "yoga-layout": "3.2.1" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.3.4", "@opentui/core-darwin-x64": "0.3.4", "@opentui/core-linux-arm64": "0.3.4", "@opentui/core-linux-arm64-musl": "0.3.4", "@opentui/core-linux-x64": "0.3.4", "@opentui/core-linux-x64-musl": "0.3.4", "@opentui/core-win32-arm64": "0.3.4", "@opentui/core-win32-x64": "0.3.4" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-y0DlrChP9lcJ4jC5z/1wMS34+ygfSTW7gD5OJHwJaAScfmlFvuJOZbwmCGrJURZ+5wFBxuOi9LatZsmeAUIKAA=="], + "@opentui/core": ["@opentui/core@0.4.3", "", { "dependencies": { "bun-ffi-structs": "0.2.4", "diff": "9.0.0", "marked": "17.0.1", "string-width": "7.2.0", "strip-ansi": "7.1.2" }, "optionalDependencies": { "@opentui/core-darwin-arm64": "0.4.3", "@opentui/core-darwin-x64": "0.4.3", "@opentui/core-linux-arm64": "0.4.3", "@opentui/core-linux-arm64-musl": "0.4.3", "@opentui/core-linux-x64": "0.4.3", "@opentui/core-linux-x64-musl": "0.4.3", "@opentui/core-win32-arm64": "0.4.3", "@opentui/core-win32-x64": "0.4.3" }, "peerDependencies": { "web-tree-sitter": "0.25.10" } }, "sha512-rrJfAk13tALDqldYjhc78eWQ+aKq1iknJgffIOg3OwyZoqQo+p6gtuqyhmWvXIfQzlNUbpgpCPcxbXlhMnlaHQ=="], - "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.3.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4A7JYXUsZqhu9PPCe07E30ourSJYkitkwMujUyNKjM5e/dHNDVnz+5r5cO3M5snofLafc1DN7+9jEPn4UQzchQ=="], + "@opentui/core-darwin-arm64": ["@opentui/core-darwin-arm64@0.4.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-p5+7AAxpxGuDGagyQfewKtmTFnN7THvTVY4FyKqUtJomNaHdQXPHztapNNzMx0DGWbwOUbVKzpL+yc3CZY3chQ=="], - "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.3.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-Jvm9E8n2sPhKEyKSXn9GlmJcj8WoJXJTooXb3djwjVaiimjihIj0XxHzCWhdqbDtQp+VxDFyCKoQagOOz20qhA=="], + "@opentui/core-darwin-x64": ["@opentui/core-darwin-x64@0.4.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-+fh0vEUE0lwVC7RW5ijYLRlTLp5NfvCRj8SzxDVd7IL2j2ssB6YXcfIbXq2EW7UGnrejwPRXf1tgUrIXW9KmOw=="], - "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.3.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-0uPuHCeZxm/O7+L+iNQl8zRAfehiwYstKkT9J0uTZO64/byBCLvy5lvn1DiE/72s/nTJ5nwpLN+pQs2/WYVKLQ=="], + "@opentui/core-linux-arm64": ["@opentui/core-linux-arm64@0.4.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-gl6qA5QJy6u8Cbt7gOtHbhhfMZ4qQDb0kEwFXHcMGmbnKzz4OHoq74D6tNjyvSQB9saoC7C6C0tvn2DcJOuNog=="], - "@opentui/core-linux-arm64-musl": ["@opentui/core-linux-arm64-musl@0.3.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-sJYUzYcSOb5PCXRlhwsse/fdsMiVomNvIwq/2TDhAANef+YPO3Br+OH9kQRbuj0bjVDmUS36SGYWSTFu2lUO+A=="], + "@opentui/core-linux-arm64-musl": ["@opentui/core-linux-arm64-musl@0.4.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-8p8g8/AEq/xFGpQ7XcIFKcAqjc0QwsZcv+Ll9RbCDpUA56FGH6jfLDir0KYTNTgYXJTIrBIENI9K46VuxMUMQA=="], - "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.3.4", "", { "os": "linux", "cpu": "x64" }, "sha512-btYIQeNdPbN4JCrCjVB/RwMGrnRY7qWB2piNEfALSByuULKNjPKQ33PYIj38Yd01zCvCV7FotIeXEGSHx3tgCA=="], + "@opentui/core-linux-x64": ["@opentui/core-linux-x64@0.4.3", "", { "os": "linux", "cpu": "x64" }, "sha512-dXpJitiZdYE3hq2Pvx6e9I0uPQSOcnaLLp1pDgWAHv+3kvKSHEX//9Yr/pV/Ua6qqT7p+2D/K4vXNap/NKVo2w=="], - "@opentui/core-linux-x64-musl": ["@opentui/core-linux-x64-musl@0.3.4", "", { "os": "linux", "cpu": "x64" }, "sha512-fhmUey4oJJ2+N62xlIgAPxAl36Fa7wYffqDOT4QLpm0jfyD5xzo+wL/hr2zUqaEI439R8Iq6jHNxf/Nsx1WuuQ=="], + "@opentui/core-linux-x64-musl": ["@opentui/core-linux-x64-musl@0.4.3", "", { "os": "linux", "cpu": "x64" }, "sha512-/QiFpCrpU2O7vy8QYmLIQYbvAtKDgmqcVjR7dGtqSzkiQk3ktNJoo5RozG7ueXnjung1Wp0nKldKxo2Csg/OrA=="], - "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.3.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-sh432vPU+eLp8eA4I0KWKKn7D0VHbk01YTg6mA9/ihCNYHntc6LZ8/sLvsPv8CvKscMotfIkh3M5YhdS36BuXw=="], + "@opentui/core-win32-arm64": ["@opentui/core-win32-arm64@0.4.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-Mx2zuOjrhm/z2SDS6RExIyjP/SnN/8QhhagxURUw0jQi/NssGSeAllu1cBAFFnhobJL5QLTE4FU4CRhUK9svgg=="], - "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.3.4", "", { "os": "win32", "cpu": "x64" }, "sha512-dw8FcjUZaLAjw25P3/7BarobCh/QOHn3srYaWYQdysoqyvSlPkQumpI8kV/KgpJtdITU1GW02MQC4EeLIFFalA=="], + "@opentui/core-win32-x64": ["@opentui/core-win32-x64@0.4.3", "", { "os": "win32", "cpu": "x64" }, "sha512-NuoqvWKGXaYnmlqvu7Gg2lLI6yVMnS9OfWBvxp+7Q+McSgHFSTQmYBXaPpvQ8HikpQXE1nCeMPtuSG4PdZHe2w=="], - "@opentui/keymap": ["@opentui/keymap@0.3.4", "", { "dependencies": { "@opentui/core": "0.3.4" }, "peerDependencies": { "@opentui/react": "0.3.4", "@opentui/solid": "0.3.4", "react": ">=19.2.0", "solid-js": "1.9.12" }, "optionalPeers": ["@opentui/react", "@opentui/solid", "react", "solid-js"] }, "sha512-8fo6BZWQgCjANfbKkzPo0ghAzS1E7TlHjDDS+SUhrX01qEUO1clFTRssKluHbXd2UJY1Ehle01TV5bFmY78f8w=="], + "@opentui/keymap": ["@opentui/keymap@0.4.3", "", { "dependencies": { "@opentui/core": "0.4.3" }, "peerDependencies": { "@opentui/react": "0.4.3", "@opentui/solid": "0.4.3", "react": ">=19.2.0", "solid-js": "1.9.12" }, "optionalPeers": ["@opentui/react", "@opentui/solid", "react", "solid-js"] }, "sha512-sinX0pyQBRrEvo89PSSUbSUDIYpL3xWo81VEfec58VFoVRB5FG48/deAtvRTQfJ8w1kgbzN8hzdOXdSm61zBmw=="], - "@opentui/solid": ["@opentui/solid@0.3.4", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.3.4", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-gin1VnsVBahX0nrU3mpgh5U1qvyJBIZu4NE5mc0YnObWOEf9HVNxKY4/BpUvQPh91kT6zeOzTBvAvYK4R7g9MQ=="], + "@opentui/solid": ["@opentui/solid@0.4.3", "", { "dependencies": { "@babel/core": "7.28.0", "@babel/preset-typescript": "7.27.1", "@opentui/core": "0.4.3", "babel-plugin-module-resolver": "5.0.2", "babel-preset-solid": "1.9.12", "entities": "7.0.1", "s-js": "^0.4.9" }, "peerDependencies": { "solid-js": "1.9.12" } }, "sha512-RcV0+S8HMdXOASyr7HmJUBuTUIaFPzAxMDa44VftS5C2JUgrmAuWo0Njv1q3TWRB1owjHnyKhEfWGKq7A82wxw=="], "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], @@ -2196,43 +2186,43 @@ "@oxc-project/types": ["@oxc-project/types@0.127.0", "", {}, "sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ=="], - "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.20.0", "", { "os": "android", "cpu": "arm" }, "sha512-IjfWOXRgJFNdORDl+Uf1aibNgZY2guOD3zmOhx1BGVb/MIiqlFTdmjpQNplSN58lhWehnX4UNqC3QwpUo8pjJg=="], + "@oxc-resolver/binding-android-arm-eabi": ["@oxc-resolver/binding-android-arm-eabi@11.23.0", "", { "os": "android", "cpu": "arm" }, "sha512-8IJyWRLVAyhTfe9/TIEbQqSQnl5rUqYJrUOS6Dkr+Mq9FGHMxDGeiEmwkBqCvDP5KckpPh/GYSgbag66O6JsCw=="], - "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.20.0", "", { "os": "android", "cpu": "arm64" }, "sha512-QqslZAuFQG8Q9xm7JuIn8JUbvywhSBMVhuQHtYW+auirZJloS41oxUUaBXk7uUhZJgp44c5zQLeVvmFaDQB+2Q=="], + "@oxc-resolver/binding-android-arm64": ["@oxc-resolver/binding-android-arm64@11.23.0", "", { "os": "android", "cpu": "arm64" }, "sha512-pprVojnNhHxupwTT2gdeUlkxll6XEvWWBk3oVicOSNVWQC99OBnDhMQDoirqnzrE1bScQSMS2JgPpqdlrhz/Fg=="], - "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.20.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MUcavykj2ewlR+kc5arpg4tC2RvzJkUxWtNv74pf7lcNk00GpIpN43vXMj+j6r4eMmfZhlb8hueKoIb8e9kAGQ=="], + "@oxc-resolver/binding-darwin-arm64": ["@oxc-resolver/binding-darwin-arm64@11.23.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-mbIrWIMAJeytyee36OyUP5XH92TP7FaKaQ2m5AjokKy7STgjrhRt7SMXqpqLjhGm6Xn721Xmsg6H3Rtd9YQETw=="], - "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.20.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-BGB16nRUK5Etiv//ihPyzj8Lj1px0mhh4YIfe0FDf045ywknfSm0GEbiRESpr6Q4K82AvnyaRIhhluHByvS4bg=="], + "@oxc-resolver/binding-darwin-x64": ["@oxc-resolver/binding-darwin-x64@11.23.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-UnIphmZ1LazUCr9DXWaKYWtKDefPMbgLsywaoYxRqVCNHhq4MM6d2q1Nz1i9Vzxt5i+cE2nRUYpAUHr/lijNYA=="], - "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.20.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JZgtePaqj3qmD5XFHJaSLWzHRxQu0LaPkdoM1KJXYADvAaa83ijXHclV3ej3CueeW0wxfIAbGCZVP45J0CA7uQ=="], + "@oxc-resolver/binding-freebsd-x64": ["@oxc-resolver/binding-freebsd-x64@11.23.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-aaZ/cSEYFkSxgS2hOrobT6RQcsWNviOX8dW6CEkVx2/UYkAf9MeHbjl3W0usWV53rVV//ndBdn2nb1y7jsu4lw=="], - "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.20.0", "", { "os": "linux", "cpu": "arm" }, "sha512-hOQ/p3ry3v3SchUBXicrrnszaI/UmYzM4wtS4RGfwgVUX7a+HbyQSzJ5aOzu+o6XZkFkS3ZXN4PZAzhOb77OSg=="], + "@oxc-resolver/binding-linux-arm-gnueabihf": ["@oxc-resolver/binding-linux-arm-gnueabihf@11.23.0", "", { "os": "linux", "cpu": "arm" }, "sha512-IoJLvO5SjLSVMaq83BNTrPCb1FppvoJc1IhZ5CoUVl3PykUBku7D+LK1j0GSurhJcIc6zfjghsvaZNpq5ev6Mg=="], - "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.20.0", "", { "os": "linux", "cpu": "arm" }, "sha512-2ArPksaw0AqeuGBfoS715VF+JvJQAhD2niWgjE5hVO+L+nAfikVQopvngCMX9x4BD8itWoQ3dnikrQyl5Ho5Jg=="], + "@oxc-resolver/binding-linux-arm-musleabihf": ["@oxc-resolver/binding-linux-arm-musleabihf@11.23.0", "", { "os": "linux", "cpu": "arm" }, "sha512-vskFpwg44T/LFsfjSCnVZ5ygcuqzPC1yUzVEiKa8BgHAQz0+QLQQW3EGWLPVi8EXFghzjR4EtgPBtOhCjU4jdw=="], - "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.20.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0bJnmYFp62JdZ4nVMDUZ/C58BCZOCcqgKtnUlp7L9Ojf/czIN+3j72YlLPeWLkzlr6SlYvIQA4SGV/HyO0d+qg=="], + "@oxc-resolver/binding-linux-arm64-gnu": ["@oxc-resolver/binding-linux-arm64-gnu@11.23.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-//TcHVhrChyw5RYtgts6WO7KcWq9387c1Z5Zvhqpk/ktAbyaRYgBZrpSY1GDCFq50ASt6B6jhh+JxB1rB45IAg=="], - "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.20.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-wKHHzPKZo7Ufhv/Bt6yxT7FOgnIgW4gwXcJUipkShGp68W3wGVqvr1Sr0fY65lN0Oy6y41+g2kIDvkgZaMMUkw=="], + "@oxc-resolver/binding-linux-arm64-musl": ["@oxc-resolver/binding-linux-arm64-musl@11.23.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-ZFqlwiTf7CXLLSGyAR9tYiO33LiaeIEXW+xm42d8mnUGpDgPltyrCGYtQezyMMEXvjhOgCz1X+i7sbDTJEx+bg=="], - "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.20.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-RN8goF7Ie0B79L4i4G6OeBocTgSC56vJbQ65VJje+oXnldVpLnOU7j/AQ/dP94TcCS+Yh6WG8u3Qt4ETteXFNQ=="], + "@oxc-resolver/binding-linux-ppc64-gnu": ["@oxc-resolver/binding-linux-ppc64-gnu@11.23.0", "", { "os": "linux", "cpu": "ppc64" }, "sha512-oZ5LeN5+H1R19dRjTAxKrxQguH+AsemHcnthEfFxf4OjmBSty2doHLeSmMunKy3zpTHJQ3lh3Af+dNS+W6dYeA=="], - "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.20.0", "", { "os": "linux", "cpu": "none" }, "sha512-5l1yU6/xQEqLZRzxqmMxJfWPslpwCmBsdDGaBvABPehxquCXDC7dd7oraNdKSJUMDXSM7VvVj8H2D2FTjU7oWw=="], + "@oxc-resolver/binding-linux-riscv64-gnu": ["@oxc-resolver/binding-linux-riscv64-gnu@11.23.0", "", { "os": "linux", "cpu": "none" }, "sha512-O4ciFDyX5ebQd0qkb1bjAIg8IEfiLT03GbSeylwlwlUMK9KwBWaALwrxSbc0Msaz4U6iPj+T9eRXpD5mxBfmvA=="], - "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.20.0", "", { "os": "linux", "cpu": "none" }, "sha512-xHEvkbgz6UC+A3JOyDQy76LkUaxsNSfIr3/GV8slwZsnuooJiIB34gzJfsyvR4JdCYNUUPsRJc/w/oWkODu+hg=="], + "@oxc-resolver/binding-linux-riscv64-musl": ["@oxc-resolver/binding-linux-riscv64-musl@11.23.0", "", { "os": "linux", "cpu": "none" }, "sha512-P3o8Y9kISYjcxadmbO+94ThRwLhwGuDAbA7dcdd4+YLpfeF+mmobz8fXf4NmSdfSqjyRSkceJDBRZha9NVYkiQ=="], - "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.20.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-aWPDUUmSeyHvlW+SoEUd+JIJsQhVhu6a5tBpDRMu058naPAchTgAVGCFy35zjbnFlt0i8hLWziff6HX0D3LU4g=="], + "@oxc-resolver/binding-linux-s390x-gnu": ["@oxc-resolver/binding-linux-s390x-gnu@11.23.0", "", { "os": "linux", "cpu": "s390x" }, "sha512-oj03m1E3RmTFczKhcKJDzHaEDKJnPIsDcQFVxBJsSdXGSuIPdt5TvcM332FfMQgzI6yDJqyl4InrnFfXrmUTKQ=="], - "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.20.0", "", { "os": "linux", "cpu": "x64" }, "sha512-x2YeSimvhJjKLVD8KSu8f/rqU1potcdEMkApIPJqjZWN7c2Fpt4g2X32WDg1p+XDAmyT7nuQGe0vnhvXeLbH+g=="], + "@oxc-resolver/binding-linux-x64-gnu": ["@oxc-resolver/binding-linux-x64-gnu@11.23.0", "", { "os": "linux", "cpu": "x64" }, "sha512-BqJxbSC8FdP7mSuSpRePTGHm0hXWV+dfz//f7SjsteZncLaBgWTBmi/OZNv7sX6CyG/Pt/eJkPorP+DkMOhMwQ=="], - "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.20.0", "", { "os": "linux", "cpu": "x64" }, "sha512-kcRLEIxpZefeYfLChjpgFf3ilBzRDZ+yobMrpRsQlSrxuFGtm3U6PMU7AaEpMqo3NfDGVyJJseAjnRLzMFHjwQ=="], + "@oxc-resolver/binding-linux-x64-musl": ["@oxc-resolver/binding-linux-x64-musl@11.23.0", "", { "os": "linux", "cpu": "x64" }, "sha512-utmw+VmUrW4K8LI5/6jhg4aGYKJHOIjQ9syYOOA6pF3w7haKu4r4enTe2U0C04/HbUvkq/Zif43xFsKW1Pnq9w=="], - "@oxc-resolver/binding-openharmony-arm64": ["@oxc-resolver/binding-openharmony-arm64@11.20.0", "", { "os": "none", "cpu": "arm64" }, "sha512-HHcfnApSZGtKhTiHqe8OZruOZe5XuFQH5/E0Yhj3u8fnFvzkM4/k6WjacUf4SvA0SPEAbfbgYmVPuo0VX/fIBQ=="], + "@oxc-resolver/binding-openharmony-arm64": ["@oxc-resolver/binding-openharmony-arm64@11.23.0", "", { "os": "none", "cpu": "arm64" }, "sha512-V6lbRrthHa4TbvsLjPtg+EkXT1tRY+s4I8rYLXUfiHlZzGx3sLv1EH9CEOOevjvUYHLsbe/gqCIc73XnQfPb9A=="], - "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.20.0", "", { "dependencies": { "@emnapi/core": "1.10.0", "@emnapi/runtime": "1.10.0", "@napi-rs/wasm-runtime": "^1.1.4" }, "cpu": "none" }, "sha512-Tn0y1XOFYHNfK1wp1Z5QK8Rcld/bsOwRISQXfqAZ5IBpv8Gz1IvV39fUWNprqNdRizgcvFhOzWwFun2zkJsyBg=="], + "@oxc-resolver/binding-wasm32-wasi": ["@oxc-resolver/binding-wasm32-wasi@11.23.0", "", { "dependencies": { "@emnapi/core": "1.11.1", "@emnapi/runtime": "1.11.1", "@napi-rs/wasm-runtime": "^1.1.6" }, "cpu": "none" }, "sha512-gRoOxQPdnAmIAjxcuQNBxfihvx+wjTaQM/9/eP12xwnGNawOG/+Zz9RHN4WNSxT45b5CrscK4NB8aPh+oZQXAQ=="], - "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.20.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-qPi25YNPe4YenS8MgsQU2+bIFHxxpLx1LVna2444cEHqNPhNjvWf9zqj4aWE43H9LpAsTmkkAlA3eL5ElBU3mA=="], + "@oxc-resolver/binding-win32-arm64-msvc": ["@oxc-resolver/binding-win32-arm64-msvc@11.23.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-CgTGMYsJVe1eUiCdJTpGw21svXw79ITsemN1h0hcNkiswasDbN5MoibSLY+gRMWP5syfEz5iffrjZnwEP8xeUA=="], - "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.20.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Wb14jWEW8huH6It9F6sXd9vrYmIS7pMrgkU6sxpLxkP+9z+wRgs71hUEhRpcn8FOXAFa27FVWfY2tRpbfTzfLw=="], + "@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.23.0", "", { "os": "win32", "cpu": "x64" }, "sha512-gUGJpr+Rn6zMxm5juApV0K3U845i8t47o8k+rbO0BHbi4PoJIfSPeQmrE2dgohQm2g5k6iviNFyXCGqvmaYUpw=="], "@oxc-transform/binding-android-arm64": ["@oxc-transform/binding-android-arm64@0.96.0", "", { "os": "android", "cpu": "arm64" }, "sha512-wOm+ZsqFvyZ7B9RefUMsj0zcXw77Z2pXA51nbSQyPXqr+g0/pDGxriZWP8Sdpz/e4AEaKPA9DvrwyOZxu7GRDQ=="], @@ -2358,7 +2348,7 @@ "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.1", "", { "os": "win32", "cpu": "x64" }, "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA=="], - "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.7.0", "", { "dependencies": { "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-W8ZfWzLmQnrcky+eh3tni4IozMdqBDiHWU0N+vve/UGjMaUs8c0L7A2oEdkBXS8rTpWDpK/aoI3DG/L/hxmxPg=="], + "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.8.0", "", { "dependencies": { "@peculiar/utils": "^2.0.2", "asn1js": "^3.0.10", "tslib": "^2.8.1" } }, "sha512-7YT0U/ze0tF2QOBbE15gKZwy5tvgGyLRiRHLzhlbOpf7BT032oBSd0haZqXn5W6l26WLlu3dyxzjM+2638/z2Q=="], "@peculiar/json-schema": ["@peculiar/json-schema@1.1.12", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w=="], @@ -2410,8 +2400,6 @@ "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], - "@protobufjs/inquire": ["@protobufjs/inquire@1.1.2", "", {}, "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw=="], - "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], @@ -2486,55 +2474,55 @@ "@rollup/pluginutils": ["@rollup/pluginutils@5.4.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg=="], - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.4", "", { "os": "android", "cpu": "arm" }, "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.62.2", "", { "os": "android", "cpu": "arm" }, "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg=="], - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.4", "", { "os": "android", "cpu": "arm64" }, "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw=="], + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.62.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw=="], - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.60.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA=="], + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.62.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A=="], - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.60.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg=="], + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.62.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA=="], - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.60.4", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g=="], + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.62.2", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw=="], - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.60.4", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw=="], + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.62.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg=="], - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.60.4", "", { "os": "linux", "cpu": "arm" }, "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA=="], + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.62.2", "", { "os": "linux", "cpu": "arm" }, "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg=="], - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.60.4", "", { "os": "linux", "cpu": "arm" }, "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w=="], + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.62.2", "", { "os": "linux", "cpu": "arm" }, "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA=="], - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.60.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg=="], + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.62.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA=="], - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.60.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A=="], + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.62.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ=="], - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ=="], + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg=="], - "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw=="], + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ=="], - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.60.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg=="], + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.62.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A=="], - "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.60.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A=="], + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.62.2", "", { "os": "linux", "cpu": "ppc64" }, "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w=="], - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA=="], + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg=="], - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.60.4", "", { "os": "linux", "cpu": "none" }, "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw=="], + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.62.2", "", { "os": "linux", "cpu": "none" }, "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q=="], - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.60.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ=="], + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.62.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg=="], - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.60.4", "", { "os": "linux", "cpu": "x64" }, "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ=="], + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.62.2", "", { "os": "linux", "cpu": "x64" }, "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A=="], - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.60.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg=="], + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.62.2", "", { "os": "linux", "cpu": "x64" }, "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg=="], - "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.60.4", "", { "os": "openbsd", "cpu": "x64" }, "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA=="], + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.62.2", "", { "os": "openbsd", "cpu": "x64" }, "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg=="], - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.60.4", "", { "os": "none", "cpu": "arm64" }, "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg=="], + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.62.2", "", { "os": "none", "cpu": "arm64" }, "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA=="], - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.60.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw=="], + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.62.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg=="], - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.60.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA=="], + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.62.2", "", { "os": "win32", "cpu": "ia32" }, "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q=="], - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.60.4", "", { "os": "win32", "cpu": "x64" }, "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw=="], + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.62.2", "", { "os": "win32", "cpu": "x64" }, "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg=="], - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.4", "", { "os": "win32", "cpu": "x64" }, "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw=="], + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.62.2", "", { "os": "win32", "cpu": "x64" }, "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA=="], "@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="], @@ -2620,93 +2608,93 @@ "@slack/socket-mode": ["@slack/socket-mode@1.3.6", "", { "dependencies": { "@slack/logger": "^3.0.0", "@slack/web-api": "^6.12.1", "@types/node": ">=12.0.0", "@types/ws": "^7.4.7", "eventemitter3": "^5", "finity": "^0.5.4", "ws": "^7.5.3" } }, "sha512-G+im7OP7jVqHhiNSdHgv2VVrnN5U7KY845/5EZimZkrD4ZmtV0P3BiWkgeJhPtdLuM7C7i6+M6h6Bh+S4OOalA=="], - "@slack/types": ["@slack/types@2.21.1", "", {}, "sha512-I8vmSjNYWsaxuWPx6dz4yeh0h7vRBWbgAMK14LEmblbZ404BtrPbXs6jDPx4cYgGf8msDGF4A9opLZBu21FViQ=="], + "@slack/types": ["@slack/types@2.22.0", "", {}, "sha512-sZ9lIgJhPX2qft/tKWiklFlc0o1FWeI7QtciZJfW1+ErH1eGGHvOZ8e73sleTCFEFJp1q/R0WeS8Oa7AsiDprg=="], "@slack/web-api": ["@slack/web-api@6.13.0", "", { "dependencies": { "@slack/logger": "^3.0.0", "@slack/types": "^2.11.0", "@types/is-stream": "^1.1.0", "@types/node": ">=12.0.0", "axios": "^1.7.4", "eventemitter3": "^3.1.0", "form-data": "^2.5.0", "is-electron": "2.2.2", "is-stream": "^1.1.0", "p-queue": "^6.6.1", "p-retry": "^4.0.0" } }, "sha512-dv65crIgdh9ZYHrevLU6XFHTQwTyDmNqEqzuIrV+Vqe/vgiG6w37oex5ePDU1RGm2IJ90H8iOvHFvzdEO/vB+g=="], - "@smithy/config-resolver": ["@smithy/config-resolver@4.5.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-HehAZr4sq2m+4zHgEqDvtWENy/B5yywMKA8Pl4gBcU3F4ekelpZqDLDxQHdJlguaKNyTq31cZYjLWomzdujQrA=="], + "@smithy/config-resolver": ["@smithy/config-resolver@4.6.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-yI8StAYGQKiI+DxT0xkLhHSzxcIFSZTTWi0c4Lk3WLgmbe2QfLpR/Roo81ZF3VYwfwqH4IQVTKsy3FLZiVRaTQ=="], - "@smithy/core": ["@smithy/core@3.24.5", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-Kt8phUg45M15EjhYAbZ+fFikYneijLu9Liugz8ZsYz2i8j0hzGv27LWKpEHYRfvj+LyCOSijpcR/2i8RouV+cA=="], + "@smithy/core": ["@smithy/core@3.29.1", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-qoiY4nrk5OCu1+eIR1VB8l5DmON/oKiqrd5zZFAhXJXjJlLWQusKEW/SkBDAtGDcPaz86m9kfcE1lngU0GlM6A=="], - "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.3.6", "", { "dependencies": { "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-tHhdiWZfG1ZIh2YcRfPJmY2gHcBmqbAzqm3ER4TIDFYsSEqTD5tICT7cgQ/kI8LRakxp12myOYyK68XPn7MnHw=="], + "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-B2WQ/PV/H6Jeg3lrIq6bKUfa6Hy01mtK7CGs6lhjzHA6k4aagldH6T6eEjnzKl4HI0cJnAsxfJ19pgb5PV+CVQ=="], "@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.7", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.11.0", "@smithy/util-hex-encoding": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-DrpkEoM3j9cBBWhufqBwnbbn+3nf1N9FP6xuVJ+e220jbactKuQgaZwjwP5CP1t+O94brm2JgVMD2atMGX3xIQ=="], - "@smithy/eventstream-serde-browser": ["@smithy/eventstream-serde-browser@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-M9rMkTar7JcRrvUHsK1271AuWDmrISIPQpQ4TSHmYZ4KMisGnMH0gfjCWnBwdndR7skvvp/UheHhZGvO3Cr8/g=="], + "@smithy/eventstream-serde-browser": ["@smithy/eventstream-serde-browser@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-++N4gziozNj71MLr9HN/pzt8nnoTdsX9ccjShQthl2TcoZtHObjmbT3d3kBZ8ih1uRTepGGVUVc06qkFtRUAKg=="], - "@smithy/eventstream-serde-config-resolver": ["@smithy/eventstream-serde-config-resolver@4.4.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-lUwPPu7DNNVJjeS+gV7g2rDHbW9X1wSRQIsIyzOgBtP7KDMefLhz0kz42AWAxZIFPcOO3pUbtq76LSkVcxLKRw=="], + "@smithy/eventstream-serde-config-resolver": ["@smithy/eventstream-serde-config-resolver@4.5.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-Xn7gFGQg6fxaE0bQSnoAN6miP4M4t7juhv/0ch7wBba+8r+XHCNaF7ktpLkOSrzyCrVQ3ixV8SaMZKINWB80hA=="], - "@smithy/eventstream-serde-node": ["@smithy/eventstream-serde-node@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-QydEYKqvdiS6dJb0tOfDiogt12FzzImt2FnL7gMD72hNrkiUAUKqtStRmkTrdzDKFJ46abe3yH94luCuhtnCkQ=="], + "@smithy/eventstream-serde-node": ["@smithy/eventstream-serde-node@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-kt2PZjaLJK+kSfLetRFKdHo6rfUeVuk65TreMlGBwVi+EhGspaDw3GTQMKKCrHPVe/LVYrkNf518pMZ4hrj/EQ=="], - "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.4.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-SK3VMeH0fibgdTg2QeB+O4p7Yy/2E5HBOHJeC58FshkDdeuX8lOgO7PfjYfLyPLP1ch55j91cQqKBzDS0mRjSQ=="], + "@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.6.3", "", { "dependencies": { "@smithy/core": "^3.29.1", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-CwCc/7SMTj45y97MUnDTbTaxvtAsiNNRm81z3abROIuMbMsC2Iy5EKfkkVdsKrz8WExQAAMx1EJapq+9j4fFTQ=="], - "@smithy/hash-blob-browser": ["@smithy/hash-blob-browser@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-DNInwxNX32WtmhiKVrplzFtkKk5ePNHitJYPCnsPrD2EHm06iWJKQo8F8eq5ss94yp/xSfmojYD7nFBsgzrHHQ=="], + "@smithy/hash-blob-browser": ["@smithy/hash-blob-browser@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-9fGuAK2nhFC3J3XCOrAlzUP6td4LhBN7sBUxkcGMzXljFMJAmVnXBoKLImZP2BNB5IqJJlEUUAgqNJ5uAuIudQ=="], - "@smithy/hash-node": ["@smithy/hash-node@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-/tUIDaB36qjLq/CIhMRIiFXCT7rVGBGAhFmMA9PbC/iW2u3QPNATZuFSdK0JBO3qeSPoHBeudFMmsbFq2Mf5EQ=="], + "@smithy/hash-node": ["@smithy/hash-node@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-O6YGQgZGxypohUJDm+aIBNx9ldzOvQOjnnAmHYKAVJcVRMYQLf+g88s/vCUIHJudeXbgEo7xq1vXUGYlBpdBsg=="], - "@smithy/hash-stream-node": ["@smithy/hash-stream-node@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-dLboKYf5ezU+b8SDDzVNjSHWHYPiU9aTI7IfIh9GhUpvCkwfdw1zUtK6dAGFHOrI5l1nVmsEWZrcAHophlNKug=="], + "@smithy/hash-stream-node": ["@smithy/hash-stream-node@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-yk7nZACmlT5GVchRP+vazlOU9krAsl1AwPny7x4YmiDOsnFdgxl9LhoXRlN12RY+t60dY2fDoiNpAlmsCHPPMQ=="], - "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-c8C1GzrU4PcY1QT/HP0ILCTLutyVONT93kPSisOyHoZaXlKQZtV6+RKqolhBtPolGULf59vq2yseagU6+WY82w=="], + "@smithy/invalid-dependency": ["@smithy/invalid-dependency@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-M2NNf2yB5pDYQiMyW3q6kD/aQyEfQlVFtFNR+LCnRKS/sg9xqOrOqkIZNP94B2aTwf+pwX3Qgp6foKw2ls9vIg=="], - "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-AzWk7NstKv+z3h0GmZlQkDdgcnh3tvBWnBr0zoBY/agV/zaMqEBnpqgF1S+sJAy5yfE1b2KZqiz+uHHV70vOYg=="], + "@smithy/is-array-buffer": ["@smithy/is-array-buffer@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-eFcGFew1vrbZvpAeMdAjoivnWepwb2BTHZq5MPjcSBFL1Sm6ThDC/se6Q1i8BlUz9qKsh0Kd6jhEIf5BXtEhjw=="], - "@smithy/md5-js": ["@smithy/md5-js@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-U/zFWFDuNFspkLAtUbatmpevrRjXwQkoGPJTg1hapUsjLKK+aN3u4seX4+aSBzLom+RnZSdWncfSIgG100vsGg=="], + "@smithy/md5-js": ["@smithy/md5-js@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-iF/3959r6gxyhaMA8ZO1dAknRe5znpRJX8KGp9zh3YhkFX7XYRJXxR1vM5pV4rTHfCAEKZRTR5wqYnfNLBvlBw=="], - "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-lzOzJ4c0t3vkBut02CjdWNgduN3mUWjc1WK9TPr75KVV6OgVWico9wMDn9ZnQN97VJPYfweBW6Dm5CElvQl8BQ=="], + "@smithy/middleware-content-length": ["@smithy/middleware-content-length@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-kMXyfLgm2iqC3objUiElh1fp0AI33PxiAmPX+C0z7H8v4sfae2I2V9N62MlwO/LVPf+MlXpmfCYCHouetbecGg=="], - "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.5.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-8DnkSoUMQAcuT/DHdigsFPti8M/Dm6TPCAsrIQ/bUDGxRkrgGuI++3dXRr8CoUyc9r0kGSCcZHjJje407ydgBQ=="], + "@smithy/middleware-endpoint": ["@smithy/middleware-endpoint@4.6.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-d7L894W4LE9HL2MkpWi0+KJG6/VCcuoxkquVaXYMMsrqK7PLT83GZsUBYL+ixxpEfwnlSE5hBotsB1A/qfWO9A=="], - "@smithy/middleware-retry": ["@smithy/middleware-retry@4.6.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-fumMIfh5xOFjirylbSzmBX9bgQtrWFtQrosPfkjsJSBzqXVbQMNDGIC8oJBz4V3bokIm2F0CL3bziLtbXR7cbA=="], + "@smithy/middleware-retry": ["@smithy/middleware-retry@4.7.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-zUF+liYyzSiPcz8vQhGCjUlykg521Y3shrsyzJ37Y3nkpz20KujcVXcOvgZb6e68n7Unl/Pb2RG0jrkx73AE+Q=="], - "@smithy/middleware-serde": ["@smithy/middleware-serde@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-+7glfRrb7byruZCPAM53TvmK8cx/ghzAThB4EvPzHynAYobtISl0g+DzzSVEC0NQob5BunP9gC9GP+Fcz6H9yw=="], + "@smithy/middleware-serde": ["@smithy/middleware-serde@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-h9JBsYQBiltcbe5EJECXoJy+ZJSmnJKhc9UXyoWvEB1BIUkE8inxQ614dpeb+yydm2cq4YXqMXQLQB0QUBE6rA=="], - "@smithy/middleware-stack": ["@smithy/middleware-stack@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-Yj4wjBQZXHePRIy9cBIKfCOn/kPjRlgDPGlr7DjIhwrnz8kWu7Ux7UwPr51P/wcug5oq4nWdBXSY4TV5afBdew=="], + "@smithy/middleware-stack": ["@smithy/middleware-stack@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-LUO+XAQP381sbiZ0QHOSLKPpS2I0/wXTh44rH/kP4/751Ogscn5JUsAWvUH+rYJWLupmiEsdHZT3Bn4Dvd4J/Q=="], - "@smithy/node-config-provider": ["@smithy/node-config-provider@4.4.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-c2G9QJ4xVZLwAkAf+WQESSSCkKbtt33ytje1klGvTcBn6cKuqV28E+62wbRPHwuTikkB3LQ7CBnNrayCoJur5A=="], + "@smithy/node-config-provider": ["@smithy/node-config-provider@4.5.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-3fFpVGK28z1UhbDIPY6pujmnGwDhcD70NqJ8wJJwdQES5EYBe3mdOojSZdXtL0jfQE9BAbZSBi73WQ6VEOLRgQ=="], - "@smithy/node-http-handler": ["@smithy/node-http-handler@4.7.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-3dA9TQ+ybRSZ/m0wnbZhiBy4Dezjgq1Ib/ZZrYTpJDBgpoLLU/SDzZc/g0x0MNAdOJe1wPcM+x2PBRmoOur+Sw=="], + "@smithy/node-http-handler": ["@smithy/node-http-handler@4.9.3", "", { "dependencies": { "@smithy/core": "^3.29.1", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-qZTa4gQFUo8RM02rk6q5UVTDLNrQ1oS20LsepBzqq1QBVc/EHJ03OOUADcqMZiXHArW+Y7+OGY0BpdTwZRq/Yg=="], - "@smithy/property-provider": ["@smithy/property-provider@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-QNc22/FgfEm/9/rkefShfQUVckH3HWiQ2RPs+40hwAdY65hbg88gombeHwkfMzmVDZjolcyQeyOjnxZRmpavIA=="], + "@smithy/property-provider": ["@smithy/property-provider@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-lXq53BiaAI5XHMu0Sckzc+ouMX33exTdxkIyfaP4/61AAblnnjSd1QiT64LqjlFYwtxl8ldya1Wx0LLhtMv+hw=="], - "@smithy/protocol-http": ["@smithy/protocol-http@5.4.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-jOD+4WNWQLntiLJn3r82C7BLheEbRCKTbU5U5bskZmT7nwRiGkh0IghuHwHRZ1ZEFXpHltQxxp9/koOPsdluJg=="], + "@smithy/protocol-http": ["@smithy/protocol-http@5.5.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-ezPS1foOBPU+uv0da16sLF/7fMBXxeo7hFKitn/2gOxHd8HaQ7qK6DT8l0f1dUGoUS1lZC2s7mEkCwJ44QLCJg=="], - "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.5.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-W7IPDXj8AZdyH5EWEXmOvN7ao8iN0JKJ0FNLpGcqj08HZc0MmqGcJnGgh3DfUdGYtzrPIEudxs+ovq/EWZgLjg=="], + "@smithy/shared-ini-file-loader": ["@smithy/shared-ini-file-loader@4.6.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-kxqLaXEbE7GhUIupgwMvAL0bM59UlbhKcRQmXPDO6/ZyL712fhn2u63WJEgWu2b/HDLstWNL5QejZ+mTBI8EYg=="], - "@smithy/signature-v4": ["@smithy/signature-v4@5.4.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-QBJKWGqIknH0dc9LWpfH1mkdokAx6iXYN3UcQ3eY6uIEyScuoQAhfl94ge7ozUy9WgFUdE8xsvwBjaYBbWmPNA=="], + "@smithy/signature-v4": ["@smithy/signature-v4@5.6.2", "", { "dependencies": { "@smithy/core": "^3.29.1", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-QgHflghMoPxCJ9axiCVh8KZfbC9fuP6vkXXyK//E3cq7nLaSSyyLj0GAoqVWezYeDQmXIZhmlRvLE16jsqDK6g=="], - "@smithy/smithy-client": ["@smithy/smithy-client@4.13.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-pg9QRQESz3m/5HgAW/z9lA3ln8MSsCWNWc82MX40Djlxpcj/+7DZQ0yIk7tGWYJCVZog/9LBdNl1uEVRAhqm5Q=="], + "@smithy/smithy-client": ["@smithy/smithy-client@4.14.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-Nr6u0buDP8iprqxAJ83pSFu2RavKHa/OG8n/ReWTYHg1OS3GLoDoa8F+2zoWoYkvwUawTa/dFugJ7NS0CuPcYg=="], - "@smithy/types": ["@smithy/types@4.14.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-P+otAxbV4CqBybp7EkcJCrig63yE2E7PuNVOmilVMRcx/O+QDzGULTrKsq4DV13gSfak9ObPrWaHl/9bL5YcWw=="], + "@smithy/types": ["@smithy/types@4.15.1", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-x3L0XSACF6UYzKpa9biqiRMgvH5+wnFFew9Tm/grFYqgaupPwx/+ojDPpPJM8dZON3S9tjz5U+PQYsCBd1Mw5Q=="], - "@smithy/url-parser": ["@smithy/url-parser@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-f7kUYrRdLiAHz10WXQXiUkuBFaL2c2ZBD2kSwZyQBh73lWFTvXwdpS9l5irQ/uldk8YMJpm66BozmqCg/3uZvA=="], + "@smithy/url-parser": ["@smithy/url-parser@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-bR6Te2/feLMCLiyEFqnZpM5AqkXlBGr7A5jHQn+WSVLk0X53NvPq1KF8jh5TJIv56RzDv3oKEW3t0DysRNLZdw=="], - "@smithy/util-base64": ["@smithy/util-base64@4.4.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-2J8l+DoX3IIiP75X5SYkJ3mIgOkxW29MxOs7oPjbXLuInQ7UL6zLw2IJHbQ44+eKDBBhTjvt+GgwsTTNBGt8zA=="], + "@smithy/util-base64": ["@smithy/util-base64@4.5.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-N3hAANIKhtewRYICJjHscGtqQmAWISV+6Re5kbh8mOMiGKn6CvM252zocDdh9YWCmE/x9S1XAbe+5lzw+zjEZQ=="], - "@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-nQtYwXg4spM6uc0Luq3yck+WXZ1VPfrYkC2SqkQ+YOGks0qR2bKKlSCjidSqfpq+VAY/RJe1O5V+CtBmnT63KQ=="], + "@smithy/util-body-length-browser": ["@smithy/util-body-length-browser@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-oCVUok1wVnObl1nvtuj3DrVDtsgFNSmvVFc5VstnXKusqGKycKKPTtQHdlUMCklpB4g8pOp0jUOt7l7aAJlksg=="], - "@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-BAsAed9yWExECwNIi61Le6D8ZTY71MFEFrf3d4L2+uzcbTjFAWxOtymkA1vCV8bNZQN9TGgZo4c68JDsnjNShA=="], + "@smithy/util-body-length-node": ["@smithy/util-body-length-node@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-hNk9goWxXF3BGXT7yIyyzG29gYvtqxk55cn7wyZHRsWDWEAA1ZN9E+tLFLpKEkEPVVqprCqLmHAmnmPc/556sg=="], - "@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-CthqHx5VTlNIsS5rJni+pIfkGgYPnVFsy9qYiv8e+hMQDPemZod5wTa+2DkrI+vubX51sD6qqcgH3UHqdTf2bw=="], + "@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-xJPlHmHVnEXFpO1Z1JZ0Labweqkzty5RjpnTH2C7niM0nI7cJSw3LEVfhIYG6zK4EpYtiiB14SUeaTH8R/9G5Q=="], - "@smithy/util-config-provider": ["@smithy/util-config-provider@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-7yflDiFlO+bVXjI7BJe3B8jx5HyGCI146xrkZRwK9pO2ParfgWzgGfPGK3KsXkxcU+EBzIz1kFnX7fJRxAMbQA=="], + "@smithy/util-config-provider": ["@smithy/util-config-provider@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-L7S1sESDjjfAh7YMCnEb1fg0WSF5i7Y+bwvf76sryJzm1TI9MACvdtrKB0yELFzYUdGE5jOGKjABFYSuZMtNmQ=="], - "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.4.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-LbE6AGHhQOunqIN5UyWDMgpPwmUHUzrV2NtUOQ+lt6Stpipzo6S7uDyeGtO0GGgUD1balEPCNu8Xfl1AQNiruQ=="], + "@smithy/util-defaults-mode-browser": ["@smithy/util-defaults-mode-browser@4.5.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-lsApK6dpDK9LY49GMHEsNQV2XpT/Y9WxKy8CmfbN6oLqPMCXlCYVLeIhedtdJmgbi0Mg09ZIjbhYVEg+V/wK0Q=="], - "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-72gNpNDQ2iIGbaNmeaF9I58shWsEuD5tNI7my5uXlm1CSPH5i8IKI/nzU50qqB8y+kgw/qTLGgsf0We5qeM/aA=="], + "@smithy/util-defaults-mode-node": ["@smithy/util-defaults-mode-node@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-lKt5zA8YVx5SXanQ1t1iVZuaCuQcoJxUEh9BEpW64y5qKo3asCua7PiYsKkCv2RctwWZQqeEquB6WMostXBI4w=="], - "@smithy/util-endpoints": ["@smithy/util-endpoints@3.5.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-NJhe8KmNjeZ7V+gJsQR5xw0IN47N8pBKosed40xfhelDuYkg8VQ5CVGDcHTEuJq3e3zQb21vnoOOReQothejhA=="], + "@smithy/util-endpoints": ["@smithy/util-endpoints@3.6.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-IIgVh4W8OwBP3WL17RROPs7EWkaRdygli4I3vnhEK+zkVvMFagoKN7KbDCitTafQ7GSM3ev0ZawYehN+cFzd+A=="], - "@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-+ip3QrXGjDOzV/ciNWPTm6bhJuXjmzugMR19ouXgA26QqhEo0zuXM7pvYE9S4VfX13YmPgSYDPkF4+2bPqIwAg=="], + "@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-hdLoL1t/JqmsSbhodgbs7/fYwXIGEq+3MiJcSBsVoHsHyaBFv/Y1qQfZm0i5FR3NakhgYQsD5d1Z4Aoc5JdDlg=="], - "@smithy/util-middleware": ["@smithy/util-middleware@4.3.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-N1IR4bMHIDbqO3GxkJHgqNGsnrd7MNrj+EVqhFqKeRqSBV5I3KCjNllKfnbF9KV0YteGhfLqcMR5CYsPLJqpqw=="], + "@smithy/util-middleware": ["@smithy/util-middleware@4.4.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-13aBkHIs4auNrqDwGE40rbkF/gXZQ/qNtufQKDHxYjc1juSAzY0ol0Kbv8Md5oaUovnNpTp2cXLQXZn3eAEnlA=="], - "@smithy/util-retry": ["@smithy/util-retry@4.4.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-W9Ovy9i02yGqtLlpqZNQuXNxXc5OPfXujnembxN/FxyBtGjJd8vKY0PQYEJ8FNybTOcXG+ZxsSsX23HOb3zQzg=="], + "@smithy/util-retry": ["@smithy/util-retry@4.5.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-o7QZYe6U1HV5c9Oqb/mwf01YL+8NJ1wTWjGNSyA3fuaOaiC0U2UhmAY320dcBZlKOJU8O60QNfr8RWqE+OnU/w=="], - "@smithy/util-stream": ["@smithy/util-stream@4.6.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-PFzBVEBP5k8R+mK/c+VAKmtpUTL+KzBIXWJ6oM0GWOb31K+QgymXV9IW03XLPM1wtkC7oAb9ZBN2aswSSVbNFg=="], + "@smithy/util-stream": ["@smithy/util-stream@4.7.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-eUq7Efp6Wn0/IzSs4EP55whnN2jQF/U20HxIEOg+zW3RyfuM6ypW7RvdMiJV+AOeVfsU6Yn76sraz1ayDgZvBg=="], "@smithy/util-utf8": ["@smithy/util-utf8@4.2.0", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw=="], - "@smithy/util-waiter": ["@smithy/util-waiter@4.4.5", "", { "dependencies": { "@smithy/core": "^3.24.5", "tslib": "^2.6.2" } }, "sha512-EYviebytZE6vplW0AGwZ2Rc3sNuVR83lfUCNZu11VchUiKhMwJqrRWy7iVDTNEwG/vEwItno591Iad6/prj6Bw=="], + "@smithy/util-waiter": ["@smithy/util-waiter@4.5.6", "", { "dependencies": { "@smithy/core": "^3.29.1", "tslib": "^2.6.2" } }, "sha512-96pDomZ4N3QmkcFZ9m9wl68pW8ny+JSV2fBZhmhQBrsuvygH90DNiFafKsGqzwvLQrh3mURsGpiqwxGHH4ZwcQ=="], "@socket.io/component-emitter": ["@socket.io/component-emitter@3.1.2", "", {}, "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="], @@ -2758,7 +2746,7 @@ "@solidjs/start": ["@solidjs/start@https://pkg.pr.new/@solidjs/start@dfb2020", { "dependencies": { "@babel/core": "^7.28.3", "@babel/traverse": "^7.28.3", "@babel/types": "^7.28.5", "@solidjs/meta": "^0.29.4", "@tanstack/server-functions-plugin": "1.134.5", "@types/babel__traverse": "^7.28.0", "@types/micromatch": "^4.0.9", "cookie-es": "^2.0.0", "defu": "^6.1.4", "error-stack-parser": "^2.1.4", "es-module-lexer": "^1.7.0", "esbuild": "^0.25.3", "fast-glob": "^3.3.3", "h3": "npm:h3@2.0.1-rc.4", "html-to-image": "^1.11.13", "micromatch": "^4.0.8", "path-to-regexp": "^8.2.0", "pathe": "^2.0.3", "radix3": "^1.1.2", "seroval": "^1.3.2", "seroval-plugins": "^1.2.1", "shiki": "^1.26.1", "solid-js": "^1.9.9", "source-map-js": "^1.2.1", "srvx": "^0.9.1", "terracotta": "^1.0.6", "vite": "7.1.10", "vite-plugin-solid": "^2.11.9", "vitest": "^4.0.10" } }, "sha512-7JjjA49VGNOsMRI8QRUhVudZmv0CnJ18SliSgK1ojszs/c3ijftgVkzvXdkSLN4miDTzbkXewf65D6ZBo6W+GQ=="], - "@speed-highlight/core": ["@speed-highlight/core@1.2.15", "", {}, "sha512-BMq1K3DsElxDWawkX6eLg9+CKJrTVGCBAWVuHXVUV2u0s2711qiChLSId6ikYPfxhdYocLNt3wWwSvDiTvFabw=="], + "@speed-highlight/core": ["@speed-highlight/core@1.2.17", "", {}, "sha512-Z92FwKpCtfaW1V0jTU/fh3QzYEZN8wDwrzRIBoADCJfn4mJCNcJN/XegifX7BDrQ8/h9Xh/JnbyMchL0FqXrkg=="], "@standard-community/standard-json": ["@standard-community/standard-json@0.3.5", "", { "peerDependencies": { "@standard-schema/spec": "^1.0.0", "@types/json-schema": "^7.0.15", "@valibot/to-json-schema": "^1.3.0", "arktype": "^2.1.20", "effect": "^3.16.8", "quansync": "^0.2.11", "sury": "^10.0.0", "typebox": "^1.0.17", "valibot": "^1.1.0", "zod": "^3.25.0 || ^4.0.0", "zod-to-json-schema": "^3.24.5" }, "optionalPeers": ["@valibot/to-json-schema", "arktype", "effect", "sury", "typebox", "valibot", "zod", "zod-to-json-schema"] }, "sha512-4+ZPorwDRt47i+O7RjyuaxHRK/37QY/LmgxlGrRrSTLYoFatEOzvqIc85GTlM18SFZ5E91C+v0o/M37wZPpUHA=="], @@ -2766,25 +2754,25 @@ "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], - "@storybook/addon-a11y": ["@storybook/addon-a11y@10.4.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "axe-core": "^4.2.0" }, "peerDependencies": { "storybook": "^10.4.1" } }, "sha512-MGft/IXjJ20a9KbaSVG9bHTAAoanbucKrgEiJJRNqpim8DsXA01+XTdSk17LmiOCB203Rrq9mWgdQ6+79cc8iA=="], + "@storybook/addon-a11y": ["@storybook/addon-a11y@10.4.6", "", { "dependencies": { "@storybook/global": "^5.0.0", "axe-core": "^4.2.0" }, "peerDependencies": { "storybook": "^10.4.6" } }, "sha512-XCJy+f0DFOiCgUU9knRDlLDxVFI+AAQ3/wE/NF85zB9iDPPS2DwkSN+mas3zDgHt66zhN8Cq3/UiyCDUweV9Zw=="], - "@storybook/addon-docs": ["@storybook/addon-docs@10.4.1", "", { "dependencies": { "@mdx-js/react": "^3.0.0", "@storybook/csf-plugin": "10.4.1", "@storybook/icons": "^2.0.2", "@storybook/react-dom-shim": "10.4.1", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "ts-dedent": "^2.0.0" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.4.1" }, "optionalPeers": ["@types/react"] }, "sha512-IYqUdjoZe4VO2LFZlKL/gwy7DsQSWCq6hX+zc1MBmZo04yycDASk1tte57n9pdlW3ajw9yYMF/+lVBi+xQjyvw=="], + "@storybook/addon-docs": ["@storybook/addon-docs@10.4.6", "", { "dependencies": { "@mdx-js/react": "^3.0.0", "@storybook/csf-plugin": "10.4.6", "@storybook/icons": "^2.0.2", "@storybook/react-dom-shim": "10.4.6", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "ts-dedent": "^2.0.0" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.4.6" }, "optionalPeers": ["@types/react"] }, "sha512-aWAfP5JMiT5a3zBJizwroCRzOCqZwDTJmvsYvwMD3ilIEa/kT1vhf6Xrbk4XIPhDwbh8Hpb/Gfnka1xBYEISWg=="], - "@storybook/addon-links": ["@storybook/addon-links@10.4.1", "", { "dependencies": { "@storybook/global": "^5.0.0" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.4.1" }, "optionalPeers": ["@types/react", "react"] }, "sha512-h/5D23GwMuHA55sB7XDyhByF9psF7UFmaQOn72pjNAarew5eOpue5A+jXk3AKEYokHbvgQaoz+FrvWo9GEfSKQ=="], + "@storybook/addon-links": ["@storybook/addon-links@10.4.6", "", { "dependencies": { "@storybook/global": "^5.0.0" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.4.6" }, "optionalPeers": ["@types/react", "react"] }, "sha512-VGfERTsGRFmfvNP3SKprFWkC6Od5kXzSutT5PSZjQ/O9NnCdHhd/RILxFDN2TzZn9ywDc7t5b4AldKmSYCv3EQ=="], - "@storybook/addon-onboarding": ["@storybook/addon-onboarding@10.4.1", "", { "peerDependencies": { "storybook": "^10.4.1" } }, "sha512-XJ3vaPeXLc8GRrnYKoi0zmAMyT34XTnD6SZNcSV0ceEQrmfZKpLbn6wei1e4oqQRctkRH2QFl/ha7SqqB3yYmQ=="], + "@storybook/addon-onboarding": ["@storybook/addon-onboarding@10.4.6", "", { "peerDependencies": { "storybook": "^10.4.6" } }, "sha512-BzTu5LW5Ygwv0BbmQM0QohGS5Uoa8GjSxPcZFCQ1iQfizUukKnd72UIsPDZBKjVytO0DbZ3YoM1Ww5+KL6ZXEg=="], - "@storybook/addon-vitest": ["@storybook/addon-vitest@10.4.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.2" }, "peerDependencies": { "@vitest/browser": "^3.0.0 || ^4.0.0", "@vitest/browser-playwright": "^4.0.0", "@vitest/runner": "^3.0.0 || ^4.0.0", "storybook": "^10.4.1", "vitest": "^3.0.0 || ^4.0.0" }, "optionalPeers": ["@vitest/browser", "@vitest/browser-playwright", "@vitest/runner", "vitest"] }, "sha512-ymrX9EOou1x3d21iDhjP3j3XfhOAiflhlPZWKcipULBoJCq/aZPbV68EghzovkJNuGRl9ezMYxbbKxwrMmCmGg=="], + "@storybook/addon-vitest": ["@storybook/addon-vitest@10.4.6", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.2" }, "peerDependencies": { "@vitest/browser": "^3.0.0 || ^4.0.0", "@vitest/browser-playwright": "^4.0.0", "@vitest/runner": "^3.0.0 || ^4.0.0", "storybook": "^10.4.6", "vitest": "^3.0.0 || ^4.0.0" }, "optionalPeers": ["@vitest/browser", "@vitest/browser-playwright", "@vitest/runner", "vitest"] }, "sha512-VvskHge0GZy86LG6kcY5Ww34z8rDV8JBxqSdUpcJVsWfIvyX6MfAbqI76LlereSyBIJGZJZsqaLwRXsQoVY+0Q=="], - "@storybook/builder-vite": ["@storybook/builder-vite@10.4.1", "", { "dependencies": { "@storybook/csf-plugin": "10.4.1", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^10.4.1", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-/oyQrXoNOqN8SW5hNnYP+I1uvgFxKxWXj/EP6NXYzc5SQwImofgru+D2+6gDhL0+Q//+Hx05DJoQO2omvUJ8bQ=="], + "@storybook/builder-vite": ["@storybook/builder-vite@10.4.4", "", { "dependencies": { "@storybook/csf-plugin": "10.4.4", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^10.4.4", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-VyuZ4mEvhhVXjJa1qXMWKH8ohnas0rgEuJDf6u4aJ54XeENFebPUEAHde1Qo2PflJ4rUdVdXieOZzKbYwP5RAQ=="], - "@storybook/csf-plugin": ["@storybook/csf-plugin@10.4.1", "", { "dependencies": { "unplugin": "^2.3.5" }, "peerDependencies": { "esbuild": "*", "rollup": "*", "storybook": "^10.4.1", "vite": "*", "webpack": "*" }, "optionalPeers": ["esbuild", "rollup", "vite", "webpack"] }, "sha512-WdPepGBxDGOUDjYd8KxMtcf+us/2PAcnBczl77XtrnxxHNs0jWesxKkiJ9yiuGrge4BPhDeAj6rxjbBoaHxLBA=="], + "@storybook/csf-plugin": ["@storybook/csf-plugin@10.4.6", "", { "dependencies": { "unplugin": "^2.3.5" }, "peerDependencies": { "esbuild": "*", "rollup": "*", "storybook": "^10.4.6", "vite": "*", "webpack": "*" }, "optionalPeers": ["esbuild", "rollup", "vite", "webpack"] }, "sha512-NILLxDqpA/JR/AazGWpsz+4fadJwRU4uhHephGtYpVOWnQA/DkJfKT6zpcJVq8+QA8A2zKMLX3GVKsXIrxjuDA=="], "@storybook/global": ["@storybook/global@5.0.0", "", {}, "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ=="], - "@storybook/icons": ["@storybook/icons@2.0.2", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-KZBCpXsshAIjczYNXR/rlxEtCUX/eAbpFNwKi8bcOomrLA4t/SyPz5RF+lVPO2oZBUE4sAkt43mfJUevQDSEEw=="], + "@storybook/icons": ["@storybook/icons@2.1.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Fxh9vYpX9bQqFeHRiY8h2ApeRGDzRSMLwJwNZ/AIRqnyOKHxRKL+yFe+ctEkVJmuptRE9u1Hrn8ZZNHyfDKKNg=="], - "@storybook/react-dom-shim": ["@storybook/react-dom-shim@10.4.1", "", { "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.4.1" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-6QFqfDNH4DMrt7yHKRfpqRopsVUc/Az+sXIdJ39IetYnHUxL3nW4NVaPc6uy/8Qi8urzUyEXL/nn7cpSIP2aPQ=="], + "@storybook/react-dom-shim": ["@storybook/react-dom-shim@10.4.6", "", { "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.4.6" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-iGNmKzrq9vgl2PDrYAnZKI+yvac3Ym+lJXXuQaqlFRS23zA5MNm4EBX+rAG7WulqchoK6NaZ0KQOs2mAgEpTMg=="], "@stripe/stripe-js": ["@stripe/stripe-js@8.6.1", "", {}, "sha512-UJ05U2062XDgydbUcETH1AoRQLNhigQ2KmDn1BG8sC3xfzu6JKg95Qt6YozdzFpxl1Npii/02m2LEWFt1RYjVA=="], @@ -2852,7 +2840,7 @@ "@tufjs/models": ["@tufjs/models@4.1.0", "", { "dependencies": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^10.1.1" } }, "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww=="], - "@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="], @@ -2890,7 +2878,7 @@ "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="], - "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="], @@ -2926,7 +2914,7 @@ "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], - "@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="], + "@types/mdx": ["@types/mdx@2.0.14", "", {}, "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg=="], "@types/micromatch": ["@types/micromatch@4.0.10", "", { "dependencies": { "@types/braces": "*" } }, "sha512-5jOhFDElqr4DKTrTEbnW8DZ4Hz5LRUEmyrGpCMrD/NphYv3nUnaF08xmSLx1rGGnyEs/kFnhiw6dCgcDqMr5PQ=="], @@ -2954,8 +2942,6 @@ "@types/pacote": ["@types/pacote@11.1.8", "", { "dependencies": { "@types/node": "*", "@types/npm-registry-fetch": "*", "@types/npmlog": "*", "@types/ssri": "*" } }, "sha512-/XLR0VoTh2JEO0jJg1q/e6Rh9bxjBq9vorJuQmtT7rRrXSiWz7e7NsvXVYJQ0i8JxMlBMPPYDTnrRe7MZRFA8Q=="], - "@types/plist": ["@types/plist@3.0.5", "", { "dependencies": { "@types/node": "*", "xmlbuilder": ">=11.0.1" } }, "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA=="], - "@types/promise.allsettled": ["@types/promise.allsettled@1.0.6", "", {}, "sha512-wA0UT0HeT2fGHzIFV9kWpYz5mdoyLxKrTgMdZQM++5h6pYAFH73HXcQhefg24nD1yivUFEn5KU+EF4b+CXJ4Wg=="], "@types/prop-types": ["@types/prop-types@15.7.15", "", {}, "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw=="], @@ -2996,8 +2982,6 @@ "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], - "@types/verror": ["@types/verror@1.10.11", "", {}, "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg=="], - "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="], "@types/which": ["@types/which@3.0.4", "", {}, "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w=="], @@ -3028,9 +3012,9 @@ "@typescript/vfs": ["@typescript/vfs@1.6.4", "", { "dependencies": { "debug": "^4.4.3" }, "peerDependencies": { "typescript": "*" } }, "sha512-PJFXFS4ZJKiJ9Qiuix6Dz/OwEIqHD7Dme1UwZhTK11vR+5dqW2ACbdndWQexBzCx+CPuMe5WBYQWCsFyGlQLlQ=="], - "@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.5", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-yURCknZhvywvQItHMMmFSo+fq5arCUIyz/CVk7jD89MSai7dkaX8ufjCWp3NttLojoTVbcE72ri+be/TnEbMHw=="], + "@typespec/ts-http-runtime": ["@typespec/ts-http-runtime@0.3.6", "", { "dependencies": { "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "tslib": "^2.6.2" } }, "sha512-jIXhD0eWQ1JA6ln/5Dltyx22UxWNrw0hZmhy2rlv6m6KgF7kplHx3g0fzi09lNmTJQRR91OlemYp3xFnvDK9og=="], - "@ungap/structured-clone": ["@ungap/structured-clone@1.3.1", "", {}, "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ=="], + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.2", "", {}, "sha512-5jsZFwgR5rTdKwidH9Qmat75RKwqfpKlWWB1frDkljN127mwqBu8K0PYo7/hFpF03IEJpfVPpCQDY/eDx3iHvA=="], "@upstash/redis": ["@upstash/redis@1.38.0", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-wu+dZBptlLy0+MCUEoHmzrY/TnmgDey3+c7EbIGwrLqAvkP8yi5MWZHYGIFtAygmL4Bkz2TdFu+eU0vFPncIcg=="], @@ -3040,21 +3024,19 @@ "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="], - "@vitest/coverage-v8": ["@vitest/coverage-v8@4.1.8", "", { "dependencies": { "@bcoe/v8-coverage": "^1.0.2", "@vitest/utils": "4.1.8", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", "magicast": "^0.5.2", "obug": "^2.1.1", "std-env": "^4.0.0-rc.1", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "@vitest/browser": "4.1.8", "vitest": "4.1.8" }, "optionalPeers": ["@vitest/browser"] }, "sha512-lt3kovsyHwYe00wq4D1ti0Z974fWj4NLp6siqiyEufUpyFwK9Yhi7rBhac9JL5aA0zoMrJqc4vYPZRUnI7l7nw=="], - "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="], - "@vitest/mocker": ["@vitest/mocker@4.1.7", "", { "dependencies": { "@vitest/spy": "4.1.7", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA=="], + "@vitest/mocker": ["@vitest/mocker@4.1.9", "", { "dependencies": { "@vitest/spy": "4.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw=="], - "@vitest/pretty-format": ["@vitest/pretty-format@4.1.7", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw=="], + "@vitest/pretty-format": ["@vitest/pretty-format@4.1.9", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-s0iufns3iIFitdgm+YR7g1whCAaGtXz459VS9/PqyKDEEFgYIhsHOQmXgIgDuYCt7DeQmiZT0Qe2OA2p4ZPu5A=="], - "@vitest/runner": ["@vitest/runner@4.1.7", "", { "dependencies": { "@vitest/utils": "4.1.7", "pathe": "^2.0.3" } }, "sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw=="], + "@vitest/runner": ["@vitest/runner@4.1.9", "", { "dependencies": { "@vitest/utils": "4.1.9", "pathe": "^2.0.3" } }, "sha512-KXLMDtc7oe70+3mJfGrPUWPesswH+3sTxAMAMl8DG7I8IUQT4XW718dY5ID3vPUcmlu27CcKfY4P3h3I29SLJg=="], - "@vitest/snapshot": ["@vitest/snapshot@4.1.7", "", { "dependencies": { "@vitest/pretty-format": "4.1.7", "@vitest/utils": "4.1.7", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw=="], + "@vitest/snapshot": ["@vitest/snapshot@4.1.9", "", { "dependencies": { "@vitest/pretty-format": "4.1.9", "@vitest/utils": "4.1.9", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-Jc7RKGNBo8Z28WYIm0Niej4xdSPByRf6mU58VpHQkd6Zh05rlnA+twjbK5HyeIGHxrzsc3mJgS43uM0CZKzaIA=="], "@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="], - "@vitest/utils": ["@vitest/utils@4.1.7", "", { "dependencies": { "@vitest/pretty-format": "4.1.7", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw=="], + "@vitest/utils": ["@vitest/utils@4.1.9", "", { "dependencies": { "@vitest/pretty-format": "4.1.9", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-A51o8ymO5PpqlWNnBP9ZHPXDIpuMtTLlGSjN7la4US+LJzoUMyhwjA5QXlm39JexgwHKW4Xjs8Z2d3dLCXOeuA=="], "@volar/kit": ["@volar/kit@2.4.28", "", { "dependencies": { "@volar/language-service": "2.4.28", "@volar/typescript": "2.4.28", "typesafe-path": "^0.2.2", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { "typescript": "*" } }, "sha512-cKX4vK9dtZvDRaAzeoUdaAJEew6IdxHNCRrdp5Kvcl6zZOqb6jTOfk3kXkIkG3T7oTFXguEMt5+9ptyqYR84Pg=="], @@ -3108,7 +3090,7 @@ "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], - "ajv-keywords": ["ajv-keywords@3.5.2", "", { "peerDependencies": { "ajv": "^6.9.1" } }, "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ=="], + "ajv-i18n": ["ajv-i18n@4.2.0", "", { "peerDependencies": { "ajv": "^8.0.0-beta.0" } }, "sha512-v/ei2UkCEeuKNXh8RToiFsUclmU+G57LO1Oo22OagNMENIw+Yb8eMwvHu7Vn9fmkjJyv6XclhJ8TbuigSglPkg=="], "ansi-align": ["ansi-align@3.0.1", "", { "dependencies": { "string-width": "^4.1.0" } }, "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w=="], @@ -3124,7 +3106,7 @@ "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], - "app-builder-bin": ["app-builder-bin@5.0.0-alpha.12", "", {}, "sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w=="], + "anynum": ["anynum@1.0.1", "", {}, "sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A=="], "app-builder-lib": ["app-builder-lib@26.15.2", "", { "dependencies": { "@electron/asar": "3.4.1", "@electron/fuses": "^1.8.0", "@electron/get": "^3.0.0", "@electron/notarize": "2.5.0", "@electron/osx-sign": "1.3.3", "@electron/rebuild": "^4.0.4", "@electron/universal": "2.0.3", "@malept/flatpak-bundler": "^0.4.0", "@noble/hashes": "^2.2.0", "@peculiar/webcrypto": "^1.7.1", "@types/fs-extra": "9.0.13", "ajv": "^8.18.0", "asn1js": "^3.0.10", "async-exit-hook": "^2.0.1", "builder-util": "26.15.0", "builder-util-runtime": "9.7.0", "chromium-pickle-js": "^0.2.0", "ci-info": "4.3.1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", "electron-publish": "26.15.1", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "isbinaryfile": "^5.0.0", "jiti": "^2.4.2", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", "minimatch": "^10.2.5", "pkijs": "^3.4.0", "plist": "3.1.0", "proper-lockfile": "^4.1.2", "resedit": "^1.7.0", "semver": "~7.7.3", "tar": "^7.5.7", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0", "unzipper": "^0.12.3", "which": "^5.0.0" }, "peerDependencies": { "dmg-builder": "26.15.2", "electron-builder-squirrel-windows": "26.15.2" } }, "sha512-3mYfKOjr/ZY7gFESOcq8kylBMgGPpmlQYnpBVit4p6zIg0t/8bkWBILdMMtnjFyN2jllyBf225T8dLlz3D6oBQ=="], @@ -3156,16 +3138,10 @@ "asn1js": ["asn1js@3.0.10", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.5", "tslib": "^2.8.1" } }, "sha512-S2s3aOytiKdFRdulw2qPE51MzjzVOisppcVv7jVFR+Kw0kxwvFrDcYA0h7Ndqbmj0HkMIXYWaoj7fli8kgx1eg=="], - "assert-plus": ["assert-plus@1.0.0", "", {}, "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw=="], - "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], - "ast-v8-to-istanbul": ["ast-v8-to-istanbul@1.0.3", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.31", "estree-walker": "^3.0.3", "js-tokens": "^10.0.0" } }, "sha512-jCMQ6ZylLPudp0CDfBmQBZUsrh1/8psbmu9ibeVWKuHWD0YrH9YABwlKu5kVEFoT0GCQQW9Z/SxfuEbbkGQCRg=="], - - "astral-regex": ["astral-regex@2.0.0", "", {}, "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ=="], - "astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="], "astro": ["astro@5.7.13", "", { "dependencies": { "@astrojs/compiler": "^2.11.0", "@astrojs/internal-helpers": "0.6.1", "@astrojs/markdown-remark": "6.3.1", "@astrojs/telemetry": "3.2.1", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.1.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.2.1", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.6.0", "unifont": "~0.5.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.3.4", "vitefu": "^1.0.6", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", "zod": "^3.24.2", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-cRGq2llKOhV3XMcYwQpfBIUcssN6HEK5CRbcMxAfd9OcFhvWE7KUy50zLioAZVVl3AqgUTJoNTlmZfD2eG0G1w=="], @@ -3186,7 +3162,7 @@ "atomically": ["atomically@2.1.1", "", { "dependencies": { "stubborn-fs": "^2.0.0", "when-exit": "^2.1.4" } }, "sha512-P4w9o2dqARji6P7MHprklbfiArZAWvo07yW7qs3pdljb3BWr12FIB7W+p0zJiuiVsUpRO0iZn1kFFcpPegg0tQ=="], - "autoprefixer": ["autoprefixer@10.5.0", "", { "dependencies": { "browserslist": "^4.28.2", "caniuse-lite": "^1.0.30001787", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong=="], + "autoprefixer": ["autoprefixer@10.5.2", "", { "dependencies": { "browserslist": "^4.28.4", "caniuse-lite": "^1.0.30001799", "fraction.js": "^5.3.4", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-rD5t5DwOjJdmSORcTq64j8MawTC+tbQ+HHqjR4NDumamy/ambn1UJrlKL+KdwujWxMkFjPM3pPHOEA9tl4767Q=="], "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], @@ -3198,9 +3174,9 @@ "aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="], - "axe-core": ["axe-core@4.11.4", "", {}, "sha512-KunSNx+TVpkAw/6ULfhnx+HWRecjqZGTOyquAoWHYLRSdK1tB5Ihce1ZW+UY3fj33bYAFWPu7W/GRSmmrCGuxA=="], + "axe-core": ["axe-core@4.12.1", "", {}, "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA=="], - "axios": ["axios@1.16.1", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A=="], + "axios": ["axios@1.18.1", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], @@ -3218,23 +3194,23 @@ "balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - "bare-events": ["bare-events@2.8.3", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-HdUm8EMQBLaJvGUdidNNbqpA1kYkwNcb+MYxkxCLAPJGQzlv9J0C24h8V65Z4c5GLd/JEALDvpFCQgpLJqc0zw=="], + "bare-events": ["bare-events@2.9.1", "", { "peerDependencies": { "bare-abort-controller": "*" }, "optionalPeers": ["bare-abort-controller"] }, "sha512-Z0oHEHAFDZkffN8Qc39zNZjQlMDkPJRyyyZieU1VH7u8c5S+qHZ2S8ixdKIAxEjfHO7FJxXmJWgteOghVanIsg=="], - "bare-fs": ["bare-fs@4.7.1", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-WDRsyVN52eAx/lBamKD6uyw8H4228h/x0sGGGegOamM2cd7Pag88GfMQalobXI+HaEUxpCkbKQUDOQqt9wawRw=="], + "bare-fs": ["bare-fs@4.7.3", "", { "dependencies": { "bare-events": "^2.5.4", "bare-path": "^3.0.0", "bare-stream": "^2.6.4", "bare-url": "^2.2.2", "fast-fifo": "^1.3.2" }, "peerDependencies": { "bare-buffer": "*" }, "optionalPeers": ["bare-buffer"] }, "sha512-xRgplks8SvcKkdlv2M6Z2LZmRsmqd+x0nXXGXeMEjwdibj1HSDrlnqBRLeYdMvsgCox7Bq0e+DHwfczOfsn6IA=="], - "bare-os": ["bare-os@3.9.1", "", {}, "sha512-6M5XjcnsygQNPMCMPXSK379xrJFiZ/AEMNBmFEmQW8d/789VQATvriyi5r0HYTL9TkQ26rn3kgdTG3aisbrXkQ=="], + "bare-os": ["bare-os@3.9.3", "", {}, "sha512-fF4Q7QsyKVF5Rj0qvI8BgUNjqzC2JvQlpTaPLjVJVxYVUX5Zr9un+y3w1HmA4nNKdFmRBT8z/WmrjvXzXVerKQ=="], - "bare-path": ["bare-path@3.0.0", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw=="], + "bare-path": ["bare-path@3.0.1", "", { "dependencies": { "bare-os": "^3.0.1" } }, "sha512-ghj2DSK/2e99a1anTVPCV4m4YIYtrbXhfM7V3D7XZLOTsybnYyaJloymGqssQc8l/or0UoDyRtNQkmkEF/ysgQ=="], - "bare-stream": ["bare-stream@2.13.1", "", { "dependencies": { "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-abort-controller", "bare-buffer", "bare-events"] }, "sha512-Vp0cnjYyrEC4whYTymQ+YZi6pBpfiICZO3cfRG8sy67ZNWe951urv1x4eW1BKNngw3U+3fPYb5JQvHbCtxH7Ow=="], + "bare-stream": ["bare-stream@2.13.3", "", { "dependencies": { "b4a": "^1.8.1", "streamx": "^2.25.0", "teex": "^1.0.1" }, "peerDependencies": { "bare-abort-controller": "*", "bare-buffer": "*", "bare-events": "*" }, "optionalPeers": ["bare-abort-controller", "bare-buffer", "bare-events"] }, "sha512-Kc+brLqvEqGkjyfiwJmImAOqLZL7OsoLKuavx+hJjgVV3nLTOjloJyPMFxjUPerGGHrNH0fLU06jjykMLWrERQ=="], - "bare-url": ["bare-url@2.4.3", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-Kccpc7ACfXaxfeInfqKcZtW4pT5YBn1mesc4sCsun6sRwtbJ4h+sNOaksUpYEJUKfN65YWC6Bw2OJEFiKxq8nQ=="], + "bare-url": ["bare-url@2.4.5", "", { "dependencies": { "bare-path": "^3.0.0" } }, "sha512-K+y9xF1tN+CdPu4qWwr0QiK1Al07eFPGYK5M2pDXcmHdMdgC/tT/bpmMe1hrmRHaidKLkXrC+cRNYf3XVDUhSQ=="], "base-64": ["base-64@1.0.0", "", {}, "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - "baseline-browser-mapping": ["baseline-browser-mapping@2.10.33", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.41", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-WwS7MHhqGHHlaVsqRZnhvCEMS0owDX+SxRlve7JkuH7My1Ara3ZriTmCQupPfYjxMZ8I/tgxtJYr2t7taHaH4A=="], "bcp-47": ["bcp-47@2.1.0", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w=="], @@ -3256,7 +3232,7 @@ "bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], - "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], + "body-parser": ["body-parser@2.3.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^2.0.0", "debug": "^4.4.3", "http-errors": "^2.0.1", "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", "qs": "^6.15.2", "raw-body": "^3.0.2", "type-is": "^2.1.0" } }, "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw=="], "bonjour-service": ["bonjour-service@1.3.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "multicast-dns": "^7.2.5" } }, "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA=="], @@ -3270,13 +3246,13 @@ "boxen": ["boxen@8.0.1", "", { "dependencies": { "ansi-align": "^3.0.1", "camelcase": "^8.0.0", "chalk": "^5.3.0", "cli-boxes": "^3.0.0", "string-width": "^7.2.0", "type-fest": "^4.21.0", "widest-line": "^5.0.0", "wrap-ansi": "^9.0.0" } }, "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw=="], - "brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], + "brace-expansion": ["brace-expansion@5.0.7", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], "brotli": ["brotli@1.3.3", "", { "dependencies": { "base64-js": "^1.1.2" } }, "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg=="], - "browserslist": ["browserslist@4.28.2", "", { "dependencies": { "baseline-browser-mapping": "^2.10.12", "caniuse-lite": "^1.0.30001782", "electron-to-chromium": "^1.5.328", "node-releases": "^2.0.36", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg=="], + "browserslist": ["browserslist@4.28.4", "", { "dependencies": { "baseline-browser-mapping": "^2.10.38", "caniuse-lite": "^1.0.30001799", "electron-to-chromium": "^1.5.376", "node-releases": "^2.0.48", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw=="], "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], @@ -3286,13 +3262,15 @@ "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + "buffer-image-size": ["buffer-image-size@0.6.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-nEh+kZOPY1w+gcCMobZ6ETUp9WfibndnosbpwB1iJk/8Gt5ZF2bhS6+B6bPYz424KtwsR6Rflc3tCz1/ghX2dQ=="], + "buffers": ["buffers@0.1.1", "", {}, "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ=="], "builder-util": ["builder-util@26.15.0", "", { "dependencies": { "@types/debug": "^4.1.6", "builder-util-runtime": "9.7.0", "chalk": "^4.1.2", "cross-spawn": "^7.0.6", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "js-yaml": "^4.1.0", "sanitize-filename": "^1.6.3", "source-map-support": "^0.5.19", "stat-mode": "^1.0.0", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0" } }, "sha512-dUx+HxVbiNsNQ4mGe1PyoC/tBmsHwBNDLdBuqWCj+rhHFE9lHgrXiGYKAM1uNlznhAaUSyMlms84VeSSr3gOBA=="], "builder-util-runtime": ["builder-util-runtime@9.7.0", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-g/kR520giAFYkSXTzcmF3kqQq7wi8F6N6SzeDgZrqTBN+VHdmgWOyTdD1yD7AATDId/yXLvuP34CxW46/BwCdw=="], - "bun-ffi-structs": ["bun-ffi-structs@0.2.2", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-N/ZWtyN0piZlrXQT7TO0V+q952orYqkfhXRXM1Hcbb+R3QSiBH4vLnib187Mrs1H7pWIYECAmPeapGYDOMCl+w=="], + "bun-ffi-structs": ["bun-ffi-structs@0.2.4", "", { "peerDependencies": { "typescript": "^5" } }, "sha512-AJzsqoVFs1KBbJbWHIYrVZLDC3NhTqqh25awRXqzoLzmBAKr5oqk6+CwuYHAekKx+VBCYVohBoKuRq40dV+TYg=="], "bun-pty": ["bun-pty@0.4.8", "", {}, "sha512-rO70Mrbr13+jxHHHu2YBkk2pNqrJE5cJn29WE++PUr+GFA0hq/VgtQPZANJ8dJo6d7XImvBk37Innt8GM7O28w=="], @@ -3326,7 +3304,7 @@ "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], - "caniuse-lite": ["caniuse-lite@1.0.30001793", "", {}, "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA=="], + "caniuse-lite": ["caniuse-lite@1.0.30001800", "", {}, "sha512-MMHtuAz9Ys840zAY5F4k6fV5GaivZ9sPk+nz0mY+GYVzRBnYkN0mpqkSR92oWRQ19yQWo4HvBV/FnC16AJX8MA=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], @@ -3440,8 +3418,6 @@ "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="], - "crc": ["crc@3.8.0", "", { "dependencies": { "buffer": "^5.1.0" } }, "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ=="], - "crc-32": ["crc-32@1.2.2", "", { "bin": { "crc32": "bin/crc32.njs" } }, "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="], "crc32-stream": ["crc32-stream@6.0.0", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^4.0.0" } }, "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g=="], @@ -3452,7 +3428,7 @@ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - "crossws": ["crossws@0.4.5", "", { "peerDependencies": { "srvx": ">=0.11.5" }, "optionalPeers": ["srvx"] }, "sha512-wUR89x/Rw7/8t+vn0CmGDYM9TD6VtARGb0LD5jq2wjtMy1vCP4M+sm6N6TigWeTYvnA8MoW29NqqXD0ep0rfBA=="], + "crossws": ["crossws@0.4.9", "", { "peerDependencies": { "srvx": ">=0.11.5" }, "optionalPeers": ["srvx"] }, "sha512-iWx+1OMSG2aOHpjyf9AESOzkwsVdS49cXM9dVrI2PDhxU5l2RIWE/KG56gk4BbAnsMoycvniJ9OnOxO9LRzHVA=="], "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], @@ -3566,8 +3542,6 @@ "dmg-builder": ["dmg-builder@26.15.2", "", { "dependencies": { "app-builder-lib": "26.15.2", "builder-util": "26.15.0", "fs-extra": "^10.1.0", "js-yaml": "^4.1.0" } }, "sha512-fMkjRqKyPtsz4Kzu/qGP0BGjqzMCIgp+/7kw/u6YH6lvn/8hvL3c0TXhoFayBoYdpPCnEinnCHztd4bW7/jetA=="], - "dmg-license": ["dmg-license@1.0.11", "", { "dependencies": { "@types/plist": "^3.0.1", "@types/verror": "^1.10.3", "ajv": "^6.10.0", "crc": "^3.8.0", "iconv-corefoundation": "^1.1.7", "plist": "^3.0.4", "smart-buffer": "^4.0.2", "verror": "^1.10.0" }, "os": "darwin", "bin": { "dmg-license": "bin/dmg-license.js" } }, "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q=="], - "dns-packet": ["dns-packet@5.6.1", "", { "dependencies": { "@leichtgewicht/ip-codec": "^2.0.1" } }, "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw=="], "dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="], @@ -3616,7 +3590,7 @@ "electron-builder": ["electron-builder@26.15.2", "", { "dependencies": { "app-builder-lib": "26.15.2", "builder-util": "26.15.0", "builder-util-runtime": "9.7.0", "chalk": "^4.1.2", "ci-info": "^4.2.0", "dmg-builder": "26.15.2", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" }, "bin": { "electron-builder": "./cli.js", "install-app-deps": "./install-app-deps.js" } }, "sha512-veKM9+dCljaC5A74Pwc0ZWQ9arOHREXWh9hUIf8NGg49ch7x+IB4QhbMzIrV5ONZIXM2OEkaxW11cAPjPtoi4A=="], - "electron-builder-squirrel-windows": ["electron-builder-squirrel-windows@26.8.1", "", { "dependencies": { "app-builder-lib": "26.8.1", "builder-util": "26.8.1", "electron-winstaller": "5.4.0" } }, "sha512-o288fIdgPLHA76eDrFADHPoo7VyGkDCYbLV1GzndaMSAVBoZrGvM9m2IehdcVMzdAZJ2eV9bgyissQXHv5tGzA=="], + "electron-builder-squirrel-windows": ["electron-builder-squirrel-windows@26.15.2", "", { "dependencies": { "app-builder-lib": "26.15.2", "builder-util": "26.15.0", "electron-winstaller": "5.4.0" } }, "sha512-PNl+SSRoma9mXhxycNGxutZPgvmK19v41mn8F9oecpAU2QNAldpB4HfMuA1LwFC2j8aRzzV5M9HKlKe6dfpvNw=="], "electron-context-menu": ["electron-context-menu@4.1.2", "", { "dependencies": { "cli-truncate": "^4.0.0", "electron-dl": "^4.0.0", "electron-is-dev": "^3.0.1" } }, "sha512-9xYTUV0oRqKL50N9W71IrXNdVRB0LuBp3R1zkUdUc2wfIa2/QZwYYj5RLuO7Tn7ZSLVIaO3X6u+EIBK+cBvzrQ=="], @@ -3630,7 +3604,7 @@ "electron-store": ["electron-store@11.0.2", "", { "dependencies": { "conf": "^15.0.2", "type-fest": "^5.0.1" } }, "sha512-4VkNRdN+BImL2KcCi41WvAYbh6zLX5AUTi4so68yPqiItjbgTjqpEnGAqasgnG+lB6GuAyUltKwVopp6Uv+gwQ=="], - "electron-to-chromium": ["electron-to-chromium@1.5.364", "", {}, "sha512-G/dYE3+AYhyHwzTwg8UbnXf7zqMERYh7l2jJ3QujhFsH8agSYwtnGAR2aZ7f0AakIKJXd5En/Hre4igIUrdlYw=="], + "electron-to-chromium": ["electron-to-chromium@1.5.385", "", {}, "sha512-78sa/M08MNAYHQfjoWMvOlKQqZ0ElhSm/L5HNUc96VZ3b+KvDVnngFm8sYQy0XrhTRgAhggHr5abA7yTvRdo4Q=="], "electron-updater": ["electron-updater@6.8.9", "", { "dependencies": { "builder-util-runtime": "9.7.0", "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", "lodash.isequal": "^4.5.0", "semver": "~7.7.3", "tiny-typed-emitter": "^2.1.0" } }, "sha512-ZhVxM9iGONUpZGI1FxdMRgJjUFXi7AYGVa5PwKlO1tV1/4zDxQmfKpXOHVztKrd6L9rLcFjERvi1Mf2vxyTkig=="], @@ -3648,15 +3622,13 @@ "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], - "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="], - "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], - "engine.io-client": ["engine.io-client@6.6.5", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1", "engine.io-parser": "~5.2.1", "ws": "~8.20.1", "xmlhttprequest-ssl": "~2.1.1" } }, "sha512-QCwxUDULPlXv8F6tqMMKx5dNkTe6OaBYRMPYeXKBlyOoKvAmE0ac6pW7fFhSscJ/5SI7666/U/B+MElbsrJlIg=="], + "engine.io-client": ["engine.io-client@6.6.6", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1", "engine.io-parser": "~5.2.1", "ws": "~8.21.0", "xmlhttprequest-ssl": "~2.1.1" } }, "sha512-iY6QdftLQ9pyiPoX082bpf/u1UewnOaJrtJIF9T0++QB34lZrj0uP+Q/bj8AlUsAxqhnkTV2BS8SBZSxOmoV5Q=="], "engine.io-parser": ["engine.io-parser@5.2.3", "", {}, "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q=="], - "enhanced-resolve": ["enhanced-resolve@5.22.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww=="], + "enhanced-resolve": ["enhanced-resolve@5.24.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw=="], "entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], @@ -3670,6 +3642,8 @@ "es-abstract": ["es-abstract@1.24.2", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="], + "es-abstract-get": ["es-abstract-get@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "es-object-atoms": "^1.1.2", "is-callable": "^1.2.7", "object-inspect": "^1.13.4" } }, "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg=="], + "es-array-method-boxes-properly": ["es-array-method-boxes-properly@1.0.0", "", {}, "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA=="], "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], @@ -3684,7 +3658,7 @@ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], - "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="], + "es-to-primitive": ["es-to-primitive@1.3.4", "", { "dependencies": { "es-abstract-get": "^1.0.0", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "is-callable": "^1.2.7", "is-date-object": "^1.1.0", "is-symbol": "^1.1.1" } }, "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw=="], "es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="], @@ -3738,7 +3712,7 @@ "exit-hook": ["exit-hook@2.2.1", "", {}, "sha512-eNTPlAD67BmP31LDINZ3U7HSF8l57TxOY2PmBJ1shpCvpnxBF93mWCE8YHBnXs8qiUZJc9WDcWIeC3a2HIAMfw=="], - "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="], + "expect-type": ["expect-type@1.4.0", "", {}, "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA=="], "exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="], @@ -3748,7 +3722,7 @@ "expressive-code": ["expressive-code@0.41.7", "", { "dependencies": { "@expressive-code/core": "^0.41.7", "@expressive-code/plugin-frames": "^0.41.7", "@expressive-code/plugin-shiki": "^0.41.7", "@expressive-code/plugin-text-markers": "^0.41.7" } }, "sha512-2wZjC8OQ3TaVEMcBtYY4Va3lo6J+Ai9jf3d4dbhURMJcU4Pbqe6EcHe424MIZI0VHUA1bR6xdpoHYi3yxokWqA=="], - "exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="], + "exsolve": ["exsolve@1.1.0", "", {}, "sha512-D+42+T12DdIlJM3uepa55qGiL3sYdLBOxIl2ifQCzCHz4c7eiolaHsi3BIqEr7JxBzxv2pYZQX9kw16ziMcEmw=="], "ext-list": ["ext-list@2.2.2", "", { "dependencies": { "mime-db": "^1.28.0" } }, "sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA=="], @@ -3760,8 +3734,6 @@ "extract-zip": ["extract-zip@2.0.1", "", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": { "extract-zip": "cli.js" } }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="], - "extsprintf": ["extsprintf@1.4.1", "", {}, "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA=="], - "fast-check": ["fast-check@4.8.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg=="], "fast-decode-uri-component": ["fast-decode-uri-component@1.0.1", "", {}, "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg=="], @@ -3772,19 +3744,17 @@ "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], - "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], - "fast-json-stringify": ["fast-json-stringify@6.4.0", "", { "dependencies": { "@fastify/merge-json-schemas": "^0.2.0", "ajv": "^8.12.0", "ajv-formats": "^3.0.1", "fast-uri": "^3.0.0", "json-schema-ref-resolver": "^3.0.0", "rfdc": "^1.2.0" } }, "sha512-ibRCQ0GZKJIQ+P3Et1h0LhPgp3PMTYk0MH8O+kW3lNYsvmaQww5Nn3f1jf73Q0jR1Yz3a1CDP4/NZD3vOajWJQ=="], "fast-querystring": ["fast-querystring@1.1.2", "", { "dependencies": { "fast-decode-uri-component": "^1.0.1" } }, "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg=="], - "fast-uri": ["fast-uri@3.1.2", "", {}, "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ=="], + "fast-uri": ["fast-uri@3.1.3", "", {}, "sha512-i70LwGWUduXqzicKXWshooq+sWL1K3WUU5rKZNG/0i3a1OSoX3HqhH5WbWwTmqWfor4urUakGPiRQcleRZTwOg=="], - "fast-xml-builder": ["fast-xml-builder@1.2.0", "", { "dependencies": { "path-expression-matcher": "^1.5.0", "xml-naming": "^0.1.0" } }, "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q=="], + "fast-xml-builder": ["fast-xml-builder@1.2.1", "", { "dependencies": { "path-expression-matcher": "^1.5.0", "xml-naming": "^0.1.0" } }, "sha512-tPb5TTWfgfVx5BNSi2xV0eLr89POeXXn0dXIsCJ9m1narrWxeIyx6je9d7Rce/3NyXLbvuQmLkxq+RuxMWejvw=="], "fast-xml-parser": ["fast-xml-parser@4.4.1", "", { "dependencies": { "strnum": "^1.0.5" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw=="], - "fastify": ["fastify@5.8.5", "", { "dependencies": { "@fastify/ajv-compiler": "^4.0.5", "@fastify/error": "^4.0.0", "@fastify/fast-json-stringify-compiler": "^5.0.0", "@fastify/proxy-addr": "^5.0.0", "abstract-logging": "^2.0.1", "avvio": "^9.0.0", "fast-json-stringify": "^6.0.0", "find-my-way": "^9.0.0", "light-my-request": "^6.0.0", "pino": "^9.14.0 || ^10.1.0", "process-warning": "^5.0.0", "rfdc": "^1.3.1", "secure-json-parse": "^4.0.0", "semver": "^7.6.0", "toad-cache": "^3.7.0" } }, "sha512-Yqptv59pQzPgQUSIm87hMqHJmdkb1+GPxdE6vW6FRyVE9G86mt7rOghitiU4JHRaTyDUk9pfeKmDeu70lAwM4Q=="], + "fastify": ["fastify@5.9.0", "", { "dependencies": { "@fastify/ajv-compiler": "^4.0.5", "@fastify/error": "^4.0.0", "@fastify/fast-json-stringify-compiler": "^5.0.0", "@fastify/proxy-addr": "^5.0.0", "abstract-logging": "^2.0.1", "avvio": "^9.0.0", "fast-json-stringify": "^6.0.0", "find-my-way": "^9.6.0", "light-my-request": "^6.0.0", "pino": "^9.14.0 || ^10.1.0", "process-warning": "^5.0.0", "rfdc": "^1.3.1", "secure-json-parse": "^4.0.0", "semver": "^7.6.0", "toad-cache": "^3.7.0" } }, "sha512-VMS5lE0zj+MZlJpQa3Qv5iGjfun0H2N7VRgoBwpcTNQ2bdIQpv7fDpb+HGteGbicBsGkzGS+X+hdx9mmrfWuHQ=="], "fastify-plugin": ["fastify-plugin@5.1.0", "", {}, "sha512-FAIDA8eovSt5qcDgcBvDuX/v0Cjz0ohGhENZ/wpc3y+oZCY2afZ9Baqql3g/lC+OHRnciQol4ww7tuthOb9idw=="], @@ -3824,7 +3794,7 @@ "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], + "form-data": ["form-data@4.0.6", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.4", "mime-types": "^2.1.35" } }, "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ=="], "form-data-encoder": ["form-data-encoder@1.7.2", "", {}, "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="], @@ -3850,15 +3820,15 @@ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], - "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="], + "function.prototype.name": ["function.prototype.name@1.2.0", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2", "hasown": "^2.0.4", "is-callable": "^1.2.7", "is-document.all": "^1.0.0" } }, "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew=="], "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], "fuzzysort": ["fuzzysort@3.1.0", "", {}, "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ=="], - "gaxios": ["gaxios@7.1.4", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-bTIgTsM2bWn3XklZISBTQX7ZSddGW+IO3bMdGaemHZ3tbqExMENHLx6kKZ/KlejgrMtj8q7wBItt51yegqalrA=="], + "gaxios": ["gaxios@7.1.5", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-5FZy72Rh8LhtjmvDrKkI+lVhrsQrVKVsItxMoDm5mNQE+xR0WVIIs+jzPSJgBvKVsLi24fZhXJIsNI0bihDzFg=="], - "gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="], + "gcp-metadata": ["gcp-metadata@8.1.3", "", { "dependencies": { "gaxios": "7.1.3", "google-logging-utils": "1.1.3", "json-bigint": "^1.0.0" } }, "sha512-ziTrzUhhpL9Zk5k0HHzgP/KIpWDJT0VMBC/ynt/QIBvTW+UUcSivQRl6VlwTf/EilDxtSWklHoRsKy1c4k+59w=="], "generate-function": ["generate-function@2.3.1", "", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="], @@ -3906,7 +3876,7 @@ "google-auth-library": ["google-auth-library@10.5.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.0.0", "gcp-metadata": "^8.0.0", "google-logging-utils": "^1.0.0", "gtoken": "^8.0.0", "jws": "^4.0.0" } }, "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w=="], - "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], + "google-logging-utils": ["google-logging-utils@1.1.4", "", {}, "sha512-LXxE6ND+JHhDPYtPFt3oeWrjxFPrnRZCZ4At6lpbi1ZDSAN7bmGET9s53vvARbxT93p+xpeDUbc/nCR4C+7vcw=="], "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], @@ -3914,7 +3884,7 @@ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], - "graphql": ["graphql@16.14.0", "", {}, "sha512-BBvQ/406p+4CZbTpCbVPSxfzrZrbnuWSP1ELYgyS6B+hNeKzgrdB4JczCa5VZUBQrDa9hUngm0KnexY6pJRN5Q=="], + "graphql": ["graphql@16.14.2", "", {}, "sha512-Chq1s4CY7jmh8gO2qvLIJyfCDIN+EHLFW/9iShnp1z8FjBQMoodWP1kDC36VAMXXIvAjj4ARa7ntfAV2BrjsbA=="], "graphql-request": ["graphql-request@6.1.0", "", { "dependencies": { "@graphql-typed-document-node/core": "^3.2.0", "cross-fetch": "^3.1.5" }, "peerDependencies": { "graphql": "14 - 16" } }, "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw=="], @@ -3924,7 +3894,7 @@ "h3": ["h3@2.0.1-rc.4", "", { "dependencies": { "rou3": "^0.7.8", "srvx": "^0.9.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-vZq8pEUp6THsXKXrUXX44eOqfChic2wVQ1GlSzQCBr7DeFBkfIZAo2WyNND4GSv54TAa0E4LYIK73WSPdgKUgw=="], - "happy-dom": ["happy-dom@20.9.0", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.18.3" } }, "sha512-GZZ9mKe8r646NUAf/zemnGbjYh4Bt8/MqASJY+pSm5ZDtc3YQox+4gsLI7yi1hba6o+eCsGxpHn5+iEVn31/FQ=="], + "happy-dom": ["happy-dom@20.10.6", "", { "dependencies": { "@types/node": ">=20.0.0", "@types/whatwg-mimetype": "^3.0.2", "@types/ws": "^8.18.1", "buffer-image-size": "^0.6.4", "entities": "^7.0.1", "whatwg-mimetype": "^3.0.0", "ws": "^8.21.0" } }, "sha512-6QD0ilzDDt93tX44y8tbmZdAcdTRYDhUP+Asgi6pC8Pp5IA3cvaZGyoVN/EGtlq9ziT65iPuBBn3ASLr6hCgVw=="], "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], @@ -4030,8 +4000,6 @@ "i18next": ["i18next@23.16.8", "", { "dependencies": { "@babel/runtime": "^7.23.2" } }, "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg=="], - "iconv-corefoundation": ["iconv-corefoundation@1.1.7", "", { "dependencies": { "cli-truncate": "^2.1.0", "node-addon-api": "^1.6.3" }, "os": "darwin" }, "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ=="], - "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], @@ -4060,7 +4028,7 @@ "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="], - "ioredis": ["ioredis@5.11.0", "", { "dependencies": { "@ioredis/commands": "1.10.0", "cluster-key-slot": "1.1.1", "debug": "4.4.3", "denque": "2.1.0", "redis-errors": "1.2.0", "redis-parser": "3.0.0", "standard-as-callback": "2.1.0" } }, "sha512-EZBErytyVovD8f6pDfG3Kb37N6Y3lmDA9NNj+4+IP13CzzHGeX+OyeRM2Um13khRzoBSzzL+5lVnCX8V2RLeMg=="], + "ioredis": ["ioredis@5.11.1", "", { "dependencies": { "@ioredis/commands": "1.10.0", "cluster-key-slot": "1.1.1", "debug": "4.4.3", "denque": "2.1.0", "redis-errors": "1.2.0", "redis-parser": "3.0.0", "standard-as-callback": "2.1.0" } }, "sha512-ehuGcf94bQXhfagULNXrJdfnWO38v070jxSx/qE87Kjzmu2fU7ro5EFAb+OPituLqgfyuQaym5DlrNydW2sJ9A=="], "ip-address": ["ip-address@10.2.0", "", {}, "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA=="], @@ -4100,6 +4068,8 @@ "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + "is-document.all": ["is-document.all@1.0.0", "", { "dependencies": { "call-bound": "^1.0.4" } }, "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g=="], + "is-electron": ["is-electron@2.2.2", "", {}, "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg=="], "is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="], @@ -4148,6 +4118,8 @@ "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], + "is-unsafe": ["is-unsafe@1.0.1", "", {}, "sha512-CLK2+VdgERgD96EYm5lUQssZYlRg2tkZnbsxZoacmSiRxiFJ4Nk4SzjCl+Ur+v3kXIY9dTIdb3IH22y1mZ56LA=="], + "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="], @@ -4170,12 +4142,6 @@ "isomorphic-ws": ["isomorphic-ws@5.0.0", "", { "peerDependencies": { "ws": "*" } }, "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw=="], - "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="], - - "istanbul-lib-report": ["istanbul-lib-report@3.0.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw=="], - - "istanbul-reports": ["istanbul-reports@3.2.0", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA=="], - "iterate-iterator": ["iterate-iterator@1.0.2", "", {}, "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw=="], "iterate-value": ["iterate-value@1.0.2", "", { "dependencies": { "es-get-iterator": "^1.0.2", "iterate-iterator": "^1.0.1" } }, "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ=="], @@ -4190,13 +4156,13 @@ "js-base64": ["js-base64@3.7.7", "", {}, "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw=="], - "js-beautify": ["js-beautify@1.15.4", "", { "dependencies": { "config-chain": "^1.1.13", "editorconfig": "^1.0.4", "glob": "^10.4.2", "js-cookie": "^3.0.5", "nopt": "^7.2.1" }, "bin": { "css-beautify": "js/bin/css-beautify.js", "html-beautify": "js/bin/html-beautify.js", "js-beautify": "js/bin/js-beautify.js" } }, "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA=="], + "js-beautify": ["js-beautify@1.15.4", "", { "dependencies": { "config-chain": "^1.1.13", "editorconfig": "^1.0.4", "glob": "^10.4.2", "js-cookie": "^3.0.5", "nopt": "^7.2.1" }, "bin": { "js-beautify": "js/bin/js-beautify.js", "css-beautify": "js/bin/css-beautify.js", "html-beautify": "js/bin/html-beautify.js" } }, "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA=="], "js-cookie": ["js-cookie@3.0.8", "", {}, "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw=="], "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - "js-yaml": ["js-yaml@3.14.2", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg=="], + "js-yaml": ["js-yaml@3.15.0", "", { "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ttBQIIQPDeLjpPOohtUdXuXUVoA2uIB6fEH9HyJ7234s5mBJ5wTx20njxplLZQgLaOfpmPQA7X2t5AX6tIPbog=="], "jsbi": ["jsbi@4.3.2", "", {}, "sha512-9fqMSQbhJykSeii05nxKl4m6Eqn2P6rOlYiS+C5Dr/HPIU/7yZxu5qzbs40tgaFORiw2Amd0mirjxatXYMkIew=="], @@ -4344,8 +4310,6 @@ "magicast": ["magicast@0.3.5", "", { "dependencies": { "@babel/parser": "^7.25.4", "@babel/types": "^7.25.4", "source-map-js": "^1.2.0" } }, "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ=="], - "make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="], - "make-fetch-happen": ["make-fetch-happen@15.0.6", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/agent": "^4.0.0", "@npmcli/redact": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^6.0.0", "ssri": "^13.0.0" } }, "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw=="], "markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="], @@ -4536,7 +4500,7 @@ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "msgpackr": ["msgpackr@2.0.2", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-c5hYOXFbP79Slh6Dzd2wzk+jnV7mX1UxfMYtilnY1NmalXPqG8DGb5cYCMBrW4AsH3zekBBZd4QrKz9NhtvYLQ=="], + "msgpackr": ["msgpackr@2.0.4", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-o1C5KRmuRt+apqMr1HuGSqWStZoRBUpEsCsl15uM9VdAF1qHLtvMOU2En747EnTyEl6c4pzPewRMFF31s1CNbA=="], "msgpackr-extract": ["msgpackr-extract@3.0.4", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw=="], @@ -4556,7 +4520,7 @@ "nanoevents": ["nanoevents@7.0.1", "", {}, "sha512-o6lpKiCxLeijK4hgsqfR6CNToPyRU3keKyyI6uwuHRvpRTbZ0wXw51WRgyldVugZqoJfkGFrjrIenYH3bfEO3Q=="], - "nanoid": ["nanoid@3.3.12", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ=="], + "nanoid": ["nanoid@3.3.15", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA=="], "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], @@ -4570,7 +4534,7 @@ "no-case": ["no-case@3.0.4", "", { "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" } }, "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg=="], - "node-abi": ["node-abi@4.31.0", "", { "dependencies": { "semver": "^7.6.3" } }, "sha512-Erq5w/t3syw3s4sDsUaX4QttIdBPsGKTT1DTRsCkTonGggczhlDKm/wDX3o+HPJpQ41EjXCbcmXf0tgr5YZJXw=="], + "node-abi": ["node-abi@4.33.0", "", { "dependencies": { "semver": "^7.6.3" } }, "sha512-vLBWCKb+7LWsX+TbfzWOkw0W81m377tyx3hOweBTjO43CXZnRGS1/JPWs20fr0PgZyDXk6ROYrylsEycK8raDA=="], "node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="], @@ -4582,7 +4546,7 @@ "node-fetch-native": ["node-fetch-native@1.6.7", "", {}, "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="], - "node-gyp": ["node-gyp@12.3.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "tar": "^7.5.4", "tinyglobby": "^0.2.12", "undici": "^6.25.0", "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-QNcUWM+HgJplcPzBvFBZ9VXacyGZ4+VTOb80PwWR+TlVzoHbRKULNEzpRsnaoxG3Wzr7Qh7BYxGDU3CbKib2Yg=="], + "node-gyp": ["node-gyp@12.4.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "tar": "^7.5.4", "tinyglobby": "^0.2.12", "undici": "^6.25.0", "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw=="], "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], @@ -4594,7 +4558,7 @@ "node-mock-http": ["node-mock-http@1.0.4", "", {}, "sha512-8DY+kFsDkNXy1sJglUfuODx1/opAGJGyrTuFqEoN90oRc2Vk0ZbD4K2qmKXBBEhZQzdKHIVfEJpDU8Ak2NJEvQ=="], - "node-releases": ["node-releases@2.0.46", "", {}, "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ=="], + "node-releases": ["node-releases@2.0.50", "", {}, "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg=="], "nopt": ["nopt@9.0.0", "", { "dependencies": { "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw=="], @@ -4620,7 +4584,7 @@ "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], - "nypm": ["nypm@0.6.6", "", { "dependencies": { "citty": "^0.2.2", "pathe": "^2.0.3", "tinyexec": "^1.1.1" }, "bin": { "nypm": "dist/cli.mjs" } }, "sha512-vRyr0r4cbBapw07Xw8xrj9Teq3o7MUD35rSaTcanDbW+aK2XHDgJFiU6ZTj2GBw7Q12ysdsyFss+Vdz4hQ0Y6Q=="], + "nypm": ["nypm@0.6.8", "", { "dependencies": { "citty": "^0.2.2", "pathe": "^2.0.3", "tinyexec": "^1.2.4" }, "bin": { "nypm": "./dist/cli.mjs" } }, "sha512-Q9K4Diu6l5u6xJQogeFSs/zKtyMSgFKFtRQV+tHP4kL7KPm2grpBU0dFIwFaXwNxN0MtfKWc43VpCugAa+LPsw=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], @@ -4632,7 +4596,7 @@ "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], - "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="], + "obug": ["obug@2.1.3", "", {}, "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg=="], "ofetch": ["ofetch@2.0.0-alpha.3", "", {}, "sha512-zpYTCs2byOuft65vI3z43Dd6iSdFbOZZLb9/d21aCpx2rGastVU9dOCv0lu4ykc1Ur1anAYjDi3SUvR0vq50JA=="], @@ -4674,7 +4638,7 @@ "oxc-parser": ["oxc-parser@0.127.0", "", { "dependencies": { "@oxc-project/types": "^0.127.0" }, "optionalDependencies": { "@oxc-parser/binding-android-arm-eabi": "0.127.0", "@oxc-parser/binding-android-arm64": "0.127.0", "@oxc-parser/binding-darwin-arm64": "0.127.0", "@oxc-parser/binding-darwin-x64": "0.127.0", "@oxc-parser/binding-freebsd-x64": "0.127.0", "@oxc-parser/binding-linux-arm-gnueabihf": "0.127.0", "@oxc-parser/binding-linux-arm-musleabihf": "0.127.0", "@oxc-parser/binding-linux-arm64-gnu": "0.127.0", "@oxc-parser/binding-linux-arm64-musl": "0.127.0", "@oxc-parser/binding-linux-ppc64-gnu": "0.127.0", "@oxc-parser/binding-linux-riscv64-gnu": "0.127.0", "@oxc-parser/binding-linux-riscv64-musl": "0.127.0", "@oxc-parser/binding-linux-s390x-gnu": "0.127.0", "@oxc-parser/binding-linux-x64-gnu": "0.127.0", "@oxc-parser/binding-linux-x64-musl": "0.127.0", "@oxc-parser/binding-openharmony-arm64": "0.127.0", "@oxc-parser/binding-wasm32-wasi": "0.127.0", "@oxc-parser/binding-win32-arm64-msvc": "0.127.0", "@oxc-parser/binding-win32-ia32-msvc": "0.127.0", "@oxc-parser/binding-win32-x64-msvc": "0.127.0" } }, "sha512-bkgD4qHlN7WxLdX8bLXdaU54TtQtAIg/ZBAfm0aje/mo3MRDo3P0hZSgr4U7O3xfX+fQmR5AP04JS/TGcZLcFA=="], - "oxc-resolver": ["oxc-resolver@11.20.0", "", { "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.20.0", "@oxc-resolver/binding-android-arm64": "11.20.0", "@oxc-resolver/binding-darwin-arm64": "11.20.0", "@oxc-resolver/binding-darwin-x64": "11.20.0", "@oxc-resolver/binding-freebsd-x64": "11.20.0", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.20.0", "@oxc-resolver/binding-linux-arm-musleabihf": "11.20.0", "@oxc-resolver/binding-linux-arm64-gnu": "11.20.0", "@oxc-resolver/binding-linux-arm64-musl": "11.20.0", "@oxc-resolver/binding-linux-ppc64-gnu": "11.20.0", "@oxc-resolver/binding-linux-riscv64-gnu": "11.20.0", "@oxc-resolver/binding-linux-riscv64-musl": "11.20.0", "@oxc-resolver/binding-linux-s390x-gnu": "11.20.0", "@oxc-resolver/binding-linux-x64-gnu": "11.20.0", "@oxc-resolver/binding-linux-x64-musl": "11.20.0", "@oxc-resolver/binding-openharmony-arm64": "11.20.0", "@oxc-resolver/binding-wasm32-wasi": "11.20.0", "@oxc-resolver/binding-win32-arm64-msvc": "11.20.0", "@oxc-resolver/binding-win32-x64-msvc": "11.20.0" } }, "sha512-CblytBiV/a/ZXY34dsVU2NxhIOxMXst8CvDCtyBelVITgd7PLrKzbEbA6oKLdPjvDKDzCiW48qzmzZ+mYaqn+g=="], + "oxc-resolver": ["oxc-resolver@11.23.0", "", { "optionalDependencies": { "@oxc-resolver/binding-android-arm-eabi": "11.23.0", "@oxc-resolver/binding-android-arm64": "11.23.0", "@oxc-resolver/binding-darwin-arm64": "11.23.0", "@oxc-resolver/binding-darwin-x64": "11.23.0", "@oxc-resolver/binding-freebsd-x64": "11.23.0", "@oxc-resolver/binding-linux-arm-gnueabihf": "11.23.0", "@oxc-resolver/binding-linux-arm-musleabihf": "11.23.0", "@oxc-resolver/binding-linux-arm64-gnu": "11.23.0", "@oxc-resolver/binding-linux-arm64-musl": "11.23.0", "@oxc-resolver/binding-linux-ppc64-gnu": "11.23.0", "@oxc-resolver/binding-linux-riscv64-gnu": "11.23.0", "@oxc-resolver/binding-linux-riscv64-musl": "11.23.0", "@oxc-resolver/binding-linux-s390x-gnu": "11.23.0", "@oxc-resolver/binding-linux-x64-gnu": "11.23.0", "@oxc-resolver/binding-linux-x64-musl": "11.23.0", "@oxc-resolver/binding-openharmony-arm64": "11.23.0", "@oxc-resolver/binding-wasm32-wasi": "11.23.0", "@oxc-resolver/binding-win32-arm64-msvc": "11.23.0", "@oxc-resolver/binding-win32-x64-msvc": "11.23.0" } }, "sha512-f0+l598CJMOLnYPXsXxttJALH0ljtivdRMKtvHhxRuWa5FYmw5+qODARl8oYjMC/brpzKcrpdORsOBrTqhBZ9A=="], "oxc-transform": ["oxc-transform@0.96.0", "", { "optionalDependencies": { "@oxc-transform/binding-android-arm64": "0.96.0", "@oxc-transform/binding-darwin-arm64": "0.96.0", "@oxc-transform/binding-darwin-x64": "0.96.0", "@oxc-transform/binding-freebsd-x64": "0.96.0", "@oxc-transform/binding-linux-arm-gnueabihf": "0.96.0", "@oxc-transform/binding-linux-arm-musleabihf": "0.96.0", "@oxc-transform/binding-linux-arm64-gnu": "0.96.0", "@oxc-transform/binding-linux-arm64-musl": "0.96.0", "@oxc-transform/binding-linux-riscv64-gnu": "0.96.0", "@oxc-transform/binding-linux-s390x-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-gnu": "0.96.0", "@oxc-transform/binding-linux-x64-musl": "0.96.0", "@oxc-transform/binding-wasm32-wasi": "0.96.0", "@oxc-transform/binding-win32-arm64-msvc": "0.96.0", "@oxc-transform/binding-win32-x64-msvc": "0.96.0" } }, "sha512-dQPNIF+gHpSkmC0+Vg9IktNyhcn28Y8R3eTLyzn52UNymkasLicl3sFAtz7oEVuFmCpgGjaUTKkwk+jW2cHpDQ=="], @@ -4692,7 +4656,7 @@ "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], - "p-map": ["p-map@7.0.4", "", {}, "sha512-tkAQEw8ysMzmkhgw8k+1U/iPhWNhykKnSk4Rd5zLoPJCuJaGRPo6YposrZgaxHKzDHdDWWZvE/Sk7hsL2X/CpQ=="], + "p-map": ["p-map@7.0.5", "", {}, "sha512-e8vJF4XdVkzqqSHguEMz41mQO1wKwxKm5ENrUJQUu9kLDCtn83cxbyHZcszr4QC5zEA7WffRRC4gsTecC7J9oA=="], "p-queue": ["p-queue@8.1.1", "", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^6.1.2" } }, "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ=="], @@ -4704,9 +4668,9 @@ "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], - "package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="], + "package-manager-detector": ["package-manager-detector@1.7.0", "", {}, "sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ=="], - "pacote": ["pacote@21.5.0", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "@npmcli/run-script": "^10.0.0", "cacache": "^20.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^13.0.0", "npm-packlist": "^10.0.1", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", "sigstore": "^4.0.0", "ssri": "^13.0.0", "tar": "^7.4.3" }, "bin": { "pacote": "bin/index.js" } }, "sha512-VtZ0SB8mb5Tzw3dXDfVAIjhyVKUHZkS/ZH9/5mpKenwC9sFOXNI0JI7kEF7IMkwOnsWMFrvAZHzx1T5fmrp9FQ=="], + "pacote": ["pacote@21.5.1", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "@npmcli/run-script": "^10.0.0", "cacache": "^20.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^13.0.0", "npm-packlist": "^10.0.1", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", "sigstore": "^4.0.0", "ssri": "^13.0.0", "tar": "^7.4.3" }, "bin": { "pacote": "bin/index.js" } }, "sha512-KvcJ9iy3crysCsgqc4+PknH/w6jkrp8JN36mpZBPwNaDRwTfMZD37YzRazNstiZUOhuF5pno9f78n9mEJBavwg=="], "pagefind": ["pagefind@1.5.2", "", { "optionalDependencies": { "@pagefind/darwin-arm64": "1.5.2", "@pagefind/darwin-x64": "1.5.2", "@pagefind/freebsd-x64": "1.5.2", "@pagefind/linux-arm64": "1.5.2", "@pagefind/linux-x64": "1.5.2", "@pagefind/windows-arm64": "1.5.2", "@pagefind/windows-x64": "1.5.2" }, "bin": { "pagefind": "lib/runner/bin.cjs" } }, "sha512-XTUaK0hXMCu2jszWE584JGQT7y284TmMV9l/HX3rnG5uo3rHI/uHU56XTyyyPFjeWEBxECbAi0CaFDJOONtG0Q=="], @@ -4736,7 +4700,7 @@ "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], - "path-expression-matcher": ["path-expression-matcher@1.5.0", "", {}, "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ=="], + "path-expression-matcher": ["path-expression-matcher@1.6.1", "", {}, "sha512-h7bxdzhHk8Knyc4Tj+jMaa7fEEoUJy7p1qtbVgkYg1Uhpe5Np5VuGXCRZnkZvU+Q42M1vStt0ifa3ueykRJPmQ=="], "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], @@ -4766,7 +4730,7 @@ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], - "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="], + "picomatch": ["picomatch@4.0.5", "", {}, "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A=="], "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], @@ -4794,11 +4758,11 @@ "plist": ["plist@3.1.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="], - "poe-oauth": ["poe-oauth@0.0.8", "", {}, "sha512-zlaRVLR6vuxBIYUkZoTIVo3f8h3qd27gv9Ms+kmGiYEiiV4TdccddTdNcGyI0DnuJ9tVi+5LP3Bvzez59IFbjw=="], + "poe-oauth": ["poe-oauth@0.0.10", "", {}, "sha512-XohR2aTnXT6U3KAly540b7IcJT7yxa4d8PKibeqShpeLN1KLRHb5FBJ9WY42IhDQxOrF/GNndc+nnsliJtPlSA=="], "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], - "postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="], + "postcss": ["postcss@8.5.16", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg=="], "postcss-css-variables": ["postcss-css-variables@0.18.0", "", { "dependencies": { "balanced-match": "^1.0.0", "escape-string-regexp": "^1.0.3", "extend": "^3.0.1" }, "peerDependencies": { "postcss": "^8.2.6" } }, "sha512-lYS802gHbzn1GI+lXvy9MYIYDuGnl1WB4FTKoqMQqJ3Mab09A7a/1wZvGTkCEZJTM8mSbIyb1mJYn8f0aPye0Q=="], @@ -4810,7 +4774,7 @@ "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], - "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + "postcss-selector-parser": ["postcss-selector-parser@6.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ=="], "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], @@ -4856,11 +4820,11 @@ "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], - "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], + "property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="], "proto-list": ["proto-list@1.2.4", "", {}, "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA=="], - "protobufjs": ["protobufjs@7.6.2", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-N9EiLovGEQOJSPF26Ij7qUGvahfEnq0eeYZ02aigIedkmz1qZSwjnP9SBITHJuF/6MYbIW4HDN8zdYjsjqJKXQ=="], + "protobufjs": ["protobufjs@7.6.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw=="], "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], @@ -4868,17 +4832,15 @@ "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], - "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], - "pupa": ["pupa@3.3.0", "", { "dependencies": { "escape-goat": "^4.0.0" } }, "sha512-LjgDO2zPtoXP2wJpDjZrGdojii1uqO0cnwKoIoUzkfS98HDmbeiGmYiXo3lXeFlq2xvne1QFQhwYXSUCLKtEuA=="], - "pure-rand": ["pure-rand@8.4.0", "", {}, "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A=="], + "pure-rand": ["pure-rand@8.4.1", "", {}, "sha512-c58R2+SPFcSIPXoU834QN/KPDDOSd8sXcSrqf6e83Me6Rrp1EYkxukkjXMVrKvKaADs1SOyNkWdfvLf6zY8qLQ=="], "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="], "pvutils": ["pvutils@1.1.5", "", {}, "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA=="], - "qs": ["qs@6.15.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw=="], + "qs": ["qs@6.15.3", "", { "dependencies": { "es-define-property": "^1.0.1", "side-channel": "^1.1.1" } }, "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A=="], "quansync": ["quansync@0.2.11", "", {}, "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA=="], @@ -4890,7 +4852,7 @@ "radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="], - "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + "range-parser": ["range-parser@1.3.0", "", {}, "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw=="], "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], @@ -4898,8 +4860,6 @@ "react": ["react@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ=="], - "react-docgen-typescript": ["react-docgen-typescript@2.4.0", "", { "peerDependencies": { "typescript": ">= 4.3.x" } }, "sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg=="], - "react-dom": ["react-dom@18.2.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.0" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g=="], "react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="], @@ -4930,7 +4890,7 @@ "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], - "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="], + "recast": ["recast@0.23.12", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA=="], "recma-build-jsx": ["recma-build-jsx@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew=="], @@ -5032,11 +4992,11 @@ "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - "rimraf": ["rimraf@2.6.3", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="], + "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], "roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="], - "rollup": ["rollup@4.60.4", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.4", "@rollup/rollup-android-arm64": "4.60.4", "@rollup/rollup-darwin-arm64": "4.60.4", "@rollup/rollup-darwin-x64": "4.60.4", "@rollup/rollup-freebsd-arm64": "4.60.4", "@rollup/rollup-freebsd-x64": "4.60.4", "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", "@rollup/rollup-linux-arm-musleabihf": "4.60.4", "@rollup/rollup-linux-arm64-gnu": "4.60.4", "@rollup/rollup-linux-arm64-musl": "4.60.4", "@rollup/rollup-linux-loong64-gnu": "4.60.4", "@rollup/rollup-linux-loong64-musl": "4.60.4", "@rollup/rollup-linux-ppc64-gnu": "4.60.4", "@rollup/rollup-linux-ppc64-musl": "4.60.4", "@rollup/rollup-linux-riscv64-gnu": "4.60.4", "@rollup/rollup-linux-riscv64-musl": "4.60.4", "@rollup/rollup-linux-s390x-gnu": "4.60.4", "@rollup/rollup-linux-x64-gnu": "4.60.4", "@rollup/rollup-linux-x64-musl": "4.60.4", "@rollup/rollup-openbsd-x64": "4.60.4", "@rollup/rollup-openharmony-arm64": "4.60.4", "@rollup/rollup-win32-arm64-msvc": "4.60.4", "@rollup/rollup-win32-ia32-msvc": "4.60.4", "@rollup/rollup-win32-x64-gnu": "4.60.4", "@rollup/rollup-win32-x64-msvc": "4.60.4", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g=="], + "rollup": ["rollup@4.62.2", "", { "dependencies": { "@types/estree": "1.0.9" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.62.2", "@rollup/rollup-android-arm64": "4.62.2", "@rollup/rollup-darwin-arm64": "4.62.2", "@rollup/rollup-darwin-x64": "4.62.2", "@rollup/rollup-freebsd-arm64": "4.62.2", "@rollup/rollup-freebsd-x64": "4.62.2", "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", "@rollup/rollup-linux-arm-musleabihf": "4.62.2", "@rollup/rollup-linux-arm64-gnu": "4.62.2", "@rollup/rollup-linux-arm64-musl": "4.62.2", "@rollup/rollup-linux-loong64-gnu": "4.62.2", "@rollup/rollup-linux-loong64-musl": "4.62.2", "@rollup/rollup-linux-ppc64-gnu": "4.62.2", "@rollup/rollup-linux-ppc64-musl": "4.62.2", "@rollup/rollup-linux-riscv64-gnu": "4.62.2", "@rollup/rollup-linux-riscv64-musl": "4.62.2", "@rollup/rollup-linux-s390x-gnu": "4.62.2", "@rollup/rollup-linux-x64-gnu": "4.62.2", "@rollup/rollup-linux-x64-musl": "4.62.2", "@rollup/rollup-openbsd-x64": "4.62.2", "@rollup/rollup-openharmony-arm64": "4.62.2", "@rollup/rollup-win32-arm64-msvc": "4.62.2", "@rollup/rollup-win32-ia32-msvc": "4.62.2", "@rollup/rollup-win32-x64-gnu": "4.62.2", "@rollup/rollup-win32-x64-msvc": "4.62.2", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA=="], "rou3": ["rou3@0.7.12", "", {}, "sha512-iFE4hLDuloSWcD7mjdCDhx2bKcIsYbtOTpfH5MHHLSKMOUyjqQXTeZVa289uuwEGEKFoE/BAPbhaU4B774nceg=="], @@ -5074,7 +5034,7 @@ "selderee": ["selderee@0.11.0", "", { "dependencies": { "parseley": "^0.12.0" } }, "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA=="], - "semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], "semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="], @@ -5110,7 +5070,7 @@ "shikiji": ["shikiji@0.6.13", "", { "dependencies": { "hast-util-to-html": "^9.0.0" } }, "sha512-4T7X39csvhT0p7GDnq9vysWddf2b6BeioiN3Ymhnt3xcy9tXmDcnsEFVxX18Z4YcQgEE/w48dLJ4pPPUcG9KkA=="], - "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], + "side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="], "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], @@ -5138,7 +5098,7 @@ "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], - "smol-toml": ["smol-toml@1.6.1", "", {}, "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg=="], + "smol-toml": ["smol-toml@1.7.0", "", {}, "sha512-aqVvWoyO21L23mb+drl4RmMXbf6N7FdHjAhTRA9ZBL7apWBgfWC16KjrASI+1p9GAroljyMHj6fK67i0UiTNvQ=="], "socket.io-client": ["socket.io-client@4.8.3", "", { "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1", "engine.io-client": "~6.6.1", "socket.io-parser": "~4.2.4" } }, "sha512-uP0bpjWrjQmUt5DTHq9RuoCBdFJF10cdX9X+a368j/Ft0wmaVgxlrjvK3kjvgCODOMMOz9lcaRzxmso0bTWZ/g=="], @@ -5226,21 +5186,21 @@ "stoppable": ["stoppable@1.1.0", "", {}, "sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw=="], - "storybook": ["storybook@10.4.1", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.2", "@testing-library/jest-dom": "^6.9.1", "@testing-library/user-event": "^14.6.1", "@vitest/expect": "3.2.4", "@vitest/spy": "3.2.4", "@webcontainer/env": "^1.1.1", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0", "open": "^10.2.0", "oxc-parser": "^0.127.0", "oxc-resolver": "^11.19.1", "recast": "^0.23.5", "semver": "^7.7.3", "use-sync-external-store": "^1.5.0", "ws": "^8.18.0" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "prettier": "^2 || ^3", "vite-plus": "^0.1.15" }, "optionalPeers": ["@types/react", "prettier", "vite-plus"], "bin": "./dist/bin/dispatcher.js" }, "sha512-V1Zd2e+gBFufqAQVZ1JR8KLqALsEZ3JYSBnWwQbKa6zCfWWanR6AFMyuOkLt2gZOgGp3h2Riuz88pGNVTQSG0A=="], + "storybook": ["storybook@10.4.6", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.2", "@testing-library/jest-dom": "^6.9.1", "@testing-library/user-event": "^14.6.1", "@vitest/expect": "3.2.4", "@vitest/spy": "3.2.4", "@webcontainer/env": "^1.1.1", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0 || ^0.28.0", "open": "^10.2.0", "oxc-parser": "^0.127.0", "oxc-resolver": "^11.19.1", "recast": "^0.23.5", "semver": "^7.7.3", "use-sync-external-store": "^1.5.0", "ws": "^8.18.0" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "prettier": "^2 || ^3", "vite-plus": "^0.1.15" }, "optionalPeers": ["@types/react", "prettier", "vite-plus"], "bin": "./dist/bin/dispatcher.js" }, "sha512-6wkA6LxfDSSilloITsrFOJfsnw0mDUP2h8Ls+lRt8oRsudtz2RWFhLv+Toiwg6NW7hUpdTDc2hzR7DztJid6+A=="], - "storybook-solidjs-vite": ["storybook-solidjs-vite@10.1.1", "", { "dependencies": { "@joshwooding/vite-plugin-react-docgen-typescript": "^0.7.0", "@storybook/builder-vite": "^10.4.0", "@storybook/global": "^5.0.0", "semver": "7.8.1" }, "peerDependencies": { "@solidjs/web": "^2.0.0-0", "solid-js": "^1.8.0-0 || ^2.0.0-0", "storybook": "^0.0.0-0 || ^10.0.0", "typescript": "^4.0.0 || ^5.0.0 || ^6.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", "vite-plugin-solid": "^2.0.0-0 || ^3.0.0-0" }, "optionalPeers": ["@solidjs/web", "typescript"] }, "sha512-4acj1yxVPM3PieEGFPJukPeIXmpboJprewiX0KMrdYvtAZy8zbkZ7QBf8iENyKNJOayeXWzMm+z7hWBQDUirYg=="], + "storybook-solidjs-vite": ["storybook-solidjs-vite@10.5.2", "", { "dependencies": { "@storybook/builder-vite": "10.4.4", "@storybook/global": "5.0.0", "@volar/language-core": "2.4.28", "@volar/typescript": "2.4.28", "semver": "7.8.1" }, "peerDependencies": { "@solidjs/web": "^2.0.0-0", "solid-js": "^1.8.0-0 || ^2.0.0-0", "storybook": "^0.0.0-0 || ^10.0.0", "typescript": "^4.0.0 || ^5.0.0 || ^6.0.0", "vite": "7.1.11", "vite-plugin-solid": "2.11.12" }, "optionalPeers": ["@solidjs/web", "typescript"] }, "sha512-u+XSoTxE8JoVZ4IdI+gJRuNMQL00PCLA1BinBPdwHRKSSSVczf+JQhcfBJ2xxODs430RJp+JjAajKZeaSIHj9Q=="], "stream-replace-string": ["stream-replace-string@2.0.0", "", {}, "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w=="], - "streamx": ["streamx@2.26.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-VvNG1K72Po/xwJzxZFnZ++Tbrv4lwSptsbkFuzXCJAYZvCK5nnxsvXU6ajqkv7chyiI1Y0YXq2Jh8Iy8Y7NF/A=="], + "streamx": ["streamx@2.28.0", "", { "dependencies": { "events-universal": "^1.0.0", "fast-fifo": "^1.3.2", "text-decoder": "^1.1.0" } }, "sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw=="], "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="], + "string.prototype.trim": ["string.prototype.trim@1.2.11", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-object-atoms": "^1.1.2", "has-property-descriptors": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w=="], - "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="], + "string.prototype.trimend": ["string.prototype.trimend@1.0.10", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.2" } }, "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw=="], "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], @@ -5290,7 +5250,7 @@ "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], - "tar": ["tar@7.5.15", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-dzGK0boVlC4W5QFuQN1EFSl3bIDYsk7Tj40U6eIBnK2k/8ml7TZ5agbI5j5+qnoVcAA+rNtBml8SEiLxZpNqRQ=="], + "tar": ["tar@7.5.19", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw=="], "tar-stream": ["tar-stream@3.2.0", "", { "dependencies": { "b4a": "^1.6.4", "bare-fs": "^4.5.5", "fast-fifo": "^1.2.0", "streamx": "^2.15.0" } }, "sha512-ojzvCvVaNp6aOTFmG7jaRD0meowIAuPc3cMMhSgKiVWws1GyHbGd/xvnyuRKcKlMpt3qvxx6r0hreCNITP9hIg=="], @@ -5344,7 +5304,7 @@ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], - "toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="], + "toml": ["toml@4.1.2", "", {}, "sha512-m0vXfHODcw3gk+KONAOlVQ5yNHc3yS3B1ybM3HS1vqDoS0RWTDDVBVVTYi8hH0k+2OM1vmo9fb1WX9EVqjqfHA=="], "toolbeam-docs-theme": ["toolbeam-docs-theme@0.4.8", "", { "peerDependencies": { "@astrojs/starlight": "^0.34.3", "astro": "^5.7.13" } }, "sha512-b+5ynEFp4Woe5a22hzNQm42lD23t13ZMihVxHbzjA50zdcM9aOSJTIjdJ0PDSd4/50HbBXcpHiQsz6rM4N88ww=="], @@ -5368,7 +5328,7 @@ "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], - "ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="], + "ts-dedent": ["ts-dedent@2.3.0", "", {}, "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg=="], "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], @@ -5432,7 +5392,7 @@ "uncrypto": ["uncrypto@0.1.3", "", {}, "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q=="], - "undici": ["undici@8.3.0", "", {}, "sha512-TkUDgb6tl7KOGZ+7e8E3d2FYgUQgF6z5YypqjWmixVQSQERFcVrVg0ySADm2LVLRh5ljAaHTCR5Fmz3Q34rB7Q=="], + "undici": ["undici@8.6.0", "", {}, "sha512-l2FlC6I510GawyEd1qgcE/okihKrzy+BRTEBlu6T0fdbM9m5yxtIH5Oa3ysRsH0zC4EhmWUEaSDsy2QngBeRlw=="], "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], @@ -5482,12 +5442,10 @@ "unzip-stream": ["unzip-stream@0.3.4", "", { "dependencies": { "binary": "^0.3.0", "mkdirp": "^0.5.1" } }, "sha512-PyofABPVv+d7fL7GOpusx7eRT9YETY2X04PhwbSipdj6bMxVCFJrr+nm0Mxqbf9hUiTin/UsnuFWBXlDZFy0Cw=="], - "unzipper": ["unzipper@0.12.3", "", { "dependencies": { "bluebird": "~3.7.2", "duplexer2": "~0.1.4", "fs-extra": "^11.2.0", "graceful-fs": "^4.2.2", "node-int64": "^0.4.0" } }, "sha512-PZ8hTS+AqcGxsaQntl3IRBw65QrBI6lxzqDEL7IAo/XCEqRTKGfOX56Vea5TH9SZczRVxuzk1re04z/YjuYCJA=="], + "unzipper": ["unzipper@0.12.5", "", { "dependencies": { "bluebird": "~3.7.2", "duplexer2": "~0.1.4", "fs-extra": "11.3.1", "graceful-fs": "^4.2.2", "node-int64": "^0.4.0" } }, "sha512-tXYOi9R57Uj/2Z25SOs5RRSzq886MBQj2gY8dPL+xl/kv6s6SvByoKfAtvfVeEuhntWDgjd2o9p2lb4TVPAz0A=="], "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], - "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], - "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], @@ -5500,9 +5458,9 @@ "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], - "uuid": ["uuid@14.0.0", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-Qo+uWgilfSmAhXCMav1uYFynlQO7fMFiMVZsQqZRMIXp0O7rR7qjkj+cPvBHLgBqi960QCoo/PH2/6ZtVqKvrg=="], + "uuid": ["uuid@14.0.1", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew=="], - "valibot": ["valibot@1.4.1", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-klCmFTz2jeDluy9RwX+F884TCiogtdBJ/YaxSx1EOBYXa3NXNWj8kR1jjN8rzluwojJVWWaHJ4r1U5LfICnM3g=="], + "valibot": ["valibot@1.4.2", "", { "peerDependencies": { "typescript": ">=5" }, "optionalPeers": ["typescript"] }, "sha512-gjdCvJ6d3RyHAneqxMYMW9QMCwYMb3jpOO0IyHZV1bnRHFBHrX3VkIILt5XYR0WhwHiH7Mty8ovuPZ/O3gamrg=="], "validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="], @@ -5510,8 +5468,6 @@ "venice-ai-sdk-provider": ["venice-ai-sdk-provider@2.1.1", "", { "dependencies": { "@ai-sdk/openai-compatible": "^2.0.51", "@ai-sdk/provider": "^3.0.10", "@ai-sdk/provider-utils": "^4.0.30" }, "peerDependencies": { "ai": "^6.0.90" } }, "sha512-w3OHkuzzKZ3r2TOxER6myBYzZJNoDqol+DUHu3NnfBN/GETnUVxecZJab0CHQQ8GZc0jjzpFymepjcLDPS4SQg=="], - "verror": ["verror@1.10.1", "", { "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", "extsprintf": "^1.2.0" } }, "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg=="], - "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="], @@ -5528,21 +5484,21 @@ "vitefu": ["vitefu@1.1.3", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["vite"] }, "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg=="], - "vitest": ["vitest@4.1.7", "", { "dependencies": { "@vitest/expect": "4.1.7", "@vitest/mocker": "4.1.7", "@vitest/pretty-format": "4.1.7", "@vitest/runner": "4.1.7", "@vitest/snapshot": "4.1.7", "@vitest/spy": "4.1.7", "@vitest/utils": "4.1.7", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.7", "@vitest/browser-preview": "4.1.7", "@vitest/browser-webdriverio": "4.1.7", "@vitest/coverage-istanbul": "4.1.7", "@vitest/coverage-v8": "4.1.7", "@vitest/ui": "4.1.7", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA=="], + "vitest": ["vitest@4.1.9", "", { "dependencies": { "@vitest/expect": "4.1.9", "@vitest/mocker": "4.1.9", "@vitest/pretty-format": "4.1.9", "@vitest/runner": "4.1.9", "@vitest/snapshot": "4.1.9", "@vitest/spy": "4.1.9", "@vitest/utils": "4.1.9", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.1.0", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.9", "@vitest/browser-preview": "4.1.9", "@vitest/browser-webdriverio": "4.1.9", "@vitest/coverage-istanbul": "4.1.9", "@vitest/coverage-v8": "4.1.9", "@vitest/ui": "4.1.9", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/coverage-istanbul", "@vitest/coverage-v8", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "./vitest.mjs" } }, "sha512-nE3/LEyc0z87uHYLZebqCUOaJr2hdtuPp7BQ4BosVFnfltxgAvMG08NyrSGlPpOUWvR27c5flSmYFTNr78L9GQ=="], - "volar-service-css": ["volar-service-css@0.0.70", "", { "dependencies": { "vscode-css-languageservice": "^6.3.0", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-K1qyOvBpE3rzdAv3e4/6Rv5yizrYPy5R/ne3IWCAzLBuMO4qBMV3kSqWzj6KUVe6S0AnN6wxF7cRkiaKfYMYJw=="], + "volar-service-css": ["volar-service-css@0.0.71", "", { "dependencies": { "vscode-css-languageservice": "^6.3.0", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-wRRFt9BpjMKCazcgOh67MSjUjiWUCAh99DyYSDIOTuxaRjEtDC7PpB0k1Y1wbJIW/pVtMUSVbpPo3UGSm0Byxw=="], - "volar-service-emmet": ["volar-service-emmet@0.0.70", "", { "dependencies": { "@emmetio/css-parser": "^0.4.1", "@emmetio/html-matcher": "^1.3.0", "@vscode/emmet-helper": "^2.9.3", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-xi5bC4m/VyE3zy/n2CXspKeDZs3qA41tHLTw275/7dNWM/RqE2z3BnDICQybHIVp/6G1iOQj5c1qXMgQC08TNg=="], + "volar-service-emmet": ["volar-service-emmet@0.0.71", "", { "dependencies": { "@emmetio/css-parser": "^0.4.1", "@emmetio/html-matcher": "^1.3.0", "@vscode/emmet-helper": "^2.9.3", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-zqjzt6bN95e3CUstBm0PBFAJnrfz0ZAARka87fart46/gNCLLuP3Vujy8V/J8HEziTFLnfkgIASLFYPUhonJcA=="], - "volar-service-html": ["volar-service-html@0.0.70", "", { "dependencies": { "vscode-html-languageservice": "^5.3.0", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-eR6vCgMdmYAo4n+gcT7DSyBQbwB8S3HZZvSagTf0sxNaD4WppMCFfpqWnkrlGStPKMZvMiejRRVmqsX9dYcTvQ=="], + "volar-service-html": ["volar-service-html@0.0.71", "", { "dependencies": { "vscode-html-languageservice": "^5.3.0", "vscode-languageserver-textdocument": "^1.0.11", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-e8tHPhgQ7ooLfudAEIku+kgd9pWkq3SSz8RbnQDI1+Eb8wbenkLGHqoirLqz5ORLV6wIMr2Iv08RWBG5eOcgpw=="], - "volar-service-prettier": ["volar-service-prettier@0.0.70", "", { "dependencies": { "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0", "prettier": "^2.2 || ^3.0" }, "optionalPeers": ["@volar/language-service", "prettier"] }, "sha512-Z6BCFSpGVCd8BPAsZ785Kce1BGlWd5ODqmqZGVuB14MJvrR4+CYz6cDy4F+igmE1gMifqfvMhdgT8Aud4M5ngg=="], + "volar-service-prettier": ["volar-service-prettier@0.0.71", "", { "dependencies": { "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0", "prettier": "^2.2 || ^3.0" }, "optionalPeers": ["@volar/language-service", "prettier"] }, "sha512-Rz7JVH3qD108UCdmIEiZvOBNljMt2nLFdbN8AXcDfn7xD9F5I2aCIsDVqBbXw21PsnxG0b7MfwtNF+zPS/NKUg=="], - "volar-service-typescript": ["volar-service-typescript@0.0.70", "", { "dependencies": { "path-browserify": "^1.0.1", "semver": "^7.6.2", "typescript-auto-import-cache": "^0.3.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-nls": "^5.2.0", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-l46Bx4cokkUedTd74ojO5H/zqHZJ8SUuyZ0IB8JN4jfRqUM3bQFBHoOwlZCyZmOeO0A3RQNkMnFclxO4c++gsg=="], + "volar-service-typescript": ["volar-service-typescript@0.0.71", "", { "dependencies": { "path-browserify": "^1.0.1", "semver": "^7.6.2", "typescript-auto-import-cache": "^0.3.5", "vscode-languageserver-textdocument": "^1.0.11", "vscode-nls": "^5.2.0", "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-yTtM/BVT6hoyEYnDtaCyAtNhdNeS/mhTTABlBOdw3NNiRBUin3IznFJpgfjer4c6RYopiPjjQjc9VFhxVl1mLw=="], - "volar-service-typescript-twoslash-queries": ["volar-service-typescript-twoslash-queries@0.0.70", "", { "dependencies": { "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-IdD13Z9N2Bu8EM6CM0fDV1E69olEYGHDU25X51YXmq8Y0CmJ2LNj6gOiBJgpS5JGUqFzECVhMNBW7R0sPdRTMQ=="], + "volar-service-typescript-twoslash-queries": ["volar-service-typescript-twoslash-queries@0.0.71", "", { "dependencies": { "vscode-uri": "^3.0.8" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-9K2k72s4n7rV9s4bX0MyjbX9iBribvKZbBJKuEmTCZfeWJXs6Yh7bGpY4eoc7UufAjvpheBqwyZCOIPBvxCv0A=="], - "volar-service-yaml": ["volar-service-yaml@0.0.70", "", { "dependencies": { "vscode-uri": "^3.0.8", "yaml-language-server": "~1.20.0" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-0c8bXDBeoATF9F6iPIlOuYTuZAC4c+yi0siQo920u7eiBJk8oQmUmg9cDUbR4+Gl++bvGP4plj3fErbJuPqdcQ=="], + "volar-service-yaml": ["volar-service-yaml@0.0.71", "", { "dependencies": { "vscode-uri": "^3.0.8", "yaml-language-server": "~1.23.0" }, "peerDependencies": { "@volar/language-service": "~2.4.0" }, "optionalPeers": ["@volar/language-service"] }, "sha512-qYGWGuVpUTnZGu5P/CR4KLK4aIR8RrcVnmfZ2eRcj9q/I8VZCoC5yy9FtEvfNvnDp4MU17yhdJcvpQPIqhJS2Q=="], "vscode-css-languageservice": ["vscode-css-languageservice@6.3.10", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "vscode-languageserver-textdocument": "^1.0.12", "vscode-languageserver-types": "3.17.5", "vscode-uri": "^3.1.0" } }, "sha512-eq5N9Er3fC4vA9zd9EFhyBG90wtCCuXgRSpAndaOgXMh1Wgep5lBgRIeDgjZBW9pa+332yC9+49cZMW8jcL3MA=="], @@ -5554,7 +5510,7 @@ "vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="], - "vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.5", "", { "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg=="], + "vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.18.2", "", { "dependencies": { "vscode-jsonrpc": "9.0.1", "vscode-languageserver-types": "3.18.0" } }, "sha512-XRyDbT0Pp3sSNti3JmxVEUMySWCSi1hhM+/KUlCy1hV1zmrqpM1OwO12EAki8blhmLuIMpaJrYbo0OzGVfK2Qg=="], "vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.12", "", {}, "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="], @@ -5596,7 +5552,7 @@ "which-pm-runs": ["which-pm-runs@1.1.0", "", {}, "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA=="], - "which-typed-array": ["which-typed-array@1.1.21", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw=="], + "which-typed-array": ["which-typed-array@1.1.22", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw=="], "why-is-node-running": ["why-is-node-running@3.2.2", "", { "bin": { "why-is-node-running": "cli.js" } }, "sha512-NKUzAelcoCXhXL4dJzKIwXeR8iEVqsA0Lq6Vnd0UXvgaKbzVo4ZTHROF2Jidrv+SgxOQ03fMinnNhzZATxOD3A=="], @@ -5638,7 +5594,7 @@ "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], - "yaml-language-server": ["yaml-language-server@1.20.0", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "prettier": "^3.5.0", "request-light": "^0.5.7", "vscode-json-languageservice": "4.1.8", "vscode-languageserver": "^9.0.0", "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "^3.16.0", "vscode-uri": "^3.0.2", "yaml": "2.7.1" }, "bin": { "yaml-language-server": "bin/yaml-language-server" } }, "sha512-qhjK/bzSRZ6HtTvgeFvjNPJGWdZ0+x5NREV/9XZWFjIGezew2b4r5JPy66IfOhd5OA7KeFwk1JfmEbnTvev0cA=="], + "yaml-language-server": ["yaml-language-server@1.23.0", "", { "dependencies": { "@vscode/l10n": "^0.0.18", "ajv": "^8.17.1", "ajv-draft-04": "^1.0.0", "ajv-i18n": "^4.2.0", "prettier": "^3.8.1", "request-light": "^0.5.7", "vscode-json-languageservice": "4.1.8", "vscode-languageserver": "^9.0.0", "vscode-languageserver-textdocument": "^1.0.1", "vscode-languageserver-types": "^3.16.0", "vscode-uri": "^3.0.2", "yaml": "2.8.3" }, "bin": { "yaml-language-server": "bin/yaml-language-server" } }, "sha512-3qVyCOexLCWw06PQa5kRPwvMWMZ/eZeCRWUvgD6a0OkqL/4iCnxy2WumbWifa937Uo5xhyWJ0uxlU39ljhNh7A=="], "yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="], @@ -5652,8 +5608,6 @@ "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="], - "yoga-layout": ["yoga-layout@3.2.1", "", {}, "sha512-0LPOt3AxKqMdFBZA3HBAt/t/8vIKq7VaQYbuA8WxCgung+p9TVyKRYdpvCb80HcdTN2NkbIKbhNwKUfm3tQywQ=="], - "youch": ["youch@4.1.0-beta.10", "", { "dependencies": { "@poppinss/colors": "^4.1.5", "@poppinss/dumper": "^0.6.4", "@speed-highlight/core": "^1.2.7", "cookie": "^1.0.2", "youch-core": "^0.3.3" } }, "sha512-rLfVLB4FgQneDr0dv1oddCVZmKjcJ6yX6mS4pU82Mq/Dt9a3cLZQ62pDBL4AUO+uVrCvtWz3ZFUL2HFAFJ/BXQ=="], "youch-core": ["youch-core@0.3.3", "", { "dependencies": { "@poppinss/exception": "^1.2.2", "error-stack-parser-es": "^1.0.5" } }, "sha512-ho7XuGjLaJ2hWHoK8yFnsUGy2Y5uDpqSTq1FkHLK4/oqKtyUU1AFbOOxY4IpC9f0fTLjwYbslUz0Po5BpD1wrA=="], @@ -5682,7 +5636,7 @@ "@actions/github/undici": ["undici@5.29.0", "", { "dependencies": { "@fastify/busboy": "^2.0.0" } }, "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg=="], - "@actions/http-client/undici": ["undici@6.26.0", "", {}, "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A=="], + "@actions/http-client/undici": ["undici@6.27.0", "", {}, "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg=="], "@ai-sdk/alibaba/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], @@ -5708,25 +5662,25 @@ "@ai-sdk/cohere/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], - "@ai-sdk/deepgram/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + "@ai-sdk/deepgram/@ai-sdk/provider": ["@ai-sdk/provider@3.0.13", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-ZPtVYt5QIJzOta1kdUiDuCx4HhFkvNPv/rvmZ2b1iXwybYjJsCnNYR4PAw4kW7rgVfDARvHXcU64efWuqNp6bw=="], - "@ai-sdk/deepgram/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], + "@ai-sdk/deepgram/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.35", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bjYld/2KGPLt78kpqbya+fD4LYS7BqVQJyUjE3qAHrYB0FR2Q90BaWEVIBZaguTWXf/A8L6uG1zO1v9TxVlGWg=="], "@ai-sdk/deepinfra/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw=="], - "@ai-sdk/deepseek/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + "@ai-sdk/deepseek/@ai-sdk/provider": ["@ai-sdk/provider@3.0.13", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-ZPtVYt5QIJzOta1kdUiDuCx4HhFkvNPv/rvmZ2b1iXwybYjJsCnNYR4PAw4kW7rgVfDARvHXcU64efWuqNp6bw=="], - "@ai-sdk/deepseek/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], + "@ai-sdk/deepseek/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.35", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bjYld/2KGPLt78kpqbya+fD4LYS7BqVQJyUjE3qAHrYB0FR2Q90BaWEVIBZaguTWXf/A8L6uG1zO1v9TxVlGWg=="], - "@ai-sdk/elevenlabs/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + "@ai-sdk/elevenlabs/@ai-sdk/provider": ["@ai-sdk/provider@3.0.13", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-ZPtVYt5QIJzOta1kdUiDuCx4HhFkvNPv/rvmZ2b1iXwybYjJsCnNYR4PAw4kW7rgVfDARvHXcU64efWuqNp6bw=="], - "@ai-sdk/elevenlabs/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], + "@ai-sdk/elevenlabs/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.35", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bjYld/2KGPLt78kpqbya+fD4LYS7BqVQJyUjE3qAHrYB0FR2Q90BaWEVIBZaguTWXf/A8L6uG1zO1v9TxVlGWg=="], - "@ai-sdk/fireworks/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.48", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-z9MC6M4Oh/yUY/F/eszOtO8wc2nMz99XmZQKd2gWTtyIfe716xTfrKe3aYZKg20NZDtyjqPPKPSR+wqz7q1T7Q=="], + "@ai-sdk/fireworks/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.56", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@ai-sdk/provider-utils": "4.0.35" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cQrN6OUn/jvsY3OdsU6Wn+ss7vp1iwIcakZKSlSRMnYqShBfyT7Qht+eqmgxs7w9ttrw6FAG6o11AiBs+iEsTA=="], - "@ai-sdk/fireworks/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + "@ai-sdk/fireworks/@ai-sdk/provider": ["@ai-sdk/provider@3.0.13", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-ZPtVYt5QIJzOta1kdUiDuCx4HhFkvNPv/rvmZ2b1iXwybYjJsCnNYR4PAw4kW7rgVfDARvHXcU64efWuqNp6bw=="], - "@ai-sdk/fireworks/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], + "@ai-sdk/fireworks/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.35", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bjYld/2KGPLt78kpqbya+fD4LYS7BqVQJyUjE3qAHrYB0FR2Q90BaWEVIBZaguTWXf/A8L6uG1zO1v9TxVlGWg=="], "@ai-sdk/google/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], @@ -5758,61 +5712,59 @@ "@ai-sdk/xai/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], - "@astrojs/check/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + "@astrojs/check/yargs": ["yargs@17.7.3", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g=="], - "@astrojs/cloudflare/vite": ["vite@6.4.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ=="], + "@astrojs/cloudflare/vite": ["vite@6.4.3", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A=="], "@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], - "@astrojs/markdown-remark/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "@astrojs/markdown-remark/js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], - "@astrojs/markdown-remark/shiki": ["shiki@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/engine-javascript": "3.20.0", "@shikijs/engine-oniguruma": "3.20.0", "@shikijs/langs": "3.20.0", "@shikijs/themes": "3.20.0", "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kgCOlsnyWb+p0WU+01RjkCH+eBVsjL1jOwUYWv0YDWkM2/A46+LDKVs5yZCUXjJG6bj4ndFoAg5iLIIue6dulg=="], + "@astrojs/markdown-remark/shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], "@astrojs/mdx/@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.11", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.6", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.1", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.21.0", "smol-toml": "^1.6.0", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.2", "vfile": "^6.0.3" } }, "sha512-hcaxX/5aC6lQgHeGh1i+aauvSwIT6cfyFjKWvExYSxUhZZBBdvCliOtu06gbQyhbe0pGJNoNmqNlQZ5zYUuIyQ=="], - "@astrojs/mdx/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - "@astrojs/mdx/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], "@astrojs/sitemap/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], - "@astrojs/solid-js/vite": ["vite@6.4.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ=="], + "@astrojs/solid-js/vite": ["vite@6.4.3", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A=="], - "@astrojs/starlight/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "@astrojs/starlight/js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], - "@aws-crypto/crc32/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-crypto/crc32/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-crypto/crc32c/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-crypto/crc32c/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-crypto/sha1-browser/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-crypto/sha1-browser/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], "@aws-crypto/sha1-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], - "@aws-crypto/sha256-browser/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-crypto/sha256-browser/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], "@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], - "@aws-crypto/sha256-js/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-crypto/sha256-js/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-crypto/util/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-crypto/util/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], "@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="], "@aws-sdk/client-athena/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], - "@aws-sdk/client-cognito-identity/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/client-cognito-identity/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/client-cognito-identity/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.47", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.41", "@aws-sdk/credential-provider-http": "^3.972.43", "@aws-sdk/credential-provider-ini": "^3.972.46", "@aws-sdk/credential-provider-process": "^3.972.41", "@aws-sdk/credential-provider-sso": "^3.972.45", "@aws-sdk/credential-provider-web-identity": "^3.972.45", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/credential-provider-imds": "^4.3.6", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-HrId+C0DWA5qDIyLG64/kjUB2RNtPypxmABnIctK+TA1P1kHlOYoE/Wf5T5tKOMKgb08P7k/zNyhvfJ3lh5Oag=="], + "@aws-sdk/client-cognito-identity/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.62", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.53", "@aws-sdk/credential-provider-http": "^3.972.55", "@aws-sdk/credential-provider-ini": "^3.972.60", "@aws-sdk/credential-provider-process": "^3.972.53", "@aws-sdk/credential-provider-sso": "^3.972.59", "@aws-sdk/credential-provider-web-identity": "^3.972.59", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/credential-provider-imds": "^4.4.5", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-S6Slq3Tx7bvFk5yc34XNADyZYTX2HUXvaFAnowGRQnhjBO8J/mP62Fn7lxvJwjaDyYm/7gh9h6HEHaltRyMFXw=="], - "@aws-sdk/client-cognito-identity/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/client-cognito-identity/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], "@aws-sdk/client-firehose/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], - "@aws-sdk/client-lambda/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/client-lambda/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.47", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.41", "@aws-sdk/credential-provider-http": "^3.972.43", "@aws-sdk/credential-provider-ini": "^3.972.46", "@aws-sdk/credential-provider-process": "^3.972.41", "@aws-sdk/credential-provider-sso": "^3.972.45", "@aws-sdk/credential-provider-web-identity": "^3.972.45", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/credential-provider-imds": "^4.3.6", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-HrId+C0DWA5qDIyLG64/kjUB2RNtPypxmABnIctK+TA1P1kHlOYoE/Wf5T5tKOMKgb08P7k/zNyhvfJ3lh5Oag=="], + "@aws-sdk/client-lambda/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.62", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.53", "@aws-sdk/credential-provider-http": "^3.972.55", "@aws-sdk/credential-provider-ini": "^3.972.60", "@aws-sdk/credential-provider-process": "^3.972.53", "@aws-sdk/credential-provider-sso": "^3.972.59", "@aws-sdk/credential-provider-web-identity": "^3.972.59", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/credential-provider-imds": "^4.4.5", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-S6Slq3Tx7bvFk5yc34XNADyZYTX2HUXvaFAnowGRQnhjBO8J/mP62Fn7lxvJwjaDyYm/7gh9h6HEHaltRyMFXw=="], - "@aws-sdk/client-lambda/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/client-lambda/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], "@aws-sdk/client-s3/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], @@ -5844,23 +5796,23 @@ "@aws-sdk/core/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], - "@aws-sdk/credential-provider-cognito-identity/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/credential-provider-cognito-identity/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-sdk/credential-provider-env/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/credential-provider-env/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/credential-provider-env/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/credential-provider-env/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-sdk/credential-provider-http/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/credential-provider-http/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/credential-provider-http/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/credential-provider-http/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-sdk/credential-provider-ini/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/credential-provider-ini/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/credential-provider-ini/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/credential-provider-ini/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-sdk/credential-provider-login/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/credential-provider-login/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/credential-provider-login/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/credential-provider-login/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], "@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.932.0", "", { "dependencies": { "@aws-sdk/core": "3.932.0", "@aws-sdk/types": "3.930.0", "@smithy/property-provider": "^4.2.5", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-ozge/c7NdHUDyHqro6+P5oHt8wfKSUBN+olttiVfBe9Mw3wBMpPa3gQ0pZnG+gwBkKskBuip2bMR16tqYvUSEA=="], @@ -5874,37 +5826,37 @@ "@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.933.0", "", { "dependencies": { "@aws-sdk/core": "3.932.0", "@aws-sdk/nested-clients": "3.933.0", "@aws-sdk/types": "3.930.0", "@smithy/property-provider": "^4.2.5", "@smithy/shared-ini-file-loader": "^4.4.0", "@smithy/types": "^4.9.0", "tslib": "^2.6.2" } }, "sha512-c7Eccw2lhFx2/+qJn3g+uIDWRuWi2A6Sz3PVvckFUEzPsP0dPUo19hlvtarwP5GzrsXn0yEPRVhpewsIaSCGaQ=="], - "@aws-sdk/credential-provider-process/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/credential-provider-process/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/credential-provider-process/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/credential-provider-process/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-sdk/credential-provider-sso/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/credential-provider-sso/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/credential-provider-sso/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/credential-provider-sso/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-sdk/credential-provider-web-identity/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/credential-provider-web-identity/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/credential-provider-web-identity/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/credential-provider-web-identity/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-sdk/credential-providers/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/credential-providers/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/credential-providers/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.47", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.41", "@aws-sdk/credential-provider-http": "^3.972.43", "@aws-sdk/credential-provider-ini": "^3.972.46", "@aws-sdk/credential-provider-process": "^3.972.41", "@aws-sdk/credential-provider-sso": "^3.972.45", "@aws-sdk/credential-provider-web-identity": "^3.972.45", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/credential-provider-imds": "^4.3.6", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-HrId+C0DWA5qDIyLG64/kjUB2RNtPypxmABnIctK+TA1P1kHlOYoE/Wf5T5tKOMKgb08P7k/zNyhvfJ3lh5Oag=="], + "@aws-sdk/credential-providers/@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.62", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.53", "@aws-sdk/credential-provider-http": "^3.972.55", "@aws-sdk/credential-provider-ini": "^3.972.60", "@aws-sdk/credential-provider-process": "^3.972.53", "@aws-sdk/credential-provider-sso": "^3.972.59", "@aws-sdk/credential-provider-web-identity": "^3.972.59", "@aws-sdk/types": "^3.973.15", "@smithy/core": "^3.29.0", "@smithy/credential-provider-imds": "^4.4.5", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-S6Slq3Tx7bvFk5yc34XNADyZYTX2HUXvaFAnowGRQnhjBO8J/mP62Fn7lxvJwjaDyYm/7gh9h6HEHaltRyMFXw=="], - "@aws-sdk/credential-providers/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/credential-providers/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], "@aws-sdk/middleware-flexible-checksums/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], "@aws-sdk/middleware-sdk-s3/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], - "@aws-sdk/nested-clients/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/nested-clients/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/nested-clients/@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.30", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-HULDLMVzkmTSEv6//7kx2kRevp/VYUpm8hJNNFbmhxDn0fUiGTxVcM9yg31TukvTq8nyOBDUN2gH0o5IRbKjdw=="], + "@aws-sdk/nested-clients/@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.38", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-C379Sk+MiFZCfWZphKlMyLHKxV22OjoGM5KJjj5IJNJcOCWL4IGIpnEGzv1FQiRwhYXfq55SJMfxlqPE08JJ9g=="], - "@aws-sdk/nested-clients/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/nested-clients/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], - "@aws-sdk/token-providers/@aws-sdk/core": ["@aws-sdk/core@3.974.15", "", { "dependencies": { "@aws-sdk/types": "^3.973.9", "@aws-sdk/xml-builder": "^3.972.26", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/core": "^3.24.5", "@smithy/signature-v4": "^5.4.5", "@smithy/types": "^4.14.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-UpA0rTGW/tHGITcCqHisbuuEPraYg9GG+mWmXjY5+RxZBMLGe6aL9oe0ix50LztwAcPIkGZLH0yWdMIkCM10hw=="], + "@aws-sdk/token-providers/@aws-sdk/core": ["@aws-sdk/core@3.974.27", "", { "dependencies": { "@aws-sdk/types": "^3.973.15", "@aws-sdk/xml-builder": "^3.972.33", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.29.0", "@smithy/signature-v4": "^5.6.1", "@smithy/types": "^4.15.1", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-WRWEgIq6vx+NU6ot3VrRu4Jovj9MIObitSi6of/GV5THDDPccBhivCRNkWJutMM+m3GvdeI3l/UbGNcoOobxOA=="], - "@aws-sdk/token-providers/@aws-sdk/types": ["@aws-sdk/types@3.973.9", "", { "dependencies": { "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-kuBfgQVdcz5Bmapc4A13YbpVw/pXkesfhetcFYwbntqas8sF41OHyd4o28+/TG2ZQdHBsv90Lsu5y6oitvYCdg=="], + "@aws-sdk/token-providers/@aws-sdk/types": ["@aws-sdk/types@3.973.15", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-IULn8uBV/SMtmOIANsm4WHXIOtVPBWfOWs3WGL0j/sI+KhaYehvOw0ET+9urnn8MBpiijuU/0JOpuwKOE451PQ=="], "@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.2.5", "", { "dependencies": { "strnum": "^2.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ=="], @@ -5914,7 +5866,7 @@ "@azure/core-http/uuid": ["uuid@8.3.2", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="], - "@azure/core-xml/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], + "@azure/core-xml/fast-xml-parser": ["fast-xml-parser@5.9.3", "", { "dependencies": { "@nodable/entities": "^2.2.0", "fast-xml-builder": "^1.2.0", "is-unsafe": "^1.0.1", "path-expression-matcher": "^1.5.0", "strnum": "^2.4.1", "xml-naming": "^0.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-brCNCeScma/kqa54J4PIDriSSSLssRkuYaUCpvHJulGc3HGI/xxKUCTDcYkAdqJsyb//ydpbxecjC3hB9+tb/g=="], "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], @@ -5932,8 +5884,6 @@ "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], - "@develar/schema-utils/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], - "@dot/log/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "@electron/asar/commander": ["commander@5.1.0", "", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="], @@ -5946,29 +5896,31 @@ "@electron/fuses/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], - "@electron/get/undici": ["undici@7.26.0", "", {}, "sha512-3O9Tf67pGhgOv9jM35AbhkXAKi13f3oy3aE4CSgr+TckGeY+/iu97ZXN+J7DpHPzLbVApFd1IFhcnBjREYXYcg=="], + "@electron/get/undici": ["undici@7.28.0", "", {}, "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA=="], "@electron/notarize/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], "@electron/osx-sign/isbinaryfile": ["isbinaryfile@4.0.10", "", {}, "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw=="], - "@electron/universal/fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="], + "@electron/universal/fs-extra": ["fs-extra@11.3.1", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g=="], "@electron/universal/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], - "@electron/windows-sign/fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="], + "@electron/windows-sign/fs-extra": ["fs-extra@11.3.1", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g=="], "@expressive-code/plugin-shiki/shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], "@fastify/proxy-addr/ipaddr.js": ["ipaddr.js@2.4.0", "", {}, "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ=="], - "@hey-api/json-schema-ref-parser/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "@gitlab/opencode-gitlab-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], + + "@hey-api/json-schema-ref-parser/js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], "@hey-api/openapi-ts/open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="], "@hey-api/openapi-ts/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - "@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + "@img/sharp-wasm32/@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="], "@jsx-email/cli/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -5982,35 +5934,31 @@ "@malept/flatpak-bundler/fs-extra": ["fs-extra@9.1.0", "", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], - "@mdx-js/mdx/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - "@mdx-js/mdx/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], - "@modelcontextprotocol/sdk/hono": ["hono@4.12.23", "", {}, "sha512-eIaZ9qDgu7XV0pxOCrg7/WhnQ6Ivm22UcxhXx/A3dcbqbbYgBEkc6e/J/s7j2tS96zoB0S9VBdLwQNCWwUo4LA=="], + "@modelcontextprotocol/sdk/hono": ["hono@4.12.27", "", {}, "sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q=="], "@modelcontextprotocol/sdk/jose": ["jose@6.2.3", "", {}, "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw=="], - "@modelcontextprotocol/sdk/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], - "@npmcli/config/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="], "@npmcli/git/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="], - "@npmcli/query/postcss-selector-parser": ["postcss-selector-parser@7.1.1", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg=="], + "@npmcli/query/postcss-selector-parser": ["postcss-selector-parser@7.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg=="], - "@octokit/auth-app/@octokit/request": ["@octokit/request@10.0.10", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w=="], + "@octokit/auth-app/@octokit/request": ["@octokit/request@10.0.11", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q=="], "@octokit/auth-app/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], - "@octokit/auth-oauth-app/@octokit/request": ["@octokit/request@10.0.10", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w=="], + "@octokit/auth-oauth-app/@octokit/request": ["@octokit/request@10.0.11", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q=="], "@octokit/auth-oauth-app/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - "@octokit/auth-oauth-device/@octokit/request": ["@octokit/request@10.0.10", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w=="], + "@octokit/auth-oauth-device/@octokit/request": ["@octokit/request@10.0.11", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q=="], "@octokit/auth-oauth-device/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], - "@octokit/auth-oauth-user/@octokit/request": ["@octokit/request@10.0.10", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w=="], + "@octokit/auth-oauth-user/@octokit/request": ["@octokit/request@10.0.11", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q=="], "@octokit/auth-oauth-user/@octokit/types": ["@octokit/types@16.0.0", "", { "dependencies": { "@octokit/openapi-types": "^27.0.0" } }, "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg=="], @@ -6024,11 +5972,11 @@ "@octokit/endpoint/universal-user-agent": ["universal-user-agent@6.0.1", "", {}, "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ=="], - "@octokit/graphql/@octokit/request": ["@octokit/request@10.0.10", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w=="], + "@octokit/graphql/@octokit/request": ["@octokit/request@10.0.11", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q=="], "@octokit/graphql/@octokit/types": ["@octokit/types@15.0.2", "", { "dependencies": { "@octokit/openapi-types": "^26.0.0" } }, "sha512-rR+5VRjhYSer7sC51krfCctQhVTmjyUMAaShfPB8mscVa8tSoLyon3coxQmXu0ahJoLVWl8dSGD/3OGZlFV44Q=="], - "@octokit/oauth-methods/@octokit/request": ["@octokit/request@10.0.10", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w=="], + "@octokit/oauth-methods/@octokit/request": ["@octokit/request@10.0.11", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q=="], "@octokit/oauth-methods/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], @@ -6064,8 +6012,6 @@ "@opencode-ai/core/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.41", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-kNAGINk71AlOXx10Dq/PXw4t/9XjdK8uxfpVElRwtSFMdeSiLVt58p9TPx4/FJD+hxZuVhvxYj9r42osxWq79g=="], - "@opencode-ai/core/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], - "@opencode-ai/desktop/@actions/artifact": ["@actions/artifact@4.0.0", "", { "dependencies": { "@actions/core": "^1.10.0", "@actions/github": "^6.0.1", "@actions/http-client": "^2.1.0", "@azure/core-http": "^3.0.5", "@azure/storage-blob": "^12.15.0", "@octokit/core": "^5.2.1", "@octokit/plugin-request-log": "^1.0.4", "@octokit/plugin-retry": "^3.0.9", "@octokit/request": "^8.4.1", "@octokit/request-error": "^5.1.1", "@protobuf-ts/plugin": "^2.2.3-alpha.1", "archiver": "^7.0.1", "jwt-decode": "^3.1.2", "unzip-stream": "^0.3.1" } }, "sha512-HCc2jMJRAfviGFAh0FsOR/jNfWhirxl7W6z8zDtttt0GltwxBLdEIjLiweOPFl9WbyJRW1VWnPUSAixJqcWUMQ=="], "@opencode-ai/desktop/marked": ["marked@15.0.12", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA=="], @@ -6076,8 +6022,6 @@ "@opencode-ai/llm/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], - "@opencode-ai/script/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], - "@opencode-ai/session-ui/@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ=="], "@opencode-ai/ui/@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.3", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.3", "@solid-primitives/rootless": "^1.5.2", "@solid-primitives/static-store": "^0.1.2", "@solid-primitives/utils": "^6.3.2" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zBLje5E06TgOg93S7rGPldmhDnouNGhvfZVKOp+oG2XU8snA+GoCSSCz1M+jpNAg5Ek2EakU5UVQqL152WmdXQ=="], @@ -6090,9 +6034,9 @@ "@oslojs/jwt/@oslojs/encoding": ["@oslojs/encoding@0.4.1", "", {}, "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q=="], - "@oxc-resolver/binding-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], + "@oxc-resolver/binding-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], - "@oxc-resolver/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + "@oxc-resolver/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], "@parcel/watcher/detect-libc": ["detect-libc@1.0.3", "", { "bin": { "detect-libc": "./bin/detect-libc.js" } }, "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg=="], @@ -6146,7 +6090,7 @@ "@slack/web-api/eventemitter3": ["eventemitter3@3.1.2", "", {}, "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q=="], - "@slack/web-api/form-data": ["form-data@2.5.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-jqdObeR2rxZZbPSGL+3VckHMYtu+f9//KXBsVny6JSX/pa38Fy+bGjuG8eW/H6USNQWhLi8Num++cU2yOCNz4A=="], + "@slack/web-api/form-data": ["form-data@2.5.6", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.4", "mime-types": "^2.1.35", "safe-buffer": "^5.2.1" } }, "sha512-Ogz/E85h9tlfJzpI6TuFpGcHZFhLrb9Gw8wq9v40CxSCPnv7ahKr6Xgtkn0KYCDQJ8DNn5VoMO8EXr9V5PadyA=="], "@slack/web-api/p-queue": ["p-queue@6.6.2", "", { "dependencies": { "eventemitter3": "^4.0.4", "p-timeout": "^3.2.0" } }, "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ=="], @@ -6156,17 +6100,15 @@ "@solidjs/start/vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="], - "@standard-community/standard-json/effect": ["effect@4.0.0-beta.74", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.8.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.1", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^14.0.0", "yaml": "^2.9.0" } }, "sha512-Yx+Kh12U+i2FmjwEfKs+ePFmpMd43RPD1oGqc/VraSS9bYzvF0Ff3PojwEFEVEewp8xc92Uxu28gTspU4qyvHA=="], - - "@standard-community/standard-openapi/effect": ["effect@4.0.0-beta.74", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.8.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.1", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^14.0.0", "yaml": "^2.9.0" } }, "sha512-Yx+Kh12U+i2FmjwEfKs+ePFmpMd43RPD1oGqc/VraSS9bYzvF0Ff3PojwEFEVEewp8xc92Uxu28gTspU4qyvHA=="], + "@storybook/builder-vite/@storybook/csf-plugin": ["@storybook/csf-plugin@10.4.4", "", { "dependencies": { "unplugin": "^2.3.5" }, "peerDependencies": { "esbuild": "*", "rollup": "*", "storybook": "^10.4.4", "vite": "*", "webpack": "*" }, "optionalPeers": ["esbuild", "rollup", "vite", "webpack"] }, "sha512-1mzZyAwVUmAcw4WEUsJDVdSupkJf+Kf/f5uNAs4RzlBXA75P8YRkDKAb2EoMwsB5URiXFi9XoeAN/vWke0G6+w=="], "@storybook/csf-plugin/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.10.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" }, "bundled": true }, "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.10.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA=="], - "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w=="], + "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" }, "bundled": true }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], @@ -6184,29 +6126,17 @@ "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], - "@types/plist/xmlbuilder": ["xmlbuilder@15.1.1", "", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], - - "@vitest/coverage-v8/@vitest/utils": ["@vitest/utils@4.1.8", "", { "dependencies": { "@vitest/pretty-format": "4.1.8", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.1.0" } }, "sha512-uOJamYALNhfJ6iolExyQM40yIQwDqYnkKtQ5VCiSe17E33H0aQ/u+1GlRuz4LZBk6Mm3sg90G9hEbmEt37C1Zg=="], - - "@vitest/coverage-v8/magicast": ["magicast@0.5.3", "", { "dependencies": { "@babel/parser": "^7.29.3", "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw=="], - "@vitest/expect/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="], "@vitest/expect/tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="], - "@vitest/mocker/@vitest/spy": ["@vitest/spy@4.1.7", "", {}, "sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q=="], + "@vitest/mocker/@vitest/spy": ["@vitest/spy@4.1.9", "", {}, "sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA=="], "@vscode/emmet-helper/jsonc-parser": ["jsonc-parser@2.3.1", "", {}, "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg=="], - "ai-gateway-provider/@ai-sdk/amazon-bedrock": ["@ai-sdk/amazon-bedrock@4.0.107", "", { "dependencies": { "@ai-sdk/anthropic": "3.0.78", "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27", "@smithy/eventstream-codec": "^4.0.1", "@smithy/util-utf8": "^4.0.0", "aws4fetch": "^1.0.20" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-8nT08pGPy25rleJNk56ep00UHK6kCtCmu+ZNqVVSSPDieADlIZqcaN1iRXAFBoCH0Fb9F6C2EjFDaySdsargfQ=="], + "@vscode/emmet-helper/vscode-languageserver-types": ["vscode-languageserver-types@3.18.0", "", {}, "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g=="], - "ai-gateway-provider/@ai-sdk/anthropic": ["@ai-sdk/anthropic@3.0.78", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-0OY12G20cUt6iU6htpEA1491Oz++NVxZxlmWGX4B7rSbeZ5pnDmOu6YtW9BKzdZlNx5Gn23i6WMxyZFoMKNcgA=="], - - "ai-gateway-provider/@ai-sdk/openai": ["@ai-sdk/openai@3.0.53", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@ai-sdk/provider-utils": "4.0.23" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Wld+Rbc05KaUn08uBt06eEuwcgalcIFtIl32Yp+GxuZXUQwOb6YeAuq+C6da4ch6BurFoqEaLemJVwjBb7x+PQ=="], - - "ai-gateway-provider/@openrouter/ai-sdk-provider": ["@openrouter/ai-sdk-provider@2.8.1", "", { "peerDependencies": { "ai": "^6.0.0", "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Y6j3yivgoEUf/kutD/k5GX/mzZfioRFoSx0gbQ+mIOzMaH/vJv1rCkztiuvlLw5xRYQil7oxHUZvmSfXqOx1NQ=="], - - "ajv-keywords/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], + "ai-gateway-provider/@ai-sdk/openai": ["@ai-sdk/openai@3.0.67", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@ai-sdk/provider-utils": "4.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-oAiGC9eWG7IgtdsdS74bOCnAAHarAfTJhWN9x5INwnWPekL802AvF+0I5DvLzIF1MIRmNw4N8mPSL/GUVbX9Mw=="], "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -6218,9 +6148,9 @@ "app-builder-lib/hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="], - "app-builder-lib/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "app-builder-lib/js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], - "app-builder-lib/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + "app-builder-lib/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "app-builder-lib/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], @@ -6228,23 +6158,19 @@ "archiver-utils/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], - "ast-v8-to-istanbul/js-tokens": ["js-tokens@10.0.0", "", {}, "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q=="], - "astro/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="], - "astro/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - "astro/common-ancestor-path": ["common-ancestor-path@1.0.1", "", {}, "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w=="], "astro/diff": ["diff@5.2.2", "", {}, "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A=="], - "astro/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "astro/js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], - "astro/shiki": ["shiki@3.20.0", "", { "dependencies": { "@shikijs/core": "3.20.0", "@shikijs/engine-javascript": "3.20.0", "@shikijs/engine-oniguruma": "3.20.0", "@shikijs/langs": "3.20.0", "@shikijs/themes": "3.20.0", "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-kgCOlsnyWb+p0WU+01RjkCH+eBVsjL1jOwUYWv0YDWkM2/A46+LDKVs5yZCUXjJG6bj4ndFoAg5iLIIue6dulg=="], + "astro/shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], "astro/unstorage": ["unstorage@1.17.5", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.10", "lru-cache": "^11.2.7", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg=="], - "astro/vite": ["vite@6.4.2", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ=="], + "astro/vite": ["vite@6.4.3", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NTKlcQjlAK7MlQoyb6LgaqHc8sso/pVyUJYWMws3jg21uTJw/LddqIFPcPqP6PzpgbIcZyKI85sFE4HBrQDA8A=="], "astro/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -6254,9 +6180,11 @@ "babel-plugin-module-resolver/glob": ["glob@9.3.5", "", { "dependencies": { "fs.realpath": "^1.0.0", "minimatch": "^8.0.2", "minipass": "^4.2.4", "path-scurry": "^1.6.1" } }, "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q=="], + "body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], + "builder-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "builder-util/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "builder-util/js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], @@ -6272,17 +6200,13 @@ "config-chain/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], - "crc/buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], - "cross-spawn/which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], "dir-compare/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], "dir-compare/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - "dmg-builder/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - - "dmg-license/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], + "dmg-builder/js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], @@ -6298,11 +6222,7 @@ "electron-builder/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - "electron-builder/yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], - - "electron-builder-squirrel-windows/app-builder-lib": ["app-builder-lib@26.8.1", "", { "dependencies": { "@develar/schema-utils": "~2.6.5", "@electron/asar": "3.4.1", "@electron/fuses": "^1.8.0", "@electron/get": "^3.0.0", "@electron/notarize": "2.5.0", "@electron/osx-sign": "1.3.3", "@electron/rebuild": "^4.0.3", "@electron/universal": "2.0.3", "@malept/flatpak-bundler": "^0.4.0", "@types/fs-extra": "9.0.13", "async-exit-hook": "^2.0.1", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chromium-pickle-js": "^0.2.0", "ci-info": "4.3.1", "debug": "^4.3.4", "dotenv": "^16.4.5", "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", "electron-publish": "26.8.1", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "isbinaryfile": "^5.0.0", "jiti": "^2.4.2", "js-yaml": "^4.1.0", "json5": "^2.2.3", "lazy-val": "^1.0.5", "minimatch": "^10.0.3", "plist": "3.1.0", "proper-lockfile": "^4.1.2", "resedit": "^1.7.0", "semver": "~7.7.3", "tar": "^7.5.7", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0", "which": "^5.0.0" }, "peerDependencies": { "dmg-builder": "26.8.1", "electron-builder-squirrel-windows": "26.8.1" } }, "sha512-p0Im/Dx5C4tmz8QEE1Yn4MkuPC8PrnlRneMhWJj7BBXQfNTJUshM/bp3lusdEsDbvvfJZpXWnYesgSLvwtM2Zw=="], - - "electron-builder-squirrel-windows/builder-util": ["builder-util@26.8.1", "", { "dependencies": { "7zip-bin": "~5.2.0", "@types/debug": "^4.1.6", "app-builder-bin": "5.0.0-alpha.12", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "cross-spawn": "^7.0.6", "debug": "^4.3.4", "fs-extra": "^10.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "js-yaml": "^4.1.0", "sanitize-filename": "^1.6.3", "source-map-support": "^0.5.19", "stat-mode": "^1.0.0", "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0" } }, "sha512-pm1lTYbGyc90DHgCDO7eo8Rl4EqKLciayNbZqGziqnH9jrlKe8ZANGdityLZU+pJh16dfzjAx2xQq9McuIPEtw=="], + "electron-builder/yargs": ["yargs@17.7.3", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g=="], "electron-publish/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -6310,18 +6230,12 @@ "electron-store/type-fest": ["type-fest@5.7.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg=="], - "electron-updater/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "electron-updater/js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], - "electron-updater/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + "electron-updater/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], "electron-winstaller/fs-extra": ["fs-extra@7.0.1", "", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], - "encoding/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - - "engine.io-client/ws": ["ws@8.20.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w=="], - - "esast-util-from-js/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - "esbuild-plugin-copy/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], "esbuild-plugin-copy/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], @@ -6344,7 +6258,11 @@ "gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], - "gitlab-ai-provider/openai": ["openai@6.39.1", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-z3dO9fEWOXBzlXynVb/xZ/tujzUjFWQWn3C0n0mw6Vo0zJTbEkaN4b2cLWjhJ6haJQx8LlREoafHRl+Gu/Hl+A=="], + "gcp-metadata/gaxios": ["gaxios@7.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "rimraf": "^5.0.1" } }, "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ=="], + + "gcp-metadata/google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], + + "gitlab-ai-provider/openai": ["openai@6.45.0", "", { "peerDependencies": { "@aws-sdk/credential-provider-node": ">=3.972.0 <4", "@smithy/hash-node": ">=4.3.0 <5", "@smithy/signature-v4": ">=5.4.0 <6", "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["@aws-sdk/credential-provider-node", "@smithy/hash-node", "@smithy/signature-v4", "ws", "zod"] }, "sha512-5DQVNErssk0afNpTTHUm/qZPU4iKR9OYdNid8Ib4puq4gHNNvGWZht2zY4h9a8JMF949Ik6m8gQutllVPbjdnw=="], "gitlab-ai-provider/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], @@ -6358,12 +6276,6 @@ "htmlparser2/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], - "iconv-corefoundation/cli-truncate": ["cli-truncate@2.1.0", "", { "dependencies": { "slice-ansi": "^3.0.0", "string-width": "^4.2.0" } }, "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg=="], - - "iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="], - - "istanbul-reports/html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="], - "js-beautify/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "js-beautify/nopt": ["nopt@7.2.1", "", { "dependencies": { "abbrev": "^2.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w=="], @@ -6378,8 +6290,6 @@ "md-to-react-email/marked": ["marked@7.0.4", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ=="], - "micromark-extension-mdxjs/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], @@ -6394,15 +6304,15 @@ "minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "motion/framer-motion": ["framer-motion@12.40.0", "", { "dependencies": { "motion-dom": "^12.40.0", "motion-utils": "^12.39.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-uaBd3qC1v3KQqBEjwTUd183K6PbS+j0yR9w9VmEOLWA/tnUcSn8Xa3uck7t4dgpDoUss8xQTcj8W2L07lrnLFg=="], + "motion/framer-motion": ["framer-motion@12.42.2", "", { "dependencies": { "motion-dom": "^12.42.2", "motion-utils": "^12.39.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-5XY9luDiu0oHfHBjpDthFMh0ES+122w6p/papSJBweMkO8Sn+PW2QaEgRblQBpWFnuvZS5qvarpt/hO2pjGmnw=="], "nitro/h3": ["h3@2.0.1-rc.5", "", { "dependencies": { "rou3": "^0.7.9", "srvx": "^0.9.1" }, "peerDependencies": { "crossws": "^0.4.1" }, "optionalPeers": ["crossws"] }, "sha512-qkohAzCab0nLzXNm78tBjZDvtKMTmtygS8BJLT3VPczAQofdqlFXDPkXdLMJN4r05+xqneG8snZJ0HgkERCZTg=="], - "nitro/undici": ["undici@7.26.0", "", {}, "sha512-3O9Tf67pGhgOv9jM35AbhkXAKi13f3oy3aE4CSgr+TckGeY+/iu97ZXN+J7DpHPzLbVApFd1IFhcnBjREYXYcg=="], + "nitro/undici": ["undici@7.28.0", "", {}, "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA=="], "node-gyp/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], - "node-gyp/undici": ["undici@6.26.0", "", {}, "sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A=="], + "node-gyp/undici": ["undici@6.27.0", "", {}, "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg=="], "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], @@ -6418,10 +6328,10 @@ "opencode/minimatch": ["minimatch@10.0.3", "", { "dependencies": { "@isaacs/brace-expansion": "^5.0.0" } }, "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw=="], - "opencode/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], - "opencode-gitlab-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], + "opencode-poe-auth/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], + "openid-client/jose": ["jose@4.15.9", "", {}, "sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA=="], "openid-client/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], @@ -6462,7 +6372,7 @@ "readdir-glob/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], - "rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="], "roarr/sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], @@ -6486,6 +6396,10 @@ "storybook/open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="], + "storybook-solidjs-vite/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + + "storybook-solidjs-vite/vite": ["vite@7.1.10", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA=="], + "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -6496,7 +6410,7 @@ "tar/yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], - "terser/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], + "temp/rimraf": ["rimraf@2.6.3", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "./bin.js" } }, "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="], "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], @@ -6506,7 +6420,7 @@ "topojson-client/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], - "tree-sitter-bash/node-addon-api": ["node-addon-api@8.8.0", "", {}, "sha512-c5Ko1fZJIJmzhFIkhRN76WTq+fC6tWnGy9CXA0fA+XygsWZmEwG8vmbkNqxMyoaa0Tin4djul49NzdVcJJcjeA=="], + "tree-sitter-bash/node-addon-api": ["node-addon-api@8.9.0", "", {}, "sha512-ekZMeaaIzSQTSpr7X2X3iJM7lTzgnx8ahAG9pJfT/7+14mlEM8ZYQ9cgCDvSSRbReFK0oHli3WrZdCiRsgAT9Q=="], "tw-to-css/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], @@ -6516,31 +6430,25 @@ "unifont/ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], - "unplugin/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], - "unplugin/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "unused-filename/path-exists": ["path-exists@5.0.0", "", {}, "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ=="], - "unzipper/fs-extra": ["fs-extra@11.3.5", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg=="], + "unzipper/fs-extra": ["fs-extra@11.3.1", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g=="], - "venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.53", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@ai-sdk/provider-utils": "4.0.32" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-SoPSkrL5cbNQnAljRsJ7pOzJ2FmWgnhC0lfFOda873ycCdFJL1A+h3Ib7mX2spcv3XnNaO13y/45/0RyqNWlIQ=="], + "venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.56", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@ai-sdk/provider-utils": "4.0.35" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-cQrN6OUn/jvsY3OdsU6Wn+ss7vp1iwIcakZKSlSRMnYqShBfyT7Qht+eqmgxs7w9ttrw6FAG6o11AiBs+iEsTA=="], "venice-ai-sdk-provider/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], - "venice-ai-sdk-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.32", "", { "dependencies": { "@ai-sdk/provider": "3.0.12", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-Kwj499fTcN9bP/AfGoPU7JWIXeP6VZqKI6omsH062c9E2G4gdjeJczkz4z/tYSkzYjLE2AI3DtZbMfs6D7vn2Q=="], - - "verror/core-util-is": ["core-util-is@1.0.2", "", {}, "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="], - - "vite-plugin-dynamic-import/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], + "venice-ai-sdk-provider/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.35", "", { "dependencies": { "@ai-sdk/provider": "3.0.13", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-bjYld/2KGPLt78kpqbya+fD4LYS7BqVQJyUjE3qAHrYB0FR2Q90BaWEVIBZaguTWXf/A8L6uG1zO1v9TxVlGWg=="], "vite-plugin-icons-spritesheet/glob": ["glob@11.1.0", "", { "dependencies": { "foreground-child": "^3.3.1", "jackspeak": "^4.1.1", "minimatch": "^10.1.1", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^2.0.0" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw=="], - "vitest/@vitest/expect": ["@vitest/expect@4.1.7", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.7", "@vitest/utils": "4.1.7", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w=="], + "vitest/@vitest/expect": ["@vitest/expect@4.1.9", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.9", "@vitest/utils": "4.1.9", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA=="], - "vitest/@vitest/spy": ["@vitest/spy@4.1.7", "", {}, "sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q=="], + "vitest/@vitest/spy": ["@vitest/spy@4.1.9", "", {}, "sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA=="], - "vitest/es-module-lexer": ["es-module-lexer@2.1.0", "", {}, "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ=="], + "vitest/es-module-lexer": ["es-module-lexer@2.3.0", "", {}, "sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw=="], "vitest/tinyexec": ["tinyexec@1.2.4", "", {}, "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg=="], @@ -6548,7 +6456,13 @@ "vitest/why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], - "vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="], + "vscode-json-languageservice/vscode-languageserver-types": ["vscode-languageserver-types@3.18.0", "", {}, "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g=="], + + "vscode-languageserver/vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.5", "", { "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg=="], + + "vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@9.0.1", "", {}, "sha512-rfuA6T75H6m5EkbhtEPzre9pT0HPcDI2MMy4+nPFIBks5J8JBAUHD4tRYSgaBOijIEC7SRkC1kKyXTLqbmh9jw=="], + + "vscode-languageserver-protocol/vscode-languageserver-types": ["vscode-languageserver-types@3.18.0", "", {}, "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g=="], "wrangler/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], @@ -6558,9 +6472,13 @@ "wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + "yaml-language-server/prettier": ["prettier@3.9.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-yWG/o/4oJfo036EKAfK6ACAoDOfHeRHx4tuxkfBZiauURiaSmYwlpOr5LQqKtIkRD2z1PLteme2WoxEnj4tHTg=="], + "yaml-language-server/request-light": ["request-light@0.5.8", "", {}, "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg=="], - "yaml-language-server/yaml": ["yaml@2.7.1", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ=="], + "yaml-language-server/vscode-languageserver-types": ["vscode-languageserver-types@3.18.0", "", {}, "sha512-8TsGPNMIMiiBdkORgRSvLjuiEIiAFtO+KssmYWxQ+uSVvlf7RjK8YKCOjPzZ+YA04jXEV7+7LvkSmHkhpNS99g=="], + + "yaml-language-server/yaml": ["yaml@2.8.3", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="], "yargs/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="], @@ -6620,23 +6538,23 @@ "@astrojs/markdown-remark/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "@astrojs/markdown-remark/shiki/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], + "@astrojs/markdown-remark/shiki/@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], - "@astrojs/markdown-remark/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg=="], + "@astrojs/markdown-remark/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="], - "@astrojs/markdown-remark/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-Yx3gy7xLzM0ZOjqoxciHjA7dAt5tyzJE3L4uQoM83agahy+PlW244XJSrmJRSBvGYELDhYXPacD4R/cauV5bzQ=="], + "@astrojs/markdown-remark/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g=="], - "@astrojs/markdown-remark/shiki/@shikijs/langs": ["@shikijs/langs@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-le+bssCxcSHrygCWuOrYJHvjus6zhQ2K7q/0mgjiffRbkhM4o1EWu2m+29l0yEsHDbWaWPNnDUTRVVBvBBeKaA=="], + "@astrojs/markdown-remark/shiki/@shikijs/langs": ["@shikijs/langs@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg=="], - "@astrojs/markdown-remark/shiki/@shikijs/themes": ["@shikijs/themes@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ=="], + "@astrojs/markdown-remark/shiki/@shikijs/themes": ["@shikijs/themes@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA=="], - "@astrojs/markdown-remark/shiki/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], + "@astrojs/markdown-remark/shiki/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], "@astrojs/mdx/@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.6", "", {}, "sha512-GOle7smBWKfMSP8osUIGOlB5kaHdQLV3foCsf+5Q9Wsuu+C6Fs3Ez/ttXmhjZ1HkSgsogcM1RXSjjOVieHq16Q=="], "@astrojs/mdx/@astrojs/markdown-remark/@astrojs/prism": ["@astrojs/prism@3.3.0", "", { "dependencies": { "prismjs": "^1.30.0" } }, "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ=="], - "@astrojs/mdx/@astrojs/markdown-remark/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "@astrojs/mdx/@astrojs/markdown-remark/js-yaml": ["js-yaml@4.3.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q=="], "@astrojs/mdx/@astrojs/markdown-remark/shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="], @@ -6648,9 +6566,13 @@ "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], - "@aws-sdk/client-cognito-identity/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/client-cognito-identity/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], - "@aws-sdk/client-lambda/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/client-cognito-identity/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], + + "@aws-sdk/client-lambda/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], + + "@aws-sdk/client-lambda/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.775.0", "", { "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-6ESVxwCbGm7WZ17kY1fjmxQud43vzJFoLd4bmlR+idQSWdqlzGDYdcfzpjDKTcivdtNrVYmFvcH1JBUwCRAZhw=="], @@ -6664,13 +6586,21 @@ "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.782.0", "", { "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/nested-clients": "3.782.0", "@aws-sdk/types": "3.775.0", "@smithy/property-provider": "^4.0.2", "@smithy/types": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-xCna0opVPaueEbJoclj5C6OpDNi0Gynj+4d7tnuXGgQhTHPyAz8ZyClkVqpi5qvHTgxROdUEDxWqEO5jqRHZHQ=="], - "@aws-sdk/credential-provider-env/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-env/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], - "@aws-sdk/credential-provider-http/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-env/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], - "@aws-sdk/credential-provider-ini/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-http/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], - "@aws-sdk/credential-provider-login/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-http/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], + + "@aws-sdk/credential-provider-ini/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], + + "@aws-sdk/credential-provider-ini/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], + + "@aws-sdk/credential-provider-login/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], "@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.933.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.932.0", "@aws-sdk/middleware-host-header": "3.930.0", "@aws-sdk/middleware-logger": "3.930.0", "@aws-sdk/middleware-recursion-detection": "3.933.0", "@aws-sdk/middleware-user-agent": "3.932.0", "@aws-sdk/region-config-resolver": "3.930.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@aws-sdk/util-user-agent-browser": "3.930.0", "@aws-sdk/util-user-agent-node": "3.932.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.2", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.9", "@smithy/middleware-retry": "^4.4.9", "@smithy/middleware-serde": "^4.2.5", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.8", "@smithy/util-defaults-mode-node": "^4.2.11", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-o1GX0+IPlFi/D8ei9y/jj3yucJWNfPnbB5appVBWevAyUdZA5KzQ2nK/hDxiu9olTZlFEFpf1m1Rn3FaGxHqsw=="], @@ -6678,26 +6608,36 @@ "@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.933.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.932.0", "@aws-sdk/middleware-host-header": "3.930.0", "@aws-sdk/middleware-logger": "3.930.0", "@aws-sdk/middleware-recursion-detection": "3.933.0", "@aws-sdk/middleware-user-agent": "3.932.0", "@aws-sdk/region-config-resolver": "3.930.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@aws-sdk/util-user-agent-browser": "3.930.0", "@aws-sdk/util-user-agent-node": "3.932.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.2", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.9", "@smithy/middleware-retry": "^4.4.9", "@smithy/middleware-serde": "^4.2.5", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.8", "@smithy/util-defaults-mode-node": "^4.2.11", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-o1GX0+IPlFi/D8ei9y/jj3yucJWNfPnbB5appVBWevAyUdZA5KzQ2nK/hDxiu9olTZlFEFpf1m1Rn3FaGxHqsw=="], - "@aws-sdk/credential-provider-process/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-process/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], - "@aws-sdk/credential-provider-sso/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-process/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], - "@aws-sdk/credential-provider-web-identity/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-sso/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], - "@aws-sdk/credential-providers/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-sso/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], - "@aws-sdk/nested-clients/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-web-identity/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], - "@aws-sdk/token-providers/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.26", "", { "dependencies": { "@smithy/types": "^4.14.2", "fast-xml-parser": "5.7.3", "tslib": "^2.6.2" } }, "sha512-cDbrqvDS73whl6YAPSPq0U6whzG6UWI9PuWh0wrUuGoZexhWEqhdunbukV7iBoaWnFV1AODutM5hOD6rtn439g=="], + "@aws-sdk/credential-provider-web-identity/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], - "@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], + "@aws-sdk/credential-providers/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], - "@azure/core-xml/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], + "@aws-sdk/credential-providers/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], + + "@aws-sdk/nested-clients/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], + + "@aws-sdk/nested-clients/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], + + "@aws-sdk/token-providers/@aws-sdk/core/@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.33", "", { "dependencies": { "@smithy/types": "^4.15.1", "tslib": "^2.6.2" } }, "sha512-ezbwz9WpuLctm6o7P2t2naDhVVPI5jFGrVefVybhcKGjU57VIyT46pQVO0RI2RYkUdhdj2Z9uSIlAzGZE9NW9A=="], + + "@aws-sdk/token-providers/@aws-sdk/core/@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="], + + "@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.4.1", "", { "dependencies": { "anynum": "^1.0.1" } }, "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg=="], + + "@azure/core-xml/fast-xml-parser/strnum": ["strnum@2.4.1", "", { "dependencies": { "anynum": "^1.0.1" } }, "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg=="], "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], - "@develar/schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "@electron/asar/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="], "@electron/fuses/fs-extra/jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], @@ -6722,6 +6662,8 @@ "@expressive-code/plugin-shiki/shiki/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], + "@gitlab/opencode-gitlab-auth/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], + "@hey-api/json-schema-ref-parser/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], "@jsx-email/cli/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.19.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA=="], @@ -6842,7 +6784,7 @@ "@octokit/plugin-paginate-rest/@octokit/core/@octokit/graphql": ["@octokit/graphql@9.0.3", "", { "dependencies": { "@octokit/request": "^10.0.6", "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA=="], - "@octokit/plugin-paginate-rest/@octokit/core/@octokit/request": ["@octokit/request@10.0.10", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w=="], + "@octokit/plugin-paginate-rest/@octokit/core/@octokit/request": ["@octokit/request@10.0.11", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q=="], "@octokit/plugin-paginate-rest/@octokit/core/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], @@ -6856,7 +6798,7 @@ "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/graphql": ["@octokit/graphql@9.0.3", "", { "dependencies": { "@octokit/request": "^10.0.6", "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA=="], - "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/request": ["@octokit/request@10.0.10", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w=="], + "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/request": ["@octokit/request@10.0.11", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q=="], "@octokit/plugin-rest-endpoint-methods/@octokit/core/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], @@ -6876,7 +6818,7 @@ "@octokit/rest/@octokit/core/@octokit/graphql": ["@octokit/graphql@9.0.3", "", { "dependencies": { "@octokit/request": "^10.0.6", "@octokit/types": "^16.0.0", "universal-user-agent": "^7.0.0" } }, "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA=="], - "@octokit/rest/@octokit/core/@octokit/request": ["@octokit/request@10.0.10", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w=="], + "@octokit/rest/@octokit/core/@octokit/request": ["@octokit/request@10.0.11", "", { "dependencies": { "@octokit/endpoint": "^11.0.3", "@octokit/request-error": "^7.0.2", "@octokit/types": "^16.0.0", "content-type": "^2.0.0", "json-with-bigint": "^3.5.3", "universal-user-agent": "^7.0.2" } }, "sha512-+s7HUxjfFqOMS9VlIwDffq0MikjSAK0gSpG73W+meAvVAvX4MBrHYTK5Bj3Uot55qFT4gzUtfzE4mGWY4Br8/Q=="], "@octokit/rest/@octokit/core/@octokit/request-error": ["@octokit/request-error@7.1.0", "", { "dependencies": { "@octokit/types": "^16.0.0" } }, "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw=="], @@ -6892,6 +6834,8 @@ "@opentui/solid/@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "@oxc-resolver/binding-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + "@pierre/diffs/@shikijs/transformers/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], "@pierre/diffs/@shikijs/transformers/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], @@ -6928,6 +6872,8 @@ "@slack/bolt/express/path-to-regexp": ["path-to-regexp@0.1.13", "", {}, "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA=="], + "@slack/bolt/express/range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="], + "@slack/bolt/express/send": ["send@0.19.2", "", { "dependencies": { "debug": "2.6.9", "depd": "2.0.0", "destroy": "1.2.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", "fresh": "~0.5.2", "http-errors": "~2.0.1", "mime": "1.6.0", "ms": "2.1.3", "on-finished": "~2.4.1", "range-parser": "~1.2.1", "statuses": "~2.0.2" } }, "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg=="], "@slack/bolt/express/serve-static": ["serve-static@1.16.3", "", { "dependencies": { "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", "send": "~0.19.1" } }, "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA=="], @@ -6954,33 +6900,17 @@ "@solidjs/start/shiki/@shikijs/types": ["@shikijs/types@1.29.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw=="], - "@standard-community/standard-json/effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - - "@standard-community/standard-openapi/effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], - - "@storybook/csf-plugin/unplugin/acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], + "@storybook/builder-vite/@storybook/csf-plugin/unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="], "@storybook/csf-plugin/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], - "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg=="], - - "@vitest/coverage-v8/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@4.1.8", "", { "dependencies": { "tinyrainbow": "^3.1.0" } }, "sha512-9GasEBxpZ1VYIpqHf/0+YGg121uSNwCKOJqIrTwWP/TB7DmFCiaBpNl3aPZzoLWfWkuqhbH8vJIVobZkvdo2cA=="], + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], "@vitest/expect/@vitest/utils/@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="], - "ai-gateway-provider/@ai-sdk/amazon-bedrock/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], + "ai-gateway-provider/@ai-sdk/openai/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], - "ai-gateway-provider/@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], - - "ai-gateway-provider/@ai-sdk/amazon-bedrock/@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.14", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.1", "@smithy/util-hex-encoding": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw=="], - - "ai-gateway-provider/@ai-sdk/amazon-bedrock/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], - - "ai-gateway-provider/@ai-sdk/anthropic/@ai-sdk/provider": ["@ai-sdk/provider@3.0.10", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-Q3BZ27qfpYqnCYGvE3vt+Qi6LGOF9R5Nmzn+9JoM1lCRsD9mYaIhfJLkSunN48nfGXJ6n+XNV0J/XVpqGQl7Dw=="], - - "ai-gateway-provider/@ai-sdk/anthropic/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], - - "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + "ai-gateway-provider/@ai-sdk/openai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@4.0.27", "", { "dependencies": { "@ai-sdk/provider": "3.0.10", "@standard-schema/spec": "^1.1.0", "eventsource-parser": "^3.0.8" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ubkAJ+xODouwtmN1tYlvTPphH1hPOBfZaEQe8U7skGvFAnIRs9PPpsq57bC2+Ky/MB4yzhd6YOsxTAx9sGpazw=="], "ansi-align/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -7006,17 +6936,17 @@ "astro/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "astro/shiki/@shikijs/core": ["@shikijs/core@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-f2ED7HYV4JEk827mtMDwe/yQ25pRiXZmtHjWF8uzZKuKiEsJR7Ce1nuQ+HhV9FzDcbIo4ObBCD9GPTzNuy9S1g=="], + "astro/shiki/@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="], - "astro/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-OFx8fHAZuk7I42Z9YAdZ95To6jDePQ9Rnfbw9uSRTSbBhYBp1kEOKv/3jOimcj3VRUKusDYM6DswLauwfhboLg=="], + "astro/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="], - "astro/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-Yx3gy7xLzM0ZOjqoxciHjA7dAt5tyzJE3L4uQoM83agahy+PlW244XJSrmJRSBvGYELDhYXPacD4R/cauV5bzQ=="], + "astro/shiki/@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g=="], - "astro/shiki/@shikijs/langs": ["@shikijs/langs@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-le+bssCxcSHrygCWuOrYJHvjus6zhQ2K7q/0mgjiffRbkhM4o1EWu2m+29l0yEsHDbWaWPNnDUTRVVBvBBeKaA=="], + "astro/shiki/@shikijs/langs": ["@shikijs/langs@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg=="], - "astro/shiki/@shikijs/themes": ["@shikijs/themes@3.20.0", "", { "dependencies": { "@shikijs/types": "3.20.0" } }, "sha512-U1NSU7Sl26Q7ErRvJUouArxfM2euWqq1xaSrbqMu2iqa+tSp0D1Yah8216sDYbdDHw4C8b75UpE65eWorm2erQ=="], + "astro/shiki/@shikijs/themes": ["@shikijs/themes@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA=="], - "astro/shiki/@shikijs/types": ["@shikijs/types@3.20.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-lhYAATn10nkZcBQ0BlzSbJA3wcmL5MXUUF8d2Zzon6saZDlToKaiRX60n2+ZaHJCmXEcZRWNzn+k9vplr8Jhsw=="], + "astro/shiki/@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="], "astro/unstorage/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], @@ -7046,8 +6976,6 @@ "dmg-builder/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "dmg-license/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "duplexer2/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], "duplexer2/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], @@ -7056,30 +6984,6 @@ "editorconfig/minimatch/brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="], - "electron-builder-squirrel-windows/app-builder-lib/@electron/get": ["@electron/get@3.1.0", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ=="], - - "electron-builder-squirrel-windows/app-builder-lib/builder-util-runtime": ["builder-util-runtime@9.5.1", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ=="], - - "electron-builder-squirrel-windows/app-builder-lib/ci-info": ["ci-info@4.3.1", "", {}, "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA=="], - - "electron-builder-squirrel-windows/app-builder-lib/dmg-builder": ["dmg-builder@26.8.1", "", { "dependencies": { "app-builder-lib": "26.8.1", "builder-util": "26.8.1", "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" }, "optionalDependencies": { "dmg-license": "^1.0.11" } }, "sha512-glMJgnTreo8CFINujtAhCgN96QAqApDMZ8Vl1r8f0QT8QprvC1UCltV4CcWj20YoIyLZx6IUskaJZ0NV8fokcg=="], - - "electron-builder-squirrel-windows/app-builder-lib/electron-publish": ["electron-publish@26.8.1", "", { "dependencies": { "@types/fs-extra": "^9.0.11", "builder-util": "26.8.1", "builder-util-runtime": "9.5.1", "chalk": "^4.1.2", "form-data": "^4.0.5", "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, "sha512-q+jrSTIh/Cv4eGZa7oVR+grEJo/FoLMYBAnSL5GCtqwUpr1T+VgKB/dn1pnzxIxqD8S/jP1yilT9VrwCqINR4w=="], - - "electron-builder-squirrel-windows/app-builder-lib/hosted-git-info": ["hosted-git-info@4.1.0", "", { "dependencies": { "lru-cache": "^6.0.0" } }, "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA=="], - - "electron-builder-squirrel-windows/app-builder-lib/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - - "electron-builder-squirrel-windows/app-builder-lib/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - - "electron-builder-squirrel-windows/app-builder-lib/which": ["which@5.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ=="], - - "electron-builder-squirrel-windows/builder-util/builder-util-runtime": ["builder-util-runtime@9.5.1", "", { "dependencies": { "debug": "^4.3.4", "sax": "^1.2.4" } }, "sha512-qt41tMfgHTllhResqM5DcnHyDIWNgzHvuY2jDcYP9iaGpkWxTUzV6GQjDeLnlR1/DtdlcsWQbA7sByMpmJFTLQ=="], - - "electron-builder-squirrel-windows/builder-util/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "electron-builder-squirrel-windows/builder-util/js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], - "electron-builder/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], "electron-builder/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -7094,9 +6998,7 @@ "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], - "iconv-corefoundation/cli-truncate/slice-ansi": ["slice-ansi@3.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", "is-fullwidth-code-point": "^3.0.0" } }, "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ=="], - - "iconv-corefoundation/cli-truncate/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + "gcp-metadata/gaxios/node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], "js-beautify/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], @@ -7112,12 +7014,14 @@ "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], - "motion/framer-motion/motion-dom": ["motion-dom@12.40.0", "", { "dependencies": { "motion-utils": "^12.39.0" } }, "sha512-HxU3ZaBwNPVQUBQf1xxgq+7JrPNZvjLVxgbpEZL7RrWJnsxOf0/OM+yrHG9ogLQ31Do/r57Oz2gQWPK+6q62mg=="], + "motion/framer-motion/motion-dom": ["motion-dom@12.42.2", "", { "dependencies": { "motion-utils": "^12.39.0" } }, "sha512-5gIMWLp/PycBtJRJWRgjxke5n8dlvkSn2DrYW+tr3XcqAZY1xZh6BJyooJXCM8wdfM7wfMjkBJNLge1CKPUIRA=="], "motion/framer-motion/motion-utils": ["motion-utils@12.39.0", "", {}, "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ=="], "opencode-gitlab-auth/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], + "opencode-poe-auth/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], + "p-locate/p-limit/yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], "pkg-dir/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], @@ -7126,12 +7030,18 @@ "readdir-glob/minimatch/brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="], - "rimraf/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + "rimraf/glob/jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "rimraf/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + + "rimraf/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], "storybook/open/wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="], "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + "temp/rimraf/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + "tw-to-css/tailwindcss/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "tw-to-css/tailwindcss/glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], @@ -7140,15 +7050,15 @@ "tw-to-css/tailwindcss/object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], - "tw-to-css/tailwindcss/postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="], + "tw-to-css/tailwindcss/postcss": ["postcss@8.5.16", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg=="], "unplugin/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "unzipper/fs-extra/jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], - "venice-ai-sdk-provider/@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@3.0.12", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-sj9DWTJ2Ze0WR9qsiOPqoqzNx3OxL6iMxHImbhvoe9qOspekbzxNDMiJ4TIGfYHYh9w4OmBjz3prvqhzTi96+Q=="], + "venice-ai-sdk-provider/@ai-sdk/openai-compatible/@ai-sdk/provider": ["@ai-sdk/provider@3.0.13", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-ZPtVYt5QIJzOta1kdUiDuCx4HhFkvNPv/rvmZ2b1iXwybYjJsCnNYR4PAw4kW7rgVfDARvHXcU64efWuqNp6bw=="], - "venice-ai-sdk-provider/@ai-sdk/provider-utils/@ai-sdk/provider": ["@ai-sdk/provider@3.0.12", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-sj9DWTJ2Ze0WR9qsiOPqoqzNx3OxL6iMxHImbhvoe9qOspekbzxNDMiJ4TIGfYHYh9w4OmBjz3prvqhzTi96+Q=="], + "venice-ai-sdk-provider/@ai-sdk/provider-utils/@ai-sdk/provider": ["@ai-sdk/provider@3.0.13", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-ZPtVYt5QIJzOta1kdUiDuCx4HhFkvNPv/rvmZ2b1iXwybYjJsCnNYR4PAw4kW7rgVfDARvHXcU64efWuqNp6bw=="], "venice-ai-sdk-provider/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], @@ -7156,6 +7066,8 @@ "vitest/@vitest/expect/chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="], + "vscode-languageserver/vscode-languageserver-protocol/vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="], + "wrangler/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="], "wrangler/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="], @@ -7244,10 +7156,6 @@ "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from/@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], - "@aws-sdk/client-cognito-identity/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - - "@aws-sdk/client-lambda/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.782.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.0", "@smithy/middleware-retry": "^4.1.0", "@smithy/middleware-serde": "^4.0.3", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.8", "@smithy/util-defaults-mode-node": "^4.0.8", "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA=="], "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/client-sso": ["@aws-sdk/client-sso@3.782.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.0", "@smithy/middleware-retry": "^4.1.0", "@smithy/middleware-serde": "^4.0.3", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.8", "@smithy/util-defaults-mode-node": "^4.0.8", "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-5GlJBejo8wqMpSSEKb45WE82YxI2k73YuebjLH/eWDNQeE6VI5Bh9lA1YQ7xNkLLH8hIsb0pSfKVuwh0VEzVrg=="], @@ -7256,32 +7164,12 @@ "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.782.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.0", "@smithy/middleware-retry": "^4.1.0", "@smithy/middleware-serde": "^4.0.3", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.8", "@smithy/util-defaults-mode-node": "^4.0.8", "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA=="], - "@aws-sdk/credential-provider-env/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - - "@aws-sdk/credential-provider-http/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - - "@aws-sdk/credential-provider-ini/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - - "@aws-sdk/credential-provider-login/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - "@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-ini/@aws-sdk/nested-clients/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], "@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.933.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.932.0", "@aws-sdk/middleware-host-header": "3.930.0", "@aws-sdk/middleware-logger": "3.930.0", "@aws-sdk/middleware-recursion-detection": "3.933.0", "@aws-sdk/middleware-user-agent": "3.932.0", "@aws-sdk/region-config-resolver": "3.930.0", "@aws-sdk/types": "3.930.0", "@aws-sdk/util-endpoints": "3.930.0", "@aws-sdk/util-user-agent-browser": "3.930.0", "@aws-sdk/util-user-agent-node": "3.932.0", "@smithy/config-resolver": "^4.4.3", "@smithy/core": "^3.18.2", "@smithy/fetch-http-handler": "^5.3.6", "@smithy/hash-node": "^4.2.5", "@smithy/invalid-dependency": "^4.2.5", "@smithy/middleware-content-length": "^4.2.5", "@smithy/middleware-endpoint": "^4.3.9", "@smithy/middleware-retry": "^4.4.9", "@smithy/middleware-serde": "^4.2.5", "@smithy/middleware-stack": "^4.2.5", "@smithy/node-config-provider": "^4.3.5", "@smithy/node-http-handler": "^4.4.5", "@smithy/protocol-http": "^5.3.5", "@smithy/smithy-client": "^4.9.5", "@smithy/types": "^4.9.0", "@smithy/url-parser": "^4.2.5", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", "@smithy/util-defaults-mode-browser": "^4.3.8", "@smithy/util-defaults-mode-node": "^4.2.11", "@smithy/util-endpoints": "^3.2.5", "@smithy/util-middleware": "^4.2.5", "@smithy/util-retry": "^4.2.5", "@smithy/util-utf8": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-o1GX0+IPlFi/D8ei9y/jj3yucJWNfPnbB5appVBWevAyUdZA5KzQ2nK/hDxiu9olTZlFEFpf1m1Rn3FaGxHqsw=="], "@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-web-identity/@aws-sdk/nested-clients/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], - "@aws-sdk/credential-provider-process/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - - "@aws-sdk/credential-provider-sso/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - - "@aws-sdk/credential-provider-web-identity/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - - "@aws-sdk/credential-providers/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - - "@aws-sdk/nested-clients/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - - "@aws-sdk/token-providers/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser": ["fast-xml-parser@5.7.3", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.1.7", "path-expression-matcher": "^1.5.0", "strnum": "^2.2.3" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg=="], - "@electron/asar/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], "@electron/universal/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], @@ -7384,9 +7272,9 @@ "@solidjs/start/shiki/@shikijs/engine-javascript/oniguruma-to-es": ["oniguruma-to-es@2.3.0", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^5.1.1", "regex-recursion": "^5.1.1" } }, "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g=="], - "ai-gateway-provider/@ai-sdk/amazon-bedrock/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@storybook/builder-vite/@storybook/csf-plugin/unplugin/webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], - "ai-gateway-provider/@ai-sdk/anthropic/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "ai-gateway-provider/@ai-sdk/openai/@ai-sdk/provider-utils/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], "ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -7414,26 +7302,6 @@ "editorconfig/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "electron-builder-squirrel-windows/app-builder-lib/@electron/get/env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], - - "electron-builder-squirrel-windows/app-builder-lib/@electron/get/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], - - "electron-builder-squirrel-windows/app-builder-lib/@electron/get/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "electron-builder-squirrel-windows/app-builder-lib/dmg-builder/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], - - "electron-builder-squirrel-windows/app-builder-lib/electron-publish/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], - - "electron-builder-squirrel-windows/app-builder-lib/electron-publish/mime": ["mime@2.6.0", "", { "bin": { "mime": "cli.js" } }, "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg=="], - - "electron-builder-squirrel-windows/app-builder-lib/hosted-git-info/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], - - "electron-builder-squirrel-windows/app-builder-lib/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - - "electron-builder-squirrel-windows/app-builder-lib/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="], - - "electron-builder-squirrel-windows/builder-util/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], - "electron-builder/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "electron-builder/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], @@ -7446,10 +7314,6 @@ "filelist/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "iconv-corefoundation/cli-truncate/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "iconv-corefoundation/cli-truncate/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "js-beautify/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], "js-beautify/glob/minimatch/brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="], @@ -7464,7 +7328,13 @@ "readdir-glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="], + "rimraf/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.1.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA=="], + + "rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "temp/rimraf/glob/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], "tw-to-css/tailwindcss/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], @@ -7476,34 +7346,10 @@ "@astrojs/check/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "@aws-sdk/client-cognito-identity/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - - "@aws-sdk/client-lambda/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - "@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.782.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "3.775.0", "@aws-sdk/middleware-host-header": "3.775.0", "@aws-sdk/middleware-logger": "3.775.0", "@aws-sdk/middleware-recursion-detection": "3.775.0", "@aws-sdk/middleware-user-agent": "3.782.0", "@aws-sdk/region-config-resolver": "3.775.0", "@aws-sdk/types": "3.775.0", "@aws-sdk/util-endpoints": "3.782.0", "@aws-sdk/util-user-agent-browser": "3.775.0", "@aws-sdk/util-user-agent-node": "3.782.0", "@smithy/config-resolver": "^4.1.0", "@smithy/core": "^3.2.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/hash-node": "^4.0.2", "@smithy/invalid-dependency": "^4.0.2", "@smithy/middleware-content-length": "^4.0.2", "@smithy/middleware-endpoint": "^4.1.0", "@smithy/middleware-retry": "^4.1.0", "@smithy/middleware-serde": "^4.0.3", "@smithy/middleware-stack": "^4.0.2", "@smithy/node-config-provider": "^4.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/url-parser": "^4.0.2", "@smithy/util-base64": "^4.0.0", "@smithy/util-body-length-browser": "^4.0.0", "@smithy/util-body-length-node": "^4.0.0", "@smithy/util-defaults-mode-browser": "^4.0.8", "@smithy/util-defaults-mode-node": "^4.0.8", "@smithy/util-endpoints": "^3.0.2", "@smithy/util-middleware": "^4.0.2", "@smithy/util-retry": "^4.0.2", "@smithy/util-utf8": "^4.0.0", "tslib": "^2.6.2" } }, "sha512-QOYC8q7luzHFXrP0xYAqBctoPkynjfV0r9dqntFu4/IWMTyC1vlo1UTxFAjIPyclYw92XJyEkVCVg9v/nQnsUA=="], - "@aws-sdk/credential-provider-env/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - - "@aws-sdk/credential-provider-http/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - - "@aws-sdk/credential-provider-ini/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - - "@aws-sdk/credential-provider-login/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - "@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-sso/@aws-sdk/token-providers/@aws-sdk/nested-clients/@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="], - "@aws-sdk/credential-provider-process/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - - "@aws-sdk/credential-provider-sso/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - - "@aws-sdk/credential-provider-web-identity/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - - "@aws-sdk/credential-providers/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - - "@aws-sdk/nested-clients/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - - "@aws-sdk/token-providers/@aws-sdk/core/@aws-sdk/xml-builder/fast-xml-parser/strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], - "@jsx-email/cli/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "@sentry/bundler-plugin-core/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], @@ -7524,14 +7370,10 @@ "babel-plugin-module-resolver/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "electron-builder-squirrel-windows/app-builder-lib/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], - "electron-builder/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "electron-builder/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "iconv-corefoundation/cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "js-beautify/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], "js-beautify/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], @@ -7542,8 +7384,14 @@ "pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + "rimraf/glob/jackspeak/@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "rimraf/glob/jackspeak/@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + "rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + "temp/rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.15", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg=="], + "tw-to-css/tailwindcss/chokidar/readdirp/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "archiver-utils/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], @@ -7553,5 +7401,11 @@ "js-beautify/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "js-beautify/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "rimraf/glob/jackspeak/@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "rimraf/glob/jackspeak/@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "temp/rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], } } diff --git a/package.json b/package.json index 9da29ab6bab..e3d65f0d216 100644 --- a/package.json +++ b/package.json @@ -42,9 +42,9 @@ "@octokit/rest": "22.0.0", "@hono/standard-validator": "0.2.0", "@hono/zod-validator": "0.4.2", - "@opentui/core": "0.3.4", - "@opentui/keymap": "0.3.4", - "@opentui/solid": "0.3.4", + "@opentui/core": "0.4.3", + "@opentui/keymap": "0.4.3", + "@opentui/solid": "0.4.3", "@tanstack/solid-virtual": "3.13.28", "@shikijs/stream": "4.2.0", "ulid": "3.0.1", diff --git a/packages/plugin/package.json b/packages/plugin/package.json index d97f6552538..93214e61bfb 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -32,9 +32,9 @@ "zod": "catalog:" }, "peerDependencies": { - "@opentui/core": ">=0.3.4", - "@opentui/keymap": ">=0.3.4", - "@opentui/solid": ">=0.3.4" + "@opentui/core": ">=0.4.3", + "@opentui/keymap": ">=0.4.3", + "@opentui/solid": ">=0.4.3" }, "peerDependenciesMeta": { "@opentui/core": { From 7f008df79d746b52605498f4cd79cedea061196d Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Mon, 6 Jul 2026 09:19:04 -0500 Subject: [PATCH 02/46] fix(codemode): improve prompting (#35509) --- packages/codemode/README.md | 27 +- packages/codemode/codemode.md | 102 ++++--- packages/codemode/src/codemode.ts | 18 +- packages/codemode/src/tool-runtime.ts | 321 +++++++++------------ packages/codemode/src/tool-schema.ts | 4 +- packages/codemode/test/codemode.test.ts | 196 ++++++++----- packages/codemode/test/enumeration.test.ts | 8 +- packages/codemode/test/signature.test.ts | 91 +++--- packages/core/test/mcp.test.ts | 2 +- 9 files changed, 407 insertions(+), 362 deletions(-) diff --git a/packages/codemode/README.md b/packages/codemode/README.md index 0be6d769c7c..afd178a36cf 100644 --- a/packages/codemode/README.md +++ b/packages/codemode/README.md @@ -179,14 +179,14 @@ Supported bearer, basic, header, and query authentication follows OpenAPI `secur ## Discovery -The agent-tool instructions use a budgeted catalog. Every tool namespace is always listed with its tool count regardless of budget, and as many complete tool signatures (each with a one-line description) as fit an estimated-token budget are inlined. Selection is round-robin across namespaces for fairness: in each round (namespaces alphabetical), every namespace still holding un-inlined tools attempts to place its next-cheapest signature line against the shared budget, and a namespace whose next line does not fit drops out while the others keep going - so every namespace gets some representation before any namespace gets everything. The instructions state exactly how comprehensive the list is, both overall (`COMPLETE list` vs `PARTIAL - N of M shown`) and per namespace (`(3 tools)`, `(3 tools, 1 shown)`, `(3 tools, none shown)`). +The agent-tool instructions use a budgeted catalog. Every tool namespace is always listed with its tool count regardless of budget, and as many complete, JSDoc-annotated tool signatures (each with a one-line description) as fit an estimated-token budget are inlined. Schema field descriptions and tags are part of each signature's measured cost. Selection is round-robin across namespaces for fairness: in each round (namespaces alphabetical), every namespace still holding un-inlined tools attempts to place its next-cheapest signature against the shared budget, and a namespace whose next signature does not fit drops out while the others keep going - so every namespace gets some representation before any namespace gets everything. The instructions state exactly how comprehensive the list is, both overall (`COMPLETE list` vs `PARTIAL - N of M shown`) and per namespace (`(3 tools)`, `(3 tools, 1 shown)`, `(3 tools, none shown)`). -The default budget is 2,000 estimated tokens (characters / 4, the same heuristic OpenCode uses). Override it when constructing a runtime: +The catalog-entry budget defaults to 2,000 estimated tokens (characters / 4, the same heuristic OpenCode uses). It applies only to full tool entries shown in the catalog; fixed instructions and namespace summaries are not counted. Override it when constructing a runtime: ```ts const runtime = CodeMode.make({ tools, - discovery: { maxInlineCatalogTokens: 6_000 }, + discovery: { catalogBudget: 6_000 }, }) ``` @@ -199,30 +199,37 @@ const matches = await tools.$codemode.search({ query: "order status", namespace: "orders", // optional: scope to one top-level namespace limit: 10, + offset: 0, }) ``` -`search` performs deterministic, additive field-weighted matching. The query is tokenized (camelCase boundaries split; every non-alphanumeric character is a separator; empties and `*` are dropped), and each term scores every tool: exact path or path-segment match (20), path substring (8), description substring (4), and searchable-text substring (2). Each term also carries naive singular variants (trailing `s`/`es` stripped), and a field check passes when the term or any variant matches - so a plural query term (`issues`) still finds a tool whose text only says `issue`, without changing the weights. The searchable text also includes the input schema's property names and their description strings, so a query naming a parameter finds its tool, and substring matching means partial words match. Scores sum across terms; matches are sorted by score (ties broken alphabetically by path) and capped at `limit` results (default 10). +`search` performs deterministic, additive field-weighted matching. The query is tokenized (camelCase boundaries split; every non-alphanumeric character is a separator; empties and `*` are dropped), and each term scores every tool: exact path or path-segment match (20), path substring (8), description substring (4), and searchable-text substring (2). Each term also carries naive singular variants (trailing `s`/`es` stripped), and a field check passes when the term or any variant matches - so a plural query term (`issues`) still finds a tool whose text only says `issue`, without changing the weights. The searchable text also includes the input schema's property names and their description strings, so a query naming a parameter finds its tool, and substring matching means partial words match. Scores sum across terms; matches are sorted by score (ties broken alphabetically by path), then sliced from the zero-based `offset` (default 0) to the configured `limit` (default 10). `remaining` counts matches after the current page. `next` is `{ offset }` when another page exists and `null` on the final page; spread it into the original request to preserve its query, namespace, and limit. -Each result contains the path, description, and generated TypeScript signature, so no second lookup is needed. The result signature is the pretty, JSDoc-annotated multiline form: each described input/output field carries its schema `description` as a `/** ... */` comment, and constraints TypeScript cannot express ride along as tags (`@deprecated`, `@default`, `@format`, `@minItems`, `@maxItems`). The inline catalog in the instructions keeps the compact single-line form. +```ts +const request = { query: "order status", namespace: "orders", limit: 10 } +const page = await tools.$codemode.search(request) +const nextPage = page.next ? await tools.$codemode.search({ ...request, ...page.next }) : undefined +``` + +Each result contains the path, description, and the same generated TypeScript signature used by the inline catalog, so no second lookup is needed. Signatures use the JSDoc-annotated multiline form: each described input/output field carries its schema `description` as a `/** ... */` comment, and constraints TypeScript cannot express ride along as tags (`@deprecated`, `@default`, `@format`, `@minItems`, `@maxItems`). ```ts tools.github.list_issues(input: { /** Repository owner */ - owner: string + owner: string, /** Cursor from the previous response's pageInfo */ - after?: string + after?: string, /** * Results per page * @default 30 */ - perPage?: number + perPage?: number, }): Promise ``` Result paths are rendered as JavaScript expressions rooted at `tools` (`tools.orders.lookup`, or `tools.context7["resolve-library-id"]` for non-identifier segments), so each `path` is directly usable as the call site. An empty query browses the catalog alphabetically by path; combined with `namespace` (`{ query: "", namespace: "orders" }`) it lists everything in that namespace. A query that names one tool path exactly (canonical path, `tools.`-prefixed path, or rendered JavaScript expression) is treated as a lookup and returns that tool alone. -The instructions are structured markdown, ordered so the workflow sits at the top and the catalog at the bottom: a `## Workflow` section with numbered steps (find a tool via search when the catalog is partial, or pick from the inlined list when it is complete; call the exact path as-is; `JSON.parse` string results; return only the needed fields), a `## Rules` section holding only guidance the workflow does not already cover (only listed/search-result tools exist inside `tools`; filter and aggregate collections in code; treat `Promise` results as shapeless until verified; run independent calls through `Promise.all`; enumerate `tools` with `Object.keys`/`for...in`; browse a namespace via search when it is advertised), a short `## Syntax` section that assumes standard JavaScript and names only what is unusual (TypeScript annotations stripped; the data-boundary serialization of Date/Map/Set/RegExp) or missing (classes, generators, `for await...of`, `.then`/`.catch`/`.finally`), and the budgeted `## Available tools` catalog. Example call forms use explicit `.`/`` placeholders - never a real or fabricated tool name. +The instructions are structured markdown, ordered so the workflow sits at the top and the catalog at the bottom: a `## Workflow` section with numbered steps (find a tool via search when the catalog is partial, or pick from the inlined list when it is complete; call the exact path as-is; return only the needed fields), a `## Rules` section holding only guidance the workflow does not already cover (only listed/search-result Code Mode tools and internal runtime tools exist inside `tools`; filter and aggregate collections in code; narrow `Promise` results at runtime; run independent calls through `Promise.all`; enumerate `tools` with `Object.keys`/`for...in`; browse a namespace and paginate search results when search is advertised), a short `## Language` section that identifies the runtime as a restricted JavaScript orchestration language and names its major unavailable capabilities, and the budgeted `## Available tools` catalog. Example call forms use explicit `.`/`` placeholders - never a real or fabricated tool name. A host cannot define its own `$codemode` top-level namespace. @@ -234,7 +241,7 @@ CodeMode executes a deliberately bounded JavaScript subset. It supports: - `if`, conditional expressions, `switch`, `for`, `for...of` (arrays, strings, Maps, Sets), `for...in` (own keys of plain objects, index strings of arrays, and namespace/tool names of `tools` references - anything else is an error suggesting `for...of` or `Object.keys`, rather than real JS's surprising behavior of indices for strings and zero iterations for Maps/Sets), `while`, and `do...while`. - Arrow functions and function declarations with closures, defaults, rest parameters, and destructuring. - Optional chaining, nullish coalescing, templates, spread (arrays, strings, Maps, Sets), and `try`/`catch`. -- Common array, string, number, `Object`, `Math`, and `JSON` operations. Mutating array methods include `push`/`pop`/`shift`/`unshift`/`splice` (removes in place and returns the removed elements)/`fill`/`copyWithin`; array `keys`/`values`/`entries` return **arrays** (matching the Map/Set convention) and work with `for...of` and spread. String methods include `localeCompare` (locale/options arguments ignored), `normalize`, and the `trimLeft`/`trimRight` aliases. `Object.keys` also accepts arrays (index strings, as in JS) and tool references: `Object.keys(tools)` lists the top-level namespaces and `Object.keys(tools.ns)` the names at that node (a callable tool enumerates as `[]`; an unknown path is an `UnknownTool` diagnostic). `Object.values`/`Object.entries` on a tool reference fail with a pointer at `Object.keys(tools)` and `tools.$codemode.search`. +- Common array, string, number, `Object`, `Math`, and `JSON` operations. Mutating array methods include `push`/`pop`/`shift`/`unshift`/`splice` (removes in place and returns the removed elements)/`fill`/`copyWithin`; array `keys`/`values`/`entries` return **arrays** (matching the Map/Set convention) and work with `for...of` and spread. String methods include `localeCompare` (locale/options arguments ignored), `normalize`, and the `trimLeft`/`trimRight` aliases. `Object.keys` also accepts arrays (index strings, as in JS) and tool references: `Object.keys(tools)` lists the top-level namespaces, including `$codemode`, and `Object.keys(tools.ns)` lists the names at that node (a callable tool enumerates as `[]`; an unknown path is an `UnknownTool` diagnostic). `Object.values`/`Object.entries` on a tool reference fail with a pointer at `Object.keys(tools)` and `tools.$codemode.search`. - `Date` - `Date.now()`/`Date.parse()`/`Date.UTC()`, `new Date(...)`, the getter methods, and date arithmetic/comparison via the time value. Dates stringify as ISO (`toString` included, for determinism across host timezones). - Regular expressions - `/literals/` and `new RegExp(...)` with `test`/`exec` (stateful `lastIndex` for `g`), plus string `match`/`matchAll`/`replace`/`replaceAll`/`split`/`search` with patterns. Match results are arrays carrying `index` and named `groups` as own properties (`input` is omitted). Invalid patterns, invalid flags, and missing-`g` calls fail with catchable errors that say what was wrong and how to fix it (escaping hints, the exact `/pattern/g` to write). Patterns run on the host engine, so pathological backtracking is bounded only by the execution timeout. Function replacers are not supported. - `Map` and `Set` - construction from entries/arrays/strings, `get`/`set`/`add`/`has`/`delete`/`clear`/`size`/`forEach`, and `keys`/`values`/`entries` returning **arrays** (not iterators). diff --git a/packages/codemode/codemode.md b/packages/codemode/codemode.md index a94f1d4eec6..8f14ed6a974 100644 --- a/packages/codemode/codemode.md +++ b/packages/codemode/codemode.md @@ -65,17 +65,24 @@ From issue #34787 and design discussion. Do not relitigate these casually. ### Discovery / search - **Search only - no separate `describe`.** `tools.$codemode.search({ query?, namespace?, -limit? })` over the final tool tree, owned by this package. -- Search result item shape: `{ path, description, signature }` in an `{ items, total }` - wrapper. The `signature` string embeds the full input/output TypeScript types - in search - results it is the pretty, JSDoc-annotated multiline form (Fix 7), so per-field schema - `description`s and constraints (`@default`, `@format`, `@deprecated`, `@minItems`, - `@maxItems`) ride along as field comments. The original spec's separate `input`/`output` +limit?, offset? })` over the final tool tree, owned by this package. +- Search result item shape: `{ path, description, signature }` in an + `{ items, remaining, next }` + wrapper. The `signature` string embeds the full input/output TypeScript types and uses the + same pretty, JSDoc-annotated multiline form in inline catalogs and search results, so + per-field schema `description`s and constraints (`@default`, `@format`, `@deprecated`, + `@minItems`, `@maxItems`) ride along as field comments. The original spec's separate `input`/`output` raw-schema fields are deliberately NOT added: shapes are already fully expressed in the TypeScript signature and schema annotations now arrive as JSDoc - intent satisfied, letter deviated. Result `path`s render a JavaScript expression rooted at `tools` (for example `tools.github.list_issues` or `tools.context7["resolve-library-id"]`) so each is directly usable as the call site; the internal `ToolDescription.path` stays unprefixed. +- `offset` is zero-based and defaults to 0. `remaining` counts matches after the current page; + `next` is `{ offset }` when another page exists and `null` on the final page. +- Search is an internal `Tool.make` definition backed by Effect input/output schemas. Its + validation, output checking, call observation, and TypeScript signature use the same path as + host-provided schema tools. Host-only catalog preparation keeps internal tools out of their + own search index; only conditional advertisement remains special. - Default limit: **10** (done). Exact-path lookup goes through search too: a query equal to a canonical tool path, `tools.`-prefixed path, or rendered JavaScript expression returns that tool alone (done). @@ -251,7 +258,7 @@ output limit; return a smaller value]`; logs keep leading lines within the remai truncation is now the only result-size mechanism.) - **Search polish**: default limit 12 -> **10** (`defaultSearchLimit`); exact-path lookup - a trimmed query equal to one tool path (optionally `tools.`-prefixed) returns that tool alone - (`total: 1`), bypassing ranking. Tokenization/ranking/shape unchanged. + (`remaining: 0`, `next: null`), bypassing ranking. Tokenization/ranking/shape unchanged. ### Wave 3 - OpenCode MCP adapter (done) @@ -312,10 +319,10 @@ Instructions are now the budgeted-catalog + prompting-guidance form; verified e2 real MCP config. Package still 101 tests / 0 fail; opencode adapter suites still 34 + 16; both packages typecheck clean. -- **Budgeted catalog** (`discoveryPlan` in `tool-runtime.ts`): the all-or-nothing +- **Budgeted catalog** (`prepare` in `tool-runtime.ts`): the all-or-nothing inline/search modes are gone - `DiscoveryMode` deleted, `CodeMode.DiscoveryOptions` is just `{ maxInlineCatalogBytes? }` (default 16,000 UTF-8 bytes; later converted to - `maxInlineCatalogTokens`, default 4,000 estimated tokens - see Post-wave fixes). Port of + `catalogBudget`, default 4,000 estimated tokens - see Post-wave fixes). Port of the old opencode `describe()` `PREVIEW_BUDGET` algorithm, adapted to `ToolDescription`: every namespace is ALWAYS listed with its tool count; full signature lines @@ -439,9 +446,9 @@ adapter needed **no changes**. defeating discovery. Fixes, all in this package: - `ToolRuntime.make` now returns a `keys(path)` capability (`namespaceKeys` in `tool-runtime.ts`) threaded into the `Interpreter` alongside `invoke` - the interpreter - still never holds the host tool tree. `Object.keys(tools)` yields the top-level namespace - names (never `$codemode`, which is virtual - but `Object.keys(tools.$codemode)` yields - `["search"]`), `Object.keys(tools.ns)` the names at that node; a callable tool leaf + still never holds the callable tool tree. `Object.keys(tools)` yields the top-level namespace + names, including the internally registered `$codemode`; `Object.keys(tools.$codemode)` yields + `["search"]`, and `Object.keys(tools.ns)` yields names at that node; a callable tool leaf enumerates as `[]` (like `Object.keys` of a JS function); an unknown path throws an `UnknownTool` diagnostic suggesting `Object.keys(tools)` and `$codemode.search` (matching call-time unknown-tool behavior rather than silently returning `[]`). @@ -459,7 +466,7 @@ adapter needed **no changes**. - `supportedSyntaxMessage`, the instructions loops line, and README "Supported Programs" mention the new surface; tests in `test/enumeration.test.ts` (14, incl. the exact transcript program) plus one adapter-level assertion that `Object.keys(tools)` returns - MCP server names. + MCP server and CodeMode namespace names. - **Search ranking, namespace scoping, prefixed result paths (done).** Motivation: the Wave 4 e2e run showed a model retrying calls because search-result paths @@ -480,7 +487,7 @@ adapter needed **no changes**. An empty query now browses ALPHABETICALLY by path (was declaration order). Kept: `{ path, description, signature }` result items, default limit 10, exact-path instant lookup, input validation errors. - - **Namespace scoping**: `tools.$codemode.search({ query?, namespace?, limit? })` - + - **Namespace scoping**: `tools.$codemode.search({ query?, namespace?, limit?, offset? })` - `namespace` (validated as a string when provided) filters `SearchEntry`s to one top-level namespace before ranking; `{ query: "", namespace: "github" }` lists that namespace alphabetically. `searchSignature` updated. @@ -489,7 +496,7 @@ adapter needed **no changes**. segments), directly usable as the call site. Internal `ToolDescription.path` stays unprefixed; only the search RESULT items are rendered this way. Exact-path queries accept canonical paths and rendered expressions. - - **Instructions** (`discoveryPlan`): an explicit calling-convention line and a browse + - **Instructions** (`prepare`): an explicit calling-convention line and a browse hint on the search advertisement (both since absorbed into the `## Rules` section by the instructions restructure below). - **Tests**: package search/discovery tests updated (prefixed paths, alphabetical browse) @@ -499,28 +506,23 @@ adapter needed **no changes**. - **Instructions restructure: markdown sections, placeholder-only call forms (done).** The flat prose instructions (which mixed a real catalog tool with fabricated result - fields in the worked example) are replaced by structured markdown in `discoveryPlan`, + fields in the worked example) are replaced by structured markdown in `prepare`, ordered so the workflow sits at the top (the least likely part of a long description to be truncated or skimmed away) and the catalog at the bottom (the per-section content - described here was later condensed by Fix 8 - Workflow/Rules deduped, Syntax inverted): - - **Intro** (2 lines): "Write a CodeMode program... Return code only." + "Execute - JavaScript in a confined runtime with access to the tools listed below under - `tools.*`." (the second line drops the tools clause when the tree is empty). - - **`## Workflow`**: numbered steps - find a tool via `tools.$codemode.search` -> read - the `{ path, description, signature }` matches -> call by path -> `typeof res === -"string" ? JSON.parse(res) : res` -> return only the needed fields. When the catalog is - COMPLETE the search/read steps collapse into "Pick a tool from the list under - `## Available tools`" and the steps renumber (4 instead of 5). - - **`## Rules`**: call-by-exact-path; TEXT-is-JSON -> JSON.parse; return small (never raw - payloads); filter/aggregate large collections in code instead of per-item round-trips; + described here was later condensed by Fix 8 and the language-accuracy pass): + - **Intro**: identifies the language as restricted JavaScript for calling tools rather than + a general-purpose runtime. + - **`## Workflow`**: with a partial catalog, return search results from one execution, then + copy a selected path into the next execution. With a complete catalog, pick and call an + inlined signature, then return only the needed fields. + - **`## Rules`**: narrow unknown results at runtime; filter/aggregate large collections in code instead of per-item round-trips; console.log/warn/error/dir/table for intermediates; `Promise.all` parallelism (no .then/.catch - await + try/catch); `Object.keys(tools)`/`for...in` enumeration; browse-one-namespace via search (PARTIAL only); and host-side media handling (files/ images never enter the program; a media-only call yields a small text marker - wording verified against the adapter's `toSandboxResult`/`mediaMarker`). - - **`## Syntax`**: the dense syntax lines unchanged, minus the Promise.all and console - lines (moved into Rules) and the `for (const ns in tools)` fragment (redundant with - the enumeration rule). + - **`## Language`**: a concise positive capability summary plus the major unavailable + runtime capabilities and the data-boundary serialization note. - **`## Available tools`**: the budgeted catalog unchanged, with the COMPLETE/PARTIAL header merged into the section heading (no trailing colon); the search-signature advertisement follows when PARTIAL (its description-reading and browse clauses moved @@ -532,7 +534,7 @@ adapter needed **no changes**. appear anywhere in the instructions. Zero tools keep "No tools are currently available." under minimal sections (intro + Syntax + Available tools). - **Tests**: the package worked-example test replaced by section-structure/placeholder - assertions (section order; JSON.parse + return-small rules present; no + assertions (section order; unknown-result + return-small rules present; no `total_count`/`list_issues`/real-tool example lines; browse hint only when PARTIAL; zero-tool minimal sections) - 156 pass / 0 fail; adapter suites gain the same assertions on the built description (still 35 + 16, green). @@ -542,9 +544,9 @@ budget; namespaces must always be present): - `src/token.ts` added: copy of `@opencode-ai/core/util/token` (`round(chars / 4)`), so the package stays dependency-free; keep in sync if the core heuristic changes. -- `CodeMode.DiscoveryOptions.maxInlineCatalogBytes` -> `maxInlineCatalogTokens` (default 4,000 +- `CodeMode.DiscoveryOptions.maxInlineCatalogBytes` -> `catalogBudget` (default 4,000 estimated tokens ~ the old 16,000 bytes at 4 chars/token - behavior parity, not a size - reduction). `discoveryPlan` charges `estimate(catalogLine(tool))` per line; cheapest-first + reduction). `prepare` charges `estimate(catalogLine(tool))` per line; cheapest-first - stop-on-first-miss unchanged at the time (stop-on-first-miss replaced by round-robin in Fix 8). Namespace stub lines were and remain unbudgeted - every namespace always appears with its tool count, even at budget 0 (asserted in package and @@ -672,10 +674,8 @@ along). All in `tool-runtime.ts`; no interpreter changes. interfaces/type aliases are stripped and TS **enums actually work** (transpileModule compiles them to an IIFE the interpreter runs), hence enums deliberately unmentioned. `supportedSyntaxMessage` (the in-diagnostic text in `codemode.ts`) is untouched. -- **Workflow/Rules deduped**: the call-by-exact-path, JSON.parse-string-results, and - return-small content now lives ONLY in the numbered Workflow steps (with their - compliance-driving justifications inline: "most tools return JSON as a string", "raw - payloads get truncated and waste context"); Rules keeps only bullets adding new +- **Workflow/Rules deduped**: the call-by-exact-path and return-small content now lives ONLY + in the numbered Workflow steps; Rules keeps only bullets adding new content - filter/aggregate collections in code, console.\* intermediates (logs ride back), Promise.all parallelism, Object.keys/for...in enumeration, browse-namespace (PARTIAL only), and the media rule compressed to one line. The no-.then/.catch @@ -690,7 +690,7 @@ along). All in `tool-runtime.ts`; no interpreter changes. (332 -> 176), Syntax 453 -> 188 (419 -> 174); fixed prose total 1,005 -> 610 (927 -> 562), ~ 40% reduction with no behavioral content dropped. Workflow grew slightly because it absorbed the deduped parse/return-small justifications. -- **Round-robin namespace inlining** (`discoveryPlan`): the ported stop-on-first-miss +- **Round-robin namespace inlining** (`prepare`): the ported stop-on-first-miss behavior (alphabetically-late namespaces starved to "none shown" while an early namespace inlines everything) is replaced by round-robin fairness - in each round (namespaces alphabetical), every namespace still holding un-inlined tools attempts to @@ -708,9 +708,9 @@ along). All in `tool-runtime.ts`; no interpreter changes. the four field checks passes when ANY form matches. Weights, exact-path lookup, and namespace scoping untouched. A true plural path match still outranks a singular-only description match (path substring 8 + searchable 2 > description 4 + searchable 2). -- **Tests**: package instruction/structure assertions updated to the new text; new - syntax-section test (leads with "Standard modern JavaScript works", names the - verified not-supported list, keeps the data-boundary note); the budget-exhaustion +- **Tests**: package instruction/structure assertions updated to the new text; the + language-section test rejects full-runtime wording, names major unavailable capabilities, + and keeps the data-boundary note; the budget-exhaustion test rewritten to assert the new fairness (alpha.expensive not fitting must NOT prevent beta.cheap from showing: PARTIAL 2 of 3, `- beta (1 tool)` fully shown); new plural/singular test (query "issues" finds a singular-only tool; ranking still @@ -724,7 +724,7 @@ along). All in `tool-runtime.ts`; no interpreter changes. **Fix 9 - prompting trims per user review of Fix 8** (user reviewed the condensed instructions and directed further cuts): -- Default `maxInlineCatalogTokens` 4,000 -> **2,000** (user wants ~2k tokens of signatures +- Default `catalogBudget` 4,000 -> **2,000** (user wants ~2k tokens of signatures auto-inlined; round-robin fairness from Fix 8 spreads it across all namespaces). - Console rule and files/images rule DROPPED from `## Rules`. Replaced by a single `unknown`-treatment warning: "A result typed `Promise` has no guaranteed @@ -733,9 +733,9 @@ instructions and directed further cuts): return the same data; the prompt stays console-neutral, neither for nor against.) The media-stripping MECHANISM is unchanged and still tested; only the prose about it is gone - the `[N images attached]` marker is self-explanatory in context. -- Kept as-is per user: the JSON.parse workflow step (maps to the original motivating - transcript failure; NOT copied from prior art - see section 5 note), the browse-namespace rule - (undecided), no no-fetch/ambient-authority rule added (proposed, not approved). +- Later revised: unconditional JSON parsing was removed because text results are not + necessarily JSON. The browse-namespace rule remains; the language section now states that + ambient `fetch` is unavailable and external operations go through Code Mode tools. - Explicitly REJECTED for now: auto-parsing JSON-looking text results at the adapter boundary ("could get weird" - type flips, program-sees vs tool-sent divergence). Logged as a next-iteration follow-up below. @@ -1004,11 +1004,19 @@ focused interpreter-surface pass rather than picked off piecemeal. - [x] Sandbox values nested inside logged containers print `[CodeMode reference]` (`console.log({ m: map })`) - could deep-format instead. +### Next iteration: optional search input boundary + +- [ ] `SearchInput` uses Effect's exact `optionalKey`, so an omitted field is accepted but an + explicitly present `undefined` field is rejected. The previous handwritten validator + treated explicit `undefined` as omission. Decide whether search should preserve that + convenience locally or whether all tool arguments should adopt JSON-style undefined + normalization; do not broaden `copyOut` semantics solely to fix search. + ### Next iteration: text-result handling (deliberate follow-up, user-directed) - [ ] Revisit how MCP text results reach the program. Today: `structuredContent` when the - server sends it, else joined text as a plain string (the program JSON.parses it, - guided by a workflow step). Considered and deferred: (a) conservative boundary + server sends it, else joined text as a plain string. Programs narrow unknown results + before use; the prompt no longer recommends unconditional JSON parsing. Considered and deferred: (a) conservative boundary auto-parse (text starting with `{`/`[` that parses cleanly becomes an object) - rejected for now as potentially confusing (type flips; program sees something other than what the tool sent); (b) raw-envelope passthrough with the envelope shape diff --git a/packages/codemode/src/codemode.ts b/packages/codemode/src/codemode.ts index b207efe46a8..083f62e28b5 100644 --- a/packages/codemode/src/codemode.ts +++ b/packages/codemode/src/codemode.ts @@ -38,12 +38,12 @@ export type ExecutionLimits = { /** Controls how much of the tool catalog is inlined in agent instructions. */ export type DiscoveryOptions = { /** - * Estimated-token budget (chars/4, default 2000) for inlined full tool signatures in agent - * instructions. Signatures that fit are inlined round-robin across namespaces; every - * namespace is always listed with its tool count regardless of budget, and + * Approximate budget, in estimated tokens (chars/4, default 2000), for full tool entries in + * the instruction catalog. Tool entries are selected round-robin across namespaces. Fixed + * instructions and namespace summaries do not count toward the budget, and * `tools.$codemode.search` is always registered. */ - readonly maxInlineCatalogTokens?: number + readonly catalogBudget?: number } type ToolTree = { @@ -3921,8 +3921,8 @@ const executeWithLimits = >( const tools = ToolRuntime.make( (options.tools ?? {}) as HostTools>, limits.maxToolCalls, - hooks, searchIndex, + hooks, ) const logs: Array = [] const logged = () => (logs.length > 0 ? { logs: [...logs] } : {}) @@ -4061,10 +4061,10 @@ export const make = = {}>( const tools = (options.tools ?? {}) as HostTools> ToolRuntime.assertValidTools(tools) const limits = resolveExecutionLimits(options.limits) - const discovery = ToolRuntime.discoveryPlan(tools, options.discovery?.maxInlineCatalogTokens) - const executeProgram = (code: string) => executeWithLimits({ ...options, code }, limits, discovery.searchIndex) - const catalog = discovery.catalog - const instructions = discovery.instructions + const prepared = ToolRuntime.prepare(tools, options.discovery?.catalogBudget) + const executeProgram = (code: string) => executeWithLimits({ ...options, code }, limits, prepared.searchIndex) + const catalog = prepared.catalog + const instructions = prepared.instructions return { catalog: () => catalog, diff --git a/packages/codemode/src/tool-runtime.ts b/packages/codemode/src/tool-runtime.ts index 268953b56ac..64fbc6d14ea 100644 --- a/packages/codemode/src/tool-runtime.ts +++ b/packages/codemode/src/tool-runtime.ts @@ -1,4 +1,4 @@ -import { Cause, Effect } from "effect" +import { Cause, Effect, Schema } from "effect" import { ToolError, toolError } from "./tool-error.js" import { decodeInput as decodeToolInput, @@ -75,10 +75,26 @@ export type ToolDescription = { export type SafeObject = Record const reservedNamespace = "$codemode" -const defaultMaxInlineCatalogTokens = 2_000 +const defaultCatalogBudget = 2_000 const defaultSearchLimit = 10 -const searchSignature = - "tools.$codemode.search({ query?: string, namespace?: string, limit?: number }): Promise<{ items: Array<{ path: string; description: string; signature: string }>; total: number }>" +const PositiveInt = Schema.Int.check(Schema.isGreaterThan(0)) +const NonNegativeInt = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)) +const SearchInput = Schema.Struct({ + query: Schema.optionalKey(Schema.String), + namespace: Schema.optionalKey(Schema.String), + limit: Schema.optionalKey(PositiveInt), + offset: Schema.optionalKey(NonNegativeInt), +}) +const SearchItem = Schema.Struct({ + path: Schema.String, + description: Schema.String, + signature: Schema.String, +}) +const SearchOutput = Schema.Struct({ + items: Schema.Array(SearchItem), + remaining: NonNegativeInt, + next: Schema.NullOr(Schema.Struct({ offset: NonNegativeInt })), +}) const toolExpression = (path: string) => "tools" + path @@ -294,15 +310,17 @@ const definitions = ( return entries } +const describeDefinition = (path: string, definition: Definition): ToolDescription => ({ + path, + description: definition.description, + signature: `${toolExpression(path)}(input: ${inputTypeScript(definition, true)}): Promise<${outputTypeScript(definition, true)}>`, +}) + const visibleDefinitions = (tools: HostTools) => definitions(tools).map(({ path, definition }) => ({ path, definition, - description: { - path, - description: definition.description, - signature: `${toolExpression(path)}(input: ${inputTypeScript(definition)}): Promise<${outputTypeScript(definition)}>`, - }, + description: describeDefinition(path, definition), })) export const catalog = (tools: HostTools): ReadonlyArray => @@ -316,11 +334,6 @@ export type DiscoveryPlan = { export type SearchEntry = { readonly description: ToolDescription - /** - * JSDoc-annotated multiline signature shown on search-result items; the compact - * single-line form (inline catalog lines) stays in `description.signature`. - */ - readonly signature: string /** Top-level namespace (first path segment), matched by the search `namespace` option. */ readonly namespace: string /** Lowercased path + description + input property names/descriptions, for substring matching. */ @@ -354,8 +367,75 @@ const termForms = (term: string): Array => { return forms } +const makeSearchTool = (searchIndex: ReadonlyArray): Definition => ({ + _tag: "CodeModeTool", + description: "Search available Code Mode tools", + input: SearchInput, + output: SearchOutput, + run: (input) => + Effect.sync(() => { + const request = input as typeof SearchInput.Type + const query = request.query ?? "" + const offset = request.offset ?? 0 + const scoped = + request.namespace === undefined + ? searchIndex + : searchIndex.filter((entry) => entry.namespace === request.namespace) + // A query that names one tool path exactly (canonical path or rendered JavaScript + // expression) is a lookup, not a search: return that tool alone. + const trimmed = query.trim() + const pathQuery = trimmed.startsWith("tools.") ? trimmed.slice("tools.".length) : trimmed + const exact = + pathQuery === "" + ? undefined + : scoped.find( + (entry) => entry.description.path === pathQuery || toolExpression(entry.description.path) === trimmed, + ) + const terms = tokenize(query).map(termForms) + // Additive field-weighted scoring, summed across terms: exact path or path segment + // (20) > path substring (8) > description substring (4) > any searchable text, + // including input parameter names and descriptions (2). + const ranked = + exact !== undefined + ? [exact] + : scoped + .map((entry) => { + const path = entry.description.path.toLowerCase() + const description = entry.description.description.toLowerCase() + const score = terms.reduce( + (total, forms) => + total + + (forms.some((form) => path === form || path.endsWith(`.${form}`)) ? 20 : 0) + + (forms.some((form) => path.includes(form)) ? 8 : 0) + + (forms.some((form) => description.includes(form)) ? 4 : 0) + + (forms.some((form) => entry.searchText.includes(form)) ? 2 : 0), + 0, + ) + return { entry, score } + }) + .filter(({ score }) => terms.length === 0 || score > 0) + .sort( + (left, right) => + right.score - left.score || left.entry.description.path.localeCompare(right.entry.description.path), + ) + .map(({ entry }) => entry) + const items = ranked.slice(offset, offset + (request.limit ?? defaultSearchLimit)).map(({ description }) => ({ + ...description, + path: toolExpression(description.path), + })) + const remaining = Math.max(0, ranked.length - offset - items.length) + return { + items, + remaining, + next: remaining > 0 ? { offset: offset + items.length } : null, + } + }), +}) + +const searchDescription = describeDefinition(`${reservedNamespace}.search`, makeSearchTool([])) + const catalogLine = (tool: ToolDescription) => { - // Inline catalog lines use only a compact first line; full text stays in search results. + // Keep the tool description concise; the full schema documentation remains in the signature. const line = tool.description.split("\n", 1)[0]!.trim() const description = line.length > 120 ? line.slice(0, 119) + "..." : line return description === "" ? ` - ${tool.signature}` : ` - ${tool.signature} // ${description}` @@ -363,7 +443,6 @@ const catalogLine = (tool: ToolDescription) => { const toSearchEntry = (path: string, definition: Definition, description: ToolDescription): SearchEntry => ({ description, - signature: `${toolExpression(path)}(input: ${inputTypeScript(definition, true)}): Promise<${outputTypeScript(definition, true)}>`, namespace: path.split(".", 1)[0]!, searchText: [ path, @@ -388,7 +467,7 @@ export const assertValidTools = (tools: HostTools): void => { /** * Budgeted catalog: every namespace is always listed with its tool count; full call - * signatures are inlined against the `maxInlineCatalogTokens` budget (estimated tokens, + * signatures are inlined against the `catalogBudget` (estimated tokens, * chars/4) round-robin across namespaces - in each round (namespaces alphabetical), every * namespace still holding un-inlined tools attempts to place its next-cheapest line, and * a namespace whose next line does not fit is done while the others keep going - so every @@ -397,12 +476,9 @@ export const assertValidTools = (tools: HostTools): void => { * namespace. Namespace stub lines are never budgeted: every namespace appears with its * tool count even at budget 0. */ -export const discoveryPlan = ( - tools: HostTools, - maxInlineCatalogTokens = defaultMaxInlineCatalogTokens, -): DiscoveryPlan => { - if (!Number.isSafeInteger(maxInlineCatalogTokens) || maxInlineCatalogTokens < 0) { - throw new RangeError("discovery.maxInlineCatalogTokens must be a non-negative safe integer") +export const prepare = (tools: HostTools, catalogBudget = defaultCatalogBudget): DiscoveryPlan => { + if (!Number.isSafeInteger(catalogBudget) || catalogBudget < 0) { + throw new RangeError("discovery.catalogBudget must be a non-negative safe integer") } const visible = visibleDefinitions(tools) const described = visible.map(({ description }) => description) @@ -437,7 +513,7 @@ export const discoveryPlan = ( for (const selection of active) { const tool = selection.queue[0]! const cost = estimateTokens(catalogLine(tool)) - if (used + cost > maxInlineCatalogTokens) continue + if (used + cost > catalogBudget) continue selection.queue.shift() selection.picked.add(tool) used += cost @@ -458,13 +534,14 @@ export const discoveryPlan = ( // catalog at the bottom. Example call forms use placeholders - never a real or fabricated // tool name - and show both dot and bracket notation so non-identifier names are not normalized. const intro = [ - "Write a CodeMode program to answer the request. Return code only.", empty - ? "Execute JavaScript in a confined runtime." + ? "This is a restricted JavaScript language for calling tools, not a general-purpose runtime." : complete - ? "Execute JavaScript in a confined runtime. Inside this program, `tools` contains only the host-provided tools listed below; surrounding agent tools are not available unless listed here." - : "Execute JavaScript in a confined runtime. Inside this program, `tools` contains only the host-provided tools listed or searchable below; surrounding agent tools are not available unless listed here.", - ...(empty ? [] : ["Do not infer or normalize tool names; use only exact signatures shown below or returned by search."]), + ? "This is a restricted JavaScript language for calling tools, not a general-purpose runtime. Inside the confined interpreter, `tools` contains the Code Mode tools listed below and internal runtime tools; surrounding agent tools are not available." + : "This is a restricted JavaScript language for calling tools, not a general-purpose runtime. Inside the confined interpreter, `tools` contains the Code Mode tools listed or searchable below and internal runtime tools; surrounding agent tools are not available.", + ...(empty + ? [] + : ["Do not infer or normalize tool names; use only exact signatures shown below or returned by search."]), ] // The search step exists only when search is advertised (PARTIAL catalog); a COMPLETE @@ -478,16 +555,12 @@ export const discoveryPlan = ( ...(complete ? [ "1. Pick a tool from the list under `## Available tools` - each line is the exact call signature; use it as-is rather than guessing segments.", - '2. Call it using the exact signature shown; bracket notation and quotes are part of the path.', - '3. Parse text results: `const data = typeof res === "string" ? JSON.parse(res) : res` - most tools return JSON as a string.', - "4. Return only the fields you need: `return { : data. }` - raw payloads get truncated and waste context.", + "2. Call it using the exact signature shown: `const result = await tools..(input)`; bracket notation and quotes are part of the path.", + "3. Return only the fields you need from structured results; narrow unknown results before reading fields, and avoid returning large raw payloads.", ] : [ - '1. If the exact signature is not listed below, first search: `const { items } = await tools.$codemode.search({ query: "" })`.', - "2. Read the matches: each item is `{ path, description, signature }` - read the description before using an unfamiliar tool.", - "3. Call the result's `path` as-is; bracket notation and quotes are part of the path.", - '4. Parse text results: `const data = typeof res === "string" ? JSON.parse(res) : res` - most tools return JSON as a string.', - "5. Return only the fields you need: `return { : data. }` - raw payloads get truncated and waste context.", + '1. If needed, discover tools: `return await tools.$codemode.search({ query: "" })`.', + "2. In the next execution, copy a returned path exactly, call it, and return only the needed fields.", ]), ] @@ -498,24 +571,26 @@ export const discoveryPlan = ( "## Rules", "", complete - ? "- Only tools listed here are available inside `tools`; tools from the surrounding agent/runtime are not implicitly exposed." - : "- Only tools listed here or returned by `tools.$codemode.search` are available inside `tools`; tools from the surrounding agent/runtime are not implicitly exposed.", + ? "- Only Code Mode tools listed here and internal runtime tools are available; surrounding agent tools are not implicitly exposed." + : "- Only Code Mode tools listed here or returned by `tools.$codemode.search` and internal runtime tools are available; surrounding agent tools are not implicitly exposed.", "- Filter, aggregate, and transform collections in code - never return them raw or call a tool per item across messages.", - "- A result typed `Promise` has no guaranteed shape - verify what actually came back before relying on its fields.", + "- A result typed `Promise` may be structured data or text. Before reading fields, check that it is a non-null object and not an array; otherwise handle the returned text or primitive directly.", '- Run independent calls in parallel: `await Promise.all(items.map((item) => tools..(item)))`, or use `tools.["tool-name"](item)` when the listed signature uses bracket notation.', "- `Object.keys(tools)` lists namespaces; `Object.keys(tools.)` lists its tools; `for...in` works on both.", ...(complete ? [] - : ['- Browse one namespace: `await tools.$codemode.search({ query: "", namespace: "" })`.']), + : [ + '- Browse one namespace: `await tools.$codemode.search({ query: "", namespace: "" })`.', + "- If search returns `next`, repeat the same search with `offset: next.offset`.", + ]), ] - const syntax = [ + const language = [ "", - "## Syntax", + "## Language", "", - "Standard modern JavaScript works: functions/closures, destructuring, template literals, loops, try/catch, spread, optional chaining, the usual Array/String/Object/Math/JSON methods, plus Date, RegExp, Map, Set, and Promise.all/allSettled/race/resolve/reject.", - "TypeScript type annotations are allowed and stripped before execution (decorators are not supported).", - "Not supported (each fails with a message naming the alternative): classes, generators, for await...of, .then/.catch/.finally (use await with try/catch).", + "Use common JavaScript data operations, functions, control flow, selected standard-library methods, and awaited tool calls.", + "Modules/imports, classes, generators, timers, fetch, eval, prototype access, arbitrary methods, and promise chaining are unavailable. Use Code Mode tools for external operations. Use await with try/catch.", "Dates serialize to ISO strings at data boundaries; Map/Set/RegExp serialize to `{}`.", ] @@ -544,11 +619,11 @@ export const discoveryPlan = ( for (const tool of group) if (picked.has(tool)) toolSection.push(catalogLine(tool)) } if (!complete) { - toolSection.push("", "Search returns complete callable signatures:", `- ${searchSignature}`) + toolSection.push("", "Search returns complete callable signatures:", `- ${searchDescription.signature}`) } } - const lines = [...intro, ...workflow, ...rules, ...syntax, ...toolSection] + const lines = [...intro, ...workflow, ...rules, ...language, ...toolSection] return { catalog: described, instructions: lines.join("\n"), @@ -557,20 +632,13 @@ export const discoveryPlan = ( } /** - * The enumerable names at one node of the host tool tree - namespace names at the root, + * The enumerable names at one node of the callable tool tree - namespace names at the root, * tool/namespace names below - powering `Object.keys(tools)` and `for...in` over tool * references. A callable tool is a leaf and enumerates as `[]` (like `Object.keys` of a * function in JS). An unknown path is an `UnknownTool` error pointing at the working * discovery idioms, mirroring how calling an unknown tool fails. */ -const namespaceKeys = ( - tools: HostTools, - path: ReadonlyArray, - searchEnabled: boolean, -): ReadonlyArray => { - // The reserved discovery namespace is virtual (never present in the host tree); enumerate - // it explicitly so `Object.keys(tools.$codemode)` matches the callable surface. - if (searchEnabled && path.length === 1 && path[0] === reservedNamespace) return ["search"] +const namespaceKeys = (tools: HostTools, path: ReadonlyArray): ReadonlyArray => { let value: HostTool | Definition | HostTools = tools for (const segment of path) { if ( @@ -579,15 +647,9 @@ const namespaceKeys = ( isDefinition(value) || !Object.hasOwn(value, segment) ) { - throw new ToolRuntimeError( - "UnknownTool", - `Unknown tool namespace '${path.join(".")}'.`, - searchEnabled - ? [ - "Object.keys(tools) lists the available namespaces; tools.$codemode.search({ query }) finds described tools.", - ] - : ["Object.keys(tools) lists the available namespaces."], - ) + throw new ToolRuntimeError("UnknownTool", `Unknown tool namespace '${path.join(".")}'.`, [ + "Object.keys(tools) lists the available namespaces; tools.$codemode.search({ query }) finds described tools.", + ]) } value = value[segment] as HostTool | Definition | HostTools } @@ -595,11 +657,7 @@ const namespaceKeys = ( return Object.keys(value) } -const resolve = ( - tools: HostTools, - path: ReadonlyArray, - searchEnabled: boolean, -): HostTool | Definition => { +const resolve = (tools: HostTools, path: ReadonlyArray): HostTool | Definition => { let value: HostTool | Definition | HostTools = tools for (const segment of path) { @@ -609,11 +667,9 @@ const resolve = ( isDefinition(value) || !Object.hasOwn(value, segment) ) { - throw new ToolRuntimeError( - "UnknownTool", - `Unknown tool '${path.join(".")}'.`, - searchEnabled ? ["Use tools.$codemode.search({ query }) to find available described tools."] : [], - ) + throw new ToolRuntimeError("UnknownTool", `Unknown tool '${path.join(".")}'.`, [ + "Use tools.$codemode.search({ query }) to find available described tools.", + ]) } value = value[segment] as HostTool | Definition | HostTools } @@ -629,7 +685,7 @@ export type ToolRuntime = { readonly root: ToolReference readonly calls: Array readonly invoke: (path: ReadonlyArray, args: Array) => Effect.Effect - /** Enumerable namespace/tool names at one node of the host tool tree; see `namespaceKeys`. */ + /** Enumerable namespace/tool names at one node of the callable tool tree; see `namespaceKeys`. */ readonly keys: (path: ReadonlyArray) => ReadonlyArray } @@ -637,11 +693,14 @@ export const make = ( tools: HostTools, /** Undefined means unlimited tool calls. */ maxToolCalls: number | undefined, + searchIndex: ReadonlyArray, hooks?: ToolCallHooks, - searchIndex?: ReadonlyArray, ): ToolRuntime => { const calls: Array = [] - const searchEnabled = searchIndex !== undefined + const callableTools = { + ...tools, + [reservedNamespace]: { search: makeSearchTool(searchIndex) }, + } // Wraps the settling portion of a tool call so onToolCallEnd observes success and failure // symmetrically. Interruption (e.g. the execution timeout) fires neither outcome. @@ -680,7 +739,7 @@ export const make = ( return { root: new ToolReference([]), calls, - keys: (path) => namespaceKeys(tools, path, searchEnabled), + keys: (path) => namespaceKeys(callableTools, path), invoke: (path, args) => Effect.gen(function* () { const name = path.join(".") @@ -691,107 +750,7 @@ export const make = ( recordCall(call) return calls.length - 1 }).pipe(Effect.tap((index) => hooks?.onToolCallStart?.({ index, name, input }) ?? Effect.void)) - if (name === "$codemode.search") { - if (!searchEnabled) throw new ToolRuntimeError("UnknownTool", `Unknown tool '${name}'.`) - const input = externalArgs[0] - if (externalArgs.length !== 1 || input === null || typeof input !== "object" || Array.isArray(input)) { - throw new ToolRuntimeError( - "InvalidToolInput", - "tools.$codemode.search expects { query?: string; namespace?: string; limit?: number }.", - ) - } - const request = input as { query?: unknown; namespace?: unknown; limit?: unknown } - if (request.query !== undefined && typeof request.query !== "string") { - throw new ToolRuntimeError( - "InvalidToolInput", - "tools.$codemode.search query must be a string when provided.", - ) - } - if (request.namespace !== undefined && typeof request.namespace !== "string") { - throw new ToolRuntimeError( - "InvalidToolInput", - "tools.$codemode.search namespace must be a string when provided.", - ) - } - if ( - request.limit !== undefined && - (typeof request.limit !== "number" || !Number.isSafeInteger(request.limit) || request.limit <= 0) - ) { - throw new ToolRuntimeError( - "InvalidToolInput", - "tools.$codemode.search limit must be a positive safe integer when provided.", - ) - } - const query = typeof request.query === "string" ? request.query : "" - const namespace = typeof request.namespace === "string" ? request.namespace : undefined - const index = yield* recordAndObserve(request) - return yield* observeEnd( - Effect.try({ - try: () => { - const limit = typeof request.limit === "number" ? request.limit : defaultSearchLimit - const scoped = - namespace === undefined ? searchIndex : searchIndex.filter((entry) => entry.namespace === namespace) - // A query that names one tool path exactly (canonical path or rendered - // JavaScript expression) is a lookup, not a search: return that tool alone. - const trimmed = query.trim() - const pathQuery = trimmed.startsWith("tools.") ? trimmed.slice("tools.".length) : trimmed - const exact = - pathQuery === "" - ? undefined - : scoped.find( - (entry) => - entry.description.path === pathQuery || toolExpression(entry.description.path) === trimmed, - ) - const terms = tokenize(query).map(termForms) - // Additive field-weighted scoring, summed across terms: exact path or path - // segment (20) > path substring (8) > description substring (4) > any - // searchable text, incl. input parameter names/descriptions (2). Each term - // matches a field when any of its forms (the term or a singular variant) - // does. An empty query browses everything, alphabetical by path. - const ranked = - exact !== undefined - ? [exact] - : scoped - .map((entry) => { - const path = entry.description.path.toLowerCase() - const description = entry.description.description.toLowerCase() - const score = terms.reduce( - (total, forms) => - total + - (forms.some((form) => path === form || path.endsWith(`.${form}`)) ? 20 : 0) + - (forms.some((form) => path.includes(form)) ? 8 : 0) + - (forms.some((form) => description.includes(form)) ? 4 : 0) + - (forms.some((form) => entry.searchText.includes(form)) ? 2 : 0), - 0, - ) - return { entry, score } - }) - .filter(({ score }) => terms.length === 0 || score > 0) - .sort( - (left, right) => - right.score - left.score || - left.entry.description.path.localeCompare(right.entry.description.path), - ) - .map(({ entry }) => entry) - // Result paths are rendered as JavaScript expressions so each `path` is - // directly usable as the call site (`await tools.github.list({ ... })` or - // `await tools.ns["dashed-name"]({ ... })`). The signature is the pretty, - // JSDoc-annotated form (schema descriptions and constraints ride along as - // field comments). - const items = ranked.slice(0, limit).map(({ description, signature }) => ({ - ...description, - path: toolExpression(description.path), - signature, - })) - return copyIn({ items, total: ranked.length }, "Result from tool '$codemode.search'") - }, - catch: (cause) => cause, - }), - { index, name, input: request }, - ) - } - - const tool = resolve(tools, path, searchEnabled) + const tool = resolve(callableTools, path) let describedInput: unknown if (isDefinition(tool)) { if (externalArgs.length !== 1) diff --git a/packages/codemode/src/tool-schema.ts b/packages/codemode/src/tool-schema.ts index 65c444083f0..16213fa8eeb 100644 --- a/packages/codemode/src/tool-schema.ts +++ b/packages/codemode/src/tool-schema.ts @@ -187,9 +187,9 @@ const renderSchema = ( if (properties.length === 0 && indexType === undefined) return "{}" const pad = " ".repeat(depth + 1) const lines = properties.map( - (entry) => `${jsdoc(entry[1].description, docTags(entry[1]), pad)}${pad}${field(entry)}`, + (entry) => `${jsdoc(entry[1].description, docTags(entry[1]), pad)}${pad}${field(entry)},`, ) - if (indexType !== undefined) lines.push(`${pad}[key: string]: ${indexType}`) + if (indexType !== undefined) lines.push(`${pad}[key: string]: ${indexType},`) return `{\n${lines.join("\n")}\n${" ".repeat(depth)}}` } return "unknown" diff --git a/packages/codemode/test/codemode.test.ts b/packages/codemode/test/codemode.test.ts index 087678c778c..f5a7169cf55 100644 --- a/packages/codemode/test/codemode.test.ts +++ b/packages/codemode/test/codemode.test.ts @@ -426,7 +426,7 @@ describe("CodeMode schema flexibility", () => { { path: "adapter.call", description: "Call an adapter-described tool", - signature: "tools.adapter.call(input: { id: string; count?: number }): Promise", + signature: "tools.adapter.call(input: {\n id: string,\n count?: number,\n}): Promise", }, ]) @@ -459,7 +459,7 @@ describe("CodeMode schema flexibility", () => { { path: "users.lookup", description: "Look up a user", - signature: "tools.users.lookup(input: { login: string }): Promise<{ login: string; id: number }>", + signature: "tools.users.lookup(input: {\n login: string,\n}): Promise<{\n login: string,\n id: number,\n}>", }, ]) @@ -475,7 +475,7 @@ describe("CodeMode schema flexibility", () => { run: () => Effect.succeed("pong"), }) const runtime = CodeMode.make({ tools: { net: { ping } } }) - expect(runtime.catalog()[0]?.signature).toBe("tools.net.ping(input: { host: string }): Promise") + expect(runtime.catalog()[0]?.signature).toBe("tools.net.ping(input: {\n host: string,\n}): Promise") const result = await Effect.runPromise(runtime.execute(`return await tools.net.ping({ host: "example.test" })`)) expect(result.ok).toBe(true) @@ -512,19 +512,19 @@ describe("CodeMode public contract", () => { { path: "orders.lookup", description: "Look up an order by ID", - signature: "tools.orders.lookup(input: { id: string }): Promise<{ id: string; status: string }>", + signature: "tools.orders.lookup(input: {\n id: string,\n}): Promise<{\n id: string,\n status: string,\n}>", }, ]) expect(runtime.instructions()).toContain("Available tools (COMPLETE list") expect(runtime.instructions()).toContain("- orders (1 tool)") expect(runtime.instructions()).toContain( - " - tools.orders.lookup(input: { id: string }): Promise<{ id: string; status: string }> // Look up an order by ID", + " - tools.orders.lookup(input: {\n id: string,\n}): Promise<{\n id: string,\n status: string,\n}> // Look up an order by ID", ) // A fully inlined catalog does not advertise search in the instructions... expect(runtime.instructions()).not.toMatch(/\$codemode/) - // ...but the search tool stays registered, so a speculative call still works. Search - // results carry the pretty multiline signature; the inline catalog stays compact. + // ...but the search tool stays registered, so a speculative call still works with the + // same signature as the inline catalog. const result = await Effect.runPromise(runtime.execute(`return await tools.$codemode.search({ query: "order" })`)) expect(result.ok).toBe(true) if (result.ok) { @@ -533,10 +533,12 @@ describe("CodeMode public contract", () => { { path: "tools.orders.lookup", description: "Look up an order by ID", - signature: "tools.orders.lookup(input: {\n id: string\n}): Promise<{\n id: string\n status: string\n}>", + signature: + "tools.orders.lookup(input: {\n id: string,\n}): Promise<{\n id: string,\n status: string,\n}>", }, ], - total: 1, + remaining: 0, + next: null, }) } }) @@ -554,11 +556,11 @@ describe("CodeMode public contract", () => { { path: "context7.resolve-library-id", description: "Resolve a library ID", - signature: 'tools.context7["resolve-library-id"](input: { libraryName: string }): Promise', + signature: 'tools.context7["resolve-library-id"](input: {\n libraryName: string,\n}): Promise', }, ]) expect(runtime.instructions()).toContain( - 'tools.context7["resolve-library-id"](input: { libraryName: string }): Promise', + 'tools.context7["resolve-library-id"](input: {\n libraryName: string,\n}): Promise', ) const search = await Effect.runPromise( @@ -571,10 +573,11 @@ describe("CodeMode public contract", () => { { path: 'tools.context7["resolve-library-id"]', description: "Resolve a library ID", - signature: 'tools.context7["resolve-library-id"](input: {\n libraryName: string\n}): Promise', + signature: 'tools.context7["resolve-library-id"](input: {\n libraryName: string,\n}): Promise', }, ], - total: 1, + remaining: 0, + next: null, }) } @@ -588,7 +591,7 @@ describe("CodeMode public contract", () => { runtime.execute(`return await tools.$codemode.search({ query: 'tools.context7["resolve-library-id"]' })`), ) expect(exact.ok).toBe(true) - if (exact.ok) expect((exact.value as { total: number }).total).toBe(1) + if (exact.ok) expect(exact.value).toMatchObject({ remaining: 0, next: null }) }) test("instructions use markdown sections with placeholder-only call forms", () => { @@ -597,23 +600,26 @@ describe("CodeMode public contract", () => { // Sections in order: workflow at the top, catalog at the bottom. expect(instructions).toContain("## Workflow") expect(instructions).toContain("## Rules") - expect(instructions).toContain("## Syntax") + expect(instructions).toContain("## Language") expect(instructions.indexOf("## Workflow")).toBeLessThan(instructions.indexOf("## Rules")) - expect(instructions.indexOf("## Rules")).toBeLessThan(instructions.indexOf("## Syntax")) - expect(instructions.indexOf("## Syntax")).toBeLessThan(instructions.indexOf("\n## Available tools (COMPLETE list")) - // The workflow carries the result-shape guidance; Rules only add content beyond it. - expect(instructions).toContain( - '`const data = typeof res === "string" ? JSON.parse(res) : res` - most tools return JSON as a string', + expect(instructions.indexOf("## Rules")).toBeLessThan(instructions.indexOf("## Language")) + expect(instructions.indexOf("## Language")).toBeLessThan( + instructions.indexOf("\n## Available tools (COMPLETE list"), ) + expect(instructions).not.toContain("JSON.parse(res)") expect(instructions).toContain("Return only the fields you need") - expect(instructions).toContain("raw payloads get truncated and waste context") + expect(instructions).toContain("avoid returning large raw payloads") expect(instructions).toContain("Do not infer or normalize tool names") expect(instructions).toContain("bracket notation and quotes are part of the path") - expect(instructions).toContain("surrounding agent tools are not available unless listed here") - expect(instructions).toContain("Only tools listed here are available inside `tools`") + expect(instructions).toContain("surrounding agent tools are not available") + expect(instructions).toContain("Only Code Mode tools listed here and internal runtime tools") // Placeholders use generic namespace/tool/field names only - no fabricated real tools // and no real catalog tools cherry-picked into example lines. - expect(instructions).toContain("`return { : data. }`") + expect(instructions).toContain("`const result = await tools..(input)`") + expect(instructions).toContain("Return only the fields you need from structured results") + expect(instructions).toContain("check that it is a non-null object and not an array") + expect(instructions).not.toContain("result.") + expect(instructions).not.toContain("data.") expect(instructions).not.toContain("total_count") expect(instructions).not.toContain("list_issues") expect(instructions).not.toContain("tools.orders.lookup({") @@ -621,36 +627,35 @@ describe("CodeMode public contract", () => { expect(instructions).toContain("1. Pick a tool from the list under `## Available tools`") expect(instructions).not.toContain("Browse one namespace") - const partial = CodeMode.make({ tools, discovery: { maxInlineCatalogTokens: 0 } }).instructions() + const partial = CodeMode.make({ tools, discovery: { catalogBudget: 0 } }).instructions() // PARTIAL: the workflow starts with search (with query-style guidance that is clearly // a query string, never a tool name) and the browse-namespace rule appears. expect(partial).toContain( - '1. If the exact signature is not listed below, first search: `const { items } = await tools.$codemode.search({ query: "" })`.', + '1. If needed, discover tools: `return await tools.$codemode.search({ query: "" })`.', ) + expect(partial).toContain("In the next execution, copy a returned path exactly") expect(partial).toContain( - "Only tools listed here or returned by `tools.$codemode.search` are available inside `tools`", + "Only Code Mode tools listed here or returned by `tools.$codemode.search` and internal runtime tools", ) expect(partial).toContain( '- Browse one namespace: `await tools.$codemode.search({ query: "", namespace: "" })`.', ) + expect(partial).toContain("repeat the same search with `offset: next.offset`") + expect(partial).toContain(" limit?: number,\n offset?: number,") expect(partial).not.toContain("total_count") expect(partial).not.toContain("tools.orders.lookup({") }) - test("the syntax section names what is unusual or missing, not an allowlist", () => { + test("the language section describes the restricted runtime without overclaiming", () => { const instructions = CodeMode.make({ tools }).instructions() - // Models already know JavaScript; the section leads with that. - expect(instructions).toContain("Standard modern JavaScript works") - expect(instructions).toContain("TypeScript type annotations are allowed and stripped before execution") - // The not-supported list is derived from (and verified against) the interpreter. - expect(instructions).toContain("Not supported") - for (const missing of ["classes", "generators", "for await...of", ".then/.catch/.finally"]) { + expect(instructions).toContain("restricted JavaScript language for calling tools") + expect(instructions).toContain("not a general-purpose runtime") + expect(instructions).not.toContain("Standard modern JavaScript works") + expect(instructions).not.toContain("TypeScript type annotations") + for (const missing of ["Modules/imports", "classes", "generators", "fetch", "promise chaining"]) { expect(instructions).toContain(missing) } - // Implemented by the DSL-expansion pass, so no longer listed as missing. - expect(instructions).not.toContain("instanceof Error") - expect(instructions).not.toContain("splice") - // The data-boundary note survives. + expect(instructions).toContain("Use Code Mode tools for external operations") expect(instructions).toContain( "Dates serialize to ISO strings at data boundaries; Map/Set/RegExp serialize to `{}`.", ) @@ -660,7 +665,7 @@ describe("CodeMode public contract", () => { const runtime = CodeMode.make({}) const instructions = runtime.instructions() expect(instructions).toContain("No tools are currently available.") - expect(instructions).toContain("## Syntax") + expect(instructions).toContain("## Language") expect(instructions).toContain("## Available tools") expect(instructions).not.toContain("## Workflow") expect(instructions).not.toContain("## Rules") @@ -682,7 +687,7 @@ describe("CodeMode public contract", () => { }) const runtime = CodeMode.make({ tools: { thread: { uploadFile: upload, generateImage: generate }, orders: { lookup } }, - discovery: { maxInlineCatalogTokens: 0 }, + discovery: { catalogBudget: 0 }, }) expect(runtime.instructions()).toContain( "Available tools (PARTIAL - 0 of 3 shown; find the rest with tools.$codemode.search)", @@ -707,15 +712,16 @@ describe("CodeMode public contract", () => { { path: "tools.thread.uploadFile", description: "Upload one readable local file to the current Discord thread", - signature: "tools.thread.uploadFile(input: {\n path: string\n}): Promise<{\n sent: boolean\n}>", + signature: "tools.thread.uploadFile(input: {\n path: string,\n}): Promise<{\n sent: boolean,\n}>", }, { path: "tools.thread.generateImage", description: "Generate an image and upload it to the current Discord thread", - signature: "tools.thread.generateImage(input: {\n prompt: string\n}): Promise<{\n sent: boolean\n}>", + signature: "tools.thread.generateImage(input: {\n prompt: string,\n}): Promise<{\n sent: boolean,\n}>", }, ], - total: 2, + remaining: 0, + next: null, }) expect(result.toolCalls).toStrictEqual([{ name: "$codemode.search" }]) @@ -761,9 +767,14 @@ describe("CodeMode public contract", () => { const browse = await Effect.runPromise(runtime.execute(`return await tools.$codemode.search({})`)) expect(browse.ok).toBe(true) if (browse.ok) { - const value = browse.value as { items: Array<{ path: string }>; total: number } + const value = browse.value as { + items: Array<{ path: string }> + remaining: number + next: { offset: number } | null + } expect(value.items).toHaveLength(10) - expect(value.total).toBe(14) + expect(value.remaining).toBe(4) + expect(value.next).toStrictEqual({ offset: 10 }) } for (const query of ["many.tool13", "tools.many.tool13"]) { @@ -777,10 +788,11 @@ describe("CodeMode public contract", () => { { path: "tools.many.tool13", description: "Numbered tool 13", - signature: "tools.many.tool13(input: {\n id: string\n}): Promise", + signature: "tools.many.tool13(input: {\n id: string,\n}): Promise", }, ], - total: 1, + remaining: 0, + next: null, }) } } @@ -807,8 +819,8 @@ describe("CodeMode public contract", () => { ) expect(browse.ok).toBe(true) if (browse.ok) { - const value = browse.value as { items: Array<{ path: string }>; total: number } - expect(value.total).toBe(2) + const value = browse.value as { items: Array<{ path: string }>; remaining: number } + expect(value.remaining).toBe(0) expect(value.items.map((item) => item.path)).toStrictEqual([ "tools.github.create_issue", "tools.github.list_issues", @@ -821,8 +833,8 @@ describe("CodeMode public contract", () => { ) expect(scoped.ok).toBe(true) if (scoped.ok) { - const value = scoped.value as { items: Array<{ path: string }>; total: number } - expect(value.total).toBe(1) + const value = scoped.value as { items: Array<{ path: string }>; remaining: number } + expect(value.remaining).toBe(0) expect(value.items[0]?.path).toBe("tools.linear.list_issues") } @@ -858,8 +870,8 @@ describe("CodeMode public contract", () => { ) expect(byParameter.ok).toBe(true) if (byParameter.ok) { - const value = byParameter.value as { items: Array<{ path: string }>; total: number } - expect(value.total).toBe(1) + const value = byParameter.value as { items: Array<{ path: string }>; remaining: number } + expect(value.remaining).toBe(0) expect(value.items[0]?.path).toBe("tools.files.upload") } @@ -869,8 +881,8 @@ describe("CodeMode public contract", () => { ) expect(bySubstring.ok).toBe(true) if (bySubstring.ok) { - const value = bySubstring.value as { items: Array<{ path: string }>; total: number } - expect(value.total).toBe(1) + const value = bySubstring.value as { items: Array<{ path: string }>; remaining: number } + expect(value.remaining).toBe(0) expect(value.items[0]?.path).toBe("tools.files.upload") } }) @@ -898,8 +910,8 @@ describe("CodeMode public contract", () => { ) expect(plural.ok).toBe(true) if (plural.ok) { - const value = plural.value as { items: Array<{ path: string }>; total: number } - expect(value.total).toBe(1) + const value = plural.value as { items: Array<{ path: string }>; remaining: number } + expect(value.remaining).toBe(0) expect(value.items[0]?.path).toBe("tools.tracker.fetch_all") } @@ -907,8 +919,8 @@ describe("CodeMode public contract", () => { const ranked = await Effect.runPromise(runtime.execute(`return await tools.$codemode.search({ query: "issues" })`)) expect(ranked.ok).toBe(true) if (ranked.ok) { - const value = ranked.value as { items: Array<{ path: string }>; total: number } - expect(value.total).toBe(2) + const value = ranked.value as { items: Array<{ path: string }>; remaining: number } + expect(value.remaining).toBe(0) expect(value.items.map((item) => item.path)).toStrictEqual([ "tools.github.list_issues", "tools.tracker.fetch_all", @@ -934,13 +946,33 @@ describe("CodeMode public contract", () => { const browse = await Effect.runPromise(runtime.execute(`return await tools.$codemode.search({})`)) expect(browse.ok).toBe(true) if (browse.ok) { - const value = browse.value as { items: Array<{ path: string }>; total: number } + const value = browse.value as { items: Array<{ path: string }>; remaining: number; next: unknown } expect(value.items.map((item) => item.path)).toStrictEqual([ "tools.alpha.aardvark", "tools.alpha.beta", "tools.zeta.last", ]) + expect(value.remaining).toBe(0) + expect(value.next).toBeNull() } + + const middle = await Effect.runPromise( + runtime.execute(`return await tools.$codemode.search({ limit: 1, offset: 1 })`), + ) + expect(middle.ok).toBe(true) + if (middle.ok) { + expect(middle.value).toMatchObject({ + items: [{ path: "tools.alpha.beta" }], + remaining: 1, + next: { offset: 2 }, + }) + } + + const exhausted = await Effect.runPromise( + runtime.execute(`return await tools.$codemode.search({ limit: 1, offset: 3 })`), + ) + expect(exhausted.ok).toBe(true) + if (exhausted.ok) expect(exhausted.value).toStrictEqual({ items: [], remaining: 0, next: null }) }) test("inlines round-robin across namespaces so one expensive namespace cannot starve the rest", () => { @@ -965,7 +997,7 @@ describe("CodeMode public contract", () => { // other namespaces from inlining (beta already got its line in the same round). const runtime = CodeMode.make({ tools: { alpha: { cheap, expensive }, beta: { cheap } }, - discovery: { maxInlineCatalogTokens: 40 }, + discovery: { catalogBudget: 40 }, }) const instructions = runtime.instructions() @@ -973,14 +1005,38 @@ describe("CodeMode public contract", () => { "Available tools (PARTIAL - 2 of 3 shown; find the rest with tools.$codemode.search)", ) expect(instructions).toContain("- alpha (2 tools, 1 shown)") - expect(instructions).toContain(" - tools.alpha.cheap(input: { q: string }): Promise // Cheap") + expect(instructions).toContain(" - tools.alpha.cheap(input: {\n q: string,\n}): Promise // Cheap") expect(instructions).not.toContain("tools.alpha.expensive(") // Fully shown namespaces read cleanly (no "shown" annotation). expect(instructions).toContain("- beta (1 tool)") - expect(instructions).toContain(" - tools.beta.cheap(input: { q: string }): Promise // Cheap") + expect(instructions).toContain(" - tools.beta.cheap(input: {\n q: string,\n}): Promise // Cheap") expect(instructions).toMatch(/\$codemode\.search/) }) + test("charges inline JSDoc against the catalog token budget", () => { + const documented = Tool.make({ + description: "Look up a record", + input: { + type: "object", + properties: { + id: { type: "string", description: "A detailed identifier description. ".repeat(20) }, + }, + required: ["id"], + } as const, + run: () => Effect.succeed("ok"), + }) + const runtime = CodeMode.make({ + tools: { records: { lookup: documented } }, + discovery: { catalogBudget: 40 }, + }) + + expect(runtime.catalog()[0]?.signature).toContain("/** A detailed identifier description.") + expect(runtime.instructions()).toContain( + "Available tools (PARTIAL - 0 of 1 shown; find the rest with tools.$codemode.search)", + ) + expect(runtime.instructions()).not.toContain("tools.records.lookup(input:") + }) + test("decodes tool input and output before exposing either side", async () => { const observed: Array = [] const transformed = Tool.make({ @@ -1031,17 +1087,27 @@ describe("CodeMode public contract", () => { expect(() => CodeMode.execute({ code: "return 1", limits: { maxToolCalls: -1 } })).toThrow(RangeError) expect(() => CodeMode.execute({ code: "return 1", limits: { maxOutputBytes: -1 } })).toThrow(RangeError) - expect(() => CodeMode.make({ tools, discovery: { maxInlineCatalogTokens: -1 } })).toThrow(RangeError) + expect(() => CodeMode.make({ tools, discovery: { catalogBudget: -1 } })).toThrow(RangeError) const result = await Effect.runPromise( CodeMode.make({ tools, - discovery: { maxInlineCatalogTokens: 0 }, + discovery: { catalogBudget: 0 }, }).execute(`return await tools.$codemode.search({ query: "order", limit: 0.5 })`), ) expect(result.ok).toBe(false) if (result.ok) return expect(result.error.kind).toBe("InvalidToolInput") + + for (const offset of [-1, 0.5, Number.MAX_SAFE_INTEGER + 1, "1"]) { + const invalidOffset = await Effect.runPromise( + CodeMode.make({ tools }).execute( + `return await tools.$codemode.search({ query: "order", offset: ${JSON.stringify(offset)} })`, + ), + ) + expect(invalidOffset.ok).toBe(false) + if (!invalidOffset.ok) expect(invalidOffset.error.kind).toBe("InvalidToolInput") + } }) test("enforces the tool-call limit as a diagnostic", async () => { diff --git a/packages/codemode/test/enumeration.test.ts b/packages/codemode/test/enumeration.test.ts index 87c075a7928..0de3dc3ea0d 100644 --- a/packages/codemode/test/enumeration.test.ts +++ b/packages/codemode/test/enumeration.test.ts @@ -41,7 +41,7 @@ describe("Object.keys over tool references", () => { const namespaces = Object.keys(tools) return { namespaces, count: namespaces.length } `), - ).toEqual({ namespaces: ["github", "memory", "playwright"], count: 3 }) + ).toEqual({ namespaces: ["github", "memory", "playwright", "$codemode"], count: 4 }) }) test("enumerates tool names at a nested namespace", async () => { @@ -52,7 +52,7 @@ describe("Object.keys over tool references", () => { expect(await value(`return Object.keys(tools.github.list_issues)`)).toEqual([]) }) - test("the virtual discovery namespace enumerates its callable surface", async () => { + test("the internal discovery namespace enumerates its callable surface", async () => { expect(await value(`return Object.keys(tools.$codemode)`)).toEqual(["search"]) }) @@ -137,7 +137,7 @@ describe("for...in", () => { ).toBe("only") }) - test("enumerates namespaces and tools from the host tool tree", async () => { + test("enumerates namespaces and tools from the callable tool tree", async () => { expect( await value(` const names = [] @@ -146,7 +146,7 @@ describe("for...in", () => { } return names `), - ).toEqual(["github.list_issues", "github.get_issue", "memory.search", "playwright.navigate"]) + ).toEqual(["github.list_issues", "github.get_issue", "memory.search", "playwright.navigate", "$codemode.search"]) }) test("unsupported values fail with a hint at for...of and Object.keys", async () => { diff --git a/packages/codemode/test/signature.test.ts b/packages/codemode/test/signature.test.ts index 47345be7d77..232c6dcb221 100644 --- a/packages/codemode/test/signature.test.ts +++ b/packages/codemode/test/signature.test.ts @@ -40,21 +40,21 @@ describe("pretty signature rendering", () => { [ "{", " /** Repository owner */", - " owner: string", + " owner: string,", " /** Cursor from the previous response's pageInfo */", - " after?: string", + " after?: string,", " /**", " * Results per page", " * @default 30", " */", - " perPage?: number", + " perPage?: number,", " /**", " * Filter by labels", " * @minItems 1", " * @maxItems 10", " */", - " labels?: Array", - ' state?: "open" | "closed"', + " labels?: Array,", + ' state?: "open" | "closed",', "}", ].join("\n"), ) @@ -83,18 +83,24 @@ describe("pretty signature rendering", () => { true, ) expect(pretty).toBe( - ["{", " /** Search filter */", " filter?: {", " /** Issue state */", " state?: string", " }", "}"].join( - "\n", - ), + [ + "{", + " /** Search filter */", + " filter?: {", + " /** Issue state */", + " state?: string,", + " },", + "}", + ].join("\n"), ) }) test("Effect Schema annotations become JSDoc on input and output fields", () => { expect(inputTypeScript(lookupOrder, true)).toBe( - ["{", " /** Order identifier */", " id: string", " verbose?: boolean", "}"].join("\n"), + ["{", " /** Order identifier */", " id: string,", " verbose?: boolean,", "}"].join("\n"), ) expect(outputTypeScript(lookupOrder, true)).toBe( - ["{", " /** Current order status */", " status: string", "}"].join("\n"), + ["{", " /** Current order status */", " status: string,", "}"].join("\n"), ) }) @@ -129,7 +135,7 @@ describe("pretty signature rendering", () => { { type: "object", properties: { size: { type: "number", default: 1n } } }, true, ) - expect(pretty).toBe(["{", " size?: number", "}"].join("\n")) + expect(pretty).toBe(["{", " size?: number,", "}"].join("\n")) }) test("neutralizes */ inside descriptions so nothing closes the comment early", () => { @@ -150,7 +156,7 @@ describe("pretty signature rendering", () => { true, ) expect(pretty).toBe( - ["{", " /**", " * First line", " *", " * Second line", " */", " query?: string", "}"].join("\n"), + ["{", " /**", " * First line", " *", " * Second line", " */", " query?: string,", "}"].join("\n"), ) }) @@ -235,12 +241,12 @@ describe("non-identifier property names render as quoted keys", () => { expect(jsonSchemaToTypeScript(rawSchema, true)).toBe( [ "{", - ' "123"?: number', - ' "foo-bar"?: string', - ' "@type": string', + ' "123"?: number,', + ' "foo-bar"?: string,', + ' "@type": string,', " /** Dotted name */", - ' "x.y"?: number', - " plain?: boolean", + ' "x.y"?: number,', + " plain?: boolean,", "}", ].join("\n"), ) @@ -259,7 +265,7 @@ describe("non-identifier property names render as quoted keys", () => { }) expect(inputTypeScript(tool)).toContain('"foo-bar"?: string') expect(outputTypeScript(tool)).toBe('{ "content-type": string }') - expect(outputTypeScript(tool, true)).toBe(["{", ' "content-type": string', "}"].join("\n")) + expect(outputTypeScript(tool, true)).toBe(["{", ' "content-type": string,', "}"].join("\n")) }) test("Effect Schema structs with non-identifier field names quote too", () => { @@ -269,7 +275,7 @@ describe("non-identifier property names render as quoted keys", () => { run: () => Effect.succeed(null), }) expect(inputTypeScript(tool)).toBe('{ "foo-bar": string; plain?: number }') - expect(inputTypeScript(tool, true)).toBe(["{", ' "foo-bar": string', " plain?: number", "}"].join("\n")) + expect(inputTypeScript(tool, true)).toBe(["{", ' "foo-bar": string,', " plain?: number,", "}"].join("\n")) }) }) @@ -308,10 +314,7 @@ describe("union schemas render every alternative", () => { test("allOf renders intersections with parenthesized union members", () => { const schema = { - allOf: [ - { type: "object", properties: { id: { type: "string" } } }, - { type: ["string", "null"] }, - ], + allOf: [{ type: "object", properties: { id: { type: "string" } } }, { type: ["string", "null"] }], } as const expect(jsonSchemaToTypeScript(schema)).toBe("{ id?: string } & (string | null)") }) @@ -321,7 +324,9 @@ describe("union schemas render every alternative", () => { "unknown", ) expect( - jsonSchemaToTypeScript({ allOf: [{ type: "string" }, { allOf: [{ $ref: "https://example.com/external.json" }] }] }), + jsonSchemaToTypeScript({ + allOf: [{ type: "string" }, { allOf: [{ $ref: "https://example.com/external.json" }] }], + }), ).toBe("unknown") expect( jsonSchemaToTypeScript({ @@ -333,7 +338,7 @@ describe("union schemas render every alternative", () => { }) }) -describe("pretty signatures in search results", () => { +describe("JSDoc signatures in catalogs and search results", () => { const runtime = CodeMode.make({ tools: { github: { list_issues: listIssues }, orders: { lookup: lookupOrder } } }) const search = async (query: string) => { @@ -342,7 +347,7 @@ describe("pretty signatures in search results", () => { ) expect(result.ok).toBe(true) if (!result.ok) throw new Error("search failed") - return result.value as { items: Array<{ path: string; signature: string }>; total: number } + return result.value as { items: Array<{ path: string; signature: string }>; remaining: number } } test("a raw JSON Schema (MCP-style) tool's result signature carries field JSDoc and tags", async () => { @@ -352,21 +357,21 @@ describe("pretty signatures in search results", () => { [ "tools.github.list_issues(input: {", " /** Repository owner */", - " owner: string", + " owner: string,", " /** Cursor from the previous response's pageInfo */", - " after?: string", + " after?: string,", " /**", " * Results per page", " * @default 30", " */", - " perPage?: number", + " perPage?: number,", " /**", " * Filter by labels", " * @minItems 1", " * @maxItems 10", " */", - " labels?: Array", - ' state?: "open" | "closed"', + " labels?: Array,", + ' state?: "open" | "closed",', "}): Promise", ].join("\n"), ) @@ -380,26 +385,26 @@ describe("pretty signatures in search results", () => { [ "tools.orders.lookup(input: {", " /** Order identifier */", - " id: string", - " verbose?: boolean", + " id: string,", + " verbose?: boolean,", "}): Promise<{", " /** Current order status */", - " status: string", + " status: string,", "}>", ].join("\n"), ) } }) - test("the inline catalog line for the same tool stays single-line compact", () => { + test("the inline catalog uses the same JSDoc signatures", async () => { const instructions = runtime.instructions() - expect(instructions).toContain( - ' - tools.github.list_issues(input: { owner: string; after?: string; perPage?: number; labels?: Array; state?: "open" | "closed" }): Promise // List issues in a repository', - ) - expect(instructions).toContain( - " - tools.orders.lookup(input: { id: string; verbose?: boolean }): Promise<{ status: string }> // Look up an order", - ) - expect(instructions).not.toContain("/**") + const github = (await search("list issues repository")).items.find( + ({ path }) => path === "tools.github.list_issues", + )! + const orders = (await search("look up order")).items.find(({ path }) => path === "tools.orders.lookup")! + expect(instructions).toContain(` - ${github.signature} // List issues in a repository`) + expect(instructions).toContain(` - ${orders.signature} // Look up an order`) + expect(instructions).toContain("/** Repository owner */") }) }) @@ -422,7 +427,7 @@ describe("non-identifier tool paths", () => { const instructions = runtime.instructions() expect(instructions).toContain( - 'tools.context7["resolve-library-id"](input: { query: string; libraryName: string }): Promise', + 'tools.context7["resolve-library-id"](input: {\n query: string,\n libraryName: string,\n}): Promise', ) expect(instructions).toContain("Do not infer or normalize tool names") expect(instructions).toContain("bracket notation and quotes are part of the path") diff --git a/packages/core/test/mcp.test.ts b/packages/core/test/mcp.test.ts index e40e8dfb2c9..18005fe8e78 100644 --- a/packages/core/test/mcp.test.ts +++ b/packages/core/test/mcp.test.ts @@ -183,7 +183,7 @@ it.effect("advertises MCP output schemas to Code Mode", () => yield* waitForTool(registry, "execute") const execute = (yield* toolDefinitions(registry)).find((tool) => tool.name === "execute") - expect(execute?.description).toContain("tools.demo.search(input: {}): Promise<{ ok: boolean }>") + expect(execute?.description).toContain("tools.demo.search(input: {}): Promise<{\n ok: boolean,\n}>") }), ) From 04e8801f5b3f796f03043db3f7ce55b56d88d26d Mon Sep 17 00:00:00 2001 From: "opencode-agent[bot]" <219766164+opencode-agent[bot]@users.noreply.github.com> Date: Mon, 6 Jul 2026 09:30:55 -0500 Subject: [PATCH 03/46] fix(tui): soften interrupted step styling (#35466) Co-authored-by: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> --- packages/tui/src/routes/session/index.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/tui/src/routes/session/index.tsx b/packages/tui/src/routes/session/index.tsx index 93bffbeb7c3..194ab498cf6 100644 --- a/packages/tui/src/routes/session/index.tsx +++ b/packages/tui/src/routes/session/index.tsx @@ -1200,9 +1200,10 @@ function AssistantFooter(props: { message: SessionMessageAssistant }) { const duration = createMemo(() => props.message.time.completed ? props.message.time.completed - props.message.time.created : 0, ) + const interrupted = createMemo(() => props.message.error?.message === "Step interrupted") return ( <> - + {errorMessage(props.message.error)} - + {Locale.titlecase(props.message.agent)} @@ -1224,6 +1225,9 @@ function AssistantFooter(props: { message: SessionMessageAssistant }) { · {Locale.duration(duration())} + + · interrupted + From 5b2d90a441e0bcc13c514a28df3a48ab11f42e8c Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Mon, 6 Jul 2026 10:36:02 -0500 Subject: [PATCH 04/46] feat(codemode): expand standard library support (#35566) --- packages/codemode/README.md | 7 +- packages/codemode/codemode.md | 1337 +++-------------------- packages/codemode/src/codemode.ts | 454 +++++++- packages/codemode/src/tool-runtime.ts | 36 +- packages/codemode/src/values.ts | 19 +- packages/codemode/test/codemode.test.ts | 4 +- packages/codemode/test/stdlib.test.ts | 224 +++- 7 files changed, 833 insertions(+), 1248 deletions(-) diff --git a/packages/codemode/README.md b/packages/codemode/README.md index afd178a36cf..37bde2d8696 100644 --- a/packages/codemode/README.md +++ b/packages/codemode/README.md @@ -243,12 +243,13 @@ CodeMode executes a deliberately bounded JavaScript subset. It supports: - Optional chaining, nullish coalescing, templates, spread (arrays, strings, Maps, Sets), and `try`/`catch`. - Common array, string, number, `Object`, `Math`, and `JSON` operations. Mutating array methods include `push`/`pop`/`shift`/`unshift`/`splice` (removes in place and returns the removed elements)/`fill`/`copyWithin`; array `keys`/`values`/`entries` return **arrays** (matching the Map/Set convention) and work with `for...of` and spread. String methods include `localeCompare` (locale/options arguments ignored), `normalize`, and the `trimLeft`/`trimRight` aliases. `Object.keys` also accepts arrays (index strings, as in JS) and tool references: `Object.keys(tools)` lists the top-level namespaces, including `$codemode`, and `Object.keys(tools.ns)` lists the names at that node (a callable tool enumerates as `[]`; an unknown path is an `UnknownTool` diagnostic). `Object.values`/`Object.entries` on a tool reference fail with a pointer at `Object.keys(tools)` and `tools.$codemode.search`. - `Date` - `Date.now()`/`Date.parse()`/`Date.UTC()`, `new Date(...)`, the getter methods, and date arithmetic/comparison via the time value. Dates stringify as ISO (`toString` included, for determinism across host timezones). -- Regular expressions - `/literals/` and `new RegExp(...)` with `test`/`exec` (stateful `lastIndex` for `g`), plus string `match`/`matchAll`/`replace`/`replaceAll`/`split`/`search` with patterns. Match results are arrays carrying `index` and named `groups` as own properties (`input` is omitted). Invalid patterns, invalid flags, and missing-`g` calls fail with catchable errors that say what was wrong and how to fix it (escaping hints, the exact `/pattern/g` to write). Patterns run on the host engine, so pathological backtracking is bounded only by the execution timeout. Function replacers are not supported. +- Regular expressions - `/literals/` and `new RegExp(...)` with `test`/`exec` (stateful `lastIndex` for `g`), plus string `match`/`matchAll`/`replace`/`replaceAll`/`split`/`search` with patterns. Match results are arrays carrying `index` and named `groups` as own properties (`input` is omitted). `replace` and `replaceAll` accept function replacers with captures, offset, input, and named groups; callbacks run sequentially, may await tool calls, and have their results coerced to strings. Invalid patterns, invalid flags, and missing-`g` calls fail with catchable errors that say what was wrong and how to fix it (escaping hints, the exact `/pattern/g` to write). Patterns run on the host engine, so pathological backtracking is bounded only by the execution timeout. - `Map` and `Set` - construction from entries/arrays/strings, `get`/`set`/`add`/`has`/`delete`/`clear`/`size`/`forEach`, and `keys`/`values`/`entries` returning **arrays** (not iterators). +- URL helpers - `URL` resolution and mutation, linked `URLSearchParams`, `URL.canParse`/`URL.parse`, URI and URI-component encoding/decoding, and query parameter construction, lookup, mutation, sorting, callbacks, and materialization. URLSearchParams iteration methods return arrays, matching the Map/Set convention. - First-class promises - an un-awaited `tools.ns.tool(...)` is a promise value whose call starts immediately on a supervised fiber; `await` resolves it (awaiting a non-promise value is a no-op, and `return tools.ns.tool(...)` resolves like an async-function return). `Promise.all`, `Promise.allSettled`, and `Promise.race` accept any array mixing promises and plain values (built inline, beforehand, or via spread); `Promise.resolve`/`Promise.reject` construct settled promises. `Promise.allSettled` rejection reasons are the same plain `{ name?, message }` data a `catch` binding sees, and `Promise.race` interrupts its losing in-flight calls. At most 8 tool calls run concurrently. When a program completes, still-running un-awaited calls are awaited before the execution ends; a failure from a call that was never awaited surfaces as an unhandled-rejection diagnostic. -- `throw value` and `throw new Error(message)` for explicit program failure. `Error` (and `TypeError`/`RangeError`/`SyntaxError`/`ReferenceError`/`EvalError`/`URIError`) are real constructors, callable with or without `new`; error values are plain `{ name, message }` data that additionally satisfy `instanceof Error` (a specific type matches itself and `Error`, as in JS). Every caught failure - thrown errors, interpreter runtime errors, and tool failures - is `instanceof Error` in a `catch` block; a thrown non-error value (`throw "text"`) is not, matching JS. Caught failures carry the `name` the equivalent real-JS failure would have - `JSON.parse` and invalid regex patterns produce a `SyntaxError` (satisfying `instanceof SyntaxError`), an unknown identifier a `ReferenceError`, assigning to a constant a `TypeError`, a bad `normalize` form a `RangeError`; failures with no specific analogue (including tool failures) are named `"Error"`. `instanceof` also recognizes `Date`, `RegExp`, `Map`, `Set`, `Array`, `Object`, and `Promise`; any other right-hand side is a catchable error. +- `throw value` and `throw new Error(message)` for explicit program failure. `Error` (and `TypeError`/`RangeError`/`SyntaxError`/`ReferenceError`/`EvalError`/`URIError`) are real constructors, callable with or without `new`; error values are plain `{ name, message }` data that additionally satisfy `instanceof Error` (a specific type matches itself and `Error`, as in JS). Every caught failure - thrown errors, interpreter runtime errors, and tool failures - is `instanceof Error` in a `catch` block; a thrown non-error value (`throw "text"`) is not, matching JS. Caught failures carry the `name` the equivalent real-JS failure would have - `JSON.parse` and invalid regex patterns produce a `SyntaxError` (satisfying `instanceof SyntaxError`), an unknown identifier a `ReferenceError`, assigning to a constant a `TypeError`, a bad `normalize` form a `RangeError`; failures with no specific analogue (including tool failures) are named `"Error"`. `instanceof` also recognizes `Date`, `RegExp`, `Map`, `Set`, `URL`, `URLSearchParams`, `Array`, `Object`, and `Promise`; any other right-hand side is a catchable error. -Inside a program, Date/RegExp/Map/Set values stay live everywhere: the internal data checkpoints (`Object.*` helpers, spread, coercion inputs) preserve the instances, so `Object.values({ d: date })[0].getTime()` and a spread copy of an object holding a Map keep working. Only at the host boundary (final result, tool arguments, `JSON.stringify`) do the four value types serialize exactly as `JSON.stringify` would: a Date becomes its ISO string (`null` when invalid) and RegExp/Map/Set become `{}`. Promise values never cross a data boundary: an un-awaited promise in a result or tool argument produces a diagnostic that says to await it, instead of serializing to `{}`. +Inside a program, standard-library values stay live everywhere: the internal data checkpoints (`Object.*` helpers, spread, coercion inputs) preserve the instances, so `Object.values({ d: date })[0].getTime()` and a spread copy of an object holding a Map keep working. Only at the host boundary (final result, tool arguments, `JSON.stringify`) do they serialize exactly as `JSON.stringify` would: Date and URL become strings (an invalid Date becomes `null`), while RegExp, Map, Set, and URLSearchParams become `{}`. Promise values never cross a data boundary: an un-awaited promise in a result or tool argument produces a diagnostic that says to await it, instead of serializing to `{}`. It does not expose `eval`, dynamic imports, modules, classes, generators, timers, host globals, prototype mutation, custom promise constructors (`new Promise`), promise chaining (`.then`/`.catch`/`.finally` - `await` with `try`/`catch` is the supported style), or arbitrary method calls. Unsupported syntax returns an `UnsupportedSyntax` diagnostic with a source location when available. diff --git a/packages/codemode/codemode.md b/packages/codemode/codemode.md index 8f14ed6a974..71bb3f27cf2 100644 --- a/packages/codemode/codemode.md +++ b/packages/codemode/codemode.md @@ -1,1233 +1,166 @@ -# CodeMode - Status, Decisions, and Remaining Work +# CodeMode Design and Status -This document is the working plan for `@opencode-ai/codemode` and its OpenCode integration. -It captures every locked decision, everything already implemented, and a detailed TODO of what -remains - enough context that someone (human or agent) can pick up any item cold. +This is the living design and status document for `@opencode-ai/codemode` and its existing V2 OpenCode adapter. +It records current behavior, intentional boundaries, durable rationale, and material remaining work. -Tracking issue: https://github.com/anomalyco/opencode/issues/34787 -Working branch: `codemode-v2` (base: `dev`) +Completed implementation history, branch names, test counts, and closed findings belong in git, not here. Remove +completed work instead of preserving checked-off chronology. ---- +Detailed package API documentation lives in [README.md](./README.md). OpenAPI-specific follow-ups live in +[src/openapi/TODO.md](./src/openapi/TODO.md). -## 1. What this is +## How CodeMode Works -CodeMode gives a model one `execute` tool that runs JavaScript/TypeScript programs against a -tree of schema-described tools (`tools..(input)`), instead of exposing dozens -of MCP tools individually. The point is **control flow**: sequencing, filtering, and composing -tool calls in one program instead of round-tripping through the agent loop, plus not flooding -the context window when users connect many MCP servers. +### Purpose -Architecture split (locked): +CodeMode gives a model one `execute` tool backed by a confined JavaScript interpreter. Inside the program, the model +can call an explicit tree of schema-described tools, sequence dependent work, run independent calls concurrently, +and filter or aggregate results before returning them to the agent loop. -- **`packages/codemode` (`@opencode-ai/codemode`)** - the generic, host-agnostic runtime: - a hand-rolled, Effect-native, tree-walking interpreter over acorn ASTs (TypeScript stripped - via `typescript`'s `transpileModule`), the tool runtime/data boundary, discovery/search, and - `Tool.make`. It knows nothing about OpenCode, MCP, permissions, or rendering. -- **`packages/opencode`** - the OpenCode integration: an MCP adapter that converts MCP tool - definitions into `Tool.make(...)` definitions, permission gating, host-side attachment - collection, the agent-facing `execute` tool, and TUI progress rendering. +The goals are: -This package was seeded from the experiments workspace implementation -(`experiments/agents/packages/codemode`, package `@agents/codemode`) and then modified here. -The older vendored interpreter in `packages/opencode/src/session/rune/` was superseded by this -package and was **deleted** in Wave 3 (done, see below). +- Reduce model context consumed by large tool catalogs. +- Avoid an agent round-trip between every dependent tool call. +- Keep large intermediate results inside the program instead of sending them through model context. +- Give generated code only the authority explicitly supplied by the host. ---- +CodeMode is an orchestration language, not a general JavaScript runtime or an application authorization system. -## 2. Locked decisions +### Runtime -From issue #34787 and design discussion. Do not relitigate these casually. +The generic runtime lives in `packages/codemode` and is host-neutral: -### Core direction +1. The host builds a tree of `Tool.make(...)` definitions and calls `CodeMode.make(...)` or `CodeMode.execute(...)`. +2. CodeMode generates model instructions, a budgeted inline catalog, and the internal `$codemode.search` tool. +3. TypeScript syntax is transpiled away, Acorn parses the resulting JavaScript, and an owned tree-walking interpreter + executes it without `eval`. +4. Tool inputs and outputs cross schema and plain-data boundaries before they become visible on either side. +5. Execution returns `CodeMode.Result`. Expected program and tool failures are diagnostic data; host interruption + remains Effect interruption. -- Generic CodeMode lives in its own package: `@opencode-ai/codemode` (repo scope convention; - the issue's `@opencode/codemode` name was normalized to the `@opencode-ai/*` convention). -- **Keep the hand-rolled interpreter.** No QuickJS/V8/sandbox-engine dependency. We own and - test the whole surface; the model only needs orchestration syntax, not a full runtime. -- Naming: `CodeMode`, `Tool`, `ToolError`, `UnknownTool` (diagnostic kind), `$codemode` - reserved discovery namespace. (Historical names - "rune", "capability" - are dead.) -- Existing OpenCode core tools (bash/edit/patch/...) stay registered normally for v1. - CodeMode covers MCP tools, user-registered tools, and deferred tools only. -- Test runner is `bun test`; typecheck is `tsgo --noEmit` (repo conventions). Not vitest. -- **Never reference external prior-art implementations** (other companies' code-execution - products/blog posts) in code, comments, commit messages, or docs in this repo. +Effect Schemas validate and transform tool inputs and outputs. JSON Schemas render model-facing signatures but do not +validate values; adapter-provided values still cross the plain-data boundary. A tool without an output schema is +advertised as `Promise`. -### MCP / tools +### Discovery and model workflow -- The MCP adapter lives in OpenCode, not here. It converts MCP definitions into ordinary - `Tool.make(...)` definitions and hands CodeMode a plain tool tree. -- Permissions stay in the OpenCode adapter (each tool's `run` wraps the permission ask). - CodeMode stays dumb - no permission model in this package. -- Namespace collisions: last write wins (plain JS object override). No `tools.mcp.*` prefix, - no `_2` suffixing, no cleverness. OpenCode groups flat `server_tool` MCP names into - `tools..` namespaces before handing them over. +The model sees a token-budgeted catalog. Every namespace remains visible, and complete signatures are selected +round-robin across namespaces so one large namespace cannot starve the others. `$codemode.search` is always callable +and is advertised when the inline catalog is partial. -### Discovery / search +The intended workflow is: -- **Search only - no separate `describe`.** `tools.$codemode.search({ query?, namespace?, -limit?, offset? })` over the final tool tree, owned by this package. -- Search result item shape: `{ path, description, signature }` in an - `{ items, remaining, next }` - wrapper. The `signature` string embeds the full input/output TypeScript types and uses the - same pretty, JSDoc-annotated multiline form in inline catalogs and search results, so - per-field schema `description`s and constraints (`@default`, `@format`, `@deprecated`, - `@minItems`, `@maxItems`) ride along as field comments. The original spec's separate `input`/`output` - raw-schema fields are deliberately NOT added: shapes are already fully expressed in the - TypeScript signature and schema annotations now arrive as JSDoc - intent satisfied, letter - deviated. Result `path`s render a JavaScript expression rooted at `tools` (for example - `tools.github.list_issues` or `tools.context7["resolve-library-id"]`) so each is directly - usable as the call site; the internal `ToolDescription.path` stays unprefixed. -- `offset` is zero-based and defaults to 0. `remaining` counts matches after the current page; - `next` is `{ offset }` when another page exists and `null` on the final page. -- Search is an internal `Tool.make` definition backed by Effect input/output schemas. Its - validation, output checking, call observation, and TypeScript signature use the same path as - host-provided schema tools. Host-only catalog preparation keeps internal tools out of their - own search index; only conditional advertisement remains special. -- Default limit: **10** (done). Exact-path lookup goes through search too: a query equal to a - canonical tool path, `tools.`-prefixed path, or rendered JavaScript expression returns that - tool alone (done). -- Signatures render **native payloads**: `Promise`, NOT `Promise>`. - There is no result envelope; attachments never appear in return types (they are collected - host-side, see below). -- Tools without an output schema render `unknown` as their return type. +1. Pick an exact signature from the inline catalog, or return `$codemode.search(...)` results and use a selected path + in the next execution. +2. Call the exact returned path without guessing or normalizing segments. +3. Narrow `Promise` results before reading fields. +4. Start independent calls together and await them with `Promise.all`. +5. Filter and aggregate inside the program, then return only the data needed by the model. -### Schemas / Tool.make +Search returns directly usable JavaScript paths, descriptions, and complete TypeScript signatures. It supports exact +path lookup, namespace browsing, deterministic ranking, and pagination. -- `Tool.make` carries rich metadata so search can render real signatures. -- Support **Effect Schema** (first-class, validating) and **JSON Schema** (initially - render-only - used for TypeScript rendering; the adapter may validate on its own). Leave - room for Standard Schema later. -- Tool implementations are **Effect-based** for v1 (`run` returns `Effect`). Promise - normalization for plugin authors can come later. +### Tool execution -### Attachments / output +Calling a tool starts its Effect eagerly on a supervised fiber. The returned sandbox promise is run-once and can be +awaited directly or through the supported `Promise` combinators. At most eight tool calls execute concurrently. +Unfinished calls are drained before successful program completion, and an unhandled call failure becomes a diagnostic. -- **No `output.text/file/image` API in v1.** (Deleted in Wave 2.) -- Tool calls return native structured payloads into the sandbox. Files/images emitted by - child tools **never enter the sandbox** - the OpenCode adapter strips and accumulates them - host-side as calls happen, then returns them on the outer `execute` tool result as ordinary - tool-result attachments (OpenCode already has `Tool.ExecuteResult.attachments` -> vision - plumbing in `message-v2.ts`). -- No base64 in CodeMode values, ever. The model routes nothing; it can't accidentally dump - image bytes into context or drop attachments. +The public execution-policy knobs are `timeoutMs`, `maxToolCalls`, and `maxOutputBytes`. The package supplies no +defaults because budgets are host policy. The interpreter also enforces fixed internal boundaries for tool-call +concurrency and data nesting depth. -### Runtime behavior +### Data, files, and failures -- Limits are EXACTLY the three public knobs: `{ timeoutMs, maxToolCalls, maxOutputBytes }` - - matching the original locked spec exactly. NO limit has a default (user direction, Fix 6 - for the first two; extended to `maxOutputBytes` in the truncation-layering fix below): - absent = no timeout / unlimited calls / no output truncation - budgets are host policy. - A host without its own output bounding should set `maxOutputBytes` explicitly, or - oversized results silently flood model context. OpenCode's adapter policy (user - direction): NO limits at all - no timeout, unlimited tool calls (each child call is - permission-gated; user cancel interrupts the execution fiber and its children), and no - CodeMode truncation (output bounding is OpenCode's native tool-output truncation). - The internal limit system that Wave 2 kept behind - an `@internal` `InternalExecutionLimits` type (maxOperations, maxDataBytes, maxValueDepth, - maxCollectionLength, maxSourceBytes, maxAuditBytes, maxConcurrency) was deleted outright in - Fix 5 (see Post-wave fixes). Two internals survive as fixed constants, not knobs: - `TOOL_CALL_CONCURRENCY = 8` (the fork semaphore) and `MAX_VALUE_DEPTH = 32` (the `copyIn` - boundary depth check, kept only because it beats a native stack-overflow RangeError as an - error message; still reports `InvalidDataValue`). -- Truncation layering RESOLVED (user direction): CodeMode truncation is off in OpenCode. - `execute` is a normal `Tool.define` tool, so OpenCode's native tool-output truncation - (50KB / 2000 lines in `tool.ts` + `truncate.ts`, full output dumped to a file) applies to - it with no special-casing - verified by tracing `wrap()` in `tool.ts:130-144` (the - `metadata.truncated` exemption never fires for `execute`). One truncation layer, the - host's. `maxOutputBytes` remains available for hosts without their own bounding. -- Pure-JS built-ins only. **No ambient authority**: no fs, child processes, network/fetch, - process/env, or timers in v1. The agent has the bash tool for that. -- Forgiving JS semantics are locked (see section 3, Wave 1a/1b-i) - missing props read `undefined`, - `typeof` never throws, NaN/Infinity flow in-sandbox, etc. -- `console.*` is captured into `logs` on the result; the host appends them to model-facing - output. Not a tool call; costs no tool budget. -- Simple tool-call **start/end hooks** for nested progress: `onToolCallStart({ index, name, -input })` and `onToolCallEnd({ index, name, input, durationMs, outcome, message? })`. - Interrupted calls fire no end event. No `CurrentToolCall` context service (removed in - Wave 2). +Program results and tool arguments are JSON-like data. Dates become ISO strings at host boundaries; RegExp, Map, and +Set values become `{}` as they do under JSON serialization. Promise and runtime reference values cannot cross the +boundary. ---- +Unknown host failures and invalid outputs are sanitized. `ToolError` is the explicit channel for a safe message that a +tool wants the model to see. Diagnostic categories distinguish parsing, unsupported syntax, unknown tools, invalid +data, tool failures, limits, timeouts, and execution failures. -## 3. Current status (what is already done on `codemode-v2`) +Files and other attachment content stay outside the interpreter. A host may collect them while child tools execute and +attach them to the outer result, but the program receives only the structured tool output. -Everything below is committed and pushed on `codemode-v2` (six commits, in pairs of -generic-package + OpenCode-integration: waves 0-5, Fixes 4-9, then the DSL-expansion pass / -real-JS error names / truncation layering). Verification: from `packages/codemode`, -`bun test` (211 pass / 0 fail across `codemode/parity/stdlib/promise/enumeration/signature`) -and `bun run typecheck`; from `packages/opencode`, `bun run typecheck` and -`bun test test/tool/` (all green - the adapter suites are `test/tool/code-mode.test.ts`, -43 tests, and `test/tool/code-mode-integration.test.ts`, 16 tests, moved from -`test/session/` by the registry promotion; registry coverage in -`test/tool/registry.test.ts`). +### V2 OpenCode adapter -### Wave 0 - scaffold (done) +CodeMode is integrated into V2 through `packages/core/src/tool/registry.ts` and +`packages/core/src/tool/execute.ts`: -- `packages/codemode` created from the experiments implementation: `src/{index,codemode,tool, -tool-error,tool-runtime}.ts`, README, AGENTS.md, tests. -- `package.json`: name `@opencode-ai/codemode`, deps `acorn@8.15.0`, `typescript: catalog:`, - `effect: catalog:` (both repos pin effect `4.0.0-beta.83`; opencode's effect patch only - touches `unstable/httpapi`, which this package doesn't use). -- Tests converted vitest -> `bun:test`. Only src change from verbatim: the `CurrentToolCall` - Context.Service key string renamed to `@opencode-ai/codemode/CurrentToolCall`. +- Core has one canonical `Tool` representation. Location-scoped producers register direct or deferred tools through + `Tools.Service`. +- Each model step snapshots effective registrations, applies catalog visibility filtering, and exposes direct tools + normally. +- When visible deferred tools exist, Core reserves and materializes one `execute` tool. Grouped deferred tools become + CodeMode namespaces instead of flattened model-facing names. +- Each nested call checks that its captured registration is still current before dispatching it. +- Authorization and side-effect ordering remain responsibilities of the leaf tool. Catalog visibility is not execution + authorization. +- Structured child output enters the interpreter. File parts are collected host-side and attached to the outer result. +- Nested call statuses are returned as final `execute` metadata for the TUI. +- `execute` is the one model-facing tool invocation. Nested calls reuse its invocation context and do not independently + run registry hooks or model-output bounding; this keeps complete intermediate structured values available for + in-program filtering. The outer `execute` settlement is the single model-output bounding boundary. +- Core supplies no CodeMode timeout or tool-call limit. User cancellation interrupts the outer invocation and its + supervised children; the outer settlement applies Core's normal output-retention policy. -### Wave 1a - forgiving JS semantics (done) +MCP tools use this canonical path: they register as grouped tools and are deferred while CodeMode is enabled. Existing +output schemas are preserved in generated signatures. Direct Core tools remain direct and are not ambient globals +inside CodeMode. -Ported from the old opencode rune work; `test/parity.test.ts` (24 tests) is the acceptance -spec. The seeded interpreter was deliberately strict; these behaviors replaced that: +## Intentionally Unsupported -- **H1**: NaN/Infinity flow as in-sandbox values (`copyIn` admits them; `NaN`/`Infinity` are - bindable globals; `charCodeAt` returns real NaN). Normalized to `null` only at the data - boundary (`copyOut` - single chokepoint for final results AND tool-call arguments), matching - `JSON.stringify`. Guards like `Number.isNaN(x)` / `parseInt(x) || 0` work. -- **H2/H3**: unknown property reads on strings/numbers/arrays -> `undefined` (incl. under - `?.`), instead of throwing. This was the real-transcript failure: models write - `result?.login ?? result` against JSON-string tool results. -- **H4**: `typeof undeclaredIdentifier` -> `"undefined"` (short-circuits before resolution). -- **H5**: `Boolean`/`String`/`Number` accepted as array callbacks (`filter(Boolean)`). -- **H6**: `{...null}` / `{...undefined}` object spread is a no-op. Array spread of - null/undefined still throws (real JS throws too). - -### Wave 1b-i - stdlib value types: Date, RegExp, Map, Set (done) - -`src/values.ts` holds `SandboxDate/SandboxRegExp/SandboxMap/SandboxSet` (own module so both -`codemode.ts` and `tool-runtime.ts` import without a cycle). Design: - -- Opaque-by-default: all four join `isRuntimeReference`, with explicit carve-outs (member - access allowlists, Date in binary/unary ops, Map/Set in spread/for...of, console formatting, - `containsOpaqueReference` for operator guards; the `runtimeValueBytes` byte-accounting - carve-out died with that machinery in Fix 5). -- **JSON semantics at every boundary and checkpoint**: Date -> ISO string (invalid -> null), - RegExp/Map/Set -> `{}`. `copyIn` also converts host `Date`/`RegExp`/`Map`/`Set` instances the - same way (a host tool may legitimately return them). (Narrowed by the DSL-expansion pass: - intra-sandbox checkpoints now preserve the instances; JSON forms apply at the host - boundary only.) -- Date: `Date.now/parse/UTC`, `new Date(epoch|string|components)`, getters + UTC variants, - `end - start`, `a < b`, `+date`; `toString` is ISO for cross-host determinism. -- RegExp: literals + `new RegExp`, `test`/`exec` (stateful `lastIndex` for `g`), string - `match/matchAll/replace/replaceAll/split/search`. Match results are plain arrays carrying - `index`/named `groups` as own properties (enabled by a general array own-property read fix); - `input` omitted deliberately. Function replacers unsupported (clear error). Patterns run on - the host engine - catastrophic backtracking is bounded only by `timeoutMs` (accepted, in - README). -- Map/Set: full method sets; `keys/values/entries` return **arrays** (not iterators); - `for...of` + spread work; `Object.fromEntries(map)`, `Array.from(map|set)`; SameValueZero - keys (NaN findable). (The incremental byte totals and `maxCollectionLength`/`maxDataBytes` - enforcement this wave added were deleted in Fix 5.) -- Rode along, same spirit: `typeof` never throws for any value (`typeof fn` -> `"function"`), - `!` works on any value, `for...of` over strings, `{...sandboxValue}` no-op, template - interpolation renders `/regex/` and ISO dates directly. - -### Wave 2 - API layer (done) - -The package's public contract, reshaped for the Wave 3 adapter. 101 tests / 0 fail after this -wave; both packages typecheck clean. - -- **`Tool.make` schema flexibility** (`src/tool.ts`): `input`/`output` each accept an Effect - Schema (validating, decoded both directions as before) OR a raw JSON Schema document - (render-only - no validation, values pass through; rendering handles `$defs`/`definitions` - - `$ref`). `output` is **optional** -> signature renders `Promise` and the host - result is exposed as-is. Discrimination via `Schema.isSchema`. New helpers exported from - `tool-schema.ts`: `inputTypeScript`/`outputTypeScript`/`decodeInput`/`decodeOutput`/ - `jsonSchemaToTypeScript`; `tool-runtime.ts` consumes them (no direct `Schema.*` use there - anymore). Types `Tool.JsonSchema`/`Tool.SchemaType` exported from the index. Note: an empty - `Schema.Struct({})` renders as `{ } | Array` (effect's JSON Schema emission) - - cosmetic, fixed in Wave 4. -- **`output.*` API deleted**: `OutputItem`(+Schema), result `output` fields, the `output` - global/namespace dispatch, `invokeOutput`/`outputItem`/helpers, interpreter output fields, - instructions line, README section, seeded tests. AGENTS.md keeps a rephrased - future-design note (channel name stays `output` if it ever returns). -- **Hooks**: `CurrentToolCall` removed entirely (class, provideService, `Services` Exclude - special-casing, index export). `onToolCall` -> `onToolCallStart({ index, name, input })` + - `onToolCallEnd({ index, name, input, durationMs, outcome: "success"|"failure", message? })`. - End fires symmetrically via `Effect.tap`/`tapError` around the settling portion (host run + - output decode + boundary copy; search too - its post-record body is wrapped in `Effect.try` - so failures are typed and observable). `message` is the model-safe failure message - (`ToolError`/`ToolRuntimeError` message, else "Tool execution failed"). Interrupted calls - fire no end event (timeout kills the whole execution anyway). -- **Limits collapse**: public `CodeMode.ExecutionLimits` = `{ timeoutMs?, maxToolCalls?, -maxOutputBytes? }` (defaults 10_000 / 100 / 32_000). This wave kept the other knobs as - internal defaults reachable through an `@internal` `InternalExecutionLimits` type; Fix 5 - later deleted that type and the internal limit system entirely. -- **`maxOutputBytes` truncation** (CodeMode-owned, never fails): applied via `boundOutput` in - a final `Effect.map` over every result path (success/timeout/normalized failure). Oversized - serialized values become truncated text + ` [result truncated: N bytes exceeds the M-byte -output limit; return a smaller value]`; logs keep leading lines within the remaining budget - - `[logs truncated: showing K of N lines]`; result gains `truncated: true` (also added to - `CodeMode.Result`). UTF-8-safe truncation (no split code points). (The in-sandbox - `maxDataBytes` check that used to throw first on oversized raw values died in Fix 5 - - truncation is now the only result-size mechanism.) -- **Search polish**: default limit 12 -> **10** (`defaultSearchLimit`); exact-path lookup - a - trimmed query equal to one tool path (optionally `tools.`-prefixed) returns that tool alone - (`remaining: 0`, `next: null`), bypassing ranking. Tokenization/ranking/shape unchanged. - -### Wave 3 - OpenCode MCP adapter (done) - -`packages/opencode/src/session/code-mode.ts` rewritten as a thin adapter over this package; -the vendored rune interpreter is gone. Same `define(mcpTools, mcpDefs, servers)` signature, so -`tools.ts` gating (flag on + MCP tools exist -> single `execute` tool, early-return suppresses -per-MCP registration; MCP resource tools unaffected) is unchanged. - -- **Tool tree**: `groupByServer` (longest-sanitized-prefix, ported) groups flat `server_tool` - keys into `CatalogEntry`s carrying the raw MCP `inputSchema`/`outputSchema` as render-only - JSON Schema; `toolTree` turns each into `Tool.make({ description, input, output?, run })` - under `tools..`. The agent-facing description is - `CodeMode.make({ tools }).instructions()` over a preview tree (placeholder runs, never - invoked) - so signature rendering, the inline-vs-search switch, and `$codemode.search` - availability all come from this package and stay consistent with execution. -- **`run` path**: per-child permission ask first (`ctx.ask({ permission: entry.key, patterns: -["*"], always: ["*"] })`, exactly the old gating; approving `execute` approves no child). - Denials and host failures are mapped to `toolError(message)` so they surface as safe, - catchable in-program failures (MCP `isError` text propagates as `e.message`; without this - they'd be sanitized to "Tool execution failed"). Dispatch reuses the ai-sdk wrapper from - `catalog.convertTool` (`entry.tool.execute!`), which owns callTool timeouts/progress-reset. -- **Result shaping** (`toSandboxResult`): prefer `structuredContent`; else joined text - content; media (image/audio/resource blob/resource_link) NEVER enters the sandbox - blocks - are stripped into a per-execution `Attachment[]` accumulator, and a media-only result - becomes a marker payload (`"[1 image attached to the result]"`, noun/count adjusted). An - MCP-shaped result with nothing extractable becomes `null`; non-MCP values pass through. - No handles, no `Result` envelope, no base64 in the sandbox, no data-size tuning (the - `maxDataBytes` budget that existed at the time was deleted in Fix 5). -- **Execute result**: `{ output: formatValue(value) + trailing "Logs:" section (success AND -error - logs are plain pre-formatted lines now), attachments: accumulated }` through the - existing `Tool.ExecuteResult.attachments` -> `message-v2.ts` vision plumbing; attachments - ride on both success and error results. Diagnostic `suggestions` not already contained in - the message are appended to error output. Native outer truncation stays on (adapter never - sets `metadata.truncated`); CodeMode's own `maxOutputBytes` (32 KB default at the time) - cut first - since the truncation-layering fix, native truncation is the only layer. - Limits: `{ timeoutMs: 30_000 }` at the time (matched the default MCP request timeout); - killed in Fix 6 - the adapter now passes no limits at all. -- **Progress**: `onToolCallStart`/`onToolCallEnd` -> `ctx.metadata({ toolCalls })` with - `{ tool, status: running|completed|error, input? }` per call index - the exact shape the - TUI `Execute` component (`packages/tui/src/routes/session/index.tsx`) already renders. - `$codemode.search` calls stream through the same channel. -- **Deletions/deps**: `src/session/rune/` (all five files) and - `test/session/rune-parity.test.ts` (superseded by this package's `test/parity.test.ts`) - deleted; `acorn` removed from opencode deps, `typescript` moved back to devDependencies, - `"@opencode-ai/codemode": "workspace:*"` added; `bun install` run (lockfile updated). -- **Tests**: both opencode suites rewritten against the adapter design - - `code-mode.test.ts` (34: grouping, description/signature rendering incl. the large-catalog - search fallback, execution, permission flow + denial, metadata streaming, attachment - accumulation + media-only marker, logs on success/error, truncation marker, - `toSandboxResult`/`formatValue`/`withLogs` units) and `code-mode-integration.test.ts` - (16: real in-memory MCP server; native structured results, attachment accumulation, isError - propagation, logs, permissions, live metadata). Old envelope/attachment-handle/`$rune` - describe/`renderType`/`rankTools` tests died with the old design (58+17+24 -> 34+16). - -### Wave 4 - instructions/prompting + polish (done) - -Instructions are now the budgeted-catalog + prompting-guidance form; verified e2e against a -real MCP config. Package still 101 tests / 0 fail; opencode adapter suites still 34 + 16; both -packages typecheck clean. - -- **Budgeted catalog** (`prepare` in `tool-runtime.ts`): the all-or-nothing - inline/search modes are gone - `DiscoveryMode` deleted, `CodeMode.DiscoveryOptions` is just - `{ maxInlineCatalogBytes? }` (default 16,000 UTF-8 bytes; later converted to - `catalogBudget`, default 4,000 estimated tokens - see Post-wave fixes). Port of - the old opencode - `describe()` `PREVIEW_BUDGET` algorithm, adapted to `ToolDescription`: every namespace is - ALWAYS listed with its tool count; full signature lines - (` - // `) are inlined - cheapest-first (line byte length, path tiebreak) within each namespace, namespaces processed - alphabetically; once one line does not fit, inlining stops for every remaining namespace - (counts only), exactly like the ported algorithm (this stop-everything behavior was later - replaced by round-robin fairness in Fix 8). The header states comprehensiveness - precisely: "Available tools (COMPLETE list - ...)" vs "Available tools (PARTIAL - N of M - shown; find the rest with tools.$codemode.search)"; namespace labels are `(N tools)` / - `(N tools, K shown)` / `(N tools, none shown)`. An empty tree renders "No tools are - currently available." -- **Search always registered** (documented decision): `DiscoveryPlan.searchIndex` is required - and built unconditionally (new exported `ToolRuntime.searchIndex(tools)`; `SearchEntry` type - exported); `CodeMode.execute` (one-shot) passes it too, preserving the - `execute`==`make().execute` law. A speculative `tools.$codemode.search` call on a small - catalog now succeeds instead of `UnknownTool`, and unknown-tool suggestions always point at - search. Search is _advertised_ in the instructions only when the inlined list is PARTIAL, - keeping small-catalog instructions tight. -- **Prompting content** in `instructions()`, mapping 1:1 to the section 5 transcript failures: - parse-string-results-as-JSON, return-small, console-for-intermediates, and - read-the-description-before-calling guidance. (The flat prose layout this wave produced - was later replaced wholesale by the markdown-section restructure - see Post-wave fixes - - which also deleted this wave's worked example.) -- **Cosmetic renderer fixes** (`renderSchema` in `tool-schema.ts`): an object schema with no - properties renders `{}` (was `{ }`), and the empty `Schema.Struct({})` emission - (`anyOf: [{ type: "object" }, { type: "array" }]`, no properties/items) collapses to `{}` - (was `{ } | Array`). -- **Tests**: 4 package discovery tests rewritten for the budgeted behavior (COMPLETE small - catalog + search-still-registered; PARTIAL at budget 0; cheapest-first selection + - per-namespace labels + budget-exhaustion stopping later namespaces; mode-validation - assertion dropped); 3 opencode description assertions updated (COMPLETE/PARTIAL headers, - namespace labels, `(input: {})` rendering, cheapest-first op_0 shown / op_149 not). -- **E2E (verified, headless)**: from the repo root with `OPENCODE_EXPERIMENTAL_CODE_MODE=1`, - the scratch `.opencode/opencode.jsonc` (context7, github, playwright, sentry, memory, - sequential-thinking; left uncommitted/as-is), and `bun packages/opencode/src/index.ts run ---dangerously-skip-permissions -m opencode/claude-sonnet-4-5 "..."`. Confirmed: a single - `execute` tool registered alongside core tools (per-MCP registration suppressed; MCP - resource tools unaffected); the live description read back as "Available tools (PARTIAL - - 56 of 88 shown; find the rest with tools.$codemode.search):" with correct per-namespace - labels (context7/github/memory fully shown; playwright/sentry/sequential-thinking "none - shown" - the alphabetical-exhaustion starvation Fix 8 later replaced with round-robin - fairness); programs executed with in-program `$codemode.search` - calls and returned the correct answer. NOT verified e2e (headless only; covered by - unit/integration tests instead): TUI child-call rendering, attachments becoming visible - images, output truncation. - -### Wave 5 - Promise generalization (done) - -First-class promise values in the interpreter; the direct-tool-call-only `Promise.all` -restriction (and its bespoke AST checks) is gone. Package suite is 136 tests / 0 fail (35 new -in `test/promise.test.ts`); adapter suites and both typechecks unchanged/green; the opencode -adapter needed **no changes**. - -- **Decision: eager fork** (`const p = tools.a.b(x)` starts the call immediately on a - supervised child fiber; `await p` observes its settlement). Chosen over lazy because: - (1) it's spec-faithful - JS promise work starts at call time, so - `const a = t1(); const b = t2(); return [await a, await b]` gets real parallelism instead of - silently sequential awaits; (2) run-once is free - a fiber settles exactly once and - `Fiber.await` is idempotent, so `await p` twice or `Promise.all([p, p])` can never re-invoke - the tool (lazy needs a deferred/latch to match); (3) effect's structured concurrency does the - hard part - `Effect.forkChild` children are auto-supervised (interrupted when the parent - fiber exits) and `Effect.timeoutOrElse` is `raceFirst`, which runs the program on its own - raced fiber, so forked calls cannot escape the timeout (tested: in-flight forks are - interrupted, awaited or abandoned, direct or inside `Promise.all`). -- **Mechanics**: `SandboxPromise` in `values.ts` (fiber-backed for tool calls; fiberless - `immediate` effect for `Promise.resolve`/`reject`). Forks run - `semaphore.withPermit(invoke)` with `startImmediately: true` - a per-execution - `Semaphore.makeUnsafe(TOOL_CALL_CONCURRENCY)` (fixed 8, see Fix 5) caps live calls (the - "Effect.all or equivalent" cap lives where the work is, so combinator joins can be - sequential without losing parallelism), and the tool-call-count charge (`recordCall`) plus - `onToolCallStart` fire at the call site before any await. `await` of a non-promise is a passthrough no-op; a returned - top-level promise resolves like an async-function return (`return tools.a.b(x)` works - without await). -- **Promise combinators are normal functions over values**: `Promise.all`/`allSettled`/`race` - accept any array (or spreadable collection) mixing promises and plain data - inline, built - beforehand, spread, nested in variables. `allSettled` yields - `{ status: "fulfilled", value } | { status: "rejected", reason }` with reasons produced by - the same `caughtErrorValue` helper the `catch` binding uses (factored out of - `evaluateTryStatement`). `race` resolves/rejects with the first settlement and interrupts - losing in-flight calls; awaiting an interrupted loser afterwards is a catchable program - failure ("interrupted because another value settled a Promise.race first"), while any other - interrupt-only settlement keeps propagating as interruption (preserving the - host-interruption law). `Promise.resolve` flattens promises; `Promise.reject` rejects with - the reason via `ProgramThrow`. -- **Opaqueness/boundaries**: promises are runtime references - `typeof` -> `"object"` (real JS), - operators reject them, `copyIn` raises an await-hinting `InvalidDataValue` ("contains an - un-awaited Promise; await tool calls (...) before using their results") for results, tool - arguments, and `JSON.stringify` instead of `{}`. Property access on a promise is a - deliberate error (not the forgiving `undefined`): `.then/.catch/.finally` -> - `UnsupportedSyntax` pointing at `await` + try/catch; anything else -> "await it first". - `new Promise(...)` -> UnsupportedSyntax ("tool calls already return promises"); - `Promise.` lists the five available statics. `console.log(p)` prints - `[Promise (await it to get its value)]`. -- **Program-end drain**: on successful completion the interpreter awaits still-running - un-awaited fibers (like a runtime waiting on in-flight I/O at exit), so fire-and-forget - calls complete deterministically; a failure nobody could have handled surfaces as an - "Unhandled rejection from an un-awaited tool call: ..." diagnostic (kind preserved, - suggestion says to await) - keeping pre-wave failure visibility for un-awaited - statement-position calls. Settlement observation (await/all/allSettled/race) marks a - promise handled; failed executions skip the drain and children are interrupted by - supervision. -- **Deletions/updates**: `evaluatePromiseAll`, `evaluateParallelMap`, `isToolCallExpression`, - `isToolPath`, `forkForParallelCallback`, and `PromiseAllReference` deleted - (`PromiseMethodReference` over `all/allSettled/race/resolve/reject` replaces it); - `supportedSyntaxMessage`, the two instructions lines in `tool-runtime.ts`, and README - "Supported Programs" rewritten for the new surface. -- **Known divergences (deliberate)**: `p === q` on promises throws the operators-need-data - diagnostic instead of comparing identity; `{...promise}` errors instead of JS's silent `{}`; - a per-iteration `await` inside `items.map(async (i) => await tools.x(i))` runs sequentially - (interpreter callbacks compose synchronously) - the parallel idiom is mapping to un-awaited - calls and awaiting `Promise.all`, which the instructions show. - -### Post-wave fixes - -- **Key enumeration: `Object.keys(tools)` + `for...in` (done).** Motivating transcript: a - model tried to enumerate tool namespaces with `Object.keys(tools)` (failed with the generic - "Object.keys input must contain plain objects only." - `tools` is a `ToolReference`, not - plain data) and then `for (const key in tools)` ("Syntax 'ForInStatement' is not - supported"), and had to fall back to guessing namespace names from the instructions - - defeating discovery. Fixes, all in this package: - - `ToolRuntime.make` now returns a `keys(path)` capability (`namespaceKeys` in - `tool-runtime.ts`) threaded into the `Interpreter` alongside `invoke` - the interpreter - still never holds the callable tool tree. `Object.keys(tools)` yields the top-level namespace - names, including the internally registered `$codemode`; `Object.keys(tools.$codemode)` yields - `["search"]`, and `Object.keys(tools.ns)` yields names at that node; a callable tool leaf - enumerates as `[]` (like `Object.keys` of a JS function); an unknown path throws an - `UnknownTool` diagnostic suggesting `Object.keys(tools)` and `$codemode.search` (matching - call-time unknown-tool behavior rather than silently returning `[]`). - - `Object.values`/`Object.entries` (and every other `Object.*` helper) on a tool reference - now fail with "...not plain data. Use Object.keys(tools) for names, or - tools.$codemode.search({ query }) for signatures." instead of the generic message. - - `Object.keys(array)` returns index strings (`["0", "1", ...]`) like real JS (was a - Backlog item). - - `for...in` (ForInStatement) iterates own enumerable string keys of plain objects, index - strings of arrays, and namespace/tool names of tool references - sharing the interpreter's - `enumerableKeys` helper with the `Object.keys` tool path. const/let declarations and bare - identifiers bind the key; break/continue work. Anything else (strings, Map/Set, numbers, - null, ...) is a clear error suggesting `for...of` or `Object.keys` - deliberately smaller - than real JS (which yields indices for strings and zero iterations for Maps/Sets/null). - - `supportedSyntaxMessage`, the instructions loops line, and README "Supported Programs" - mention the new surface; tests in `test/enumeration.test.ts` (14, incl. the exact - transcript program) plus one adapter-level assertion that `Object.keys(tools)` returns - MCP server and CodeMode namespace names. - -- **Search ranking, namespace scoping, prefixed result paths (done).** - Motivation: the Wave 4 e2e run showed a model retrying calls because search-result paths - lacked the `tools.` prefix (a Backlog item), and the word-set ranker missed - parameter-name and partial-word queries. Fixes: - - **Ranking ported from the pre-rebuild implementation** (the `searchTextFor`/`tokenize`/ - `rankTools` algorithm in `packages/opencode/src/session/code-mode.ts` at git HEAD), - replacing the word-set ranker in `tool-runtime.ts`. Searchable text per tool = path + - description + input-schema property names + their `description` strings - extracted by - the new `inputProperties` helper in `tool-schema.ts` (Effect Schemas via - `Schema.toJsonSchemaDocument`, the same emission signature rendering uses; JSON Schemas - read `properties` directly, resolving a trivial top-level `$ref`; try/catch falls back to - path + description). Queries tokenize on camelCase boundaries + non-alphanumeric - separators (empties and `*` dropped). Additive per-term scoring: exact path or - path-segment match 20, path substring 8, description substring 4, searchable-text - substring 2; summed across terms, filtered to score > 0, sorted score desc then path asc - (Fix 8 later made each field check accept the term OR a naive singular variant). - An empty query now browses ALPHABETICALLY by path (was declaration order). Kept: - `{ path, description, signature }` result items, default limit 10, exact-path instant - lookup, input validation errors. - - **Namespace scoping**: `tools.$codemode.search({ query?, namespace?, limit?, offset? })` - - `namespace` (validated as a string when provided) filters `SearchEntry`s to one top-level - namespace before ranking; `{ query: "", namespace: "github" }` lists that namespace - alphabetically. `searchSignature` updated. - - **Callable result paths**: search-result `path`s are rendered as JavaScript expressions - rooted at `tools` (`tools.github.list_issues`, or bracket notation for non-identifier - segments), directly usable as the call site. Internal `ToolDescription.path` stays - unprefixed; only the search RESULT items are rendered this way. Exact-path queries accept - canonical paths and rendered expressions. - - **Instructions** (`prepare`): an explicit calling-convention line and a browse - hint on the search advertisement (both since absorbed into the `## Rules` section by - the instructions restructure below). - - **Tests**: package search/discovery tests updated (prefixed paths, alphabetical browse) - plus new coverage for namespace scoping, parameter-name matching, partial-word substring - matching, alphabetical empty-query order, and prefixed exact-path lookup; one adapter - assertion updated to the prefixed path (suites stay 35 + 16, green). - -- **Instructions restructure: markdown sections, placeholder-only call forms (done).** - The flat prose instructions (which mixed a real catalog tool with fabricated result - fields in the worked example) are replaced by structured markdown in `prepare`, - ordered so the workflow sits at the top (the least likely part of a long description to - be truncated or skimmed away) and the catalog at the bottom (the per-section content - described here was later condensed by Fix 8 and the language-accuracy pass): - - **Intro**: identifies the language as restricted JavaScript for calling tools rather than - a general-purpose runtime. - - **`## Workflow`**: with a partial catalog, return search results from one execution, then - copy a selected path into the next execution. With a complete catalog, pick and call an - inlined signature, then return only the needed fields. - - **`## Rules`**: narrow unknown results at runtime; filter/aggregate large collections in code instead of per-item round-trips; - console.log/warn/error/dir/table for intermediates; `Promise.all` parallelism (no - .then/.catch - await + try/catch); `Object.keys(tools)`/`for...in` enumeration; - browse-one-namespace via search (PARTIAL only); and host-side media handling (files/ - images never enter the program; a media-only call yields a small text marker - wording - verified against the adapter's `toSandboxResult`/`mediaMarker`). - - **`## Language`**: a concise positive capability summary plus the major unavailable - runtime capabilities and the data-boundary serialization note. - - **`## Available tools`**: the budgeted catalog unchanged, with the COMPLETE/PARTIAL - header merged into the section heading (no trailing colon); the search-signature - advertisement follows when PARTIAL (its description-reading and browse clauses moved - to Workflow/Rules). - - Every call form in Workflow/Rules uses explicit `.`/`` - placeholders - the example builder that derived a worked example from the first inlined - catalog tool (`exampleArguments` + the example-selection machinery) is DELETED, so no - real catalog tool is cherry-picked into examples and no fabricated names or fields - appear anywhere in the instructions. Zero tools keep "No tools are currently - available." under minimal sections (intro + Syntax + Available tools). - - **Tests**: the package worked-example test replaced by section-structure/placeholder - assertions (section order; unknown-result + return-small rules present; no - `total_count`/`list_issues`/real-tool example lines; browse hint only when PARTIAL; - zero-tool minimal sections) - 156 pass / 0 fail; adapter suites gain the same - assertions on the built description (still 35 + 16, green). - -**Fix 4 - token-budgeted catalog (was bytes)** (user direction: signatures need a token -budget; namespaces must always be present): - -- `src/token.ts` added: copy of `@opencode-ai/core/util/token` (`round(chars / 4)`), so - the package stays dependency-free; keep in sync if the core heuristic changes. -- `CodeMode.DiscoveryOptions.maxInlineCatalogBytes` -> `catalogBudget` (default 4,000 - estimated tokens ~ the old 16,000 bytes at 4 chars/token - behavior parity, not a size - reduction). `prepare` charges `estimate(catalogLine(tool))` per line; cheapest-first - - stop-on-first-miss unchanged at the time (stop-on-first-miss replaced by round-robin in - Fix 8). Namespace stub lines were and remain unbudgeted - every - namespace always appears with its tool count, even at budget 0 (asserted in package and - adapter tests). -- Ripple: chars/4 rounding erases small line-length differences, so equal-cost lines fall - to the lexicographic path tiebreak; the adapter's PARTIAL test now asserts the - lexicographic tail (`op_99`) is excluded instead of `op_149`. Fixed-prose measurements - (2026-07): preamble ~44 + Workflow ~146 + Rules ~362 + Syntax ~453 ~ 1,100 tokens fixed; - worst-case net description ~ fixed + 4,000 ~ 5,100 estimated tokens. - -**Fix 5 - internal limits removed** (user direction: only the three PUBLIC limits survive as -configurable knobs; the internal limit system dies): - -- `CodeMode.ExecutionLimits` (`timeoutMs` 10_000 / `maxToolCalls` 100 / `maxOutputBytes` 32_000 at - the time; Fix 6 later removed the first two defaults. Same validation: safe integers, - timeoutMs >= 1, others >= 0, RangeError otherwise) is now - the ENTIRE limit surface - exactly the shape section 2's original locked spec named. - `ResolvedExecutionLimits` shrank to those three fields; the `@internal` - `InternalExecutionLimits` type is deleted. -- **Deleted outright**: `maxOperations` and the whole operation-budget machinery - (`recordWork`/`recordOperation`/`budget.operations`, plus the `workUnits`/ - `cheapArrayMethods` cost helpers); `maxSourceBytes` (the pre-parse source-size check); - `maxDataBytes` (every byte-accounting path: `runtimeValueBytes`, `boundedProgramValue`, - the container-size caches (`containerSizes`/`objectCounts`), Map/Set incremental `bytes` - fields in `values.ts`, string-growth `limitString` checks, tool-argument/result byte - checks in `tool-runtime.ts`, and the final-result size check); `maxAuditBytes` (log and - audit-trail byte accounting - `toolCalls` records and the start/end hooks are unchanged); - `maxCollectionLength` (every array-length/object-field-count check - this knob was - actively harmful: an MCP tool returning 20k rows failed). The `OperationLimitExceeded` - and `AuditLimitExceeded` diagnostic kinds are gone from the `DiagnosticKind` union and - `CodeMode.Result` (fine - the package is unreleased). -- **Fixed constants, not knobs**: `TOOL_CALL_CONCURRENCY = 8` (codemode.ts; the fork - semaphore) and `MAX_VALUE_DEPTH = 32` (tool-runtime.ts; the `copyIn` depth check - kept - only because it produces a clearer error than a native stack-overflow RangeError; still - `InvalidDataValue`). The `DataLimits` plumbing through `tool-runtime.ts` is gone - - `copyIn(value, label)` needs no limits argument, and `ToolRuntime.make` takes just - `(tools, maxToolCalls, hooks?, searchIndex?)`. -- **Verified fact**: timeout interruption does NOT depend on the operation budget - the - Effect fiber runtime auto-yields between interpreter steps, so `timeoutMs` interrupts - even a pure `while (true) {}` loop (empirically verified: a 200ms timeout fired at - ~225ms with maxOperations set to MAX_SAFE_INTEGER before the deletion). A regression - test in `codemode.test.ts` asserts exactly this (`while(true){}` + `timeoutMs: 200` -> - `TimeoutExceeded`, elapsed well under a few seconds). -- **Kept (correctness, not budgets)**: circular detection (`copyIn` walks + - `rejectCircularInsertion` on mutations), plain-objects-only, blocked properties - (`__proto__`/`constructor`/`prototype`), data-only checks, and all three public-limit - behaviors unchanged. -- Behavior deltas beyond the intended kills: in-sandbox structures deeper than 32 levels - now fail at the data boundary (`copyIn`) instead of at construction; array index - assignment allows any non-negative integer index (holes permitted, message now "must be - a non-negative integer"); interpreter-produced deep/hostile structures that overflow the - native stack during a walk still normalize to the existing "Execution exceeded the - maximum nesting depth." data diagnostic - failures remain data everywhere. -- Tests: deleted the knob-only tests (stdlib Map/Set collection-length growth x2, - enumeration operation-budget, codemode maxDataBytes/maxSourceBytes/maxOperations/ - maxConcurrency-RangeError assertions, and the adapter's runaway-loop-via-operation-limit - test - superseded by the package timeout regression test); rewrote the helpers that used - `InternalExecutionLimits` as a convenience to plain `CodeMode.ExecutionLimits` - (promise/enumeration/stdlib run helpers). Package suite: 154 pass / 0 fail; adapter - suites: 34 + 16. - -**Fix 6 - no default timeout / tool-call cap** (user direction): `timeoutMs` and -`maxToolCalls` lost their defaults (were 10_000 / 100) - absent now means no timeout / -unlimited calls. Budgets are host policy, not library policy; `maxOutputBytes` kept its -32,000 default at the time (removed later - see the truncation-layering entry: absent now -means no truncation). `ResolvedExecutionLimits` carries `number | undefined` for both, the -timeout wrapper is only applied when configured, and `ToolRuntime.make` treats undefined -`maxToolCalls` as uncapped. Validation is unchanged when values ARE provided (safe integers, -timeoutMs >= 1, others >= 0). The OpenCode adapter is unaffected in behavior it sets -(explicit 30s timeout) but now runs with unlimited tool calls. Immediately after, per user -direction, the adapter's 30s timeout was killed too: `CODE_LIMITS` is deleted and OpenCode -passes NO limits - no timeout, no tool-call cap. Rationale: user cancel interrupts the -execution fiber and structured concurrency takes the program and in-flight child calls down -with it; every child call is permission-gated; output truncation (32KB default) is the only -active bound. New regression test: 150 tool calls succeed with no limits configured (would -have tripped the old default 100). Package suite: 155 pass / 0 fail. - -**Fix 7 - JSDoc-annotated search signatures**: `tools.$codemode.search` result signatures are -now the pretty, indented multiline form with per-field JSDoc - ported from the pre-rebuild -rune renderer in this repo's git history (`renderType(def, { pretty })`/`docTags`/`jsdoc`/ -`renderObject`), adapted to the current renderer's conventions (`Array`, `unknown` -fallback, existing `$defs`/`$ref` handling and empty-object `{}` collapse; the old -`Result`/`returnType` machinery was deliberately not ported - payloads stay native). -Semantics: each described input/output field carries its schema `description` as a -`/** ... */` comment at the right indent (nested objects recurse deeper); constraints TS can't -express surface as JSDoc tags - `@deprecated`, `@default ` (unserializable defaults -skipped), `@format`, `@minItems`/`@maxItems`; `*/` inside text is neutralized to `* /`; -multiline descriptions become `*`-prefixed blocks with blank edges trimmed; undescribed, -untagged fields get no comment. Implementation: `renderSchema` in `tool-schema.ts` grew a -`RenderContext` (`{ definitions, pretty }`), a `MAX_RENDER_DEPTH = 8` recursion ceiling plus -a `$ref` `seen` guard (the renderer previously had neither - a cyclic `$defs` would have -looped; it now degrades to the ref name/`unknown`), and try/catch totality on the public -helpers (`toTypeScript`/`jsonSchemaToTypeScript`/`inputTypeScript`/`outputTypeScript` never -throw - pathological schemas render `unknown`); each helper takes an optional trailing -`pretty = false` parameter, so existing callers are unchanged and compact output stays -byte-identical (inline `catalogLine`s and the token budget depend on it). `SearchEntry` -gained an eagerly-computed `signature` field (built once per tool at index-build time in -`toSearchEntry` - rendering is cheap and the search hot path stays allocation-free); both -ranked results and exact-path lookups serve it. Works for both tool kinds: Effect Schema -annotations (`Schema.String.annotate({ description })`) flow through the emitted JSON -Schema, and raw JSON Schema (MCP) property metadata is read directly - both covered in -`test/signature.test.ts` (12 tests) plus one strengthened adapter assertion (MCP property -description appears as JSDoc in a live search result; the tool description/catalog contains -no `/**`). README search section updated with an example. Package suite: 167 pass / 0 fail; -adapter suites: 34 + 16. - -**Fix 8 - condensed instructions + round-robin catalog fairness + plural-aware search** -(user direction: the fixed instruction prose was too verbose; two discovery fixes ride -along). All in `tool-runtime.ts`; no interpreter changes. - -- **Syntax section inverted**: the three dense allowlist lines (~453 estimated tokens) - are replaced by four short lines (~188) built on "models already know JavaScript; name - only what is unusual or missing": (1) standard modern JS works - functions/closures, - destructuring, template literals, loops, try/catch, spread, optional chaining, the - usual Array/String/Object/Math/JSON methods, plus Date/RegExp/Map/Set and - Promise.all/allSettled/race/resolve/reject; (2) TypeScript type annotations are - stripped before execution, decorators are not supported; (3) NOT supported (each fails - with a message naming the alternative): classes, generators, for await...of, - .then/.catch/.finally (use await with try/catch), `x instanceof Error` (caught errors - are plain `{ name, message }` objects), splice; (4) the data-boundary note (Dates -> - ISO strings; Map/Set/RegExp -> `{}`). Every claim was verified against the interpreter - before writing: probed empirically - classes/generators/for-await/.then/.catch/ - .finally/`instanceof Error`/splice/decorators/BigInt/labeled statements/tagged - templates/object getters all fail with clear diagnostics; TS annotations/`as`/ - interfaces/type aliases are stripped and TS **enums actually work** (transpileModule - compiles them to an IIFE the interpreter runs), hence enums deliberately unmentioned. - `supportedSyntaxMessage` (the in-diagnostic text in `codemode.ts`) is untouched. -- **Workflow/Rules deduped**: the call-by-exact-path and return-small content now lives ONLY - in the numbered Workflow steps; Rules keeps only bullets adding new - content - filter/aggregate collections in code, console.\* intermediates (logs ride - back), Promise.all parallelism, Object.keys/for...in enumeration, browse-namespace - (PARTIAL only), and the media rule compressed to one line. The no-.then/.catch - guidance moved to the Syntax not-supported line. Content upgrades: the PARTIAL search - step gained query-style guidance (`- short phrases like "list issues" work best`; a - clearly-a-query-string example, not a tool name), and the exact-path guidance is now - "call it with the result's `path` as-is (never guess segments)" / COMPLETE: "use it - as-is rather than guessing segments". -- **Fixed-prose measurements** (instructions split on `"\n## "`, catalog budget 0, - bytes/3.7 - same method as Fix 4; chars/4 in parentheses): - preamble 44 -> 44 (41 -> 41), Workflow 146 -> 187 (135 -> 171), Rules 362 -> 191 - (332 -> 176), Syntax 453 -> 188 (419 -> 174); fixed prose total 1,005 -> 610 (927 -> 562), - ~ 40% reduction with no behavioral content dropped. Workflow grew slightly because it - absorbed the deduped parse/return-small justifications. -- **Round-robin namespace inlining** (`prepare`): the ported stop-on-first-miss - behavior (alphabetically-late namespaces starved to "none shown" while an early - namespace inlines everything) is replaced by round-robin fairness - in each round - (namespaces alphabetical), every namespace still holding un-inlined tools attempts to - place its next-cheapest line against the shared token budget; a namespace whose next - line does not fit is done while the others keep going; stop when all are done. Every - namespace gets some representation before any namespace gets everything. Kept: - `estimate` (chars/4) budget accounting, unbudgeted namespace stub lines, per-namespace - `(N tools)`/`(N tools, K shown)`/`(N tools, none shown)` labels, COMPLETE vs PARTIAL - header, alphabetical namespace order in the output, cheapest-first within each - namespace's shown set. -- **Plural/singular search fix**: `tokenize`d terms matched one-directionally (term must - be substring of indexed text), so query "issues" missed a tool whose text only says - "issue". Now each term expands to `termForms` - the term plus naive singular variants - (trailing "es" stripped when length > 3, trailing "s" when length > 2) - and each of - the four field checks passes when ANY form matches. Weights, exact-path lookup, and - namespace scoping untouched. A true plural path match still outranks a singular-only - description match (path substring 8 + searchable 2 > description 4 + searchable 2). -- **Tests**: package instruction/structure assertions updated to the new text; the - language-section test rejects full-runtime wording, names major unavailable capabilities, - and keeps the data-boundary note; the budget-exhaustion - test rewritten to assert the new fairness (alpha.expensive not fitting must NOT - prevent beta.cheap from showing: PARTIAL 2 of 3, `- beta (1 tool)` fully shown); new - plural/singular test (query "issues" finds a singular-only tool; ranking still - prefers the true "issues" path match). Adapter: description assertions updated; the - large-catalog PARTIAL test now asserts `zeta_only_tool` IS shown (`- zeta (1 tool)` + - its inlined line) - it was "none shown" under starvation. README updated (budgeted - catalog paragraph -> round-robin; search paragraph -> singular variants; - instructions-structure paragraph -> new section contents). Package suite: 169 pass / - 0 fail; adapter suites: 34 + 16. - -**Fix 9 - prompting trims per user review of Fix 8** (user reviewed the condensed -instructions and directed further cuts): - -- Default `catalogBudget` 4,000 -> **2,000** (user wants ~2k tokens of signatures - auto-inlined; round-robin fairness from Fix 8 spreads it across all namespaces). -- Console rule and files/images rule DROPPED from `## Rules`. Replaced by a single - `unknown`-treatment warning: "A result typed `Promise` has no guaranteed - shape - verify what actually came back before relying on its fields." (Deliberately - does NOT suggest console.log - user review: naming it there nudges models to log AND - return the same data; the prompt stays console-neutral, neither for nor against.) - The media-stripping MECHANISM is unchanged and still tested; only the prose about it - is gone - the `[N images attached]` marker is self-explanatory in context. -- Later revised: unconditional JSON parsing was removed because text results are not - necessarily JSON. The browse-namespace rule remains; the language section now states that - ambient `fetch` is unavailable and external operations go through Code Mode tools. -- Explicitly REJECTED for now: auto-parsing JSON-looking text results at the adapter - boundary ("could get weird" - type flips, program-sees vs tool-sent divergence). Logged - as a next-iteration follow-up below. - -**DSL-expansion pass - interpreter-surface batch from section 4** (the deferred medium-tier JS -parity items, done as one focused pass; no public API or limit changes): - -- **`instanceof` + real Error values**: the `errorConstructors` names (`Error`, - `TypeError`, `RangeError`, `SyntaxError`, `ReferenceError`, `EvalError`, `URIError`) are - bound globals (`ErrorConstructorReference`, callable with or without `new`; `typeof` -> - `"function"`). Error values stay the same plain `{ name, message }` null-prototype - objects as before - the constructor name additionally rides on a NON-ENUMERABLE symbol - key (`ErrorBrand`), which every `Object.entries`-based walk (copyIn/copyOut, spread, - JSON.stringify) is blind to, so serialization is byte-identical to the old shape and the - brand is lost on spread/boundary copies exactly like JS loses the prototype. - `caughtErrorValue` produces `{ name, message }` wrappers via `createErrorValue`, so - caught interpreter AND tool failures are `instanceof Error` and carry the `name` the - equivalent real-JS failure would have (follow-up fix, user-directed - "closest to real - JS"): `InterpreterRuntimeError` gained an `errorName` field ("Error" default) set - fluently at throw sites via `.as(name)` - `JSON.parse` failures are `"SyntaxError"` (and - now include the engine's position detail in the message; safe - derived from the - program-supplied string), invalid regex patterns/flags `"SyntaxError"`, unknown - identifiers and TDZ access `"ReferenceError"`, assignment to a constant `"TypeError"`, - a bad `normalize` form `"RangeError"`; a host Error reaching the catch path directly - keeps its own name when it is one of the standard seven. Tool failures and everything - without a specific analogue stay `"Error"` - internal class names never leak. Specific - names satisfy the specific `instanceof` (`e instanceof SyntaxError`), matching JS. - The operator is handled in `evaluateBinaryExpression` - BEFORE the data-only operand check (like `typeof`, it observes any lhs - promises and - functions included); recognized rhs: the error constructors (a specific type matches its - own brand or `Error`, never a sibling), `Date`/`RegExp`/`Map`/`Set` (sandbox classes), - `Array`, `Object` (any object/function-ish value), `Promise` (`SandboxPromise`), and - `Number`/`String`/`Boolean` (always false - no boxed values exist); anything else is a - catchable error naming the recognized constructors. -- **Array methods**: `splice` (mutating, returns the removed elements; insertions run - `rejectCircularInsertion` like push/unshift; one-arg form removes to the end, undefined - delete count removes nothing), `fill` (circular-checked value) and `copyWithin` - (host-delegated), and `keys`/`values`/`entries` returning **arrays** (the Map/Set - convention - for...of and spread work either way). The `retryableArrayMethods` - "rewrite using map/filter" hint set emptied out and was deleted with its branch; unknown - array properties still read `undefined`. -- **String methods**: `localeCompare(that)` (locale/options arguments ignored - host - default locale; the dominant use is a sort comparator), `normalize(form?)` (invalid form - -> catchable error naming the four valid forms), `trimLeft`/`trimRight` as - trimStart/trimEnd aliases. -- **Actionable regex failures**: `toHostRegex` and `constructRegExp` now show the - offending pattern (or flags) plus the engine reason (deduped "Invalid regular - expression:" prefix via `regexFailureReason`) and a shared escaping hint - (`escapeRegexHint`); flags failures list the valid flag letters; the - replaceAll/matchAll missing-`g` errors spell out the exact `/pattern/g` to write and - the single-match alternative. -- **copyIn split (the important one)**: `copyIn(value, label, preserveSandboxValues = -false)` - recursion moved to a private `copyBounded`; `boundedData` (every intra-sandbox - checkpoint: `Object.*` helpers, coercion/Array.from/join inputs, template - interpolation, expression-result checkpoints) is now `copyIn(value, label, true)`, - which passes `SandboxDate`/`SandboxRegExp`/`SandboxMap`/`SandboxSet` through **by - reference as leaves** (contents not walked - Map/Set members are validated at their - mutation sites) while keeping the depth (`MAX_VALUE_DEPTH`), circularity, - plain-objects-only, blocked-property, and data-only checks; un-awaited promises keep - the await-hinting rejection in BOTH modes (deliberate - JS-parity pass-through was - considered and skipped to preserve the nudge). The HOST boundary (final result, - tool-call arguments, `JSON.stringify`, tool-result intake) uses the default mode and - still serializes JSON forms (Date -> ISO, RegExp/Map/Set -> `{}`); host instances met on - the preserving path are defensively wrapped into sandbox equivalents. Ripple: the - `Object.*` helpers treat sandbox values as empty objects (`Object.keys(map)` -> `[]`, - assign sources contribute nothing, hasOwn -> false - JS has no own enumerable props - there), so interpreter internals (`.map`/`.time`/`.regex`) can never leak; the - template-literal sandbox carve-out collapsed into `boundedData`. Object/array spread - already preserved instances (reference copies, no checkpoint) - now tested. -- **Console formatting**: `formatConsoleArgument` is total and deep - (`formatConsoleValue`): numbers render via `String` (`NaN`/`Infinity`/`-Infinity` - literally - never the JSON `null`; finite numbers match their JSON form), nested - strings are JSON-quoted, sandbox values keep their friendly forms at ANY depth (ISO - date, `/regex/flags`, `Map(n) [...]`, `Set(n) [...]`), opaque references become - in-place `[CodeMode reference]` markers instead of collapsing the whole argument, - cycles render `[Circular]` (reachable via Map/Set members, which mutation never - checkpoints), and depth beyond `MAX_CONSOLE_DEPTH = 32` (fixed constant, not a knob) - degrades to `...` - console can no longer fail a program. `console.table` guards with - `containsOpaqueReference` (sandbox cells render, e.g. ISO dates) and its row/cell - walkers treat sandbox values as scalar cells. -- **Prose**: the instructions Syntax not-supported line dropped its `instanceof -Error`/splice mentions (nothing else reworded); README updated (checkpoint - preservation vs boundary serialization, error values/`instanceof`, new array/string - methods, regex-failure behavior); `supportedSyntaxMessage` left untouched (it lists - supported syntax, was already non-exhaustive, and stays accurate). -- **Tests**: package suite 169 -> 209 (parity: Error/instanceof + real-JS error-name - coverage, splice/fill/copyWithin/keys/values/entries, localeCompare/normalize/trim-alias - describes; stdlib: checkpoint survival incl. tool-arg boundary pinning, stdlib - `instanceof`, regex-message assertions; codemode: NaN/Infinity + nested/cyclic console - rendering, table cells, caught-tool-failure `instanceof`); adapter suites unchanged - (34 + 16, green); both packages `tsgo --noEmit` clean. - -**Truncation layering - CodeMode truncation off in OpenCode** (user direction; resolves the -section 4 outer-truncation item the OPPOSITE way from "kill the outer one"): - -- `maxOutputBytes` lost its 32,000 default and now behaves exactly like the other two - limits: absent = no truncation. All three limits are uniformly no-default - budgets are - host policy. `ResolvedExecutionLimits.maxOutputBytes` is `number | undefined`; - `boundOutput` only runs when the host set the limit. Explicit values validate as before - (safe integer >= 0). -- OpenCode continues to pass NO limits, which now also means no CodeMode truncation. - `execute` is a normal `Tool.define` tool, so OpenCode's native tool-output truncation - applies with no special-casing - verified by tracing `wrap()` (`tool.ts:130-144`, - 50KB/2000-line thresholds in `truncate.ts`, full output dumped to a file under - `tool-output/`): the `metadata.truncated` self-truncation exemption never fires for - `execute` (its metadata never sets that key). One truncation layer, the host's - and it - is the richer one (file dump + explore/grep hint vs an inline marker). -- Hosts without their own output bounding set `maxOutputBytes` explicitly; README table - and prose updated, adapter comment rewritten. Tests: codemode +1 (absent limit -> 100KB - value + 50KB log line pass through unbounded, `truncated` undefined); the adapter test - that relied on the old default now asserts the oversized result reaches the shared - wrapper un-truncated. Suites: 210 + 50, tsgo clean both. - -**Docs polish** (post-API-review): stale `CodeMode.DiscoveryOptions` JSDoc fixed (claimed default -4,000 and alphabetical cheapest-first - now 2,000 and round-robin, matching Fix 8/9 reality) -and the README's incorrect "`effect` as a peer dependency" line corrected (`effect` is a -regular dependency; hosts depend on it themselves because the API surface is Effect-typed). - -**Registry promotion + permission-aware catalog** (the "promote to a proper tool service" -restructure; fixes the section 4 permission-advertising bug): - -- **The adapter moved** `src/session/code-mode.ts` -> `src/tool/code-mode.ts` and is now a - registry-resident tool service on the TaskTool precedent: `CodeModeTool = -Tool.define(CODE_MODE_TOOL, ...)` whose init depends on `MCP.Service`, `Agent.Service`, - and `Session.Service`. It is yielded in `ToolRegistry.layer`, gated into `builtin` by - `flags.experimentalCodeMode` (like the lsp/plan experiments), and `MCP.node` joined the - registry's `node.deps` (`MCP.node` has no ToolRegistry dependency, so no cycle). The - session-level special-casing in `session/tools.ts` (ad-hoc `SessionCodeMode.define` + - append) is deleted; the early return that suppresses raw per-MCP registration when the - flag is on stays session-side, keyed on the same flag+tool-count condition. -- **Enablement** lives in `ToolRegistry.tools()` next to the WebSearchTool check: the MCP - tool count is consulted once (an Effect) before the synchronous filter, and code mode - passes the predicate iff `flags.experimentalCodeMode` && count > 0. -- **Description split on the `describeTask` precedent**: the tool's static base - description is a two-line summary; `describeCodeMode(agent)` in `registry.tools()` - appends the full CodeMode instructions (workflow/rules/syntax + grouped catalog, - `catalogInstructions` in the adapter) at the same composition point as task - so - `plugin.trigger("tool.definition")` sees the base description first. -- **Permission-aware catalog + dispatch** (the bug fix): the visibility predicate from - `llm/request.ts` `resolveTools` is hoisted to `Permission.visibleTools(tools, ruleset)` - (a record filter over `Permission.disabled` - only a hard `deny` with pattern `"*"` - hides a tool; ask-level rules stay fully visible and prompt at call time) and - `resolveTools` now uses it, so the two paths cannot drift. `describeCodeMode` filters - with the merged agent+session ruleset that `SessionTools.resolve` passes into the - registry before building the catalog/search index; `execute` rebuilds the runtime per - execution from a fresh, filtered `mcp.tools()` snapshot using the same merged ruleset - (`Agent.get(ctx.agent)` + `Session.get(ctx.sessionID)`, matching the merge - `SessionTools.context` wires into `ctx.ask`) - a denied tool is not dispatchable - even if the model guesses its name and yields the normal unknown-tool diagnostic. - Documented gap (out of scope by design): per-message `user.tools[key] === false` arrives - at request-prep after descriptions are built and has no child-call equivalent. -- **Preserved behavior**: cancellation race + pre-aborted-signal guard, `toSandboxResult` - unwrap order, attachment accumulation, `CODE_MODE_TOOL` at all title sites, no execution - limits (native truncation only), `displayInput`, per-child `ctx.ask` gating (now wired - through `Tool.Context` exactly like every registry tool). -- **Explicit non-goal**: memoizing the catalog builder keyed on (ToolsChanged generation, - permission ruleset) was considered and deliberately skipped - the per-turn rebuild is - cheap (grouping + string rendering); revisit only if profiling shows it matters. -- **Tests**: the two adapter suites moved to `test/tool/{code-mode,code-mode-integration} -.test.ts` (mocked `MCP.Service`/`Agent.Service`/`Session.Service` replacing the direct - `define(...)` construction; description assertions target `catalogInstructions`, the - registry's composition input) and gained permission coverage: deny excluded from - catalog/search, ask-level stays visible and callable, denied tool undispatchable - (unknown-tool diagnostic), `Permission.visibleTools` semantics. `test/tool/ -registry.test.ts` gained four registry-level tests: registered with flag+MCP tools, - excluded without MCP tools, excluded with flag off, and deny/ask catalog filtering - through `registry.tools()`. Suites: 43 + 16 adapter tests, 16 registry tests, all green. - -**Shared MCP invocation middle (`McpInvoke.invoke`)** (closes the section 4 "plugin hooks skip -child calls" gap): - -- `packages/opencode/src/mcp/invoke.ts` extracts the duplicated "invoke an MCP tool" - middle into one shared `McpInvoke.invoke(input)`: plugin `tool.execute.before` hook -> - permission ask (`{ permission: key, patterns: ["*"], always: ["*"] }` via the caller's - `ctx.ask`) -> dispatch through the ai-sdk tool's execute inside the `Tool.execute` - tracing span (`tool.name`/`tool.call_id`/`session.id`/`message.id` attributes) -> - plugin `tool.execute.after` hook. It returns the RAW result the ai-sdk execute - resolved with; each caller keeps its own shaping edge - the legacy per-MCP loop in - `SessionTools.resolve` applies its existing model-facing shaping/truncation, code - mode applies `toSandboxResult`. It lives under `src/mcp/` because both callers - already depend on MCP and the function is about invoking an MCP-backed ai-sdk tool, - not about sessions or code mode. -- **After-hook payload**: fired inside `McpInvoke.invoke` with the raw MCP result - - which is exactly what the legacy loop always passed (the raw `CallToolResult`, not - the shaped `{title, output, metadata}`), so legacy behavior is preserved bit-for-bit - and the hook payload cannot drift between callers. No callback/edge-firing design - was needed. -- **Synthetic child callID**: code-mode child calls pass `${parentCallID}/${n}` as the - hook/span callID (`parentCallID` = the `execute` call's `ctx.callID`, falling back to - the entry key; `n` = per-execution counter starting at 1, shared across all child - calls in one program). callID is an opaque string - nothing parses it. The ai-sdk - `toolCallId` (`options.toolCallId`) stays each caller's existing value - (`ctx.callID ?? entry.key` for code mode). -- **Child-scoped hook failures**: `CodeModeTool` (which now also yields - `Plugin.Service`) wraps the whole child call - hooks, ask, dispatch - in - `toCatchable` (the generalization of the old `askPermission` catchCause), so a plugin - hook failure fails ONLY that child call as a catchable in-program `toolError`; other - calls in the same program keep running and interruption still propagates as - interruption. Legacy semantics unchanged: a hook failure fails the tool call. -- **Tests**: `test/tool/code-mode.test.ts` +2 (child calls fire before/after with the - MCP key and `parent/1`, `parent/2` ids, after hook carries the raw MCP result; a - failing before hook is caught in-program, gates dispatch, and leaves the outer - execute ok) - both code-mode harnesses gained a `Plugin.Service` mock (pass-through - trigger by default, overridable). New `test/session/tools.test.ts` (3 tests) pins - `SessionTools.resolve` at the real-registry seam (LayerNode.compile, fake MCP layer): - flag on + MCP tools -> `execute` present, raw MCP keys suppressed; flag off -> raw - keys present, `execute` absent; and the legacy raw-MCP execute fires before/after - hooks keyed by the ai-sdk toolCallId with the raw result payload. Suites: adapter - 45 + 16, session/tool/permission all green; this package untouched (211 pass). - -**Signature rendering + compound-assignment parity fixes** (externally reported, both -verified real with failing tests before fixing): - -- **Non-identifier property names in rendered signatures** (`src/tool-schema.ts`): `renderSchema` - emitted raw property names, so schema properties like `foo-bar`/`@type`/`x.y`/`123` - rendered invalid TypeScript (`{ foo-bar?: string }`). Fixed with a `renderKey` helper - - bare identifiers stay bare, everything else is `JSON.stringify`-quoted - applied in the - single `field` closure both the compact and pretty renderings share. The - `identifierSegment` regex now lives in `tool-schema.ts` (internal) and `tool-runtime.ts`'s - bracket-notation `toolExpression` imports it: one source of truth for "is this a bare - identifier" across object keys and tool paths. Tests: `signature.test.ts` +4 (compact, - pretty with JSDoc on a quoted key, JSON Schema input+output, Effect Schema struct). -- **Numeric schema unions keep their real alternatives** (`src/tool-schema.ts`): the old - `anyOf`/`oneOf` renderer collapsed any union containing `{ type: "number" }` to just - `number`, dropping real JSON Schema alternatives (`string | number`, `number | null`, - etc.). The collapse is now restricted to Effect's number-schema artifact - (`number | "NaN" | "Infinity" | "-Infinity"`, emitted as single-value string enums), - while raw JSON Schema unions render every branch. Tests: `signature.test.ts` +3. -- **Compound assignment now matches binary-operator semantics** (`src/codemode.ts`): - `applyCompoundAssignment` did raw JS ops on interpreter wrapper objects, so `x += y` - diverged from `x = x + y` (sandbox Date `d += 1` produced `"[object Object]1"`; - `d -= 400` gave `NaN` instead of epoch arithmetic). The operator table + coercion moved - verbatim out of `evaluateBinaryExpression` into a shared `applyBinaryOperator`; - compound assignment validates against a `compoundOperators` set (`+=` ... `>>>=`) and - dispatches through it (`operator.slice(0, -1)`). Logical assignments (`&&=`/`||=`/`??=`) - keep their separate short-circuit path (`evaluateLogicalAssignment`), and both - assignment call sites still wrap results in `boundedData`. Deliberate side effect: - compound assignment now rejects opaque references, consistent with binary operators. - Tests: `parity.test.ts` +5 (Date `+=` concat parity, Date `-=`/`/=` epoch parity, - string `+=` object/array, member-target compound, 13-case operator sweep vs real JS). - Package suite: 220 pass. - ---- - -## 4. Remaining work (detailed TODO) - -### Next DSL-expansion pass (done - see the DSL-expansion pass entry in section 3) - -Batch these together - per user direction: important, but deliberately deferred to one -focused interpreter-surface pass rather than picked off piecemeal. - -- [x] Medium-tier JS parity items deferred from the original audit: caught errors are plain - `{ name, message }` objects, not `instanceof Error` (and `Error` isn't a value - - `x instanceof Error` is unsupported syntax); `splice` (still a - "rewrite using map/filter" hint) and array `entries()/keys()/values()`; - `localeCompare`/`normalize`/`trimLeft`/`trimRight`; friendlier regex-y error messages. - (`fill`/`copyWithin` - which the hint set also covered - were implemented too since - they are trivial host delegations, so the hint set is gone entirely.) -- [x] `Date`/`Map`/`Set`/`RegExp` values passing through `Object.*` helpers and coercion - checkpoints take their JSON forms (e.g. `Object.values({ d: date })` yields the ISO - string, not the Date - calling `.getTime()` on it then fails). Currently deliberate - (documented in README) but flagged as important: fix in this pass by letting sandbox - values survive `Object.*`/spread checkpoints instead of JSON-serializing them. -- [x] `console.log(NaN)` prints `"null"` (goes through the boundary chokepoint) - could - special-case number formatting in `formatConsoleArgument`. -- [x] Sandbox values nested inside logged containers print `[CodeMode reference]` - (`console.log({ m: map })`) - could deep-format instead. - -### Next iteration: optional search input boundary - -- [ ] `SearchInput` uses Effect's exact `optionalKey`, so an omitted field is accepted but an - explicitly present `undefined` field is rejected. The previous handwritten validator - treated explicit `undefined` as omission. Decide whether search should preserve that - convenience locally or whether all tool arguments should adopt JSON-style undefined - normalization; do not broaden `copyOut` semantics solely to fix search. - -### Next iteration: text-result handling (deliberate follow-up, user-directed) - -- [ ] Revisit how MCP text results reach the program. Today: `structuredContent` when the - server sends it, else joined text as a plain string. Programs narrow unknown results - before use; the prompt no longer recommends unconditional JSON parsing. Considered and deferred: (a) conservative boundary - auto-parse (text starting with `{`/`[` that parses cleanly becomes an object) - - rejected for now as potentially confusing (type flips; program sees something other - than what the tool sent); (b) raw-envelope passthrough with the envelope shape - stamped into every output schema - rejected (more digging per call, verbose - signatures). Result quality is dominated by whether servers declare output schemas; - revisit once real usage shows which failure modes matter. - -### Next iteration: stdlib surface (prioritized) - -Current instructions say "usual Array/String/Object/Math/JSON methods," but the interpreter is -intentionally a subset. Keep CodeMode focused on orchestration and data shaping, not a full host -runtime, but close the high-friction gaps models are likely to reach for. - -- [ ] **P0: tighten wording first** - change instructions/docs to say "common stdlib subset" - until the surface is broader. This avoids misleading the model into assuming every JS - helper exists. -- [ ] **P1: URL parsing helpers** - add `URL` and `URLSearchParams`. These are high-value for - tool orchestration (query strings, ids in URLs, API links), deterministic, and do not add - ambient host authority. -- [ ] **P2: Math completion** - add the missing standard deterministic `Math` methods - (`sin`/`cos`/`tan`, inverse/hyperbolic variants, `atan2`, `log1p`, `expm1`, `imul`, - `fround`, `clz32`, etc.). Decide explicitly on `Math.random`: likely acceptable because - `Date.now()` is already exposed, but document the nondeterminism if enabled. -- [ ] **P3: base64 helpers** - add string-only `atob`/`btoa` equivalents. Useful for API/tool - payload cleanup and does not require opening the broader binary boundary. -- [ ] **P4: small crypto helper** - consider `crypto.randomUUID()` only, not full `crypto`. - UUID generation is a common orchestration need; broader crypto can wait until there is a - concrete use case and a clear capability boundary. -- [ ] **P5: text/binary primitives** - consider `TextEncoder`/`TextDecoder` first, then - `ArrayBuffer`/typed arrays/`DataView`/`Blob`/`File` only with an explicit boundary design - (serialization, size limits, and how values cross tool args/results). This is reasonable - but lower priority than URL/base64 because CodeMode is still plain-data oriented. -- [ ] **P6: date/formatting conveniences** - consider `Date` setters and common formatting - helpers (`toUTCString`, maybe `Intl` later). Lower priority; most orchestration can use - existing getters, `Date.parse`, `Date.UTC`, and ISO strings. -- [ ] **P7: environment/config access** - do not expose raw `process.env` as a global ambient - authority. If this becomes useful, add an explicit host-provided/whitelisted capability - (for example a small env/config tool or injected read-only object) so secrets are not - accidentally exposed to arbitrary CodeMode programs. - -Explicit non-goals for now: `structuredClone`, `WeakMap`/`WeakSet`, and timers -(`setTimeout`/`setInterval`/`queueMicrotask`). They do not materially improve the current tool -orchestration use case. - -### Wiring-review findings (subagent code review of the OpenCode integration, triaged) - -Pre-PR fixes (user-approved cut): - -- [x] **Cancellation does not interrupt the interpreter** - the no-limits rationale claimed - "user cancel interrupts the execution fiber," but `tools.ts` runs tools via - `run.promise` -> `Effect.runPromise` (`effect/bridge.ts:64-66`) with NO abort wiring; - on cancel the ai-sdk abandons the promise, child MCP calls abort (they hold - `ctx.abort`) but the interpreter fiber spun on - `while(true){}` or a try/catch - loop was uncancellable with no timeout backstop. Verified by hand, not just the - reviewer. FIXED in the adapter: `Effect.raceFirst(runtime.execute(code), cancelled)` - where `cancelled` is an `Effect.callback` abort-signal watcher (listener removed on - interruption) resuming with an `ok: false` "Execution cancelled." result - the abort - winning the race interrupts the execution fiber (interpreter auto-yield makes busy - loops preemptible, same mechanism as timeoutMs) and returning a value keeps the - runner's post-abort `completeToolCall` bookkeeping on its normal path. A pre-aborted - signal short-circuits at entry before the program starts (racing alone still lets - the loser run its first steps). Tests: +2 adapter (child call triggers abort - deterministically then the program enters `while(true){}` - would hang if - interruption broke; pre-aborted signal runs nothing). Adapter suite 34 -> 36. - (Wiring abort->interrupt into the shared `tools.ts` runner for ALL tools remains a - worthwhile separate change.) -- [x] **Permission-denied/disabled MCP tools are still advertised in the catalog** - the - non-code-mode path filters them from the model's view (`llm/request.ts:208-213`); - code mode builds the catalog from all of `mcp.tools()`, so the model is invited to - call tools that can only fail at permission time, and per-message `tools[key]=false` - disabling has no child-call equivalent. Fix: filter the catalog with the same - ruleset. - DONE (see the "Registry promotion + permission-aware catalog" entry in section 3): the - shared `Permission.visibleTools` predicate filters both the appended - catalog/description (`describeCodeMode`, agent ruleset) and the execute-time tool - tree (merged agent+session ruleset) - hard-denied tools are neither advertised nor - dispatchable. Ask-level tools stay visible/callable. Per-message - `tools[key] === false` remains a documented gap by design (it arrives at - request-prep, after descriptions are built). -- [x] Style: `code-mode.ts` is the only `src/session` sibling without the - `export * as ... from "./..."` self-reexport footer, forcing a star import at - `tools.ts:26` (AGENTS.md violation). Add footer + import the projection. - DONE: added `export * as SessionCodeMode from "./code-mode"` footer; `tools.ts` now - imports the named `SessionCodeMode` projection. -- [x] Trivial: latent `groupByServer` fallback bug - `key.slice(0, key.indexOf("_"))` is - `slice(0, -1)` when no underscore (unreachable today; guard or drop); dead - `CODE_MODE_TOOL` export (integration points hardcode `"execute"` - use it or inline - it). - DONE: no-underscore key now falls back to the whole key (test pins it); the four - `title: "execute"` sites in `code-mode.ts` now reference `CODE_MODE_TOOL`. - -Post-MVP (logged, not blocking an experimental flag): - -- [x] **Plugin `tool.execute.before/after` hooks skip child calls** - legacy MCP - registration fires them per tool (`tools.ts:419-441`); under code mode only the - outer `execute` fires them, so auditing/intercepting plugins silently lose MCP - coverage when the flag flips. - DONE (see the "Shared MCP invocation middle" entry in section 3): both paths now run - `McpInvoke.invoke` (`src/mcp/invoke.ts`) - hooks AND the `Tool.execute` span fire - for child calls with synthetic `${parentCallID}/${n}` callIDs; hook failures are - child-scoped, catchable in-program errors. -- [x] Description/preview rebuilt every assistant turn - `registry.tools()` re-runs - `groupByServer` + a throwaway `CodeMode.make(...).instructions()` per turn - (`describeCodeMode`). DECIDED as an explicit non-goal: memoizing the catalog - builder keyed on (ToolsChanged generation, permission ruleset) was considered and - deliberately skipped - the per-turn rebuild is cheap (grouping + string - rendering); revisit only if profiling shows it matters. A second `CodeMode.make` - per execution is inherent (description precedes execution). -- [ ] Child permission rejection round-trips through the defect channel - `ctx.ask` - defect (`tools.ts:90` orDie) recovered via `catchCause` + `Cause.squash` - (`code-mode.ts:238-245`). Works, interrupts preserved, but fragile coupling; - exposing the typed rejection on `Tool.Context.ask` would be cleaner. -- [ ] No collision guard on the `execute` tool id (a plugin/custom tool named `execute` - is silently shadowed; a log line would do). -- [ ] Style nits: triple-nested `yield*` in `tools.ts:101-107` argument position (bind - first, like neighbors); single-use micro-helpers (`toJsonSchema` is a bare cast); - comment density far above session-neighbor norm; adapter tests use raw - `Effect.runPromise` + hand-built layers with `as any` instead of the - `testEffect`/`LayerNode.compile` fixture pattern (`test/tool/grep.test.ts:25-31`) - and star-import `Truncate`. -- [ ] Reviewer observation worth keeping: MCP server instructions (`sys.mcp`, - `session/system.ts:110-126`) still inject prose referencing server-native tool - names that are no longer directly callable under code mode. -- [ ] Tool-tree path segments named `__proto__`, `constructor`, or `prototype` are included - in discovery but rejected by `ToolRuntime` resolution even when supplied as safe own - properties on null-prototype host records. Hosts should preserve registered names rather - than invent incompatible aliases. CodeMode should own a consistent policy: safely admit - these names as own tool-tree members, reject them before catalog generation with a clear - diagnostic, or define one canonical escaping contract. - -### Backlog / loose ends (non-blocking, any order) - -- [ ] `evaluateUpdateExpression` (`++`/`--`) still uses raw `Number(current)`, so `d++` on a - sandbox Date yields `NaN` where `d += 1` now uses epoch semantics (and real JS `d++` - would give epoch+0 numeric). Pre-existing, out of scope of the compound-assignment - parity fix; route it through `applyBinaryOperator` if it ever matters. -- [ ] Media-only marker could name what it attached when MCP provides names: `image`/`audio` - blocks carry no filename (mime + data only) so the generic - `[N images attached to the result]` stays, but `resource`/`resource_link` blocks have - URIs/names we could surface, e.g. `[2 files attached: chart.png, data.csv]`. Minor. -- [x] Truncation layering decided (user direction): the OPPOSITE of killing the outer layer - - CodeMode truncation off in OpenCode (`maxOutputBytes` lost its default; absent = no - truncation, uniform with the other two limits), native tool-output truncation is the - single active layer (verified: `execute` flows through `tool.ts` `wrap()` like any - normal tool, no exemption). See the section 3 entry. -- [x] Flaky wall-clock assertion removed from `test/promise.test.ts`: the parallelism test - now relies solely on the deterministic `trace.maxActive > 1` counter (which proves - true temporal overlap). The timeout tests were never flaky - 100ms timeout vs 60s - tool sleeps (600x margin) with counter-based assertions. -- [ ] Attachment propagation believed correct but unverified end-to-end at the OpenCode - wiring layer (codemode strips -> `Tool.ExecuteResult.attachments` -> processor - normalizes -> `FilePart`s visible to the model). Code-reviewed as sound; confirm with - one interactive session (an image-returning MCP tool) when convenient. Same session - can eyeball TUI child-call rendering via `metadata.toolCalls`. -- [x] Commit hygiene: all work committed and pushed on `codemode-v2` as six commits, in - generic-package + OpenCode-integration pairs (waves 0-5; Fixes 4-9; DSL pass + - error names + truncation layering). Future work: commit only when explicitly asked; - push with `--no-verify` per repo convention. The scratch `.opencode/opencode.jsonc` - stays uncommitted. -- [ ] MVP scope decided (user direction): the interactive e2e eyeball is NOT required - - remaining pre-PR work is essentially just opening the PR. Attachment-propagation - verification (below) stays parked as post-MVP. - ---- - -## 5. Context and gotchas for whoever picks this up - -- **Motivating failure (why forgiving semantics + prompting matter):** in a real transcript, - the model wrote `me.result?.login ?? me.result` where the tool result was a JSON _string_ - - the old strict interpreter threw (`String property 'login' is not available`); then the - model returned a raw 105KB payload, which native truncation dumped to a file, costing a - subagent round-trip to extract one number. Interpreter forgiveness stops the crashes; - Wave 4 prompting stops the payload dumping. Both are needed. -- Realistically **all MCP tools render `Promise`** (no outputSchema), so the - instructions prose is the only lever for result-shape behavior in the dominant case. -- **`copyIn` has two roles, split by a mode flag** (DSL-expansion pass): host<->sandbox - boundary (default mode - final result, tool arguments, `JSON.stringify`, tool-result - intake; sandbox value types serialize to JSON forms) AND intra-sandbox data checkpoint - (`boundedData` = `copyIn(value, label, true)` - sandbox value instances pass through by - reference as leaves, everything else keeps the same plain-data validation). If you add a - new value type, follow the Wave 1b-i pattern: class in `values.ts`, opaque-by-default via - `isRuntimeReference`, explicit carve-outs, JSON form in `copyIn`'s boundary mode plus - pass-through in its preserving mode, console formatting (`formatConsoleValue`), tests - - and make sure the `Object.*` helpers treat it as an empty object so class fields never - leak. -- The interpreter throws synchronously inside `Effect.gen`/`Effect.sync` freely; everything is - normalized by `catchCause` -> `normalizeError` into `Diagnostic` data. Program failures are - **data, never Effect failures**; only interruption propagates. -- `parseProgram` wraps source in `async function __codemode__() { ... }`, transpiles TS, then - slices between the first `{` and last `}` - line/col diagnostics are offset accordingly - (`sourceLocation`). Don't inject prologue code; it breaks the offsets. -- OpenCode wraps every tool's output with auto-truncation (`Tool.define` wrapper, - `truncate.output`, 2000 lines / 50KB, saves full output to disk and appends a hint) unless - `metadata.truncated` is set. The `execute` tool currently rides that for free. -- Effect version: both repos pin `effect@4.0.0-beta.83` via bun catalogs. This package uses - v4-only APIs (`Schema.Decoder`, `Schema.toJsonSchemaDocument`, `Context.Service`, - `Cause.hasInterruptsOnly`, `Effect.timeoutOrElse`). The effect-smol checkout referenced in - the workspace is the implementation source of truth for v4 behavior questions. -- File map (this package): `src/codemode.ts` - types/limits/parser/Interpreter/execute/make; - `src/tool-runtime.ts` - tool tree, `copyIn`/`copyOut`, search/discovery, invoke path; - `src/tool.ts` - public `Tool` definitions; `src/tool-schema.ts` - schema rendering and decoding; - `src/values.ts` - sandbox value - types; `src/tool-error.ts` - `ToolError`; tests in `test/{codemode,parity,stdlib}.test.ts`. -- OpenCode file map (integration points): `src/tool/code-mode.ts` (the adapter, now a - registry tool service - `CodeModeTool` + `catalogInstructions`; formerly - `src/session/code-mode.ts`); `src/tool/registry.ts` (`describeCodeMode`, enablement in - `tools()`, `MCP.node` dep); `src/session/tools.ts` (raw-MCP-registration suppression - when the flag is on); `src/permission/index.ts` (`Permission.visibleTools`, the shared - visibility predicate, also used by `src/session/llm/request.ts` `resolveTools`); - `src/mcp/index.ts` (`MCP.tools()`/`MCP.defs()`); `src/mcp/catalog.ts` (`convertTool`, - `server_tool` naming); `src/tool/tool.ts` (`ExecuteResult.attachments`, truncation - wrapper); `src/session/message-v2.ts` (attachments -> vision); - `packages/tui/src/routes/session/index.tsx` (`Execute` progress component); - `src/effect/runtime-flags.ts` (feature flag). +These are product boundaries rather than DSL backlog: + +- Ambient filesystem, process, environment, network, credential, or application access. External work must go through + supplied tools. +- Modules, imports, dynamic imports, `eval`, arbitrary host globals, npm packages, and prototype mutation. +- Generic permission prompts, authorization policy, durable pause/resume, replay, storage, or exactly-once external + side effects. Hosts and tools own those concerns. +- Heuristic parsing of text tool results as JSON. A result should not silently change type based on its contents. + +The OpenAPI adapter may gain more transports and encodings, but it must continue skipping operations it cannot +represent accurately rather than guessing semantics. + +## Decisions and Rationale + +| Decision | Rationale | +| --- | --- | +| Keep an owned tree-walking interpreter. | The product need is bounded tool orchestration, not arbitrary JavaScript. Owning the language surface keeps authority and behavior explicit. | +| Treat schemas as the model-facing interface. | Signatures drive correct calls; Effect Schema also provides the runtime validation boundary, while JSON Schema supports adapter interoperability. | +| Keep authority host-owned. | CodeMode can only confine programs to supplied tools. The host chooses those tools, and each tool enforces its own authorization and side-effect policy. | +| Use progressive catalog disclosure plus search. | Large tool sets should not consume the prompt, but every namespace must remain discoverable and speculative search calls should remain valid. | +| Start tool promises eagerly and supervise them. | This preserves normal call-time parallelism while giving each call run-once settlement and interruption safety. | +| Keep files outside the sandbox value space. | Models should compose structured data without routing binary payloads through generated code or context. | +| Treat `execute` as the model-facing invocation boundary. | Nested calls are implementation details of one orchestration program. Reusing the outer context and bounding only the final result preserves complete intermediate data without inventing durable child-call identities. | +| Return expected failures as data. | Models need actionable diagnostics without exposing private host causes; host interruption and defects must still propagate correctly. | +| Leave execution-limit defaults to hosts. | Appropriate budgets depend on the surrounding product and its own cancellation, retention, and output-bounding policies. | +| Skip unsupported OpenAPI operations. | Incorrect parameter encoding, authentication, or transport behavior is worse than a precise `skipped` reason. | + +## Remaining Work + +Keep only material unresolved work here. Small isolated defects should be GitHub issues; adapter-only work belongs in +the adapter TODO. Delete entries when completed. + +### DSL expansion + +The supported JavaScript subset should grow when common model-generated code improves tool orchestration. These are +current omissions to implement, not intentional product boundaries. + +- [ ] Design proper multi-stage promise pipelines. Supporting `.then`, `.catch`, and `.finally` should preserve promise + assimilation, cancellation, failure handling, and concurrent per-item pipelines rather than adding syntax-only + shims. Consider `Promise.any` in the same pass. +- [ ] Support async iteration and `for await...of`. Define behavior first for the runtime's supported promise and + collection values, then extend it to bounded host streams when a stream boundary exists. +- [ ] Complete the deterministic `Math` surface beyond the current arithmetic, rounding, root, power, and logarithm + helpers. Decide separately whether nondeterministic `Math.random` belongs in the runtime. +- [ ] Refine diagnostics so user throws, expected tool failures, unexpected host/tool defects, and genuine interpreter + defects are distinguishable without leaking private causes. + +### Tool and result contracts + +- [ ] Design explicit tagged representations and size rules before allowing Blob, File, ArrayBuffer, typed arrays, or + host streams to cross the sandbox boundary. +- [ ] Define one consistent policy for tool path segments named `__proto__`, `constructor`, or `prototype`. They must + either be safely callable, rejected before catalog generation, or use one documented escaping rule. diff --git a/packages/codemode/src/codemode.ts b/packages/codemode/src/codemode.ts index 083f62e28b5..d62f87a0df6 100644 --- a/packages/codemode/src/codemode.ts +++ b/packages/codemode/src/codemode.ts @@ -16,7 +16,16 @@ import { } from "./tool-runtime.js" import type { Definition } from "./tool.js" import { ToolError } from "./tool-error.js" -import { isSandboxValue, SandboxDate, SandboxMap, SandboxPromise, SandboxRegExp, SandboxSet } from "./values.js" +import { + isSandboxValue, + SandboxDate, + SandboxMap, + SandboxPromise, + SandboxRegExp, + SandboxSet, + SandboxURL, + SandboxURLSearchParams, +} from "./values.js" /** A tool call admitted during an execution. */ export type { ToolCall, ToolCallEnded, ToolCallHooks, ToolCallStarted, ToolDescription } from "./tool-runtime.js" @@ -184,7 +193,7 @@ type StatementResult = | { kind: "continue" } type MemberReference = { - target: SafeObject | Array + target: SafeObject | Array | SandboxURL key: string | number } @@ -217,7 +226,18 @@ class PromiseMethodReference { // A built-in global namespace (`Object`, `Math`, `JSON`, `Array`, ...); members resolve to a // GlobalMethodReference, except known constants (e.g. `Math.PI`) which resolve to a value. -type GlobalNamespaceName = "Object" | "Math" | "JSON" | "Array" | "console" | "Date" | "RegExp" | "Map" | "Set" +type GlobalNamespaceName = + | "Object" + | "Math" + | "JSON" + | "Array" + | "console" + | "Date" + | "RegExp" + | "Map" + | "Set" + | "URL" + | "URLSearchParams" class GlobalNamespace { constructor(readonly name: GlobalNamespaceName) {} @@ -234,6 +254,10 @@ class CoercionFunction { constructor(readonly name: "Number" | "String" | "Boolean" | "parseInt" | "parseFloat") {} } +class UriFunction { + constructor(readonly name: "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent") {} +} + class ProgramThrow { constructor(readonly value: unknown) {} } @@ -355,7 +379,7 @@ const errorConstructors = new Set([ "URIError", ]) -const valueConstructors = new Set(["Date", "RegExp", "Map", "Set"]) +const valueConstructors = new Set(["Date", "RegExp", "Map", "Set", "URL", "URLSearchParams"]) const dateMethods = new Set([ "getTime", @@ -400,10 +424,52 @@ const regexpProperties = new Set([ const mapMethods = new Set(["get", "set", "has", "delete", "clear", "forEach", "keys", "values", "entries"]) const setMethods = new Set(["add", "has", "delete", "clear", "forEach", "keys", "values", "entries"]) +const urlProperties = new Set([ + "href", + "origin", + "protocol", + "username", + "password", + "host", + "hostname", + "port", + "pathname", + "search", + "hash", +]) +const urlWritableProperties = new Set([ + "href", + "protocol", + "username", + "password", + "host", + "hostname", + "port", + "pathname", + "search", + "hash", +]) +const urlMethods = new Set(["toString", "toJSON"]) +const urlStatics = new Set(["canParse", "parse"]) +const urlSearchParamsMethods = new Set([ + "append", + "delete", + "get", + "getAll", + "has", + "set", + "sort", + "forEach", + "keys", + "values", + "entries", + "toString", +]) + const OptionalShortCircuit: unique symbol = Symbol("codemode.optional-short-circuit") const supportedSyntaxMessage = - "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, and Promise.all/allSettled/race/resolve/reject over arrays mixing promises and plain values for parallel tool calls (promise chaining with .then/.catch is not supported - use await with try/catch)." + "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set/URL/URLSearchParams, URI encoding helpers, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, and Promise.all/allSettled/race/resolve/reject over arrays mixing promises and plain values for parallel tool calls (promise chaining with .then/.catch is not supported - use await with try/catch)." const unsupportedSyntax = (kind: string, node: AstNode): InterpreterRuntimeError => new InterpreterRuntimeError( @@ -662,6 +728,7 @@ const isRuntimeReference = (value: unknown): boolean => value instanceof PromiseMethodReference || value instanceof SandboxPromise || value instanceof CoercionFunction || + value instanceof UriFunction || value instanceof ErrorConstructorReference || isSandboxValue(value) @@ -677,7 +744,7 @@ const containsRuntimeReference = (value: unknown, seen = new Set()): boo return contains } -// Like containsRuntimeReference, but sandbox value types (Date/RegExp/Map/Set) count as data: +// Like containsRuntimeReference, but sandbox standard-library values count as data: // operators and switch treat them as ordinary object operands (identity equality, ToPrimitive // coercion) rather than rejecting them as opaque interpreter machinery. const containsOpaqueReference = (value: unknown, seen = new Set()): boolean => { @@ -707,6 +774,7 @@ const typeofValue = (value: unknown): string => { value instanceof ErrorConstructorReference ) return "function" + if (value instanceof UriFunction) return "function" if (value instanceof ToolReference) return value.path.length > 0 ? "function" : "object" if (value instanceof GlobalNamespace) { return value.name === "Math" || value.name === "JSON" || value.name === "console" ? "object" : "function" @@ -733,6 +801,10 @@ const instanceofValue = (lhs: unknown, rhs: unknown, node: AstNode): boolean => return lhs instanceof SandboxMap case "Set": return lhs instanceof SandboxSet + case "URL": + return lhs instanceof SandboxURL + case "URLSearchParams": + return lhs instanceof SandboxURLSearchParams case "Array": return Array.isArray(lhs) case "Object": @@ -746,7 +818,7 @@ const instanceofValue = (lhs: unknown, rhs: unknown, node: AstNode): boolean => return false } throw new InterpreterRuntimeError( - "The right-hand side of 'instanceof' must be a constructor CodeMode knows: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, Array, Object, or Promise.", + "The right-hand side of 'instanceof' must be a constructor CodeMode knows: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise.", node, ) } @@ -885,14 +957,6 @@ const invokeStringMethod = (value: string, name: string, args: Array, n break case "replace": case "replaceAll": { - if (args[0] instanceof CodeModeFunction || args[1] instanceof CodeModeFunction) { - throw new InterpreterRuntimeError( - `String.${name} does not support function replacers in CodeMode; use match/matchAll and rebuild the string instead.`, - node, - "UnsupportedSyntax", - [supportedSyntaxMessage], - ) - } if (args[0] instanceof SandboxRegExp) { const pattern = (args[0] as SandboxRegExp).regex const replacement = str(1) @@ -1028,6 +1092,8 @@ const coerceToString = (value: unknown): string => { if (value instanceof SandboxRegExp) return `/${value.regex.source}/${value.regex.flags}` if (value instanceof SandboxMap) return "[object Map]" if (value instanceof SandboxSet) return "[object Set]" + if (value instanceof SandboxURL) return value.url.href + if (value instanceof SandboxURLSearchParams) return value.params.toString() if (typeof value === "object") { return Array.isArray(value) ? value.map((item) => (item === null || item === undefined ? "" : coerceToString(item))).join(",") @@ -1072,7 +1138,7 @@ const invokeCoercion = (ref: CoercionFunction, args: Array, node: AstNo const invokeObjectMethod = (name: string, args: Array, node: AstNode): unknown => { const requireObject = (): Record => { const value = boundedData(args[0], `Object.${name} input`) - // Sandbox values (Date/RegExp/Map/Set) have no own enumerable properties in JS, so the + // Sandbox standard-library values have no own enumerable properties in JS, so the // Object.* helpers see them as empty objects - never their interpreter internals. if (isSandboxValue(value)) return {} if (value === null || typeof value !== "object" || Array.isArray(value)) { @@ -1124,6 +1190,11 @@ const invokeObjectMethod = (name: string, args: Array, node: AstNode): for (const [key, item] of (args[0] as SandboxMap).map.entries()) guardedSet(out, coerceToString(key), item) return out } + if (args[0] instanceof SandboxURLSearchParams) { + const out: Record = Object.create(null) + for (const [key, value] of args[0].params.entries()) guardedSet(out, key, value) + return out + } const pairs = boundedData(args[0], "Object.fromEntries input") if (!Array.isArray(pairs)) throw new InterpreterRuntimeError("Object.fromEntries expects an array of [key, value] pairs.", node) @@ -1241,6 +1312,9 @@ const invokeArrayStatic = (name: string, args: Array, node: AstNode): u if (args[0] instanceof SandboxMap) return Array.from((args[0] as SandboxMap).map.entries(), ([key, item]) => [key, item]) if (args[0] instanceof SandboxSet) return Array.from((args[0] as SandboxSet).set.values()) + if (args[0] instanceof SandboxURLSearchParams) { + return Array.from(args[0].params.entries(), ([key, value]) => [key, value]) + } const source = boundedData(args[0], "Array.from input") if (typeof source === "string") return Array.from(source) if (Array.isArray(source)) return [...source] @@ -1385,6 +1459,52 @@ const invokeRegExpMethod = (value: SandboxRegExp, name: string, args: Array coerceToString(boundedData(value, label)) + +const invokeUriFunction = (ref: UriFunction, args: Array, node: AstNode): string => { + const value = uriArgument(args[0], `${ref.name} input`) + try { + switch (ref.name) { + case "encodeURI": + return encodeURI(value) + case "encodeURIComponent": + return encodeURIComponent(value) + case "decodeURI": + return decodeURI(value) + case "decodeURIComponent": + return decodeURIComponent(value) + } + } catch (error) { + throw new InterpreterRuntimeError( + `${ref.name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}`, + node, + ).as("URIError") + } +} + +const urlArgument = (value: unknown, label: string): string => + value instanceof SandboxURL ? value.url.href : uriArgument(value, label) + +const invokeURLStatic = (name: string, args: Array, node: AstNode): unknown => { + if (!urlStatics.has(name)) throw new InterpreterRuntimeError(`URL.${name} is not available in CodeMode.`, node) + if (args.length === 0) { + throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node).as("TypeError") + } + const input = urlArgument(args[0], `URL.${name} input`) + const base = args[1] === undefined ? undefined : urlArgument(args[1], `URL.${name} base`) + try { + const url = new URL(input, base) + return name === "canParse" ? true : new SandboxURL(url) + } catch { + return name === "canParse" ? false : null + } +} + +const invokeURLMethod = (value: SandboxURL, name: string, node: AstNode): string => { + if (name === "toString" || name === "toJSON") return value.url.href + throw new InterpreterRuntimeError(`URL method '${name}' is not available in CodeMode.`, node) +} + const invokeGlobalMethod = (ref: GlobalMethodReference, args: Array, node: AstNode): unknown => { if (ref.namespace === "console") throw new InterpreterRuntimeError(`console.${ref.name} is not available in CodeMode.`, node) @@ -1393,12 +1513,18 @@ const invokeGlobalMethod = (ref: GlobalMethodReference, args: Array, no if (ref.namespace === "Array") return invokeArrayStatic(ref.name, args, node) if (ref.namespace === "Number") return invokeNumberStatic(ref.name, args, node) if (ref.namespace === "String") return invokeStringStatic(ref.name, args, node) + if (ref.namespace === "URL") return invokeURLStatic(ref.name, args, node) if (ref.namespace === "Date") { if (!dateStatics.has(ref.name)) throw new InterpreterRuntimeError(`Date.${ref.name} is not available in CodeMode.`, node) return invokeDateStatic(ref.name, args, node) } - if (ref.namespace === "RegExp" || ref.namespace === "Map" || ref.namespace === "Set") { + if ( + ref.namespace === "RegExp" || + ref.namespace === "Map" || + ref.namespace === "Set" || + ref.namespace === "URLSearchParams" + ) { throw new InterpreterRuntimeError(`${ref.namespace}.${ref.name} is not available in CodeMode.`, node) } return invokeJsonMethod(ref.name, args, node) @@ -1411,6 +1537,8 @@ const spreadItems = (spread: unknown): Array | undefined => { if (spread instanceof SandboxMap) return Array.from(spread.map.entries(), ([key, item]): Array => [key, item]) if (spread instanceof SandboxSet) return Array.from(spread.set.values()) + if (spread instanceof SandboxURLSearchParams) + return Array.from(spread.params.entries(), ([key, value]): Array => [key, value]) return undefined } @@ -1485,6 +1613,12 @@ class Interpreter { globalScope.set("RegExp", { mutable: false, value: new GlobalNamespace("RegExp") }) globalScope.set("Map", { mutable: false, value: new GlobalNamespace("Map") }) globalScope.set("Set", { mutable: false, value: new GlobalNamespace("Set") }) + globalScope.set("URL", { mutable: false, value: new GlobalNamespace("URL") }) + globalScope.set("URLSearchParams", { mutable: false, value: new GlobalNamespace("URLSearchParams") }) + globalScope.set("encodeURI", { mutable: false, value: new UriFunction("encodeURI") }) + globalScope.set("encodeURIComponent", { mutable: false, value: new UriFunction("encodeURIComponent") }) + globalScope.set("decodeURI", { mutable: false, value: new UriFunction("decodeURI") }) + globalScope.set("decodeURIComponent", { mutable: false, value: new UriFunction("decodeURIComponent") }) // Error constructors are real values, so `x instanceof Error` works and `Error("msg")` // (with or without `new`) constructs a branded { name, message } error object. for (const name of errorConstructors) { @@ -2331,8 +2465,12 @@ class Interpreter { return self.constructRegExp(args, node) case "Map": return self.constructMap(args[0], node) - default: + case "Set": return self.constructSet(args[0], node) + case "URL": + return self.constructURL(args, node) + default: + return self.constructURLSearchParams(args[0], node) } }) } @@ -2421,6 +2559,67 @@ class Interpreter { return target } + private constructURL(args: Array, node: AstNode): SandboxURL { + if (args.length === 0) { + throw new InterpreterRuntimeError("new URL(...) requires a URL string and an optional base URL.", node).as( + "TypeError", + ) + } + const input = urlArgument(args[0], "new URL input") + const base = args[1] === undefined ? undefined : urlArgument(args[1], "new URL base") + try { + return new SandboxURL(new URL(input, base)) + } catch { + throw new InterpreterRuntimeError( + `new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`, + node, + ).as("TypeError") + } + } + + private constructURLSearchParams(init: unknown, node: AstNode): SandboxURLSearchParams { + if (init === undefined) return new SandboxURLSearchParams(new URLSearchParams()) + if (init instanceof SandboxURLSearchParams) { + return new SandboxURLSearchParams(new URLSearchParams(init.params)) + } + if (typeof init === "string") return new SandboxURLSearchParams(new URLSearchParams(init)) + if (init === null || typeof init === "number" || typeof init === "boolean") { + return new SandboxURLSearchParams(new URLSearchParams(coerceToString(init))) + } + if (init instanceof SandboxMap) { + return this.constructURLSearchParams( + Array.from(init.map.entries(), ([key, value]) => [key, value]), + node, + ) + } + if (Array.isArray(init)) { + const entries = init.map((pair) => { + if (!Array.isArray(pair) || pair.length !== 2) { + throw new InterpreterRuntimeError( + "new URLSearchParams(...) expects an array of [name, value] pairs.", + node, + ).as("TypeError") + } + return [uriArgument(pair[0], "URLSearchParams name"), uriArgument(pair[1], "URLSearchParams value")] as [ + string, + string, + ] + }) + return new SandboxURLSearchParams(new URLSearchParams(entries)) + } + if (isSandboxValue(init)) return new SandboxURLSearchParams(new URLSearchParams()) + const data = boundedData(init, "new URLSearchParams input") + if (data === null || typeof data !== "object") { + throw new InterpreterRuntimeError( + "new URLSearchParams(...) expects a query string, data object, array of pairs, or URLSearchParams.", + node, + ).as("TypeError") + } + return new SandboxURLSearchParams( + new URLSearchParams(Object.fromEntries(Object.entries(data).map(([key, value]) => [key, coerceToString(value)]))), + ) + } + private evaluateBinaryExpression(node: AstNode): Effect.Effect { const operator = getString(node, "operator") const self = this @@ -2699,6 +2898,9 @@ class Interpreter { if (callable instanceof CoercionFunction) { return boundedData(invokeCoercion(callable, args, node), `${callable.name} result`) } + if (callable instanceof UriFunction) { + return invokeUriFunction(callable, args, node) + } // `Error("msg")` without `new` constructs an error exactly like `new Error("msg")`, as in JS. if (callable instanceof ErrorConstructorReference) { return createErrorValue(callable.name, args[0] === undefined ? "" : coerceToString(args[0])) @@ -2759,6 +2961,8 @@ class Interpreter { if (value instanceof SandboxPromise) return "[Promise (await it to get its value)]" if (value instanceof SandboxDate) return coerceToString(value) if (value instanceof SandboxRegExp) return coerceToString(value) + if (value instanceof SandboxURL) return coerceToString(value) + if (value instanceof SandboxURLSearchParams) return coerceToString(value) if (depth > MAX_CONSOLE_DEPTH) return "..." if (seen.has(value)) return "[Circular]" if (value instanceof SandboxMap) { @@ -3026,6 +3230,12 @@ class Interpreter { node: AstNode, ): Effect.Effect { if (typeof ref.receiver === "string") { + if ( + (ref.name === "replace" || ref.name === "replaceAll") && + (args[1] instanceof CodeModeFunction || args[1] instanceof CoercionFunction || args[1] instanceof UriFunction) + ) { + return this.invokeStringReplacer(ref.receiver, ref.name, args, node) + } return Effect.succeed(invokeStringMethod(ref.receiver, ref.name, args, node)) } if (typeof ref.receiver === "number") { @@ -3046,23 +3256,95 @@ class Interpreter { if (ref.receiver instanceof SandboxSet) { return this.invokeSetMethod(ref.receiver, ref.name, args, node) } + if (ref.receiver instanceof SandboxURL) { + return Effect.succeed(invokeURLMethod(ref.receiver, ref.name, node)) + } + if (ref.receiver instanceof SandboxURLSearchParams) { + return this.invokeURLSearchParamsMethod(ref.receiver, ref.name, args, node) + } throw new InterpreterRuntimeError(`Method '${ref.name}' is not available in CodeMode.`, node) } - // Runs a Map/Set callback (forEach) accepting a user function or a builtin coercion, + private invokeStringReplacer( + value: string, + name: "replace" | "replaceAll", + args: Array, + node: AstNode, + ): Effect.Effect { + const apply = this.applyCollectionCallback(args[1], `String.${name}`, node) + const matches: Array<{ readonly match: string; readonly offset: number; readonly args: Array }> = [] + const collect = (...callbackArgs: Array): string => { + const match = callbackArgs[0] + const groups = callbackArgs[callbackArgs.length - 1] + const hasGroups = groups !== null && typeof groups === "object" + const offset = callbackArgs[callbackArgs.length - (hasGroups ? 3 : 2)] + if (typeof match !== "string" || typeof offset !== "number") { + throw new InterpreterRuntimeError(`String.${name} produced an invalid replacement match.`, node) + } + if (hasGroups) { + const safeGroups: SafeObject = Object.create(null) as SafeObject + for (const [key, group] of Object.entries(groups)) { + if (!isBlockedMember(key)) safeGroups[key] = group + } + callbackArgs[callbackArgs.length - 1] = safeGroups + } + matches.push({ match, offset, args: callbackArgs }) + return match + } + + const pattern = args[0] + if (pattern instanceof SandboxRegExp) { + if (name === "replaceAll" && !pattern.regex.global) { + throw new InterpreterRuntimeError( + `String.replaceAll requires a regular expression with the global (g) flag: write /${pattern.regex.source}/${pattern.regex.flags}g, or use String.replace to replace only the first match.`, + node, + ) + } + if (name === "replace") value.replace(pattern.regex, collect) + else value.replaceAll(pattern.regex, collect) + } else { + if (typeof pattern !== "string") { + throw new InterpreterRuntimeError(`String.${name} expects argument 1 to be a string.`, node) + } + if (name === "replace") value.replace(pattern, collect) + else value.replaceAll(pattern, collect) + } + + return Effect.gen(function* () { + const output: Array = [] + let end = 0 + for (const match of matches) { + output.push( + value.slice(end, match.offset), + coerceToString(boundedData(yield* apply(match.args), `String.${name} replacer result`)), + ) + end = match.offset + match.match.length + } + output.push(value.slice(end)) + return boundedData(output.join(""), `String.${name} result`) + }) + } + + // Runs a collection callback accepting a user function or supported builtin callable, // mirroring the array-method callback contract. private applyCollectionCallback( callback: unknown, name: string, node: AstNode, ): (args: Array) => Effect.Effect { - if (!(callback instanceof CodeModeFunction) && !(callback instanceof CoercionFunction)) { + if ( + !(callback instanceof CodeModeFunction) && + !(callback instanceof CoercionFunction) && + !(callback instanceof UriFunction) + ) { throw new InterpreterRuntimeError(`${name} expects a function callback.`, node) } return (callbackArgs) => callback instanceof CoercionFunction ? Effect.succeed(invokeCoercion(callback, callbackArgs, node)) - : this.invokeFunction(callback, callbackArgs) + : callback instanceof UriFunction + ? Effect.succeed(invokeUriFunction(callback, callbackArgs, node)) + : this.invokeFunction(callback, callbackArgs) } private invokeMapMethod( @@ -3145,6 +3427,81 @@ class Interpreter { } } + private invokeURLSearchParamsMethod( + target: SandboxURLSearchParams, + name: string, + args: Array, + node: AstNode, + ): Effect.Effect { + const arg = (index: number): string => uriArgument(args[index], `URLSearchParams.${name} argument ${index + 1}`) + const requireArgs = (count: number): void => { + if (args.length < count) { + throw new InterpreterRuntimeError( + `URLSearchParams.${name} requires ${count} argument${count === 1 ? "" : "s"}.`, + node, + ).as("TypeError") + } + } + switch (name) { + case "append": { + requireArgs(2) + return Effect.sync(() => { + target.params.append(arg(0), arg(1)) + return undefined + }) + } + case "delete": { + requireArgs(1) + return Effect.sync(() => { + if (args[1] !== undefined) target.params.delete(arg(0), arg(1)) + else target.params.delete(arg(0)) + return undefined + }) + } + case "get": + requireArgs(1) + return Effect.sync(() => target.params.get(arg(0))) + case "getAll": + requireArgs(1) + return Effect.sync(() => target.params.getAll(arg(0))) + case "has": + requireArgs(1) + return Effect.sync(() => + args[1] !== undefined ? target.params.has(arg(0), arg(1)) : target.params.has(arg(0)), + ) + case "set": { + requireArgs(2) + return Effect.sync(() => { + target.params.set(arg(0), arg(1)) + return undefined + }) + } + case "sort": + return Effect.sync(() => { + target.params.sort() + return undefined + }) + case "keys": + return Effect.sync(() => Array.from(target.params.keys())) + case "values": + return Effect.sync(() => Array.from(target.params.values())) + case "entries": + return Effect.sync(() => Array.from(target.params.entries(), ([key, value]): Array => [key, value])) + case "toString": + return Effect.sync(() => target.params.toString()) + case "forEach": { + requireArgs(1) + const apply = this.applyCollectionCallback(args[0], "URLSearchParams.forEach", node) + return Effect.gen(function* () { + for (const [key, value] of Array.from(target.params.entries())) yield* apply([value, key, target]) + return undefined + }) + } + default: + throw new InterpreterRuntimeError(`URLSearchParams method '${name}' is not available in CodeMode.`, node) + } + } + private invokeArrayMethod( target: Array, name: string, @@ -3254,17 +3611,23 @@ class Interpreter { } const callback = args[0] - if (!(callback instanceof CodeModeFunction) && !(callback instanceof CoercionFunction)) { + if ( + !(callback instanceof CodeModeFunction) && + !(callback instanceof CoercionFunction) && + !(callback instanceof UriFunction) + ) { throw new InterpreterRuntimeError(`Array.${name} expects a function callback.`, node) } const self = this - // Accept a user arrow function or a builtin coercion callable (Boolean/String/Number), so the - // idioms `filter(Boolean)` / `map(String)` / `map(Number)` work as in JS. Coercions are - // synchronous; only CodeModeFunctions can await tool calls. + // Accept a user function or supported builtin callable, so idioms such as + // `filter(Boolean)`, `map(String)`, and `map(encodeURIComponent)` work as in JS. Builtins + // are synchronous; only CodeModeFunctions can await tool calls. const apply = (callbackArgs: Array): Effect.Effect => callback instanceof CoercionFunction ? Effect.succeed(invokeCoercion(callback, callbackArgs, node)) - : self.invokeFunction(callback, callbackArgs) + : callback instanceof UriFunction + ? Effect.succeed(invokeUriFunction(callback, callbackArgs, node)) + : self.invokeFunction(callback, callbackArgs) return Effect.gen(function* () { // Iterate a snapshot taken at call time so a callback that mutates the array can't // self-extend the loop - matching JS, where elements appended during iteration are not visited. @@ -3418,7 +3781,7 @@ class Interpreter { const spread = yield* self.evaluateExpression(getNode(property, "argument")) // JS treats `{ ...null }` / `{ ...undefined }` as a no-op, so the common // `{ ...maybeOpts, override }` merge works when the operand is absent. Sandbox values - // (Date/RegExp/Map/Set) have no own enumerable properties in JS, so they are no-ops too. + // have no own enumerable properties in JS, so they are no-ops too. if (spread === null || spread === undefined || isSandboxValue(spread)) continue if (typeof spread !== "object" || Array.isArray(spread) || isRuntimeReference(spread)) { throw new InterpreterRuntimeError( @@ -3655,6 +4018,21 @@ class Interpreter { if (typeof key === "string" && setMethods.has(key)) return new IntrinsicReference(objectValue, key) return new ComputedValue(undefined) } + if (objectValue instanceof SandboxURL) { + if (key === "searchParams") { + return new ComputedValue(objectValue.searchParams) + } + if (typeof key === "string" && urlMethods.has(key)) return new IntrinsicReference(objectValue, key) + if (typeof key === "string" && urlProperties.has(key)) return { target: objectValue, key } + return new ComputedValue(undefined) + } + if (objectValue instanceof SandboxURLSearchParams) { + if (key === "size") return new ComputedValue(objectValue.params.size) + if (typeof key === "string" && urlSearchParamsMethods.has(key)) { + return new IntrinsicReference(objectValue, key) + } + return new ComputedValue(undefined) + } // Any property access on a promise is a confused program (`p.then(...)`, `p.value`); // reading `undefined` here would hide the missing await, so both paths get an explicit, @@ -3732,6 +4110,9 @@ class Interpreter { } return reference.key === "length" ? reference.target.length : reference.target[Number(reference.key)] } + if (reference.target instanceof SandboxURL) { + return (reference.target.url as unknown as Record)[String(reference.key)] + } return reference.target[String(reference.key)] }) } @@ -3769,7 +4150,10 @@ class Interpreter { } } const key = Array.isArray(reference.target) ? Number(reference.key) : String(reference.key) - const current = (reference.target as Record)[key] + const current = + reference.target instanceof SandboxURL + ? (reference.target.url as unknown as Record)[key] + : (reference.target as Record)[key] const { write, next, result } = yield* compute(current) if (write) self.assignToReference(reference, key, next, node) return result @@ -3809,6 +4193,20 @@ class Interpreter { target[index] = next return } + if (reference.target instanceof SandboxURL) { + const property = key as string + if (!urlWritableProperties.has(property)) { + throw new InterpreterRuntimeError(`URL.${property} is read-only.`, node).as("TypeError") + } + try { + const url = reference.target.url as unknown as Record + url[property] = uriArgument(next, `URL.${property} value`) + return + } catch (error) { + if (error instanceof InterpreterRuntimeError || error instanceof ToolRuntimeError) throw error + throw new InterpreterRuntimeError(`URL.${property} received an invalid value.`, node).as("TypeError") + } + } const target = reference.target as SafeObject const objectKey = key as string this.rejectCircularInsertion(target, next, "Object assignment result", node) diff --git a/packages/codemode/src/tool-runtime.ts b/packages/codemode/src/tool-runtime.ts index 64fbc6d14ea..f4ccc61d4c4 100644 --- a/packages/codemode/src/tool-runtime.ts +++ b/packages/codemode/src/tool-runtime.ts @@ -9,7 +9,15 @@ import { outputTypeScript, } from "./tool-schema.js" import { isDefinition as isToolDefinition, type Definition } from "./tool.js" -import { SandboxDate, SandboxMap, SandboxPromise, SandboxRegExp, SandboxSet } from "./values.js" +import { + SandboxDate, + SandboxMap, + SandboxPromise, + SandboxRegExp, + SandboxSet, + SandboxURL, + SandboxURLSearchParams, +} from "./values.js" const estimateTokens = (input: string) => Math.max(0, Math.round(input.length / 4)) @@ -152,9 +160,9 @@ export const isBlockedMember = (name: string): boolean => blockedMemberNames.has * Two modes share the walk: * - **Boundary** (`preserveSandboxValues` false, the default): the host<->sandbox boundary - * final results, tool-call arguments, `JSON.stringify`. Sandbox value types serialize - * exactly as JSON.stringify would: Date -> ISO string (invalid -> null), RegExp/Map/Set -> {}. + * exactly as JSON.stringify would: Date/URL -> strings, the remaining value types -> {}. * - **Intra-sandbox checkpoint** (`preserveSandboxValues` true; see `boundedData` in - * codemode.ts): Date/RegExp/Map/Set instances pass through untouched (treated as leaves, + * codemode.ts): standard-library value instances pass through untouched (treated as leaves, * contents not walked), so values flowing through `Object.*` helpers, coercion inputs, and * other in-sandbox checkpoints stay fully usable (`.getTime()`, `.has()`, ...). * @@ -208,7 +216,9 @@ const copyBounded = ( value instanceof SandboxDate || value instanceof SandboxRegExp || value instanceof SandboxMap || - value instanceof SandboxSet + value instanceof SandboxSet || + value instanceof SandboxURL || + value instanceof SandboxURLSearchParams ) { return value } @@ -228,24 +238,30 @@ const copyBounded = ( for (const item of value.values()) wrapped.set.add(copyBounded(item, label, depth + 1, seen, true)) return wrapped } + if (value instanceof URL) return new SandboxURL(new URL(value.href)) + if (value instanceof URLSearchParams) return new SandboxURLSearchParams(new URLSearchParams(value)) } // Sandbox value types (and their host counterparts, which a host tool may legitimately - // return) serialize exactly as JSON.stringify would at the data boundary: a Date is its - // toJSON() ISO string (invalid -> null), and RegExp/Map/Set have no JSON form beyond {}. + // return) serialize exactly as JSON.stringify would at the data boundary: Date/URL use + // toJSON(), while RegExp/Map/Set/URLSearchParams have no JSON form beyond {}. if (value instanceof SandboxDate) { return Number.isFinite(value.time) ? new Date(value.time).toISOString() : null } if (value instanceof Date) { return Number.isFinite(value.getTime()) ? value.toISOString() : null } + if (value instanceof SandboxURL) return value.url.href + if (value instanceof URL) return value.href if ( value instanceof SandboxRegExp || value instanceof SandboxMap || value instanceof SandboxSet || + value instanceof SandboxURLSearchParams || value instanceof RegExp || value instanceof Map || - value instanceof Set + value instanceof Set || + value instanceof URLSearchParams ) { return Object.create(null) as SafeObject } @@ -589,9 +605,9 @@ export const prepare = (tools: HostTools, catalogBudget = defaultCatalogBu "", "## Language", "", - "Use common JavaScript data operations, functions, control flow, selected standard-library methods, and awaited tool calls.", - "Modules/imports, classes, generators, timers, fetch, eval, prototype access, arbitrary methods, and promise chaining are unavailable. Use Code Mode tools for external operations. Use await with try/catch.", - "Dates serialize to ISO strings at data boundaries; Map/Set/RegExp serialize to `{}`.", + "Use common JavaScript data operations, functions, control flow, selected standard-library methods, and awaited tool calls. Built-ins include Date, RegExp, Map, Set, URL, URLSearchParams, and URI encoding helpers.", + "Modules/imports, classes, generators, timers, fetch, eval, prototype access, unlisted methods, and promise chaining are unavailable. Use Code Mode tools for external operations. Use await with try/catch.", + "Dates and URLs serialize to strings at data boundaries; Map/Set/RegExp/URLSearchParams serialize to `{}`.", ] const toolSection: Array = [""] diff --git a/packages/codemode/src/values.ts b/packages/codemode/src/values.ts index 07f22adb8a2..4ca305d815e 100644 --- a/packages/codemode/src/values.ts +++ b/packages/codemode/src/values.ts @@ -27,8 +27,23 @@ export class SandboxSet { readonly set = new Set() } -export const isSandboxValue = (value: unknown): value is SandboxDate | SandboxRegExp | SandboxMap | SandboxSet => +export class SandboxURLSearchParams { + constructor(readonly params: URLSearchParams) {} +} + +export class SandboxURL { + readonly searchParams: SandboxURLSearchParams + constructor(readonly url: URL) { + this.searchParams = new SandboxURLSearchParams(url.searchParams) + } +} + +export const isSandboxValue = ( + value: unknown, +): value is SandboxDate | SandboxRegExp | SandboxMap | SandboxSet | SandboxURL | SandboxURLSearchParams => value instanceof SandboxDate || value instanceof SandboxRegExp || value instanceof SandboxMap || - value instanceof SandboxSet + value instanceof SandboxSet || + value instanceof SandboxURL || + value instanceof SandboxURLSearchParams diff --git a/packages/codemode/test/codemode.test.ts b/packages/codemode/test/codemode.test.ts index f5a7169cf55..221b5e07dfe 100644 --- a/packages/codemode/test/codemode.test.ts +++ b/packages/codemode/test/codemode.test.ts @@ -655,9 +655,11 @@ describe("CodeMode public contract", () => { for (const missing of ["Modules/imports", "classes", "generators", "fetch", "promise chaining"]) { expect(instructions).toContain(missing) } + expect(instructions).toContain("URL, URLSearchParams, and URI encoding helpers") + expect(instructions).not.toContain("host globals") expect(instructions).toContain("Use Code Mode tools for external operations") expect(instructions).toContain( - "Dates serialize to ISO strings at data boundaries; Map/Set/RegExp serialize to `{}`.", + "Dates and URLs serialize to strings at data boundaries; Map/Set/RegExp/URLSearchParams serialize to `{}`.", ) }) diff --git a/packages/codemode/test/stdlib.test.ts b/packages/codemode/test/stdlib.test.ts index ac0e8e2e794..f7831a06033 100644 --- a/packages/codemode/test/stdlib.test.ts +++ b/packages/codemode/test/stdlib.test.ts @@ -1,12 +1,12 @@ import { describe, expect, test } from "bun:test" -import { Effect } from "effect" +import { Effect, Schema } from "effect" import { CodeMode, Tool } from "../src/index.js" // Standard-library value types: Date, RegExp, Map, Set. Programs use them as ordinary JS; // intra-sandbox checkpoints (Object.* helpers, spread, coercion inputs) preserve the live // values, while at the host boundary (final result, tool arguments, JSON.stringify) they // serialize exactly as JSON.stringify would: Date -> ISO string (invalid -> null), -// RegExp/Map/Set -> {}. +// URL -> href, and RegExp/Map/Set/URLSearchParams -> {}. const run = (code: string) => Effect.runPromise(CodeMode.execute({ code, tools: {} })) const value = async (code: string) => { const result = await run(code) @@ -149,6 +149,67 @@ describe("RegExp", () => { expect(await value(`return "hi bob".replace(/b(o)b/, "[$1]")`)).toBe("hi [o]") }) + test("function replacers receive captures, offsets, input, and named groups", async () => { + expect( + await value(` + const seen = [] + const output = "a1b22".replace(/(\\d)(\\d)?/g, (match, first, second, offset, input) => { + seen.push([match, first, second === undefined, offset, input]) + return Number(match) * 2 + }) + return { output, seen } + `), + ).toEqual({ + output: "a2b44", + seen: [ + ["1", "1", true, 1, "a1b22"], + ["22", "2", false, 3, "a1b22"], + ], + }) + expect( + await value(` + return "red-blue".replace( + /(?[a-z]+)-(?[a-z]+)/, + (match, left, right, offset, input, groups) => groups.right + ":" + groups.left, + ) + `), + ).toBe("blue:red") + }) + + test("function replacers support string searches, zero-length matches, and result coercion", async () => { + expect(await value(`return "banana".replace("na", (match, offset, input) => "[" + offset + "]")`)).toBe("ba[2]na") + expect(await value(`return "ab".replaceAll("", (match, offset) => offset)`)).toBe("0a1b2") + expect(await value(`return "😀".replaceAll(/(?:)/gu, (match, offset) => "[" + offset + "]")`)).toBe("[0]😀[2]") + expect( + await value(`return "123".replace(/\\d/g, (match) => match === "1" ? 7 : match === "2" ? null : { n: 3 })`), + ).toBe("7null[object Object]") + }) + + test("function replacers can await effectful tool calls", async () => { + const decorate = Tool.make({ + description: "Decorate a string", + input: Schema.String, + output: Schema.String, + run: (input) => Effect.succeed(`[${input}]`), + }) + const result = await Effect.runPromise( + CodeMode.execute({ + tools: { host: { decorate } }, + code: `return "a1b22".replace(/\\d+/g, async (match) => await tools.host.decorate(match))`, + }), + ) + expect(result.ok && result.value).toBe("a[1]b[22]") + + const missingAwait = await Effect.runPromise( + CodeMode.execute({ + tools: { host: { decorate } }, + code: `return "a1".replace(/\\d/, (match) => tools.host.decorate(match))`, + }), + ) + expect(!missingAwait.ok && missingAwait.error.kind).toBe("InvalidDataValue") + expect(!missingAwait.ok && missingAwait.error.message).toContain("un-awaited Promise") + }) + test("replaceAll without the g flag is a catchable error", async () => { expect(await value(`try { "a".replaceAll(/a/, "b"); return "no" } catch { return "caught" }`)).toBe("caught") }) @@ -208,6 +269,165 @@ describe("RegExp", () => { }) }) +describe("URL and URI helpers", () => { + test("encodes and decodes complete URIs and URI components", async () => { + expect( + await value(` + return [ + encodeURI("https://example.test/a b?q=a/b"), + encodeURIComponent("a b/c?"), + decodeURI("https://example.test/a%20b?q=a/b"), + decodeURIComponent("a%20b%2Fc%3F"), + ["a b", "c/d"].map(encodeURIComponent), + ] + `), + ).toEqual([ + "https://example.test/a%20b?q=a/b", + "a%20b%2Fc%3F", + "https://example.test/a b?q=a/b", + "a b/c?", + ["a%20b", "c%2Fd"], + ]) + expect( + await value(`try { decodeURIComponent("%zz"); return false } catch (error) { return error instanceof URIError }`), + ).toBe(true) + }) + + test("resolves and mutates URLs with linked search parameters", async () => { + expect( + await value(` + const url = new URL("../users?id=old#top", "https://user:pass@example.com:8443/api/v1/") + url.pathname = "/items/a b" + url.searchParams.set("id", "a b") + url.searchParams.append("tag", "x/y") + url.hash = "part 1" + return { + href: url.href, + origin: url.origin, + host: url.host, + pathname: url.pathname, + search: url.search, + id: url.searchParams.get("id"), + string: String(url), + json: url.toJSON(), + instances: [ + url instanceof URL, + url.searchParams instanceof URLSearchParams, + url.searchParams === url.searchParams, + ], + } + `), + ).toEqual({ + href: "https://user:pass@example.com:8443/items/a%20b?id=a+b&tag=x%2Fy#part%201", + origin: "https://example.com:8443", + host: "example.com:8443", + pathname: "/items/a%20b", + search: "?id=a+b&tag=x%2Fy", + id: "a b", + string: "https://user:pass@example.com:8443/items/a%20b?id=a+b&tag=x%2Fy#part%201", + json: "https://user:pass@example.com:8443/items/a%20b?id=a+b&tag=x%2Fy#part%201", + instances: [true, true, true], + }) + }) + + test("URLSearchParams supports records, pairs, mutation, callbacks, and materialization", async () => { + expect( + await value(` + const params = new URLSearchParams([["tag", "b"], ["tag", "a"], ["q", "a b"]]) + const seen = [] + params.forEach((value, key) => seen.push(key + "=" + value)) + params.delete("tag", "b") + params.append("tag", "c") + params.sort() + return { + text: params.toString(), + size: params.size, + tags: params.getAll("tag"), + has: params.has("tag", "c"), + entries: Array.from(params), + object: Object.fromEntries(params), + record: new URLSearchParams({ page: 2, filter: "open" }).toString(), + seen, + } + `), + ).toEqual({ + text: "q=a+b&tag=a&tag=c", + size: 3, + tags: ["a", "c"], + has: true, + entries: [ + ["q", "a b"], + ["tag", "a"], + ["tag", "c"], + ], + object: { q: "a b", tag: "c" }, + record: "page=2&filter=open", + seen: ["tag=b", "tag=a", "q=a b"], + }) + }) + + test("URL parsing failures are catchable and values use native JSON forms", async () => { + expect( + await value(` + const parsed = URL.parse("/users", "https://example.test/api/") + let invalidIsTypeError = false + try { new URL("not relative without a base") } catch (error) { invalidIsTypeError = error instanceof TypeError } + return { + canParse: URL.canParse("/users", "https://example.test/api/"), + cannotParse: URL.canParse("not relative without a base"), + parsed: parsed.href, + invalidIsTypeError, + boundary: [new URL("https://example.test/a"), new URLSearchParams("q=one")], + json: JSON.stringify({ url: new URL("https://example.test/a"), params: new URLSearchParams("q=one") }), + } + `), + ).toEqual({ + canParse: true, + cannotParse: false, + parsed: "https://example.test/users", + invalidIsTypeError: true, + boundary: ["https://example.test/a", {}], + json: '{"url":"https://example.test/a","params":{}}', + }) + }) + + test("distinguishes omitted URL arguments from explicit undefined", async () => { + expect( + await value(` + function throwsTypeError(run) { + try { run(); return false } catch (error) { return error instanceof TypeError } + } + const params = new URLSearchParams() + const required = [ + () => params.append(), + () => params.delete(), + () => params.get(), + () => params.getAll(), + () => params.has(), + () => params.set(), + () => params.forEach(), + ].map(throwsTypeError) + params.append(undefined, undefined) + return { + construct: throwsTypeError(() => new URL()), + canParse: throwsTypeError(() => URL.canParse()), + parse: throwsTypeError(() => URL.parse()), + explicitUndefined: new URL(undefined, "https://example.test/base/").href, + params: params.toString(), + required, + } + `), + ).toEqual({ + construct: true, + canParse: true, + parse: true, + explicitUndefined: "https://example.test/base/undefined", + params: "undefined=undefined", + required: [true, true, true, true, true, true, true], + }) + }) +}) + describe("Map", () => { test("get/set/has/size with chaining", async () => { expect( From f406fed92471fbd2d3a116c02f82e1d38e229157 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 6 Jul 2026 12:34:33 -0400 Subject: [PATCH 05/46] fix(cli): ignore version mismatch on reconnect --- packages/cli/src/commands/handlers/default.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/commands/handlers/default.ts b/packages/cli/src/commands/handlers/default.ts index d7ba88a8247..62c3ace63f3 100644 --- a/packages/cli/src/commands/handlers/default.ts +++ b/packages/cli/src/commands/handlers/default.ts @@ -54,12 +54,15 @@ export default Runtime.handler(Commands, (input) => // retry the same address; for the managed service discovery re-reads the // registration and may start a replacement. const serviceOptions = server === undefined && !input.standalone ? yield* ServiceConfig.options() : undefined - const discover = serviceOptions + // Only startup enforces the CLI version. A reconnect must accept a server + // replaced by another client or the two clients will restart it forever. + const reconnectOptions = serviceOptions ? { ...serviceOptions, version: undefined } : undefined + const discover = reconnectOptions ? () => Effect.runPromise( Effect.gen(function* () { - const found = yield* Service.discover(serviceOptions) - return found ?? (yield* Service.start(serviceOptions)) + const found = yield* Service.discover(reconnectOptions) + return found ?? (yield* Service.start(reconnectOptions)) }).pipe(Effect.provide(NodeFileSystem.layer)), ) : () => Promise.resolve(transport) From 4cee5bd8249ed63adfe06a5c885eb3a1ac5e6758 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Mon, 6 Jul 2026 12:01:14 -0500 Subject: [PATCH 06/46] refactor(codemode): split interpreter and stdlib (#35572) --- packages/codemode/codemode.md | 6 + packages/codemode/src/codemode.ts | 4332 +----------------- packages/codemode/src/interpreter/model.ts | 200 + packages/codemode/src/interpreter/runtime.ts | 3465 ++++++++++++++ packages/codemode/src/stdlib/collections.ts | 51 + packages/codemode/src/stdlib/console.ts | 4 + packages/codemode/src/stdlib/date.ts | 94 + packages/codemode/src/stdlib/json.ts | 42 + packages/codemode/src/stdlib/math.ts | 65 + packages/codemode/src/stdlib/number.ts | 66 + packages/codemode/src/stdlib/object.ts | 77 + packages/codemode/src/stdlib/promise.ts | 6 + packages/codemode/src/stdlib/regexp.ts | 74 + packages/codemode/src/stdlib/string.ts | 52 + packages/codemode/src/stdlib/url.ts | 90 + packages/codemode/src/stdlib/value.ts | 90 + 16 files changed, 4394 insertions(+), 4320 deletions(-) create mode 100644 packages/codemode/src/interpreter/model.ts create mode 100644 packages/codemode/src/interpreter/runtime.ts create mode 100644 packages/codemode/src/stdlib/collections.ts create mode 100644 packages/codemode/src/stdlib/console.ts create mode 100644 packages/codemode/src/stdlib/date.ts create mode 100644 packages/codemode/src/stdlib/json.ts create mode 100644 packages/codemode/src/stdlib/math.ts create mode 100644 packages/codemode/src/stdlib/number.ts create mode 100644 packages/codemode/src/stdlib/object.ts create mode 100644 packages/codemode/src/stdlib/promise.ts create mode 100644 packages/codemode/src/stdlib/regexp.ts create mode 100644 packages/codemode/src/stdlib/string.ts create mode 100644 packages/codemode/src/stdlib/url.ts create mode 100644 packages/codemode/src/stdlib/value.ts diff --git a/packages/codemode/codemode.md b/packages/codemode/codemode.md index 71bb3f27cf2..9a307f2200b 100644 --- a/packages/codemode/codemode.md +++ b/packages/codemode/codemode.md @@ -153,6 +153,12 @@ current omissions to implement, not intentional product boundaries. shims. Consider `Promise.any` in the same pass. - [ ] Support async iteration and `for await...of`. Define behavior first for the runtime's supported promise and collection values, then extend it to bounded host streams when a stream boundary exists. +- [ ] Support callback-bearing standard-library variants that models commonly generate: the mapper argument to + `Array.from(...)` and replacers for `JSON.stringify(...)`, including Effect-aware callbacks where needed. +- [ ] Close basic `Object` parity gaps: let `Object.values`/`Object.entries` accept arrays, make `Object.assign` validate + and mutate its target, add `Object.is`, and let `Object.fromEntries` consume every supported iterable. +- [ ] Add deterministic modern collection conveniences where they improve orchestration: `Object.groupBy`, Set + composition methods, and `Array.prototype.toSpliced`. - [ ] Complete the deterministic `Math` surface beyond the current arithmetic, rounding, root, power, and logarithm helpers. Decide separately whether nondeterministic `Math.random` belongs in the runtime. - [ ] Refine diagnostics so user throws, expected tool failures, unexpected host/tool defects, and genuine interpreter diff --git a/packages/codemode/src/codemode.ts b/packages/codemode/src/codemode.ts index d62f87a0df6..842209dac57 100644 --- a/packages/codemode/src/codemode.ts +++ b/packages/codemode/src/codemode.ts @@ -1,31 +1,12 @@ -import { parse } from "acorn" -import { Cause, Effect, Exit, Fiber, Schema, Semaphore } from "effect" -import { DiagnosticCategory, ModuleKind, ScriptTarget, flattenDiagnosticMessageText, transpileModule } from "typescript" +import { Effect, Schema } from "effect" +import { executeWithLimits } from "./interpreter/runtime.js" import { - copyIn, - copyOut, - isBlockedMember, - ToolReference, - ToolRuntime, - ToolRuntimeError, type HostTools, - type SafeObject, - type ToolCall, - type ToolDescription, type Services, + type ToolDescription, + ToolRuntime, } from "./tool-runtime.js" import type { Definition } from "./tool.js" -import { ToolError } from "./tool-error.js" -import { - isSandboxValue, - SandboxDate, - SandboxMap, - SandboxPromise, - SandboxRegExp, - SandboxSet, - SandboxURL, - SandboxURLSearchParams, -} from "./values.js" /** A tool call admitted during an execution. */ export type { ToolCall, ToolCallEnded, ToolCallHooks, ToolCallStarted, ToolDescription } from "./tool-runtime.js" @@ -36,22 +17,13 @@ export type ExecutionLimits = { readonly timeoutMs?: number /** Maximum number of tool calls admitted by the runtime. No default: absent means unlimited. */ readonly maxToolCalls?: number - /** - * Maximum UTF-8 bytes of model-facing output: the serialized result value plus captured - * logs. Excess output is truncated with an explanatory marker instead of failing. No - * default: absent means no truncation (for hosts with their own output bounding). - */ + /** Maximum UTF-8 bytes of model-facing output. No default: absent means no truncation. */ readonly maxOutputBytes?: number } /** Controls how much of the tool catalog is inlined in agent instructions. */ export type DiscoveryOptions = { - /** - * Approximate budget, in estimated tokens (chars/4, default 2000), for full tool entries in - * the instruction catalog. Tool entries are selected round-robin across namespaces. Fixed - * instructions and namespace summaries do not count toward the budget, and - * `tools.$codemode.search` is always registered. - */ + /** Approximate token budget (chars/4, default 2000) for full catalog entries. */ readonly catalogBudget?: number } @@ -59,12 +31,9 @@ type ToolTree = { readonly [name: string]: Definition | ToolTree } -type ResolvedExecutionLimits = { - /** Undefined means no timeout. */ +export type ResolvedExecutionLimits = { readonly timeoutMs: number | undefined - /** Undefined means unlimited tool calls. */ readonly maxToolCalls: number | undefined - /** Undefined means no output truncation. */ readonly maxOutputBytes: number | undefined } @@ -147,344 +116,11 @@ export type Result = typeof Result.Type /** Reusable confined runtime over one explicit tool tree. */ export type Runtime = { - /** Lists schema-described tool paths provided by the host. */ readonly catalog: () => ReadonlyArray - /** Builds model-facing syntax guidance and visible tool signatures. */ readonly instructions: () => string - /** Executes a program using this runtime's configured host tools. */ readonly execute: (code: string) => Effect.Effect } -type SourcePosition = { - line: number - column: number -} - -type SourceLocation = { - start: SourcePosition - end: SourcePosition -} - -type AstNode = { - type: string - loc?: SourceLocation - [key: string]: unknown -} - -type ProgramNode = AstNode & { - type: "Program" - body: Array -} - -type Binding = { - mutable: boolean - value: unknown - // Absent means initialized. `false` marks a parameter binding seeded into its scope but not - // yet bound, so a default that forward-references a later parameter sees a TDZ error (as in JS) - // rather than silently resolving to an outer binding of the same name. - initialized?: boolean -} - -type StatementResult = - | { kind: "none" } - | { kind: "value"; value: unknown } - | { kind: "return"; value: unknown } - | { kind: "break" } - | { kind: "continue" } - -type MemberReference = { - target: SafeObject | Array | SandboxURL - key: string | number -} - -class CodeModeFunction { - constructor( - readonly parameters: ReadonlyArray, - readonly body: AstNode, - readonly capturedScopes: ReadonlyArray>, - ) {} -} - -class IntrinsicReference { - constructor( - readonly receiver: unknown, - readonly name: string, - ) {} -} - -class ComputedValue { - constructor(readonly value: unknown) {} -} - -class PromiseNamespace {} - -type PromiseMethodName = "all" | "allSettled" | "race" | "resolve" | "reject" - -class PromiseMethodReference { - constructor(readonly name: PromiseMethodName) {} -} - -// A built-in global namespace (`Object`, `Math`, `JSON`, `Array`, ...); members resolve to a -// GlobalMethodReference, except known constants (e.g. `Math.PI`) which resolve to a value. -type GlobalNamespaceName = - | "Object" - | "Math" - | "JSON" - | "Array" - | "console" - | "Date" - | "RegExp" - | "Map" - | "Set" - | "URL" - | "URLSearchParams" - -class GlobalNamespace { - constructor(readonly name: GlobalNamespaceName) {} -} - -class GlobalMethodReference { - constructor( - readonly namespace: GlobalNamespaceName | "Number" | "String", - readonly name: string, - ) {} -} - -class CoercionFunction { - constructor(readonly name: "Number" | "String" | "Boolean" | "parseInt" | "parseFloat") {} -} - -class UriFunction { - constructor(readonly name: "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent") {} -} - -class ProgramThrow { - constructor(readonly value: unknown) {} -} - -class ErrorConstructorReference { - constructor(readonly name: string) {} -} - -// Non-enumerable so spread/copyOut preserve the plain `{ name, message }` data shape. -const ErrorBrand: unique symbol = Symbol("codemode.error") - -const brandError = (errorValue: SafeObject, name: string): SafeObject => { - Object.defineProperty(errorValue, ErrorBrand, { value: name }) - return errorValue -} - -const createErrorValue = (name: string, message: string): SafeObject => - brandError(Object.assign(Object.create(null) as SafeObject, { name, message }), name) - -const errorBrandName = (value: unknown): string | undefined => - value !== null && typeof value === "object" - ? ((value as Record)[ErrorBrand] as string | undefined) - : undefined - -const arrayMethods = new Set([ - "map", - "filter", - "find", - "findIndex", - "findLast", - "findLastIndex", - "some", - "every", - "includes", - "join", - "reduce", - "reduceRight", - "flatMap", - "forEach", - "sort", - "toSorted", - "slice", - "concat", - "indexOf", - "lastIndexOf", - "at", - "flat", - "reverse", - "toReversed", - "with", - "push", - "pop", - "shift", - "unshift", - "splice", - "fill", - "copyWithin", - "keys", - "values", - "entries", -]) - -const mathConstants = new Set(["PI", "E", "LN2", "LN10", "LOG2E", "LOG10E", "SQRT2", "SQRT1_2"]) - -const numberMethods = new Set(["toFixed", "toPrecision", "toExponential", "toString"]) - -const stringMethods = new Set([ - "toLowerCase", - "toUpperCase", - "trim", - "trimStart", - "trimEnd", - "trimLeft", - "trimRight", - "split", - "slice", - "substring", - "substr", - "includes", - "startsWith", - "endsWith", - "indexOf", - "lastIndexOf", - "replace", - "replaceAll", - "repeat", - "padStart", - "padEnd", - "charAt", - "charCodeAt", - "codePointAt", - "at", - "concat", - "toString", - "match", - "matchAll", - "search", - "localeCompare", - "normalize", -]) - -const numberConstants = new Set(["MAX_SAFE_INTEGER", "MIN_SAFE_INTEGER", "MAX_VALUE", "MIN_VALUE", "EPSILON"]) - -const numberStatics = new Set(["isInteger", "isFinite", "isNaN", "isSafeInteger", "parseInt", "parseFloat"]) - -const stringStatics = new Set(["fromCharCode", "fromCodePoint"]) - -const consoleMethods = new Set(["log", "info", "debug", "warn", "error", "dir", "table"]) - -const promiseStatics = new Set(["all", "allSettled", "race", "resolve", "reject"]) - -const errorConstructors = new Set([ - "Error", - "TypeError", - "RangeError", - "SyntaxError", - "ReferenceError", - "EvalError", - "URIError", -]) - -const valueConstructors = new Set(["Date", "RegExp", "Map", "Set", "URL", "URLSearchParams"]) - -const dateMethods = new Set([ - "getTime", - "valueOf", - "toISOString", - "toJSON", - "toString", - "getFullYear", - "getMonth", - "getDate", - "getDay", - "getHours", - "getMinutes", - "getSeconds", - "getMilliseconds", - "getUTCFullYear", - "getUTCMonth", - "getUTCDate", - "getUTCDay", - "getUTCHours", - "getUTCMinutes", - "getUTCSeconds", - "getUTCMilliseconds", - "getTimezoneOffset", -]) -const dateStatics = new Set(["now", "parse", "UTC"]) - -const regexpMethods = new Set(["test", "exec", "toString"]) -// Read-only host regex fields surfaced as plain values. -const regexpProperties = new Set([ - "source", - "flags", - "lastIndex", - "global", - "ignoreCase", - "multiline", - "sticky", - "unicode", - "dotAll", -]) - -const mapMethods = new Set(["get", "set", "has", "delete", "clear", "forEach", "keys", "values", "entries"]) -const setMethods = new Set(["add", "has", "delete", "clear", "forEach", "keys", "values", "entries"]) - -const urlProperties = new Set([ - "href", - "origin", - "protocol", - "username", - "password", - "host", - "hostname", - "port", - "pathname", - "search", - "hash", -]) -const urlWritableProperties = new Set([ - "href", - "protocol", - "username", - "password", - "host", - "hostname", - "port", - "pathname", - "search", - "hash", -]) -const urlMethods = new Set(["toString", "toJSON"]) -const urlStatics = new Set(["canParse", "parse"]) -const urlSearchParamsMethods = new Set([ - "append", - "delete", - "get", - "getAll", - "has", - "set", - "sort", - "forEach", - "keys", - "values", - "entries", - "toString", -]) - -const OptionalShortCircuit: unique symbol = Symbol("codemode.optional-short-circuit") - -const supportedSyntaxMessage = - "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set/URL/URLSearchParams, URI encoding helpers, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, and Promise.all/allSettled/race/resolve/reject over arrays mixing promises and plain values for parallel tool calls (promise chaining with .then/.catch is not supported - use await with try/catch)." - -const unsupportedSyntax = (kind: string, node: AstNode): InterpreterRuntimeError => - new InterpreterRuntimeError( - `Syntax '${kind}' is not supported in CodeMode. ${supportedSyntaxMessage}`, - node, - "UnsupportedSyntax", - [supportedSyntaxMessage], - ) - -/** How many eagerly forked tool calls may run at once. Fixed; not a configurable knob. */ -const TOOL_CALL_CONCURRENCY = 8 - -/** Console formatting recursion ceiling; deeper values render as "...". Fixed; not a knob. */ -const MAX_CONSOLE_DEPTH = 32 - const validateLimit = ( name: keyof ExecutionLimits, value: Value, @@ -496,3944 +132,13 @@ const validateLimit = ( return value } -// No limit has a default: absent means no timeout / unlimited calls / no output truncation - -// budgets are host policy, not library policy. A host without its own output bounding should -// pass maxOutputBytes explicitly, or oversized results flood model context. const resolveExecutionLimits = (limits?: ExecutionLimits): ResolvedExecutionLimits => ({ timeoutMs: validateLimit("timeoutMs", limits?.timeoutMs, 1), maxToolCalls: validateLimit("maxToolCalls", limits?.maxToolCalls, 0), maxOutputBytes: validateLimit("maxOutputBytes", limits?.maxOutputBytes, 0), }) -class InterpreterRuntimeError extends Error { - readonly node?: AstNode - /** - * The constructor name a program observes when it catches this failure (`caught.name`, and - * the brand behind `caught instanceof SyntaxError` etc.). "Error" unless the failing - * operation names a standard type in real JS - e.g. JSON.parse and invalid regex patterns - * throw SyntaxError, an unknown identifier is a ReferenceError, a bad normalize form is a - * RangeError. - */ - errorName: string = "Error" - - constructor( - message: string, - node?: AstNode, - readonly kind: DiagnosticKind = "ExecutionFailure", - readonly suggestions?: ReadonlyArray, - ) { - super(message) - this.name = "InterpreterRuntimeError" - - if (node) { - this.node = node - } - } - - as(errorName: string): this { - this.errorName = errorName - return this - } -} - -const isRecord = (value: unknown): value is Record => typeof value === "object" && value !== null - -const asNode = (value: unknown, context: string): AstNode => { - if (!isRecord(value) || typeof value.type !== "string") { - throw new InterpreterRuntimeError(`Invalid AST node while reading ${context}.`) - } - - return value as AstNode -} - -const getArray = (node: AstNode, key: string): Array => { - const value = node[key] - if (!Array.isArray(value)) { - throw new InterpreterRuntimeError(`Expected '${key}' to be an array.`, node) - } - - return value -} - -const getString = (node: AstNode, key: string): string => { - const value = node[key] - if (typeof value !== "string") { - throw new InterpreterRuntimeError(`Expected '${key}' to be a string.`, node) - } - - return value -} - -const getBoolean = (node: AstNode, key: string): boolean => { - const value = node[key] - if (typeof value !== "boolean") { - throw new InterpreterRuntimeError(`Expected '${key}' to be a boolean.`, node) - } - - return value -} - -const getOptionalNode = (node: AstNode, key: string): AstNode | undefined => { - const value = node[key] - if (value === undefined || value === null) { - return undefined - } - - return asNode(value, key) -} - -const getNode = (node: AstNode, key: string): AstNode => { - const value = node[key] - return asNode(value, key) -} - -const parseProgram = (code: string): ProgramNode => { - const transpiled = transpileModule(`async function __codemode__() {\n${code}\n}`, { - reportDiagnostics: true, - compilerOptions: { - target: ScriptTarget.ESNext, - module: ModuleKind.ESNext, - }, - }) - const diagnostic = transpiled.diagnostics?.find((item) => item.category === DiagnosticCategory.Error) - - if (diagnostic) { - throw new InterpreterRuntimeError( - `Failed to parse TypeScript: ${flattenDiagnosticMessageText(diagnostic.messageText, "\n")}`, - undefined, - "ParseError", - ) - } - - const bodyStart = transpiled.outputText.indexOf("{") + 1 - const bodyEnd = transpiled.outputText.lastIndexOf("}") - const executableCode = transpiled.outputText.slice(bodyStart, bodyEnd) - const parsed = parse(executableCode, { - ecmaVersion: "latest", - sourceType: "script", - allowReturnOutsideFunction: true, - allowAwaitOutsideFunction: true, - locations: true, - }) as unknown - - if (!isRecord(parsed) || parsed.type !== "Program" || !Array.isArray(parsed.body)) { - throw new InterpreterRuntimeError("Failed to parse script as a Program node.") - } - - return parsed as ProgramNode -} - -const formatLocation = (node?: AstNode): string => { - if (!node || !node.loc) { - return "" - } - - const location = sourceLocation(node) - return ` (line ${location.line}, col ${location.column})` -} - -const sourceLocation = (node: AstNode): { readonly line: number; readonly column: number } => ({ - line: Math.max(1, (node.loc?.start.line ?? 2) - 1), - column: Math.max(1, (node.loc?.start.column ?? 4) - 3), -}) - -const publicErrorMessage = (message: string): string => - message.replace(/\/(?:Users|home|private|tmp|var\/folders)\/[^\s"'`]+/g, "") - -const normalizeError = (error: unknown): Diagnostic => { - if (error instanceof InterpreterRuntimeError) { - return { - kind: error.kind, - message: `${error.message}${formatLocation(error.node)}`, - ...(error.node?.loc ? { location: sourceLocation(error.node) } : {}), - ...(error.suggestions ? { suggestions: error.suggestions } : {}), - } - } - - if (error instanceof ToolRuntimeError) { - return { - kind: error.kind, - message: error.message, - ...(error.suggestions.length > 0 ? { suggestions: error.suggestions } : {}), - } - } - - if (error instanceof ToolError) { - return { kind: "ToolFailure", message: publicErrorMessage(error.message) } - } - - if (error instanceof ProgramThrow) { - const value = error.value - let message: string - if (containsRuntimeReference(value)) { - // A thrown tool/function reference must not leak its internal structure. - message = "a non-data value" - } else if (typeof value === "string") { - message = value - } else if ( - value !== null && - typeof value === "object" && - typeof (value as { message?: unknown }).message === "string" - ) { - message = (value as { message: string }).message - } else { - try { - message = JSON.stringify(copyOut(value)) ?? String(value) - } catch { - message = String(value) - } - } - return { kind: "ExecutionFailure", message: `Uncaught: ${message}` } - } - - if (error instanceof RangeError && /call stack|recursion/i.test(error.message)) { - return { - kind: "ExecutionFailure", - message: "Execution exceeded the maximum nesting depth.", - } - } - - if (error instanceof Error) { - return { - kind: error.name === "SyntaxError" ? "ParseError" : "ExecutionFailure", - message: publicErrorMessage(error.message), - } - } - - // A non-Error thrown by a host tool (raw string / number / Symbol) still routes through - // path redaction so filesystem paths can never leak through the catch-all branch. - return { - kind: "ExecutionFailure", - message: publicErrorMessage(String(error)), - } -} - -// Shared by catch bindings, Promise.allSettled rejection reasons, and Promise.race losers. -const caughtErrorValue = (thrown: unknown): unknown => { - if (thrown instanceof ProgramThrow) return thrown.value - if (thrown instanceof InterpreterRuntimeError) return createErrorValue(thrown.errorName, thrown.message) - const name = thrown instanceof Error && errorConstructors.has(thrown.name) ? thrown.name : "Error" - return createErrorValue(name, normalizeError(thrown).message) -} - -const boundedData = (value: unknown, label: string): unknown => copyIn(value, label, true) - -const isRuntimeReference = (value: unknown): boolean => - value instanceof CodeModeFunction || - value instanceof ToolReference || - value instanceof IntrinsicReference || - value instanceof GlobalNamespace || - value instanceof GlobalMethodReference || - value instanceof PromiseNamespace || - value instanceof PromiseMethodReference || - value instanceof SandboxPromise || - value instanceof CoercionFunction || - value instanceof UriFunction || - value instanceof ErrorConstructorReference || - isSandboxValue(value) - -const containsRuntimeReference = (value: unknown, seen = new Set()): boolean => { - if (isRuntimeReference(value)) return true - if (value === null || typeof value !== "object") return false - if (seen.has(value)) return false - seen.add(value) - const contains = Array.isArray(value) - ? value.some((item) => containsRuntimeReference(item, seen)) - : Object.values(value).some((item) => containsRuntimeReference(item, seen)) - seen.delete(value) - return contains -} - -// Like containsRuntimeReference, but sandbox standard-library values count as data: -// operators and switch treat them as ordinary object operands (identity equality, ToPrimitive -// coercion) rather than rejecting them as opaque interpreter machinery. -const containsOpaqueReference = (value: unknown, seen = new Set()): boolean => { - if (isSandboxValue(value)) return false - if (isRuntimeReference(value)) return true - if (value === null || typeof value !== "object") return false - if (seen.has(value)) return false - seen.add(value) - const contains = Array.isArray(value) - ? value.some((item) => containsOpaqueReference(item, seen)) - : Object.values(value).some((item) => containsOpaqueReference(item, seen)) - seen.delete(value) - return contains -} - -// `typeof` never throws in JS; map every interpreter value to its JS-visible category. -// A SandboxPromise falls through to the final `typeof value` and reports "object", exactly -// like a real JS promise. -const typeofValue = (value: unknown): string => { - if ( - value instanceof CodeModeFunction || - value instanceof CoercionFunction || - value instanceof IntrinsicReference || - value instanceof GlobalMethodReference || - value instanceof PromiseMethodReference || - value instanceof PromiseNamespace || - value instanceof ErrorConstructorReference - ) - return "function" - if (value instanceof UriFunction) return "function" - if (value instanceof ToolReference) return value.path.length > 0 ? "function" : "object" - if (value instanceof GlobalNamespace) { - return value.name === "Math" || value.name === "JSON" || value.name === "console" ? "object" : "function" - } - return typeof value -} - -// `x instanceof C` against the constructors CodeMode knows. Like `typeof`, it observes any -// left-hand value (opaque references included) without coercing it. Error checks use the -// error brand: `instanceof Error` accepts every branded error; a specific error type matches -// its own brand only (as in JS, where TypeError instances are also Error instances). -const instanceofValue = (lhs: unknown, rhs: unknown, node: AstNode): boolean => { - if (rhs instanceof ErrorConstructorReference) { - const brand = errorBrandName(lhs) - return brand !== undefined && (rhs.name === "Error" || brand === rhs.name) - } - if (rhs instanceof GlobalNamespace) { - switch (rhs.name) { - case "Date": - return lhs instanceof SandboxDate - case "RegExp": - return lhs instanceof SandboxRegExp - case "Map": - return lhs instanceof SandboxMap - case "Set": - return lhs instanceof SandboxSet - case "URL": - return lhs instanceof SandboxURL - case "URLSearchParams": - return lhs instanceof SandboxURLSearchParams - case "Array": - return Array.isArray(lhs) - case "Object": - return lhs !== null && (typeof lhs === "object" || typeofValue(lhs) === "function") - } - } - if (rhs instanceof PromiseNamespace) return lhs instanceof SandboxPromise - // Number/String/Boolean wrap primitives in JS; no boxed values exist in CodeMode, so - // `x instanceof Number` is always false - exactly what it is for primitives in JS. - if (rhs instanceof CoercionFunction && (rhs.name === "Number" || rhs.name === "String" || rhs.name === "Boolean")) { - return false - } - throw new InterpreterRuntimeError( - "The right-hand side of 'instanceof' must be a constructor CodeMode knows: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise.", - node, - ) -} - -// A regex engine failure message without the engine's own "Invalid regular expression:" -// prefix, so composed diagnostics read as one sentence instead of stuttering the phrase. -const regexFailureReason = (error: unknown): string => - (error instanceof Error ? error.message : String(error)).replace(/^Invalid regular expression:\s*/i, "") - -const escapeRegexHint = - 'To match special characters like ( ) [ ] { } + * ? . literally, escape them with a backslash (e.g. "\\\\(") or test for them with String.includes instead.' - -// A string method's pattern argument as a host regex: a sandbox regex passes its own host -// instance through (so `g` lastIndex semantics follow the spec across calls); a string becomes -// a pattern, exactly as String.prototype.match/matchAll/search do (`extraFlags` adds matchAll's -// implicit `g`). Invalid patterns fail as catchable program errors that say what was wrong -// with the pattern and how to fix it. -const toHostRegex = (arg: unknown, method: string, node: AstNode, extraFlags = ""): RegExp => { - if (arg instanceof SandboxRegExp) return arg.regex - if (typeof arg === "string") { - try { - return new RegExp(arg, extraFlags) - } catch (error) { - throw new InterpreterRuntimeError( - `String.${method} received the string ${JSON.stringify(arg)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}`, - node, - ).as("SyntaxError") - } - } - throw new InterpreterRuntimeError( - `String.${method} expects a regular expression (a /pattern/flags literal or new RegExp(...)) or a string pattern, not ${arg === null ? "null" : typeof arg}.`, - node, - ) -} - -// A host match result as a sandbox value: a plain array of the full match and captures, with -// `index` and named `groups` attached as own array properties (readable, and dropped at data -// boundaries exactly like JSON.stringify drops them in JS). `input` is omitted - it duplicates -// the whole subject string per match. -const matchToValue = (match: RegExpMatchArray): Array => { - const result: Array = Array.from(match, (group) => group) - if (match.index !== undefined) (result as Record & Array).index = match.index - if (match.groups) { - const groups: SafeObject = Object.create(null) as SafeObject - for (const [key, group] of Object.entries(match.groups)) { - if (!isBlockedMember(key)) groups[key] = group - } - ;(result as Record & Array).groups = groups - } - return result -} - -const invokeStringMethod = (value: string, name: string, args: Array, node: AstNode): unknown => { - const str = (index: number): string => { - const arg = args[index] - if (typeof arg !== "string") - throw new InterpreterRuntimeError(`String.${name} expects argument ${index + 1} to be a string.`, node) - return arg - } - const num = (index: number): number => { - const arg = args[index] - if (typeof arg !== "number") - throw new InterpreterRuntimeError(`String.${name} expects argument ${index + 1} to be a number.`, node) - return arg - } - const optNum = (index: number): number | undefined => (args[index] === undefined ? undefined : num(index)) - const optStr = (index: number): string | undefined => (args[index] === undefined ? undefined : str(index)) - - let result: unknown - switch (name) { - case "toLowerCase": - result = value.toLowerCase() - break - case "toUpperCase": - result = value.toUpperCase() - break - case "trim": - result = value.trim() - break - // trimLeft/trimRight are the legacy aliases of trimStart/trimEnd, kept because models write them. - case "trimStart": - case "trimLeft": - result = value.trimStart() - break - case "trimEnd": - case "trimRight": - result = value.trimEnd() - break - // Locale/options arguments are ignored: comparison runs with the host default locale, and - // the common use is a sort comparator where any consistent order works. - case "localeCompare": - result = value.localeCompare(str(0)) - break - case "normalize": { - const form = optStr(0) - try { - result = value.normalize(form) - } catch { - throw new InterpreterRuntimeError( - `String.normalize expects the form "NFC", "NFD", "NFKC", or "NFKD" (got ${JSON.stringify(form)}).`, - node, - ).as("RangeError") - } - break - } - case "split": { - if (args.length === 0) { - result = [value] - break - } - if (args[0] instanceof SandboxRegExp) { - result = value.split((args[0] as SandboxRegExp).regex, optNum(1)) - break - } - const requestedLimit = optNum(1) - result = value.split(str(0), requestedLimit === undefined ? undefined : requestedLimit >>> 0) - break - } - case "slice": - result = value.slice(optNum(0), optNum(1)) - break - case "includes": - result = value.includes(str(0), optNum(1)) - break - case "startsWith": - result = value.startsWith(str(0), optNum(1)) - break - case "endsWith": - result = value.endsWith(str(0), optNum(1)) - break - case "indexOf": - result = value.indexOf(str(0), optNum(1)) - break - case "lastIndexOf": - result = value.lastIndexOf(str(0), optNum(1)) - break - case "replace": - case "replaceAll": { - if (args[0] instanceof SandboxRegExp) { - const pattern = (args[0] as SandboxRegExp).regex - const replacement = str(1) - if (name === "replaceAll" && !pattern.global) { - throw new InterpreterRuntimeError( - `String.replaceAll requires a regular expression with the global (g) flag: write /${pattern.source}/${pattern.flags}g, or use String.replace to replace only the first match.`, - node, - ) - } - result = name === "replace" ? value.replace(pattern, replacement) : value.replaceAll(pattern, replacement) - break - } - if (name === "replace") { - result = value.replace(str(0), str(1)) - break - } - result = value.replaceAll(str(0), str(1)) - break - } - case "match": { - const pattern = toHostRegex(args[0], name, node) - const matched = value.match(pattern) - if (matched === null) return null - // A global match is a plain array of matched strings; a non-global match carries - // index/groups own properties, so bypass the copying data checkpoint to keep them. - if (pattern.global) return boundedData(matched, "String.match result") - return matchToValue(matched) - } - case "matchAll": { - const pattern = toHostRegex(args[0], name, node, "g") - if (!pattern.global) { - throw new InterpreterRuntimeError( - `String.matchAll requires a regular expression with the global (g) flag: write /${pattern.source}/${pattern.flags}g, or use String.match for a single match.`, - node, - ) - } - // Materialized as an array (not an iterator); each entry is a match array with - // index/groups own properties. Match count is bounded by the subject length. - return Array.from(value.matchAll(pattern), matchToValue) - } - case "search": { - result = value.search(toHostRegex(args[0], name, node)) - break - } - case "repeat": { - const count = num(0) - if (!Number.isFinite(count) || count < 0) - throw new InterpreterRuntimeError("String.repeat expects a finite non-negative count.", node) - result = value.repeat(count) - break - } - case "padStart": - result = value.padStart(num(0), optStr(1)) - break - case "padEnd": - result = value.padEnd(num(0), optStr(1)) - break - case "charAt": - result = value.charAt(optNum(0) ?? 0) - break - case "at": - result = value.at(optNum(0) ?? 0) - break - case "substring": - result = value.substring(optNum(0) ?? 0, optNum(1)) - break - case "substr": - result = value.substr(optNum(0) ?? 0, optNum(1)) - break - // JS charCodeAt returns NaN out of range; NaN flows as an ordinary in-sandbox value - // (normalized to null only at the data boundary - see copyOut), so return it as-is. - case "charCodeAt": - result = value.charCodeAt(optNum(0) ?? 0) - break - case "codePointAt": - result = value.codePointAt(optNum(0) ?? 0) - break - case "toString": - result = value - break - case "concat": { - result = value.concat(...args.map((_, index) => str(index))) - break - } - default: - throw new InterpreterRuntimeError(`String method '${name}' is not available in CodeMode.`, node) - } - return boundedData(result, `String.${name} result`) -} - -const invokeNumberMethod = (value: number, name: string, args: Array, node: AstNode): unknown => { - const optNum = (index: number): number | undefined => { - const arg = args[index] - if (arg === undefined) return undefined - if (typeof arg !== "number") throw new InterpreterRuntimeError(`Number.${name} expects a number argument.`, node) - return arg - } - let result: unknown - switch (name) { - case "toFixed": - result = value.toFixed(optNum(0)) - break - case "toExponential": - result = value.toExponential(optNum(0)) - break - case "toPrecision": { - const digits = optNum(0) - result = digits === undefined ? value.toString() : value.toPrecision(digits) - break - } - case "toString": { - const radix = optNum(0) - if (radix !== undefined && (radix < 2 || radix > 36)) { - throw new InterpreterRuntimeError("Number.toString radix must be between 2 and 36.", node) - } - result = value.toString(radix) - break - } - default: - throw new InterpreterRuntimeError(`Number method '${name}' is not available in CodeMode.`, node) - } - return boundedData(result, `Number.${name} result`) -} - -// JavaScript's String(...) without tripping over CodeMode's null-prototype data objects. -const coerceToString = (value: unknown): string => { - if (value === null) return "null" - if (value === undefined) return "undefined" - // Sandbox values stringify deterministically: Date as ISO (not the host's locale/timezone - // toString), RegExp as its literal form, Map/Set with their JS Object.prototype tags. - if (value instanceof SandboxDate) - return Number.isFinite(value.time) ? new Date(value.time).toISOString() : "Invalid Date" - if (value instanceof SandboxRegExp) return `/${value.regex.source}/${value.regex.flags}` - if (value instanceof SandboxMap) return "[object Map]" - if (value instanceof SandboxSet) return "[object Set]" - if (value instanceof SandboxURL) return value.url.href - if (value instanceof SandboxURLSearchParams) return value.params.toString() - if (typeof value === "object") { - return Array.isArray(value) - ? value.map((item) => (item === null || item === undefined ? "" : coerceToString(item))).join(",") - : "[object Object]" - } - return String(value) -} - -/** Compound assignment operators (`x op= y`), each applying the binary operator `op`. */ -const compoundOperators = new Set(["+=", "-=", "*=", "/=", "%=", "**=", "&=", "|=", "^=", "<<=", ">>=", ">>>="]) - -const coerceToNumber = (value: unknown): number => { - if (value instanceof SandboxDate) return value.time - if (isSandboxValue(value)) return Number.NaN - return value !== null && typeof value === "object" && !Array.isArray(value) ? Number.NaN : Number(value) -} - -const invokeCoercion = (ref: CoercionFunction, args: Array, node: AstNode): unknown => { - // Sandbox values coerce before the data checkpoint (which would JSON-serialize them): - // Number(date) is its time value, String(date) its ISO form, Boolean(x) is true. - const raw = args[0] - if (isSandboxValue(raw)) { - if (ref.name === "Boolean") return true - if (ref.name === "Number") return coerceToNumber(raw) - if (ref.name === "String") return coerceToString(raw) - if (ref.name === "parseInt") return parseInt(coerceToString(raw)) - return parseFloat(coerceToString(raw)) - } - const value = boundedData(args[0], `${ref.name} input`) - if (ref.name === "Number") return coerceToNumber(value) - if (ref.name === "Boolean") return Boolean(value) - if (ref.name === "parseInt") { - const radix = args[1] - if (radix !== undefined && typeof radix !== "number") - throw new InterpreterRuntimeError("parseInt expects a numeric radix.", node) - return parseInt(coerceToString(value), radix) - } - if (ref.name === "parseFloat") return parseFloat(coerceToString(value)) - return coerceToString(value) -} - -const invokeObjectMethod = (name: string, args: Array, node: AstNode): unknown => { - const requireObject = (): Record => { - const value = boundedData(args[0], `Object.${name} input`) - // Sandbox standard-library values have no own enumerable properties in JS, so the - // Object.* helpers see them as empty objects - never their interpreter internals. - if (isSandboxValue(value)) return {} - if (value === null || typeof value !== "object" || Array.isArray(value)) { - throw new InterpreterRuntimeError(`Object.${name} expects a data object.`, node) - } - return value as Record - } - const guardedSet = (out: Record, key: string, item: unknown): void => { - if (isBlockedMember(key)) throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, node) - out[key] = item - } - switch (name) { - case "keys": { - // Object.keys(array) yields index strings (["0", "1", ...]) exactly as in JS; objects - // yield their own enumerable keys. (Tool references never reach here - the interpreter - // resolves them against the host tool tree first.) - const value = boundedData(args[0], "Object.keys input") - if (isSandboxValue(value)) return [] - if (Array.isArray(value)) return Object.keys(value) - if (value === null || typeof value !== "object") { - throw new InterpreterRuntimeError("Object.keys expects a data object or array.", node) - } - return Object.keys(value) - } - case "values": - return Object.values(requireObject()) - case "entries": - return Object.entries(requireObject()).map(([key, item]) => [key, item]) - case "hasOwn": - return Object.hasOwn(requireObject(), String(args[1])) - case "assign": { - const out: Record = Object.create(null) - for (const source of args) { - if (source === null || source === undefined) continue - const value = boundedData(source, "Object.assign input") - // A sandbox value source contributes nothing (no own enumerable properties in JS). - if (isSandboxValue(value)) continue - if (value === null || typeof value !== "object" || Array.isArray(value)) - throw new InterpreterRuntimeError("Object.assign expects data objects.", node) - for (const [key, item] of Object.entries(value)) guardedSet(out, key, item) - } - return out - } - case "fromEntries": { - // A Map is the idiomatic fromEntries source; use its entries directly (the data - // checkpoint would serialize a Map to {}). - if (args[0] instanceof SandboxMap) { - const out: Record = Object.create(null) - for (const [key, item] of (args[0] as SandboxMap).map.entries()) guardedSet(out, coerceToString(key), item) - return out - } - if (args[0] instanceof SandboxURLSearchParams) { - const out: Record = Object.create(null) - for (const [key, value] of args[0].params.entries()) guardedSet(out, key, value) - return out - } - const pairs = boundedData(args[0], "Object.fromEntries input") - if (!Array.isArray(pairs)) - throw new InterpreterRuntimeError("Object.fromEntries expects an array of [key, value] pairs.", node) - const out: Record = Object.create(null) - for (const pair of pairs) { - if (!Array.isArray(pair)) - throw new InterpreterRuntimeError("Object.fromEntries expects [key, value] pairs.", node) - guardedSet(out, String(pair[0]), pair[1]) - } - return out - } - default: - throw new InterpreterRuntimeError(`Object.${name} is not available in CodeMode.`, node) - } -} - -const invokeMathMethod = (name: string, args: Array, node: AstNode): number => { - const nums = args.map((arg) => { - if (typeof arg !== "number") throw new InterpreterRuntimeError(`Math.${name} expects number arguments.`, node) - return arg - }) - const [a = Number.NaN, b = Number.NaN] = nums - switch (name) { - case "max": - return Math.max(...nums) - case "min": - return Math.min(...nums) - case "abs": - return Math.abs(a) - case "floor": - return Math.floor(a) - case "ceil": - return Math.ceil(a) - case "round": - return Math.round(a) - case "trunc": - return Math.trunc(a) - case "sign": - return Math.sign(a) - case "sqrt": - return Math.sqrt(a) - case "cbrt": - return Math.cbrt(a) - case "pow": - return Math.pow(a, b) - case "hypot": - return Math.hypot(...nums) - case "log": - return Math.log(a) - case "log2": - return Math.log2(a) - case "log10": - return Math.log10(a) - case "exp": - return Math.exp(a) - default: - throw new InterpreterRuntimeError(`Math.${name} is not available in CodeMode.`, node) - } -} - -const invokeJsonMethod = (name: string, args: Array, node: AstNode): unknown => { - switch (name) { - case "stringify": { - const replacer = args[1] - if (Array.isArray(replacer) || replacer instanceof CodeModeFunction) { - throw new InterpreterRuntimeError( - "JSON.stringify replacers are not supported in CodeMode.", - node, - "UnsupportedSyntax", - [supportedSyntaxMessage], - ) - } - const space = args[2] - const indent = typeof space === "number" || typeof space === "string" ? space : undefined - // copyIn first so only Data Values serialize, never a CodeModeFunction/ToolReference. - return JSON.stringify(copyOut(copyIn(args[0], "JSON.stringify value")), null, indent) - } - case "parse": { - const text = args[0] - if (typeof text !== "string") throw new InterpreterRuntimeError("JSON.parse expects a string.", node) - let parsed: unknown - try { - parsed = JSON.parse(text) - } catch (error) { - // The engine reason is derived from the program-supplied string (token/position), so - // it is safe to surface - and the position is exactly what a model needs to fix it. - throw new InterpreterRuntimeError( - `JSON.parse received invalid JSON: ${error instanceof Error ? error.message : String(error)}`, - node, - ).as("SyntaxError") - } - return copyIn(parsed, "JSON.parse result") - } - default: - throw new InterpreterRuntimeError(`JSON.${name} is not available in CodeMode.`, node) - } -} - -const invokeArrayStatic = (name: string, args: Array, node: AstNode): unknown => { - switch (name) { - case "isArray": - return Array.isArray(args[0]) - case "of": - return [...args] - case "from": { - if (args.length > 1) { - throw new InterpreterRuntimeError( - "Array.from(...) does not support a map function in CodeMode; call .map() on the result instead.", - node, - "UnsupportedSyntax", - [supportedSyntaxMessage], - ) - } - // Map/Set materialize directly (the data checkpoint would serialize them to {}). - if (args[0] instanceof SandboxMap) - return Array.from((args[0] as SandboxMap).map.entries(), ([key, item]) => [key, item]) - if (args[0] instanceof SandboxSet) return Array.from((args[0] as SandboxSet).set.values()) - if (args[0] instanceof SandboxURLSearchParams) { - return Array.from(args[0].params.entries(), ([key, value]) => [key, value]) - } - const source = boundedData(args[0], "Array.from input") - if (typeof source === "string") return Array.from(source) - if (Array.isArray(source)) return [...source] - if ( - source !== null && - typeof source === "object" && - typeof (source as { length?: unknown }).length === "number" - ) { - return Array.from(source as ArrayLike) - } - throw new InterpreterRuntimeError("Array.from expects an array, string, Map, Set, or array-like value.", node) - } - default: - throw new InterpreterRuntimeError(`Array.${name} is not available in CodeMode.`, node) - } -} - -const invokeNumberStatic = (name: string, args: Array, node: AstNode): unknown => { - const value = args[0] - switch (name) { - case "isInteger": - return Number.isInteger(value) - case "isFinite": - return Number.isFinite(value) - case "isNaN": - return Number.isNaN(value) - case "isSafeInteger": - return Number.isSafeInteger(value) - case "parseInt": { - const radix = args[1] - if (radix !== undefined && typeof radix !== "number") - throw new InterpreterRuntimeError("Number.parseInt expects a numeric radix.", node) - return parseInt(coerceToString(value), radix) - } - case "parseFloat": - return parseFloat(coerceToString(value)) - default: - throw new InterpreterRuntimeError(`Number.${name} is not available in CodeMode.`, node) - } -} - -const invokeStringStatic = (name: string, args: Array, node: AstNode): unknown => { - const codes = args.map((arg) => { - if (typeof arg !== "number") throw new InterpreterRuntimeError(`String.${name} expects number arguments.`, node) - return arg - }) - switch (name) { - case "fromCharCode": - return String.fromCharCode(...codes) - case "fromCodePoint": - return String.fromCodePoint(...codes) - default: - throw new InterpreterRuntimeError(`String.${name} is not available in CodeMode.`, node) - } -} - -const invokeDateStatic = (name: string, args: Array, node: AstNode): number => { - switch (name) { - case "now": - return Date.now() - case "parse": - return Date.parse(coerceToString(args[0])) - case "UTC": { - const parts = args.map((arg) => coerceToNumber(arg)) - return Date.UTC(...(parts as Parameters)) - } - default: - throw new InterpreterRuntimeError(`Date.${name} is not available in CodeMode.`, node) - } -} - -const invokeDateMethod = (value: SandboxDate, name: string, node: AstNode): unknown => { - const hosted = new Date(value.time) - switch (name) { - case "getTime": - case "valueOf": - return value.time - case "toISOString": { - if (!Number.isFinite(value.time)) throw new InterpreterRuntimeError("Invalid time value.", node) - return hosted.toISOString() - } - // toJSON of an invalid date is null in JS (never a throw); toString stays ISO for - // determinism across host timezones/locales. - case "toJSON": - return Number.isFinite(value.time) ? hosted.toISOString() : null - case "toString": - return coerceToString(value) - case "getFullYear": - return hosted.getFullYear() - case "getMonth": - return hosted.getMonth() - case "getDate": - return hosted.getDate() - case "getDay": - return hosted.getDay() - case "getHours": - return hosted.getHours() - case "getMinutes": - return hosted.getMinutes() - case "getSeconds": - return hosted.getSeconds() - case "getMilliseconds": - return hosted.getMilliseconds() - case "getUTCFullYear": - return hosted.getUTCFullYear() - case "getUTCMonth": - return hosted.getUTCMonth() - case "getUTCDate": - return hosted.getUTCDate() - case "getUTCDay": - return hosted.getUTCDay() - case "getUTCHours": - return hosted.getUTCHours() - case "getUTCMinutes": - return hosted.getUTCMinutes() - case "getUTCSeconds": - return hosted.getUTCSeconds() - case "getUTCMilliseconds": - return hosted.getUTCMilliseconds() - case "getTimezoneOffset": - return hosted.getTimezoneOffset() - default: - throw new InterpreterRuntimeError(`Date method '${name}' is not available in CodeMode.`, node) - } -} - -const invokeRegExpMethod = (value: SandboxRegExp, name: string, args: Array, node: AstNode): unknown => { - switch (name) { - // test/exec run on the sandbox regex's own host instance, so `g`-flag lastIndex advances - // across calls per the spec. - case "test": - return value.regex.test(coerceToString(args[0])) - case "exec": { - const matched = value.regex.exec(coerceToString(args[0])) - if (matched === null) return null - return matchToValue(matched) - } - case "toString": - return coerceToString(value) - default: - throw new InterpreterRuntimeError(`RegExp method '${name}' is not available in CodeMode.`, node) - } -} - -const uriArgument = (value: unknown, label: string): string => coerceToString(boundedData(value, label)) - -const invokeUriFunction = (ref: UriFunction, args: Array, node: AstNode): string => { - const value = uriArgument(args[0], `${ref.name} input`) - try { - switch (ref.name) { - case "encodeURI": - return encodeURI(value) - case "encodeURIComponent": - return encodeURIComponent(value) - case "decodeURI": - return decodeURI(value) - case "decodeURIComponent": - return decodeURIComponent(value) - } - } catch (error) { - throw new InterpreterRuntimeError( - `${ref.name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}`, - node, - ).as("URIError") - } -} - -const urlArgument = (value: unknown, label: string): string => - value instanceof SandboxURL ? value.url.href : uriArgument(value, label) - -const invokeURLStatic = (name: string, args: Array, node: AstNode): unknown => { - if (!urlStatics.has(name)) throw new InterpreterRuntimeError(`URL.${name} is not available in CodeMode.`, node) - if (args.length === 0) { - throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node).as("TypeError") - } - const input = urlArgument(args[0], `URL.${name} input`) - const base = args[1] === undefined ? undefined : urlArgument(args[1], `URL.${name} base`) - try { - const url = new URL(input, base) - return name === "canParse" ? true : new SandboxURL(url) - } catch { - return name === "canParse" ? false : null - } -} - -const invokeURLMethod = (value: SandboxURL, name: string, node: AstNode): string => { - if (name === "toString" || name === "toJSON") return value.url.href - throw new InterpreterRuntimeError(`URL method '${name}' is not available in CodeMode.`, node) -} - -const invokeGlobalMethod = (ref: GlobalMethodReference, args: Array, node: AstNode): unknown => { - if (ref.namespace === "console") - throw new InterpreterRuntimeError(`console.${ref.name} is not available in CodeMode.`, node) - if (ref.namespace === "Object") return invokeObjectMethod(ref.name, args, node) - if (ref.namespace === "Math") return invokeMathMethod(ref.name, args, node) - if (ref.namespace === "Array") return invokeArrayStatic(ref.name, args, node) - if (ref.namespace === "Number") return invokeNumberStatic(ref.name, args, node) - if (ref.namespace === "String") return invokeStringStatic(ref.name, args, node) - if (ref.namespace === "URL") return invokeURLStatic(ref.name, args, node) - if (ref.namespace === "Date") { - if (!dateStatics.has(ref.name)) - throw new InterpreterRuntimeError(`Date.${ref.name} is not available in CodeMode.`, node) - return invokeDateStatic(ref.name, args, node) - } - if ( - ref.namespace === "RegExp" || - ref.namespace === "Map" || - ref.namespace === "Set" || - ref.namespace === "URLSearchParams" - ) { - throw new InterpreterRuntimeError(`${ref.namespace}.${ref.name} is not available in CodeMode.`, node) - } - return invokeJsonMethod(ref.name, args, node) -} - -// Iterable spread sources: arrays, strings (code points), Maps (entry pairs), and Sets (values). -const spreadItems = (spread: unknown): Array | undefined => { - if (Array.isArray(spread)) return spread - if (typeof spread === "string") return Array.from(spread) - if (spread instanceof SandboxMap) - return Array.from(spread.map.entries(), ([key, item]): Array => [key, item]) - if (spread instanceof SandboxSet) return Array.from(spread.set.values()) - if (spread instanceof SandboxURLSearchParams) - return Array.from(spread.params.entries(), ([key, value]): Array => [key, value]) - return undefined -} - -// Every identifier a parameter pattern binds, used to seed TDZ slots before defaults run. -const collectPatternNames = (pattern: AstNode, out: Array = []): Array => { - switch (pattern.type) { - case "Identifier": - out.push(getString(pattern, "name")) - break - case "AssignmentPattern": - collectPatternNames(getNode(pattern, "left"), out) - break - case "RestElement": - collectPatternNames(getNode(pattern, "argument"), out) - break - case "ArrayPattern": - for (const element of getArray(pattern, "elements")) { - if (element !== null) collectPatternNames(asNode(element, "elements"), out) - } - break - case "ObjectPattern": - for (const property of getArray(pattern, "properties")) { - const prop = asNode(property, "properties") - collectPatternNames(prop.type === "RestElement" ? getNode(prop, "argument") : getNode(prop, "value"), out) - } - break - } - return out -} - -class Interpreter { - private scopes: Array> - private readonly invokeTool: (path: ReadonlyArray, args: Array) => Effect.Effect - // Enumerable namespace/tool names at a node of the host tool tree, threaded from - // ToolRuntime.make like invokeTool: the interpreter never holds the tree itself. - private readonly toolKeys: (path: ReadonlyArray) => ReadonlyArray - private readonly logs: Array - private lastValue: unknown - // Caps how many eagerly forked tool calls run at once (the parallel-call concurrency cap). - private readonly callPermits: Semaphore.Semaphore - // Fiber-backed promises whose settlement no program construct has observed yet. Successful - // program completion drains these (like a runtime waiting on in-flight work at exit) and - // surfaces a never-awaited failure as an unhandled-rejection diagnostic. - private readonly pendingSettlements = new Set() - - constructor( - invokeTool: (path: ReadonlyArray, args: Array) => Effect.Effect, - toolKeys: (path: ReadonlyArray) => ReadonlyArray, - logs: Array = [], - ) { - const globalScope = new Map() - this.scopes = [globalScope] - this.invokeTool = invokeTool - this.toolKeys = toolKeys - this.logs = logs - this.lastValue = undefined - this.callPermits = Semaphore.makeUnsafe(TOOL_CALL_CONCURRENCY) - globalScope.set("tools", { mutable: false, value: new ToolReference([]) }) - globalScope.set("Promise", { mutable: false, value: new PromiseNamespace() }) - globalScope.set("undefined", { mutable: false, value: undefined }) - globalScope.set("Object", { mutable: false, value: new GlobalNamespace("Object") }) - globalScope.set("Math", { mutable: false, value: new GlobalNamespace("Math") }) - globalScope.set("JSON", { mutable: false, value: new GlobalNamespace("JSON") }) - globalScope.set("Number", { mutable: false, value: new CoercionFunction("Number") }) - globalScope.set("String", { mutable: false, value: new CoercionFunction("String") }) - globalScope.set("Boolean", { mutable: false, value: new CoercionFunction("Boolean") }) - globalScope.set("Array", { mutable: false, value: new GlobalNamespace("Array") }) - globalScope.set("console", { mutable: false, value: new GlobalNamespace("console") }) - globalScope.set("parseInt", { mutable: false, value: new CoercionFunction("parseInt") }) - globalScope.set("parseFloat", { mutable: false, value: new CoercionFunction("parseFloat") }) - globalScope.set("Date", { mutable: false, value: new GlobalNamespace("Date") }) - globalScope.set("RegExp", { mutable: false, value: new GlobalNamespace("RegExp") }) - globalScope.set("Map", { mutable: false, value: new GlobalNamespace("Map") }) - globalScope.set("Set", { mutable: false, value: new GlobalNamespace("Set") }) - globalScope.set("URL", { mutable: false, value: new GlobalNamespace("URL") }) - globalScope.set("URLSearchParams", { mutable: false, value: new GlobalNamespace("URLSearchParams") }) - globalScope.set("encodeURI", { mutable: false, value: new UriFunction("encodeURI") }) - globalScope.set("encodeURIComponent", { mutable: false, value: new UriFunction("encodeURIComponent") }) - globalScope.set("decodeURI", { mutable: false, value: new UriFunction("decodeURI") }) - globalScope.set("decodeURIComponent", { mutable: false, value: new UriFunction("decodeURIComponent") }) - // Error constructors are real values, so `x instanceof Error` works and `Error("msg")` - // (with or without `new`) constructs a branded { name, message } error object. - for (const name of errorConstructors) { - globalScope.set(name, { mutable: false, value: new ErrorConstructorReference(name) }) - } - // NaN/Infinity flow as ordinary in-sandbox values (normalized to null only at the data - // boundary - see copyOut), so their global bindings must exist too, e.g. `reduce(max, -Infinity)`. - globalScope.set("NaN", { mutable: false, value: NaN }) - globalScope.set("Infinity", { mutable: false, value: Infinity }) - } - - run(program: ProgramNode): Effect.Effect { - const self = this - // Run the program body in its own module scope on top of the builtin global scope, so - // top-level declarations (`let undefined = 5`, `const Object = ...`) shadow builtins like - // JS module scope, instead of colliding with the seeded globals. - this.pushScope() - return Effect.gen(function* () { - self.hoistFunctions(program.body) - let value: unknown = undefined - let returned = false - for (const statement of program.body) { - const result = yield* self.evaluateStatement(statement) - - if (result.kind === "return") { - value = result.value - returned = true - break - } - - if (result.kind === "break" || result.kind === "continue") { - throw new InterpreterRuntimeError(`Unexpected '${result.kind}' outside of a loop.`, statement) - } - - if (result.kind === "value") { - self.lastValue = result.value - } - } - if (!returned) value = self.lastValue - - // The program body runs inside an implicit async function, so a returned promise - // resolves before crossing the data boundary - `return tools.ns.tool(...)` works - // without an explicit await, exactly as in JS. - if (value instanceof SandboxPromise) value = yield* self.settlePromise(value) - yield* self.drainPendingSettlements() - return value - }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) - } - - // Awaits every fiber-backed promise the program abandoned (fire-and-forget tool calls), so - // their work completes before the execution ends - mirroring a JS runtime waiting on - // in-flight I/O at exit. A failure nobody could have handled becomes an unhandled-rejection - // diagnostic (interrupted calls, e.g. Promise.race losers, are ignored). - private drainPendingSettlements(): Effect.Effect { - const self = this - return Effect.gen(function* () { - for (const promise of [...self.pendingSettlements]) { - const exit = yield* self.observePromise(promise) - if (Exit.isSuccess(exit) || Cause.hasInterruptsOnly(exit.cause)) continue - const failure = normalizeError(Cause.squash(exit.cause)) - throw new InterpreterRuntimeError( - `Unhandled rejection from an un-awaited tool call: ${failure.message}`, - undefined, - failure.kind, - ["Await tool calls - `const result = await tools.ns.tool(...)` - so failures can be caught and handled."], - ) - } - }) - } - - // Eagerly starts a tool call on a supervised child fiber (so the execution timeout and - // scope teardown interrupt it) gated by the concurrency semaphore, and wraps the fiber in a - // first-class promise value. `startImmediately` makes the runtime admit the call - charging - // the tool-call budget and firing onToolCallStart - at the call site, before any await. - private createToolCallPromise( - path: ReadonlyArray, - args: Array, - ): Effect.Effect { - const self = this - return Effect.map( - Effect.forkChild(this.callPermits.withPermit(Effect.suspend(() => self.invokeTool(path, args))), { - startImmediately: true, - }), - (fiber) => { - const promise = new SandboxPromise(fiber) - self.pendingSettlements.add(promise) - return promise - }, - ) - } - - // The promise's settlement as an Exit, marking it observed for unhandled-rejection tracking. - // Fiber settlement is idempotent, so observing the same promise repeatedly (await twice, - // Promise.all([p, p])) never re-runs the underlying call. - private observePromise(promise: SandboxPromise): Effect.Effect> { - this.pendingSettlements.delete(promise) - return promise.fiber !== undefined ? Fiber.await(promise.fiber) : Effect.exit(promise.immediate ?? Effect.void) - } - - // `await promise`: succeed with the fulfilled value or re-raise the failure so try/catch - // observes it exactly like a synchronous throw at the await site. - private settlePromise(promise: SandboxPromise, node?: AstNode): Effect.Effect { - const self = this - return Effect.flatMap(this.observePromise(promise), (exit) => self.unwrapPromiseExit(promise, exit, node)) - } - - private unwrapPromiseExit( - promise: SandboxPromise | undefined, - exit: Exit.Exit, - node?: AstNode, - ): Effect.Effect { - if (Exit.isSuccess(exit)) return Effect.succeed(exit.value) - // A call Promise.race interrupted after losing settles as a catchable program failure; - // any other interruption is execution teardown (timeout/host) and must keep propagating - // as interruption rather than becoming program-visible data. - if (promise?.interrupted === true && Cause.hasInterruptsOnly(exit.cause)) { - return Effect.fail( - new InterpreterRuntimeError( - "This tool call was interrupted because another value settled a Promise.race first.", - node, - ), - ) - } - return Effect.failCause(exit.cause) - } - - private evaluateStatement(node: AstNode): Effect.Effect { - switch (node.type) { - case "ExpressionStatement": - return Effect.map(this.evaluateExpression(getNode(node, "expression")), (value) => ({ kind: "value", value })) - case "VariableDeclaration": - return Effect.map(this.evaluateVariableDeclaration(node), () => ({ kind: "none" })) - case "ReturnStatement": { - const argumentNode = getOptionalNode(node, "argument") - return argumentNode - ? Effect.map(this.evaluateExpression(argumentNode), (value) => ({ kind: "return", value })) - : Effect.succeed({ kind: "return", value: undefined }) - } - case "BlockStatement": - return this.evaluateBlock(node) - case "IfStatement": - return this.evaluateIfStatement(node) - case "SwitchStatement": - return this.evaluateSwitchStatement(node) - case "WhileStatement": - return this.evaluateWhileStatement(node) - case "DoWhileStatement": - return this.evaluateDoWhileStatement(node) - case "ForStatement": - return this.evaluateForStatement(node) - case "ForOfStatement": - return this.evaluateForOfStatement(node) - case "ForInStatement": - return this.evaluateForInStatement(node) - case "BreakStatement": - return Effect.succeed(this.evaluateBreakStatement(node)) - case "ContinueStatement": - return Effect.succeed(this.evaluateContinueStatement(node)) - case "ThrowStatement": - return this.evaluateThrowStatement(node) - case "TryStatement": - return this.evaluateTryStatement(node) - case "EmptyStatement": - return Effect.succeed({ kind: "none" }) - case "FunctionDeclaration": - return Effect.succeed({ kind: "none" }) // bound ahead of time by hoistFunctions - default: - throw unsupportedSyntax(node.type, node) - } - } - - private evaluateBlock(node: AstNode): Effect.Effect { - this.pushScope() - const self = this - return Effect.gen(function* () { - const body = getArray(node, "body") - self.hoistFunctions(body) - - for (const statementValue of body) { - const statement = asNode(statementValue, "body") - const result = yield* self.evaluateStatement(statement) - - if (result.kind === "value") { - self.lastValue = result.value - continue - } - - if (result.kind !== "none") { - return result - } - } - - return { kind: "none" } satisfies StatementResult - }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) - } - - private createFunction(node: AstNode): CodeModeFunction { - if (node.generator === true) { - throw new InterpreterRuntimeError( - "Generator functions are not supported in CodeMode.", - node, - "UnsupportedSyntax", - [supportedSyntaxMessage], - ) - } - return new CodeModeFunction( - getArray(node, "params").map((parameter, index) => asNode(parameter, `params[${index}]`)), - getNode(node, "body"), - this.scopes.slice(), - ) - } - - // Function declarations are hoisted: bound in their scope before the body runs, so a - // program can call a helper defined further down (matching JavaScript). - private hoistFunctions(statements: Array): void { - for (const statementValue of statements) { - if (!isRecord(statementValue) || statementValue.type !== "FunctionDeclaration") continue - const node = statementValue as AstNode - this.declare(getString(getNode(node, "id"), "name"), this.createFunction(node), true, node) - } - } - - private evaluateIfStatement(node: AstNode): Effect.Effect { - const testNode = getNode(node, "test") - const consequentNode = getNode(node, "consequent") - const alternateNode = getOptionalNode(node, "alternate") - - return Effect.flatMap(this.evaluateExpression(testNode), (test) => - test - ? this.evaluateStatement(consequentNode) - : alternateNode - ? this.evaluateStatement(alternateNode) - : Effect.succeed({ kind: "none" }), - ) - } - - private evaluateSwitchStatement(node: AstNode): Effect.Effect { - const self = this - this.pushScope() - return Effect.gen(function* () { - const discriminant = yield* self.evaluateExpression(getNode(node, "discriminant")) - if (containsOpaqueReference(discriminant)) { - throw new InterpreterRuntimeError( - "Switch discriminants must be data values in CodeMode.", - node, - "InvalidDataValue", - ) - } - const cases = getArray(node, "cases").map((value, index) => asNode(value, `cases[${index}]`)) - let defaultIndex: number | undefined - let selected: number | undefined - for (const [index, branch] of cases.entries()) { - const test = getOptionalNode(branch, "test") - if (!test) { - defaultIndex = index - continue - } - const candidate = yield* self.evaluateExpression(test) - if (containsOpaqueReference(candidate)) { - throw new InterpreterRuntimeError( - "Switch case values must be data values in CodeMode.", - test, - "InvalidDataValue", - ) - } - if (candidate === discriminant) { - selected = index - break - } - } - const start = selected ?? defaultIndex - if (start === undefined) return { kind: "none" } satisfies StatementResult - for (let index = start; index < cases.length; index += 1) { - for (const statementValue of getArray(cases[index]!, "consequent")) { - const result = yield* self.evaluateStatement(asNode(statementValue, "consequent")) - if (result.kind === "break") return { kind: "none" } satisfies StatementResult - if (result.kind === "return" || result.kind === "continue") return result - if (result.kind === "value") self.lastValue = result.value - } - } - return { kind: "none" } satisfies StatementResult - }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) - } - - private evaluateWhileStatement(node: AstNode): Effect.Effect { - const testNode = getNode(node, "test") - const bodyNode = getNode(node, "body") - - const self = this - return Effect.gen(function* () { - while (yield* self.evaluateExpression(testNode)) { - const result = yield* self.evaluateStatement(bodyNode) - - if (result.kind === "continue") { - continue - } - - if (result.kind === "break") { - return { kind: "none" } satisfies StatementResult - } - - if (result.kind === "return") { - return result - } - - if (result.kind === "value") { - self.lastValue = result.value - } - } - - return { kind: "none" } satisfies StatementResult - }) - } - - private evaluateDoWhileStatement(node: AstNode): Effect.Effect { - const bodyNode = getNode(node, "body") - const testNode = getNode(node, "test") - - const self = this - return Effect.gen(function* () { - do { - const result = yield* self.evaluateStatement(bodyNode) - - if (result.kind === "continue") { - continue - } - - if (result.kind === "break") { - return { kind: "none" } satisfies StatementResult - } - - if (result.kind === "return") { - return result - } - - if (result.kind === "value") { - self.lastValue = result.value - } - } while (yield* self.evaluateExpression(testNode)) - - return { kind: "none" } satisfies StatementResult - }) - } - - private evaluateForStatement(node: AstNode): Effect.Effect { - this.pushScope() - const self = this - return Effect.gen(function* () { - const initNode = getOptionalNode(node, "init") - const testNode = getOptionalNode(node, "test") - const updateNode = getOptionalNode(node, "update") - const bodyNode = getNode(node, "body") - - if (initNode) { - if (initNode.type === "VariableDeclaration") { - yield* self.evaluateVariableDeclaration(initNode) - } else { - yield* self.evaluateExpression(initNode) - } - } - - const perIterationBindings = - initNode?.type === "VariableDeclaration" && getString(initNode, "kind") !== "var" - ? Array.from(self.currentScope().keys()) - : [] - - while (testNode ? yield* self.evaluateExpression(testNode) : true) { - let iterationScope: Map | undefined - if (perIterationBindings.length > 0) { - iterationScope = new Map( - perIterationBindings.map((name) => { - const binding = self.currentScope().get(name)! - return [name, { ...binding }] - }), - ) - self.scopes.push(iterationScope) - } - const result = yield* self.evaluateStatement(bodyNode).pipe( - Effect.ensuring( - Effect.sync(() => { - if (iterationScope) self.popScope() - }), - ), - ) - - if (result.kind === "return") { - return result - } - - if (result.kind === "break") { - return { kind: "none" } satisfies StatementResult - } - - if (result.kind === "value") { - self.lastValue = result.value - } - - if (iterationScope) { - const loopScope = self.currentScope() - for (const name of perIterationBindings) { - loopScope.set(name, { ...iterationScope.get(name)! }) - } - } - - if (updateNode) { - yield* self.evaluateExpression(updateNode) - } - - if (result.kind === "continue") { - continue - } - } - - return { kind: "none" } satisfies StatementResult - }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) - } - - private evaluateForOfStatement(node: AstNode): Effect.Effect { - if (getBoolean(node, "await")) { - throw new InterpreterRuntimeError("for await...of is not supported.", node) - } - - const self = this - return Effect.gen(function* () { - const left = getNode(node, "left") - const right = yield* self.evaluateExpression(getNode(node, "right")) - const body = getNode(node, "body") - - // Arrays iterate in place; strings iterate code points; Maps iterate [key, value] - // pairs and Sets iterate values over a snapshot (mutation during iteration is safe). - const iterable = Array.isArray(right) ? right : spreadItems(right) - if (iterable === undefined) { - throw new InterpreterRuntimeError("for...of requires an array, string, Map, or Set value in CodeMode.", node) - } - - let declaration: { readonly pattern: AstNode; readonly mutable: boolean } | undefined - let assignmentName: string | undefined - - if (left.type === "VariableDeclaration") { - const declarations = getArray(left, "declarations") - if (declarations.length !== 1) { - throw new InterpreterRuntimeError("for...of supports one declared binding.", left) - } - - const declarator = asNode(declarations[0], "declarations[0]") - declaration = { pattern: getNode(declarator, "id"), mutable: getString(left, "kind") !== "const" } - } else if (left.type === "Identifier") { - assignmentName = getString(left, "name") - } else { - throw new InterpreterRuntimeError("Unsupported for...of binding.", left) - } - - for (const value of iterable) { - if (declaration) { - self.pushScope() - yield* self.declarePattern(declaration.pattern, value, declaration.mutable, left) - } else if (assignmentName) { - self.setIdentifierValue(assignmentName, value, left) - } - - const result = yield* self.evaluateStatement(body).pipe( - Effect.ensuring( - Effect.sync(() => { - if (declaration) self.popScope() - }), - ), - ) - - if (result.kind === "return") { - return result - } - - if (result.kind === "break") { - return { kind: "none" } - } - - if (result.kind === "value") { - self.lastValue = result.value - } - - if (result.kind === "continue") { - continue - } - } - - return { kind: "none" } - }) - } - - // Own enumerable string keys of a value, shared by `for...in` and `Object.keys` over tool - // references: plain data objects enumerate their own keys, arrays their index strings (plus - // any own non-index properties, e.g. match results' index/groups - exactly Object.keys in - // JS), and a tool reference the namespace/tool names at its path in the host tool tree. - // Returns undefined for everything else so callers can raise a contextual error. - private enumerableKeys(value: unknown): Array | undefined { - if (value instanceof ToolReference) { - return [...this.toolKeys(value.path)] - } - if (Array.isArray(value)) { - return Object.keys(value) - } - if (value !== null && typeof value === "object" && !isRuntimeReference(value)) { - return Object.keys(value) - } - return undefined - } - - private evaluateForInStatement(node: AstNode): Effect.Effect { - const self = this - return Effect.gen(function* () { - const left = getNode(node, "left") - const right = yield* self.evaluateExpression(getNode(node, "right")) - const body = getNode(node, "body") - - // Keys are snapshotted up front (mutation during iteration is safe): plain objects - // enumerate their own keys, arrays their index strings, and tool references the - // namespace/tool names at that node - the same enumeration Object.keys performs. - // Anything else (strings, Maps, Sets, numbers, null, ...) is a deliberate error rather - // than real JS's surprising behavior (indices for strings, zero iterations for - // Maps/Sets/null): the hint points at the constructs that do what the program means. - const keys = self.enumerableKeys(right) - if (keys === undefined) { - throw new InterpreterRuntimeError( - "for...in requires a plain object, array, or tools reference in CodeMode. Use for...of for arrays/strings/Maps/Sets, or Object.keys(value) for a key list.", - node, - ) - } - - let declaration: { readonly pattern: AstNode; readonly mutable: boolean } | undefined - let assignmentName: string | undefined - - if (left.type === "VariableDeclaration") { - const declarations = getArray(left, "declarations") - if (declarations.length !== 1) { - throw new InterpreterRuntimeError("for...in supports one declared binding.", left) - } - - const declarator = asNode(declarations[0], "declarations[0]") - declaration = { pattern: getNode(declarator, "id"), mutable: getString(left, "kind") !== "const" } - } else if (left.type === "Identifier") { - assignmentName = getString(left, "name") - } else { - throw new InterpreterRuntimeError("Unsupported for...in binding.", left) - } - - for (const key of keys) { - if (declaration) { - self.pushScope() - yield* self.declarePattern(declaration.pattern, key, declaration.mutable, left) - } else if (assignmentName) { - self.setIdentifierValue(assignmentName, key, left) - } - - const result = yield* self.evaluateStatement(body).pipe( - Effect.ensuring( - Effect.sync(() => { - if (declaration) self.popScope() - }), - ), - ) - - if (result.kind === "return") { - return result - } - - if (result.kind === "break") { - return { kind: "none" } - } - - if (result.kind === "value") { - self.lastValue = result.value - } - - if (result.kind === "continue") { - continue - } - } - - return { kind: "none" } - }) - } - - private evaluateBreakStatement(node: AstNode): StatementResult { - const labelNode = getOptionalNode(node, "label") - - if (labelNode) { - throw new InterpreterRuntimeError("Labeled break is not supported in v1.", node) - } - - return { kind: "break" } - } - - private evaluateContinueStatement(node: AstNode): StatementResult { - const labelNode = getOptionalNode(node, "label") - - if (labelNode) { - throw new InterpreterRuntimeError("Labeled continue is not supported in v1.", node) - } - - return { kind: "continue" } - } - - private evaluateThrowStatement(node: AstNode): Effect.Effect { - const argument = getNode(node, "argument") - return Effect.flatMap(this.evaluateExpression(argument), (value) => Effect.fail(new ProgramThrow(value))) - } - - private evaluateTryStatement(node: AstNode): Effect.Effect { - const body = getNode(node, "block") - const handler = getOptionalNode(node, "handler") - const finalizer = getOptionalNode(node, "finalizer") - const self = this - - const attempted = Effect.matchCauseEffect(this.evaluateStatement(body), { - onFailure: (cause) => { - if (cause.reasons.some(Cause.isInterruptReason) || !handler) { - return Effect.failCause(cause) - } - - // The program sees a plain { message } error (or the thrown value itself) - see - // caughtErrorValue, shared with Promise.allSettled rejection reasons. - const caught = caughtErrorValue(Cause.squash(cause)) - const parameter = getOptionalNode(handler, "param") - self.pushScope() - return Effect.gen(function* () { - if (parameter) yield* self.declarePattern(parameter, caught, true, handler) - return yield* self.evaluateStatement(getNode(handler, "body")) - }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) - }, - onSuccess: Effect.succeed, - }) - - if (!finalizer) return attempted - - const isAbrupt = (result: StatementResult): boolean => - result.kind === "return" || result.kind === "break" || result.kind === "continue" - - return Effect.matchCauseEffect(attempted, { - onFailure: (cause) => - cause.reasons.some(Cause.isInterruptReason) - ? Effect.failCause(cause) - : Effect.flatMap(this.evaluateStatement(finalizer), (final) => - isAbrupt(final) ? Effect.succeed(final) : Effect.failCause(cause), - ), - onSuccess: (result) => - Effect.flatMap(this.evaluateStatement(finalizer), (final) => - isAbrupt(final) ? Effect.succeed(final) : Effect.succeed(result), - ), - }) - } - - private evaluateVariableDeclaration(node: AstNode): Effect.Effect { - const kind = getString(node, "kind") - const declarations = getArray(node, "declarations") - const self = this - return Effect.gen(function* () { - for (const declarationValue of declarations) { - const declaration = asNode(declarationValue, "declarations") - - if (declaration.type !== "VariableDeclarator") { - throw new InterpreterRuntimeError("Unsupported variable declaration shape.", declaration) - } - - const init = getOptionalNode(declaration, "init") - const value = init ? yield* self.evaluateExpression(init) : undefined - yield* self.declarePattern(getNode(declaration, "id"), value, kind !== "const", declaration) - } - }) - } - - private declarePattern( - pattern: AstNode, - value: unknown, - mutable: boolean, - node: AstNode, - ): Effect.Effect { - const self = this - return Effect.gen(function* () { - if (pattern.type === "Identifier") { - self.declare(getString(pattern, "name"), value, mutable, node) - return - } - - // Default values: `x = expr` / `{ a = 1 }` - the default is evaluated only when the value is undefined. - if (pattern.type === "AssignmentPattern") { - const resolved = value === undefined ? yield* self.evaluateExpression(getNode(pattern, "right")) : value - yield* self.declarePattern(getNode(pattern, "left"), resolved, mutable, node) - return - } - - if (pattern.type === "ObjectPattern") { - if (value === null || typeof value !== "object" || Array.isArray(value) || isRuntimeReference(value)) { - throw new InterpreterRuntimeError( - "Object destructuring requires a data object value.", - pattern, - "InvalidDataValue", - ) - } - - const consumed = new Set() - for (const propertyValue of getArray(pattern, "properties")) { - const property = asNode(propertyValue, "properties") - - // Object rest: `{ a, ...others }` - gather the not-yet-consumed own keys. - if (property.type === "RestElement") { - const rest: SafeObject = Object.create(null) as SafeObject - for (const [key, item] of Object.entries(value as SafeObject)) { - if (!consumed.has(key) && !isBlockedMember(key)) rest[key] = item - } - yield* self.declarePattern(getNode(property, "argument"), rest, mutable, property) - continue - } - - if ( - property.type !== "Property" || - getBoolean(property, "computed") || - getString(property, "kind") !== "init" - ) { - throw new InterpreterRuntimeError("Only named object destructuring properties are supported.", property) - } - - const keyNode = getNode(property, "key") - const key = keyNode.type === "Identifier" ? getString(keyNode, "name") : String(keyNode.value) - if (isBlockedMember(key)) { - throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, keyNode) - } - consumed.add(key) - yield* self.declarePattern(getNode(property, "value"), (value as SafeObject)[key], mutable, property) - } - return - } - - if (pattern.type === "ArrayPattern") { - if (!Array.isArray(value)) { - throw new InterpreterRuntimeError("Array destructuring requires an array value.", pattern) - } - - for (const [index, item] of getArray(pattern, "elements").entries()) { - if (item === null) continue - const element = asNode(item, `elements[${index}]`) - // Array rest: `[head, ...tail]` - binds the remaining elements (must be last). - if (element.type === "RestElement") { - yield* self.declarePattern(getNode(element, "argument"), value.slice(index), mutable, element) - break - } - yield* self.declarePattern(element, value[index], mutable, pattern) - } - return - } - - throw new InterpreterRuntimeError(`Unsupported binding pattern '${pattern.type}'.`, pattern) - }) - } - - private evaluateExpression(node: AstNode): Effect.Effect { - switch (node.type) { - case "Literal": { - // A regex literal parses as a Literal node carrying { pattern, flags }; construct the - // sandbox regex from those (the host `value` instance is never exposed). - const regex = node.regex - if (isRecord(regex) && typeof regex.pattern === "string") { - return Effect.sync(() => - this.constructRegExp([regex.pattern, typeof regex.flags === "string" ? regex.flags : ""], node), - ) - } - return Effect.sync(() => boundedData(node.value, "Literal")) - } - case "Identifier": - return Effect.sync(() => this.getIdentifierValue(getString(node, "name"), node)) - case "BinaryExpression": - return this.evaluateBinaryExpression(node) - case "LogicalExpression": - return this.evaluateLogicalExpression(node) - case "UnaryExpression": - return this.evaluateUnaryExpression(node) - case "AssignmentExpression": - return this.evaluateAssignmentExpression(node) - case "CallExpression": - return this.evaluateCallExpression(node) - case "ArrowFunctionExpression": - case "FunctionExpression": - return Effect.sync(() => this.createFunction(node)) - case "MemberExpression": - return this.readMember(node) - case "ChainExpression": - return Effect.map(this.evaluateExpression(getNode(node, "expression")), (value) => - value === OptionalShortCircuit ? undefined : value, - ) - case "ObjectExpression": - return this.evaluateObjectExpression(node) - case "ArrayExpression": - return this.evaluateArrayExpression(node) - case "TemplateLiteral": - return this.evaluateTemplateLiteral(node) - case "ConditionalExpression": - return this.evaluateConditionalExpression(node) - case "UpdateExpression": - return this.evaluateUpdateExpression(node) - case "AwaitExpression": { - // `await` resolves a promise value; awaiting anything else is a passthrough no-op, - // matching real JS semantics for non-thenables. - const self = this - return Effect.flatMap(this.evaluateExpression(getNode(node, "argument")), (value) => - value instanceof SandboxPromise ? self.settlePromise(value, node) : Effect.succeed(value), - ) - } - case "NewExpression": - return this.evaluateNewExpression(node) - default: - throw unsupportedSyntax(node.type, node) - } - } - - private evaluateNewExpression(node: AstNode): Effect.Effect { - const callee = getNode(node, "callee") - if (callee.type !== "Identifier") { - throw unsupportedSyntax("NewExpression", node) - } - const name = getString(callee, "name") - const argNodes = getArray(node, "arguments") - const self = this - if (name === "Promise") { - throw new InterpreterRuntimeError( - "new Promise(...) is not supported in CodeMode; tool calls already return promises - call the tool and await the result.", - node, - "UnsupportedSyntax", - [supportedSyntaxMessage], - ) - } - if (errorConstructors.has(name)) { - return Effect.gen(function* () { - const arg = - argNodes.length > 0 ? yield* self.evaluateExpression(asNode(argNodes[0], "arguments[0]")) : undefined - return createErrorValue(name, arg === undefined ? "" : coerceToString(arg)) - }) - } - if (valueConstructors.has(name)) { - return Effect.gen(function* () { - const args = yield* self.evaluateCallArguments(argNodes) - switch (name) { - case "Date": - return self.constructDate(args) - case "RegExp": - return self.constructRegExp(args, node) - case "Map": - return self.constructMap(args[0], node) - case "Set": - return self.constructSet(args[0], node) - case "URL": - return self.constructURL(args, node) - default: - return self.constructURLSearchParams(args[0], node) - } - }) - } - throw unsupportedSyntax("NewExpression", node) - } - - private constructDate(args: Array): SandboxDate { - if (args.length === 0) return new SandboxDate(Date.now()) - if (args.length === 1) { - const arg = args[0] - if (arg instanceof SandboxDate) return new SandboxDate(arg.time) - if (typeof arg === "number") return new SandboxDate(new Date(arg).getTime()) - if (typeof arg === "string") return new SandboxDate(Date.parse(arg)) - return new SandboxDate(Number.NaN) - } - // new Date(year, month, day?, hours?, ...) - local-time component form. - const parts = args.map((arg) => coerceToNumber(arg)) - return new SandboxDate(new Date(...(parts as [number, number])).getTime()) - } - - private constructRegExp(args: Array, node: AstNode): SandboxRegExp { - const first = args[0] - const pattern = - first instanceof SandboxRegExp ? first.regex.source : first === undefined ? "" : coerceToString(first) - const flagsArg = args[1] - if (flagsArg !== undefined && typeof flagsArg !== "string") { - throw new InterpreterRuntimeError( - `RegExp flags must be a string of flag characters (e.g. "g", "gi"), not ${flagsArg === null ? "null" : typeof flagsArg}.`, - node, - ) - } - const flags = flagsArg ?? (first instanceof SandboxRegExp ? first.regex.flags : "") - try { - return new SandboxRegExp(pattern, flags) - } catch (error) { - // Say which part was rejected and how to fix it, instead of passing the engine - // message through bare. A flags failure names the flags; a pattern failure gets the - // escaping hint (the usual cause is an unescaped metacharacter in a built-up string). - const reason = regexFailureReason(error) - throw new InterpreterRuntimeError( - /flag/i.test(reason) - ? `new RegExp(...) received invalid flags ${JSON.stringify(flags)} (${reason}). Valid flags are d, g, i, m, s, u, v, and y.` - : `new RegExp(...) received ${JSON.stringify(pattern)}, which is not a valid regular expression pattern (${reason}). ${escapeRegexHint}`, - node, - ).as("SyntaxError") - } - } - - private constructMap(init: unknown, node: AstNode): SandboxMap { - const target = new SandboxMap() - if (init === undefined || init === null) return target - const entries = Array.isArray(init) - ? init - : init instanceof SandboxMap - ? Array.from(init.map.entries(), ([key, item]): Array => [key, item]) - : undefined - if (entries === undefined) { - throw new InterpreterRuntimeError( - "new Map(...) expects an array of [key, value] pairs, a Map, or no argument.", - node, - ) - } - for (const pair of entries) { - if (!Array.isArray(pair)) { - throw new InterpreterRuntimeError("new Map(...) expects [key, value] pairs.", node) - } - target.map.set(pair[0], pair[1]) - } - return target - } - - private constructSet(init: unknown, node: AstNode): SandboxSet { - const target = new SandboxSet() - if (init === undefined || init === null) return target - const items = Array.isArray(init) - ? init - : init instanceof SandboxSet - ? Array.from(init.set.values()) - : typeof init === "string" - ? Array.from(init) - : undefined - if (items === undefined) { - throw new InterpreterRuntimeError("new Set(...) expects an array, Set, string, or no argument.", node) - } - for (const item of items) target.set.add(item) - return target - } - - private constructURL(args: Array, node: AstNode): SandboxURL { - if (args.length === 0) { - throw new InterpreterRuntimeError("new URL(...) requires a URL string and an optional base URL.", node).as( - "TypeError", - ) - } - const input = urlArgument(args[0], "new URL input") - const base = args[1] === undefined ? undefined : urlArgument(args[1], "new URL base") - try { - return new SandboxURL(new URL(input, base)) - } catch { - throw new InterpreterRuntimeError( - `new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`, - node, - ).as("TypeError") - } - } - - private constructURLSearchParams(init: unknown, node: AstNode): SandboxURLSearchParams { - if (init === undefined) return new SandboxURLSearchParams(new URLSearchParams()) - if (init instanceof SandboxURLSearchParams) { - return new SandboxURLSearchParams(new URLSearchParams(init.params)) - } - if (typeof init === "string") return new SandboxURLSearchParams(new URLSearchParams(init)) - if (init === null || typeof init === "number" || typeof init === "boolean") { - return new SandboxURLSearchParams(new URLSearchParams(coerceToString(init))) - } - if (init instanceof SandboxMap) { - return this.constructURLSearchParams( - Array.from(init.map.entries(), ([key, value]) => [key, value]), - node, - ) - } - if (Array.isArray(init)) { - const entries = init.map((pair) => { - if (!Array.isArray(pair) || pair.length !== 2) { - throw new InterpreterRuntimeError( - "new URLSearchParams(...) expects an array of [name, value] pairs.", - node, - ).as("TypeError") - } - return [uriArgument(pair[0], "URLSearchParams name"), uriArgument(pair[1], "URLSearchParams value")] as [ - string, - string, - ] - }) - return new SandboxURLSearchParams(new URLSearchParams(entries)) - } - if (isSandboxValue(init)) return new SandboxURLSearchParams(new URLSearchParams()) - const data = boundedData(init, "new URLSearchParams input") - if (data === null || typeof data !== "object") { - throw new InterpreterRuntimeError( - "new URLSearchParams(...) expects a query string, data object, array of pairs, or URLSearchParams.", - node, - ).as("TypeError") - } - return new SandboxURLSearchParams( - new URLSearchParams(Object.fromEntries(Object.entries(data).map(([key, value]) => [key, coerceToString(value)]))), - ) - } - - private evaluateBinaryExpression(node: AstNode): Effect.Effect { - const operator = getString(node, "operator") - const self = this - return Effect.gen(function* () { - const lhs = yield* self.evaluateExpression(getNode(node, "left")) - const rhs = yield* self.evaluateExpression(getNode(node, "right")) - // Like `typeof`, `instanceof` observes any value without coercing it (a promise or - // function operand is a legitimate question, not an error), so it is handled before - // the data-only operand check. - if (operator === "instanceof") return instanceofValue(lhs, rhs, node) - return boundedData(self.applyBinaryOperator(operator, lhs, rhs, node), "Binary expression result") - }) - } - - /** - * Applies a binary operator to two already-evaluated operands with CodeMode's coercion - * semantics. Shared by binary expressions and compound assignment (`x op= y` must behave - * exactly like `x = x op y`, coercion included). - */ - private applyBinaryOperator(operator: string, lhs: unknown, rhs: unknown, node: AstNode): unknown { - if (containsOpaqueReference(lhs) || containsOpaqueReference(rhs)) { - throw new InterpreterRuntimeError("Binary operators require data values in CodeMode.", node, "InvalidDataValue") - } - // Data objects/arrays are null-prototype, so JS's ToPrimitive throws an opaque host - // "No default value" TypeError when an operator coerces them. Coerce to their JS string - // form first (as String(x) / template literals do) so operators behave like JavaScript. - // A Date follows its ToPrimitive hints: string for `+` (concatenation), its time value - // for arithmetic and ordering - so `end - start` and `a < b` work as in JS. - // Identity (=== / !==) and the right operand of `in` keep their raw object value. - const coerceOperand = (operand: unknown): unknown => { - if (operand instanceof SandboxDate) return operator === "+" ? coerceToString(operand) : operand.time - return operand !== null && typeof operand === "object" ? coerceToString(operand) : operand - } - const bothObjects = lhs !== null && typeof lhs === "object" && rhs !== null && typeof rhs === "object" - const l = coerceOperand(lhs) - const r = coerceOperand(rhs) - switch (operator) { - case "+": - return (l as string) + (r as string) - case "-": - return (l as number) - (r as number) - case "*": - return (l as number) * (r as number) - case "/": - return (l as number) / (r as number) - case "%": - return (l as number) % (r as number) - case "**": - return (l as number) ** (r as number) - // Two objects compare by identity in JS (no ToPrimitive); only object-vs-primitive coerces. - case "==": - return bothObjects ? lhs === rhs : l == r - case "===": - return lhs === rhs - case "!=": - return bothObjects ? lhs !== rhs : l != r - case "!==": - return lhs !== rhs - case "<": - return (l as string) < (r as string) - case "<=": - return (l as string) <= (r as string) - case ">": - return (l as string) > (r as string) - case ">=": - return (l as string) >= (r as string) - case "&": - return (l as number) & (r as number) - case "|": - return (l as number) | (r as number) - case "^": - return (l as number) ^ (r as number) - case "<<": - return (l as number) << (r as number) - case ">>": - return (l as number) >> (r as number) - case ">>>": - return (l as number) >>> (r as number) - case "in": - if (rhs === null || typeof rhs !== "object") { - throw new InterpreterRuntimeError("The 'in' operator requires a data object on the right-hand side.", node) - } - // Own properties only, so arrays don't leak the host Array.prototype (map/constructor/...). - return Object.hasOwn(rhs as object, coerceOperand(lhs) as PropertyKey) - default: - throw new InterpreterRuntimeError(`Unsupported binary operator '${operator}'.`, node) - } - } - - private evaluateLogicalExpression(node: AstNode): Effect.Effect { - const operator = getString(node, "operator") - return Effect.flatMap(this.evaluateExpression(getNode(node, "left")), (left) => { - if (operator === "&&") return left ? this.evaluateExpression(getNode(node, "right")) : Effect.succeed(left) - if (operator === "||") return left ? Effect.succeed(left) : this.evaluateExpression(getNode(node, "right")) - if (operator === "??") - return left !== null && left !== undefined - ? Effect.succeed(left) - : this.evaluateExpression(getNode(node, "right")) - throw new InterpreterRuntimeError(`Unsupported logical operator '${operator}'.`, node) - }) - } - - private evaluateUnaryExpression(node: AstNode): Effect.Effect { - const operator = getString(node, "operator") - const argument = getNode(node, "argument") - // `typeof undeclaredIdentifier` is `"undefined"` in JS (never a ReferenceError), so - // feature-detection guards like `typeof x !== "undefined"` don't crash. Short-circuit before - // evaluating the argument; a declared-but-TDZ binding still falls through to the normal throw. - if (operator === "typeof" && argument.type === "Identifier" && !this.resolveBinding(getString(argument, "name"))) { - return Effect.succeed("undefined") - } - return Effect.map(this.evaluateExpression(argument), (value) => { - // `typeof` and `!` never throw in JS - they observe any value (functions and runtime - // references included) without coercing it, so feature detection and negation work. - if (operator === "typeof") return typeofValue(value) - if (operator === "!") return !value - if (containsOpaqueReference(value)) { - throw new InterpreterRuntimeError("Unary operators require data values in CodeMode.", node, "InvalidDataValue") - } - // Numeric/bitwise unary operators ToPrimitive their operand; a Date yields its time value - // (`+date` is the epoch-ms idiom), other null-prototype data objects/arrays coerce to - // their JS string form first (see evaluateBinaryExpression). - const operand = - value instanceof SandboxDate - ? value.time - : value !== null && typeof value === "object" - ? coerceToString(value) - : value - let result: unknown - switch (operator) { - case "+": - result = +(operand as number) - break - case "-": - result = -(operand as number) - break - case "~": - result = ~(operand as number) - break - default: - throw new InterpreterRuntimeError(`Unsupported unary operator '${operator}'.`, node) - } - return boundedData(result, "Unary expression result") - }) - } - - private evaluateAssignmentExpression(node: AstNode): Effect.Effect { - const left = getNode(node, "left") - const operator = getString(node, "operator") - const self = this - return Effect.gen(function* () { - if (operator === "??=" || operator === "||=" || operator === "&&=") { - return yield* self.evaluateLogicalAssignment(node, left, operator) - } - const rightValue = yield* self.evaluateExpression(getNode(node, "right")) - if (left.type === "Identifier") { - const name = getString(left, "name") - if (operator === "=") return self.setIdentifierValue(name, rightValue, left) - const next = boundedData( - self.applyCompoundAssignment(operator, self.getIdentifierValue(name, left), rightValue, node), - "Assignment result", - ) - return self.setIdentifierValue(name, next, left) - } - if (left.type === "MemberExpression") { - if (operator === "=") return yield* self.writeMember(left, rightValue) - return yield* self.modifyMember(left, (current) => { - const next = boundedData( - self.applyCompoundAssignment(operator, current, rightValue, node), - "Assignment result", - ) - return Effect.succeed({ write: true, next, result: next }) - }) - } - throw new InterpreterRuntimeError("Assignment target must be an Identifier or MemberExpression.", left) - }) - } - - private evaluateLogicalAssignment( - node: AstNode, - left: AstNode, - operator: string, - ): Effect.Effect { - const self = this - const shouldAssign = (current: unknown): boolean => - operator === "??=" ? current === null || current === undefined : operator === "||=" ? !current : Boolean(current) - if (left.type === "Identifier") { - const name = getString(left, "name") - return Effect.gen(function* () { - const current = self.getIdentifierValue(name, left) - if (!shouldAssign(current)) return current - const rightValue = yield* self.evaluateExpression(getNode(node, "right")) - return self.setIdentifierValue(name, rightValue, left) - }) - } - if (left.type === "MemberExpression") { - // Resolve the member exactly once; evaluate the RHS only if we actually assign. - return self.modifyMember(left, (current) => - shouldAssign(current) - ? Effect.map(self.evaluateExpression(getNode(node, "right")), (rightValue) => ({ - write: true, - next: rightValue, - result: rightValue, - })) - : Effect.succeed({ write: false, next: current, result: current }), - ) - } - throw new InterpreterRuntimeError("Assignment target must be an Identifier or MemberExpression.", left) - } - - private evaluateUpdateExpression(node: AstNode): Effect.Effect { - const operator = getString(node, "operator") - const argument = getNode(node, "argument") - const prefix = getBoolean(node, "prefix") - - const increment = operator === "++" ? 1 : operator === "--" ? -1 : undefined - - if (increment === undefined) { - throw new InterpreterRuntimeError(`Unsupported update operator '${operator}'.`, node) - } - - if (argument.type === "Identifier") { - return Effect.sync(() => { - const name = getString(argument, "name") - const current = Number(this.getIdentifierValue(name, argument)) - const next = current + increment - this.setIdentifierValue(name, next, argument) - return prefix ? next : current - }) - } - - if (argument.type === "MemberExpression") { - return this.modifyMember(argument, (current) => { - const value = Number(current) - const next = value + increment - return Effect.succeed({ write: true, next, result: prefix ? next : value }) - }) - } - - throw new InterpreterRuntimeError("Update target must be an Identifier or MemberExpression.", argument) - } - - private evaluateCallExpression(node: AstNode): Effect.Effect { - const callee = getNode(node, "callee") - const argNodes = getArray(node, "arguments") - - const self = this - return Effect.gen(function* () { - const callable = yield* self.evaluateExpression(callee) - if (callable === OptionalShortCircuit) return OptionalShortCircuit - if ((callable === null || callable === undefined) && node.optional === true) return OptionalShortCircuit - - const args = yield* self.evaluateCallArguments(argNodes) - - if (callable instanceof ToolReference) { - if (callable.path.length === 0) throw new InterpreterRuntimeError("The tools root is not callable.", callee) - // An un-awaited tool call is a first-class promise value; the call itself starts now. - return yield* self.createToolCallPromise(callable.path, args) - } - if (callable instanceof PromiseMethodReference) { - return yield* self.invokePromiseMethod(callable, args, node) - } - if (callable instanceof CodeModeFunction) { - return yield* self.invokeFunction(callable, args) - } - if (callable instanceof IntrinsicReference) { - return yield* self.invokeIntrinsic(callable, args, node) - } - if (callable instanceof GlobalMethodReference) { - if (callable.namespace === "console") return self.invokeConsole(callable.name, args, node) - if (callable.namespace === "Object" && args[0] instanceof ToolReference) { - return self.invokeObjectMethodOnTools(callable.name, args[0] as ToolReference, node) - } - return boundedData(invokeGlobalMethod(callable, args, node), `${callable.namespace}.${callable.name} result`) - } - if (callable instanceof CoercionFunction) { - return boundedData(invokeCoercion(callable, args, node), `${callable.name} result`) - } - if (callable instanceof UriFunction) { - return invokeUriFunction(callable, args, node) - } - // `Error("msg")` without `new` constructs an error exactly like `new Error("msg")`, as in JS. - if (callable instanceof ErrorConstructorReference) { - return createErrorValue(callable.name, args[0] === undefined ? "" : coerceToString(args[0])) - } - throw new InterpreterRuntimeError("Only tools are callable in CodeMode.", callee) - }) - } - - // Object.* over a tool reference: `Object.keys(tools)` / `Object.keys(tools.ns)` enumerate - // namespace/tool names from the host tool tree - the discovery idiom a model reaches for - // first. Every other Object helper cannot produce data from a tool reference, so it fails - // with a pointer at the working idioms instead of the generic plain-objects-only message. - private invokeObjectMethodOnTools(name: string, ref: ToolReference, node: AstNode): unknown { - if (name === "keys") { - return boundedData(this.enumerableKeys(ref)!, "Object.keys result") - } - throw new InterpreterRuntimeError( - `Object.${name}(...) cannot read tool references: they are not plain data. Use Object.keys(tools) for names, or tools.$codemode.search({ query }) for signatures.`, - node, - "InvalidDataValue", - ) - } - - private invokeConsole(name: string, args: Array, node: AstNode): undefined { - if (!consoleMethods.has(name)) - throw new InterpreterRuntimeError(`console.${name} is not available in CodeMode.`, node) - this.logs.push(publicErrorMessage(this.formatConsoleMessage(name, args, node))) - return undefined - } - - private formatConsoleMessage(name: string, args: Array, node: AstNode): string { - if (name === "dir") return args.length === 0 ? "undefined" : this.formatConsoleArgument(args[0]) - if (name === "table") return this.formatConsoleTable(args[0], args[1], node) - const prefix = name === "warn" ? "[warn] " : name === "error" ? "[error] " : name === "debug" ? "[debug] " : "" - return `${prefix}${args.map((arg) => this.formatConsoleArgument(arg)).join(" ")}` - } - - // Console arguments format deeply and totally: values render as a debugger would show them - // rather than as boundary JSON - numbers keep NaN/Infinity (JSON would say null), sandbox - // values keep their friendly forms at ANY depth (ISO date, /regex/flags, Map(n) [...], - // Set(n) [...]), opaque runtime references become "[CodeMode reference]" markers in place, - // and plain objects/arrays render JSON-style. Formatting never fails the program: cycles - // render "[Circular]" and extreme depth degrades to "...". - private formatConsoleArgument(value: unknown): string { - if (value === undefined) return "undefined" - // A top-level string prints bare; nested strings are JSON-quoted (see formatConsoleValue). - if (typeof value === "string") return value - return this.formatConsoleValue(value, new Set(), 0) - } - - private formatConsoleValue(value: unknown, seen: Set, depth: number): string { - // Nested undefined renders as null, matching what JSON boundary output would show. - if (value === null || value === undefined) return "null" - if (typeof value === "string") return JSON.stringify(value) - // String(value) keeps NaN/Infinity/-Infinity readable; finite numbers match their JSON form. - if (typeof value === "number" || typeof value === "boolean") return String(value) - if (typeof value !== "object") return String(value) - if (value instanceof SandboxPromise) return "[Promise (await it to get its value)]" - if (value instanceof SandboxDate) return coerceToString(value) - if (value instanceof SandboxRegExp) return coerceToString(value) - if (value instanceof SandboxURL) return coerceToString(value) - if (value instanceof SandboxURLSearchParams) return coerceToString(value) - if (depth > MAX_CONSOLE_DEPTH) return "..." - if (seen.has(value)) return "[Circular]" - if (value instanceof SandboxMap) { - seen.add(value) - try { - const entries = Array.from(value.map.entries(), ([key, item]): Array => [key, item]) - return `Map(${value.map.size}) ${this.formatConsoleValue(entries, seen, depth + 1)}` - } finally { - seen.delete(value) - } - } - if (value instanceof SandboxSet) { - seen.add(value) - try { - return `Set(${value.set.size}) ${this.formatConsoleValue(Array.from(value.set.values()), seen, depth + 1)}` - } finally { - seen.delete(value) - } - } - if (isRuntimeReference(value)) return "[CodeMode reference]" - seen.add(value) - try { - if (Array.isArray(value)) { - return `[${value.map((item) => this.formatConsoleValue(item, seen, depth + 1)).join(",")}]` - } - return `{${Object.entries(value) - .map(([key, item]) => `${JSON.stringify(key)}:${this.formatConsoleValue(item, seen, depth + 1)}`) - .join(",")}}` - } finally { - seen.delete(value) - } - } - - private formatConsoleTable(value: unknown, columnsArgument: unknown, node: AstNode): string { - if (value === undefined) return "undefined" - // Sandbox values are legitimate table data (cells render their friendly forms); only - // truly opaque references (functions, tools, promises) collapse to the marker. - if (containsOpaqueReference(value)) return "[CodeMode reference]" - const data = boundedData(value, "console.table argument") - const columns = this.consoleTableColumns(columnsArgument, node) - const rows = this.consoleTableRows(data, columns) - const keys = columns ?? Array.from(new Set(rows.flatMap((row) => Object.keys(row.values)))) - const header = ["(index)", ...keys].join("\t") - return [ - header, - ...rows.map((row) => [row.index, ...keys.map((key) => this.formatConsoleTableCell(row.values[key]))].join("\t")), - ].join("\n") - } - - private consoleTableColumns(value: unknown, node: AstNode): ReadonlyArray | undefined { - if (value === undefined) return undefined - if (containsRuntimeReference(value)) return undefined - const columns = copyOut(copyIn(value, "console.table columns"), true) - return Array.isArray(columns) ? columns.map((column) => String(column)) : undefined - } - - private consoleTableRows( - data: unknown, - columns: ReadonlyArray | undefined, - ): Array<{ readonly index: string; readonly values: Record }> { - if (Array.isArray(data)) { - return data.map((item, index) => ({ index: String(index), values: this.consoleTableValues(item, columns) })) - } - if (data !== null && typeof data === "object" && !isSandboxValue(data)) { - return Object.entries(data).map(([index, item]) => ({ index, values: this.consoleTableValues(item, columns) })) - } - return [{ index: "0", values: { Value: data } }] - } - - private consoleTableValues(value: unknown, columns: ReadonlyArray | undefined): Record { - if (value !== null && typeof value === "object" && !Array.isArray(value) && !isSandboxValue(value)) { - const source = value as Record - if (columns !== undefined) return Object.fromEntries(columns.map((column) => [column, source[column]])) - return Object.fromEntries(Object.entries(source)) - } - return { Value: value } - } - - private formatConsoleTableCell(value: unknown): string { - if (value === undefined) return "" - if (typeof value === "string") return value - return this.formatConsoleValue(value, new Set(), 0) - } - - private evaluateCallArguments(argNodes: Array): Effect.Effect, unknown, R> { - const self = this - return Effect.gen(function* () { - const args: Array = [] - for (const [index, arg] of argNodes.entries()) { - const argNode = asNode(arg, `arguments[${index}]`) - if (argNode.type === "SpreadElement") { - const spread = yield* self.evaluateExpression(getNode(argNode, "argument")) - const items = spreadItems(spread) - if (items === undefined) - throw new InterpreterRuntimeError( - "Spread arguments require an array, string, Map, or Set in CodeMode.", - argNode, - ) - args.push(...items) - } else { - args.push(yield* self.evaluateExpression(argNode)) - } - } - return args - }) - } - - // Promise.* over ordinary runtime values. Combinators accept ANY array (or spreadable - // collection) mixing promise values and plain data - built inline, beforehand, via spread, - // whatever - because tool calls already run eagerly on their own fibers; the combinators - // only observe settlements. Joining is therefore sequential (no extra fibers) without - // costing parallelism, and the concurrency cap stays where the work is: the fork semaphore. - private invokePromiseMethod( - ref: PromiseMethodReference, - args: Array, - node: AstNode, - ): Effect.Effect { - const self = this - if (ref.name === "resolve") { - // Promise.resolve of a promise is that promise (JS flattens); anything else is a - // promise already fulfilled with the value. - const value = args[0] - return Effect.succeed( - value instanceof SandboxPromise ? value : new SandboxPromise(undefined, Effect.succeed(value)), - ) - } - if (ref.name === "reject") { - return Effect.sync(() => new SandboxPromise(undefined, Effect.fail(new ProgramThrow(args[0])))) - } - - const items = Array.isArray(args[0]) ? args[0] : spreadItems(args[0]) - if (items === undefined) { - throw new InterpreterRuntimeError( - `Promise.${ref.name} expects an array of promises or plain values (e.g. Promise.${ref.name}(items.map((item) => tools.ns.tool(item)))).`, - node, - ) - } - - switch (ref.name) { - case "all": { - // Mark every promise element observed up-front (Promise.all handles all of its - // members' failures, as in JS), then join in index order; the first failure rejects - // the whole call while unrelated in-flight members keep running. - const settles = items.map((item) => - item instanceof SandboxPromise ? this.settlePromise(item, node) : Effect.succeed(item), - ) - return Effect.gen(function* () { - const values: Array = [] - for (const settle of settles) values.push(yield* settle) - return values - }) - } - case "allSettled": { - const observations = items.map((item) => - item instanceof SandboxPromise - ? Effect.map(this.observePromise(item), (exit) => ({ promise: item as SandboxPromise | undefined, exit })) - : Effect.succeed({ promise: undefined as SandboxPromise | undefined, exit: Exit.succeed(item as unknown) }), - ) - return Effect.gen(function* () { - const outcomes: Array = [] - for (const observation of observations) { - const { exit, promise } = yield* observation - if (Exit.isSuccess(exit)) { - outcomes.push( - Object.assign(Object.create(null) as SafeObject, { status: "fulfilled", value: exit.value }), - ) - continue - } - const raceInterrupted = promise?.interrupted === true && Cause.hasInterruptsOnly(exit.cause) - if (Cause.hasInterruptsOnly(exit.cause) && !raceInterrupted) { - // Execution teardown (timeout/host interruption), not a program-level rejection. - return yield* Effect.failCause(exit.cause) - } - const thrown = raceInterrupted - ? new InterpreterRuntimeError( - "This tool call was interrupted because another value settled a Promise.race first.", - node, - ) - : Cause.squash(exit.cause) - outcomes.push( - Object.assign(Object.create(null) as SafeObject, { - status: "rejected", - reason: caughtErrorValue(thrown), - }), - ) - } - return outcomes - }) - } - case "race": { - if (items.length === 0) { - throw new InterpreterRuntimeError( - "Promise.race([]) would never settle; provide at least one promise or value.", - node, - ) - } - const observations = items.map((item, index) => - item instanceof SandboxPromise - ? Effect.map(this.observePromise(item), (exit) => ({ index, exit })) - : Effect.succeed({ index, exit: Exit.succeed(item as unknown) }), - ) - return Effect.gen(function* () { - // First settlement (fulfilled OR rejected) wins; the observations never fail, so - // racing them yields exactly that. Losing in-flight calls are then interrupted. - const winner = yield* Effect.raceAll(observations) - for (const [index, item] of items.entries()) { - if (index === winner.index || !(item instanceof SandboxPromise) || item.fiber === undefined) continue - item.interrupted = true - yield* Fiber.interrupt(item.fiber) - } - const winningItem = items[winner.index] - return yield* self.unwrapPromiseExit( - winningItem instanceof SandboxPromise ? winningItem : undefined, - winner.exit, - node, - ) - }) - } - } - } - - private invokeFunction(fn: CodeModeFunction, args: Array): Effect.Effect { - const self = this - return Effect.suspend(() => { - const savedScopes = self.scopes - self.scopes = [...fn.capturedScopes, new Map()] - const run = Effect.gen(function* () { - // Seed every parameter name into the scope as a TDZ slot first, so a default that - // references another parameter resolves to that (uninitialized) param rather than - // silently falling through to an outer binding of the same name - matching JS. - const paramScope = self.currentScope() - for (const parameter of fn.parameters) { - for (const name of collectPatternNames(parameter)) { - paramScope.set(name, { mutable: true, value: undefined, initialized: false }) - } - } - for (const [index, parameter] of fn.parameters.entries()) { - if (parameter.type === "RestElement") { - yield* self.declarePattern(getNode(parameter, "argument"), args.slice(index), true, parameter) - break - } - yield* self.declarePattern(parameter, args[index], true, parameter) - } - - if (fn.body.type === "BlockStatement") { - const result = yield* self.evaluateStatement(fn.body) - return result.kind === "return" || result.kind === "value" ? result.value : undefined - } - - return yield* self.evaluateExpression(fn.body) - }) - return run.pipe( - Effect.ensuring( - Effect.sync(() => { - self.scopes = savedScopes - }), - ), - ) - }) - } - - private invokeIntrinsic( - ref: IntrinsicReference, - args: Array, - node: AstNode, - ): Effect.Effect { - if (typeof ref.receiver === "string") { - if ( - (ref.name === "replace" || ref.name === "replaceAll") && - (args[1] instanceof CodeModeFunction || args[1] instanceof CoercionFunction || args[1] instanceof UriFunction) - ) { - return this.invokeStringReplacer(ref.receiver, ref.name, args, node) - } - return Effect.succeed(invokeStringMethod(ref.receiver, ref.name, args, node)) - } - if (typeof ref.receiver === "number") { - return Effect.succeed(invokeNumberMethod(ref.receiver, ref.name, args, node)) - } - if (Array.isArray(ref.receiver)) { - return this.invokeArrayMethod(ref.receiver, ref.name, args, node) - } - if (ref.receiver instanceof SandboxDate) { - return Effect.succeed(invokeDateMethod(ref.receiver, ref.name, node)) - } - if (ref.receiver instanceof SandboxRegExp) { - return Effect.succeed(invokeRegExpMethod(ref.receiver, ref.name, args, node)) - } - if (ref.receiver instanceof SandboxMap) { - return this.invokeMapMethod(ref.receiver, ref.name, args, node) - } - if (ref.receiver instanceof SandboxSet) { - return this.invokeSetMethod(ref.receiver, ref.name, args, node) - } - if (ref.receiver instanceof SandboxURL) { - return Effect.succeed(invokeURLMethod(ref.receiver, ref.name, node)) - } - if (ref.receiver instanceof SandboxURLSearchParams) { - return this.invokeURLSearchParamsMethod(ref.receiver, ref.name, args, node) - } - throw new InterpreterRuntimeError(`Method '${ref.name}' is not available in CodeMode.`, node) - } - - private invokeStringReplacer( - value: string, - name: "replace" | "replaceAll", - args: Array, - node: AstNode, - ): Effect.Effect { - const apply = this.applyCollectionCallback(args[1], `String.${name}`, node) - const matches: Array<{ readonly match: string; readonly offset: number; readonly args: Array }> = [] - const collect = (...callbackArgs: Array): string => { - const match = callbackArgs[0] - const groups = callbackArgs[callbackArgs.length - 1] - const hasGroups = groups !== null && typeof groups === "object" - const offset = callbackArgs[callbackArgs.length - (hasGroups ? 3 : 2)] - if (typeof match !== "string" || typeof offset !== "number") { - throw new InterpreterRuntimeError(`String.${name} produced an invalid replacement match.`, node) - } - if (hasGroups) { - const safeGroups: SafeObject = Object.create(null) as SafeObject - for (const [key, group] of Object.entries(groups)) { - if (!isBlockedMember(key)) safeGroups[key] = group - } - callbackArgs[callbackArgs.length - 1] = safeGroups - } - matches.push({ match, offset, args: callbackArgs }) - return match - } - - const pattern = args[0] - if (pattern instanceof SandboxRegExp) { - if (name === "replaceAll" && !pattern.regex.global) { - throw new InterpreterRuntimeError( - `String.replaceAll requires a regular expression with the global (g) flag: write /${pattern.regex.source}/${pattern.regex.flags}g, or use String.replace to replace only the first match.`, - node, - ) - } - if (name === "replace") value.replace(pattern.regex, collect) - else value.replaceAll(pattern.regex, collect) - } else { - if (typeof pattern !== "string") { - throw new InterpreterRuntimeError(`String.${name} expects argument 1 to be a string.`, node) - } - if (name === "replace") value.replace(pattern, collect) - else value.replaceAll(pattern, collect) - } - - return Effect.gen(function* () { - const output: Array = [] - let end = 0 - for (const match of matches) { - output.push( - value.slice(end, match.offset), - coerceToString(boundedData(yield* apply(match.args), `String.${name} replacer result`)), - ) - end = match.offset + match.match.length - } - output.push(value.slice(end)) - return boundedData(output.join(""), `String.${name} result`) - }) - } - - // Runs a collection callback accepting a user function or supported builtin callable, - // mirroring the array-method callback contract. - private applyCollectionCallback( - callback: unknown, - name: string, - node: AstNode, - ): (args: Array) => Effect.Effect { - if ( - !(callback instanceof CodeModeFunction) && - !(callback instanceof CoercionFunction) && - !(callback instanceof UriFunction) - ) { - throw new InterpreterRuntimeError(`${name} expects a function callback.`, node) - } - return (callbackArgs) => - callback instanceof CoercionFunction - ? Effect.succeed(invokeCoercion(callback, callbackArgs, node)) - : callback instanceof UriFunction - ? Effect.succeed(invokeUriFunction(callback, callbackArgs, node)) - : this.invokeFunction(callback, callbackArgs) - } - - private invokeMapMethod( - target: SandboxMap, - name: string, - args: Array, - node: AstNode, - ): Effect.Effect { - switch (name) { - case "get": - return Effect.succeed(target.map.get(args[0])) - case "has": - return Effect.succeed(target.map.has(args[0])) - case "set": - return Effect.sync(() => { - target.map.set(args[0], args[1]) - return target - }) - case "delete": - return Effect.sync(() => target.map.delete(args[0])) - case "clear": - return Effect.sync(() => { - target.map.clear() - return undefined - }) - case "keys": - return Effect.sync(() => Array.from(target.map.keys())) - case "values": - return Effect.sync(() => Array.from(target.map.values())) - case "entries": - return Effect.sync(() => Array.from(target.map.entries(), ([key, item]): Array => [key, item])) - case "forEach": { - const apply = this.applyCollectionCallback(args[0], "Map.forEach", node) - return Effect.gen(function* () { - // Snapshot iteration, matching the array-method callback contract. - for (const [key, item] of Array.from(target.map.entries())) yield* apply([item, key, target]) - return undefined - }) - } - default: - throw new InterpreterRuntimeError(`Map method '${name}' is not available in CodeMode.`, node) - } - } - - private invokeSetMethod( - target: SandboxSet, - name: string, - args: Array, - node: AstNode, - ): Effect.Effect { - switch (name) { - case "has": - return Effect.succeed(target.set.has(args[0])) - case "add": - return Effect.sync(() => { - target.set.add(args[0]) - return target - }) - case "delete": - return Effect.sync(() => target.set.delete(args[0])) - case "clear": - return Effect.sync(() => { - target.set.clear() - return undefined - }) - case "keys": - case "values": - return Effect.sync(() => Array.from(target.set.values())) - case "entries": - return Effect.sync(() => Array.from(target.set.values(), (item): Array => [item, item])) - case "forEach": { - const apply = this.applyCollectionCallback(args[0], "Set.forEach", node) - return Effect.gen(function* () { - for (const item of Array.from(target.set.values())) yield* apply([item, item, target]) - return undefined - }) - } - default: - throw new InterpreterRuntimeError(`Set method '${name}' is not available in CodeMode.`, node) - } - } - - private invokeURLSearchParamsMethod( - target: SandboxURLSearchParams, - name: string, - args: Array, - node: AstNode, - ): Effect.Effect { - const arg = (index: number): string => uriArgument(args[index], `URLSearchParams.${name} argument ${index + 1}`) - const requireArgs = (count: number): void => { - if (args.length < count) { - throw new InterpreterRuntimeError( - `URLSearchParams.${name} requires ${count} argument${count === 1 ? "" : "s"}.`, - node, - ).as("TypeError") - } - } - switch (name) { - case "append": { - requireArgs(2) - return Effect.sync(() => { - target.params.append(arg(0), arg(1)) - return undefined - }) - } - case "delete": { - requireArgs(1) - return Effect.sync(() => { - if (args[1] !== undefined) target.params.delete(arg(0), arg(1)) - else target.params.delete(arg(0)) - return undefined - }) - } - case "get": - requireArgs(1) - return Effect.sync(() => target.params.get(arg(0))) - case "getAll": - requireArgs(1) - return Effect.sync(() => target.params.getAll(arg(0))) - case "has": - requireArgs(1) - return Effect.sync(() => - args[1] !== undefined ? target.params.has(arg(0), arg(1)) : target.params.has(arg(0)), - ) - case "set": { - requireArgs(2) - return Effect.sync(() => { - target.params.set(arg(0), arg(1)) - return undefined - }) - } - case "sort": - return Effect.sync(() => { - target.params.sort() - return undefined - }) - case "keys": - return Effect.sync(() => Array.from(target.params.keys())) - case "values": - return Effect.sync(() => Array.from(target.params.values())) - case "entries": - return Effect.sync(() => Array.from(target.params.entries(), ([key, value]): Array => [key, value])) - case "toString": - return Effect.sync(() => target.params.toString()) - case "forEach": { - requireArgs(1) - const apply = this.applyCollectionCallback(args[0], "URLSearchParams.forEach", node) - return Effect.gen(function* () { - for (const [key, value] of Array.from(target.params.entries())) yield* apply([value, key, target]) - return undefined - }) - } - default: - throw new InterpreterRuntimeError(`URLSearchParams method '${name}' is not available in CodeMode.`, node) - } - } - - private invokeArrayMethod( - target: Array, - name: string, - args: Array, - node: AstNode, - ): Effect.Effect { - const optNumber = (value: unknown, label: string): number | undefined => { - if (value === undefined) return undefined - if (typeof value !== "number") - throw new InterpreterRuntimeError(`Array.${name} expects ${label} to be a number.`, node) - return value - } - switch (name) { - case "join": { - if (args.length > 1 || (args.length === 1 && typeof args[0] !== "string")) { - throw new InterpreterRuntimeError("Array.join expects zero arguments or one string separator.", node) - } - const input = boundedData(target, "Array.join input") as Array - return Effect.succeed( - input.map((item) => coerceToString(item ?? "")).join(args.length === 0 ? "," : (args[0] as string)), - ) - } - case "includes": - if (args.length === 0 || args.length > 2) - throw new InterpreterRuntimeError("Array.includes expects a value and optional start index.", node) - return Effect.succeed(target.includes(args[0], optNumber(args[1], "start index"))) - case "indexOf": - return Effect.succeed(target.indexOf(args[0], optNumber(args[1], "start index"))) - case "lastIndexOf": - return Effect.succeed( - args[1] === undefined - ? target.lastIndexOf(args[0]) - : target.lastIndexOf(args[0], optNumber(args[1], "start index")), - ) - case "at": - return Effect.succeed(target.at(optNumber(args[0], "index") ?? 0)) - case "slice": - return Effect.succeed(target.slice(optNumber(args[0], "start"), optNumber(args[1], "end"))) - case "concat": - return Effect.succeed(target.concat(...args)) - case "flat": - return Effect.succeed(target.flat(optNumber(args[0], "depth") ?? 1)) - case "reverse": - return Effect.succeed([...target].reverse()) - case "sort": - case "toSorted": - return this.sortArray(target, args[0], node) - case "toReversed": - return Effect.succeed([...target].reverse()) - case "with": { - const index = optNumber(args[0], "index") ?? 0 - const resolved = index < 0 ? target.length + index : index - if (resolved < 0 || resolved >= target.length) { - throw new InterpreterRuntimeError("Array.with index is out of range.", node) - } - const copied = [...target] - copied[resolved] = args[1] - return Effect.succeed(copied) - } - case "push": { - // Validate before mutating (so no rollback is needed): inserting a container into - // itself would create a cycle no later walk could survive. - for (const item of args) this.rejectCircularInsertion(target, item, "Array.push result", node) - target.push(...args) - return Effect.succeed(target.length) - } - case "unshift": { - for (const item of args) this.rejectCircularInsertion(target, item, "Array.unshift result", node) - target.unshift(...args) - return Effect.succeed(target.length) - } - case "pop": - return Effect.succeed(target.pop()) - case "shift": - return Effect.succeed(target.shift()) - case "splice": { - // Mutates in place and returns the removed elements, exactly like JS: one argument - // removes to the end, an undefined delete count removes nothing. - if (args.length === 0) return Effect.succeed(target.splice(0, 0)) - const start = optNumber(args[0], "start") ?? 0 - if (args.length === 1) return Effect.succeed(target.splice(start)) - const deleteCount = optNumber(args[1], "delete count") ?? 0 - const inserted = args.slice(2) - for (const item of inserted) this.rejectCircularInsertion(target, item, "Array.splice result", node) - return Effect.succeed(target.splice(start, deleteCount, ...inserted)) - } - case "fill": { - this.rejectCircularInsertion(target, args[0], "Array.fill result", node) - return Effect.succeed(target.fill(args[0], optNumber(args[1], "start"), optNumber(args[2], "end"))) - } - case "copyWithin": - return Effect.succeed( - target.copyWithin( - optNumber(args[0], "target index") ?? 0, - optNumber(args[1], "start") ?? 0, - optNumber(args[2], "end"), - ), - ) - // keys/values/entries return arrays (not iterators), matching the Map/Set convention; - // they work with for...of and spread either way. - case "keys": - return Effect.succeed(Array.from(target.keys())) - case "values": - return Effect.succeed([...target]) - case "entries": - return Effect.succeed(Array.from(target.entries(), ([index, item]): Array => [index, item])) - } - - const callback = args[0] - if ( - !(callback instanceof CodeModeFunction) && - !(callback instanceof CoercionFunction) && - !(callback instanceof UriFunction) - ) { - throw new InterpreterRuntimeError(`Array.${name} expects a function callback.`, node) - } - const self = this - // Accept a user function or supported builtin callable, so idioms such as - // `filter(Boolean)`, `map(String)`, and `map(encodeURIComponent)` work as in JS. Builtins - // are synchronous; only CodeModeFunctions can await tool calls. - const apply = (callbackArgs: Array): Effect.Effect => - callback instanceof CoercionFunction - ? Effect.succeed(invokeCoercion(callback, callbackArgs, node)) - : callback instanceof UriFunction - ? Effect.succeed(invokeUriFunction(callback, callbackArgs, node)) - : self.invokeFunction(callback, callbackArgs) - return Effect.gen(function* () { - // Iterate a snapshot taken at call time so a callback that mutates the array can't - // self-extend the loop - matching JS, where elements appended during iteration are not visited. - const items = target.slice() - switch (name) { - case "map": { - const values: Array = [] - for (const [index, item] of items.entries()) values.push(yield* apply([item, index, items])) - return values - } - case "flatMap": { - const values: Array = [] - for (const [index, item] of items.entries()) { - const mapped = yield* apply([item, index, items]) - if (Array.isArray(mapped)) values.push(...mapped) - else values.push(mapped) - } - return values - } - case "filter": { - const values: Array = [] - for (const [index, item] of items.entries()) { - if (yield* apply([item, index, items])) values.push(item) - } - return values - } - case "find": - for (const [index, item] of items.entries()) { - if (yield* apply([item, index, items])) return item - } - return undefined - case "findIndex": - for (const [index, item] of items.entries()) { - if (yield* apply([item, index, items])) return index - } - return -1 - case "some": - for (const [index, item] of items.entries()) { - if (yield* apply([item, index, items])) return true - } - return false - case "every": - for (const [index, item] of items.entries()) { - if (!(yield* apply([item, index, items]))) return false - } - return true - case "forEach": - for (const [index, item] of items.entries()) yield* apply([item, index, items]) - return undefined - case "reduce": { - let accumulator: unknown - let start: number - if (args.length >= 2) { - accumulator = args[1] - start = 0 - } else { - if (items.length === 0) - throw new InterpreterRuntimeError("Array.reduce of an empty array with no initial value.", node) - accumulator = items[0] - start = 1 - } - for (let index = start; index < items.length; index += 1) { - accumulator = yield* apply([accumulator, items[index], index, items]) - } - return accumulator - } - case "reduceRight": { - let accumulator: unknown - let start: number - if (args.length >= 2) { - accumulator = args[1] - start = items.length - 1 - } else { - if (items.length === 0) - throw new InterpreterRuntimeError("Array.reduceRight of an empty array with no initial value.", node) - accumulator = items[items.length - 1] - start = items.length - 2 - } - for (let index = start; index >= 0; index -= 1) { - accumulator = yield* apply([accumulator, items[index], index, items]) - } - return accumulator - } - case "findLast": - for (let index = items.length - 1; index >= 0; index -= 1) { - if (yield* apply([items[index], index, items])) return items[index] - } - return undefined - case "findLastIndex": - for (let index = items.length - 1; index >= 0; index -= 1) { - if (yield* apply([items[index], index, items])) return index - } - return -1 - } - throw new InterpreterRuntimeError(`Array method '${name}' is not available in CodeMode.`, node) - }) - } - - private sortArray( - target: Array, - comparator: unknown, - node: AstNode, - ): Effect.Effect, unknown, R> { - if (comparator !== undefined && !(comparator instanceof CodeModeFunction)) { - throw new InterpreterRuntimeError("Array.sort expects an arrow function comparator.", node) - } - if (!(comparator instanceof CodeModeFunction)) { - return Effect.sync(() => - [...target].sort((a, b) => { - const left = coerceToString(a) - const right = coerceToString(b) - return left < right ? -1 : left > right ? 1 : 0 - }), - ) - } - const self = this - const mergeSort = (items: Array): Effect.Effect, unknown, R> => { - if (items.length <= 1) return Effect.succeed(items) - const midpoint = Math.floor(items.length / 2) - return Effect.gen(function* () { - const left = yield* mergeSort(items.slice(0, midpoint)) - const right = yield* mergeSort(items.slice(midpoint)) - const merged: Array = [] - let leftIndex = 0 - let rightIndex = 0 - while (leftIndex < left.length && rightIndex < right.length) { - // Coerce the comparator's result like JS ToNumber (data objects -> NaN, never a host - // crash) and treat NaN as 0 - the spec's "no consistent order" -> keep the left element. - const order = coerceToNumber(yield* self.invokeFunction(comparator, [left[leftIndex], right[rightIndex]])) - if (Number.isNaN(order) || order <= 0) merged.push(left[leftIndex++]) - else merged.push(right[rightIndex++]) - } - return [...merged, ...left.slice(leftIndex), ...right.slice(rightIndex)] - }) - } - // Per spec, undefined elements sort to the end and the comparator is never called on them. - const defined = target.filter((item) => item !== undefined) - const undefinedCount = target.length - defined.length - return Effect.map(mergeSort(defined), (items) => [...items, ...Array(undefinedCount).fill(undefined)]) - } - - private evaluateObjectExpression(node: AstNode): Effect.Effect, unknown, R> { - const objectValue: Record = Object.create(null) as Record - const properties = getArray(node, "properties") - const self = this - return Effect.gen(function* () { - for (const propertyValue of properties) { - const property = asNode(propertyValue, "properties") - - if (property.type === "SpreadElement") { - const spread = yield* self.evaluateExpression(getNode(property, "argument")) - // JS treats `{ ...null }` / `{ ...undefined }` as a no-op, so the common - // `{ ...maybeOpts, override }` merge works when the operand is absent. Sandbox values - // have no own enumerable properties in JS, so they are no-ops too. - if (spread === null || spread === undefined || isSandboxValue(spread)) continue - if (typeof spread !== "object" || Array.isArray(spread) || isRuntimeReference(spread)) { - throw new InterpreterRuntimeError( - "Object spread requires a data object in CodeMode.", - property, - "InvalidDataValue", - ) - } - for (const [key, value] of Object.entries(spread)) { - if (isBlockedMember(key)) - throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, property) - objectValue[key] = value - } - continue - } - - if (property.type !== "Property") { - throw new InterpreterRuntimeError("Only standard object properties are supported.", property) - } - - if (getString(property, "kind") !== "init") { - throw new InterpreterRuntimeError("Only init object properties are supported.", property) - } - - const keyNode = getNode(property, "key") - const valueNode = getNode(property, "value") - const computed = getBoolean(property, "computed") - - let key: PropertyKey - - if (computed) { - key = self.toPropertyKey(yield* self.evaluateExpression(keyNode), keyNode) - } else if (keyNode.type === "Identifier") { - key = getString(keyNode, "name") - } else if (keyNode.type === "Literal") { - key = self.toPropertyKey(keyNode.value, keyNode) - } else { - throw new InterpreterRuntimeError("Unsupported object property key shape.", keyNode) - } - - if (isBlockedMember(String(key))) { - throw new InterpreterRuntimeError(`Property '${String(key)}' is not available in CodeMode.`, keyNode) - } - objectValue[String(key)] = yield* self.evaluateExpression(valueNode) - } - - return objectValue - }) - } - - private evaluateArrayExpression(node: AstNode): Effect.Effect, unknown, R> { - const elements = getArray(node, "elements") - const values: Array = [] - - const self = this - return Effect.gen(function* () { - for (const elementValue of elements) { - if (elementValue === null) { - values.push(undefined) - continue - } - const element = asNode(elementValue, "elements") - if (element.type === "SpreadElement") { - const spread = yield* self.evaluateExpression(getNode(element, "argument")) - const items = spreadItems(spread) - if (items === undefined) - throw new InterpreterRuntimeError( - "Array spread requires an array, string, Map, or Set in CodeMode.", - element, - ) - values.push(...items) - } else { - values.push(yield* self.evaluateExpression(element)) - } - } - return values - }) - } - - private evaluateTemplateLiteral(node: AstNode): Effect.Effect { - const quasis = getArray(node, "quasis") - const expressions = getArray(node, "expressions") - - let output = "" - - const self = this - return Effect.gen(function* () { - for (let index = 0; index < quasis.length; index += 1) { - const quasi = asNode(quasis[index], "quasis") - const rawValue = quasi.value - - if (!isRecord(rawValue) || typeof rawValue.cooked !== "string") { - throw new InterpreterRuntimeError("Invalid template literal quasi.", quasi) - } - - output += rawValue.cooked - - if (index < expressions.length) { - const raw = yield* self.evaluateExpression(asNode(expressions[index], "expressions")) - // The preserving checkpoint keeps sandbox values intact, so coerceToString renders - // them directly (ISO date, /regex/ literal form) instead of a JSON-serialized husk. - output += coerceToString(boundedData(raw, "Template interpolation")) - } - } - - return output - }) - } - - private evaluateConditionalExpression(node: AstNode): Effect.Effect { - return Effect.flatMap(this.evaluateExpression(getNode(node, "test")), (test) => - this.evaluateExpression(getNode(node, test ? "consequent" : "alternate")), - ) - } - - private applyCompoundAssignment(operator: string, current: unknown, incoming: unknown, node: AstNode): unknown { - // `x op= y` is `x = x op y`: dispatch through the shared binary operator implementation - // so compound assignment inherits the same coercion semantics (Dates, data objects, ...). - // Only the arithmetic/bitwise operators are compoundable; logical assignments (&&=/||=/??=) - // short-circuit and are handled by evaluateLogicalAssignment before reaching here. - if (!compoundOperators.has(operator)) { - throw new InterpreterRuntimeError(`Unsupported assignment operator '${operator}'.`, node) - } - return this.applyBinaryOperator(operator.slice(0, -1), current, incoming, node) - } - - private getMemberReference( - node: AstNode, - ): Effect.Effect< - | MemberReference - | ToolReference - | PromiseMethodReference - | IntrinsicReference - | GlobalMethodReference - | ComputedValue - | typeof OptionalShortCircuit - | undefined, - unknown, - R - > { - const objectNode = getNode(node, "object") - const propertyNode = getNode(node, "property") - const computed = getBoolean(node, "computed") - const optional = node.optional === true - const self = this - return Effect.gen(function* () { - const objectValue = yield* self.evaluateExpression(objectNode) - if (objectValue === OptionalShortCircuit) return OptionalShortCircuit - if ((objectValue === null || objectValue === undefined) && optional) return OptionalShortCircuit - - const key = computed - ? self.toPropertyKey(yield* self.evaluateExpression(propertyNode), propertyNode) - : propertyNode.type === "Identifier" - ? getString(propertyNode, "name") - : self.toPropertyKey(yield* self.evaluateExpression(propertyNode), propertyNode) - - if (objectValue instanceof ToolReference) { - if (typeof key !== "string" || isBlockedMember(key)) { - throw new InterpreterRuntimeError("Tool paths must use safe string property names.", propertyNode) - } - return new ToolReference([...objectValue.path, key]) - } - - if (objectValue instanceof PromiseNamespace) { - if (typeof key === "string" && promiseStatics.has(key as PromiseMethodName)) { - return new PromiseMethodReference(key as PromiseMethodName) - } - throw new InterpreterRuntimeError( - `Promise.${String(key)} is not available in CodeMode. Available: Promise.all, Promise.allSettled, Promise.race, Promise.resolve, and Promise.reject; consume promises with await.`, - propertyNode, - ) - } - - if (objectValue instanceof GlobalNamespace) { - if (typeof key !== "string" || isBlockedMember(key)) { - throw new InterpreterRuntimeError( - `${objectValue.name}.${String(key)} is not available in CodeMode.`, - propertyNode, - ) - } - if (objectValue.name === "Math" && mathConstants.has(key)) { - return new ComputedValue((Math as unknown as Record)[key]) - } - return new GlobalMethodReference(objectValue.name, key) - } - - if (typeof objectValue === "string") { - if (key === "length") return new ComputedValue(objectValue.length) - if (typeof key === "number") return new ComputedValue(objectValue[key]) - if (typeof key === "string" && /^\d+$/.test(key)) return new ComputedValue(objectValue[Number(key)]) - if (typeof key === "string" && stringMethods.has(key)) return new IntrinsicReference(objectValue, key) - // Unknown property on a string reads as `undefined`, matching JS (`"x".foo === undefined`), - // instead of throwing - so defensive access like `result?.login ?? result` on a JSON-string - // tool result doesn't crash. (Optional chaining only guards null/undefined receivers, so a - // real string still reaches here.) Only the method allowlist above yields callables. - return new ComputedValue(undefined) - } - - if (typeof objectValue === "number") { - if (typeof key === "string" && numberMethods.has(key)) return new IntrinsicReference(objectValue, key) - // Unknown property on a number reads as `undefined`, matching JS, rather than throwing. - return new ComputedValue(undefined) - } - - // Number / String expose a small allowlist of statics; everything else stays opaque. - if (objectValue instanceof CoercionFunction && typeof key === "string" && !isBlockedMember(key)) { - if (objectValue.name === "Number" && numberConstants.has(key)) { - return new ComputedValue((Number as unknown as Record)[key]) - } - if (objectValue.name === "Number" && numberStatics.has(key)) return new GlobalMethodReference("Number", key) - if (objectValue.name === "String" && stringStatics.has(key)) return new GlobalMethodReference("String", key) - } - - // Sandbox value types expose their method/property allowlists; any other key reads as - // `undefined`, consistent with unknown-property reads on strings/numbers/arrays. - if (objectValue instanceof SandboxDate) { - if (typeof key === "string" && dateMethods.has(key)) return new IntrinsicReference(objectValue, key) - return new ComputedValue(undefined) - } - if (objectValue instanceof SandboxRegExp) { - if (typeof key === "string" && regexpProperties.has(key)) { - return new ComputedValue((objectValue.regex as unknown as Record)[key]) - } - if (typeof key === "string" && regexpMethods.has(key)) return new IntrinsicReference(objectValue, key) - return new ComputedValue(undefined) - } - if (objectValue instanceof SandboxMap) { - if (key === "size") return new ComputedValue(objectValue.map.size) - if (typeof key === "string" && mapMethods.has(key)) return new IntrinsicReference(objectValue, key) - return new ComputedValue(undefined) - } - if (objectValue instanceof SandboxSet) { - if (key === "size") return new ComputedValue(objectValue.set.size) - if (typeof key === "string" && setMethods.has(key)) return new IntrinsicReference(objectValue, key) - return new ComputedValue(undefined) - } - if (objectValue instanceof SandboxURL) { - if (key === "searchParams") { - return new ComputedValue(objectValue.searchParams) - } - if (typeof key === "string" && urlMethods.has(key)) return new IntrinsicReference(objectValue, key) - if (typeof key === "string" && urlProperties.has(key)) return { target: objectValue, key } - return new ComputedValue(undefined) - } - if (objectValue instanceof SandboxURLSearchParams) { - if (key === "size") return new ComputedValue(objectValue.params.size) - if (typeof key === "string" && urlSearchParamsMethods.has(key)) { - return new IntrinsicReference(objectValue, key) - } - return new ComputedValue(undefined) - } - - // Any property access on a promise is a confused program (`p.then(...)`, `p.value`); - // reading `undefined` here would hide the missing await, so both paths get an explicit, - // await-hinting error instead of the forgiving unknown-property fallthrough. - if (objectValue instanceof SandboxPromise) { - if (key === "then" || key === "catch" || key === "finally") { - throw new InterpreterRuntimeError( - `Promise.prototype.${String(key)} is not supported in CodeMode; use await instead (with try/catch to handle failures) - e.g. \`const result = await tools.ns.tool(...)\`.`, - propertyNode, - "UnsupportedSyntax", - [supportedSyntaxMessage], - ) - } - throw new InterpreterRuntimeError( - "This value is an un-awaited Promise and has no readable properties; await it first - e.g. `const result = await tools.ns.tool(...)`.", - objectNode, - "InvalidDataValue", - ) - } - - if (isRuntimeReference(objectValue)) { - throw new InterpreterRuntimeError( - "CodeMode runtime references are opaque and do not expose properties.", - objectNode, - "InvalidDataValue", - ) - } - - if (typeof objectValue !== "object" || objectValue === null) { - throw new InterpreterRuntimeError("Cannot access a property on a non-object value.", objectNode) - } - - if (typeof key === "string" && isBlockedMember(key)) { - throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, propertyNode) - } - - if (Array.isArray(objectValue)) { - if ( - key !== "length" && - !(typeof key === "string" && arrayMethods.has(key)) && - typeof key !== "number" && - !/^\d+$/.test(key) - ) { - // Own non-index properties read through (match results carry index/groups); like JS, - // they are readable in place and dropped by JSON at data boundaries. - if (typeof key === "string" && Object.hasOwn(objectValue, key)) { - return new ComputedValue((objectValue as Record & Array)[key]) - } - // Unknown property on an array reads as `undefined`, matching JS (`[1,2].foo === undefined`), - // instead of throwing - so defensive access under optional chaining behaves as expected. - return new ComputedValue(undefined) - } - return { target: objectValue, key } - } - - return { target: objectValue as SafeObject, key } - }) - } - - private readMember(node: AstNode): Effect.Effect { - return Effect.map(this.getMemberReference(node), (reference) => { - if (reference === OptionalShortCircuit) return OptionalShortCircuit - if (reference instanceof ComputedValue) return reference.value - if ( - reference === undefined || - reference instanceof ToolReference || - reference instanceof PromiseMethodReference || - reference instanceof IntrinsicReference || - reference instanceof GlobalMethodReference - ) - return reference - if (Array.isArray(reference.target)) { - if (typeof reference.key === "string" && arrayMethods.has(reference.key)) { - return new IntrinsicReference(reference.target, reference.key) - } - return reference.key === "length" ? reference.target.length : reference.target[Number(reference.key)] - } - if (reference.target instanceof SandboxURL) { - return (reference.target.url as unknown as Record)[String(reference.key)] - } - return reference.target[String(reference.key)] - }) - } - - private writeMember(node: AstNode, value: unknown): Effect.Effect { - return this.modifyMember(node, () => Effect.succeed({ write: true, next: value, result: value })) - } - - // Resolves the member reference EXACTLY ONCE (so a side-effecting object/key expression - // runs once), then lets `compute` decide whether to write - enabling compound assignment, - // updates, plain writes, and short-circuiting logical assignment to share one safe path. - private modifyMember( - node: AstNode, - compute: (current: unknown) => Effect.Effect<{ write: boolean; next: unknown; result: unknown }, unknown, R>, - ): Effect.Effect { - const self = this - return Effect.gen(function* () { - const reference = yield* self.getMemberReference(node) - if ( - reference === OptionalShortCircuit || - reference instanceof ComputedValue || - reference === undefined || - reference instanceof ToolReference || - reference instanceof PromiseMethodReference || - reference instanceof IntrinsicReference || - reference instanceof GlobalMethodReference - ) { - throw new InterpreterRuntimeError("Only data fields may be assigned in CodeMode.", node) - } - if (Array.isArray(reference.target)) { - if (reference.key === "length") - throw new InterpreterRuntimeError("Array length cannot be assigned in CodeMode.", node) - if (typeof reference.key === "string" && arrayMethods.has(reference.key)) { - throw new InterpreterRuntimeError("Array methods cannot be assigned in CodeMode.", node) - } - } - const key = Array.isArray(reference.target) ? Number(reference.key) : String(reference.key) - const current = - reference.target instanceof SandboxURL - ? (reference.target.url as unknown as Record)[key] - : (reference.target as Record)[key] - const { write, next, result } = yield* compute(current) - if (write) self.assignToReference(reference, key, next, node) - return result - }) - } - - // Rejects inserting a value that (transitively) contains the container it is being inserted - // into - the mutation that would create a circular structure no later walk could survive. - private rejectCircularInsertion( - container: object, - value: unknown, - label: string, - node: AstNode, - seen = new Set(), - ): void { - if (value === container) - throw new InterpreterRuntimeError(`${label} contains a circular value.`, node, "InvalidDataValue") - if (value === null || typeof value !== "object" || isRuntimeReference(value) || seen.has(value)) return - seen.add(value) - const items = Array.isArray(value) ? value : Object.values(value) - for (const item of items) this.rejectCircularInsertion(container, item, label, node, seen) - seen.delete(value) - } - - private assignToReference(reference: MemberReference, key: number | string, next: unknown, node: AstNode): void { - if (Array.isArray(reference.target)) { - const target = reference.target - const index = key as number - if (!Number.isInteger(index) || index < 0) { - throw new InterpreterRuntimeError( - "Array assignment index must be a non-negative integer.", - node, - "InvalidDataValue", - ) - } - this.rejectCircularInsertion(target, next, "Array assignment result", node) - target[index] = next - return - } - if (reference.target instanceof SandboxURL) { - const property = key as string - if (!urlWritableProperties.has(property)) { - throw new InterpreterRuntimeError(`URL.${property} is read-only.`, node).as("TypeError") - } - try { - const url = reference.target.url as unknown as Record - url[property] = uriArgument(next, `URL.${property} value`) - return - } catch (error) { - if (error instanceof InterpreterRuntimeError || error instanceof ToolRuntimeError) throw error - throw new InterpreterRuntimeError(`URL.${property} received an invalid value.`, node).as("TypeError") - } - } - const target = reference.target as SafeObject - const objectKey = key as string - this.rejectCircularInsertion(target, next, "Object assignment result", node) - target[objectKey] = next - } - - private toPropertyKey(value: unknown, node: AstNode): string | number { - if (typeof value === "string" || typeof value === "number") { - return value - } - - throw new InterpreterRuntimeError("Property key must be a string or number.", node) - } - - private declare(name: string, value: unknown, mutable: boolean, node: AstNode): void { - const scope = this.currentScope() - - // A pre-seeded parameter slot (initialized === false) is being bound for the first time; - // anything else already present is a genuine duplicate declaration. - const existing = scope.get(name) - if (existing && existing.initialized !== false) { - throw new InterpreterRuntimeError(`Identifier '${name}' has already been declared.`, node) - } - - scope.set(name, { mutable, value, initialized: true }) - } - - private getIdentifierValue(name: string, node: AstNode): unknown { - const binding = this.resolveBinding(name) - - if (!binding) { - throw new InterpreterRuntimeError(`Unknown identifier '${name}'.`, node).as("ReferenceError") - } - - // A parameter default that forward-references a later (not-yet-bound) parameter - JS TDZ. - if (binding.initialized === false) { - throw new InterpreterRuntimeError(`Cannot access '${name}' before initialization.`, node).as("ReferenceError") - } - - return binding.value - } - - private setIdentifierValue(name: string, value: unknown, node: AstNode): unknown { - const binding = this.resolveBinding(name) - - if (!binding) { - throw new InterpreterRuntimeError(`Unknown identifier '${name}'.`, node).as("ReferenceError") - } - - if (!binding.mutable) { - throw new InterpreterRuntimeError(`Cannot assign to constant '${name}'.`, node).as("TypeError") - } - - binding.value = value - return value - } - - private resolveBinding(name: string): Binding | undefined { - for (let index = this.scopes.length - 1; index >= 0; index -= 1) { - const scope = this.scopes[index] - const binding = scope?.get(name) - - if (binding) { - return binding - } - } - - return undefined - } - - private currentScope(): Map { - const scope = this.scopes[this.scopes.length - 1] - - if (!scope) { - throw new InterpreterRuntimeError("Interpreter scope stack is empty.") - } - - return scope - } - - private pushScope(): void { - this.scopes.push(new Map()) - } - - private popScope(): void { - this.scopes.pop() - } -} - -/** - * Executes one Effect-native CodeMode program without constructing a reusable runtime. - * - * @example - * ```ts - * const result = yield* CodeMode.execute({ - * tools: { lookup }, - * code: `return await tools.lookup({ id: "order_42" })`, - * }) - * ``` - */ -const executeWithLimits = >( - options: ExecuteOptions, - limits: ResolvedExecutionLimits, - searchIndex: ToolRuntime.DiscoveryPlan["searchIndex"], -): Effect.Effect> => { - const hooks = { - ...(options.onToolCallStart === undefined ? {} : { onToolCallStart: options.onToolCallStart }), - ...(options.onToolCallEnd === undefined ? {} : { onToolCallEnd: options.onToolCallEnd }), - } - const tools = ToolRuntime.make( - (options.tools ?? {}) as HostTools>, - limits.maxToolCalls, - searchIndex, - hooks, - ) - const logs: Array = [] - const logged = () => (logs.length > 0 ? { logs: [...logs] } : {}) - - if (options.code.trim().length === 0) { - return Effect.succeed({ - ok: false, - error: { kind: "ParseError", message: "Code cannot be empty." }, - toolCalls: tools.calls, - }) - } - - const operation = Effect.gen(function* () { - const program = parseProgram(options.code) - const interpreter = new Interpreter>(tools.invoke, tools.keys, logs) - const value = yield* interpreter.run(program) - const result = copyOut(copyIn(value, "Execution result"), true) as DataValue - return { - ok: true, - value: result, - ...logged(), - toolCalls: tools.calls, - } satisfies Result - }).pipe((program) => { - const timeoutMs = limits.timeoutMs - if (timeoutMs === undefined) return program - return program.pipe( - Effect.timeoutOrElse({ - duration: timeoutMs, - orElse: () => - Effect.succeed({ - ok: false, - error: { kind: "TimeoutExceeded", message: `Execution timed out after ${timeoutMs}ms.` }, - ...logged(), - toolCalls: tools.calls, - } satisfies Result), - }), - ) - }) - - return operation.pipe( - Effect.catchCause((cause) => - Cause.hasInterruptsOnly(cause) - ? Effect.interrupt - : Effect.succeed({ - ok: false, - error: normalizeError(Cause.squash(cause)), - ...logged(), - toolCalls: tools.calls, - } satisfies Result), - ), - Effect.map((result) => (limits.maxOutputBytes === undefined ? result : boundOutput(result, limits.maxOutputBytes))), - ) -} - -const utf8ByteLength = (value: string): number => new TextEncoder().encode(value).byteLength - -// Truncates to a UTF-8 byte budget without splitting a code point (a split multi-byte -// sequence decodes to a replacement character, which is dropped). -const utf8Truncate = (value: string, maxBytes: number): string => { - const bytes = new TextEncoder().encode(value) - if (bytes.byteLength <= maxBytes) return value - const text = new TextDecoder("utf-8").decode(bytes.slice(0, Math.max(0, maxBytes))) - return text.endsWith("\uFFFD") ? text.slice(0, -1) : text -} - -/** - * Bounds the model-facing output (serialized result value plus logs) to `maxOutputBytes`. - * Oversized values are replaced by their truncated serialized text with an explanatory marker, - * and logs are kept from the start until the remaining budget is exhausted. Truncation never - * fails the execution; `truncated: true` marks affected results. Only runs when the host set - * `maxOutputBytes` - with the limit absent, output passes through unbounded. - */ -const boundOutput = (result: Result, maxOutputBytes: number): Result => { - let truncated = false - - let value: DataValue = null - let valueBytes = 0 - if (result.ok) { - const serialized = JSON.stringify(result.value) ?? "null" - const bytes = utf8ByteLength(serialized) - if (bytes > maxOutputBytes) { - truncated = true - value = `${utf8Truncate(serialized, maxOutputBytes)} [result truncated: ${bytes} bytes exceeds the ${maxOutputBytes}-byte output limit; return a smaller value]` - valueBytes = maxOutputBytes - } else { - value = result.value - valueBytes = bytes - } - } - - const logs = result.logs ?? [] - const kept: Array = [] - const logBudget = Math.max(0, maxOutputBytes - valueBytes) - let logBytes = 0 - for (const line of logs) { - const lineBytes = utf8ByteLength(line) + 1 - if (logBytes + lineBytes > logBudget) break - logBytes += lineBytes - kept.push(line) - } - if (kept.length < logs.length) { - truncated = true - kept.push(`[logs truncated: showing ${kept.length} of ${logs.length} lines]`) - } - - if (!truncated) return result - const logsPart = kept.length > 0 ? { logs: kept } : {} - return result.ok - ? { ok: true, value, ...logsPart, truncated: true, toolCalls: result.toolCalls } - : { ok: false, error: result.error, ...logsPart, truncated: true, toolCalls: result.toolCalls } -} - +/** Executes one Effect-native CodeMode program without constructing a reusable runtime. */ export const execute = >( options: ExecuteOptions, ): Effect.Effect> => { @@ -4442,17 +147,7 @@ export const execute = >( return executeWithLimits(options, resolveExecutionLimits(options.limits), ToolRuntime.searchIndex(tools)) } -/** - * Creates an Effect-native runtime over explicit, schema-described tools. - * - * Use `execute` for host-driven execution. Tool requirements remain in the returned Effect environment. - * - * @example - * ```ts - * const runtime = CodeMode.make({ tools: { orders: { lookup } } }) - * const result = runtime.execute("return await tools.orders.lookup({ id: 'order_42' })") - * ``` - */ +/** Creates an Effect-native runtime over explicit, schema-described tools. */ export const make = = {}>( options: Options = {} as Options, ): Runtime> => { @@ -4460,13 +155,10 @@ export const make = = {}>( ToolRuntime.assertValidTools(tools) const limits = resolveExecutionLimits(options.limits) const prepared = ToolRuntime.prepare(tools, options.discovery?.catalogBudget) - const executeProgram = (code: string) => executeWithLimits({ ...options, code }, limits, prepared.searchIndex) - const catalog = prepared.catalog - const instructions = prepared.instructions return { - catalog: () => catalog, - instructions: () => instructions, - execute: executeProgram, + catalog: () => prepared.catalog, + instructions: () => prepared.instructions, + execute: (code) => executeWithLimits({ ...options, code }, limits, prepared.searchIndex), } } diff --git a/packages/codemode/src/interpreter/model.ts b/packages/codemode/src/interpreter/model.ts new file mode 100644 index 00000000000..0869a89cb28 --- /dev/null +++ b/packages/codemode/src/interpreter/model.ts @@ -0,0 +1,200 @@ +import type { SafeObject } from "../tool-runtime.js" +import type { SandboxURL } from "../values.js" + +export type SourcePosition = { + line: number + column: number +} + +export type SourceLocation = { + start: SourcePosition + end: SourcePosition +} + +export type AstNode = { + type: string + loc?: SourceLocation + [key: string]: unknown +} + +export type ProgramNode = AstNode & { + type: "Program" + body: Array +} + +export type Binding = { + mutable: boolean + value: unknown + initialized?: boolean +} + +export type StatementResult = + | { kind: "none" } + | { kind: "value"; value: unknown } + | { kind: "return"; value: unknown } + | { kind: "break" } + | { kind: "continue" } + +export type MemberReference = { + target: SafeObject | Array | SandboxURL + key: string | number +} + +export class CodeModeFunction { + constructor( + readonly parameters: ReadonlyArray, + readonly body: AstNode, + readonly capturedScopes: ReadonlyArray>, + ) {} +} + +export class IntrinsicReference { + constructor( + readonly receiver: unknown, + readonly name: string, + ) {} +} + +export class ComputedValue { + constructor(readonly value: unknown) {} +} + +export class PromiseNamespace {} + +export type PromiseMethodName = "all" | "allSettled" | "race" | "resolve" | "reject" + +export class PromiseMethodReference { + constructor(readonly name: PromiseMethodName) {} +} + +export type GlobalNamespaceName = + | "Object" + | "Math" + | "JSON" + | "Array" + | "console" + | "Date" + | "RegExp" + | "Map" + | "Set" + | "URL" + | "URLSearchParams" + +export class GlobalNamespace { + constructor(readonly name: GlobalNamespaceName) {} +} + +export class GlobalMethodReference { + constructor( + readonly namespace: GlobalNamespaceName | "Number" | "String", + readonly name: string, + ) {} +} + +export class CoercionFunction { + constructor(readonly name: "Number" | "String" | "Boolean" | "parseInt" | "parseFloat") {} +} + +export class UriFunction { + constructor(readonly name: "encodeURI" | "encodeURIComponent" | "decodeURI" | "decodeURIComponent") {} +} + +export class ProgramThrow { + constructor(readonly value: unknown) {} +} + +export class ErrorConstructorReference { + constructor(readonly name: string) {} +} + +export type DiagnosticKind = + | "ParseError" + | "UnsupportedSyntax" + | "UnknownTool" + | "InvalidToolInput" + | "InvalidToolOutput" + | "InvalidDataValue" + | "ToolCallLimitExceeded" + | "TimeoutExceeded" + | "ToolFailure" + | "ExecutionFailure" + +export const OptionalShortCircuit: unique symbol = Symbol("codemode.optional-short-circuit") + +export const supportedSyntaxMessage = + "Supported orchestration syntax: tools.* calls (they return promises - resolve them with await), data literals, destructuring, optional chaining, template literals, conditionals, switch, loops (incl. for...of and for...in over object/array/tools keys), arrow functions, spread, try/catch, array methods (map/filter/find/findIndex/some/every/reduce/flatMap/forEach/sort/slice/concat/indexOf/lastIndexOf/at/flat/reverse/includes/join), string methods (incl. match/matchAll/replace/split with regular expressions), Date/RegExp/Map/Set/URL/URLSearchParams, URI encoding helpers, Object/Math/JSON helpers, captured console.log/warn/error/dir/table, and Promise.all/allSettled/race/resolve/reject over arrays mixing promises and plain values for parallel tool calls (promise chaining with .then/.catch is not supported - use await with try/catch)." + +export class InterpreterRuntimeError extends Error { + readonly node?: AstNode + errorName: string = "Error" + + constructor( + message: string, + node?: AstNode, + readonly kind: DiagnosticKind = "ExecutionFailure", + readonly suggestions?: ReadonlyArray, + ) { + super(message) + this.name = "InterpreterRuntimeError" + if (node) this.node = node + } + + as(errorName: string): this { + this.errorName = errorName + return this + } +} + +export const unsupportedSyntax = (kind: string, node: AstNode): InterpreterRuntimeError => + new InterpreterRuntimeError( + `Syntax '${kind}' is not supported in CodeMode. ${supportedSyntaxMessage}`, + node, + "UnsupportedSyntax", + [supportedSyntaxMessage], + ) + +export const isRecord = (value: unknown): value is Record => typeof value === "object" && value !== null + +export const asNode = (value: unknown, context: string): AstNode => { + if (!isRecord(value) || typeof value.type !== "string") { + throw new InterpreterRuntimeError(`Invalid AST node while reading ${context}.`) + } + return value as AstNode +} + +export const getArray = (node: AstNode, key: string): Array => { + const value = node[key] + if (!Array.isArray(value)) throw new InterpreterRuntimeError(`Expected '${key}' to be an array.`, node) + return value +} + +export const getString = (node: AstNode, key: string): string => { + const value = node[key] + if (typeof value !== "string") throw new InterpreterRuntimeError(`Expected '${key}' to be a string.`, node) + return value +} + +export const getBoolean = (node: AstNode, key: string): boolean => { + const value = node[key] + if (typeof value !== "boolean") throw new InterpreterRuntimeError(`Expected '${key}' to be a boolean.`, node) + return value +} + +export const getOptionalNode = (node: AstNode, key: string): AstNode | undefined => { + const value = node[key] + if (value === undefined || value === null) return undefined + return asNode(value, key) +} + +export const getNode = (node: AstNode, key: string): AstNode => asNode(node[key], key) + +export const sourceLocation = (node: AstNode): { readonly line: number; readonly column: number } => ({ + line: Math.max(1, (node.loc?.start.line ?? 2) - 1), + column: Math.max(1, (node.loc?.start.column ?? 4) - 3), +}) + +export const formatLocation = (node?: AstNode): string => { + if (!node?.loc) return "" + const location = sourceLocation(node) + return ` (line ${location.line}, col ${location.column})` +} diff --git a/packages/codemode/src/interpreter/runtime.ts b/packages/codemode/src/interpreter/runtime.ts new file mode 100644 index 00000000000..093f5777651 --- /dev/null +++ b/packages/codemode/src/interpreter/runtime.ts @@ -0,0 +1,3465 @@ +import { parse } from "acorn" +import { Cause, Effect, Exit, Fiber, Semaphore } from "effect" +import { DiagnosticCategory, ModuleKind, ScriptTarget, flattenDiagnosticMessageText, transpileModule } from "typescript" +import { + copyIn, + copyOut, + isBlockedMember, + ToolReference, + ToolRuntime, + ToolRuntimeError, + type HostTools, + type SafeObject, + type Services, +} from "../tool-runtime.js" +import { ToolError } from "../tool-error.js" +import type { + DataValue, + Diagnostic, + DiagnosticKind, + ExecuteOptions, + ResolvedExecutionLimits, + Result, +} from "../codemode.js" +import { + type AstNode, + asNode, + type Binding, + CodeModeFunction, + CoercionFunction, + ComputedValue, + ErrorConstructorReference, + GlobalMethodReference, + GlobalNamespace, + type GlobalNamespaceName, + formatLocation, + getArray, + getBoolean, + getNode, + getOptionalNode, + getString, + IntrinsicReference, + InterpreterRuntimeError, + isRecord, + type MemberReference, + OptionalShortCircuit, + PromiseMethodReference, + type PromiseMethodName, + PromiseNamespace, + ProgramThrow, + type ProgramNode, + type StatementResult, + sourceLocation, + supportedSyntaxMessage, + unsupportedSyntax, + UriFunction, +} from "./model.js" +import { arrayMethods, mapMethods, setMethods, spreadItems } from "../stdlib/collections.js" +import { consoleMethods, MAX_CONSOLE_DEPTH } from "../stdlib/console.js" +import { dateMethods, dateStatics, invokeDateMethod, invokeDateStatic } from "../stdlib/date.js" +import { invokeJsonMethod } from "../stdlib/json.js" +import { invokeMathMethod, mathConstants } from "../stdlib/math.js" +import { + invokeNumberMethod, + invokeNumberStatic, + numberConstants, + numberMethods, + numberStatics, +} from "../stdlib/number.js" +import { invokeObjectMethod } from "../stdlib/object.js" +import { promiseStatics, TOOL_CALL_CONCURRENCY } from "../stdlib/promise.js" +import { + escapeRegexHint, + invokeRegExpMethod, + matchToValue, + regexpMethods, + regexpProperties, + regexFailureReason, + toHostRegex, +} from "../stdlib/regexp.js" +import { invokeStringStatic, stringMethods, stringStatics } from "../stdlib/string.js" +import { + urlMethods, + urlProperties, + urlSearchParamsMethods, + urlStatics, + urlWritableProperties, + invokeUriFunction, + invokeURLMethod, + invokeURLStatic, + uriArgument, + urlArgument, +} from "../stdlib/url.js" +import { + boundedData, + coerceToNumber, + coerceToString, + compoundOperators, + createErrorValue, + errorBrandName, + errorConstructors, + invokeCoercion, + valueConstructors, +} from "../stdlib/value.js" +import { + isSandboxValue, + SandboxDate, + SandboxMap, + SandboxPromise, + SandboxRegExp, + SandboxSet, + SandboxURL, + SandboxURLSearchParams, +} from "../values.js" + +const parseProgram = (code: string): ProgramNode => { + const transpiled = transpileModule(`async function __codemode__() {\n${code}\n}`, { + reportDiagnostics: true, + compilerOptions: { + target: ScriptTarget.ESNext, + module: ModuleKind.ESNext, + }, + }) + const diagnostic = transpiled.diagnostics?.find((item) => item.category === DiagnosticCategory.Error) + + if (diagnostic) { + throw new InterpreterRuntimeError( + `Failed to parse TypeScript: ${flattenDiagnosticMessageText(diagnostic.messageText, "\n")}`, + undefined, + "ParseError", + ) + } + + const bodyStart = transpiled.outputText.indexOf("{") + 1 + const bodyEnd = transpiled.outputText.lastIndexOf("}") + const executableCode = transpiled.outputText.slice(bodyStart, bodyEnd) + const parsed = parse(executableCode, { + ecmaVersion: "latest", + sourceType: "script", + allowReturnOutsideFunction: true, + allowAwaitOutsideFunction: true, + locations: true, + }) as unknown + + if (!isRecord(parsed) || parsed.type !== "Program" || !Array.isArray(parsed.body)) { + throw new InterpreterRuntimeError("Failed to parse script as a Program node.") + } + + return parsed as ProgramNode +} + +const publicErrorMessage = (message: string): string => + message.replace(/\/(?:Users|home|private|tmp|var\/folders)\/[^\s"'`]+/g, "") + +const normalizeError = (error: unknown): Diagnostic => { + if (error instanceof InterpreterRuntimeError) { + return { + kind: error.kind, + message: `${error.message}${formatLocation(error.node)}`, + ...(error.node?.loc ? { location: sourceLocation(error.node) } : {}), + ...(error.suggestions ? { suggestions: error.suggestions } : {}), + } + } + + if (error instanceof ToolRuntimeError) { + return { + kind: error.kind, + message: error.message, + ...(error.suggestions.length > 0 ? { suggestions: error.suggestions } : {}), + } + } + + if (error instanceof ToolError) { + return { kind: "ToolFailure", message: publicErrorMessage(error.message) } + } + + if (error instanceof ProgramThrow) { + const value = error.value + let message: string + if (containsRuntimeReference(value)) { + // A thrown tool/function reference must not leak its internal structure. + message = "a non-data value" + } else if (typeof value === "string") { + message = value + } else if ( + value !== null && + typeof value === "object" && + typeof (value as { message?: unknown }).message === "string" + ) { + message = (value as { message: string }).message + } else { + try { + message = JSON.stringify(copyOut(value)) ?? String(value) + } catch { + message = String(value) + } + } + return { kind: "ExecutionFailure", message: `Uncaught: ${message}` } + } + + if (error instanceof RangeError && /call stack|recursion/i.test(error.message)) { + return { + kind: "ExecutionFailure", + message: "Execution exceeded the maximum nesting depth.", + } + } + + if (error instanceof Error) { + return { + kind: error.name === "SyntaxError" ? "ParseError" : "ExecutionFailure", + message: publicErrorMessage(error.message), + } + } + + // A non-Error thrown by a host tool (raw string / number / Symbol) still routes through + // path redaction so filesystem paths can never leak through the catch-all branch. + return { + kind: "ExecutionFailure", + message: publicErrorMessage(String(error)), + } +} + +// Shared by catch bindings, Promise.allSettled rejection reasons, and Promise.race losers. +const caughtErrorValue = (thrown: unknown): unknown => { + if (thrown instanceof ProgramThrow) return thrown.value + if (thrown instanceof InterpreterRuntimeError) return createErrorValue(thrown.errorName, thrown.message) + const name = thrown instanceof Error && errorConstructors.has(thrown.name) ? thrown.name : "Error" + return createErrorValue(name, normalizeError(thrown).message) +} + +const isRuntimeReference = (value: unknown): boolean => + value instanceof CodeModeFunction || + value instanceof ToolReference || + value instanceof IntrinsicReference || + value instanceof GlobalNamespace || + value instanceof GlobalMethodReference || + value instanceof PromiseNamespace || + value instanceof PromiseMethodReference || + value instanceof SandboxPromise || + value instanceof CoercionFunction || + value instanceof UriFunction || + value instanceof ErrorConstructorReference || + isSandboxValue(value) + +const containsRuntimeReference = (value: unknown, seen = new Set()): boolean => { + if (isRuntimeReference(value)) return true + if (value === null || typeof value !== "object") return false + if (seen.has(value)) return false + seen.add(value) + const contains = Array.isArray(value) + ? value.some((item) => containsRuntimeReference(item, seen)) + : Object.values(value).some((item) => containsRuntimeReference(item, seen)) + seen.delete(value) + return contains +} + +// Like containsRuntimeReference, but sandbox standard-library values count as data: +// operators and switch treat them as ordinary object operands (identity equality, ToPrimitive +// coercion) rather than rejecting them as opaque interpreter machinery. +const containsOpaqueReference = (value: unknown, seen = new Set()): boolean => { + if (isSandboxValue(value)) return false + if (isRuntimeReference(value)) return true + if (value === null || typeof value !== "object") return false + if (seen.has(value)) return false + seen.add(value) + const contains = Array.isArray(value) + ? value.some((item) => containsOpaqueReference(item, seen)) + : Object.values(value).some((item) => containsOpaqueReference(item, seen)) + seen.delete(value) + return contains +} + +// `typeof` never throws in JS; map every interpreter value to its JS-visible category. +// A SandboxPromise falls through to the final `typeof value` and reports "object", exactly +// like a real JS promise. +const typeofValue = (value: unknown): string => { + if ( + value instanceof CodeModeFunction || + value instanceof CoercionFunction || + value instanceof IntrinsicReference || + value instanceof GlobalMethodReference || + value instanceof PromiseMethodReference || + value instanceof PromiseNamespace || + value instanceof ErrorConstructorReference + ) + return "function" + if (value instanceof UriFunction) return "function" + if (value instanceof ToolReference) return value.path.length > 0 ? "function" : "object" + if (value instanceof GlobalNamespace) { + return value.name === "Math" || value.name === "JSON" || value.name === "console" ? "object" : "function" + } + return typeof value +} + +// `x instanceof C` against the constructors CodeMode knows. Like `typeof`, it observes any +// left-hand value (opaque references included) without coercing it. Error checks use the +// error brand: `instanceof Error` accepts every branded error; a specific error type matches +// its own brand only (as in JS, where TypeError instances are also Error instances). +const instanceofValue = (lhs: unknown, rhs: unknown, node: AstNode): boolean => { + if (rhs instanceof ErrorConstructorReference) { + const brand = errorBrandName(lhs) + return brand !== undefined && (rhs.name === "Error" || brand === rhs.name) + } + if (rhs instanceof GlobalNamespace) { + switch (rhs.name) { + case "Date": + return lhs instanceof SandboxDate + case "RegExp": + return lhs instanceof SandboxRegExp + case "Map": + return lhs instanceof SandboxMap + case "Set": + return lhs instanceof SandboxSet + case "URL": + return lhs instanceof SandboxURL + case "URLSearchParams": + return lhs instanceof SandboxURLSearchParams + case "Array": + return Array.isArray(lhs) + case "Object": + return lhs !== null && (typeof lhs === "object" || typeofValue(lhs) === "function") + } + } + if (rhs instanceof PromiseNamespace) return lhs instanceof SandboxPromise + // Number/String/Boolean wrap primitives in JS; no boxed values exist in CodeMode, so + // `x instanceof Number` is always false - exactly what it is for primitives in JS. + if (rhs instanceof CoercionFunction && (rhs.name === "Number" || rhs.name === "String" || rhs.name === "Boolean")) { + return false + } + throw new InterpreterRuntimeError( + "The right-hand side of 'instanceof' must be a constructor CodeMode knows: Error (or a specific error type like TypeError), Date, RegExp, Map, Set, URL, URLSearchParams, Array, Object, or Promise.", + node, + ) +} + +const invokeStringMethod = (value: string, name: string, args: Array, node: AstNode): unknown => { + const str = (index: number): string => { + const arg = args[index] + if (typeof arg !== "string") + throw new InterpreterRuntimeError(`String.${name} expects argument ${index + 1} to be a string.`, node) + return arg + } + const num = (index: number): number => { + const arg = args[index] + if (typeof arg !== "number") + throw new InterpreterRuntimeError(`String.${name} expects argument ${index + 1} to be a number.`, node) + return arg + } + const optNum = (index: number): number | undefined => (args[index] === undefined ? undefined : num(index)) + const optStr = (index: number): string | undefined => (args[index] === undefined ? undefined : str(index)) + + let result: unknown + switch (name) { + case "toLowerCase": + result = value.toLowerCase() + break + case "toUpperCase": + result = value.toUpperCase() + break + case "trim": + result = value.trim() + break + // trimLeft/trimRight are the legacy aliases of trimStart/trimEnd, kept because models write them. + case "trimStart": + case "trimLeft": + result = value.trimStart() + break + case "trimEnd": + case "trimRight": + result = value.trimEnd() + break + // Locale/options arguments are ignored: comparison runs with the host default locale, and + // the common use is a sort comparator where any consistent order works. + case "localeCompare": + result = value.localeCompare(str(0)) + break + case "normalize": { + const form = optStr(0) + try { + result = value.normalize(form) + } catch { + throw new InterpreterRuntimeError( + `String.normalize expects the form "NFC", "NFD", "NFKC", or "NFKD" (got ${JSON.stringify(form)}).`, + node, + ).as("RangeError") + } + break + } + case "split": { + if (args.length === 0) { + result = [value] + break + } + if (args[0] instanceof SandboxRegExp) { + result = value.split((args[0] as SandboxRegExp).regex, optNum(1)) + break + } + const requestedLimit = optNum(1) + result = value.split(str(0), requestedLimit === undefined ? undefined : requestedLimit >>> 0) + break + } + case "slice": + result = value.slice(optNum(0), optNum(1)) + break + case "includes": + result = value.includes(str(0), optNum(1)) + break + case "startsWith": + result = value.startsWith(str(0), optNum(1)) + break + case "endsWith": + result = value.endsWith(str(0), optNum(1)) + break + case "indexOf": + result = value.indexOf(str(0), optNum(1)) + break + case "lastIndexOf": + result = value.lastIndexOf(str(0), optNum(1)) + break + case "replace": + case "replaceAll": { + if (args[0] instanceof SandboxRegExp) { + const pattern = (args[0] as SandboxRegExp).regex + const replacement = str(1) + if (name === "replaceAll" && !pattern.global) { + throw new InterpreterRuntimeError( + `String.replaceAll requires a regular expression with the global (g) flag: write /${pattern.source}/${pattern.flags}g, or use String.replace to replace only the first match.`, + node, + ) + } + result = name === "replace" ? value.replace(pattern, replacement) : value.replaceAll(pattern, replacement) + break + } + if (name === "replace") { + result = value.replace(str(0), str(1)) + break + } + result = value.replaceAll(str(0), str(1)) + break + } + case "match": { + const pattern = toHostRegex(args[0], name, node) + const matched = value.match(pattern) + if (matched === null) return null + // A global match is a plain array of matched strings; a non-global match carries + // index/groups own properties, so bypass the copying data checkpoint to keep them. + if (pattern.global) return boundedData(matched, "String.match result") + return matchToValue(matched) + } + case "matchAll": { + const pattern = toHostRegex(args[0], name, node, "g") + if (!pattern.global) { + throw new InterpreterRuntimeError( + `String.matchAll requires a regular expression with the global (g) flag: write /${pattern.source}/${pattern.flags}g, or use String.match for a single match.`, + node, + ) + } + // Materialized as an array (not an iterator); each entry is a match array with + // index/groups own properties. Match count is bounded by the subject length. + return Array.from(value.matchAll(pattern), matchToValue) + } + case "search": { + result = value.search(toHostRegex(args[0], name, node)) + break + } + case "repeat": { + const count = num(0) + if (!Number.isFinite(count) || count < 0) + throw new InterpreterRuntimeError("String.repeat expects a finite non-negative count.", node) + result = value.repeat(count) + break + } + case "padStart": + result = value.padStart(num(0), optStr(1)) + break + case "padEnd": + result = value.padEnd(num(0), optStr(1)) + break + case "charAt": + result = value.charAt(optNum(0) ?? 0) + break + case "at": + result = value.at(optNum(0) ?? 0) + break + case "substring": + result = value.substring(optNum(0) ?? 0, optNum(1)) + break + case "substr": + result = value.substr(optNum(0) ?? 0, optNum(1)) + break + // JS charCodeAt returns NaN out of range; NaN flows as an ordinary in-sandbox value + // (normalized to null only at the data boundary - see copyOut), so return it as-is. + case "charCodeAt": + result = value.charCodeAt(optNum(0) ?? 0) + break + case "codePointAt": + result = value.codePointAt(optNum(0) ?? 0) + break + case "toString": + result = value + break + case "concat": { + result = value.concat(...args.map((_, index) => str(index))) + break + } + default: + throw new InterpreterRuntimeError(`String method '${name}' is not available in CodeMode.`, node) + } + return boundedData(result, `String.${name} result`) +} + +const invokeArrayStatic = (name: string, args: Array, node: AstNode): unknown => { + switch (name) { + case "isArray": + return Array.isArray(args[0]) + case "of": + return [...args] + case "from": { + if (args.length > 1) { + throw new InterpreterRuntimeError( + "Array.from(...) does not support a map function in CodeMode; call .map() on the result instead.", + node, + "UnsupportedSyntax", + [supportedSyntaxMessage], + ) + } + // Map/Set materialize directly (the data checkpoint would serialize them to {}). + if (args[0] instanceof SandboxMap) + return Array.from((args[0] as SandboxMap).map.entries(), ([key, item]) => [key, item]) + if (args[0] instanceof SandboxSet) return Array.from((args[0] as SandboxSet).set.values()) + if (args[0] instanceof SandboxURLSearchParams) { + return Array.from(args[0].params.entries(), ([key, value]) => [key, value]) + } + const source = boundedData(args[0], "Array.from input") + if (typeof source === "string") return Array.from(source) + if (Array.isArray(source)) return [...source] + if ( + source !== null && + typeof source === "object" && + typeof (source as { length?: unknown }).length === "number" + ) { + return Array.from(source as ArrayLike) + } + throw new InterpreterRuntimeError("Array.from expects an array, string, Map, Set, or array-like value.", node) + } + default: + throw new InterpreterRuntimeError(`Array.${name} is not available in CodeMode.`, node) + } +} + +const invokeGlobalMethod = (ref: GlobalMethodReference, args: Array, node: AstNode): unknown => { + if (ref.namespace === "console") + throw new InterpreterRuntimeError(`console.${ref.name} is not available in CodeMode.`, node) + if (ref.namespace === "Object") return invokeObjectMethod(ref.name, args, node) + if (ref.namespace === "Math") return invokeMathMethod(ref.name, args, node) + if (ref.namespace === "Array") return invokeArrayStatic(ref.name, args, node) + if (ref.namespace === "Number") return invokeNumberStatic(ref.name, args, node) + if (ref.namespace === "String") return invokeStringStatic(ref.name, args, node) + if (ref.namespace === "URL") return invokeURLStatic(ref.name, args, node) + if (ref.namespace === "Date") { + if (!dateStatics.has(ref.name)) + throw new InterpreterRuntimeError(`Date.${ref.name} is not available in CodeMode.`, node) + return invokeDateStatic(ref.name, args, node) + } + if ( + ref.namespace === "RegExp" || + ref.namespace === "Map" || + ref.namespace === "Set" || + ref.namespace === "URLSearchParams" + ) { + throw new InterpreterRuntimeError(`${ref.namespace}.${ref.name} is not available in CodeMode.`, node) + } + return invokeJsonMethod(ref.name, args, node) +} + +// Every identifier a parameter pattern binds, used to seed TDZ slots before defaults run. +const collectPatternNames = (pattern: AstNode, out: Array = []): Array => { + switch (pattern.type) { + case "Identifier": + out.push(getString(pattern, "name")) + break + case "AssignmentPattern": + collectPatternNames(getNode(pattern, "left"), out) + break + case "RestElement": + collectPatternNames(getNode(pattern, "argument"), out) + break + case "ArrayPattern": + for (const element of getArray(pattern, "elements")) { + if (element !== null) collectPatternNames(asNode(element, "elements"), out) + } + break + case "ObjectPattern": + for (const property of getArray(pattern, "properties")) { + const prop = asNode(property, "properties") + collectPatternNames(prop.type === "RestElement" ? getNode(prop, "argument") : getNode(prop, "value"), out) + } + break + } + return out +} + +class Interpreter { + private scopes: Array> + private readonly invokeTool: (path: ReadonlyArray, args: Array) => Effect.Effect + // Enumerable namespace/tool names at a node of the host tool tree, threaded from + // ToolRuntime.make like invokeTool: the interpreter never holds the tree itself. + private readonly toolKeys: (path: ReadonlyArray) => ReadonlyArray + private readonly logs: Array + private lastValue: unknown + // Caps how many eagerly forked tool calls run at once (the parallel-call concurrency cap). + private readonly callPermits: Semaphore.Semaphore + // Fiber-backed promises whose settlement no program construct has observed yet. Successful + // program completion drains these (like a runtime waiting on in-flight work at exit) and + // surfaces a never-awaited failure as an unhandled-rejection diagnostic. + private readonly pendingSettlements = new Set() + + constructor( + invokeTool: (path: ReadonlyArray, args: Array) => Effect.Effect, + toolKeys: (path: ReadonlyArray) => ReadonlyArray, + logs: Array = [], + ) { + const globalScope = new Map() + this.scopes = [globalScope] + this.invokeTool = invokeTool + this.toolKeys = toolKeys + this.logs = logs + this.lastValue = undefined + this.callPermits = Semaphore.makeUnsafe(TOOL_CALL_CONCURRENCY) + globalScope.set("tools", { mutable: false, value: new ToolReference([]) }) + globalScope.set("Promise", { mutable: false, value: new PromiseNamespace() }) + globalScope.set("undefined", { mutable: false, value: undefined }) + globalScope.set("Object", { mutable: false, value: new GlobalNamespace("Object") }) + globalScope.set("Math", { mutable: false, value: new GlobalNamespace("Math") }) + globalScope.set("JSON", { mutable: false, value: new GlobalNamespace("JSON") }) + globalScope.set("Number", { mutable: false, value: new CoercionFunction("Number") }) + globalScope.set("String", { mutable: false, value: new CoercionFunction("String") }) + globalScope.set("Boolean", { mutable: false, value: new CoercionFunction("Boolean") }) + globalScope.set("Array", { mutable: false, value: new GlobalNamespace("Array") }) + globalScope.set("console", { mutable: false, value: new GlobalNamespace("console") }) + globalScope.set("parseInt", { mutable: false, value: new CoercionFunction("parseInt") }) + globalScope.set("parseFloat", { mutable: false, value: new CoercionFunction("parseFloat") }) + globalScope.set("Date", { mutable: false, value: new GlobalNamespace("Date") }) + globalScope.set("RegExp", { mutable: false, value: new GlobalNamespace("RegExp") }) + globalScope.set("Map", { mutable: false, value: new GlobalNamespace("Map") }) + globalScope.set("Set", { mutable: false, value: new GlobalNamespace("Set") }) + globalScope.set("URL", { mutable: false, value: new GlobalNamespace("URL") }) + globalScope.set("URLSearchParams", { mutable: false, value: new GlobalNamespace("URLSearchParams") }) + globalScope.set("encodeURI", { mutable: false, value: new UriFunction("encodeURI") }) + globalScope.set("encodeURIComponent", { mutable: false, value: new UriFunction("encodeURIComponent") }) + globalScope.set("decodeURI", { mutable: false, value: new UriFunction("decodeURI") }) + globalScope.set("decodeURIComponent", { mutable: false, value: new UriFunction("decodeURIComponent") }) + // Error constructors are real values, so `x instanceof Error` works and `Error("msg")` + // (with or without `new`) constructs a branded { name, message } error object. + for (const name of errorConstructors) { + globalScope.set(name, { mutable: false, value: new ErrorConstructorReference(name) }) + } + // NaN/Infinity flow as ordinary in-sandbox values (normalized to null only at the data + // boundary - see copyOut), so their global bindings must exist too, e.g. `reduce(max, -Infinity)`. + globalScope.set("NaN", { mutable: false, value: NaN }) + globalScope.set("Infinity", { mutable: false, value: Infinity }) + } + + run(program: ProgramNode): Effect.Effect { + const self = this + // Run the program body in its own module scope on top of the builtin global scope, so + // top-level declarations (`let undefined = 5`, `const Object = ...`) shadow builtins like + // JS module scope, instead of colliding with the seeded globals. + this.pushScope() + return Effect.gen(function* () { + self.hoistFunctions(program.body) + let value: unknown = undefined + let returned = false + for (const statement of program.body) { + const result = yield* self.evaluateStatement(statement) + + if (result.kind === "return") { + value = result.value + returned = true + break + } + + if (result.kind === "break" || result.kind === "continue") { + throw new InterpreterRuntimeError(`Unexpected '${result.kind}' outside of a loop.`, statement) + } + + if (result.kind === "value") { + self.lastValue = result.value + } + } + if (!returned) value = self.lastValue + + // The program body runs inside an implicit async function, so a returned promise + // resolves before crossing the data boundary - `return tools.ns.tool(...)` works + // without an explicit await, exactly as in JS. + if (value instanceof SandboxPromise) value = yield* self.settlePromise(value) + yield* self.drainPendingSettlements() + return value + }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) + } + + // Awaits every fiber-backed promise the program abandoned (fire-and-forget tool calls), so + // their work completes before the execution ends - mirroring a JS runtime waiting on + // in-flight I/O at exit. A failure nobody could have handled becomes an unhandled-rejection + // diagnostic (interrupted calls, e.g. Promise.race losers, are ignored). + private drainPendingSettlements(): Effect.Effect { + const self = this + return Effect.gen(function* () { + for (const promise of [...self.pendingSettlements]) { + const exit = yield* self.observePromise(promise) + if (Exit.isSuccess(exit) || Cause.hasInterruptsOnly(exit.cause)) continue + const failure = normalizeError(Cause.squash(exit.cause)) + throw new InterpreterRuntimeError( + `Unhandled rejection from an un-awaited tool call: ${failure.message}`, + undefined, + failure.kind, + ["Await tool calls - `const result = await tools.ns.tool(...)` - so failures can be caught and handled."], + ) + } + }) + } + + // Eagerly starts a tool call on a supervised child fiber (so the execution timeout and + // scope teardown interrupt it) gated by the concurrency semaphore, and wraps the fiber in a + // first-class promise value. `startImmediately` makes the runtime admit the call - charging + // the tool-call budget and firing onToolCallStart - at the call site, before any await. + private createToolCallPromise( + path: ReadonlyArray, + args: Array, + ): Effect.Effect { + const self = this + return Effect.map( + Effect.forkChild(this.callPermits.withPermit(Effect.suspend(() => self.invokeTool(path, args))), { + startImmediately: true, + }), + (fiber) => { + const promise = new SandboxPromise(fiber) + self.pendingSettlements.add(promise) + return promise + }, + ) + } + + // The promise's settlement as an Exit, marking it observed for unhandled-rejection tracking. + // Fiber settlement is idempotent, so observing the same promise repeatedly (await twice, + // Promise.all([p, p])) never re-runs the underlying call. + private observePromise(promise: SandboxPromise): Effect.Effect> { + this.pendingSettlements.delete(promise) + return promise.fiber !== undefined ? Fiber.await(promise.fiber) : Effect.exit(promise.immediate ?? Effect.void) + } + + // `await promise`: succeed with the fulfilled value or re-raise the failure so try/catch + // observes it exactly like a synchronous throw at the await site. + private settlePromise(promise: SandboxPromise, node?: AstNode): Effect.Effect { + const self = this + return Effect.flatMap(this.observePromise(promise), (exit) => self.unwrapPromiseExit(promise, exit, node)) + } + + private unwrapPromiseExit( + promise: SandboxPromise | undefined, + exit: Exit.Exit, + node?: AstNode, + ): Effect.Effect { + if (Exit.isSuccess(exit)) return Effect.succeed(exit.value) + // A call Promise.race interrupted after losing settles as a catchable program failure; + // any other interruption is execution teardown (timeout/host) and must keep propagating + // as interruption rather than becoming program-visible data. + if (promise?.interrupted === true && Cause.hasInterruptsOnly(exit.cause)) { + return Effect.fail( + new InterpreterRuntimeError( + "This tool call was interrupted because another value settled a Promise.race first.", + node, + ), + ) + } + return Effect.failCause(exit.cause) + } + + private evaluateStatement(node: AstNode): Effect.Effect { + switch (node.type) { + case "ExpressionStatement": + return Effect.map(this.evaluateExpression(getNode(node, "expression")), (value) => ({ kind: "value", value })) + case "VariableDeclaration": + return Effect.map(this.evaluateVariableDeclaration(node), () => ({ kind: "none" })) + case "ReturnStatement": { + const argumentNode = getOptionalNode(node, "argument") + return argumentNode + ? Effect.map(this.evaluateExpression(argumentNode), (value) => ({ kind: "return", value })) + : Effect.succeed({ kind: "return", value: undefined }) + } + case "BlockStatement": + return this.evaluateBlock(node) + case "IfStatement": + return this.evaluateIfStatement(node) + case "SwitchStatement": + return this.evaluateSwitchStatement(node) + case "WhileStatement": + return this.evaluateWhileStatement(node) + case "DoWhileStatement": + return this.evaluateDoWhileStatement(node) + case "ForStatement": + return this.evaluateForStatement(node) + case "ForOfStatement": + return this.evaluateForOfStatement(node) + case "ForInStatement": + return this.evaluateForInStatement(node) + case "BreakStatement": + return Effect.succeed(this.evaluateBreakStatement(node)) + case "ContinueStatement": + return Effect.succeed(this.evaluateContinueStatement(node)) + case "ThrowStatement": + return this.evaluateThrowStatement(node) + case "TryStatement": + return this.evaluateTryStatement(node) + case "EmptyStatement": + return Effect.succeed({ kind: "none" }) + case "FunctionDeclaration": + return Effect.succeed({ kind: "none" }) // bound ahead of time by hoistFunctions + default: + throw unsupportedSyntax(node.type, node) + } + } + + private evaluateBlock(node: AstNode): Effect.Effect { + this.pushScope() + const self = this + return Effect.gen(function* () { + const body = getArray(node, "body") + self.hoistFunctions(body) + + for (const statementValue of body) { + const statement = asNode(statementValue, "body") + const result = yield* self.evaluateStatement(statement) + + if (result.kind === "value") { + self.lastValue = result.value + continue + } + + if (result.kind !== "none") { + return result + } + } + + return { kind: "none" } satisfies StatementResult + }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) + } + + private createFunction(node: AstNode): CodeModeFunction { + if (node.generator === true) { + throw new InterpreterRuntimeError( + "Generator functions are not supported in CodeMode.", + node, + "UnsupportedSyntax", + [supportedSyntaxMessage], + ) + } + return new CodeModeFunction( + getArray(node, "params").map((parameter, index) => asNode(parameter, `params[${index}]`)), + getNode(node, "body"), + this.scopes.slice(), + ) + } + + // Function declarations are hoisted: bound in their scope before the body runs, so a + // program can call a helper defined further down (matching JavaScript). + private hoistFunctions(statements: Array): void { + for (const statementValue of statements) { + if (!isRecord(statementValue) || statementValue.type !== "FunctionDeclaration") continue + const node = statementValue as AstNode + this.declare(getString(getNode(node, "id"), "name"), this.createFunction(node), true, node) + } + } + + private evaluateIfStatement(node: AstNode): Effect.Effect { + const testNode = getNode(node, "test") + const consequentNode = getNode(node, "consequent") + const alternateNode = getOptionalNode(node, "alternate") + + return Effect.flatMap(this.evaluateExpression(testNode), (test) => + test + ? this.evaluateStatement(consequentNode) + : alternateNode + ? this.evaluateStatement(alternateNode) + : Effect.succeed({ kind: "none" }), + ) + } + + private evaluateSwitchStatement(node: AstNode): Effect.Effect { + const self = this + this.pushScope() + return Effect.gen(function* () { + const discriminant = yield* self.evaluateExpression(getNode(node, "discriminant")) + if (containsOpaqueReference(discriminant)) { + throw new InterpreterRuntimeError( + "Switch discriminants must be data values in CodeMode.", + node, + "InvalidDataValue", + ) + } + const cases = getArray(node, "cases").map((value, index) => asNode(value, `cases[${index}]`)) + let defaultIndex: number | undefined + let selected: number | undefined + for (const [index, branch] of cases.entries()) { + const test = getOptionalNode(branch, "test") + if (!test) { + defaultIndex = index + continue + } + const candidate = yield* self.evaluateExpression(test) + if (containsOpaqueReference(candidate)) { + throw new InterpreterRuntimeError( + "Switch case values must be data values in CodeMode.", + test, + "InvalidDataValue", + ) + } + if (candidate === discriminant) { + selected = index + break + } + } + const start = selected ?? defaultIndex + if (start === undefined) return { kind: "none" } satisfies StatementResult + for (let index = start; index < cases.length; index += 1) { + for (const statementValue of getArray(cases[index]!, "consequent")) { + const result = yield* self.evaluateStatement(asNode(statementValue, "consequent")) + if (result.kind === "break") return { kind: "none" } satisfies StatementResult + if (result.kind === "return" || result.kind === "continue") return result + if (result.kind === "value") self.lastValue = result.value + } + } + return { kind: "none" } satisfies StatementResult + }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) + } + + private evaluateWhileStatement(node: AstNode): Effect.Effect { + const testNode = getNode(node, "test") + const bodyNode = getNode(node, "body") + + const self = this + return Effect.gen(function* () { + while (yield* self.evaluateExpression(testNode)) { + const result = yield* self.evaluateStatement(bodyNode) + + if (result.kind === "continue") { + continue + } + + if (result.kind === "break") { + return { kind: "none" } satisfies StatementResult + } + + if (result.kind === "return") { + return result + } + + if (result.kind === "value") { + self.lastValue = result.value + } + } + + return { kind: "none" } satisfies StatementResult + }) + } + + private evaluateDoWhileStatement(node: AstNode): Effect.Effect { + const bodyNode = getNode(node, "body") + const testNode = getNode(node, "test") + + const self = this + return Effect.gen(function* () { + do { + const result = yield* self.evaluateStatement(bodyNode) + + if (result.kind === "continue") { + continue + } + + if (result.kind === "break") { + return { kind: "none" } satisfies StatementResult + } + + if (result.kind === "return") { + return result + } + + if (result.kind === "value") { + self.lastValue = result.value + } + } while (yield* self.evaluateExpression(testNode)) + + return { kind: "none" } satisfies StatementResult + }) + } + + private evaluateForStatement(node: AstNode): Effect.Effect { + this.pushScope() + const self = this + return Effect.gen(function* () { + const initNode = getOptionalNode(node, "init") + const testNode = getOptionalNode(node, "test") + const updateNode = getOptionalNode(node, "update") + const bodyNode = getNode(node, "body") + + if (initNode) { + if (initNode.type === "VariableDeclaration") { + yield* self.evaluateVariableDeclaration(initNode) + } else { + yield* self.evaluateExpression(initNode) + } + } + + const perIterationBindings = + initNode?.type === "VariableDeclaration" && getString(initNode, "kind") !== "var" + ? Array.from(self.currentScope().keys()) + : [] + + while (testNode ? yield* self.evaluateExpression(testNode) : true) { + let iterationScope: Map | undefined + if (perIterationBindings.length > 0) { + iterationScope = new Map( + perIterationBindings.map((name) => { + const binding = self.currentScope().get(name)! + return [name, { ...binding }] + }), + ) + self.scopes.push(iterationScope) + } + const result = yield* self.evaluateStatement(bodyNode).pipe( + Effect.ensuring( + Effect.sync(() => { + if (iterationScope) self.popScope() + }), + ), + ) + + if (result.kind === "return") { + return result + } + + if (result.kind === "break") { + return { kind: "none" } satisfies StatementResult + } + + if (result.kind === "value") { + self.lastValue = result.value + } + + if (iterationScope) { + const loopScope = self.currentScope() + for (const name of perIterationBindings) { + loopScope.set(name, { ...iterationScope.get(name)! }) + } + } + + if (updateNode) { + yield* self.evaluateExpression(updateNode) + } + + if (result.kind === "continue") { + continue + } + } + + return { kind: "none" } satisfies StatementResult + }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) + } + + private evaluateForOfStatement(node: AstNode): Effect.Effect { + if (getBoolean(node, "await")) { + throw new InterpreterRuntimeError("for await...of is not supported.", node) + } + + const self = this + return Effect.gen(function* () { + const left = getNode(node, "left") + const right = yield* self.evaluateExpression(getNode(node, "right")) + const body = getNode(node, "body") + + // Arrays iterate in place; strings iterate code points; Maps iterate [key, value] + // pairs and Sets iterate values over a snapshot (mutation during iteration is safe). + const iterable = Array.isArray(right) ? right : spreadItems(right) + if (iterable === undefined) { + throw new InterpreterRuntimeError("for...of requires an array, string, Map, or Set value in CodeMode.", node) + } + + let declaration: { readonly pattern: AstNode; readonly mutable: boolean } | undefined + let assignmentName: string | undefined + + if (left.type === "VariableDeclaration") { + const declarations = getArray(left, "declarations") + if (declarations.length !== 1) { + throw new InterpreterRuntimeError("for...of supports one declared binding.", left) + } + + const declarator = asNode(declarations[0], "declarations[0]") + declaration = { pattern: getNode(declarator, "id"), mutable: getString(left, "kind") !== "const" } + } else if (left.type === "Identifier") { + assignmentName = getString(left, "name") + } else { + throw new InterpreterRuntimeError("Unsupported for...of binding.", left) + } + + for (const value of iterable) { + if (declaration) { + self.pushScope() + yield* self.declarePattern(declaration.pattern, value, declaration.mutable, left) + } else if (assignmentName) { + self.setIdentifierValue(assignmentName, value, left) + } + + const result = yield* self.evaluateStatement(body).pipe( + Effect.ensuring( + Effect.sync(() => { + if (declaration) self.popScope() + }), + ), + ) + + if (result.kind === "return") { + return result + } + + if (result.kind === "break") { + return { kind: "none" } + } + + if (result.kind === "value") { + self.lastValue = result.value + } + + if (result.kind === "continue") { + continue + } + } + + return { kind: "none" } + }) + } + + // Own enumerable string keys of a value, shared by `for...in` and `Object.keys` over tool + // references: plain data objects enumerate their own keys, arrays their index strings (plus + // any own non-index properties, e.g. match results' index/groups - exactly Object.keys in + // JS), and a tool reference the namespace/tool names at its path in the host tool tree. + // Returns undefined for everything else so callers can raise a contextual error. + private enumerableKeys(value: unknown): Array | undefined { + if (value instanceof ToolReference) { + return [...this.toolKeys(value.path)] + } + if (Array.isArray(value)) { + return Object.keys(value) + } + if (value !== null && typeof value === "object" && !isRuntimeReference(value)) { + return Object.keys(value) + } + return undefined + } + + private evaluateForInStatement(node: AstNode): Effect.Effect { + const self = this + return Effect.gen(function* () { + const left = getNode(node, "left") + const right = yield* self.evaluateExpression(getNode(node, "right")) + const body = getNode(node, "body") + + // Keys are snapshotted up front (mutation during iteration is safe): plain objects + // enumerate their own keys, arrays their index strings, and tool references the + // namespace/tool names at that node - the same enumeration Object.keys performs. + // Anything else (strings, Maps, Sets, numbers, null, ...) is a deliberate error rather + // than real JS's surprising behavior (indices for strings, zero iterations for + // Maps/Sets/null): the hint points at the constructs that do what the program means. + const keys = self.enumerableKeys(right) + if (keys === undefined) { + throw new InterpreterRuntimeError( + "for...in requires a plain object, array, or tools reference in CodeMode. Use for...of for arrays/strings/Maps/Sets, or Object.keys(value) for a key list.", + node, + ) + } + + let declaration: { readonly pattern: AstNode; readonly mutable: boolean } | undefined + let assignmentName: string | undefined + + if (left.type === "VariableDeclaration") { + const declarations = getArray(left, "declarations") + if (declarations.length !== 1) { + throw new InterpreterRuntimeError("for...in supports one declared binding.", left) + } + + const declarator = asNode(declarations[0], "declarations[0]") + declaration = { pattern: getNode(declarator, "id"), mutable: getString(left, "kind") !== "const" } + } else if (left.type === "Identifier") { + assignmentName = getString(left, "name") + } else { + throw new InterpreterRuntimeError("Unsupported for...in binding.", left) + } + + for (const key of keys) { + if (declaration) { + self.pushScope() + yield* self.declarePattern(declaration.pattern, key, declaration.mutable, left) + } else if (assignmentName) { + self.setIdentifierValue(assignmentName, key, left) + } + + const result = yield* self.evaluateStatement(body).pipe( + Effect.ensuring( + Effect.sync(() => { + if (declaration) self.popScope() + }), + ), + ) + + if (result.kind === "return") { + return result + } + + if (result.kind === "break") { + return { kind: "none" } + } + + if (result.kind === "value") { + self.lastValue = result.value + } + + if (result.kind === "continue") { + continue + } + } + + return { kind: "none" } + }) + } + + private evaluateBreakStatement(node: AstNode): StatementResult { + const labelNode = getOptionalNode(node, "label") + + if (labelNode) { + throw new InterpreterRuntimeError("Labeled break is not supported in v1.", node) + } + + return { kind: "break" } + } + + private evaluateContinueStatement(node: AstNode): StatementResult { + const labelNode = getOptionalNode(node, "label") + + if (labelNode) { + throw new InterpreterRuntimeError("Labeled continue is not supported in v1.", node) + } + + return { kind: "continue" } + } + + private evaluateThrowStatement(node: AstNode): Effect.Effect { + const argument = getNode(node, "argument") + return Effect.flatMap(this.evaluateExpression(argument), (value) => Effect.fail(new ProgramThrow(value))) + } + + private evaluateTryStatement(node: AstNode): Effect.Effect { + const body = getNode(node, "block") + const handler = getOptionalNode(node, "handler") + const finalizer = getOptionalNode(node, "finalizer") + const self = this + + const attempted = Effect.matchCauseEffect(this.evaluateStatement(body), { + onFailure: (cause) => { + if (cause.reasons.some(Cause.isInterruptReason) || !handler) { + return Effect.failCause(cause) + } + + // The program sees a plain { message } error (or the thrown value itself) - see + // caughtErrorValue, shared with Promise.allSettled rejection reasons. + const caught = caughtErrorValue(Cause.squash(cause)) + const parameter = getOptionalNode(handler, "param") + self.pushScope() + return Effect.gen(function* () { + if (parameter) yield* self.declarePattern(parameter, caught, true, handler) + return yield* self.evaluateStatement(getNode(handler, "body")) + }).pipe(Effect.ensuring(Effect.sync(() => self.popScope()))) + }, + onSuccess: Effect.succeed, + }) + + if (!finalizer) return attempted + + const isAbrupt = (result: StatementResult): boolean => + result.kind === "return" || result.kind === "break" || result.kind === "continue" + + return Effect.matchCauseEffect(attempted, { + onFailure: (cause) => + cause.reasons.some(Cause.isInterruptReason) + ? Effect.failCause(cause) + : Effect.flatMap(this.evaluateStatement(finalizer), (final) => + isAbrupt(final) ? Effect.succeed(final) : Effect.failCause(cause), + ), + onSuccess: (result) => + Effect.flatMap(this.evaluateStatement(finalizer), (final) => + isAbrupt(final) ? Effect.succeed(final) : Effect.succeed(result), + ), + }) + } + + private evaluateVariableDeclaration(node: AstNode): Effect.Effect { + const kind = getString(node, "kind") + const declarations = getArray(node, "declarations") + const self = this + return Effect.gen(function* () { + for (const declarationValue of declarations) { + const declaration = asNode(declarationValue, "declarations") + + if (declaration.type !== "VariableDeclarator") { + throw new InterpreterRuntimeError("Unsupported variable declaration shape.", declaration) + } + + const init = getOptionalNode(declaration, "init") + const value = init ? yield* self.evaluateExpression(init) : undefined + yield* self.declarePattern(getNode(declaration, "id"), value, kind !== "const", declaration) + } + }) + } + + private declarePattern( + pattern: AstNode, + value: unknown, + mutable: boolean, + node: AstNode, + ): Effect.Effect { + const self = this + return Effect.gen(function* () { + if (pattern.type === "Identifier") { + self.declare(getString(pattern, "name"), value, mutable, node) + return + } + + // Default values: `x = expr` / `{ a = 1 }` - the default is evaluated only when the value is undefined. + if (pattern.type === "AssignmentPattern") { + const resolved = value === undefined ? yield* self.evaluateExpression(getNode(pattern, "right")) : value + yield* self.declarePattern(getNode(pattern, "left"), resolved, mutable, node) + return + } + + if (pattern.type === "ObjectPattern") { + if (value === null || typeof value !== "object" || Array.isArray(value) || isRuntimeReference(value)) { + throw new InterpreterRuntimeError( + "Object destructuring requires a data object value.", + pattern, + "InvalidDataValue", + ) + } + + const consumed = new Set() + for (const propertyValue of getArray(pattern, "properties")) { + const property = asNode(propertyValue, "properties") + + // Object rest: `{ a, ...others }` - gather the not-yet-consumed own keys. + if (property.type === "RestElement") { + const rest: SafeObject = Object.create(null) as SafeObject + for (const [key, item] of Object.entries(value as SafeObject)) { + if (!consumed.has(key) && !isBlockedMember(key)) rest[key] = item + } + yield* self.declarePattern(getNode(property, "argument"), rest, mutable, property) + continue + } + + if ( + property.type !== "Property" || + getBoolean(property, "computed") || + getString(property, "kind") !== "init" + ) { + throw new InterpreterRuntimeError("Only named object destructuring properties are supported.", property) + } + + const keyNode = getNode(property, "key") + const key = keyNode.type === "Identifier" ? getString(keyNode, "name") : String(keyNode.value) + if (isBlockedMember(key)) { + throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, keyNode) + } + consumed.add(key) + yield* self.declarePattern(getNode(property, "value"), (value as SafeObject)[key], mutable, property) + } + return + } + + if (pattern.type === "ArrayPattern") { + if (!Array.isArray(value)) { + throw new InterpreterRuntimeError("Array destructuring requires an array value.", pattern) + } + + for (const [index, item] of getArray(pattern, "elements").entries()) { + if (item === null) continue + const element = asNode(item, `elements[${index}]`) + // Array rest: `[head, ...tail]` - binds the remaining elements (must be last). + if (element.type === "RestElement") { + yield* self.declarePattern(getNode(element, "argument"), value.slice(index), mutable, element) + break + } + yield* self.declarePattern(element, value[index], mutable, pattern) + } + return + } + + throw new InterpreterRuntimeError(`Unsupported binding pattern '${pattern.type}'.`, pattern) + }) + } + + private evaluateExpression(node: AstNode): Effect.Effect { + switch (node.type) { + case "Literal": { + // A regex literal parses as a Literal node carrying { pattern, flags }; construct the + // sandbox regex from those (the host `value` instance is never exposed). + const regex = node.regex + if (isRecord(regex) && typeof regex.pattern === "string") { + return Effect.sync(() => + this.constructRegExp([regex.pattern, typeof regex.flags === "string" ? regex.flags : ""], node), + ) + } + return Effect.sync(() => boundedData(node.value, "Literal")) + } + case "Identifier": + return Effect.sync(() => this.getIdentifierValue(getString(node, "name"), node)) + case "BinaryExpression": + return this.evaluateBinaryExpression(node) + case "LogicalExpression": + return this.evaluateLogicalExpression(node) + case "UnaryExpression": + return this.evaluateUnaryExpression(node) + case "AssignmentExpression": + return this.evaluateAssignmentExpression(node) + case "CallExpression": + return this.evaluateCallExpression(node) + case "ArrowFunctionExpression": + case "FunctionExpression": + return Effect.sync(() => this.createFunction(node)) + case "MemberExpression": + return this.readMember(node) + case "ChainExpression": + return Effect.map(this.evaluateExpression(getNode(node, "expression")), (value) => + value === OptionalShortCircuit ? undefined : value, + ) + case "ObjectExpression": + return this.evaluateObjectExpression(node) + case "ArrayExpression": + return this.evaluateArrayExpression(node) + case "TemplateLiteral": + return this.evaluateTemplateLiteral(node) + case "ConditionalExpression": + return this.evaluateConditionalExpression(node) + case "UpdateExpression": + return this.evaluateUpdateExpression(node) + case "AwaitExpression": { + // `await` resolves a promise value; awaiting anything else is a passthrough no-op, + // matching real JS semantics for non-thenables. + const self = this + return Effect.flatMap(this.evaluateExpression(getNode(node, "argument")), (value) => + value instanceof SandboxPromise ? self.settlePromise(value, node) : Effect.succeed(value), + ) + } + case "NewExpression": + return this.evaluateNewExpression(node) + default: + throw unsupportedSyntax(node.type, node) + } + } + + private evaluateNewExpression(node: AstNode): Effect.Effect { + const callee = getNode(node, "callee") + if (callee.type !== "Identifier") { + throw unsupportedSyntax("NewExpression", node) + } + const name = getString(callee, "name") + const argNodes = getArray(node, "arguments") + const self = this + if (name === "Promise") { + throw new InterpreterRuntimeError( + "new Promise(...) is not supported in CodeMode; tool calls already return promises - call the tool and await the result.", + node, + "UnsupportedSyntax", + [supportedSyntaxMessage], + ) + } + if (errorConstructors.has(name)) { + return Effect.gen(function* () { + const arg = + argNodes.length > 0 ? yield* self.evaluateExpression(asNode(argNodes[0], "arguments[0]")) : undefined + return createErrorValue(name, arg === undefined ? "" : coerceToString(arg)) + }) + } + if (valueConstructors.has(name)) { + return Effect.gen(function* () { + const args = yield* self.evaluateCallArguments(argNodes) + switch (name) { + case "Date": + return self.constructDate(args) + case "RegExp": + return self.constructRegExp(args, node) + case "Map": + return self.constructMap(args[0], node) + case "Set": + return self.constructSet(args[0], node) + case "URL": + return self.constructURL(args, node) + default: + return self.constructURLSearchParams(args[0], node) + } + }) + } + throw unsupportedSyntax("NewExpression", node) + } + + private constructDate(args: Array): SandboxDate { + if (args.length === 0) return new SandboxDate(Date.now()) + if (args.length === 1) { + const arg = args[0] + if (arg instanceof SandboxDate) return new SandboxDate(arg.time) + if (typeof arg === "number") return new SandboxDate(new Date(arg).getTime()) + if (typeof arg === "string") return new SandboxDate(Date.parse(arg)) + return new SandboxDate(Number.NaN) + } + // new Date(year, month, day?, hours?, ...) - local-time component form. + const parts = args.map((arg) => coerceToNumber(arg)) + return new SandboxDate(new Date(...(parts as [number, number])).getTime()) + } + + private constructRegExp(args: Array, node: AstNode): SandboxRegExp { + const first = args[0] + const pattern = + first instanceof SandboxRegExp ? first.regex.source : first === undefined ? "" : coerceToString(first) + const flagsArg = args[1] + if (flagsArg !== undefined && typeof flagsArg !== "string") { + throw new InterpreterRuntimeError( + `RegExp flags must be a string of flag characters (e.g. "g", "gi"), not ${flagsArg === null ? "null" : typeof flagsArg}.`, + node, + ) + } + const flags = flagsArg ?? (first instanceof SandboxRegExp ? first.regex.flags : "") + try { + return new SandboxRegExp(pattern, flags) + } catch (error) { + // Say which part was rejected and how to fix it, instead of passing the engine + // message through bare. A flags failure names the flags; a pattern failure gets the + // escaping hint (the usual cause is an unescaped metacharacter in a built-up string). + const reason = regexFailureReason(error) + throw new InterpreterRuntimeError( + /flag/i.test(reason) + ? `new RegExp(...) received invalid flags ${JSON.stringify(flags)} (${reason}). Valid flags are d, g, i, m, s, u, v, and y.` + : `new RegExp(...) received ${JSON.stringify(pattern)}, which is not a valid regular expression pattern (${reason}). ${escapeRegexHint}`, + node, + ).as("SyntaxError") + } + } + + private constructMap(init: unknown, node: AstNode): SandboxMap { + const target = new SandboxMap() + if (init === undefined || init === null) return target + const entries = Array.isArray(init) + ? init + : init instanceof SandboxMap + ? Array.from(init.map.entries(), ([key, item]): Array => [key, item]) + : undefined + if (entries === undefined) { + throw new InterpreterRuntimeError( + "new Map(...) expects an array of [key, value] pairs, a Map, or no argument.", + node, + ) + } + for (const pair of entries) { + if (!Array.isArray(pair)) { + throw new InterpreterRuntimeError("new Map(...) expects [key, value] pairs.", node) + } + target.map.set(pair[0], pair[1]) + } + return target + } + + private constructSet(init: unknown, node: AstNode): SandboxSet { + const target = new SandboxSet() + if (init === undefined || init === null) return target + const items = Array.isArray(init) + ? init + : init instanceof SandboxSet + ? Array.from(init.set.values()) + : typeof init === "string" + ? Array.from(init) + : undefined + if (items === undefined) { + throw new InterpreterRuntimeError("new Set(...) expects an array, Set, string, or no argument.", node) + } + for (const item of items) target.set.add(item) + return target + } + + private constructURL(args: Array, node: AstNode): SandboxURL { + if (args.length === 0) { + throw new InterpreterRuntimeError("new URL(...) requires a URL string and an optional base URL.", node).as( + "TypeError", + ) + } + const input = urlArgument(args[0], "new URL input") + const base = args[1] === undefined ? undefined : urlArgument(args[1], "new URL base") + try { + return new SandboxURL(new URL(input, base)) + } catch { + throw new InterpreterRuntimeError( + `new URL(...) received an invalid URL${base === undefined ? "" : " or base URL"}.`, + node, + ).as("TypeError") + } + } + + private constructURLSearchParams(init: unknown, node: AstNode): SandboxURLSearchParams { + if (init === undefined) return new SandboxURLSearchParams(new URLSearchParams()) + if (init instanceof SandboxURLSearchParams) { + return new SandboxURLSearchParams(new URLSearchParams(init.params)) + } + if (typeof init === "string") return new SandboxURLSearchParams(new URLSearchParams(init)) + if (init === null || typeof init === "number" || typeof init === "boolean") { + return new SandboxURLSearchParams(new URLSearchParams(coerceToString(init))) + } + if (init instanceof SandboxMap) { + return this.constructURLSearchParams( + Array.from(init.map.entries(), ([key, value]) => [key, value]), + node, + ) + } + if (Array.isArray(init)) { + const entries = init.map((pair) => { + if (!Array.isArray(pair) || pair.length !== 2) { + throw new InterpreterRuntimeError( + "new URLSearchParams(...) expects an array of [name, value] pairs.", + node, + ).as("TypeError") + } + return [uriArgument(pair[0], "URLSearchParams name"), uriArgument(pair[1], "URLSearchParams value")] as [ + string, + string, + ] + }) + return new SandboxURLSearchParams(new URLSearchParams(entries)) + } + if (isSandboxValue(init)) return new SandboxURLSearchParams(new URLSearchParams()) + const data = boundedData(init, "new URLSearchParams input") + if (data === null || typeof data !== "object") { + throw new InterpreterRuntimeError( + "new URLSearchParams(...) expects a query string, data object, array of pairs, or URLSearchParams.", + node, + ).as("TypeError") + } + return new SandboxURLSearchParams( + new URLSearchParams(Object.fromEntries(Object.entries(data).map(([key, value]) => [key, coerceToString(value)]))), + ) + } + + private evaluateBinaryExpression(node: AstNode): Effect.Effect { + const operator = getString(node, "operator") + const self = this + return Effect.gen(function* () { + const lhs = yield* self.evaluateExpression(getNode(node, "left")) + const rhs = yield* self.evaluateExpression(getNode(node, "right")) + // Like `typeof`, `instanceof` observes any value without coercing it (a promise or + // function operand is a legitimate question, not an error), so it is handled before + // the data-only operand check. + if (operator === "instanceof") return instanceofValue(lhs, rhs, node) + return boundedData(self.applyBinaryOperator(operator, lhs, rhs, node), "Binary expression result") + }) + } + + /** + * Applies a binary operator to two already-evaluated operands with CodeMode's coercion + * semantics. Shared by binary expressions and compound assignment (`x op= y` must behave + * exactly like `x = x op y`, coercion included). + */ + private applyBinaryOperator(operator: string, lhs: unknown, rhs: unknown, node: AstNode): unknown { + if (containsOpaqueReference(lhs) || containsOpaqueReference(rhs)) { + throw new InterpreterRuntimeError("Binary operators require data values in CodeMode.", node, "InvalidDataValue") + } + // Data objects/arrays are null-prototype, so JS's ToPrimitive throws an opaque host + // "No default value" TypeError when an operator coerces them. Coerce to their JS string + // form first (as String(x) / template literals do) so operators behave like JavaScript. + // A Date follows its ToPrimitive hints: string for `+` (concatenation), its time value + // for arithmetic and ordering - so `end - start` and `a < b` work as in JS. + // Identity (=== / !==) and the right operand of `in` keep their raw object value. + const coerceOperand = (operand: unknown): unknown => { + if (operand instanceof SandboxDate) return operator === "+" ? coerceToString(operand) : operand.time + return operand !== null && typeof operand === "object" ? coerceToString(operand) : operand + } + const bothObjects = lhs !== null && typeof lhs === "object" && rhs !== null && typeof rhs === "object" + const l = coerceOperand(lhs) + const r = coerceOperand(rhs) + switch (operator) { + case "+": + return (l as string) + (r as string) + case "-": + return (l as number) - (r as number) + case "*": + return (l as number) * (r as number) + case "/": + return (l as number) / (r as number) + case "%": + return (l as number) % (r as number) + case "**": + return (l as number) ** (r as number) + // Two objects compare by identity in JS (no ToPrimitive); only object-vs-primitive coerces. + case "==": + return bothObjects ? lhs === rhs : l == r + case "===": + return lhs === rhs + case "!=": + return bothObjects ? lhs !== rhs : l != r + case "!==": + return lhs !== rhs + case "<": + return (l as string) < (r as string) + case "<=": + return (l as string) <= (r as string) + case ">": + return (l as string) > (r as string) + case ">=": + return (l as string) >= (r as string) + case "&": + return (l as number) & (r as number) + case "|": + return (l as number) | (r as number) + case "^": + return (l as number) ^ (r as number) + case "<<": + return (l as number) << (r as number) + case ">>": + return (l as number) >> (r as number) + case ">>>": + return (l as number) >>> (r as number) + case "in": + if (rhs === null || typeof rhs !== "object") { + throw new InterpreterRuntimeError("The 'in' operator requires a data object on the right-hand side.", node) + } + // Own properties only, so arrays don't leak the host Array.prototype (map/constructor/...). + return Object.hasOwn(rhs as object, coerceOperand(lhs) as PropertyKey) + default: + throw new InterpreterRuntimeError(`Unsupported binary operator '${operator}'.`, node) + } + } + + private evaluateLogicalExpression(node: AstNode): Effect.Effect { + const operator = getString(node, "operator") + return Effect.flatMap(this.evaluateExpression(getNode(node, "left")), (left) => { + if (operator === "&&") return left ? this.evaluateExpression(getNode(node, "right")) : Effect.succeed(left) + if (operator === "||") return left ? Effect.succeed(left) : this.evaluateExpression(getNode(node, "right")) + if (operator === "??") + return left !== null && left !== undefined + ? Effect.succeed(left) + : this.evaluateExpression(getNode(node, "right")) + throw new InterpreterRuntimeError(`Unsupported logical operator '${operator}'.`, node) + }) + } + + private evaluateUnaryExpression(node: AstNode): Effect.Effect { + const operator = getString(node, "operator") + const argument = getNode(node, "argument") + // `typeof undeclaredIdentifier` is `"undefined"` in JS (never a ReferenceError), so + // feature-detection guards like `typeof x !== "undefined"` don't crash. Short-circuit before + // evaluating the argument; a declared-but-TDZ binding still falls through to the normal throw. + if (operator === "typeof" && argument.type === "Identifier" && !this.resolveBinding(getString(argument, "name"))) { + return Effect.succeed("undefined") + } + return Effect.map(this.evaluateExpression(argument), (value) => { + // `typeof` and `!` never throw in JS - they observe any value (functions and runtime + // references included) without coercing it, so feature detection and negation work. + if (operator === "typeof") return typeofValue(value) + if (operator === "!") return !value + if (containsOpaqueReference(value)) { + throw new InterpreterRuntimeError("Unary operators require data values in CodeMode.", node, "InvalidDataValue") + } + // Numeric/bitwise unary operators ToPrimitive their operand; a Date yields its time value + // (`+date` is the epoch-ms idiom), other null-prototype data objects/arrays coerce to + // their JS string form first (see evaluateBinaryExpression). + const operand = + value instanceof SandboxDate + ? value.time + : value !== null && typeof value === "object" + ? coerceToString(value) + : value + let result: unknown + switch (operator) { + case "+": + result = +(operand as number) + break + case "-": + result = -(operand as number) + break + case "~": + result = ~(operand as number) + break + default: + throw new InterpreterRuntimeError(`Unsupported unary operator '${operator}'.`, node) + } + return boundedData(result, "Unary expression result") + }) + } + + private evaluateAssignmentExpression(node: AstNode): Effect.Effect { + const left = getNode(node, "left") + const operator = getString(node, "operator") + const self = this + return Effect.gen(function* () { + if (operator === "??=" || operator === "||=" || operator === "&&=") { + return yield* self.evaluateLogicalAssignment(node, left, operator) + } + const rightValue = yield* self.evaluateExpression(getNode(node, "right")) + if (left.type === "Identifier") { + const name = getString(left, "name") + if (operator === "=") return self.setIdentifierValue(name, rightValue, left) + const next = boundedData( + self.applyCompoundAssignment(operator, self.getIdentifierValue(name, left), rightValue, node), + "Assignment result", + ) + return self.setIdentifierValue(name, next, left) + } + if (left.type === "MemberExpression") { + if (operator === "=") return yield* self.writeMember(left, rightValue) + return yield* self.modifyMember(left, (current) => { + const next = boundedData( + self.applyCompoundAssignment(operator, current, rightValue, node), + "Assignment result", + ) + return Effect.succeed({ write: true, next, result: next }) + }) + } + throw new InterpreterRuntimeError("Assignment target must be an Identifier or MemberExpression.", left) + }) + } + + private evaluateLogicalAssignment( + node: AstNode, + left: AstNode, + operator: string, + ): Effect.Effect { + const self = this + const shouldAssign = (current: unknown): boolean => + operator === "??=" ? current === null || current === undefined : operator === "||=" ? !current : Boolean(current) + if (left.type === "Identifier") { + const name = getString(left, "name") + return Effect.gen(function* () { + const current = self.getIdentifierValue(name, left) + if (!shouldAssign(current)) return current + const rightValue = yield* self.evaluateExpression(getNode(node, "right")) + return self.setIdentifierValue(name, rightValue, left) + }) + } + if (left.type === "MemberExpression") { + // Resolve the member exactly once; evaluate the RHS only if we actually assign. + return self.modifyMember(left, (current) => + shouldAssign(current) + ? Effect.map(self.evaluateExpression(getNode(node, "right")), (rightValue) => ({ + write: true, + next: rightValue, + result: rightValue, + })) + : Effect.succeed({ write: false, next: current, result: current }), + ) + } + throw new InterpreterRuntimeError("Assignment target must be an Identifier or MemberExpression.", left) + } + + private evaluateUpdateExpression(node: AstNode): Effect.Effect { + const operator = getString(node, "operator") + const argument = getNode(node, "argument") + const prefix = getBoolean(node, "prefix") + + const increment = operator === "++" ? 1 : operator === "--" ? -1 : undefined + + if (increment === undefined) { + throw new InterpreterRuntimeError(`Unsupported update operator '${operator}'.`, node) + } + + if (argument.type === "Identifier") { + return Effect.sync(() => { + const name = getString(argument, "name") + const current = Number(this.getIdentifierValue(name, argument)) + const next = current + increment + this.setIdentifierValue(name, next, argument) + return prefix ? next : current + }) + } + + if (argument.type === "MemberExpression") { + return this.modifyMember(argument, (current) => { + const value = Number(current) + const next = value + increment + return Effect.succeed({ write: true, next, result: prefix ? next : value }) + }) + } + + throw new InterpreterRuntimeError("Update target must be an Identifier or MemberExpression.", argument) + } + + private evaluateCallExpression(node: AstNode): Effect.Effect { + const callee = getNode(node, "callee") + const argNodes = getArray(node, "arguments") + + const self = this + return Effect.gen(function* () { + const callable = yield* self.evaluateExpression(callee) + if (callable === OptionalShortCircuit) return OptionalShortCircuit + if ((callable === null || callable === undefined) && node.optional === true) return OptionalShortCircuit + + const args = yield* self.evaluateCallArguments(argNodes) + + if (callable instanceof ToolReference) { + if (callable.path.length === 0) throw new InterpreterRuntimeError("The tools root is not callable.", callee) + // An un-awaited tool call is a first-class promise value; the call itself starts now. + return yield* self.createToolCallPromise(callable.path, args) + } + if (callable instanceof PromiseMethodReference) { + return yield* self.invokePromiseMethod(callable, args, node) + } + if (callable instanceof CodeModeFunction) { + return yield* self.invokeFunction(callable, args) + } + if (callable instanceof IntrinsicReference) { + return yield* self.invokeIntrinsic(callable, args, node) + } + if (callable instanceof GlobalMethodReference) { + if (callable.namespace === "console") return self.invokeConsole(callable.name, args, node) + if (callable.namespace === "Object" && args[0] instanceof ToolReference) { + return self.invokeObjectMethodOnTools(callable.name, args[0] as ToolReference, node) + } + return boundedData(invokeGlobalMethod(callable, args, node), `${callable.namespace}.${callable.name} result`) + } + if (callable instanceof CoercionFunction) { + return boundedData(invokeCoercion(callable, args, node), `${callable.name} result`) + } + if (callable instanceof UriFunction) { + return invokeUriFunction(callable, args, node) + } + // `Error("msg")` without `new` constructs an error exactly like `new Error("msg")`, as in JS. + if (callable instanceof ErrorConstructorReference) { + return createErrorValue(callable.name, args[0] === undefined ? "" : coerceToString(args[0])) + } + throw new InterpreterRuntimeError("Only tools are callable in CodeMode.", callee) + }) + } + + // Object.* over a tool reference: `Object.keys(tools)` / `Object.keys(tools.ns)` enumerate + // namespace/tool names from the host tool tree - the discovery idiom a model reaches for + // first. Every other Object helper cannot produce data from a tool reference, so it fails + // with a pointer at the working idioms instead of the generic plain-objects-only message. + private invokeObjectMethodOnTools(name: string, ref: ToolReference, node: AstNode): unknown { + if (name === "keys") { + return boundedData(this.enumerableKeys(ref)!, "Object.keys result") + } + throw new InterpreterRuntimeError( + `Object.${name}(...) cannot read tool references: they are not plain data. Use Object.keys(tools) for names, or tools.$codemode.search({ query }) for signatures.`, + node, + "InvalidDataValue", + ) + } + + private invokeConsole(name: string, args: Array, node: AstNode): undefined { + if (!consoleMethods.has(name)) + throw new InterpreterRuntimeError(`console.${name} is not available in CodeMode.`, node) + this.logs.push(publicErrorMessage(this.formatConsoleMessage(name, args, node))) + return undefined + } + + private formatConsoleMessage(name: string, args: Array, node: AstNode): string { + if (name === "dir") return args.length === 0 ? "undefined" : this.formatConsoleArgument(args[0]) + if (name === "table") return this.formatConsoleTable(args[0], args[1], node) + const prefix = name === "warn" ? "[warn] " : name === "error" ? "[error] " : name === "debug" ? "[debug] " : "" + return `${prefix}${args.map((arg) => this.formatConsoleArgument(arg)).join(" ")}` + } + + // Console arguments format deeply and totally: values render as a debugger would show them + // rather than as boundary JSON - numbers keep NaN/Infinity (JSON would say null), sandbox + // values keep their friendly forms at ANY depth (ISO date, /regex/flags, Map(n) [...], + // Set(n) [...]), opaque runtime references become "[CodeMode reference]" markers in place, + // and plain objects/arrays render JSON-style. Formatting never fails the program: cycles + // render "[Circular]" and extreme depth degrades to "...". + private formatConsoleArgument(value: unknown): string { + if (value === undefined) return "undefined" + // A top-level string prints bare; nested strings are JSON-quoted (see formatConsoleValue). + if (typeof value === "string") return value + return this.formatConsoleValue(value, new Set(), 0) + } + + private formatConsoleValue(value: unknown, seen: Set, depth: number): string { + // Nested undefined renders as null, matching what JSON boundary output would show. + if (value === null || value === undefined) return "null" + if (typeof value === "string") return JSON.stringify(value) + // String(value) keeps NaN/Infinity/-Infinity readable; finite numbers match their JSON form. + if (typeof value === "number" || typeof value === "boolean") return String(value) + if (typeof value !== "object") return String(value) + if (value instanceof SandboxPromise) return "[Promise (await it to get its value)]" + if (value instanceof SandboxDate) return coerceToString(value) + if (value instanceof SandboxRegExp) return coerceToString(value) + if (value instanceof SandboxURL) return coerceToString(value) + if (value instanceof SandboxURLSearchParams) return coerceToString(value) + if (depth > MAX_CONSOLE_DEPTH) return "..." + if (seen.has(value)) return "[Circular]" + if (value instanceof SandboxMap) { + seen.add(value) + try { + const entries = Array.from(value.map.entries(), ([key, item]): Array => [key, item]) + return `Map(${value.map.size}) ${this.formatConsoleValue(entries, seen, depth + 1)}` + } finally { + seen.delete(value) + } + } + if (value instanceof SandboxSet) { + seen.add(value) + try { + return `Set(${value.set.size}) ${this.formatConsoleValue(Array.from(value.set.values()), seen, depth + 1)}` + } finally { + seen.delete(value) + } + } + if (isRuntimeReference(value)) return "[CodeMode reference]" + seen.add(value) + try { + if (Array.isArray(value)) { + return `[${value.map((item) => this.formatConsoleValue(item, seen, depth + 1)).join(",")}]` + } + return `{${Object.entries(value) + .map(([key, item]) => `${JSON.stringify(key)}:${this.formatConsoleValue(item, seen, depth + 1)}`) + .join(",")}}` + } finally { + seen.delete(value) + } + } + + private formatConsoleTable(value: unknown, columnsArgument: unknown, node: AstNode): string { + if (value === undefined) return "undefined" + // Sandbox values are legitimate table data (cells render their friendly forms); only + // truly opaque references (functions, tools, promises) collapse to the marker. + if (containsOpaqueReference(value)) return "[CodeMode reference]" + const data = boundedData(value, "console.table argument") + const columns = this.consoleTableColumns(columnsArgument, node) + const rows = this.consoleTableRows(data, columns) + const keys = columns ?? Array.from(new Set(rows.flatMap((row) => Object.keys(row.values)))) + const header = ["(index)", ...keys].join("\t") + return [ + header, + ...rows.map((row) => [row.index, ...keys.map((key) => this.formatConsoleTableCell(row.values[key]))].join("\t")), + ].join("\n") + } + + private consoleTableColumns(value: unknown, node: AstNode): ReadonlyArray | undefined { + if (value === undefined) return undefined + if (containsRuntimeReference(value)) return undefined + const columns = copyOut(copyIn(value, "console.table columns"), true) + return Array.isArray(columns) ? columns.map((column) => String(column)) : undefined + } + + private consoleTableRows( + data: unknown, + columns: ReadonlyArray | undefined, + ): Array<{ readonly index: string; readonly values: Record }> { + if (Array.isArray(data)) { + return data.map((item, index) => ({ index: String(index), values: this.consoleTableValues(item, columns) })) + } + if (data !== null && typeof data === "object" && !isSandboxValue(data)) { + return Object.entries(data).map(([index, item]) => ({ index, values: this.consoleTableValues(item, columns) })) + } + return [{ index: "0", values: { Value: data } }] + } + + private consoleTableValues(value: unknown, columns: ReadonlyArray | undefined): Record { + if (value !== null && typeof value === "object" && !Array.isArray(value) && !isSandboxValue(value)) { + const source = value as Record + if (columns !== undefined) return Object.fromEntries(columns.map((column) => [column, source[column]])) + return Object.fromEntries(Object.entries(source)) + } + return { Value: value } + } + + private formatConsoleTableCell(value: unknown): string { + if (value === undefined) return "" + if (typeof value === "string") return value + return this.formatConsoleValue(value, new Set(), 0) + } + + private evaluateCallArguments(argNodes: Array): Effect.Effect, unknown, R> { + const self = this + return Effect.gen(function* () { + const args: Array = [] + for (const [index, arg] of argNodes.entries()) { + const argNode = asNode(arg, `arguments[${index}]`) + if (argNode.type === "SpreadElement") { + const spread = yield* self.evaluateExpression(getNode(argNode, "argument")) + const items = spreadItems(spread) + if (items === undefined) + throw new InterpreterRuntimeError( + "Spread arguments require an array, string, Map, or Set in CodeMode.", + argNode, + ) + args.push(...items) + } else { + args.push(yield* self.evaluateExpression(argNode)) + } + } + return args + }) + } + + // Promise.* over ordinary runtime values. Combinators accept ANY array (or spreadable + // collection) mixing promise values and plain data - built inline, beforehand, via spread, + // whatever - because tool calls already run eagerly on their own fibers; the combinators + // only observe settlements. Joining is therefore sequential (no extra fibers) without + // costing parallelism, and the concurrency cap stays where the work is: the fork semaphore. + private invokePromiseMethod( + ref: PromiseMethodReference, + args: Array, + node: AstNode, + ): Effect.Effect { + const self = this + if (ref.name === "resolve") { + // Promise.resolve of a promise is that promise (JS flattens); anything else is a + // promise already fulfilled with the value. + const value = args[0] + return Effect.succeed( + value instanceof SandboxPromise ? value : new SandboxPromise(undefined, Effect.succeed(value)), + ) + } + if (ref.name === "reject") { + return Effect.sync(() => new SandboxPromise(undefined, Effect.fail(new ProgramThrow(args[0])))) + } + + const items = Array.isArray(args[0]) ? args[0] : spreadItems(args[0]) + if (items === undefined) { + throw new InterpreterRuntimeError( + `Promise.${ref.name} expects an array of promises or plain values (e.g. Promise.${ref.name}(items.map((item) => tools.ns.tool(item)))).`, + node, + ) + } + + switch (ref.name) { + case "all": { + // Mark every promise element observed up-front (Promise.all handles all of its + // members' failures, as in JS), then join in index order; the first failure rejects + // the whole call while unrelated in-flight members keep running. + const settles = items.map((item) => + item instanceof SandboxPromise ? this.settlePromise(item, node) : Effect.succeed(item), + ) + return Effect.gen(function* () { + const values: Array = [] + for (const settle of settles) values.push(yield* settle) + return values + }) + } + case "allSettled": { + const observations = items.map((item) => + item instanceof SandboxPromise + ? Effect.map(this.observePromise(item), (exit) => ({ promise: item as SandboxPromise | undefined, exit })) + : Effect.succeed({ promise: undefined as SandboxPromise | undefined, exit: Exit.succeed(item as unknown) }), + ) + return Effect.gen(function* () { + const outcomes: Array = [] + for (const observation of observations) { + const { exit, promise } = yield* observation + if (Exit.isSuccess(exit)) { + outcomes.push( + Object.assign(Object.create(null) as SafeObject, { status: "fulfilled", value: exit.value }), + ) + continue + } + const raceInterrupted = promise?.interrupted === true && Cause.hasInterruptsOnly(exit.cause) + if (Cause.hasInterruptsOnly(exit.cause) && !raceInterrupted) { + // Execution teardown (timeout/host interruption), not a program-level rejection. + return yield* Effect.failCause(exit.cause) + } + const thrown = raceInterrupted + ? new InterpreterRuntimeError( + "This tool call was interrupted because another value settled a Promise.race first.", + node, + ) + : Cause.squash(exit.cause) + outcomes.push( + Object.assign(Object.create(null) as SafeObject, { + status: "rejected", + reason: caughtErrorValue(thrown), + }), + ) + } + return outcomes + }) + } + case "race": { + if (items.length === 0) { + throw new InterpreterRuntimeError( + "Promise.race([]) would never settle; provide at least one promise or value.", + node, + ) + } + const observations = items.map((item, index) => + item instanceof SandboxPromise + ? Effect.map(this.observePromise(item), (exit) => ({ index, exit })) + : Effect.succeed({ index, exit: Exit.succeed(item as unknown) }), + ) + return Effect.gen(function* () { + // First settlement (fulfilled OR rejected) wins; the observations never fail, so + // racing them yields exactly that. Losing in-flight calls are then interrupted. + const winner = yield* Effect.raceAll(observations) + for (const [index, item] of items.entries()) { + if (index === winner.index || !(item instanceof SandboxPromise) || item.fiber === undefined) continue + item.interrupted = true + yield* Fiber.interrupt(item.fiber) + } + const winningItem = items[winner.index] + return yield* self.unwrapPromiseExit( + winningItem instanceof SandboxPromise ? winningItem : undefined, + winner.exit, + node, + ) + }) + } + } + } + + private invokeFunction(fn: CodeModeFunction, args: Array): Effect.Effect { + const self = this + return Effect.suspend(() => { + const savedScopes = self.scopes + self.scopes = [...fn.capturedScopes, new Map()] + const run = Effect.gen(function* () { + // Seed every parameter name into the scope as a TDZ slot first, so a default that + // references another parameter resolves to that (uninitialized) param rather than + // silently falling through to an outer binding of the same name - matching JS. + const paramScope = self.currentScope() + for (const parameter of fn.parameters) { + for (const name of collectPatternNames(parameter)) { + paramScope.set(name, { mutable: true, value: undefined, initialized: false }) + } + } + for (const [index, parameter] of fn.parameters.entries()) { + if (parameter.type === "RestElement") { + yield* self.declarePattern(getNode(parameter, "argument"), args.slice(index), true, parameter) + break + } + yield* self.declarePattern(parameter, args[index], true, parameter) + } + + if (fn.body.type === "BlockStatement") { + const result = yield* self.evaluateStatement(fn.body) + return result.kind === "return" || result.kind === "value" ? result.value : undefined + } + + return yield* self.evaluateExpression(fn.body) + }) + return run.pipe( + Effect.ensuring( + Effect.sync(() => { + self.scopes = savedScopes + }), + ), + ) + }) + } + + private invokeIntrinsic( + ref: IntrinsicReference, + args: Array, + node: AstNode, + ): Effect.Effect { + if (typeof ref.receiver === "string") { + if ( + (ref.name === "replace" || ref.name === "replaceAll") && + (args[1] instanceof CodeModeFunction || args[1] instanceof CoercionFunction || args[1] instanceof UriFunction) + ) { + return this.invokeStringReplacer(ref.receiver, ref.name, args, node) + } + return Effect.succeed(invokeStringMethod(ref.receiver, ref.name, args, node)) + } + if (typeof ref.receiver === "number") { + return Effect.succeed(invokeNumberMethod(ref.receiver, ref.name, args, node)) + } + if (Array.isArray(ref.receiver)) { + return this.invokeArrayMethod(ref.receiver, ref.name, args, node) + } + if (ref.receiver instanceof SandboxDate) { + return Effect.succeed(invokeDateMethod(ref.receiver, ref.name, node)) + } + if (ref.receiver instanceof SandboxRegExp) { + return Effect.succeed(invokeRegExpMethod(ref.receiver, ref.name, args, node)) + } + if (ref.receiver instanceof SandboxMap) { + return this.invokeMapMethod(ref.receiver, ref.name, args, node) + } + if (ref.receiver instanceof SandboxSet) { + return this.invokeSetMethod(ref.receiver, ref.name, args, node) + } + if (ref.receiver instanceof SandboxURL) { + return Effect.succeed(invokeURLMethod(ref.receiver, ref.name, node)) + } + if (ref.receiver instanceof SandboxURLSearchParams) { + return this.invokeURLSearchParamsMethod(ref.receiver, ref.name, args, node) + } + throw new InterpreterRuntimeError(`Method '${ref.name}' is not available in CodeMode.`, node) + } + + private invokeStringReplacer( + value: string, + name: "replace" | "replaceAll", + args: Array, + node: AstNode, + ): Effect.Effect { + const apply = this.applyCollectionCallback(args[1], `String.${name}`, node) + const matches: Array<{ readonly match: string; readonly offset: number; readonly args: Array }> = [] + const collect = (...callbackArgs: Array): string => { + const match = callbackArgs[0] + const groups = callbackArgs[callbackArgs.length - 1] + const hasGroups = groups !== null && typeof groups === "object" + const offset = callbackArgs[callbackArgs.length - (hasGroups ? 3 : 2)] + if (typeof match !== "string" || typeof offset !== "number") { + throw new InterpreterRuntimeError(`String.${name} produced an invalid replacement match.`, node) + } + if (hasGroups) { + const safeGroups: SafeObject = Object.create(null) as SafeObject + for (const [key, group] of Object.entries(groups)) { + if (!isBlockedMember(key)) safeGroups[key] = group + } + callbackArgs[callbackArgs.length - 1] = safeGroups + } + matches.push({ match, offset, args: callbackArgs }) + return match + } + + const pattern = args[0] + if (pattern instanceof SandboxRegExp) { + if (name === "replaceAll" && !pattern.regex.global) { + throw new InterpreterRuntimeError( + `String.replaceAll requires a regular expression with the global (g) flag: write /${pattern.regex.source}/${pattern.regex.flags}g, or use String.replace to replace only the first match.`, + node, + ) + } + if (name === "replace") value.replace(pattern.regex, collect) + else value.replaceAll(pattern.regex, collect) + } else { + if (typeof pattern !== "string") { + throw new InterpreterRuntimeError(`String.${name} expects argument 1 to be a string.`, node) + } + if (name === "replace") value.replace(pattern, collect) + else value.replaceAll(pattern, collect) + } + + return Effect.gen(function* () { + const output: Array = [] + let end = 0 + for (const match of matches) { + output.push( + value.slice(end, match.offset), + coerceToString(boundedData(yield* apply(match.args), `String.${name} replacer result`)), + ) + end = match.offset + match.match.length + } + output.push(value.slice(end)) + return boundedData(output.join(""), `String.${name} result`) + }) + } + + // Runs a collection callback accepting a user function or supported builtin callable, + // mirroring the array-method callback contract. + private applyCollectionCallback( + callback: unknown, + name: string, + node: AstNode, + ): (args: Array) => Effect.Effect { + if ( + !(callback instanceof CodeModeFunction) && + !(callback instanceof CoercionFunction) && + !(callback instanceof UriFunction) + ) { + throw new InterpreterRuntimeError(`${name} expects a function callback.`, node) + } + return (callbackArgs) => + callback instanceof CoercionFunction + ? Effect.succeed(invokeCoercion(callback, callbackArgs, node)) + : callback instanceof UriFunction + ? Effect.succeed(invokeUriFunction(callback, callbackArgs, node)) + : this.invokeFunction(callback, callbackArgs) + } + + private invokeMapMethod( + target: SandboxMap, + name: string, + args: Array, + node: AstNode, + ): Effect.Effect { + switch (name) { + case "get": + return Effect.succeed(target.map.get(args[0])) + case "has": + return Effect.succeed(target.map.has(args[0])) + case "set": + return Effect.sync(() => { + target.map.set(args[0], args[1]) + return target + }) + case "delete": + return Effect.sync(() => target.map.delete(args[0])) + case "clear": + return Effect.sync(() => { + target.map.clear() + return undefined + }) + case "keys": + return Effect.sync(() => Array.from(target.map.keys())) + case "values": + return Effect.sync(() => Array.from(target.map.values())) + case "entries": + return Effect.sync(() => Array.from(target.map.entries(), ([key, item]): Array => [key, item])) + case "forEach": { + const apply = this.applyCollectionCallback(args[0], "Map.forEach", node) + return Effect.gen(function* () { + // Snapshot iteration, matching the array-method callback contract. + for (const [key, item] of Array.from(target.map.entries())) yield* apply([item, key, target]) + return undefined + }) + } + default: + throw new InterpreterRuntimeError(`Map method '${name}' is not available in CodeMode.`, node) + } + } + + private invokeSetMethod( + target: SandboxSet, + name: string, + args: Array, + node: AstNode, + ): Effect.Effect { + switch (name) { + case "has": + return Effect.succeed(target.set.has(args[0])) + case "add": + return Effect.sync(() => { + target.set.add(args[0]) + return target + }) + case "delete": + return Effect.sync(() => target.set.delete(args[0])) + case "clear": + return Effect.sync(() => { + target.set.clear() + return undefined + }) + case "keys": + case "values": + return Effect.sync(() => Array.from(target.set.values())) + case "entries": + return Effect.sync(() => Array.from(target.set.values(), (item): Array => [item, item])) + case "forEach": { + const apply = this.applyCollectionCallback(args[0], "Set.forEach", node) + return Effect.gen(function* () { + for (const item of Array.from(target.set.values())) yield* apply([item, item, target]) + return undefined + }) + } + default: + throw new InterpreterRuntimeError(`Set method '${name}' is not available in CodeMode.`, node) + } + } + + private invokeURLSearchParamsMethod( + target: SandboxURLSearchParams, + name: string, + args: Array, + node: AstNode, + ): Effect.Effect { + const arg = (index: number): string => uriArgument(args[index], `URLSearchParams.${name} argument ${index + 1}`) + const requireArgs = (count: number): void => { + if (args.length < count) { + throw new InterpreterRuntimeError( + `URLSearchParams.${name} requires ${count} argument${count === 1 ? "" : "s"}.`, + node, + ).as("TypeError") + } + } + switch (name) { + case "append": { + requireArgs(2) + return Effect.sync(() => { + target.params.append(arg(0), arg(1)) + return undefined + }) + } + case "delete": { + requireArgs(1) + return Effect.sync(() => { + if (args[1] !== undefined) target.params.delete(arg(0), arg(1)) + else target.params.delete(arg(0)) + return undefined + }) + } + case "get": + requireArgs(1) + return Effect.sync(() => target.params.get(arg(0))) + case "getAll": + requireArgs(1) + return Effect.sync(() => target.params.getAll(arg(0))) + case "has": + requireArgs(1) + return Effect.sync(() => + args[1] !== undefined ? target.params.has(arg(0), arg(1)) : target.params.has(arg(0)), + ) + case "set": { + requireArgs(2) + return Effect.sync(() => { + target.params.set(arg(0), arg(1)) + return undefined + }) + } + case "sort": + return Effect.sync(() => { + target.params.sort() + return undefined + }) + case "keys": + return Effect.sync(() => Array.from(target.params.keys())) + case "values": + return Effect.sync(() => Array.from(target.params.values())) + case "entries": + return Effect.sync(() => Array.from(target.params.entries(), ([key, value]): Array => [key, value])) + case "toString": + return Effect.sync(() => target.params.toString()) + case "forEach": { + requireArgs(1) + const apply = this.applyCollectionCallback(args[0], "URLSearchParams.forEach", node) + return Effect.gen(function* () { + for (const [key, value] of Array.from(target.params.entries())) yield* apply([value, key, target]) + return undefined + }) + } + default: + throw new InterpreterRuntimeError(`URLSearchParams method '${name}' is not available in CodeMode.`, node) + } + } + + private invokeArrayMethod( + target: Array, + name: string, + args: Array, + node: AstNode, + ): Effect.Effect { + const optNumber = (value: unknown, label: string): number | undefined => { + if (value === undefined) return undefined + if (typeof value !== "number") + throw new InterpreterRuntimeError(`Array.${name} expects ${label} to be a number.`, node) + return value + } + switch (name) { + case "join": { + if (args.length > 1 || (args.length === 1 && typeof args[0] !== "string")) { + throw new InterpreterRuntimeError("Array.join expects zero arguments or one string separator.", node) + } + const input = boundedData(target, "Array.join input") as Array + return Effect.succeed( + input.map((item) => coerceToString(item ?? "")).join(args.length === 0 ? "," : (args[0] as string)), + ) + } + case "includes": + if (args.length === 0 || args.length > 2) + throw new InterpreterRuntimeError("Array.includes expects a value and optional start index.", node) + return Effect.succeed(target.includes(args[0], optNumber(args[1], "start index"))) + case "indexOf": + return Effect.succeed(target.indexOf(args[0], optNumber(args[1], "start index"))) + case "lastIndexOf": + return Effect.succeed( + args[1] === undefined + ? target.lastIndexOf(args[0]) + : target.lastIndexOf(args[0], optNumber(args[1], "start index")), + ) + case "at": + return Effect.succeed(target.at(optNumber(args[0], "index") ?? 0)) + case "slice": + return Effect.succeed(target.slice(optNumber(args[0], "start"), optNumber(args[1], "end"))) + case "concat": + return Effect.succeed(target.concat(...args)) + case "flat": + return Effect.succeed(target.flat(optNumber(args[0], "depth") ?? 1)) + case "reverse": + return Effect.succeed([...target].reverse()) + case "sort": + case "toSorted": + return this.sortArray(target, args[0], node) + case "toReversed": + return Effect.succeed([...target].reverse()) + case "with": { + const index = optNumber(args[0], "index") ?? 0 + const resolved = index < 0 ? target.length + index : index + if (resolved < 0 || resolved >= target.length) { + throw new InterpreterRuntimeError("Array.with index is out of range.", node) + } + const copied = [...target] + copied[resolved] = args[1] + return Effect.succeed(copied) + } + case "push": { + // Validate before mutating (so no rollback is needed): inserting a container into + // itself would create a cycle no later walk could survive. + for (const item of args) this.rejectCircularInsertion(target, item, "Array.push result", node) + target.push(...args) + return Effect.succeed(target.length) + } + case "unshift": { + for (const item of args) this.rejectCircularInsertion(target, item, "Array.unshift result", node) + target.unshift(...args) + return Effect.succeed(target.length) + } + case "pop": + return Effect.succeed(target.pop()) + case "shift": + return Effect.succeed(target.shift()) + case "splice": { + // Mutates in place and returns the removed elements, exactly like JS: one argument + // removes to the end, an undefined delete count removes nothing. + if (args.length === 0) return Effect.succeed(target.splice(0, 0)) + const start = optNumber(args[0], "start") ?? 0 + if (args.length === 1) return Effect.succeed(target.splice(start)) + const deleteCount = optNumber(args[1], "delete count") ?? 0 + const inserted = args.slice(2) + for (const item of inserted) this.rejectCircularInsertion(target, item, "Array.splice result", node) + return Effect.succeed(target.splice(start, deleteCount, ...inserted)) + } + case "fill": { + this.rejectCircularInsertion(target, args[0], "Array.fill result", node) + return Effect.succeed(target.fill(args[0], optNumber(args[1], "start"), optNumber(args[2], "end"))) + } + case "copyWithin": + return Effect.succeed( + target.copyWithin( + optNumber(args[0], "target index") ?? 0, + optNumber(args[1], "start") ?? 0, + optNumber(args[2], "end"), + ), + ) + // keys/values/entries return arrays (not iterators), matching the Map/Set convention; + // they work with for...of and spread either way. + case "keys": + return Effect.succeed(Array.from(target.keys())) + case "values": + return Effect.succeed([...target]) + case "entries": + return Effect.succeed(Array.from(target.entries(), ([index, item]): Array => [index, item])) + } + + const callback = args[0] + if ( + !(callback instanceof CodeModeFunction) && + !(callback instanceof CoercionFunction) && + !(callback instanceof UriFunction) + ) { + throw new InterpreterRuntimeError(`Array.${name} expects a function callback.`, node) + } + const self = this + // Accept a user function or supported builtin callable, so idioms such as + // `filter(Boolean)`, `map(String)`, and `map(encodeURIComponent)` work as in JS. Builtins + // are synchronous; only CodeModeFunctions can await tool calls. + const apply = (callbackArgs: Array): Effect.Effect => + callback instanceof CoercionFunction + ? Effect.succeed(invokeCoercion(callback, callbackArgs, node)) + : callback instanceof UriFunction + ? Effect.succeed(invokeUriFunction(callback, callbackArgs, node)) + : self.invokeFunction(callback, callbackArgs) + return Effect.gen(function* () { + // Iterate a snapshot taken at call time so a callback that mutates the array can't + // self-extend the loop - matching JS, where elements appended during iteration are not visited. + const items = target.slice() + switch (name) { + case "map": { + const values: Array = [] + for (const [index, item] of items.entries()) values.push(yield* apply([item, index, items])) + return values + } + case "flatMap": { + const values: Array = [] + for (const [index, item] of items.entries()) { + const mapped = yield* apply([item, index, items]) + if (Array.isArray(mapped)) values.push(...mapped) + else values.push(mapped) + } + return values + } + case "filter": { + const values: Array = [] + for (const [index, item] of items.entries()) { + if (yield* apply([item, index, items])) values.push(item) + } + return values + } + case "find": + for (const [index, item] of items.entries()) { + if (yield* apply([item, index, items])) return item + } + return undefined + case "findIndex": + for (const [index, item] of items.entries()) { + if (yield* apply([item, index, items])) return index + } + return -1 + case "some": + for (const [index, item] of items.entries()) { + if (yield* apply([item, index, items])) return true + } + return false + case "every": + for (const [index, item] of items.entries()) { + if (!(yield* apply([item, index, items]))) return false + } + return true + case "forEach": + for (const [index, item] of items.entries()) yield* apply([item, index, items]) + return undefined + case "reduce": { + let accumulator: unknown + let start: number + if (args.length >= 2) { + accumulator = args[1] + start = 0 + } else { + if (items.length === 0) + throw new InterpreterRuntimeError("Array.reduce of an empty array with no initial value.", node) + accumulator = items[0] + start = 1 + } + for (let index = start; index < items.length; index += 1) { + accumulator = yield* apply([accumulator, items[index], index, items]) + } + return accumulator + } + case "reduceRight": { + let accumulator: unknown + let start: number + if (args.length >= 2) { + accumulator = args[1] + start = items.length - 1 + } else { + if (items.length === 0) + throw new InterpreterRuntimeError("Array.reduceRight of an empty array with no initial value.", node) + accumulator = items[items.length - 1] + start = items.length - 2 + } + for (let index = start; index >= 0; index -= 1) { + accumulator = yield* apply([accumulator, items[index], index, items]) + } + return accumulator + } + case "findLast": + for (let index = items.length - 1; index >= 0; index -= 1) { + if (yield* apply([items[index], index, items])) return items[index] + } + return undefined + case "findLastIndex": + for (let index = items.length - 1; index >= 0; index -= 1) { + if (yield* apply([items[index], index, items])) return index + } + return -1 + } + throw new InterpreterRuntimeError(`Array method '${name}' is not available in CodeMode.`, node) + }) + } + + private sortArray( + target: Array, + comparator: unknown, + node: AstNode, + ): Effect.Effect, unknown, R> { + if (comparator !== undefined && !(comparator instanceof CodeModeFunction)) { + throw new InterpreterRuntimeError("Array.sort expects an arrow function comparator.", node) + } + if (!(comparator instanceof CodeModeFunction)) { + return Effect.sync(() => + [...target].sort((a, b) => { + const left = coerceToString(a) + const right = coerceToString(b) + return left < right ? -1 : left > right ? 1 : 0 + }), + ) + } + const self = this + const mergeSort = (items: Array): Effect.Effect, unknown, R> => { + if (items.length <= 1) return Effect.succeed(items) + const midpoint = Math.floor(items.length / 2) + return Effect.gen(function* () { + const left = yield* mergeSort(items.slice(0, midpoint)) + const right = yield* mergeSort(items.slice(midpoint)) + const merged: Array = [] + let leftIndex = 0 + let rightIndex = 0 + while (leftIndex < left.length && rightIndex < right.length) { + // Coerce the comparator's result like JS ToNumber (data objects -> NaN, never a host + // crash) and treat NaN as 0 - the spec's "no consistent order" -> keep the left element. + const order = coerceToNumber(yield* self.invokeFunction(comparator, [left[leftIndex], right[rightIndex]])) + if (Number.isNaN(order) || order <= 0) merged.push(left[leftIndex++]) + else merged.push(right[rightIndex++]) + } + return [...merged, ...left.slice(leftIndex), ...right.slice(rightIndex)] + }) + } + // Per spec, undefined elements sort to the end and the comparator is never called on them. + const defined = target.filter((item) => item !== undefined) + const undefinedCount = target.length - defined.length + return Effect.map(mergeSort(defined), (items) => [...items, ...Array(undefinedCount).fill(undefined)]) + } + + private evaluateObjectExpression(node: AstNode): Effect.Effect, unknown, R> { + const objectValue: Record = Object.create(null) as Record + const properties = getArray(node, "properties") + const self = this + return Effect.gen(function* () { + for (const propertyValue of properties) { + const property = asNode(propertyValue, "properties") + + if (property.type === "SpreadElement") { + const spread = yield* self.evaluateExpression(getNode(property, "argument")) + // JS treats `{ ...null }` / `{ ...undefined }` as a no-op, so the common + // `{ ...maybeOpts, override }` merge works when the operand is absent. Sandbox values + // have no own enumerable properties in JS, so they are no-ops too. + if (spread === null || spread === undefined || isSandboxValue(spread)) continue + if (typeof spread !== "object" || Array.isArray(spread) || isRuntimeReference(spread)) { + throw new InterpreterRuntimeError( + "Object spread requires a data object in CodeMode.", + property, + "InvalidDataValue", + ) + } + for (const [key, value] of Object.entries(spread)) { + if (isBlockedMember(key)) + throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, property) + objectValue[key] = value + } + continue + } + + if (property.type !== "Property") { + throw new InterpreterRuntimeError("Only standard object properties are supported.", property) + } + + if (getString(property, "kind") !== "init") { + throw new InterpreterRuntimeError("Only init object properties are supported.", property) + } + + const keyNode = getNode(property, "key") + const valueNode = getNode(property, "value") + const computed = getBoolean(property, "computed") + + let key: PropertyKey + + if (computed) { + key = self.toPropertyKey(yield* self.evaluateExpression(keyNode), keyNode) + } else if (keyNode.type === "Identifier") { + key = getString(keyNode, "name") + } else if (keyNode.type === "Literal") { + key = self.toPropertyKey(keyNode.value, keyNode) + } else { + throw new InterpreterRuntimeError("Unsupported object property key shape.", keyNode) + } + + if (isBlockedMember(String(key))) { + throw new InterpreterRuntimeError(`Property '${String(key)}' is not available in CodeMode.`, keyNode) + } + objectValue[String(key)] = yield* self.evaluateExpression(valueNode) + } + + return objectValue + }) + } + + private evaluateArrayExpression(node: AstNode): Effect.Effect, unknown, R> { + const elements = getArray(node, "elements") + const values: Array = [] + + const self = this + return Effect.gen(function* () { + for (const elementValue of elements) { + if (elementValue === null) { + values.push(undefined) + continue + } + const element = asNode(elementValue, "elements") + if (element.type === "SpreadElement") { + const spread = yield* self.evaluateExpression(getNode(element, "argument")) + const items = spreadItems(spread) + if (items === undefined) + throw new InterpreterRuntimeError( + "Array spread requires an array, string, Map, or Set in CodeMode.", + element, + ) + values.push(...items) + } else { + values.push(yield* self.evaluateExpression(element)) + } + } + return values + }) + } + + private evaluateTemplateLiteral(node: AstNode): Effect.Effect { + const quasis = getArray(node, "quasis") + const expressions = getArray(node, "expressions") + + let output = "" + + const self = this + return Effect.gen(function* () { + for (let index = 0; index < quasis.length; index += 1) { + const quasi = asNode(quasis[index], "quasis") + const rawValue = quasi.value + + if (!isRecord(rawValue) || typeof rawValue.cooked !== "string") { + throw new InterpreterRuntimeError("Invalid template literal quasi.", quasi) + } + + output += rawValue.cooked + + if (index < expressions.length) { + const raw = yield* self.evaluateExpression(asNode(expressions[index], "expressions")) + // The preserving checkpoint keeps sandbox values intact, so coerceToString renders + // them directly (ISO date, /regex/ literal form) instead of a JSON-serialized husk. + output += coerceToString(boundedData(raw, "Template interpolation")) + } + } + + return output + }) + } + + private evaluateConditionalExpression(node: AstNode): Effect.Effect { + return Effect.flatMap(this.evaluateExpression(getNode(node, "test")), (test) => + this.evaluateExpression(getNode(node, test ? "consequent" : "alternate")), + ) + } + + private applyCompoundAssignment(operator: string, current: unknown, incoming: unknown, node: AstNode): unknown { + // `x op= y` is `x = x op y`: dispatch through the shared binary operator implementation + // so compound assignment inherits the same coercion semantics (Dates, data objects, ...). + // Only the arithmetic/bitwise operators are compoundable; logical assignments (&&=/||=/??=) + // short-circuit and are handled by evaluateLogicalAssignment before reaching here. + if (!compoundOperators.has(operator)) { + throw new InterpreterRuntimeError(`Unsupported assignment operator '${operator}'.`, node) + } + return this.applyBinaryOperator(operator.slice(0, -1), current, incoming, node) + } + + private getMemberReference( + node: AstNode, + ): Effect.Effect< + | MemberReference + | ToolReference + | PromiseMethodReference + | IntrinsicReference + | GlobalMethodReference + | ComputedValue + | typeof OptionalShortCircuit + | undefined, + unknown, + R + > { + const objectNode = getNode(node, "object") + const propertyNode = getNode(node, "property") + const computed = getBoolean(node, "computed") + const optional = node.optional === true + const self = this + return Effect.gen(function* () { + const objectValue = yield* self.evaluateExpression(objectNode) + if (objectValue === OptionalShortCircuit) return OptionalShortCircuit + if ((objectValue === null || objectValue === undefined) && optional) return OptionalShortCircuit + + const key = computed + ? self.toPropertyKey(yield* self.evaluateExpression(propertyNode), propertyNode) + : propertyNode.type === "Identifier" + ? getString(propertyNode, "name") + : self.toPropertyKey(yield* self.evaluateExpression(propertyNode), propertyNode) + + if (objectValue instanceof ToolReference) { + if (typeof key !== "string" || isBlockedMember(key)) { + throw new InterpreterRuntimeError("Tool paths must use safe string property names.", propertyNode) + } + return new ToolReference([...objectValue.path, key]) + } + + if (objectValue instanceof PromiseNamespace) { + if (typeof key === "string" && promiseStatics.has(key as PromiseMethodName)) { + return new PromiseMethodReference(key as PromiseMethodName) + } + throw new InterpreterRuntimeError( + `Promise.${String(key)} is not available in CodeMode. Available: Promise.all, Promise.allSettled, Promise.race, Promise.resolve, and Promise.reject; consume promises with await.`, + propertyNode, + ) + } + + if (objectValue instanceof GlobalNamespace) { + if (typeof key !== "string" || isBlockedMember(key)) { + throw new InterpreterRuntimeError( + `${objectValue.name}.${String(key)} is not available in CodeMode.`, + propertyNode, + ) + } + if (objectValue.name === "Math" && mathConstants.has(key)) { + return new ComputedValue((Math as unknown as Record)[key]) + } + return new GlobalMethodReference(objectValue.name, key) + } + + if (typeof objectValue === "string") { + if (key === "length") return new ComputedValue(objectValue.length) + if (typeof key === "number") return new ComputedValue(objectValue[key]) + if (typeof key === "string" && /^\d+$/.test(key)) return new ComputedValue(objectValue[Number(key)]) + if (typeof key === "string" && stringMethods.has(key)) return new IntrinsicReference(objectValue, key) + // Unknown property on a string reads as `undefined`, matching JS (`"x".foo === undefined`), + // instead of throwing - so defensive access like `result?.login ?? result` on a JSON-string + // tool result doesn't crash. (Optional chaining only guards null/undefined receivers, so a + // real string still reaches here.) Only the method allowlist above yields callables. + return new ComputedValue(undefined) + } + + if (typeof objectValue === "number") { + if (typeof key === "string" && numberMethods.has(key)) return new IntrinsicReference(objectValue, key) + // Unknown property on a number reads as `undefined`, matching JS, rather than throwing. + return new ComputedValue(undefined) + } + + // Number / String expose a small allowlist of statics; everything else stays opaque. + if (objectValue instanceof CoercionFunction && typeof key === "string" && !isBlockedMember(key)) { + if (objectValue.name === "Number" && numberConstants.has(key)) { + return new ComputedValue((Number as unknown as Record)[key]) + } + if (objectValue.name === "Number" && numberStatics.has(key)) return new GlobalMethodReference("Number", key) + if (objectValue.name === "String" && stringStatics.has(key)) return new GlobalMethodReference("String", key) + } + + // Sandbox value types expose their method/property allowlists; any other key reads as + // `undefined`, consistent with unknown-property reads on strings/numbers/arrays. + if (objectValue instanceof SandboxDate) { + if (typeof key === "string" && dateMethods.has(key)) return new IntrinsicReference(objectValue, key) + return new ComputedValue(undefined) + } + if (objectValue instanceof SandboxRegExp) { + if (typeof key === "string" && regexpProperties.has(key)) { + return new ComputedValue((objectValue.regex as unknown as Record)[key]) + } + if (typeof key === "string" && regexpMethods.has(key)) return new IntrinsicReference(objectValue, key) + return new ComputedValue(undefined) + } + if (objectValue instanceof SandboxMap) { + if (key === "size") return new ComputedValue(objectValue.map.size) + if (typeof key === "string" && mapMethods.has(key)) return new IntrinsicReference(objectValue, key) + return new ComputedValue(undefined) + } + if (objectValue instanceof SandboxSet) { + if (key === "size") return new ComputedValue(objectValue.set.size) + if (typeof key === "string" && setMethods.has(key)) return new IntrinsicReference(objectValue, key) + return new ComputedValue(undefined) + } + if (objectValue instanceof SandboxURL) { + if (key === "searchParams") { + return new ComputedValue(objectValue.searchParams) + } + if (typeof key === "string" && urlMethods.has(key)) return new IntrinsicReference(objectValue, key) + if (typeof key === "string" && urlProperties.has(key)) return { target: objectValue, key } + return new ComputedValue(undefined) + } + if (objectValue instanceof SandboxURLSearchParams) { + if (key === "size") return new ComputedValue(objectValue.params.size) + if (typeof key === "string" && urlSearchParamsMethods.has(key)) { + return new IntrinsicReference(objectValue, key) + } + return new ComputedValue(undefined) + } + + // Any property access on a promise is a confused program (`p.then(...)`, `p.value`); + // reading `undefined` here would hide the missing await, so both paths get an explicit, + // await-hinting error instead of the forgiving unknown-property fallthrough. + if (objectValue instanceof SandboxPromise) { + if (key === "then" || key === "catch" || key === "finally") { + throw new InterpreterRuntimeError( + `Promise.prototype.${String(key)} is not supported in CodeMode; use await instead (with try/catch to handle failures) - e.g. \`const result = await tools.ns.tool(...)\`.`, + propertyNode, + "UnsupportedSyntax", + [supportedSyntaxMessage], + ) + } + throw new InterpreterRuntimeError( + "This value is an un-awaited Promise and has no readable properties; await it first - e.g. `const result = await tools.ns.tool(...)`.", + objectNode, + "InvalidDataValue", + ) + } + + if (isRuntimeReference(objectValue)) { + throw new InterpreterRuntimeError( + "CodeMode runtime references are opaque and do not expose properties.", + objectNode, + "InvalidDataValue", + ) + } + + if (typeof objectValue !== "object" || objectValue === null) { + throw new InterpreterRuntimeError("Cannot access a property on a non-object value.", objectNode) + } + + if (typeof key === "string" && isBlockedMember(key)) { + throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, propertyNode) + } + + if (Array.isArray(objectValue)) { + if ( + key !== "length" && + !(typeof key === "string" && arrayMethods.has(key)) && + typeof key !== "number" && + !/^\d+$/.test(key) + ) { + // Own non-index properties read through (match results carry index/groups); like JS, + // they are readable in place and dropped by JSON at data boundaries. + if (typeof key === "string" && Object.hasOwn(objectValue, key)) { + return new ComputedValue((objectValue as Record & Array)[key]) + } + // Unknown property on an array reads as `undefined`, matching JS (`[1,2].foo === undefined`), + // instead of throwing - so defensive access under optional chaining behaves as expected. + return new ComputedValue(undefined) + } + return { target: objectValue, key } + } + + return { target: objectValue as SafeObject, key } + }) + } + + private readMember(node: AstNode): Effect.Effect { + return Effect.map(this.getMemberReference(node), (reference) => { + if (reference === OptionalShortCircuit) return OptionalShortCircuit + if (reference instanceof ComputedValue) return reference.value + if ( + reference === undefined || + reference instanceof ToolReference || + reference instanceof PromiseMethodReference || + reference instanceof IntrinsicReference || + reference instanceof GlobalMethodReference + ) + return reference + if (Array.isArray(reference.target)) { + if (typeof reference.key === "string" && arrayMethods.has(reference.key)) { + return new IntrinsicReference(reference.target, reference.key) + } + return reference.key === "length" ? reference.target.length : reference.target[Number(reference.key)] + } + if (reference.target instanceof SandboxURL) { + return (reference.target.url as unknown as Record)[String(reference.key)] + } + return reference.target[String(reference.key)] + }) + } + + private writeMember(node: AstNode, value: unknown): Effect.Effect { + return this.modifyMember(node, () => Effect.succeed({ write: true, next: value, result: value })) + } + + // Resolves the member reference EXACTLY ONCE (so a side-effecting object/key expression + // runs once), then lets `compute` decide whether to write - enabling compound assignment, + // updates, plain writes, and short-circuiting logical assignment to share one safe path. + private modifyMember( + node: AstNode, + compute: (current: unknown) => Effect.Effect<{ write: boolean; next: unknown; result: unknown }, unknown, R>, + ): Effect.Effect { + const self = this + return Effect.gen(function* () { + const reference = yield* self.getMemberReference(node) + if ( + reference === OptionalShortCircuit || + reference instanceof ComputedValue || + reference === undefined || + reference instanceof ToolReference || + reference instanceof PromiseMethodReference || + reference instanceof IntrinsicReference || + reference instanceof GlobalMethodReference + ) { + throw new InterpreterRuntimeError("Only data fields may be assigned in CodeMode.", node) + } + if (Array.isArray(reference.target)) { + if (reference.key === "length") + throw new InterpreterRuntimeError("Array length cannot be assigned in CodeMode.", node) + if (typeof reference.key === "string" && arrayMethods.has(reference.key)) { + throw new InterpreterRuntimeError("Array methods cannot be assigned in CodeMode.", node) + } + } + const key = Array.isArray(reference.target) ? Number(reference.key) : String(reference.key) + const current = + reference.target instanceof SandboxURL + ? (reference.target.url as unknown as Record)[key] + : (reference.target as Record)[key] + const { write, next, result } = yield* compute(current) + if (write) self.assignToReference(reference, key, next, node) + return result + }) + } + + // Rejects inserting a value that (transitively) contains the container it is being inserted + // into - the mutation that would create a circular structure no later walk could survive. + private rejectCircularInsertion( + container: object, + value: unknown, + label: string, + node: AstNode, + seen = new Set(), + ): void { + if (value === container) + throw new InterpreterRuntimeError(`${label} contains a circular value.`, node, "InvalidDataValue") + if (value === null || typeof value !== "object" || isRuntimeReference(value) || seen.has(value)) return + seen.add(value) + const items = Array.isArray(value) ? value : Object.values(value) + for (const item of items) this.rejectCircularInsertion(container, item, label, node, seen) + seen.delete(value) + } + + private assignToReference(reference: MemberReference, key: number | string, next: unknown, node: AstNode): void { + if (Array.isArray(reference.target)) { + const target = reference.target + const index = key as number + if (!Number.isInteger(index) || index < 0) { + throw new InterpreterRuntimeError( + "Array assignment index must be a non-negative integer.", + node, + "InvalidDataValue", + ) + } + this.rejectCircularInsertion(target, next, "Array assignment result", node) + target[index] = next + return + } + if (reference.target instanceof SandboxURL) { + const property = key as string + if (!urlWritableProperties.has(property)) { + throw new InterpreterRuntimeError(`URL.${property} is read-only.`, node).as("TypeError") + } + try { + const url = reference.target.url as unknown as Record + url[property] = uriArgument(next, `URL.${property} value`) + return + } catch (error) { + if (error instanceof InterpreterRuntimeError || error instanceof ToolRuntimeError) throw error + throw new InterpreterRuntimeError(`URL.${property} received an invalid value.`, node).as("TypeError") + } + } + const target = reference.target as SafeObject + const objectKey = key as string + this.rejectCircularInsertion(target, next, "Object assignment result", node) + target[objectKey] = next + } + + private toPropertyKey(value: unknown, node: AstNode): string | number { + if (typeof value === "string" || typeof value === "number") { + return value + } + + throw new InterpreterRuntimeError("Property key must be a string or number.", node) + } + + private declare(name: string, value: unknown, mutable: boolean, node: AstNode): void { + const scope = this.currentScope() + + // A pre-seeded parameter slot (initialized === false) is being bound for the first time; + // anything else already present is a genuine duplicate declaration. + const existing = scope.get(name) + if (existing && existing.initialized !== false) { + throw new InterpreterRuntimeError(`Identifier '${name}' has already been declared.`, node) + } + + scope.set(name, { mutable, value, initialized: true }) + } + + private getIdentifierValue(name: string, node: AstNode): unknown { + const binding = this.resolveBinding(name) + + if (!binding) { + throw new InterpreterRuntimeError(`Unknown identifier '${name}'.`, node).as("ReferenceError") + } + + // A parameter default that forward-references a later (not-yet-bound) parameter - JS TDZ. + if (binding.initialized === false) { + throw new InterpreterRuntimeError(`Cannot access '${name}' before initialization.`, node).as("ReferenceError") + } + + return binding.value + } + + private setIdentifierValue(name: string, value: unknown, node: AstNode): unknown { + const binding = this.resolveBinding(name) + + if (!binding) { + throw new InterpreterRuntimeError(`Unknown identifier '${name}'.`, node).as("ReferenceError") + } + + if (!binding.mutable) { + throw new InterpreterRuntimeError(`Cannot assign to constant '${name}'.`, node).as("TypeError") + } + + binding.value = value + return value + } + + private resolveBinding(name: string): Binding | undefined { + for (let index = this.scopes.length - 1; index >= 0; index -= 1) { + const scope = this.scopes[index] + const binding = scope?.get(name) + + if (binding) { + return binding + } + } + + return undefined + } + + private currentScope(): Map { + const scope = this.scopes[this.scopes.length - 1] + + if (!scope) { + throw new InterpreterRuntimeError("Interpreter scope stack is empty.") + } + + return scope + } + + private pushScope(): void { + this.scopes.push(new Map()) + } + + private popScope(): void { + this.scopes.pop() + } +} + +/** + * Executes one Effect-native CodeMode program without constructing a reusable runtime. + * + * @example + * ```ts + * const result = yield* CodeMode.execute({ + * tools: { lookup }, + * code: `return await tools.lookup({ id: "order_42" })`, + * }) + * ``` + */ +export const executeWithLimits = >( + options: ExecuteOptions, + limits: ResolvedExecutionLimits, + searchIndex: ToolRuntime.DiscoveryPlan["searchIndex"], +): Effect.Effect> => { + const hooks = { + ...(options.onToolCallStart === undefined ? {} : { onToolCallStart: options.onToolCallStart }), + ...(options.onToolCallEnd === undefined ? {} : { onToolCallEnd: options.onToolCallEnd }), + } + const tools = ToolRuntime.make( + (options.tools ?? {}) as HostTools>, + limits.maxToolCalls, + searchIndex, + hooks, + ) + const logs: Array = [] + const logged = () => (logs.length > 0 ? { logs: [...logs] } : {}) + + if (options.code.trim().length === 0) { + return Effect.succeed({ + ok: false, + error: { kind: "ParseError", message: "Code cannot be empty." }, + toolCalls: tools.calls, + }) + } + + const operation = Effect.gen(function* () { + const program = parseProgram(options.code) + const interpreter = new Interpreter>(tools.invoke, tools.keys, logs) + const value = yield* interpreter.run(program) + const result = copyOut(copyIn(value, "Execution result"), true) as DataValue + return { + ok: true, + value: result, + ...logged(), + toolCalls: tools.calls, + } satisfies Result + }).pipe((program) => { + const timeoutMs = limits.timeoutMs + if (timeoutMs === undefined) return program + return program.pipe( + Effect.timeoutOrElse({ + duration: timeoutMs, + orElse: () => + Effect.succeed({ + ok: false, + error: { kind: "TimeoutExceeded", message: `Execution timed out after ${timeoutMs}ms.` }, + ...logged(), + toolCalls: tools.calls, + } satisfies Result), + }), + ) + }) + + return operation.pipe( + Effect.catchCause((cause) => + Cause.hasInterruptsOnly(cause) + ? Effect.interrupt + : Effect.succeed({ + ok: false, + error: normalizeError(Cause.squash(cause)), + ...logged(), + toolCalls: tools.calls, + } satisfies Result), + ), + Effect.map((result) => (limits.maxOutputBytes === undefined ? result : boundOutput(result, limits.maxOutputBytes))), + ) +} + +const utf8ByteLength = (value: string): number => new TextEncoder().encode(value).byteLength + +// Truncates to a UTF-8 byte budget without splitting a code point (a split multi-byte +// sequence decodes to a replacement character, which is dropped). +const utf8Truncate = (value: string, maxBytes: number): string => { + const bytes = new TextEncoder().encode(value) + if (bytes.byteLength <= maxBytes) return value + const text = new TextDecoder("utf-8").decode(bytes.slice(0, Math.max(0, maxBytes))) + return text.endsWith("\uFFFD") ? text.slice(0, -1) : text +} + +/** + * Bounds the model-facing output (serialized result value plus logs) to `maxOutputBytes`. + * Oversized values are replaced by their truncated serialized text with an explanatory marker, + * and logs are kept from the start until the remaining budget is exhausted. Truncation never + * fails the execution; `truncated: true` marks affected results. Only runs when the host set + * `maxOutputBytes` - with the limit absent, output passes through unbounded. + */ +const boundOutput = (result: Result, maxOutputBytes: number): Result => { + let truncated = false + + let value: DataValue = null + let valueBytes = 0 + if (result.ok) { + const serialized = JSON.stringify(result.value) ?? "null" + const bytes = utf8ByteLength(serialized) + if (bytes > maxOutputBytes) { + truncated = true + value = `${utf8Truncate(serialized, maxOutputBytes)} [result truncated: ${bytes} bytes exceeds the ${maxOutputBytes}-byte output limit; return a smaller value]` + valueBytes = maxOutputBytes + } else { + value = result.value + valueBytes = bytes + } + } + + const logs = result.logs ?? [] + const kept: Array = [] + const logBudget = Math.max(0, maxOutputBytes - valueBytes) + let logBytes = 0 + for (const line of logs) { + const lineBytes = utf8ByteLength(line) + 1 + if (logBytes + lineBytes > logBudget) break + logBytes += lineBytes + kept.push(line) + } + if (kept.length < logs.length) { + truncated = true + kept.push(`[logs truncated: showing ${kept.length} of ${logs.length} lines]`) + } + + if (!truncated) return result + const logsPart = kept.length > 0 ? { logs: kept } : {} + return result.ok + ? { ok: true, value, ...logsPart, truncated: true, toolCalls: result.toolCalls } + : { ok: false, error: result.error, ...logsPart, truncated: true, toolCalls: result.toolCalls } +} diff --git a/packages/codemode/src/stdlib/collections.ts b/packages/codemode/src/stdlib/collections.ts new file mode 100644 index 00000000000..f4760ff7061 --- /dev/null +++ b/packages/codemode/src/stdlib/collections.ts @@ -0,0 +1,51 @@ +export const arrayMethods = new Set([ + "map", + "filter", + "find", + "findIndex", + "findLast", + "findLastIndex", + "some", + "every", + "includes", + "join", + "reduce", + "reduceRight", + "flatMap", + "forEach", + "sort", + "toSorted", + "slice", + "concat", + "indexOf", + "lastIndexOf", + "at", + "flat", + "reverse", + "toReversed", + "with", + "push", + "pop", + "shift", + "unshift", + "splice", + "fill", + "copyWithin", + "keys", + "values", + "entries", +]) + +export const mapMethods = new Set(["get", "set", "has", "delete", "clear", "forEach", "keys", "values", "entries"]) + +export const setMethods = new Set(["add", "has", "delete", "clear", "forEach", "keys", "values", "entries"]) + +export const spreadItems = (value: unknown): Array | undefined => { + if (Array.isArray(value)) return value + if (typeof value === "string") return Array.from(value) + if (value instanceof SandboxMap) return Array.from(value.map.entries(), ([key, item]) => [key, item]) + if (value instanceof SandboxSet) return Array.from(value.set.values()) + if (value instanceof SandboxURLSearchParams) return Array.from(value.params.entries(), ([key, item]) => [key, item]) + return undefined +} +import { SandboxMap, SandboxSet, SandboxURLSearchParams } from "../values.js" diff --git a/packages/codemode/src/stdlib/console.ts b/packages/codemode/src/stdlib/console.ts new file mode 100644 index 00000000000..798563128e5 --- /dev/null +++ b/packages/codemode/src/stdlib/console.ts @@ -0,0 +1,4 @@ +export const consoleMethods = new Set(["log", "info", "debug", "warn", "error", "dir", "table"]) + +/** Console formatting recursion ceiling; deeper values render as "...". */ +export const MAX_CONSOLE_DEPTH = 32 diff --git a/packages/codemode/src/stdlib/date.ts b/packages/codemode/src/stdlib/date.ts new file mode 100644 index 00000000000..c492f58f94b --- /dev/null +++ b/packages/codemode/src/stdlib/date.ts @@ -0,0 +1,94 @@ +export const dateMethods = new Set([ + "getTime", + "valueOf", + "toISOString", + "toJSON", + "toString", + "getFullYear", + "getMonth", + "getDate", + "getDay", + "getHours", + "getMinutes", + "getSeconds", + "getMilliseconds", + "getUTCFullYear", + "getUTCMonth", + "getUTCDate", + "getUTCDay", + "getUTCHours", + "getUTCMinutes", + "getUTCSeconds", + "getUTCMilliseconds", + "getTimezoneOffset", +]) + +export const dateStatics = new Set(["now", "parse", "UTC"]) + +export const invokeDateStatic = (name: string, args: Array, node: AstNode): number => { + switch (name) { + case "now": + return Date.now() + case "parse": + return Date.parse(coerceToString(args[0])) + case "UTC": + return Date.UTC(...(args.map((arg) => coerceToNumber(arg)) as Parameters)) + default: + throw new InterpreterRuntimeError(`Date.${name} is not available in CodeMode.`, node) + } +} + +export const invokeDateMethod = (value: SandboxDate, name: string, node: AstNode): unknown => { + const hosted = new Date(value.time) + switch (name) { + case "getTime": + case "valueOf": + return value.time + case "toISOString": + if (!Number.isFinite(value.time)) throw new InterpreterRuntimeError("Invalid time value.", node) + return hosted.toISOString() + case "toJSON": + return Number.isFinite(value.time) ? hosted.toISOString() : null + case "toString": + return coerceToString(value) + case "getFullYear": + return hosted.getFullYear() + case "getMonth": + return hosted.getMonth() + case "getDate": + return hosted.getDate() + case "getDay": + return hosted.getDay() + case "getHours": + return hosted.getHours() + case "getMinutes": + return hosted.getMinutes() + case "getSeconds": + return hosted.getSeconds() + case "getMilliseconds": + return hosted.getMilliseconds() + case "getUTCFullYear": + return hosted.getUTCFullYear() + case "getUTCMonth": + return hosted.getUTCMonth() + case "getUTCDate": + return hosted.getUTCDate() + case "getUTCDay": + return hosted.getUTCDay() + case "getUTCHours": + return hosted.getUTCHours() + case "getUTCMinutes": + return hosted.getUTCMinutes() + case "getUTCSeconds": + return hosted.getUTCSeconds() + case "getUTCMilliseconds": + return hosted.getUTCMilliseconds() + case "getTimezoneOffset": + return hosted.getTimezoneOffset() + default: + throw new InterpreterRuntimeError(`Date method '${name}' is not available in CodeMode.`, node) + } +} +import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js" +import { SandboxDate } from "../values.js" +import { coerceToNumber, coerceToString } from "./value.js" diff --git a/packages/codemode/src/stdlib/json.ts b/packages/codemode/src/stdlib/json.ts new file mode 100644 index 00000000000..8a479d2c8c7 --- /dev/null +++ b/packages/codemode/src/stdlib/json.ts @@ -0,0 +1,42 @@ +import { + type AstNode, + CodeModeFunction, + InterpreterRuntimeError, + supportedSyntaxMessage, +} from "../interpreter/model.js" +import { copyIn, copyOut } from "../tool-runtime.js" + +export const jsonStatics = new Set(["stringify", "parse"]) + +export const invokeJsonMethod = (name: string, args: Array, node: AstNode): unknown => { + if (!jsonStatics.has(name)) throw new InterpreterRuntimeError(`JSON.${name} is not available in CodeMode.`, node) + switch (name) { + case "stringify": { + const replacer = args[1] + if (Array.isArray(replacer) || replacer instanceof CodeModeFunction) { + throw new InterpreterRuntimeError( + "JSON.stringify replacers are not supported in CodeMode.", + node, + "UnsupportedSyntax", + [supportedSyntaxMessage], + ) + } + const space = args[2] + const indent = typeof space === "number" || typeof space === "string" ? space : undefined + return JSON.stringify(copyOut(copyIn(args[0], "JSON.stringify value")), null, indent) + } + case "parse": { + const text = args[0] + if (typeof text !== "string") throw new InterpreterRuntimeError("JSON.parse expects a string.", node) + try { + return copyIn(JSON.parse(text), "JSON.parse result") + } catch (error) { + throw new InterpreterRuntimeError( + `JSON.parse received invalid JSON: ${error instanceof Error ? error.message : String(error)}`, + node, + ).as("SyntaxError") + } + } + } + throw new InterpreterRuntimeError(`JSON.${name} is not available in CodeMode.`, node) +} diff --git a/packages/codemode/src/stdlib/math.ts b/packages/codemode/src/stdlib/math.ts new file mode 100644 index 00000000000..cc8dd0670e9 --- /dev/null +++ b/packages/codemode/src/stdlib/math.ts @@ -0,0 +1,65 @@ +export const mathConstants = new Set(["PI", "E", "LN2", "LN10", "LOG2E", "LOG10E", "SQRT2", "SQRT1_2"]) + +export const mathMethods = new Set([ + "max", + "min", + "abs", + "floor", + "ceil", + "round", + "trunc", + "sign", + "sqrt", + "cbrt", + "pow", + "hypot", + "log", + "log2", + "log10", + "exp", +]) + +export const invokeMathMethod = (name: string, args: Array, node: AstNode): number => { + if (!mathMethods.has(name)) throw new InterpreterRuntimeError(`Math.${name} is not available in CodeMode.`, node) + const nums = args.map((arg) => { + if (typeof arg !== "number") throw new InterpreterRuntimeError(`Math.${name} expects number arguments.`, node) + return arg + }) + const [a = Number.NaN, b = Number.NaN] = nums + switch (name) { + case "max": + return Math.max(...nums) + case "min": + return Math.min(...nums) + case "abs": + return Math.abs(a) + case "floor": + return Math.floor(a) + case "ceil": + return Math.ceil(a) + case "round": + return Math.round(a) + case "trunc": + return Math.trunc(a) + case "sign": + return Math.sign(a) + case "sqrt": + return Math.sqrt(a) + case "cbrt": + return Math.cbrt(a) + case "pow": + return Math.pow(a, b) + case "hypot": + return Math.hypot(...nums) + case "log": + return Math.log(a) + case "log2": + return Math.log2(a) + case "log10": + return Math.log10(a) + case "exp": + return Math.exp(a) + } + throw new InterpreterRuntimeError(`Math.${name} is not available in CodeMode.`, node) +} +import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js" diff --git a/packages/codemode/src/stdlib/number.ts b/packages/codemode/src/stdlib/number.ts new file mode 100644 index 00000000000..79710e1ad22 --- /dev/null +++ b/packages/codemode/src/stdlib/number.ts @@ -0,0 +1,66 @@ +export const numberMethods = new Set(["toFixed", "toPrecision", "toExponential", "toString"]) + +export const numberConstants = new Set(["MAX_SAFE_INTEGER", "MIN_SAFE_INTEGER", "MAX_VALUE", "MIN_VALUE", "EPSILON"]) + +export const numberStatics = new Set(["isInteger", "isFinite", "isNaN", "isSafeInteger", "parseInt", "parseFloat"]) + +export const invokeNumberMethod = (value: number, name: string, args: Array, node: AstNode): unknown => { + const optNum = (index: number): number | undefined => { + const arg = args[index] + if (arg === undefined) return undefined + if (typeof arg !== "number") throw new InterpreterRuntimeError(`Number.${name} expects a number argument.`, node) + return arg + } + let result: unknown + switch (name) { + case "toFixed": + result = value.toFixed(optNum(0)) + break + case "toExponential": + result = value.toExponential(optNum(0)) + break + case "toPrecision": { + const digits = optNum(0) + result = digits === undefined ? value.toString() : value.toPrecision(digits) + break + } + case "toString": { + const radix = optNum(0) + if (radix !== undefined && (radix < 2 || radix > 36)) { + throw new InterpreterRuntimeError("Number.toString radix must be between 2 and 36.", node) + } + result = value.toString(radix) + break + } + default: + throw new InterpreterRuntimeError(`Number method '${name}' is not available in CodeMode.`, node) + } + return boundedData(result, `Number.${name} result`) +} + +export const invokeNumberStatic = (name: string, args: Array, node: AstNode): unknown => { + const value = args[0] + switch (name) { + case "isInteger": + return Number.isInteger(value) + case "isFinite": + return Number.isFinite(value) + case "isNaN": + return Number.isNaN(value) + case "isSafeInteger": + return Number.isSafeInteger(value) + case "parseInt": { + const radix = args[1] + if (radix !== undefined && typeof radix !== "number") { + throw new InterpreterRuntimeError("Number.parseInt expects a numeric radix.", node) + } + return parseInt(coerceToString(value), radix) + } + case "parseFloat": + return parseFloat(coerceToString(value)) + default: + throw new InterpreterRuntimeError(`Number.${name} is not available in CodeMode.`, node) + } +} +import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js" +import { boundedData, coerceToString } from "./value.js" diff --git a/packages/codemode/src/stdlib/object.ts b/packages/codemode/src/stdlib/object.ts new file mode 100644 index 00000000000..2beda0bf5ca --- /dev/null +++ b/packages/codemode/src/stdlib/object.ts @@ -0,0 +1,77 @@ +import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js" +import { isBlockedMember } from "../tool-runtime.js" +import { isSandboxValue, SandboxMap, SandboxURLSearchParams } from "../values.js" +import { boundedData, coerceToString } from "./value.js" + +export const objectStatics = new Set(["keys", "values", "entries", "hasOwn", "assign", "fromEntries"]) + +export const invokeObjectMethod = (name: string, args: Array, node: AstNode): unknown => { + if (!objectStatics.has(name)) throw new InterpreterRuntimeError(`Object.${name} is not available in CodeMode.`, node) + const requireObject = (): Record => { + const value = boundedData(args[0], `Object.${name} input`) + if (isSandboxValue(value)) return {} + if (value === null || typeof value !== "object" || Array.isArray(value)) { + throw new InterpreterRuntimeError(`Object.${name} expects a data object.`, node) + } + return value as Record + } + const guardedSet = (out: Record, key: string, item: unknown): void => { + if (isBlockedMember(key)) throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, node) + out[key] = item + } + switch (name) { + case "keys": { + const value = boundedData(args[0], "Object.keys input") + if (isSandboxValue(value)) return [] + if (Array.isArray(value)) return Object.keys(value) + if (value === null || typeof value !== "object") { + throw new InterpreterRuntimeError("Object.keys expects a data object or array.", node) + } + return Object.keys(value) + } + case "values": + return Object.values(requireObject()) + case "entries": + return Object.entries(requireObject()).map(([key, item]) => [key, item]) + case "hasOwn": + return Object.hasOwn(requireObject(), String(args[1])) + case "assign": { + const out: Record = Object.create(null) + for (const source of args) { + if (source === null || source === undefined) continue + const value = boundedData(source, "Object.assign input") + if (isSandboxValue(value)) continue + if (value === null || typeof value !== "object" || Array.isArray(value)) { + throw new InterpreterRuntimeError("Object.assign expects data objects.", node) + } + for (const [key, item] of Object.entries(value)) guardedSet(out, key, item) + } + return out + } + case "fromEntries": { + if (args[0] instanceof SandboxMap) { + const out: Record = Object.create(null) + for (const [key, item] of args[0].map.entries()) guardedSet(out, coerceToString(key), item) + return out + } + if (args[0] instanceof SandboxURLSearchParams) { + const out: Record = Object.create(null) + for (const [key, value] of args[0].params.entries()) guardedSet(out, key, value) + return out + } + const pairs = boundedData(args[0], "Object.fromEntries input") + if (!Array.isArray(pairs)) { + throw new InterpreterRuntimeError("Object.fromEntries expects an array of [key, value] pairs.", node) + } + const out: Record = Object.create(null) + for (const pair of pairs) { + if (!Array.isArray(pair)) { + throw new InterpreterRuntimeError("Object.fromEntries expects [key, value] pairs.", node) + } + guardedSet(out, String(pair[0]), pair[1]) + } + return out + } + } + throw new InterpreterRuntimeError(`Object.${name} is not available in CodeMode.`, node) +} diff --git a/packages/codemode/src/stdlib/promise.ts b/packages/codemode/src/stdlib/promise.ts new file mode 100644 index 00000000000..d0b442ccf74 --- /dev/null +++ b/packages/codemode/src/stdlib/promise.ts @@ -0,0 +1,6 @@ +import type { PromiseMethodName } from "../interpreter/model.js" + +export const promiseStatics = new Set(["all", "allSettled", "race", "resolve", "reject"]) + +/** Maximum number of eagerly forked tool calls that may run concurrently. */ +export const TOOL_CALL_CONCURRENCY = 8 diff --git a/packages/codemode/src/stdlib/regexp.ts b/packages/codemode/src/stdlib/regexp.ts new file mode 100644 index 00000000000..eac123bc16c --- /dev/null +++ b/packages/codemode/src/stdlib/regexp.ts @@ -0,0 +1,74 @@ +export const regexpMethods = new Set(["test", "exec", "toString"]) + +export const regexpProperties = new Set([ + "source", + "flags", + "lastIndex", + "global", + "ignoreCase", + "multiline", + "sticky", + "unicode", + "dotAll", +]) + +export const regexFailureReason = (error: unknown): string => + (error instanceof Error ? error.message : String(error)).replace(/^Invalid regular expression:\s*/i, "") + +export const escapeRegexHint = + 'To match special characters like ( ) [ ] { } + * ? . literally, escape them with a backslash (e.g. "\\\\(") or test for them with String.includes instead.' + +export const toHostRegex = (arg: unknown, method: string, node: AstNode, extraFlags = ""): RegExp => { + if (arg instanceof SandboxRegExp) return arg.regex + if (typeof arg === "string") { + try { + return new RegExp(arg, extraFlags) + } catch (error) { + throw new InterpreterRuntimeError( + `String.${method} received the string ${JSON.stringify(arg)}, which is not a valid regular expression pattern (${regexFailureReason(error)}). ${escapeRegexHint}`, + node, + ).as("SyntaxError") + } + } + throw new InterpreterRuntimeError( + `String.${method} expects a regular expression (a /pattern/flags literal or new RegExp(...)) or a string pattern, not ${arg === null ? "null" : typeof arg}.`, + node, + ) +} + +export const matchToValue = (match: RegExpMatchArray): Array => { + const result: Array = Array.from(match, (group) => group) + if (match.index !== undefined) (result as Record & Array).index = match.index + if (match.groups) { + const groups: SafeObject = Object.create(null) as SafeObject + for (const [key, group] of Object.entries(match.groups)) { + if (!isBlockedMember(key)) groups[key] = group + } + ;(result as Record & Array).groups = groups + } + return result +} + +export const invokeRegExpMethod = ( + value: SandboxRegExp, + name: string, + args: Array, + node: AstNode, +): unknown => { + switch (name) { + case "test": + return value.regex.test(coerceToString(args[0])) + case "exec": { + const matched = value.regex.exec(coerceToString(args[0])) + return matched === null ? null : matchToValue(matched) + } + case "toString": + return coerceToString(value) + default: + throw new InterpreterRuntimeError(`RegExp method '${name}' is not available in CodeMode.`, node) + } +} +import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js" +import { isBlockedMember, type SafeObject } from "../tool-runtime.js" +import { SandboxRegExp } from "../values.js" +import { coerceToString } from "./value.js" diff --git a/packages/codemode/src/stdlib/string.ts b/packages/codemode/src/stdlib/string.ts new file mode 100644 index 00000000000..3ac4372e363 --- /dev/null +++ b/packages/codemode/src/stdlib/string.ts @@ -0,0 +1,52 @@ +export const stringMethods = new Set([ + "toLowerCase", + "toUpperCase", + "trim", + "trimStart", + "trimEnd", + "trimLeft", + "trimRight", + "split", + "slice", + "substring", + "substr", + "includes", + "startsWith", + "endsWith", + "indexOf", + "lastIndexOf", + "replace", + "replaceAll", + "repeat", + "padStart", + "padEnd", + "charAt", + "charCodeAt", + "codePointAt", + "at", + "concat", + "toString", + "match", + "matchAll", + "search", + "localeCompare", + "normalize", +]) + +export const stringStatics = new Set(["fromCharCode", "fromCodePoint"]) + +export const invokeStringStatic = (name: string, args: Array, node: AstNode): unknown => { + const codes = args.map((arg) => { + if (typeof arg !== "number") throw new InterpreterRuntimeError(`String.${name} expects number arguments.`, node) + return arg + }) + switch (name) { + case "fromCharCode": + return String.fromCharCode(...codes) + case "fromCodePoint": + return String.fromCodePoint(...codes) + default: + throw new InterpreterRuntimeError(`String.${name} is not available in CodeMode.`, node) + } +} +import { type AstNode, InterpreterRuntimeError } from "../interpreter/model.js" diff --git a/packages/codemode/src/stdlib/url.ts b/packages/codemode/src/stdlib/url.ts new file mode 100644 index 00000000000..583d776d22a --- /dev/null +++ b/packages/codemode/src/stdlib/url.ts @@ -0,0 +1,90 @@ +export const urlProperties = new Set([ + "href", + "origin", + "protocol", + "username", + "password", + "host", + "hostname", + "port", + "pathname", + "search", + "hash", +]) + +export const urlWritableProperties = new Set([ + "href", + "protocol", + "username", + "password", + "host", + "hostname", + "port", + "pathname", + "search", + "hash", +]) + +export const urlMethods = new Set(["toString", "toJSON"]) +export const urlStatics = new Set(["canParse", "parse"]) +export const urlSearchParamsMethods = new Set([ + "append", + "delete", + "get", + "getAll", + "has", + "set", + "sort", + "forEach", + "keys", + "values", + "entries", + "toString", +]) + +export const uriArgument = (value: unknown, label: string): string => coerceToString(boundedData(value, label)) + +export const invokeUriFunction = (ref: UriFunction, args: Array, node: AstNode): string => { + const value = uriArgument(args[0], `${ref.name} input`) + try { + switch (ref.name) { + case "encodeURI": + return encodeURI(value) + case "encodeURIComponent": + return encodeURIComponent(value) + case "decodeURI": + return decodeURI(value) + case "decodeURIComponent": + return decodeURIComponent(value) + } + } catch (error) { + throw new InterpreterRuntimeError( + `${ref.name} received malformed URI data: ${error instanceof Error ? error.message : String(error)}`, + node, + ).as("URIError") + } +} + +export const urlArgument = (value: unknown, label: string): string => + value instanceof SandboxURL ? value.url.href : uriArgument(value, label) + +export const invokeURLStatic = (name: string, args: Array, node: AstNode): unknown => { + if (!urlStatics.has(name)) throw new InterpreterRuntimeError(`URL.${name} is not available in CodeMode.`, node) + if (args.length === 0) throw new InterpreterRuntimeError(`URL.${name} requires a URL argument.`, node).as("TypeError") + const input = urlArgument(args[0], `URL.${name} input`) + const base = args[1] === undefined ? undefined : urlArgument(args[1], `URL.${name} base`) + try { + const url = new URL(input, base) + return name === "canParse" ? true : new SandboxURL(url) + } catch { + return name === "canParse" ? false : null + } +} + +export const invokeURLMethod = (value: SandboxURL, name: string, node: AstNode): string => { + if (name === "toString" || name === "toJSON") return value.url.href + throw new InterpreterRuntimeError(`URL method '${name}' is not available in CodeMode.`, node) +} +import { type AstNode, InterpreterRuntimeError, UriFunction } from "../interpreter/model.js" +import { SandboxURL } from "../values.js" +import { boundedData, coerceToString } from "./value.js" diff --git a/packages/codemode/src/stdlib/value.ts b/packages/codemode/src/stdlib/value.ts new file mode 100644 index 00000000000..17ca8b1c486 --- /dev/null +++ b/packages/codemode/src/stdlib/value.ts @@ -0,0 +1,90 @@ +export const errorConstructors = new Set([ + "Error", + "TypeError", + "RangeError", + "SyntaxError", + "ReferenceError", + "EvalError", + "URIError", +]) + +export const valueConstructors = new Set(["Date", "RegExp", "Map", "Set", "URL", "URLSearchParams"]) + +export const compoundOperators = new Set(["+=", "-=", "*=", "/=", "%=", "**=", "&=", "|=", "^=", "<<=", ">>=", ">>>="]) + +const ErrorBrand: unique symbol = Symbol("codemode.error") + +export const createErrorValue = (name: string, message: string): SafeObject => { + const value = Object.assign(Object.create(null) as SafeObject, { name, message }) + Object.defineProperty(value, ErrorBrand, { value: name }) + return value +} + +export const errorBrandName = (value: unknown): string | undefined => + value !== null && typeof value === "object" + ? ((value as Record)[ErrorBrand] as string | undefined) + : undefined + +export const boundedData = (value: unknown, label: string): unknown => copyIn(value, label, true) + +export const coerceToString = (value: unknown): string => { + if (value === null) return "null" + if (value === undefined) return "undefined" + if (value instanceof SandboxDate) + return Number.isFinite(value.time) ? new Date(value.time).toISOString() : "Invalid Date" + if (value instanceof SandboxRegExp) return `/${value.regex.source}/${value.regex.flags}` + if (value instanceof SandboxMap) return "[object Map]" + if (value instanceof SandboxSet) return "[object Set]" + if (value instanceof SandboxURL) return value.url.href + if (value instanceof SandboxURLSearchParams) return value.params.toString() + if (typeof value === "object") { + return Array.isArray(value) + ? value.map((item) => (item === null || item === undefined ? "" : coerceToString(item))).join(",") + : "[object Object]" + } + return String(value) +} + +export const coerceToNumber = (value: unknown): number => { + if (value instanceof SandboxDate) return value.time + if (isSandboxValue(value)) return Number.NaN + return value !== null && typeof value === "object" && !Array.isArray(value) ? Number.NaN : Number(value) +} + +export const invokeCoercion = (ref: CoercionFunction, args: Array, node: AstNode): unknown => { + const raw = args[0] + if (isSandboxValue(raw)) { + if (ref.name === "Boolean") return true + if (ref.name === "Number") return coerceToNumber(raw) + if (ref.name === "String") return coerceToString(raw) + if (ref.name === "parseInt") return parseInt(coerceToString(raw)) + return parseFloat(coerceToString(raw)) + } + const value = boundedData(args[0], `${ref.name} input`) + if (ref.name === "Number") return coerceToNumber(value) + if (ref.name === "Boolean") return Boolean(value) + if (ref.name === "parseInt") { + const radix = args[1] + if (radix !== undefined && typeof radix !== "number") { + throw new InterpreterRuntimeError("parseInt expects a numeric radix.", node) + } + return parseInt(coerceToString(value), radix) + } + if (ref.name === "parseFloat") return parseFloat(coerceToString(value)) + return coerceToString(value) +} +import { + type AstNode, + CoercionFunction, + InterpreterRuntimeError, +} from "../interpreter/model.js" +import { copyIn, type SafeObject } from "../tool-runtime.js" +import { + isSandboxValue, + SandboxDate, + SandboxMap, + SandboxRegExp, + SandboxSet, + SandboxURL, + SandboxURLSearchParams, +} from "../values.js" From ff499c360385661f7e91b31d878c188ef975146c Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 6 Jul 2026 12:59:26 -0400 Subject: [PATCH 07/46] refactor(api): remove watermark sync surface --- packages/cli/src/mini/stream-v2.transport.ts | 4 +- packages/client/src/effect/api/api.ts | 6 +- .../client/src/effect/generated/client.ts | 15 +- .../client/src/promise/generated/client.ts | 12 +- .../client/src/promise/generated/types.ts | 11 +- packages/client/test/effect.test.ts | 7 +- packages/client/test/promise.test.ts | 8 +- packages/codemode/test/openapi.test.ts | 1 - packages/core/src/event.ts | 83 ---------- packages/core/test/event.test.ts | 46 ------ .../test/session-runner-tool-events.test.ts | 1 - packages/protocol/src/groups/event.ts | 15 +- packages/protocol/src/groups/message.ts | 6 - packages/protocol/src/groups/session.ts | 15 +- packages/schema/src/event-log.ts | 34 ---- packages/schema/src/event.ts | 2 +- packages/sdk-next/test/embedded.test.ts | 2 +- packages/sdk/js/src/v2/gen/sdk.gen.ts | 36 ++--- packages/sdk/js/src/v2/gen/types.gen.ts | 146 ++++++++---------- packages/server/src/handlers/event.ts | 65 ++++---- packages/server/src/handlers/message.ts | 5 - packages/server/src/handlers/session.ts | 3 - packages/tui/src/context/data.tsx | 2 +- packages/tui/test/cli/tui/data.test.tsx | 6 +- packages/tui/test/fixture/tui-sdk.ts | 2 +- 25 files changed, 141 insertions(+), 392 deletions(-) diff --git a/packages/cli/src/mini/stream-v2.transport.ts b/packages/cli/src/mini/stream-v2.transport.ts index 7cec6f9e87f..d6998f200bc 100644 --- a/packages/cli/src/mini/stream-v2.transport.ts +++ b/packages/cli/src/mini/stream-v2.transport.ts @@ -544,8 +544,8 @@ export async function createSessionTransport(input: StreamInput): Promise>["data"] export type SessionCreateOperation = (input?: Endpoint4_1Input) => Effect.Effect -export type Endpoint4_2Output = EffectValue> +export type Endpoint4_2Output = EffectValue>["data"] export type SessionActiveOperation = () => Effect.Effect type Endpoint4_3Request = Parameters[0] @@ -658,12 +658,8 @@ export interface SkillApi { export type Endpoint18_0Output = StreamValue>> export type EventSubscribeOperation = () => Stream.Stream -export type Endpoint18_1Output = StreamValue>> -export type EventChangesOperation = () => Stream.Stream - export interface EventApi { readonly subscribe: EventSubscribeOperation - readonly changes: EventChangesOperation } type Endpoint19_0Request = Parameters[0] diff --git a/packages/client/src/effect/generated/client.ts b/packages/client/src/effect/generated/client.ts index 1001c1e0477..b7dc996abae 100644 --- a/packages/client/src/effect/generated/client.ts +++ b/packages/client/src/effect/generated/client.ts @@ -82,7 +82,10 @@ const Endpoint4_1 = (raw: RawClient["server.session"]) => (input?: Endpoint4_1In ) const Endpoint4_2 = (raw: RawClient["server.session"]) => () => - raw["session.active"]({}).pipe(Effect.mapError(mapClientError)) + raw["session.active"]({}).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) type Endpoint4_3Request = Parameters[0] type Endpoint4_3Input = { readonly sessionID: Endpoint4_3Request["params"]["sessionID"] } @@ -796,15 +799,7 @@ const Endpoint18_0 = (raw: RawClient["server.event"]) => () => ), ) -const Endpoint18_1 = (raw: RawClient["server.event"]) => () => - Stream.unwrap( - raw["event.changes"]({}).pipe( - Effect.mapError(mapClientError), - Effect.map((stream) => stream.pipe(Stream.mapError(mapClientError))), - ), - ) - -const adaptGroup18 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint18_0(raw), changes: Endpoint18_1(raw) }) +const adaptGroup18 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint18_0(raw) }) type Endpoint19_0Request = Parameters[0] type Endpoint19_0Input = { readonly location?: Endpoint19_0Request["query"]["location"] } diff --git a/packages/client/src/promise/generated/client.ts b/packages/client/src/promise/generated/client.ts index d3e18279e0d..ad94f07fd37 100644 --- a/packages/client/src/promise/generated/client.ts +++ b/packages/client/src/promise/generated/client.ts @@ -133,7 +133,6 @@ import type { SkillListInput, SkillListOutput, EventSubscribeOutput, - EventChangesOutput, PtyListInput, PtyListOutput, PtyCreateInput, @@ -402,7 +401,7 @@ export function make(options: ClientOptions) { requestOptions, ).then((value) => value.data), active: (requestOptions?: RequestOptions) => - request( + request<{ readonly data: SessionActiveOutput }>( { method: "GET", path: `/api/session/active`, @@ -411,7 +410,7 @@ export function make(options: ClientOptions) { empty: false, }, requestOptions, - ), + ).then((value) => value.data), get: (input: SessionGetInput, requestOptions?: RequestOptions) => request<{ readonly data: SessionGetOutput }>( { @@ -646,7 +645,7 @@ export function make(options: ClientOptions) { sse( { method: "GET", - path: `/api/session/${encodeURIComponent(input.sessionID)}/log`, + path: `/api/experimental/session/${encodeURIComponent(input.sessionID)}/log`, query: { after: input["after"], follow: input["follow"] }, successStatus: 200, declaredStatuses: [404, 400, 401], @@ -1183,11 +1182,6 @@ export function make(options: ClientOptions) { { method: "GET", path: `/api/event`, successStatus: 200, declaredStatuses: [401, 400], empty: false }, requestOptions, ), - changes: (requestOptions?: RequestOptions): AsyncIterable => - sse( - { method: "GET", path: `/api/event/changes`, successStatus: 200, declaredStatuses: [401, 400], empty: false }, - requestOptions, - ), }, pty: { list: (input?: PtyListInput, requestOptions?: RequestOptions) => diff --git a/packages/client/src/promise/generated/types.ts b/packages/client/src/promise/generated/types.ts index ac0efadb5c0..dc28955f49d 100644 --- a/packages/client/src/promise/generated/types.ts +++ b/packages/client/src/promise/generated/types.ts @@ -354,7 +354,6 @@ export type SessionListOutput = { }> } }> - readonly watermarks: { readonly [x: string]: number } readonly cursor: { readonly previous?: string | null; readonly next?: string | null } } @@ -419,10 +418,7 @@ export type SessionCreateOutput = { } }["data"] -export type SessionActiveOutput = { - readonly data: { readonly [x: string]: { readonly type: "running" } } - readonly watermarks: { readonly [x: string]: number } -} +export type SessionActiveOutput = { readonly data: { readonly [x: string]: { readonly type: "running" } } }["data"] export type SessionGetInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] } @@ -1987,7 +1983,6 @@ export type MessageListOutput = { readonly time: { readonly created: number } } > - readonly watermark?: number readonly cursor: { readonly previous?: string | null; readonly next?: string | null } } @@ -5546,10 +5541,6 @@ export type EventSubscribeOutput = readonly data: {} } -export type EventChangesOutput = - | { readonly type: "log.hint"; readonly aggregateID: string; readonly seq: number } - | { readonly type: "log.sweep_required" } - export type PtyListInput = { readonly location?: { readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined diff --git a/packages/client/test/effect.test.ts b/packages/client/test/effect.test.ts index 2077c27ca5f..2073af42ac1 100644 --- a/packages/client/test/effect.test.ts +++ b/packages/client/test/effect.test.ts @@ -99,7 +99,7 @@ test("session methods retain decoded Effect inputs and outputs", async () => { return Effect.succeed( HttpClientResponse.fromWeb( request, - Response.json({ data: { ses_test: { type: "running" } }, watermarks: { ses_test: 3 } }), + Response.json({ data: { ses_test: { type: "running" } } }), ), ) } @@ -112,7 +112,7 @@ test("session methods retain decoded Effect inputs and outputs", async () => { return Effect.succeed( HttpClientResponse.fromWeb( request, - Response.json({ data: [session.data], watermarks: { ses_test: 3 }, cursor: { next: "next" } }), + Response.json({ data: [session.data], cursor: { next: "next" } }), ), ) }) @@ -148,8 +148,7 @@ test("session methods retain decoded Effect inputs and outputs", async () => { }).pipe(Effect.provideService(HttpClient.HttpClient, httpClient), Effect.runPromise) expect(DateTime.toEpochMillis(result.page.data[0].time.created)).toBe(1_717_171_717_000) - expect(result.active).toEqual({ data: { ses_test: { type: "running" } }, watermarks: { ses_test: 3 } }) - expect(result.page.watermarks).toEqual({ ses_test: 3 }) + expect(result.active).toEqual({ ses_test: { type: "running" } }) expect(Object.getPrototypeOf(result.page.data[0])).toBe(Object.prototype) expect(Object.getPrototypeOf(result.created)).toBe(Object.prototype) expect(result.created.id).toBe("ses_test") diff --git a/packages/client/test/promise.test.ts b/packages/client/test/promise.test.ts index 2dbd58a8585..04737612e25 100644 --- a/packages/client/test/promise.test.ts +++ b/packages/client/test/promise.test.ts @@ -47,7 +47,7 @@ test("exposes every standard HTTP API group", () => { expect(Object.keys(client.vcs)).toEqual(["status", "diff"]) expect(Object.keys(client.pty)).toEqual(["list", "create", "get", "update", "remove"]) expect(Object.keys(client.shell)).toEqual(["list", "create", "get", "output", "remove"]) - expect(Object.keys(client.project)).toEqual(["current", "directories"]) + expect(Object.keys(client.project)).toEqual(["list", "current", "directories"]) }) test("file.read returns binary content from the public HTTP contract", async () => { @@ -198,7 +198,7 @@ test("session methods use the public HTTP contract", async () => { if (url.includes("/context")) return Response.json({ data: [] }) if (url.includes("/message/")) return Response.json({ data: modelSwitchedMessage }) if (url.endsWith("/api/session/active")) - return Response.json({ data: { ses_test: { type: "running" } }, watermarks: { ses_test: 3 } }) + return Response.json({ data: { ses_test: { type: "running" } } }) if (init?.method === "POST" && url.endsWith("/api/session")) return Response.json(session) if (init?.method === "POST") return new Response(null, { status: 204 }) return Response.json({ data: [session.data], cursor: { next: "next" } }) @@ -227,7 +227,7 @@ test("session methods use the public HTTP contract", async () => { const message = await client.session.message({ sessionID: "ses_test", messageID: "msg_model" }) expect(page.cursor.next).toBe("next") - expect(active).toEqual({ data: { ses_test: { type: "running" } }, watermarks: { ses_test: 3 } }) + expect(active).toEqual({ ses_test: { type: "running" } }) expect(created.id).toBe("ses_test") expect(admitted.id).toBe("msg_test") expect(context).toEqual([]) @@ -243,7 +243,7 @@ test("session methods use the public HTTP contract", async () => { ["POST", "http://localhost:3000/api/session/ses_test/compact"], ["POST", "http://localhost:3000/api/session/ses_test/wait"], ["GET", "http://localhost:3000/api/session/ses_test/context"], - ["GET", "http://localhost:3000/api/session/ses_test/log?after=0"], + ["GET", "http://localhost:3000/api/experimental/session/ses_test/log?after=0"], ["POST", "http://localhost:3000/api/session/ses_test/interrupt"], ["GET", "http://localhost:3000/api/session/ses_test/message/msg_model"], ]) diff --git a/packages/codemode/test/openapi.test.ts b/packages/codemode/test/openapi.test.ts index a50460e8daa..7ad3d486247 100644 --- a/packages/codemode/test/openapi.test.ts +++ b/packages/codemode/test/openapi.test.ts @@ -204,7 +204,6 @@ describe("OpenAPI.fromSpec", () => { expect(toolAt(result.tools, "v2.pty.connect")).toBeUndefined() expect(toolAt(result.tools, "v2.session.log")).toBeUndefined() expect(toolAt(result.tools, "v2.event.subscribe")).toBeUndefined() - expect(toolAt(result.tools, "v2.event.changes")).toBeUndefined() expect(toolAt(result.tools, "v2.fs.read")).toBeUndefined() expect(toolAt(result.tools, "v2.pty.connectToken")).not.toBeUndefined() }) diff --git a/packages/core/src/event.ts b/packages/core/src/event.ts index a5b052b42ff..6b6d7813e5f 100644 --- a/packages/core/src/event.ts +++ b/packages/core/src/event.ts @@ -135,12 +135,6 @@ export interface Interface { readonly after?: number readonly follow?: boolean }) => Stream.Stream - /** - * Coalescing hint channel: latest committed seq per aggregate, never a - * delivery guarantee. Emits `SweepRequired` first on every subscribe and - * whenever per-key retention is exceeded. Never fails under backpressure. - */ - readonly changes: () => Stream.Stream /** Latest committed seq per aggregate. Aggregates without events are absent. */ readonly sequences: (aggregateIDs: ReadonlyArray) => Effect.Effect> /** @deprecated Use `all()` and consume the returned stream. */ @@ -183,11 +177,6 @@ export const liveBounded = ( export interface LayerOptions { readonly beforeAggregateRead?: (aggregateID: string) => Effect.Effect - /** - * Maximum distinct aggregates buffered per changes subscriber before the - * buffer is abandoned and the subscriber is told to sweep. - */ - readonly changesKeyCapacity?: number /** Maximum durable rows read per page while replaying or tailing an aggregate log. */ readonly logReadPageSize?: number } @@ -204,12 +193,6 @@ export const layerWith = (options?: LayerOptions) => const projectors = new Map() // TODO: Bind durable projectors to exact type+version before supporting incompatible historical payloads. const listeners = new Array() - const changesKeyCapacity = options?.changesKeyCapacity ?? 4096 - const changesSubscribers = new Set<{ - readonly hints: Map - sweepRequired: boolean - readonly wake: PubSub.PubSub - }>() const { db } = yield* Database.Service const logReadPageSize = options?.logReadPageSize ?? 512 @@ -231,9 +214,6 @@ export const layerWith = (options?: LayerOptions) => { discard: true }, ) yield* Effect.forEach(pubsub.typed.values(), PubSub.shutdown, { discard: true }) - yield* Effect.forEach(changesSubscribers, (subscriber) => PubSub.shutdown(subscriber.wake), { - discard: true, - }) }), ) @@ -394,27 +374,6 @@ export const layerWith = (options?: LayerOptions) => (wake) => PubSub.publish(wake, undefined), { discard: true }, ) - yield* Effect.forEach( - changesSubscribers, - (subscriber) => - Effect.sync(() => { - // Coalesce to the latest seq per aggregate. Overflowing key - // cardinality abandons the buffer instead of dropping hints silently. - if ( - subscriber.hints.size >= changesKeyCapacity && - !subscriber.hints.has(committed.aggregateID) - ) { - subscriber.hints.clear() - subscriber.sweepRequired = true - } else if (!subscriber.sweepRequired) { - subscriber.hints.set( - committed.aggregateID, - Math.max(subscriber.hints.get(committed.aggregateID) ?? -1, committed.seq), - ) - } - }).pipe(Effect.andThen(PubSub.publish(subscriber.wake, undefined)), Effect.asVoid), - { discard: true }, - ) } return committed }), @@ -723,47 +682,6 @@ export const layerWith = (options?: LayerOptions) => }), ) - const changes = (): Stream.Stream => - Stream.unwrap( - Effect.gen(function* () { - const wake = yield* PubSub.sliding(1) - const subscription = yield* PubSub.subscribe(wake) - const subscriber = { hints: new Map(), sweepRequired: false, wake } - yield* Effect.acquireRelease( - Effect.sync(() => changesSubscribers.add(subscriber)), - () => - Effect.sync(() => changesSubscribers.delete(subscriber)).pipe( - Effect.andThen(PubSub.shutdown(wake)), - Effect.asVoid, - ), - ) - const drain = Effect.sync((): ReadonlyArray => { - if (subscriber.sweepRequired) { - subscriber.sweepRequired = false - subscriber.hints.clear() - return [{ type: "log.sweep_required" }] - } - const hints = Array.from( - subscriber.hints, - ([aggregateID, seq]): EventLog.Change => ({ type: "log.hint", aggregateID, seq: Seq.make(seq) }), - ) - subscriber.hints.clear() - return hints - }) - // Hints missed while unsubscribed were never buffered, so every - // (re)subscribe starts from the sweep contract. - const initial: EventLog.Change = { type: "log.sweep_required" } - return Stream.make(initial).pipe( - Stream.concat( - Stream.fromSubscription(subscription).pipe( - Stream.mapEffect(() => drain), - Stream.flattenIterable, - ), - ), - ) - }), - ) - const sequences = (aggregateIDs: ReadonlyArray): Effect.Effect> => { if (aggregateIDs.length === 0) return Effect.succeed(new Map()) return db @@ -798,7 +716,6 @@ export const layerWith = (options?: LayerOptions) => subscribe, live: streamLive, log, - changes, sequences, listen, project, diff --git a/packages/core/test/event.test.ts b/packages/core/test/event.test.ts index 70a8083d16d..96e767084fd 100644 --- a/packages/core/test/event.test.ts +++ b/packages/core/test/event.test.ts @@ -1289,52 +1289,6 @@ describe("EventV2", () => { }), ) - it.effect("changes emits sweep-required on subscribe then coalesced hints per aggregate", () => - Effect.gen(function* () { - const events = yield* EventV2.Service - const first = Session.ID.create() - const second = Session.ID.create() - const pull = yield* Stream.toPull(events.changes()) - - expect(Array.from(yield* pull)).toEqual([{ type: "log.sweep_required" }]) - - yield* events.publish(DurableMessage, durableData(first, "zero")) - yield* events.publish(DurableMessage, durableData(first, "one")) - yield* events.publish(DurableMessage, durableData(first, "two")) - yield* events.publish(DurableMessage, durableData(second, "zero")) - - expect(Array.from(yield* pull)).toEqual([ - { type: "log.hint", aggregateID: first, seq: EventV2.Seq.make(2) }, - { type: "log.hint", aggregateID: second, seq: EventV2.Seq.make(0) }, - ]) - }), - ) - - it.effect("changes abandons the hint buffer for a sweep when key retention is exceeded", () => - Effect.gen(function* () { - const eventLayer = EventV2.layerWith({ changesKeyCapacity: 2 }).pipe( - Layer.provide(LayerNode.compile(Database.node)), - ) - - yield* Effect.gen(function* () { - const events = yield* EventV2.Service - const pull = yield* Stream.toPull(events.changes()) - expect(Array.from(yield* pull)).toEqual([{ type: "log.sweep_required" }]) - - yield* events.publish(DurableMessage, durableData(Session.ID.create(), "a")) - yield* events.publish(DurableMessage, durableData(Session.ID.create(), "b")) - yield* events.publish(DurableMessage, durableData(Session.ID.create(), "c")) - - expect(Array.from(yield* pull)).toEqual([{ type: "log.sweep_required" }]) - - const late = Session.ID.create() - yield* events.publish(DurableMessage, durableData(late, "d")) - - expect(Array.from(yield* pull)).toEqual([{ type: "log.hint", aggregateID: late, seq: EventV2.Seq.make(0) }]) - }).pipe(Effect.provide(Layer.merge(LayerNode.compile(Database.node), eventLayer))) - }), - ) - it.effect("sequences returns the latest committed seq per aggregate and omits unknown aggregates", () => Effect.gen(function* () { const events = yield* EventV2.Service diff --git a/packages/core/test/session-runner-tool-events.test.ts b/packages/core/test/session-runner-tool-events.test.ts index d016b2694b7..983dca8c2cd 100644 --- a/packages/core/test/session-runner-tool-events.test.ts +++ b/packages/core/test/session-runner-tool-events.test.ts @@ -29,7 +29,6 @@ const capture = () => { subscribe: () => Stream.empty, live: () => Stream.empty, log: () => Stream.empty, - changes: () => Stream.empty, sequences: () => Effect.succeed(new Map()), listen: () => Effect.succeed(Effect.void), project: () => Effect.void, diff --git a/packages/protocol/src/groups/event.ts b/packages/protocol/src/groups/event.ts index e555abe3f91..242aa745ef5 100644 --- a/packages/protocol/src/groups/event.ts +++ b/packages/protocol/src/groups/event.ts @@ -1,5 +1,4 @@ import { Event } from "@opencode-ai/schema/event" -import { EventLog } from "@opencode-ai/schema/event-log" import { EventManifest } from "@opencode-ai/schema/event-manifest" import { Location } from "@opencode-ai/schema/location" import type { Definition } from "@opencode-ai/schema/event" @@ -39,19 +38,7 @@ const make = >(definitions: identifier: "v2.event.subscribe", summary: "Subscribe to events", description: - "Subscribe to native event payloads for the server. Volatile by contract: a slow consumer overflows and fails the stream, and events during disconnection are missed. Consumers that need reliability should combine the changes feed with durable session log reads.", - }), - ), - ) - .add( - HttpApiEndpoint.get("event.changes", "/api/event/changes", { - success: HttpApiSchema.StreamSse({ data: EventLog.Change }), - }).annotateMerge( - OpenApi.annotations({ - identifier: "v2.event.changes", - summary: "Subscribe to change hints", - description: - "Payload-free hint channel: after an event commits, a subscriber eventually receives a hint for that aggregate with seq at or beyond the event, or a sweep-required marker. Hints coalesce to the latest seq per aggregate under backpressure and the stream never fails from overflow. No consumer may derive correctness from receiving a hint; correctness always comes from durable log reads plus the consumer's own checkpoint. A sweep-required marker is emitted first on every (re)subscribe and whenever hint retention is exceeded: treat every aggregate as potentially dirty and recover via bounded sweep plus log reads.", + "Subscribe to native event payloads for the server. Volatile by contract: a slow consumer overflows and fails the stream, and events during disconnection are missed.", }), ), ) diff --git a/packages/protocol/src/groups/message.ts b/packages/protocol/src/groups/message.ts index b2a360cd106..b8c387576f0 100644 --- a/packages/protocol/src/groups/message.ts +++ b/packages/protocol/src/groups/message.ts @@ -1,7 +1,5 @@ import { Session } from "@opencode-ai/schema/session" import { SessionMessage } from "@opencode-ai/schema/session-message" -import { optional } from "@opencode-ai/schema/schema" -import { Event } from "@opencode-ai/schema/event" import { Schema } from "effect" import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi" import { InvalidCursorError, SessionNotFoundError, UnknownError } from "../errors.js" @@ -30,10 +28,6 @@ export const MessageGroup = HttpApiGroup.make("server.message") query: SessionMessagesQuery, success: Schema.Struct({ data: Schema.Array(SessionMessage.Message), - watermark: optional(Event.Seq).annotate({ - description: - "Durable log seq this snapshot was computed at, read before the snapshot. Attach a live log read after the watermark to compose fetch and stream gap-free; events between the watermark and the snapshot read may be redelivered by the tail and are safe to re-apply. Absent when the session has no durable events.", - }), cursor: Schema.Struct({ previous: Schema.String.pipe(Schema.optional), next: Schema.String.pipe(Schema.optional), diff --git a/packages/protocol/src/groups/session.ts b/packages/protocol/src/groups/session.ts index d89918f515b..3d82cd3297d 100644 --- a/packages/protocol/src/groups/session.ts +++ b/packages/protocol/src/groups/session.ts @@ -104,12 +104,6 @@ const SessionActive = Schema.Struct({ type: Schema.Literal("running"), }).annotate({ identifier: "SessionActive" }) -const SessionWatermarks = Schema.Record(Session.ID, Event.Seq).annotate({ - identifier: "SessionWatermarks", - description: - "Durable log seq each session's snapshot was computed at. Attach a live log read after the watermark to compose fetch and stream gap-free; apply a snapshot only where its watermark is at or beyond already-applied events. Sessions without durable events are absent.", -}) - const BooleanFromString = Schema.Literals(["true", "false"]).pipe( Schema.decodeTo(Schema.Boolean, { decode: SchemaGetter.transform((value) => value === "true"), @@ -136,7 +130,6 @@ export const makeSessionGroup = (sessionLo query: SessionsQuery, success: Schema.Struct({ data: Schema.Array(Session.Info), - watermarks: SessionWatermarks, cursor: Schema.Struct({ previous: SessionsCursor.pipe(Schema.optional), next: SessionsCursor.pipe(Schema.optional), @@ -171,13 +164,13 @@ export const makeSessionGroup = (sessionLo ) .add( HttpApiEndpoint.get("session.active", "/api/session/active", { - success: Schema.Struct({ data: Schema.Record(Session.ID, SessionActive), watermarks: SessionWatermarks }), + success: Schema.Struct({ data: Schema.Record(Session.ID, SessionActive) }), }).annotateMerge( OpenApi.annotations({ identifier: "v2.session.active", summary: "List active sessions", description: - "Retrieve foreground Session drains currently owned by this OpenCode process. Sessions absent from the result are inactive. Watermarks are the durable log positions read alongside the activity snapshot; activity itself is process state, so the pairing is advisory rather than transactional.", + "Retrieve foreground Session drains currently owned by this OpenCode process. Sessions absent from the result are inactive.", }), ), ) @@ -498,7 +491,7 @@ export const makeSessionGroup = (sessionLo ), ) .add( - HttpApiEndpoint.get("session.log", "/api/session/:sessionID/log", { + HttpApiEndpoint.get("session.log", "/api/experimental/session/:sessionID/log", { params: { sessionID: Session.ID }, query: { after: Schema.NumberFromString.pipe(Schema.decodeTo(Event.Seq), Schema.optional), @@ -515,7 +508,7 @@ export const makeSessionGroup = (sessionLo identifier: "v2.session.log", summary: "Read the session log", description: - "Durable, ordered, gap-free read of public session events after an exclusive aggregate sequence. Emits a synced marker once replay reaches the captured watermark, then completes; with follow=true it continues with live events instead. The only event API that promises reliability: attach after a snapshot watermark to compose fetch and stream without a race window.", + "Experimental durable session event log. Reads events after an exclusive aggregate sequence and continues with live events when follow=true.", }), ), ) diff --git a/packages/schema/src/event-log.ts b/packages/schema/src/event-log.ts index 1b0bbcb924b..40910870564 100644 --- a/packages/schema/src/event-log.ts +++ b/packages/schema/src/event-log.ts @@ -19,37 +19,3 @@ export const Synced = Schema.Struct({ "Marker emitted once when a log read reaches its captured watermark. The reader holds every event committed at or below seq.", }) export interface Synced extends Schema.Schema.Type {} - -/** - * A payload-free doorbell: the aggregate's log advanced to at least `seq`. - * Hints are a latency optimization only; no consumer may derive correctness - * from receiving one. Correctness always comes from a durable log read plus - * the consumer's own checkpoint. - */ -export const Hint = Schema.Struct({ - type: Schema.Literal("log.hint"), - aggregateID: Schema.String, - seq: Event.Seq, -}).annotate({ - identifier: "EventLog.Hint", - description: - "Payload-free change hint: the aggregate's durable log advanced to at least seq. Hints coalesce under backpressure (latest per aggregate) and are never a delivery guarantee.", -}) -export interface Hint extends Schema.Schema.Type {} - -/** - * Hints may have been lost. Treat every aggregate as potentially dirty and - * recover via bounded sweep plus durable log reads. Also emitted first on - * every (re)subscribe, since hints during disconnection were never buffered. - */ -export const SweepRequired = Schema.Struct({ - type: Schema.Literal("log.sweep_required"), -}).annotate({ - identifier: "EventLog.SweepRequired", - description: - "Hints may have been lost; treat every aggregate as potentially dirty and recover via bounded sweep plus durable log reads. Emitted first on every (re)subscribe.", -}) -export interface SweepRequired extends Schema.Schema.Type {} - -export const Change = Schema.Union([Hint, SweepRequired]).annotate({ identifier: "EventLog.Change" }) -export type Change = typeof Change.Type diff --git a/packages/schema/src/event.ts b/packages/schema/src/event.ts index 9f7c347b039..34e44958073 100644 --- a/packages/schema/src/event.ts +++ b/packages/schema/src/event.ts @@ -14,7 +14,7 @@ export type ID = typeof ID.Type /** * Position in one aggregate's durable log. Values originate from the durable - * event envelope, synced markers, change hints, and snapshot watermarks; + * event envelope and synced markers; * `after` cursors accept only values that came from those sources. */ export const Seq = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)).pipe(Schema.brand("Event.Seq")) diff --git a/packages/sdk-next/test/embedded.test.ts b/packages/sdk-next/test/embedded.test.ts index 4ac31b70ab6..a6184da8379 100644 --- a/packages/sdk-next/test/embedded.test.ts +++ b/packages/sdk-next/test/embedded.test.ts @@ -117,7 +117,7 @@ it.live( expect(selected.model?.id).toBe(model.id) expect(selected.model?.providerID).toBe(model.providerID) expect(page.data.some((session) => session.id === id)).toBe(true) - expect(active).toEqual({ data: {}, watermarks: {} }) + expect(active).toEqual({}) expect(admitted.sessionID).toBe(id) expect(prompted.type).toBe("session.prompt.promoted") expect(wakeContext).toContainEqual(expect.objectContaining({ id: wake.id, type: "user" })) diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 59484dddfb5..2243f8e89db 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -278,8 +278,6 @@ import type { V2CredentialUpdateResponses, V2DebugLocationErrors, V2DebugLocationResponses, - V2EventChangesErrors, - V2EventChangesResponses, V2EventSubscribeErrors, V2EventSubscribeResponses, V2FormRequestListErrors, @@ -334,6 +332,8 @@ import type { V2ProjectCurrentResponses, V2ProjectDirectoriesErrors, V2ProjectDirectoriesResponses, + V2ProjectListErrors, + V2ProjectListResponses, V2ProviderGetErrors, V2ProviderGetResponses, V2ProviderListErrors, @@ -5896,7 +5896,7 @@ export class Session3 extends HeyApiClient { /** * List active sessions * - * Retrieve foreground Session drains currently owned by this OpenCode process. Sessions absent from the result are inactive. Watermarks are the durable log positions read alongside the activity snapshot; activity itself is process state, so the pairing is advisory rather than transactional. + * Retrieve foreground Session drains currently owned by this OpenCode process. Sessions absent from the result are inactive. */ public active(options?: Options) { return (options?.client ?? this.client).get({ @@ -6341,7 +6341,7 @@ export class Session3 extends HeyApiClient { /** * Read the session log * - * Durable, ordered, gap-free read of public session events after an exclusive aggregate sequence. Emits a synced marker once replay reaches the captured watermark, then completes; with follow=true it continues with live events instead. The only event API that promises reliability: attach after a snapshot watermark to compose fetch and stream without a race window. + * Experimental durable session event log. Reads events after an exclusive aggregate sequence and continues with live events when follow=true. */ public log( parameters: { @@ -6364,7 +6364,7 @@ export class Session3 extends HeyApiClient { ], ) return (options?.client ?? this.client).sse.get({ - url: "/api/session/{sessionID}/log", + url: "/api/experimental/session/{sessionID}/log", ...options, ...params, }) @@ -7032,6 +7032,18 @@ export class Credential extends HeyApiClient { } export class Project2 extends HeyApiClient { + /** + * List projects + * + * List known projects. + */ + public list(options?: Options) { + return (options?.client ?? this.client).get({ + url: "/api/project", + ...options, + }) + } + /** * Get current project * @@ -7357,7 +7369,7 @@ export class Event2 extends HeyApiClient { /** * Subscribe to events * - * Subscribe to native event payloads for the server. Volatile by contract: a slow consumer overflows and fails the stream, and events during disconnection are missed. Consumers that need reliability should combine the changes feed with durable session log reads. + * Subscribe to native event payloads for the server. Volatile by contract: a slow consumer overflows and fails the stream, and events during disconnection are missed. */ public subscribe(options?: Options) { return (options?.client ?? this.client).sse.get({ @@ -7365,18 +7377,6 @@ export class Event2 extends HeyApiClient { ...options, }) } - - /** - * Subscribe to change hints - * - * Payload-free hint channel: after an event commits, a subscriber eventually receives a hint for that aggregate with seq at or beyond the event, or a sweep-required marker. Hints coalesce to the latest seq per aggregate under backpressure and the stream never fails from overflow. No consumer may derive correctness from receiving a hint; correctness always comes from durable log reads plus the consumer's own checkpoint. A sweep-required marker is emitted first on every (re)subscribe and whenever hint retention is exceeded: treat every aggregate as potentially dirty and recover via bounded sweep plus log reads. - */ - public changes(options?: Options) { - return (options?.client ?? this.client).sse.get({ - url: "/api/event/changes", - ...options, - }) - } } export class Pty2 extends HeyApiClient { diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index 4d2cf1922c4..de17b34bb65 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -2796,13 +2796,8 @@ export type UnauthorizedError = { message: string } -export type SessionWatermarks = { - [key: string]: unknown | number -} - export type SessionsResponse = { data: Array - watermarks: SessionWatermarks cursor: { previous?: string next?: string @@ -2930,7 +2925,6 @@ export type SessionLogItemStream = string export type SessionMessagesResponse = { data: Array - watermark?: number cursor: { previous?: string next?: string @@ -6615,20 +6609,6 @@ export type GlobalDisposed = { } } -export type EventLogHint = { - type: "log.hint" - aggregateID: string - seq: number -} - -export type EventLogSweepRequired = { - type: "log.sweep_required" -} - -export type EventLogChange = EventLogHint | EventLogSweepRequired - -export type EventLogChangeStream = string - export type QuestionV2Request = { id: string sessionID: string @@ -7859,16 +7839,8 @@ export type SessionV2Info2 = { revert?: RevertState2 } -/** - * Durable log seq each session's snapshot was computed at. Attach a live log read after the watermark to compose fetch and stream gap-free; apply a snapshot only where its watermark is at or beyond already-applied events. Sessions without durable events are absent. - */ -export type SessionWatermarksV2 = { - [key: string]: unknown | number -} - export type SessionsResponseV2 = { data: Array - watermarks: SessionWatermarksV2 cursor: { previous?: string | null next?: string | null @@ -9059,7 +9031,6 @@ export type SessionLogItemStreamV2 = string export type SessionMessagesResponseV2 = { data: Array - watermark?: number cursor: { previous?: string | null next?: string | null @@ -9329,6 +9300,38 @@ export type McpServer2 = { integrationID?: string } +export type ProjectVcs2 = "git" | "hg" + +export type ProjectIcon2 = { + url?: string + override?: string + color?: string +} + +export type ProjectCommands2 = { + /** + * Startup script to run when creating a new workspace (worktree) + */ + start?: string +} + +export type ProjectTime2 = { + created: number + updated: number + initialized?: number +} + +export type ProjectV2 = { + id: string + worktree: string + vcs?: ProjectVcs2 + name?: string + icon?: ProjectIcon2 + commands?: ProjectCommands2 + time: ProjectTime2 + sandboxes: Array +} + export type ProjectCurrent2 = { id: string directory: string @@ -11276,26 +11279,6 @@ export type V2EventV2 = export type V2EventStreamV2 = string -/** - * Payload-free change hint: the aggregate's durable log advanced to at least seq. Hints coalesce under backpressure (latest per aggregate) and are never a delivery guarantee. - */ -export type EventLogHint2 = { - type: "log.hint" - aggregateID: string - seq: number -} - -/** - * Hints may have been lost; treat every aggregate as potentially dirty and recover via bounded sweep plus durable log reads. Emitted first on every (re)subscribe. - */ -export type EventLogSweepRequired2 = { - type: "log.sweep_required" -} - -export type EventLogChange2 = EventLogHint2 | EventLogSweepRequired2 - -export type EventLogChangeStream2 = string - export type PtyNotFoundErrorV2 = { _tag: "PtyNotFoundError" ptyID: string @@ -15770,7 +15753,6 @@ export type V2SessionActiveResponses = { data: { [key: string]: unknown | SessionActiveV2 } - watermarks: SessionWatermarksV2 } } @@ -16563,7 +16545,7 @@ export type V2SessionLogData = { after?: number | null follow?: "true" | "false" | null } - url: "/api/session/{sessionID}/log" + url: "/api/experimental/session/{sessionID}/log" } export type V2SessionLogErrors = { @@ -17353,6 +17335,35 @@ export type V2CredentialUpdateResponses = { export type V2CredentialUpdateResponse = V2CredentialUpdateResponses[keyof V2CredentialUpdateResponses] +export type V2ProjectListData = { + body?: never + path?: never + query?: never + url: "/api/project" +} + +export type V2ProjectListErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 +} + +export type V2ProjectListError = V2ProjectListErrors[keyof V2ProjectListErrors] + +export type V2ProjectListResponses = { + /** + * Success + */ + 200: Array +} + +export type V2ProjectListResponse = V2ProjectListResponses[keyof V2ProjectListResponses] + export type V2ProjectCurrentData = { body?: never path?: never @@ -18176,39 +18187,6 @@ export type V2EventSubscribeResponses = { export type V2EventSubscribeResponse = V2EventSubscribeResponses[keyof V2EventSubscribeResponses] -export type V2EventChangesData = { - body?: never - path?: never - query?: never - url: "/api/event/changes" -} - -export type V2EventChangesErrors = { - /** - * InvalidRequestError - */ - 400: InvalidRequestErrorV2 - /** - * UnauthorizedError - */ - 401: UnauthorizedErrorV2 -} - -export type V2EventChangesError = V2EventChangesErrors[keyof V2EventChangesErrors] - -export type V2EventChangesResponses = { - /** - * Success - */ - 200: { - id: string | null - event: string - data: EventLogChangeStream2 - } -} - -export type V2EventChangesResponse = V2EventChangesResponses[keyof V2EventChangesResponses] - export type V2PtyListData = { body?: never path?: never diff --git a/packages/server/src/handlers/event.ts b/packages/server/src/handlers/event.ts index 1c8b94d1240..e17c815cb8a 100644 --- a/packages/server/src/handlers/event.ts +++ b/packages/server/src/handlers/event.ts @@ -20,41 +20,36 @@ function eventData(data: unknown): Sse.Event { export const EventHandler = HttpApiBuilder.group(Api, "server.event", (handlers) => Effect.gen(function* () { const events = yield* EventV2.Service - return handlers - .handle( - "event.changes", - Effect.fn(() => Effect.succeed(events.changes())), - ) - .handleRaw("event.subscribe", () => - Effect.gen(function* () { - const connected = { - id: EventV2.ID.create(), - type: "server.connected", - data: {}, - } - const output = Stream.unwrap( - Effect.gen(function* () { - // Acquiring the bounded stream installs its listener before readiness is observable. - const live = yield* EventV2.liveBounded(events, { - capacity: subscriberCapacity, - accept: isOpenCodeEvent, - }) - return Stream.make(connected).pipe(Stream.concat(live)) - }), - ).pipe(Stream.map(eventData), Stream.pipeThroughChannel(Sse.encode())) - const heartbeat = Stream.tick("15 seconds").pipe(Stream.map(() => ": heartbeat\n\n")) - return HttpServerResponse.stream( - output.pipe(Stream.merge(heartbeat, { haltStrategy: "left" }), Stream.encodeText), - { - contentType: "text/event-stream", - headers: { - "Cache-Control": "no-cache, no-transform", - "X-Accel-Buffering": "no", - "X-Content-Type-Options": "nosniff", - }, + return handlers.handleRaw("event.subscribe", () => + Effect.gen(function* () { + const connected = { + id: EventV2.ID.create(), + type: "server.connected", + data: {}, + } + const output = Stream.unwrap( + Effect.gen(function* () { + // Acquiring the bounded stream installs its listener before readiness is observable. + const live = yield* EventV2.liveBounded(events, { + capacity: subscriberCapacity, + accept: isOpenCodeEvent, + }) + return Stream.make(connected).pipe(Stream.concat(live)) + }), + ).pipe(Stream.map(eventData), Stream.pipeThroughChannel(Sse.encode())) + const heartbeat = Stream.tick("15 seconds").pipe(Stream.map(() => ": heartbeat\n\n")) + return HttpServerResponse.stream( + output.pipe(Stream.merge(heartbeat, { haltStrategy: "left" }), Stream.encodeText), + { + contentType: "text/event-stream", + headers: { + "Cache-Control": "no-cache, no-transform", + "X-Accel-Buffering": "no", + "X-Content-Type-Options": "nosniff", }, - ) - }), - ) + }, + ) + }), + ) }), ) diff --git a/packages/server/src/handlers/message.ts b/packages/server/src/handlers/message.ts index 85de308fca4..93734c628d8 100644 --- a/packages/server/src/handlers/message.ts +++ b/packages/server/src/handlers/message.ts @@ -38,10 +38,6 @@ export const MessageHandler = HttpApiBuilder.group(Api, "server.message", (handl catch: () => new InvalidCursorError({ message: "Invalid cursor" }), }) const order = decoded?.order ?? ctx.query.order ?? "desc" - // Read the watermark before the snapshot: an understated watermark only - // redelivers already-reflected events, while an overstated one would let - // an attached tail skip events missing from the snapshot. - const watermark = (yield* session.watermarks([ctx.params.sessionID])).get(ctx.params.sessionID) const messages = yield* session .messages({ sessionID: ctx.params.sessionID, @@ -74,7 +70,6 @@ export const MessageHandler = HttpApiBuilder.group(Api, "server.message", (handl const last = messages.at(-1) return { data: messages, - watermark, cursor: { previous: first ? cursor.encode(first, order, "previous") : undefined, next: last ? cursor.encode(last, order, "next") : undefined, diff --git a/packages/server/src/handlers/session.ts b/packages/server/src/handlers/session.ts index 8a3cf1b1305..72d238e6842 100644 --- a/packages/server/src/handlers/session.ts +++ b/packages/server/src/handlers/session.ts @@ -44,7 +44,6 @@ export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handl const last = sessions.at(-1) return { data: sessions, - watermarks: Object.fromEntries(page.watermarks), cursor: { previous: first ? SessionsCursor.make({ @@ -89,10 +88,8 @@ export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handl "session.active", Effect.fn(function* () { const active = yield* session.active - const watermarks = yield* session.watermarks(Array.from(active)) return { data: Object.fromEntries(Array.from(active, (sessionID) => [sessionID, { type: "running" as const }])), - watermarks: Object.fromEntries(watermarks), } }), ) diff --git a/packages/tui/src/context/data.tsx b/packages/tui/src/context/data.tsx index d9b29c1fdd8..aa27572ac4b 100644 --- a/packages/tui/src/context/data.tsx +++ b/packages/tui/src/context/data.tsx @@ -911,7 +911,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ .then((active) => { if (generation !== connectionGeneration) return const status: Record = Object.fromEntries( - Object.keys(active.data).map((sessionID) => [sessionID, "running" as const]), + Object.keys(active).map((sessionID) => [sessionID, "running" as const]), ) for (const sessionID of changed) status[sessionID] = store.session.status[sessionID] setStore("session", "status", reconcile(status)) diff --git a/packages/tui/test/cli/tui/data.test.tsx b/packages/tui/test/cli/tui/data.test.tsx index 6c33f8496f0..1820e58f290 100644 --- a/packages/tui/test/cli/tui/data.test.tsx +++ b/packages/tui/test/cli/tui/data.test.tsx @@ -119,7 +119,7 @@ test("reconnects the event stream and bootstraps fresh data", async () => { } if (url.pathname === "/api/session/active") { requests.active++ - if (requests.active === 1) return json({ data: { "session-stale": { type: "running" } }, watermarks: {} }) + if (requests.active === 1) return json({ data: { "session-stale": { type: "running" } } }) return new Promise((resolve) => { resolveActive = resolve }) @@ -189,7 +189,7 @@ test("reconnects the event stream and bootstraps fresh data", async () => { }, }) await wait(() => data.session.status("session-new") === "running") - resolveActive(json({ data: {}, watermarks: {} })) + resolveActive(json({ data: {} })) await wait(() => data.location.model.list()?.[0]?.id === "model-2", 4000) await wait(() => data.session.status("session-stale") === "idle") @@ -350,7 +350,7 @@ test("tracks session status from active sessions and execution events", async () const events = createEventStream() const calls = createFetch((url) => { if (url.pathname === "/api/session/active") - return json({ data: { "session-active": { type: "running" } }, watermarks: {} }) + return json({ data: { "session-active": { type: "running" } } }) }, events) let data!: ReturnType diff --git a/packages/tui/test/fixture/tui-sdk.ts b/packages/tui/test/fixture/tui-sdk.ts index 5ebe0a63f49..8c6e476db0c 100644 --- a/packages/tui/test/fixture/tui-sdk.ts +++ b/packages/tui/test/fixture/tui-sdk.ts @@ -100,7 +100,7 @@ export function createFetch(override?: FetchHandler, events?: ReturnType Date: Mon, 6 Jul 2026 13:00:59 -0400 Subject: [PATCH 08/46] test(opencode): update active session mock --- packages/opencode/test/cli/run/stream-v2.transport.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/test/cli/run/stream-v2.transport.test.ts b/packages/opencode/test/cli/run/stream-v2.transport.test.ts index d191419e5c9..623b93c24d5 100644 --- a/packages/opencode/test/cli/run/stream-v2.transport.test.ts +++ b/packages/opencode/test/cli/run/stream-v2.transport.test.ts @@ -108,7 +108,7 @@ function sdk(input: { ) spyOn(client.permission, "list").mockImplementation(() => ok([])) spyOn(client.question, "list").mockImplementation(() => ok([])) - spyOn(client.session, "active").mockImplementation(() => ok({ data: input.active?.() ?? {}, watermarks: {} })) + spyOn(client.session, "active").mockImplementation(() => ok(input.active?.() ?? {})) spyOn(client.session, "switchAgent").mockImplementation(() => ok(undefined)) spyOn(client.session, "switchModel").mockImplementation(() => ok(undefined)) // The generated methods have conditional return types for throwOnError; the From 06dcf3f221466b239ca272ee6ab342941ace5fad Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 6 Jul 2026 13:08:25 -0400 Subject: [PATCH 09/46] fix(tui): remove committed undo messages --- packages/core/src/session/projector.ts | 6 +-- packages/core/test/session-projector.test.ts | 9 +++- packages/core/test/session-prompt.test.ts | 3 +- packages/tui/src/context/data.tsx | 8 +++ packages/tui/test/cli/tui/data.test.tsx | 54 ++++++++++++++++++++ 5 files changed, 74 insertions(+), 6 deletions(-) diff --git a/packages/core/src/session/projector.ts b/packages/core/src/session/projector.ts index f265aa6fc98..3cbd40c2967 100644 --- a/packages/core/src/session/projector.ts +++ b/packages/core/src/session/projector.ts @@ -1,6 +1,6 @@ export * as SessionProjector from "./projector" -import { and, asc, desc, eq, gt, inArray, lt, or, sql } from "drizzle-orm" +import { and, asc, desc, eq, gt, gte, inArray, lt, or, sql } from "drizzle-orm" import { DateTime, Effect, Layer, Schema } from "effect" import { Database } from "../database/database" import { EventV2 } from "../event" @@ -698,7 +698,7 @@ const layer = Layer.effectDiscard( yield* db .delete(SessionMessageTable) .where( - and(eq(SessionMessageTable.session_id, event.data.sessionID), gt(SessionMessageTable.seq, boundary.seq)), + and(eq(SessionMessageTable.session_id, event.data.sessionID), gte(SessionMessageTable.seq, boundary.seq)), ) .run() .pipe(Effect.orDie) @@ -707,7 +707,7 @@ const layer = Layer.effectDiscard( .where( and( eq(SessionInputTable.session_id, event.data.sessionID), - or(gt(SessionInputTable.admitted_seq, boundary.seq), gt(SessionInputTable.promoted_seq, boundary.seq)), + or(gte(SessionInputTable.admitted_seq, boundary.seq), gte(SessionInputTable.promoted_seq, boundary.seq)), ), ) .run() diff --git a/packages/core/test/session-projector.test.ts b/packages/core/test/session-projector.test.ts index 1d77303d43b..bb53c134057 100644 --- a/packages/core/test/session-projector.test.ts +++ b/packages/core/test/session-projector.test.ts @@ -70,9 +70,14 @@ describe("SessionProjector", () => { }) .run() const boundary = SessionMessage.ID.make("msg_boundary") + const earlier = SessionMessage.ID.make("msg_earlier") yield* db .insert(SessionMessageTable) - .values([assistantRow(boundary, 1), assistantRow(SessionMessage.ID.make("msg_later"), 2)]) + .values([ + assistantRow(earlier, 0), + assistantRow(boundary, 1), + assistantRow(SessionMessage.ID.make("msg_later"), 2), + ]) .run() yield* db .insert(SessionContextCheckpointTable) @@ -100,7 +105,7 @@ describe("SessionProjector", () => { }) expect( (yield* db.select({ id: SessionMessageTable.id }).from(SessionMessageTable).all()).map((row) => row.id), - ).toEqual([boundary]) + ).toEqual([earlier]) // A committed revert resets the context checkpoint so the next turn re-initializes. expect(yield* db.select().from(SessionContextCheckpointTable).get().pipe(Effect.orDie)).toBeUndefined() }), diff --git a/packages/core/test/session-prompt.test.ts b/packages/core/test/session-prompt.test.ts index e7d3f5189f8..9ef5b5d822b 100644 --- a/packages/core/test/session-prompt.test.ts +++ b/packages/core/test/session-prompt.test.ts @@ -212,7 +212,8 @@ describe("SessionV2.prompt", () => { (yield* db.select({ id: SessionMessageTable.id }).from(SessionMessageTable).all().pipe(Effect.orDie)).map( (row) => row.id, ), - ).not.toContain(stale) + ).not.toContainAnyValues([boundary.id, stale]) + expect(yield* SessionInput.find(db, boundary.id)).toBeUndefined() }), ) diff --git a/packages/tui/src/context/data.tsx b/packages/tui/src/context/data.tsx index aa27572ac4b..ae6626be394 100644 --- a/packages/tui/src/context/data.tsx +++ b/packages/tui/src/context/data.tsx @@ -553,9 +553,17 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ setStore("session", "info", event.data.sessionID, "revert", event.data.revert) break case "session.revert.cleared": + if (store.session.info[event.data.sessionID]) + setStore("session", "info", event.data.sessionID, "revert", undefined) + break case "session.revert.committed": if (store.session.info[event.data.sessionID]) setStore("session", "info", event.data.sessionID, "revert", undefined) + message.update(event.data.sessionID, (draft, index) => { + const position = draft.findIndex((item) => item.id >= event.data.messageID) + if (position === -1) return + for (const item of draft.splice(position)) index.delete(item.id) + }) break case "session.compaction.delta": break diff --git a/packages/tui/test/cli/tui/data.test.tsx b/packages/tui/test/cli/tui/data.test.tsx index 1820e58f290..0e43377657a 100644 --- a/packages/tui/test/cli/tui/data.test.tsx +++ b/packages/tui/test/cli/tui/data.test.tsx @@ -284,6 +284,60 @@ test("completes exploration when a queued prompt is promoted", async () => { } }) +test("removes committed revert messages from local state", async () => { + const events = createEventStream() + const sessionID = "session-revert" + const calls = createFetch((url) => { + if (url.pathname === `/api/session/${sessionID}/message`) return json({ data: [], cursor: {} }) + }, events) + let data!: ReturnType + + function Probe() { + data = useData() + return + } + + const app = await testRender(() => ( + + + + + + + + + + )) + + try { + for (const [seq, inputID] of ["msg_001", "msg_002", "msg_003"].entries()) { + emitEvent(events, { + id: EventV2.ID.create(), + created: seq, + type: "session.prompt.admitted", + durable: durable(sessionID, seq), + data: { sessionID, inputID, prompt: { text: inputID }, delivery: "steer" }, + }) + } + await wait(() => data.session.message.ids(sessionID).length === 3) + + emitEvent(events, { + id: EventV2.ID.create(), + created: 3, + type: "session.revert.committed", + durable: durable(sessionID, 3), + data: { sessionID, messageID: "msg_002" }, + }) + + await wait(() => data.session.message.ids(sessionID).length === 1) + expect(data.session.message.ids(sessionID)).toEqual(["msg_001"]) + expect(data.session.message.get(sessionID, "msg_002")).toBeUndefined() + expect(data.session.message.get(sessionID, "msg_003")).toBeUndefined() + } finally { + app.renderer.destroy() + } +}) + test("connectedOnce is false until first connect and persists across disconnect", async () => { const encoder = new TextEncoder() let stream: ReadableStreamDefaultController | undefined From 28301769723fda788205a223c7b21c3f5f4d275e Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Mon, 6 Jul 2026 13:36:19 -0400 Subject: [PATCH 10/46] fix(plugin): reload late SDK plugins (#35576) --- packages/core/src/event.ts | 27 ++- packages/core/src/plugin/host.ts | 22 ++- packages/core/src/plugin/sdk.ts | 13 +- packages/core/src/plugin/supervisor.ts | 2 +- packages/core/src/tool/apply-patch.ts | 223 +++++++++++------------ packages/core/src/tool/edit.ts | 213 +++++++++++----------- packages/core/src/tool/glob.ts | 121 +++++++------ packages/core/src/tool/grep.ts | 149 +++++++-------- packages/core/src/tool/question.ts | 117 ++++++------ packages/core/src/tool/read.ts | 179 +++++++++--------- packages/core/src/tool/shell.ts | 229 ++++++++++++------------ packages/core/src/tool/skill.ts | 77 ++++---- packages/core/src/tool/subagent.ts | 148 +++++++-------- packages/core/src/tool/todowrite.ts | 47 ++--- packages/core/src/tool/webfetch.ts | 105 +++++------ packages/core/src/tool/websearch.ts | 107 +++++------ packages/core/src/tool/write.ts | 67 +++---- packages/core/test/event.test.ts | 26 +++ packages/core/test/lib/tool.ts | 20 ++- packages/core/test/plugin.test.ts | 52 +++--- packages/core/test/plugin/host.ts | 2 +- packages/plugin/src/v2/effect/index.ts | 2 +- packages/plugin/src/v2/effect/tool.ts | 9 +- packages/sdk-next/README.md | 2 +- packages/sdk-next/src/opencode.ts | 3 +- packages/sdk-next/test/embedded.test.ts | 135 +++++++++++++- 26 files changed, 1181 insertions(+), 916 deletions(-) diff --git a/packages/core/src/event.ts b/packages/core/src/event.ts index 6b6d7813e5f..03c539642bd 100644 --- a/packages/core/src/event.ts +++ b/packages/core/src/event.ts @@ -111,13 +111,26 @@ export type LogItem = Payload | EventLog.Synced export const isSynced = (item: LogItem): item is EventLog.Synced => item.type === "log.synced" +export type SubscribePayload = D[number] extends infer Item + ? Item extends Definition + ? Payload + : never + : never + +export interface Subscribe { + (definition: D): Stream.Stream> + (definitions: D): Stream.Stream> +} + +const isDefinition = (input: Definition | readonly Definition[]): input is Definition => !Array.isArray(input) + export interface Interface { readonly publish: ( definition: D, data: Data, options?: PublishOptions, ) => Effect.Effect> - readonly subscribe: (definition: D) => Stream.Stream> + readonly subscribe: Subscribe /** * Volatile live channel: every event published from now on, nothing before, * nothing across a disconnect. The only channel that carries non-durable @@ -562,11 +575,21 @@ export const layerWith = (options?: LayerOptions) => ), ) - const subscribe = (definition: D): Stream.Stream> => + const subscribeOne = (definition: D): Stream.Stream> => local(Stream.unwrap(getOrCreate(definition).pipe(Effect.map((pubsub) => Stream.fromPubSub(pubsub))))).pipe( Stream.map((event) => event as Payload), ) + function subscribe(definition: D): Stream.Stream> + function subscribe( + definitions: D, + ): Stream.Stream> + function subscribe(input: Definition | readonly Definition[]): Stream.Stream { + if (isDefinition(input)) return subscribeOne(input) + const types = new Set(input.map((definition) => definition.type)) + return streamLive().pipe(Stream.filter((event) => types.has(event.type))) + } + const streamLive = (): Stream.Stream => local(Stream.fromPubSub(pubsub.live)) const readAfter = ( diff --git a/packages/core/src/plugin/host.ts b/packages/core/src/plugin/host.ts index 2e58c6b1440..03c92854142 100644 --- a/packages/core/src/plugin/host.ts +++ b/packages/core/src/plugin/host.ts @@ -18,6 +18,7 @@ import { ProviderV2 } from "../provider" import { Reference } from "../reference" import { AbsolutePath, type DeepMutable } from "../schema" import { SkillV2 } from "../skill" +import { Tool } from "../tool/tool" import { Tools } from "../tool/tools" import { ToolHooks } from "../tool/hooks" import { WorkspaceV2 } from "../workspace" @@ -298,7 +299,26 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int }), }, tool: { - register: (input, options) => tools.register(input, options), + transform: (callback) => + Effect.gen(function* () { + const registrations: Array<{ + readonly name: string + readonly tool: Tool.AnyTool + readonly options?: Tool.RegisterOptions + }> = [] + yield* Effect.sync(() => + callback({ + add: (name, tool, options) => { + registrations.push({ name, tool, ...(options ? { options } : {}) }) + }, + }), + ) + yield* Effect.forEach( + registrations, + (registration) => tools.register({ [registration.name]: registration.tool }, registration.options), + { discard: true }, + ) + }), execute: { before: (callback) => toolHooks.hook.before((event) => { diff --git a/packages/core/src/plugin/sdk.ts b/packages/core/src/plugin/sdk.ts index 221fb5fae9a..f6ceb06a8fb 100644 --- a/packages/core/src/plugin/sdk.ts +++ b/packages/core/src/plugin/sdk.ts @@ -3,6 +3,9 @@ export * as SdkPlugins from "./sdk" import type { Plugin } from "@opencode-ai/plugin/v2/effect" import { Context, Effect, Layer } from "effect" import { makeGlobalNode } from "../effect/app-node" +import { EventV2 } from "../event" + +export const Updated = EventV2.ephemeral({ type: "sdk.plugin.updated", schema: {} }) export interface Store { readonly plugins: Map @@ -16,9 +19,8 @@ const defaultStore = makeStore() * Holds the plugins an embedder (the `@opencode-ai/sdk-next` host) contributes, * so `PluginSupervisor` can add them on every Location boot through the ordinary * generation path that `PluginSupervisor` uses for plugins discovered from - * config. A plugin registered after a Location has booted only - * applies to Locations booted afterward, matching config-plugin timing; - * embedders register at startup before creating Sessions. + * config. Registration publishes an unlocated update so every booted Location + * reloads its plugin generation from the shared store. * * The store is shared explicitly between the SDK construction graph and the * embedded route graph because `LocationServiceMap` builds Location layers lazily @@ -36,6 +38,7 @@ export const layerWithStore = (store: Store) => Layer.effect( Service, Effect.gen(function* () { + const events = yield* EventV2.Service yield* Effect.addFinalizer(() => Effect.sync(() => { store.plugins.clear() @@ -45,7 +48,7 @@ export const layerWithStore = (store: Store) => register: (plugin) => Effect.sync(() => { store.plugins.set(plugin.id, plugin) - }), + }).pipe(Effect.andThen(events.publish(Updated, {})), Effect.asVoid), all: () => [...store.plugins.values()], }) }), @@ -53,4 +56,4 @@ export const layerWithStore = (store: Store) => export const layer = layerWithStore(defaultStore) -export const node = makeGlobalNode({ service: Service, layer, deps: [] }) +export const node = makeGlobalNode({ service: Service, layer, deps: [EventV2.node] }) diff --git a/packages/core/src/plugin/supervisor.ts b/packages/core/src/plugin/supervisor.ts index 4d648a7d6f3..4c4e71be17f 100644 --- a/packages/core/src/plugin/supervisor.ts +++ b/packages/core/src/plugin/supervisor.ts @@ -276,7 +276,7 @@ const layer = Layer.effect( }), ), ) - yield* events.subscribe(Event.Updated).pipe( + yield* events.subscribe([Event.Updated, SdkPlugins.Updated]).pipe( Stream.runForEach(() => reload().pipe(Effect.catchCause((cause) => Effect.logError("failed to reload plugins", { cause }))), ), diff --git a/packages/core/src/tool/apply-patch.ts b/packages/core/src/tool/apply-patch.ts index 6700e6e1ba3..2853a9130b6 100644 --- a/packages/core/src/tool/apply-patch.ts +++ b/packages/core/src/tool/apply-patch.ts @@ -63,133 +63,136 @@ export const Plugin = { const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.withPermission( - Tool.make({ - description: - "Apply one patch containing add, update, and delete file operations. All targets are resolved and approved before target contents are read. Operations apply sequentially; if a later operation fails, earlier operations remain applied and the failure reports them explicitly. Moves and atomic rollback are not supported yet.", - input: Input, - output: Output, - toModelOutput: ({ output }) => [{ type: "text", text: toModelOutput(output) }], - execute: (input, context) => { - const applied: Array = [] - const fail = (path: string) => { - const prefix = - applied.length === 0 - ? `Unable to apply patch at ${path}` - : `Patch partially applied before failing at ${path}. Applied: ${applied.map((item) => item.resource).join(", ")}` - return new ToolFailure({ message: prefix }) - } - return Effect.gen(function* () { - const source = { - type: "tool" as const, - messageID: context.assistantMessageID, - callID: context.toolCallID, + .transform((draft) => + draft.add( + name, + Tool.withPermission( + Tool.make({ + description: + "Apply one patch containing add, update, and delete file operations. All targets are resolved and approved before target contents are read. Operations apply sequentially; if a later operation fails, earlier operations remain applied and the failure reports them explicitly. Moves and atomic rollback are not supported yet.", + input: Input, + output: Output, + toModelOutput: ({ output }) => [{ type: "text", text: toModelOutput(output) }], + execute: (input, context) => { + const applied: Array = [] + const fail = (path: string) => { + const prefix = + applied.length === 0 + ? `Unable to apply patch at ${path}` + : `Patch partially applied before failing at ${path}. Applied: ${applied.map((item) => item.resource).join(", ")}` + return new ToolFailure({ message: prefix }) } - if (!input.patchText.trim()) return yield* new ToolFailure({ message: "patchText is required" }) - const hunks = yield* Effect.try({ - try: () => Patch.parse(input.patchText), - catch: (cause) => new ToolFailure({ message: `apply_patch verification failed: ${String(cause)}` }), - }) - if (hunks.length === 0) return yield* new ToolFailure({ message: "patch rejected: empty patch" }) - const move = hunks.find((hunk) => hunk.type === "update" && hunk.movePath !== undefined) - if (move) return yield* new ToolFailure({ message: "apply_patch moves are not supported yet" }) + return Effect.gen(function* () { + const source = { + type: "tool" as const, + messageID: context.assistantMessageID, + callID: context.toolCallID, + } + if (!input.patchText.trim()) return yield* new ToolFailure({ message: "patchText is required" }) + const hunks = yield* Effect.try({ + try: () => Patch.parse(input.patchText), + catch: (cause) => new ToolFailure({ message: `apply_patch verification failed: ${String(cause)}` }), + }) + if (hunks.length === 0) return yield* new ToolFailure({ message: "patch rejected: empty patch" }) + const move = hunks.find((hunk) => hunk.type === "update" && hunk.movePath !== undefined) + if (move) return yield* new ToolFailure({ message: "apply_patch moves are not supported yet" }) - const targets: Array<{ readonly hunk: Patch.Hunk; readonly target: LocationMutation.Target }> = [] - for (const hunk of hunks) - targets.push({ hunk, target: yield* mutation.resolve({ path: hunk.path, kind: "file" }) }) - const externalDirectories = new Map() - for (const { target } of targets) { - const external = target.externalDirectory - if (external) externalDirectories.set(external.resource, external) - } - for (const external of externalDirectories.values()) { + const targets: Array<{ readonly hunk: Patch.Hunk; readonly target: LocationMutation.Target }> = [] + for (const hunk of hunks) + targets.push({ hunk, target: yield* mutation.resolve({ path: hunk.path, kind: "file" }) }) + const externalDirectories = new Map() + for (const { target } of targets) { + const external = target.externalDirectory + if (external) externalDirectories.set(external.resource, external) + } + for (const external of externalDirectories.values()) { + yield* permission.assert({ + ...LocationMutation.externalDirectoryPermission(external), + sessionID: context.sessionID, + agent: context.agent, + source, + }) + } yield* permission.assert({ - ...LocationMutation.externalDirectoryPermission(external), + action: "edit", + resources: [...new Set(targets.map(({ target }) => target.resource))], + save: ["*"], sessionID: context.sessionID, agent: context.agent, source, }) - } - yield* permission.assert({ - action: "edit", - resources: [...new Set(targets.map(({ target }) => target.resource))], - save: ["*"], - sessionID: context.sessionID, - agent: context.agent, - source, - }) - const prepared: Prepared[] = [] - for (const { hunk, target } of targets) { - yield* Effect.gen(function* () { - if (hunk.type === "add") { + const prepared: Prepared[] = [] + for (const { hunk, target } of targets) { + yield* Effect.gen(function* () { + if (hunk.type === "add") { + prepared.push({ + ...hunk, + target, + before: "", + after: + hunk.contents.endsWith("\n") || hunk.contents === "" ? hunk.contents : `${hunk.contents}\n`, + }) + return + } + if ((yield* fs.stat(target.canonical)).type !== "File") yield* fail(hunk.path) + const source = yield* fs.readFile(target.canonical) + const original = new TextDecoder("utf-8", { ignoreBOM: true }).decode(source) + const before = original.replace(/^\uFEFF/, "") + if (hunk.type === "delete") { + prepared.push({ ...hunk, target, before, after: "" }) + return + } + const update = Patch.derive(hunk.path, hunk.chunks, original) prepared.push({ ...hunk, target, - before: "", - after: - hunk.contents.endsWith("\n") || hunk.contents === "" ? hunk.contents : `${hunk.contents}\n`, + source, + content: Patch.joinBom(update.content, update.bom), + before, + after: update.content, }) - return - } - if ((yield* fs.stat(target.canonical)).type !== "File") yield* fail(hunk.path) - const source = yield* fs.readFile(target.canonical) - const original = new TextDecoder("utf-8", { ignoreBOM: true }).decode(source) - const before = original.replace(/^\uFEFF/, "") - if (hunk.type === "delete") { - prepared.push({ ...hunk, target, before, after: "" }) - return - } - const update = Patch.derive(hunk.path, hunk.chunks, original) - prepared.push({ - ...hunk, - target, - source, - content: Patch.joinBom(update.content, update.bom), - before, - after: update.content, - }) - }).pipe(Effect.mapError(() => fail(hunk.path))) - } + }).pipe(Effect.mapError(() => fail(hunk.path))) + } - const patchFiles = prepared.map(patchFile) - yield* Effect.forEach( - prepared, - (change) => - Effect.gen(function* () { - if (change.type === "add") { - const result = yield* files.create({ + const patchFiles = prepared.map(patchFile) + yield* Effect.forEach( + prepared, + (change) => + Effect.gen(function* () { + if (change.type === "add") { + const result = yield* files.create({ + target: change.target, + content: + change.contents.endsWith("\n") || change.contents === "" + ? change.contents + : `${change.contents}\n`, + }) + applied.push({ type: change.type, resource: result.resource, target: result.target }) + return + } + if (change.type === "delete") { + const result = yield* files.remove({ target: change.target }) + applied.push({ type: change.type, resource: result.resource, target: result.target }) + return + } + const result = yield* files.writeIfUnchanged({ target: change.target, - content: - change.contents.endsWith("\n") || change.contents === "" - ? change.contents - : `${change.contents}\n`, + expected: change.source, + content: change.content, }) applied.push({ type: change.type, resource: result.resource, target: result.target }) - return - } - if (change.type === "delete") { - const result = yield* files.remove({ target: change.target }) - applied.push({ type: change.type, resource: result.resource, target: result.target }) - return - } - const result = yield* files.writeIfUnchanged({ - target: change.target, - expected: change.source, - content: change.content, - }) - applied.push({ type: change.type, resource: result.resource, target: result.target }) - }).pipe(Effect.mapError(() => fail(change.path))), - { discard: true }, - ) - return { applied, files: patchFiles } - }).pipe(Effect.mapError((error) => (error instanceof ToolFailure ? error : fail("patch")))) - }, - }), - "edit", + }).pipe(Effect.mapError(() => fail(change.path))), + { discard: true }, + ) + return { applied, files: patchFiles } + }).pipe(Effect.mapError((error) => (error instanceof ToolFailure ? error : fail("patch")))) + }, + }), + "edit", + ), ), - }) + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/edit.ts b/packages/core/src/tool/edit.ts index bb9bb4dee97..88feac6c346 100644 --- a/packages/core/src/tool/edit.ts +++ b/packages/core/src/tool/edit.ts @@ -94,122 +94,125 @@ export const Plugin = { const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.withPermission( - Tool.make({ - description: - "Replace exact text in one file. Relative paths resolve within the active Location. Absolute paths inside the Location are accepted. Explicit external absolute paths require external_directory approval before edit approval.", - input: Input, - output: Output, - toModelOutput: ({ input, output }) => [ - { type: "text", text: toModelOutput(output, input.oldString, input.newString) }, - ], - execute: (input, context) => { - const unableToEdit = (effect: Effect.Effect) => - effect.pipe( - Effect.mapError((error) => - error instanceof FileMutation.StaleContentError - ? new ToolFailure({ - message: "File changed after permission approval. Read it again before editing.", - }) - : new ToolFailure({ message: `Unable to edit ${input.path}` }), - ), - ) + .transform((draft) => + draft.add( + name, + Tool.withPermission( + Tool.make({ + description: + "Replace exact text in one file. Relative paths resolve within the active Location. Absolute paths inside the Location are accepted. Explicit external absolute paths require external_directory approval before edit approval.", + input: Input, + output: Output, + toModelOutput: ({ input, output }) => [ + { type: "text", text: toModelOutput(output, input.oldString, input.newString) }, + ], + execute: (input, context) => { + const unableToEdit = (effect: Effect.Effect) => + effect.pipe( + Effect.mapError((error) => + error instanceof FileMutation.StaleContentError + ? new ToolFailure({ + message: "File changed after permission approval. Read it again before editing.", + }) + : new ToolFailure({ message: `Unable to edit ${input.path}` }), + ), + ) - return Effect.gen(function* () { - const permissionSource = { - type: "tool" as const, - messageID: context.assistantMessageID, - callID: context.toolCallID, - } - if (input.oldString === input.newString) { - return yield* new ToolFailure({ - message: "No changes to apply: oldString and newString are identical.", - }) - } - if (input.oldString === "") { - return yield* new ToolFailure({ - message: "oldString must not be empty. Use write to create or overwrite a file.", - }) - } + return Effect.gen(function* () { + const permissionSource = { + type: "tool" as const, + messageID: context.assistantMessageID, + callID: context.toolCallID, + } + if (input.oldString === input.newString) { + return yield* new ToolFailure({ + message: "No changes to apply: oldString and newString are identical.", + }) + } + if (input.oldString === "") { + return yield* new ToolFailure({ + message: "oldString must not be empty. Use write to create or overwrite a file.", + }) + } + + const target = yield* unableToEdit(mutation.resolve({ path: input.path, kind: "file" })) + const external = target.externalDirectory + if (external) { + yield* unableToEdit( + permission.assert({ + ...LocationMutation.externalDirectoryPermission(external), + sessionID: context.sessionID, + agent: context.agent, + source: permissionSource, + }), + ) + } - const target = yield* unableToEdit(mutation.resolve({ path: input.path, kind: "file" })) - const external = target.externalDirectory - if (external) { yield* unableToEdit( permission.assert({ - ...LocationMutation.externalDirectoryPermission(external), + action: "edit", + resources: [target.resource], + save: ["*"], sessionID: context.sessionID, agent: context.agent, source: permissionSource, }), ) - } + const source = decodeUtf8(yield* unableToEdit(fs.readFile(target.canonical))) + const ending = detectLineEnding(source.text) + const oldString = convertToLineEnding(input.oldString, ending) + const newString = convertToLineEnding(input.newString, ending) + const replacements = countOccurrences(source.text, oldString) + if (replacements === 0) { + return yield* new ToolFailure({ + message: + "Could not find oldString in the file. It must match exactly, including whitespace and indentation.", + }) + } + if (replacements > 1 && input.replaceAll !== true) { + return yield* new ToolFailure({ + message: + "Found multiple exact matches for oldString. Provide more surrounding context or set replaceAll to true.", + }) + } - yield* unableToEdit( - permission.assert({ - action: "edit", - resources: [target.resource], - save: ["*"], - sessionID: context.sessionID, - agent: context.agent, - source: permissionSource, - }), - ) - const source = decodeUtf8(yield* unableToEdit(fs.readFile(target.canonical))) - const ending = detectLineEnding(source.text) - const oldString = convertToLineEnding(input.oldString, ending) - const newString = convertToLineEnding(input.newString, ending) - const replacements = countOccurrences(source.text, oldString) - if (replacements === 0) { - return yield* new ToolFailure({ - message: - "Could not find oldString in the file. It must match exactly, including whitespace and indentation.", - }) - } - if (replacements > 1 && input.replaceAll !== true) { - return yield* new ToolFailure({ - message: - "Found multiple exact matches for oldString. Provide more surrounding context or set replaceAll to true.", - }) - } - - const replaced = - input.replaceAll === true - ? source.text.replaceAll(oldString, newString) - : source.text.replace(oldString, newString) - const counts = diffLines(source.text, replaced).reduce( - (result, item) => ({ - additions: result.additions + (item.added ? (item.count ?? 0) : 0), - deletions: result.deletions + (item.removed ? (item.count ?? 0) : 0), - }), - { additions: 0, deletions: 0 }, - ) - const next = splitBom(replaced) - const result = yield* unableToEdit( - files.writeIfUnchanged({ - target, - expected: source.content, - content: joinBom(next.text, source.bom || next.bom), - }), - ) - return { - files: [ - { - file: result.resource, - patch: createTwoFilesPatch(result.resource, result.resource, source.text, replaced), - status: "modified" as const, - ...counts, - }, - ], - replacements, - } satisfies Output - }) - }, - }), - "edit", + const replaced = + input.replaceAll === true + ? source.text.replaceAll(oldString, newString) + : source.text.replace(oldString, newString) + const counts = diffLines(source.text, replaced).reduce( + (result, item) => ({ + additions: result.additions + (item.added ? (item.count ?? 0) : 0), + deletions: result.deletions + (item.removed ? (item.count ?? 0) : 0), + }), + { additions: 0, deletions: 0 }, + ) + const next = splitBom(replaced) + const result = yield* unableToEdit( + files.writeIfUnchanged({ + target, + expected: source.content, + content: joinBom(next.text, source.bom || next.bom), + }), + ) + return { + files: [ + { + file: result.resource, + patch: createTwoFilesPatch(result.resource, result.resource, source.text, replaced), + status: "modified" as const, + ...counts, + }, + ], + replacements, + } satisfies Output + }) + }, + }), + "edit", + ), ), - }) + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/glob.ts b/packages/core/src/tool/glob.ts index 753e36cab50..80f0ca2da4f 100644 --- a/packages/core/src/tool/glob.ts +++ b/packages/core/src/tool/glob.ts @@ -43,68 +43,71 @@ export const Plugin = { const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.make({ - description: - "Find files by glob pattern within the active Location. Returns concise relative file resources. Use a relative path to narrow the search and limit to bound the result count.", - input: Input, - output: Output, - toModelOutput: ({ output }) => [ - { - type: "text", - text: toModelOutput( - output.map((entry) => ({ ...entry, path: path.resolve(location.directory, entry.path) })), - ), - }, - ], - execute: (input, context) => - Effect.gen(function* () { - yield* permission.assert({ - action: name, - resources: [input.pattern], - save: ["*"], - metadata: { - root: input.path ?? ".", - path: input.path, - limit: input.limit, - }, - sessionID: context.sessionID, - agent: context.agent, - source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, - }) - const cwd = path.resolve(location.directory, input.path ?? ".") - yield* fs - .stat(cwd) - .pipe( - Effect.catchReason("PlatformError", "NotFound", () => - Effect.fail(new ToolFailure({ message: `Search path does not exist: ${input.path ?? "."}` })), - ), - ) - return yield* ripgrep - .glob({ - cwd, - pattern: input.pattern, - limit: input.limit ?? Number.MAX_SAFE_INTEGER, + .transform((draft) => + draft.add( + name, + Tool.make({ + description: + "Find files by glob pattern within the active Location. Returns concise relative file resources. Use a relative path to narrow the search and limit to bound the result count.", + input: Input, + output: Output, + toModelOutput: ({ output }) => [ + { + type: "text", + text: toModelOutput( + output.map((entry) => ({ ...entry, path: path.resolve(location.directory, entry.path) })), + ), + }, + ], + execute: (input, context) => + Effect.gen(function* () { + yield* permission.assert({ + action: name, + resources: [input.pattern], + save: ["*"], + metadata: { + root: input.path ?? ".", + path: input.path, + limit: input.limit, + }, + sessionID: context.sessionID, + agent: context.agent, + source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, }) - .pipe( - Effect.map((result) => - result.map((entry) => - FileSystem.Entry.make({ - ...entry, - path: RelativePath.make(path.relative(location.directory, path.resolve(cwd, entry.path))), - }), + const cwd = path.resolve(location.directory, input.path ?? ".") + yield* fs + .stat(cwd) + .pipe( + Effect.catchReason("PlatformError", "NotFound", () => + Effect.fail(new ToolFailure({ message: `Search path does not exist: ${input.path ?? "."}` })), ), - ), - ) - }).pipe( - Effect.mapError((error) => - error instanceof ToolFailure - ? error - : new ToolFailure({ message: `Unable to find files matching ${input.pattern}` }), + ) + return yield* ripgrep + .glob({ + cwd, + pattern: input.pattern, + limit: input.limit ?? Number.MAX_SAFE_INTEGER, + }) + .pipe( + Effect.map((result) => + result.map((entry) => + FileSystem.Entry.make({ + ...entry, + path: RelativePath.make(path.relative(location.directory, path.resolve(cwd, entry.path))), + }), + ), + ), + ) + }).pipe( + Effect.mapError((error) => + error instanceof ToolFailure + ? error + : new ToolFailure({ message: `Unable to find files matching ${input.pattern}` }), + ), ), - ), - }), - }) + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/grep.ts b/packages/core/src/tool/grep.ts index 685925aa040..9efce1712a1 100644 --- a/packages/core/src/tool/grep.ts +++ b/packages/core/src/tool/grep.ts @@ -57,85 +57,88 @@ export const Plugin = { const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.make({ - description: - "Search file contents by regular expression within the active Location or an absolute managed tool-output file. Use a path to narrow the search, include to filter files by glob, and limit to bound the match count. Returns concise file resources, line numbers, and bounded line previews.", - input: Input, - output: Output, - toModelOutput: ({ output }) => [ - { - type: "text", - text: toModelOutput( - output.map((match) => ({ - ...match, - entry: { ...match.entry, path: path.resolve(location.directory, match.entry.path) }, - })), - ), - }, - ], - execute: (input, context) => - Effect.gen(function* () { - yield* permission.assert({ - action: name, - resources: [input.pattern], - save: ["*"], - metadata: { - root: ".", - path: input.path, - include: input.include, - limit: input.limit, - }, - sessionID: context.sessionID, - agent: context.agent, - source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, - }) - const target = path.resolve(location.directory, input.path ?? ".") - const info = yield* fs - .stat(target) - .pipe( - Effect.catchReason("PlatformError", "NotFound", () => - Effect.fail(new ToolFailure({ message: `Search path does not exist: ${input.path ?? "."}` })), - ), - ) - return yield* ripgrep - .grep({ - cwd: info?.type === "Directory" ? target : path.dirname(target), - pattern: input.pattern, - file: info?.type === "File" ? path.basename(target) : undefined, - include: input.include, - limit: input.limit ?? Number.MAX_SAFE_INTEGER, + .transform((draft) => + draft.add( + name, + Tool.make({ + description: + "Search file contents by regular expression within the active Location or an absolute managed tool-output file. Use a path to narrow the search, include to filter files by glob, and limit to bound the match count. Returns concise file resources, line numbers, and bounded line previews.", + input: Input, + output: Output, + toModelOutput: ({ output }) => [ + { + type: "text", + text: toModelOutput( + output.map((match) => ({ + ...match, + entry: { ...match.entry, path: path.resolve(location.directory, match.entry.path) }, + })), + ), + }, + ], + execute: (input, context) => + Effect.gen(function* () { + yield* permission.assert({ + action: name, + resources: [input.pattern], + save: ["*"], + metadata: { + root: ".", + path: input.path, + include: input.include, + limit: input.limit, + }, + sessionID: context.sessionID, + agent: context.agent, + source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, }) - .pipe( - Effect.map((result) => - result.map((match) => - FileSystem.Match.make({ - ...match, - entry: FileSystem.Entry.make({ - ...match.entry, - path: RelativePath.make( - path.relative( - location.directory, - path.resolve( - info?.type === "Directory" ? target : path.dirname(target), - match.entry.path, + const target = path.resolve(location.directory, input.path ?? ".") + const info = yield* fs + .stat(target) + .pipe( + Effect.catchReason("PlatformError", "NotFound", () => + Effect.fail(new ToolFailure({ message: `Search path does not exist: ${input.path ?? "."}` })), + ), + ) + return yield* ripgrep + .grep({ + cwd: info?.type === "Directory" ? target : path.dirname(target), + pattern: input.pattern, + file: info?.type === "File" ? path.basename(target) : undefined, + include: input.include, + limit: input.limit ?? Number.MAX_SAFE_INTEGER, + }) + .pipe( + Effect.map((result) => + result.map((match) => + FileSystem.Match.make({ + ...match, + entry: FileSystem.Entry.make({ + ...match.entry, + path: RelativePath.make( + path.relative( + location.directory, + path.resolve( + info?.type === "Directory" ? target : path.dirname(target), + match.entry.path, + ), ), ), - ), + }), }), - }), + ), ), - ), - ) - }).pipe( - Effect.mapError((error) => - error instanceof ToolFailure - ? error - : new ToolFailure({ message: `Unable to grep for ${input.pattern}` }), + ) + }).pipe( + Effect.mapError((error) => + error instanceof ToolFailure + ? error + : new ToolFailure({ message: `Unable to grep for ${input.pattern}` }), + ), ), - ), - }), - }) + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/question.ts b/packages/core/src/tool/question.ts index dbabb017474..e19706f4ae7 100644 --- a/packages/core/src/tool/question.ts +++ b/packages/core/src/tool/question.ts @@ -56,65 +56,68 @@ export const Plugin = { const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.make({ - description, - input: Input, - output: Output, - toModelOutput: ({ input, output }) => [ - { type: "text", text: toModelOutput(input.questions, output.answers) }, - ], - execute: (input, context) => - permission - .assert({ - action: "question", - resources: ["*"], - sessionID: context.sessionID, - agent: context.agent, - source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, - }) - .pipe( - Effect.mapError(() => new ToolFailure({ message: "Permission denied: question" })), - Effect.andThen( - forms - .ask({ - sessionID: context.sessionID, - metadata: { - kind: "question", - tool: { messageID: context.assistantMessageID, callID: context.toolCallID }, - }, - mode: "form", - fields: input.questions.map( - (question, index): Form.Field => ({ - key: `q${index}`, - title: question.header, - description: question.question, - type: question.multiple === true ? "multiselect" : "string", - options: question.options.map((option) => ({ - value: option.label, - label: option.label, - description: option.description, - })), - custom: true, - }), - ), + .transform((draft) => + draft.add( + name, + Tool.make({ + description, + input: Input, + output: Output, + toModelOutput: ({ input, output }) => [ + { type: "text", text: toModelOutput(input.questions, output.answers) }, + ], + execute: (input, context) => + permission + .assert({ + action: "question", + resources: ["*"], + sessionID: context.sessionID, + agent: context.agent, + source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, + }) + .pipe( + Effect.mapError(() => new ToolFailure({ message: "Permission denied: question" })), + Effect.andThen( + forms + .ask({ + sessionID: context.sessionID, + metadata: { + kind: "question", + tool: { messageID: context.assistantMessageID, callID: context.toolCallID }, + }, + mode: "form", + fields: input.questions.map( + (question, index): Form.Field => ({ + key: `q${index}`, + title: question.header, + description: question.question, + type: question.multiple === true ? "multiselect" : "string", + options: question.options.map((option) => ({ + value: option.label, + label: option.label, + description: option.description, + })), + custom: true, + }), + ), + }) + .pipe(Effect.orDie), + ), + Effect.flatMap((state) => { + if (state.status === "cancelled") return Effect.die(new CancelledError()) + return Effect.succeed({ + answers: input.questions.map((_, index): QuestionV2.Answer => { + const value = state.answer[`q${index}`] + if (value === undefined) return [] + if (typeof value === "object") return Array.from(value) + return [String(value)] + }), }) - .pipe(Effect.orDie), + }), ), - Effect.flatMap((state) => { - if (state.status === "cancelled") return Effect.die(new CancelledError()) - return Effect.succeed({ - answers: input.questions.map((_, index): QuestionV2.Answer => { - const value = state.answer[`q${index}`] - if (value === undefined) return [] - if (typeof value === "object") return Array.from(value) - return [String(value)] - }), - }) - }), - ), - }), - }) + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/read.ts b/packages/core/src/tool/read.ts index de03a97974f..9ee5b4c42f0 100644 --- a/packages/core/src/tool/read.ts +++ b/packages/core/src/tool/read.ts @@ -42,100 +42,105 @@ export const Plugin = { const location = yield* Location.Service yield* ctx.tool - .register({ - [name]: Tool.make({ - description: - "Read a text file or supported image, page through a large UTF-8 text file by line offset, or list a directory page. Relative paths resolve from the current location; absolute paths inside it are accepted, while external absolute paths require external_directory approval.", - input: Input, - output: Output, - toModelOutput: ({ input, output }) => { - if (!("encoding" in output) || output.encoding !== "base64" || !SUPPORTED_IMAGE_MIMES.has(output.mime)) - return [] - return [ - { type: "text", text: "Image read successfully" }, - { type: "file", data: output.content, mime: output.mime, name: input.path }, - ] - }, - execute: (input, context) => { - return Effect.gen(function* () { - const source = { - type: "tool" as const, - messageID: context.assistantMessageID, - callID: context.toolCallID, - } - const target = yield* mutation.resolve({ path: input.path, kind: "directory" }) - const external = target.externalDirectory - if (external) + .transform((draft) => + draft.add( + name, + Tool.make({ + description: + "Read a text file or supported image, page through a large UTF-8 text file by line offset, or list a directory page. Relative paths resolve from the current location; absolute paths inside it are accepted, while external absolute paths require external_directory approval.", + input: Input, + output: Output, + toModelOutput: ({ input, output }) => { + if (!("encoding" in output) || output.encoding !== "base64" || !SUPPORTED_IMAGE_MIMES.has(output.mime)) + return [] + return [ + { type: "text", text: "Image read successfully" }, + { type: "file", data: output.content, mime: output.mime, name: input.path }, + ] + }, + execute: (input, context) => { + return Effect.gen(function* () { + const source = { + type: "tool" as const, + messageID: context.assistantMessageID, + callID: context.toolCallID, + } + const target = yield* mutation.resolve({ path: input.path, kind: "directory" }) + const external = target.externalDirectory + if (external) + yield* permission.assert({ + ...LocationMutation.externalDirectoryPermission(external), + sessionID: context.sessionID, + agent: context.agent, + source, + }) + const resource = target.resource + const absolute = AbsolutePath.make(target.canonical) + const type = yield* reader.inspect(absolute) yield* permission.assert({ - ...LocationMutation.externalDirectoryPermission(external), + action: name, + resources: [resource], + save: ["*"], sessionID: context.sessionID, agent: context.agent, source, }) - const resource = target.resource - const absolute = AbsolutePath.make(target.canonical) - const type = yield* reader.inspect(absolute) - yield* permission.assert({ - action: name, - resources: [resource], - save: ["*"], - sessionID: context.sessionID, - agent: context.agent, - source, - }) - const content = - type === "directory" - ? yield* reader.list(absolute, { offset: input.offset, limit: input.limit }) - : yield* reader.read(absolute, resource, { - offset: input.offset, - limit: input.limit, - }) - // After a successful read, discover nearby AGENTS.md walking up to the Location - // root exclusive and inject them as durable synthetic instructions. For a - // directory listing the walk starts at the directory itself (so its own AGENTS.md - // is discovered); for a file it starts at the file's dirname. External reads are - // skipped, and discovery failures never fail the read. - yield* Effect.gen(function* () { - if (target.externalDirectory !== undefined) return - const resolved = yield* fs.resolve(target.canonical) - const root = yield* fs.resolve(location.directory) - // up() searches its stop directory, so the Location-root AGENTS.md (already - // supplied by the core/instructions baseline) is dropped by the dirname filter. - const discovered = yield* fs.up({ - targets: [FILENAME], - start: type === "directory" ? resolved : dirname(resolved), - stop: root, - }) - const candidates = (yield* Effect.forEach(discovered, fs.resolve)).filter((file) => dirname(file) !== root) - if (candidates.length === 0) return - yield* sessionInstructions.load({ sessionID: context.sessionID, paths: candidates }) + const content = + type === "directory" + ? yield* reader.list(absolute, { offset: input.offset, limit: input.limit }) + : yield* reader.read(absolute, resource, { + offset: input.offset, + limit: input.limit, + }) + // After a successful read, discover nearby AGENTS.md walking up to the Location + // root exclusive and inject them as durable synthetic instructions. For a + // directory listing the walk starts at the directory itself (so its own AGENTS.md + // is discovered); for a file it starts at the file's dirname. External reads are + // skipped, and discovery failures never fail the read. + yield* Effect.gen(function* () { + if (target.externalDirectory !== undefined) return + const resolved = yield* fs.resolve(target.canonical) + const root = yield* fs.resolve(location.directory) + // up() searches its stop directory, so the Location-root AGENTS.md (already + // supplied by the core/instructions baseline) is dropped by the dirname filter. + const discovered = yield* fs.up({ + targets: [FILENAME], + start: type === "directory" ? resolved : dirname(resolved), + stop: root, + }) + const candidates = (yield* Effect.forEach(discovered, fs.resolve)).filter( + (file) => dirname(file) !== root, + ) + if (candidates.length === 0) return + yield* sessionInstructions.load({ sessionID: context.sessionID, paths: candidates }) + }).pipe( + Effect.catch(() => Effect.void), + Effect.catchDefect(() => Effect.void), + ) + if ("encoding" in content && content.encoding === "base64" && SUPPORTED_IMAGE_MIMES.has(content.mime)) { + return yield* image + .normalize(resource, { ...content, encoding: "base64" }) + .pipe(Effect.catchTag("Image.ResizerUnavailableError", () => Effect.succeed(content))) + } + if ("encoding" in content && content.encoding === "base64") + return yield* Effect.fail(new ReadToolFileSystem.BinaryFileError({ resource })) + return content }).pipe( - Effect.catch(() => Effect.void), - Effect.catchDefect(() => Effect.void), + Effect.mapError((error) => { + const message = + error instanceof ReadToolFileSystem.BinaryFileError || + error instanceof ReadToolFileSystem.MediaIngestLimitError || + error instanceof Image.DecodeError || + error instanceof Image.SizeError + ? error.message + : `Unable to read ${input.path}` + return new ToolFailure({ message }) + }), ) - if ("encoding" in content && content.encoding === "base64" && SUPPORTED_IMAGE_MIMES.has(content.mime)) { - return yield* image - .normalize(resource, { ...content, encoding: "base64" }) - .pipe(Effect.catchTag("Image.ResizerUnavailableError", () => Effect.succeed(content))) - } - if ("encoding" in content && content.encoding === "base64") - return yield* Effect.fail(new ReadToolFileSystem.BinaryFileError({ resource })) - return content - }).pipe( - Effect.mapError((error) => { - const message = - error instanceof ReadToolFileSystem.BinaryFileError || - error instanceof ReadToolFileSystem.MediaIngestLimitError || - error instanceof Image.DecodeError || - error instanceof Image.SizeError - ? error.message - : `Unable to read ${input.path}` - return new ToolFailure({ message }) - }), - ) - }, - }), - }) + }, + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/shell.ts b/packages/core/src/tool/shell.ts index cd0c428a612..c4a2820c168 100644 --- a/packages/core/src/tool/shell.ts +++ b/packages/core/src/tool/shell.ts @@ -58,8 +58,7 @@ const modelOutput = (output: Output): string | undefined => { const warnings = output.warnings?.length ? `\n\nWarnings:\n${output.warnings.map((warning) => `- ${warning}`).join("\n")}` : "" - if (output.status === "running") - return `${warnings.trimStart()}${warnings ? "\n\n" : ""}${BACKGROUND_INSTRUCTION}` + if (output.status === "running") return `${warnings.trimStart()}${warnings ? "\n\n" : ""}${BACKGROUND_INSTRUCTION}` if (output.timeout) return `${warnings.trimStart()}${warnings ? "\n\n" : ""}Command timed out before completion.` return `${warnings.trimStart()}${warnings ? "\n\n" : ""}Command exited with code ${output.exit}.` } @@ -140,136 +139,142 @@ export const Plugin = { }) yield* ctx.tool - .register({ - [name]: Tool.make({ - description: `Execute one shell command string with the host user's filesystem, process, and network authority. The active Location is the default working directory. Relative workdir values resolve from that Location. External workdir values require external_directory approval; best-effort command-argument path warnings are advisory only. Timeout values are milliseconds (default: ${DEFAULT_TIMEOUT_MS}; maximum: ${MAX_TIMEOUT_MS}). Uses the configured shell when set; otherwise uses /bin/sh on POSIX and COMSPEC or cmd.exe on Windows. Background mode (background=true) launches the command asynchronously and returns immediately; you are notified when it finishes.`, - input: Input, - output: Output, - structured: StructuredOutput, - toStructuredOutput: ({ output }) => ({ - truncated: output.truncated, - ...(output.exit === undefined ? {} : { exit: output.exit }), - ...(output.shellID === undefined ? {} : { shellID: output.shellID }), - ...(output.timeout === undefined ? {} : { timeout: output.timeout }), - }), - toModelOutput: ({ output }) => { - const parts: Content[] = [{ type: "text", text: output.output }] - const model = modelOutput(output) - if (model) parts.push({ type: "text", text: model }) - return parts - }, - execute: (input, context) => - Effect.gen(function* () { - const source = { - type: "tool" as const, - messageID: context.assistantMessageID, - callID: context.toolCallID, - } - const target = yield* mutation.resolve({ path: input.workdir ?? ".", kind: "directory" }) - const external = target.externalDirectory - if (external) + .transform((draft) => + draft.add( + name, + Tool.make({ + description: `Execute one shell command string with the host user's filesystem, process, and network authority. The active Location is the default working directory. Relative workdir values resolve from that Location. External workdir values require external_directory approval; best-effort command-argument path warnings are advisory only. Timeout values are milliseconds (default: ${DEFAULT_TIMEOUT_MS}; maximum: ${MAX_TIMEOUT_MS}). Uses the configured shell when set; otherwise uses /bin/sh on POSIX and COMSPEC or cmd.exe on Windows. Background mode (background=true) launches the command asynchronously and returns immediately; you are notified when it finishes.`, + input: Input, + output: Output, + structured: StructuredOutput, + toStructuredOutput: ({ output }) => ({ + truncated: output.truncated, + ...(output.exit === undefined ? {} : { exit: output.exit }), + ...(output.shellID === undefined ? {} : { shellID: output.shellID }), + ...(output.timeout === undefined ? {} : { timeout: output.timeout }), + }), + toModelOutput: ({ output }) => { + const parts: Content[] = [{ type: "text", text: output.output }] + const model = modelOutput(output) + if (model) parts.push({ type: "text", text: model }) + return parts + }, + execute: (input, context) => + Effect.gen(function* () { + const source = { + type: "tool" as const, + messageID: context.assistantMessageID, + callID: context.toolCallID, + } + const target = yield* mutation.resolve({ path: input.workdir ?? ".", kind: "directory" }) + const external = target.externalDirectory + if (external) + yield* permission.assert({ + ...LocationMutation.externalDirectoryPermission(external), + sessionID: context.sessionID, + agent: context.agent, + source, + }) + const warnings = (yield* externalCommandDirectories(fsUtil, input.command, target.canonical)).map( + (directory) => + `Command argument references external directory ${path.join(directory, "*").replaceAll("\\", "/")}. Shell runs with host-user filesystem, process, and network authority; this scan is advisory only.`, + ) yield* permission.assert({ - ...LocationMutation.externalDirectoryPermission(external), + action: name, + resources: [input.command], + save: [input.command], sessionID: context.sessionID, agent: context.agent, source, }) - const warnings = (yield* externalCommandDirectories(fsUtil, input.command, target.canonical)).map( - (directory) => - `Command argument references external directory ${path.join(directory, "*").replaceAll("\\", "/")}. Shell runs with host-user filesystem, process, and network authority; this scan is advisory only.`, - ) - yield* permission.assert({ - action: name, - resources: [input.command], - save: [input.command], - sessionID: context.sessionID, - agent: context.agent, - source, - }) - if ((yield* fsUtil.stat(target.canonical)).type !== "Directory") - return yield* Effect.fail(new Error(`Working directory is not a directory: ${target.canonical}`)) + if ((yield* fsUtil.stat(target.canonical)).type !== "Directory") + return yield* Effect.fail(new Error(`Working directory is not a directory: ${target.canonical}`)) - const timeout = input.timeout ?? DEFAULT_TIMEOUT_MS - const info = yield* shell.create({ - command: input.command, - cwd: target.canonical, - timeout, - metadata: { sessionID: context.sessionID }, - }) + const timeout = input.timeout ?? DEFAULT_TIMEOUT_MS + const info = yield* shell.create({ + command: input.command, + cwd: target.canonical, + timeout, + metadata: { sessionID: context.sessionID }, + }) - const settleShell = Effect.fn("ShellTool.settleShell")(function* () { - const final = yield* shell.wait(info.id) - const page = yield* shell.output(info.id, { limit: MAX_CAPTURE_BYTES }) + const settleShell = Effect.fn("ShellTool.settleShell")(function* () { + const final = yield* shell.wait(info.id) + const page = yield* shell.output(info.id, { limit: MAX_CAPTURE_BYTES }) - if (final.status === "timeout") { + if (final.status === "timeout") { + return { + exit: final.exit, + output: `Command exceeded timeout of ${timeout} ms. Retry with a larger timeout if the command is expected to take longer.`, + truncated: false, + timeout: true, + status: "completed" as const, + } + } + + const truncated = page.size > page.cursor + const body = page.output || "(no output)" + const notice = truncated ? `\n\n[output truncated; full output saved to: ${final.file}]` : "" return { exit: final.exit, - output: `Command exceeded timeout of ${timeout} ms. Retry with a larger timeout if the command is expected to take longer.`, - truncated: false, - timeout: true, + output: `${body}${notice}`, + truncated, status: "completed" as const, } + }) + + const run = settleShell().pipe( + Effect.map((output) => output.output), + Effect.onInterrupt(() => shell.remove(info.id).pipe(Effect.ignore)), + ) + const job = yield* runtime.job.start({ + id: context.toolCallID, + type: name, + title: input.command, + metadata: { sessionID: context.sessionID, shellID: info.id }, + run, + }) + + if (input.background === true) { + yield* runtime.job.background(job.id) + yield* notifyWhenDone(context.sessionID, context.toolCallID, input.command) + return { + output: BACKGROUND_STARTED, + shellID: info.id, + truncated: false, + status: "running" as const, + ...(warnings.length ? { warnings } : {}), + } } - const truncated = page.size > page.cursor - const body = page.output || "(no output)" - const notice = truncated ? `\n\n[output truncated; full output saved to: ${final.file}]` : "" - return { - exit: final.exit, - output: `${body}${notice}`, - truncated, - status: "completed" as const, + const result = yield* runtime.job + .block({ id: job.id, sessionID: context.sessionID }) + .pipe(Effect.onInterrupt(() => runtime.job.cancel(job.id).pipe(Effect.ignore))) + if (result?.type === "backgrounded") { + yield* notifyWhenDone(context.sessionID, context.toolCallID, input.command) + return { + output: BACKGROUND_STARTED, + shellID: info.id, + truncated: false, + status: "running" as const, + ...(warnings.length ? { warnings } : {}), + } } - }) + if (result?.info.status === "error") + return yield* Effect.fail(new Error(result.info.error ?? "Command failed")) + if (result?.info.status === "cancelled") return yield* Effect.fail(new Error("Command cancelled")) - const run = settleShell().pipe( - Effect.map((output) => output.output), - Effect.onInterrupt(() => shell.remove(info.id).pipe(Effect.ignore)), - ) - const job = yield* runtime.job.start({ - id: context.toolCallID, - type: name, - title: input.command, - metadata: { sessionID: context.sessionID, shellID: info.id }, - run, - }) - - if (input.background === true) { - yield* runtime.job.background(job.id) - yield* notifyWhenDone(context.sessionID, context.toolCallID, input.command) return { - output: BACKGROUND_STARTED, - shellID: info.id, - truncated: false, - status: "running" as const, + ...(yield* settleShell()), ...(warnings.length ? { warnings } : {}), } - } - - const result = yield* runtime.job.block({ id: job.id, sessionID: context.sessionID }).pipe( - Effect.onInterrupt(() => runtime.job.cancel(job.id).pipe(Effect.ignore)), - ) - if (result?.type === "backgrounded") { - yield* notifyWhenDone(context.sessionID, context.toolCallID, input.command) - return { - output: BACKGROUND_STARTED, - shellID: info.id, - truncated: false, - status: "running" as const, - ...(warnings.length ? { warnings } : {}), - } - } - if (result?.info.status === "error") return yield* Effect.fail(new Error(result.info.error ?? "Command failed")) - if (result?.info.status === "cancelled") return yield* Effect.fail(new Error("Command cancelled")) - - return { - ...(yield* settleShell()), - ...(warnings.length ? { warnings } : {}), - } - }).pipe(Effect.mapError(() => new ToolFailure({ message: `Unable to execute command: ${input.command}` }))), - }), - }) + }).pipe( + Effect.mapError(() => new ToolFailure({ message: `Unable to execute command: ${input.command}` })), + ), + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/skill.ts b/packages/core/src/tool/skill.ts index 669e36c4c88..d3a2407f32d 100644 --- a/packages/core/src/tool/skill.ts +++ b/packages/core/src/tool/skill.ts @@ -59,43 +59,46 @@ export const Plugin = { const skills = yield* SkillV2.Service const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.make({ - description, - input: Input, - output: Output, - toModelOutput: ({ output }) => [{ type: "text", text: output.output }], - execute: (input, context) => - Effect.gen(function* () { - const current = yield* skills.list() - const skill = current.find((skill) => skill.name === input.name) - if (!skill) return yield* unableToLoad(input.name) - return yield* Effect.gen(function* () { - yield* permission.assert({ - action: name, - resources: [skill.name], - save: [skill.name], - sessionID: context.sessionID, - agent: context.agent, - source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, - }) - const directory = path.dirname(skill.location) - const files = - path.basename(skill.location) === "SKILL.md" - ? (yield* fs.glob("**/*", { cwd: directory, absolute: true, include: "file", dot: true })) - .filter((file) => path.basename(file) !== "SKILL.md") - .toSorted() - .slice(0, FILE_LIMIT) - : [] - return { - name: skill.name, - directory, - output: toModelOutput(skill, files), - } - }).pipe(Effect.mapError((error) => unableToLoad(input.name, error))) - }), - }), - }) + .transform((draft) => + draft.add( + name, + Tool.make({ + description, + input: Input, + output: Output, + toModelOutput: ({ output }) => [{ type: "text", text: output.output }], + execute: (input, context) => + Effect.gen(function* () { + const current = yield* skills.list() + const skill = current.find((skill) => skill.name === input.name) + if (!skill) return yield* unableToLoad(input.name) + return yield* Effect.gen(function* () { + yield* permission.assert({ + action: name, + resources: [skill.name], + save: [skill.name], + sessionID: context.sessionID, + agent: context.agent, + source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, + }) + const directory = path.dirname(skill.location) + const files = + path.basename(skill.location) === "SKILL.md" + ? (yield* fs.glob("**/*", { cwd: directory, absolute: true, include: "file", dot: true })) + .filter((file) => path.basename(file) !== "SKILL.md") + .toSorted() + .slice(0, FILE_LIMIT) + : [] + return { + name: skill.name, + directory, + output: toModelOutput(skill, files), + } + }).pipe(Effect.mapError((error) => unableToLoad(input.name, error))) + }), + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/subagent.ts b/packages/core/src/tool/subagent.ts index 50db674ef26..c5932fce8b1 100644 --- a/packages/core/src/tool/subagent.ts +++ b/packages/core/src/tool/subagent.ts @@ -93,80 +93,88 @@ export const Plugin = { }) yield* ctx.tool - .register({ - [name]: Tool.make({ - description, - input: Input, - output: Output, - toModelOutput: ({ output }) => [{ type: "text", text: output.output }], - execute: (input, context) => - Effect.gen(function* () { - const parent = yield* runtime.session - .get(context.sessionID) - .pipe( - Effect.mapError(() => new ToolFailure({ message: `Parent session not found: ${context.sessionID}` })), - ) - const agent = yield* agents.resolve(input.agent) - if (agent === undefined) return yield* new ToolFailure({ message: `Unknown agent: ${input.agent}` }) - if (agent.mode === "primary") - return yield* new ToolFailure({ message: `Agent ${input.agent} cannot run as a subagent` }) + .transform((draft) => + draft.add( + name, + Tool.make({ + description, + input: Input, + output: Output, + toModelOutput: ({ output }) => [{ type: "text", text: output.output }], + execute: (input, context) => + Effect.gen(function* () { + const parent = yield* runtime.session + .get(context.sessionID) + .pipe( + Effect.mapError( + () => new ToolFailure({ message: `Parent session not found: ${context.sessionID}` }), + ), + ) + const agent = yield* agents.resolve(input.agent) + if (agent === undefined) return yield* new ToolFailure({ message: `Unknown agent: ${input.agent}` }) + if (agent.mode === "primary") + return yield* new ToolFailure({ message: `Agent ${input.agent} cannot run as a subagent` }) - // Model selection is policy/config/session state, not an LLM-facing tool argument. - const model = agent.model ?? parent.model - const child = yield* runtime.session - .create({ - parentID: context.sessionID, + // Model selection is policy/config/session state, not an LLM-facing tool argument. + const model = agent.model ?? parent.model + const child = yield* runtime.session + .create({ + parentID: context.sessionID, + title: input.description, + agent: AgentV2.ID.make(input.agent), + model, + // TODO(opencode kkdvxn): derive restricted subagent permissions from the parent + // session (V1 deriveSubagentSessionPermission). MVP uses the agent's own permissions. + }) + .pipe( + Effect.mapError( + () => new ToolFailure({ message: `Parent session not found: ${context.sessionID}` }), + ), + ) + + const background = input.background === true + + const run = Effect.gen(function* () { + // The child session owns its agent/model (set at create); prompt only admits input. + yield* runtime.session.prompt({ sessionID: child.id, prompt: { text: input.prompt }, resume: false }) + yield* runtime.session.resume(child.id) + return yield* latestAssistantText(child.id) + }).pipe(Effect.onInterrupt(() => runtime.session.interrupt(child.id))) + + const info = yield* runtime.job.start({ + id: child.id, + type: name, title: input.description, - agent: AgentV2.ID.make(input.agent), - model, - // TODO(opencode kkdvxn): derive restricted subagent permissions from the parent - // session (V1 deriveSubagentSessionPermission). MVP uses the agent's own permissions. + metadata: {}, + run, }) - .pipe( - Effect.mapError(() => new ToolFailure({ message: `Parent session not found: ${context.sessionID}` })), + + if (background) { + yield* runtime.job.background(info.id) + yield* notifyWhenDone(context.sessionID, child.id, input.description) + return { sessionID: child.id, status: "running" as const, output: BACKGROUND_STARTED } + } + + const result = yield* runtime.job.block({ id: child.id, sessionID: context.sessionID }).pipe( + Effect.onInterrupt(() => + Effect.all([runtime.session.interrupt(child.id), runtime.job.cancel(child.id)], { + discard: true, + }), + ), ) - - const background = input.background === true - - const run = Effect.gen(function* () { - // The child session owns its agent/model (set at create); prompt only admits input. - yield* runtime.session.prompt({ sessionID: child.id, prompt: { text: input.prompt }, resume: false }) - yield* runtime.session.resume(child.id) - return yield* latestAssistantText(child.id) - }).pipe(Effect.onInterrupt(() => runtime.session.interrupt(child.id))) - - const info = yield* runtime.job.start({ - id: child.id, - type: name, - title: input.description, - metadata: {}, - run, - }) - - if (background) { - yield* runtime.job.background(info.id) - yield* notifyWhenDone(context.sessionID, child.id, input.description) - return { sessionID: child.id, status: "running" as const, output: BACKGROUND_STARTED } - } - - const result = yield* runtime.job.block({ id: child.id, sessionID: context.sessionID }).pipe( - Effect.onInterrupt(() => - Effect.all([runtime.session.interrupt(child.id), runtime.job.cancel(child.id)], { - discard: true, - }), - ), - ) - if (result?.type === "backgrounded") { - yield* notifyWhenDone(context.sessionID, child.id, input.description) - return { sessionID: child.id, status: "running" as const, output: BACKGROUND_STARTED } - } - if (result?.info.status === "error") - return yield* new ToolFailure({ message: result.info.error ?? "Subagent failed" }) - if (result?.info.status === "cancelled") return yield* new ToolFailure({ message: "Subagent cancelled" }) - return { sessionID: child.id, status: "completed" as const, output: result?.info.output ?? NO_TEXT } - }), - }), - }) + if (result?.type === "backgrounded") { + yield* notifyWhenDone(context.sessionID, child.id, input.description) + return { sessionID: child.id, status: "running" as const, output: BACKGROUND_STARTED } + } + if (result?.info.status === "error") + return yield* new ToolFailure({ message: result.info.error ?? "Subagent failed" }) + if (result?.info.status === "cancelled") + return yield* new ToolFailure({ message: "Subagent cancelled" }) + return { sessionID: child.id, status: "completed" as const, output: result?.info.output ?? NO_TEXT } + }), + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/todowrite.ts b/packages/core/src/tool/todowrite.ts index 279792e38a1..f763be04296 100644 --- a/packages/core/src/tool/todowrite.ts +++ b/packages/core/src/tool/todowrite.ts @@ -27,28 +27,31 @@ export const Plugin = { const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.make({ - description: - "Create and maintain a structured task list for the current coding session. Use it to track progress during multi-step work and keep todo statuses current.", - input: Input, - output: Output, - toModelOutput: ({ output }) => [{ type: "text", text: toModelOutput(output) }], - execute: (input, context) => - Effect.gen(function* () { - yield* permission.assert({ - action: name, - resources: ["*"], - save: ["*"], - sessionID: context.sessionID, - agent: context.agent, - source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, - }) - yield* todos.update({ sessionID: context.sessionID, todos: input.todos }) - return { todos: input.todos } - }).pipe(Effect.mapError(() => new ToolFailure({ message: "Unable to update todos" }))), - }), - }) + .transform((draft) => + draft.add( + name, + Tool.make({ + description: + "Create and maintain a structured task list for the current coding session. Use it to track progress during multi-step work and keep todo statuses current.", + input: Input, + output: Output, + toModelOutput: ({ output }) => [{ type: "text", text: toModelOutput(output) }], + execute: (input, context) => + Effect.gen(function* () { + yield* permission.assert({ + action: name, + resources: ["*"], + save: ["*"], + sessionID: context.sessionID, + agent: context.agent, + source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, + }) + yield* todos.update({ sessionID: context.sessionID, todos: input.todos }) + return { todos: input.todos } + }).pipe(Effect.mapError(() => new ToolFailure({ message: "Unable to update todos" }))), + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/webfetch.ts b/packages/core/src/tool/webfetch.ts index b729fb43f7b..0e046daff9c 100644 --- a/packages/core/src/tool/webfetch.ts +++ b/packages/core/src/tool/webfetch.ts @@ -119,60 +119,63 @@ export const Plugin = { const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.make({ - description, - input: Input, - output: Output, - toModelOutput: ({ output }) => [{ type: "text", text: output.output }], - execute: (input, context) => - Effect.gen(function* () { - yield* Effect.try({ - try: () => assertHttpUrl(new URL(input.url)), - catch: (error) => error, - }) + .transform((draft) => + draft.add( + name, + Tool.make({ + description, + input: Input, + output: Output, + toModelOutput: ({ output }) => [{ type: "text", text: output.output }], + execute: (input, context) => + Effect.gen(function* () { + yield* Effect.try({ + try: () => assertHttpUrl(new URL(input.url)), + catch: (error) => error, + }) - yield* permission.assert({ - action: name, - resources: [input.url], - save: ["*"], - metadata: input, - sessionID: context.sessionID, - agent: context.agent, - source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, - }) + yield* permission.assert({ + action: name, + resources: [input.url], + save: ["*"], + metadata: input, + sessionID: context.sessionID, + agent: context.agent, + source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, + }) - const { body, contentType } = yield* Effect.gen(function* () { - const response = yield* execute(http, input.url, input.format).pipe( - Effect.catchIf(isCloudflareChallenge, () => execute(http, input.url, input.format, "opencode")), + const { body, contentType } = yield* Effect.gen(function* () { + const response = yield* execute(http, input.url, input.format).pipe( + Effect.catchIf(isCloudflareChallenge, () => execute(http, input.url, input.format, "opencode")), + ) + const contentType = response.headers["content-type"] || "" + const mime = mimeFrom(contentType) + if (isImageAttachment(mime)) + return yield* Effect.fail(new Error(`Unsupported fetched image content type: ${mime}`)) + if (!isTextualMime(mime)) + return yield* Effect.fail(new Error(`Unsupported fetched file content type: ${mime}`)) + return { body: yield* collectBody(response), contentType } + }).pipe( + Effect.timeoutOrElse({ + duration: Duration.seconds(input.timeout ?? DEFAULT_TIMEOUT_SECONDS), + orElse: () => Effect.fail(new Error("Request timed out")), + }), ) - const contentType = response.headers["content-type"] || "" - const mime = mimeFrom(contentType) - if (isImageAttachment(mime)) - return yield* Effect.fail(new Error(`Unsupported fetched image content type: ${mime}`)) - if (!isTextualMime(mime)) - return yield* Effect.fail(new Error(`Unsupported fetched file content type: ${mime}`)) - return { body: yield* collectBody(response), contentType } - }).pipe( - Effect.timeoutOrElse({ - duration: Duration.seconds(input.timeout ?? DEFAULT_TIMEOUT_SECONDS), - orElse: () => Effect.fail(new Error("Request timed out")), - }), - ) - const content = new TextDecoder().decode(body) - const output = yield* Effect.try({ - try: () => convert(content, contentType, input.format), - catch: (error) => error, - }) - return { - url: input.url, - contentType, - format: input.format, - output, - } - }).pipe(Effect.mapError(() => new ToolFailure({ message: `Unable to fetch ${input.url}` }))), - }), - }) + const content = new TextDecoder().decode(body) + const output = yield* Effect.try({ + try: () => convert(content, contentType, input.format), + catch: (error) => error, + }) + return { + url: input.url, + contentType, + format: input.format, + output, + } + }).pipe(Effect.mapError(() => new ToolFailure({ message: `Unable to fetch ${input.url}` }))), + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/websearch.ts b/packages/core/src/tool/websearch.ts index d0c984b89a3..bca404e185c 100644 --- a/packages/core/src/tool/websearch.ts +++ b/packages/core/src/tool/websearch.ts @@ -195,58 +195,63 @@ export const Plugin = { const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.make({ - description, - input: Input, - output: Output, - toModelOutput: ({ output }) => [{ type: "text", text: output.text }], - execute: (input, context) => { - const provider = selectProvider(context.sessionID, config, config.provider) - return Effect.gen(function* () { - yield* permission.assert({ - action: name, - resources: [input.query], - save: ["*"], - metadata: { ...input, provider }, - sessionID: context.sessionID, - agent: context.agent, - source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, - }) + .transform((draft) => + draft.add( + name, + Tool.make({ + description, + input: Input, + output: Output, + toModelOutput: ({ output }) => [{ type: "text", text: output.text }], + execute: (input, context) => { + const provider = selectProvider(context.sessionID, config, config.provider) + return Effect.gen(function* () { + yield* permission.assert({ + action: name, + resources: [input.query], + save: ["*"], + metadata: { ...input, provider }, + sessionID: context.sessionID, + agent: context.agent, + source: { type: "tool", messageID: context.assistantMessageID, callID: context.toolCallID }, + }) - const text = - provider === "exa" - ? yield* callMcp(http, exaUrl(config.exaApiKey), "web_search_exa", ExaArgs, { - query: input.query, - type: input.type || "auto", - numResults: input.numResults || 8, - livecrawl: input.livecrawl || "fallback", - contextMaxCharacters: input.contextMaxCharacters, - }) - : yield* callMcp( - http, - PARALLEL_URL, - "web_search", - ParallelArgs, - { - objective: input.query, - search_queries: [input.query], - session_id: context.sessionID, - // V2 invocation context does not safely expose the model yet. - }, - { - "User-Agent": `opencode/${InstallationVersion}`, - ...(config.parallelApiKey ? { Authorization: `Bearer ${config.parallelApiKey}` } : {}), - }, - ) - return { - provider, - text: text ?? NO_RESULTS, - } - }).pipe(Effect.mapError(() => new ToolFailure({ message: `Unable to search the web for ${input.query}` }))) - }, - }), - }) + const text = + provider === "exa" + ? yield* callMcp(http, exaUrl(config.exaApiKey), "web_search_exa", ExaArgs, { + query: input.query, + type: input.type || "auto", + numResults: input.numResults || 8, + livecrawl: input.livecrawl || "fallback", + contextMaxCharacters: input.contextMaxCharacters, + }) + : yield* callMcp( + http, + PARALLEL_URL, + "web_search", + ParallelArgs, + { + objective: input.query, + search_queries: [input.query], + session_id: context.sessionID, + // V2 invocation context does not safely expose the model yet. + }, + { + "User-Agent": `opencode/${InstallationVersion}`, + ...(config.parallelApiKey ? { Authorization: `Bearer ${config.parallelApiKey}` } : {}), + }, + ) + return { + provider, + text: text ?? NO_RESULTS, + } + }).pipe( + Effect.mapError(() => new ToolFailure({ message: `Unable to search the web for ${input.query}` })), + ) + }, + }), + ), + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/src/tool/write.ts b/packages/core/src/tool/write.ts index ca89665be42..8e8f1b563b6 100644 --- a/packages/core/src/tool/write.ts +++ b/packages/core/src/tool/write.ts @@ -50,44 +50,47 @@ export const Plugin = { const permission = yield* PermissionV2.Service yield* ctx.tool - .register({ - [name]: Tool.withPermission( - Tool.make({ - description: - "Write content to one file. Relative paths resolve within the active Location. Absolute paths inside the Location are accepted. Explicit external absolute paths require external_directory approval before edit approval.", - input: Input, - output: Output, - toModelOutput: ({ output }) => [{ type: "text", text: toModelOutput(output) }], - execute: (input, context) => - Effect.gen(function* () { - const source = { - type: "tool" as const, - messageID: context.assistantMessageID, - callID: context.toolCallID, - } - const target = yield* mutation.resolve({ path: input.path, kind: "file" }) - const external = target.externalDirectory - if (external) + .transform((draft) => + draft.add( + name, + Tool.withPermission( + Tool.make({ + description: + "Write content to one file. Relative paths resolve within the active Location. Absolute paths inside the Location are accepted. Explicit external absolute paths require external_directory approval before edit approval.", + input: Input, + output: Output, + toModelOutput: ({ output }) => [{ type: "text", text: toModelOutput(output) }], + execute: (input, context) => + Effect.gen(function* () { + const source = { + type: "tool" as const, + messageID: context.assistantMessageID, + callID: context.toolCallID, + } + const target = yield* mutation.resolve({ path: input.path, kind: "file" }) + const external = target.externalDirectory + if (external) + yield* permission.assert({ + ...LocationMutation.externalDirectoryPermission(external), + sessionID: context.sessionID, + agent: context.agent, + source, + }) yield* permission.assert({ - ...LocationMutation.externalDirectoryPermission(external), + action: "edit", + resources: [target.resource], + save: ["*"], sessionID: context.sessionID, agent: context.agent, source, }) - yield* permission.assert({ - action: "edit", - resources: [target.resource], - save: ["*"], - sessionID: context.sessionID, - agent: context.agent, - source, - }) - return yield* files.writeTextPreservingBom({ target, content: input.content }) - }).pipe(Effect.mapError(() => new ToolFailure({ message: `Unable to write ${input.path}` }))), - }), - "edit", + return yield* files.writeTextPreservingBom({ target, content: input.content }) + }).pipe(Effect.mapError(() => new ToolFailure({ message: `Unable to write ${input.path}` }))), + }), + "edit", + ), ), - }) + ) .pipe(Effect.orDie) }), } diff --git a/packages/core/test/event.test.ts b/packages/core/test/event.test.ts index 96e767084fd..1f0e8720639 100644 --- a/packages/core/test/event.test.ts +++ b/packages/core/test/event.test.ts @@ -61,6 +61,12 @@ const GlobalMessage = EventV2.ephemeral({ text: Schema.String, }, }) +const CountMessage = EventV2.ephemeral({ + type: "test.count", + schema: { + count: Schema.Number, + }, +}) const VersionedMessage = EventV2.durable({ type: "test.versioned", @@ -90,6 +96,26 @@ const it = testEffect( const itWithoutLocation = testEffect(AppNodeBuilder.build(LayerNode.group([Database.node, EventV2.node]))) describe("EventV2", () => { + it.effect("subscribes to multiple event definitions with a discriminated payload union", () => + Effect.gen(function* () { + const events = yield* EventV2.Service + // @ts-expect-error multi-definition subscriptions require at least one definition + events.subscribe([]) + const fiber = yield* events + .subscribe([Message, CountMessage]) + .pipe(Stream.take(2), Stream.runCollect, Effect.forkScoped) + yield* Effect.yieldNow + + yield* events.publish(Message, { text: "hello" }) + yield* events.publish(CountMessage, { count: 2 }) + + const received = Array.from(yield* Fiber.join(fiber)).map((event) => + event.type === "test.message" ? event.data.text : event.data.count, + ) + expect(received).toEqual(["hello", 2]) + }), + ) + it.effect("publishes events with the current location", () => Effect.gen(function* () { const events = yield* EventV2.Service diff --git a/packages/core/test/lib/tool.ts b/packages/core/test/lib/tool.ts index 74c1b710ab6..5677e288ef0 100644 --- a/packages/core/test/lib/tool.ts +++ b/packages/core/test/lib/tool.ts @@ -2,6 +2,7 @@ import { AgentV2 } from "@opencode-ai/core/agent" import type { PermissionV2 } from "@opencode-ai/core/permission" import { SessionMessage } from "@opencode-ai/core/session/message" import { ToolRegistry } from "@opencode-ai/core/tool/registry" +import { Tool } from "@opencode-ai/core/tool/tool" import { Tools } from "@opencode-ai/core/tool/tools" import type { PluginContext } from "@opencode-ai/plugin/v2/effect" import { Effect, type Scope } from "effect" @@ -49,7 +50,24 @@ export const registerToolPlugin = (plugin: { const tools = yield* Tools.Service const context: Pick = { tool: { - register: tools.register, + transform: (callback) => + Effect.gen(function* () { + const registrations: Array<{ + readonly name: string + readonly tool: Tool.AnyTool + readonly options?: Tool.RegisterOptions + }> = [] + callback({ + add: (name, tool, options) => { + registrations.push({ name, tool, ...(options ? { options } : {}) }) + }, + }) + yield* Effect.forEach( + registrations, + (registration) => tools.register({ [registration.name]: registration.tool }, registration.options), + { discard: true }, + ) + }), execute: { before: () => Effect.die("registerToolPlugin does not support tool hooks"), after: () => Effect.die("registerToolPlugin does not support tool hooks"), diff --git a/packages/core/test/plugin.test.ts b/packages/core/test/plugin.test.ts index e437feb0667..5d87102b7d5 100644 --- a/packages/core/test/plugin.test.ts +++ b/packages/core/test/plugin.test.ts @@ -165,14 +165,17 @@ describe("PluginV2", () => { id: "tool-plugin", effect: (ctx) => ctx.tool - .register({ - plugin_tool: Tool.make({ - description: "Plugin tool", - input: Schema.Struct({}), - output: Schema.Struct({ ok: Schema.Boolean }), - execute: () => Effect.succeed({ ok: true }), - }), - }) + .transform((draft) => + draft.add( + "plugin_tool", + Tool.make({ + description: "Plugin tool", + input: Schema.Struct({}), + output: Schema.Struct({ ok: Schema.Boolean }), + execute: () => Effect.succeed({ ok: true }), + }), + ), + ) .pipe(Effect.orDie), }) @@ -202,13 +205,13 @@ describe("PluginV2", () => { const plugin = define({ id: "grouped-tools", effect: (ctx) => - Effect.gen(function* () { - yield* ctx.tool.register({ plain: tool("Plain") }).pipe(Effect.orDie) - yield* ctx.tool.register({ "look/up": tool("Lookup") }, { group: "context 7" }).pipe(Effect.orDie) - yield* ctx.tool - .register({ search: tool("Search") }, { group: "context 7", deferred: true }) - .pipe(Effect.orDie) - }), + ctx.tool + .transform((draft) => { + draft.add("plain", tool("Plain")) + draft.add("look/up", tool("Lookup"), { group: "context 7" }) + draft.add("search", tool("Search"), { group: "context 7", deferred: true }) + }) + .pipe(Effect.orDie), }) yield* plugins.activate([{ plugin }]) @@ -236,14 +239,17 @@ describe("PluginV2", () => { effect: (ctx) => Effect.gen(function* () { yield* ctx.tool - .register({ - echo: Tool.make({ - description: "Echo", - input: Schema.Struct({ text: Schema.String }), - output: Schema.Struct({ text: Schema.String }), - execute: ({ text }) => Effect.sync(() => executed.push({ text })).pipe(Effect.as({ text })), - }), - }) + .transform((draft) => + draft.add( + "echo", + Tool.make({ + description: "Echo", + input: Schema.Struct({ text: Schema.String }), + output: Schema.Struct({ text: Schema.String }), + execute: ({ text }) => Effect.sync(() => executed.push({ text })).pipe(Effect.as({ text })), + }), + ), + ) .pipe(Effect.orDie) yield* ctx.tool.execute diff --git a/packages/core/test/plugin/host.ts b/packages/core/test/plugin/host.ts index 8ef98c6530f..1f37dab47b0 100644 --- a/packages/core/test/plugin/host.ts +++ b/packages/core/test/plugin/host.ts @@ -71,7 +71,7 @@ export function host(overrides: Overrides = {}): PluginContext { reload: () => Effect.die("unused skill.reload"), }, tool: overrides.tool ?? { - register: () => Effect.die("unused tool.register"), + transform: () => Effect.die("unused tool.transform"), execute: { before: () => Effect.die("unused tool.execute.before"), after: () => Effect.die("unused tool.execute.after"), diff --git a/packages/plugin/src/v2/effect/index.ts b/packages/plugin/src/v2/effect/index.ts index 2ebd0215b5a..5468dcd82f9 100644 --- a/packages/plugin/src/v2/effect/index.ts +++ b/packages/plugin/src/v2/effect/index.ts @@ -10,5 +10,5 @@ export type { IntegrationDraft, IntegrationHooks, IntegrationMethodRegistration export type { ReferenceDraft, ReferenceHooks } from "./reference.js" export type { SkillDraft, SkillHooks } from "./skill.js" export * as Tool from "./tool.js" -export type { ToolDomain, ToolExecuteBeforeEvent, ToolExecuteAfterEvent } from "./tool.js" +export type { ToolDomain, ToolDraft, ToolExecuteBeforeEvent, ToolExecuteAfterEvent } from "./tool.js" export type { SessionHooks } from "./runtime.js" diff --git a/packages/plugin/src/v2/effect/tool.ts b/packages/plugin/src/v2/effect/tool.ts index 98efaa3ce2c..bb5931af161 100644 --- a/packages/plugin/src/v2/effect/tool.ts +++ b/packages/plugin/src/v2/effect/tool.ts @@ -249,10 +249,11 @@ export interface RegisterOptions { readonly deferred?: boolean } +export interface ToolDraft { + add(name: string, tool: AnyTool, options?: RegisterOptions): void +} + export interface ToolDomain { - readonly register: ( - tools: Readonly>, - options?: RegisterOptions, - ) => Effect.Effect + readonly transform: (callback: (draft: ToolDraft) => void) => Effect.Effect readonly execute: Hooks<{ before: ToolExecuteBeforeEvent; after: ToolExecuteAfterEvent }> } diff --git a/packages/sdk-next/README.md b/packages/sdk-next/README.md index 545606b096d..a349afb7743 100644 --- a/packages/sdk-next/README.md +++ b/packages/sdk-next/README.md @@ -11,7 +11,7 @@ const opencode = yield * OpenCode.create() const session = yield * opencode.sessions.get({ sessionID }) ``` -It also exports `Tool` for plugins that register tools with `ctx.tool.register(...)`. Embedded plugins run through the ordinary discovery flow and register tools into each Location's `ToolRegistry` through the normal `Tools.Service.register(...)` path. Closing the owning Effect Scope releases router resources, location services, fibers, and scoped tool registrations. +It also exports `Tool` for plugins that add tools with `ctx.tool.transform(...)`. Embedded plugins run through the ordinary discovery flow and register tools into each Location's `ToolRegistry` through the normal `Tools.Service.register(...)` path. Closing the owning Effect Scope releases router resources, location services, fibers, and scoped tool registrations. `sessions.events({ sessionID, after })` replays durable events after the optional aggregate sequence, then emits newly committed durable events. `sessions.interrupt(...)` targets execution owned by this host, and `sessions.message(...)` retrieves one projected Session message. diff --git a/packages/sdk-next/src/opencode.ts b/packages/sdk-next/src/opencode.ts index 087f6893664..bcb06f53197 100644 --- a/packages/sdk-next/src/opencode.ts +++ b/packages/sdk-next/src/opencode.ts @@ -1,6 +1,7 @@ import { OpenCode } from "@opencode-ai/client/effect" import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { LayerNode } from "@opencode-ai/core/effect/layer-node" +import { EventV2 } from "@opencode-ai/core/event" import { PermissionSaved } from "@opencode-ai/core/permission/saved" import { SdkPlugins } from "@opencode-ai/core/plugin/sdk" import { Project } from "@opencode-ai/core/project" @@ -13,7 +14,7 @@ export const create = Effect.fn("OpenCode.create")(function* () { const memoMap = yield* Layer.makeMemoMap const sdkPlugins = SdkPlugins.makeStore() const context = yield* Layer.buildWithMemoMap( - AppNodeBuilder.build(LayerNode.group([PermissionSaved.node, Project.node, SdkPlugins.node]), [ + AppNodeBuilder.build(LayerNode.group([EventV2.node, PermissionSaved.node, Project.node, SdkPlugins.node]), [ [SdkPlugins.node, SdkPlugins.layerWithStore(sdkPlugins)], ]), memoMap, diff --git a/packages/sdk-next/test/embedded.test.ts b/packages/sdk-next/test/embedded.test.ts index a6184da8379..72edfdbc91e 100644 --- a/packages/sdk-next/test/embedded.test.ts +++ b/packages/sdk-next/test/embedded.test.ts @@ -1,6 +1,8 @@ +import fs from "fs/promises" +import path from "path" import { expect } from "bun:test" import { Flag } from "@opencode-ai/core/flag/flag" -import { Deferred, Effect, Latch, Layer, Option, Schema, Stream } from "effect" +import { Deferred, Effect, Latch, Layer, Option, Ref, Schema, Stream } from "effect" import { testEffect } from "../../core/test/lib/effect" import { tmpdir } from "../../core/test/fixture/tmpdir" import type { OpenCodeEvent } from "../src" @@ -26,6 +28,118 @@ const sessionID = (fixture: Fixture) => fixture.sdk.Session.ID.create() const location = (fixture: Fixture) => fixture.sdk.Location.Ref.make({ directory: fixture.sdk.AbsolutePath.make(fixture.directory) }) +it.live( + "reloads every booted Location after SDK plugin registration", + () => + withEmbedded("opencode-embedded-plugin-reload-", (fixture) => + Effect.gen(function* () { + const opencode = yield* fixture.sdk.OpenCode.create() + const booted = yield* Deferred.make() + const activated = yield* Deferred.make() + const bootCount = yield* Ref.make(0) + const activationCount = yield* Ref.make(0) + const secondDirectory = path.join(fixture.directory, "second") + yield* Effect.promise(() => fs.mkdir(secondDirectory)) + const refs = [ + location(fixture), + fixture.sdk.Location.Ref.make({ directory: fixture.sdk.AbsolutePath.make(secondDirectory) }), + ] + const bootstrapID = `bootstrap-sdk-${crypto.randomUUID()}` + const id = `late-sdk-${crypto.randomUUID()}` + + yield* opencode.plugin({ + id: bootstrapID, + effect: (ctx) => + Effect.gen(function* () { + yield* ctx.tool + .transform((draft) => + draft.add( + "bootstrap_sdk_tool", + fixture.sdk.Tool.make({ + description: "Marks the initial Location plugin generation", + input: Schema.Struct({}), + output: Schema.Void, + execute: () => Effect.void, + }), + ), + ) + .pipe(Effect.orDie) + if (yield* Ref.updateAndGet(bootCount, (count) => count + 1).pipe(Effect.map((count) => count === 2))) { + yield* Deferred.succeed(booted, undefined) + } + }), + }) + yield* Effect.all( + refs.map((ref) => opencode.plugin.list({ location: ref })), + { discard: true }, + ) + yield* Deferred.await(booted).pipe(Effect.timeout("4 seconds")) + yield* opencode.plugin({ + id, + effect: (ctx) => + Effect.gen(function* () { + yield* ctx.tool + .transform((draft) => + draft.add( + "late_sdk_tool", + fixture.sdk.Tool.make({ + description: "Tool registered after Location boot", + input: Schema.Struct({}), + output: Schema.Void, + execute: () => Effect.void, + }), + ), + ) + .pipe(Effect.orDie) + if ( + yield* Ref.updateAndGet(activationCount, (count) => count + 1).pipe(Effect.map((count) => count === 2)) + ) { + yield* Deferred.succeed(activated, true) + } + }), + }) + + expect(yield* Deferred.await(activated).pipe(Effect.timeout("10 seconds"))).toBe(true) + }), + ), + 25_000, +) + +it.live( + "keeps SDK plugin registration isolated between embedded hosts", + () => + withEmbedded("opencode-embedded-plugin-isolation-", (fixture) => + Effect.gen(function* () { + const first = yield* fixture.sdk.OpenCode.create() + const second = yield* fixture.sdk.OpenCode.create() + const firstReady = yield* Deferred.make() + const secondReady = yield* Deferred.make() + const activated = yield* Deferred.make() + const ref = location(fixture) + const id = `isolated-sdk-${crypto.randomUUID()}` + + yield* first.plugin({ + id: `first-ready-${crypto.randomUUID()}`, + effect: () => Deferred.succeed(firstReady, undefined), + }) + yield* second.plugin({ + id: `second-ready-${crypto.randomUUID()}`, + effect: () => Deferred.succeed(secondReady, undefined), + }) + yield* Effect.all([first.plugin.list({ location: ref }), second.plugin.list({ location: ref })], { + discard: true, + }) + yield* Effect.all([Deferred.await(firstReady), Deferred.await(secondReady)], { discard: true }) + + yield* first.plugin({ id, effect: () => Deferred.succeed(activated, undefined) }) + yield* Deferred.await(activated).pipe(Effect.timeout("5 seconds")) + + expect((yield* second.plugin.list({ location: ref })).data.map((plugin) => String(plugin.id))).not.toContain(id) + }), + ), + 15_000, +) + it.live( "embedded client uses the real router and handlers", () => @@ -42,14 +156,17 @@ it.live( id: `embedded-tools-${crypto.randomUUID()}`, effect: (ctx) => ctx.tool - .register({ - embedded_tool: fixture.sdk.Tool.make({ - description: "Embedded test tool", - input: Schema.Struct({}), - output: Schema.Struct({ ok: Schema.Boolean }), - execute: () => Effect.succeed({ ok: true }), - }), - }) + .transform((draft) => + draft.add( + "embedded_tool", + fixture.sdk.Tool.make({ + description: "Embedded test tool", + input: Schema.Struct({}), + output: Schema.Struct({ ok: Schema.Boolean }), + execute: () => Effect.succeed({ ok: true }), + }), + ), + ) .pipe(Effect.orDie), }) From f2f62438b8504076695b791b3c4ab83af5aeb4ea Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Mon, 6 Jul 2026 13:46:59 -0400 Subject: [PATCH 11/46] refactor(core): unify live event subscriptions (#35578) --- packages/core/src/event.ts | 27 +++++++++---------- packages/core/src/plugin/host.ts | 2 +- packages/core/test/event.test.ts | 4 +-- .../test/session-runner-tool-events.test.ts | 1 - 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/core/src/event.ts b/packages/core/src/event.ts index 03c539642bd..8641c928592 100644 --- a/packages/core/src/event.ts +++ b/packages/core/src/event.ts @@ -118,6 +118,11 @@ export type SubscribePayload = D[number] extend : never export interface Subscribe { + /** + * Volatile live channel: every event published from now on, nothing before or + * across a disconnect. Consumers that need reliability combine it with `log`. + */ + (): Stream.Stream (definition: D): Stream.Stream> (definitions: D): Stream.Stream> } @@ -131,12 +136,6 @@ export interface Interface { options?: PublishOptions, ) => Effect.Effect> readonly subscribe: Subscribe - /** - * Volatile live channel: every event published from now on, nothing before, - * nothing across a disconnect. The only channel that carries non-durable - * events; consumers that need reliability combine `changes` with `log`. - */ - readonly live: () => Stream.Stream /** * Durable, ordered, gap-free per-aggregate log read. `follow: false` * completes at the end of the log; `follow: true` replays then transitions @@ -150,7 +149,7 @@ export interface Interface { }) => Stream.Stream /** Latest committed seq per aggregate. Aggregates without events are absent. */ readonly sequences: (aggregateIDs: ReadonlyArray) => Effect.Effect> - /** @deprecated Use `all()` and consume the returned stream. */ + /** @deprecated Use `subscribe()` and consume the returned stream. */ readonly listen: (listener: Subscriber) => Effect.Effect readonly project: (definition: D, projector: Subscriber) => Effect.Effect readonly replay: ( @@ -575,17 +574,16 @@ export const layerWith = (options?: LayerOptions) => ), ) - const subscribeOne = (definition: D): Stream.Stream> => - local(Stream.unwrap(getOrCreate(definition).pipe(Effect.map((pubsub) => Stream.fromPubSub(pubsub))))).pipe( - Stream.map((event) => event as Payload), - ) - + function subscribe(): Stream.Stream function subscribe(definition: D): Stream.Stream> function subscribe( definitions: D, ): Stream.Stream> - function subscribe(input: Definition | readonly Definition[]): Stream.Stream { - if (isDefinition(input)) return subscribeOne(input) + function subscribe(input?: Definition | readonly Definition[]): Stream.Stream { + if (input === undefined) return streamLive() + if (isDefinition(input)) { + return local(Stream.unwrap(getOrCreate(input).pipe(Effect.map((pubsub) => Stream.fromPubSub(pubsub))))) + } const types = new Set(input.map((definition) => definition.type)) return streamLive().pipe(Stream.filter((event) => types.has(event.type))) } @@ -737,7 +735,6 @@ export const layerWith = (options?: LayerOptions) => return Service.of({ publish, subscribe, - live: streamLive, log, sequences, listen, diff --git a/packages/core/src/plugin/host.ts b/packages/core/src/plugin/host.ts index 03c92854142..01ea0da0d3f 100644 --- a/packages/core/src/plugin/host.ts +++ b/packages/core/src/plugin/host.ts @@ -159,7 +159,7 @@ export const make = Effect.fn("PluginHost.make")(function* (plugin: PluginV2.Int }), }, event: { - subscribe: () => events.live().pipe(Stream.filter(EventManifest.isServer)), + subscribe: () => events.subscribe().pipe(Stream.filter(EventManifest.isServer)), }, integration: { list: () => response(integration.list()), diff --git a/packages/core/test/event.test.ts b/packages/core/test/event.test.ts index 1f0e8720639..4bff6a7abfb 100644 --- a/packages/core/test/event.test.ts +++ b/packages/core/test/event.test.ts @@ -177,7 +177,7 @@ describe("EventV2", () => { Effect.gen(function* () { const events = yield* EventV2.Service const typed = yield* events.subscribe(Message).pipe(Stream.take(1), Stream.runCollect, Effect.forkScoped) - const wildcard = yield* events.live().pipe(Stream.take(1), Stream.runCollect, Effect.forkScoped) + const wildcard = yield* events.subscribe().pipe(Stream.take(1), Stream.runCollect, Effect.forkScoped) yield* Effect.yieldNow const event = yield* events.publish(Message, { text: "hello" }) @@ -258,7 +258,7 @@ describe("EventV2", () => { Effect.gen(function* () { const events = yield* EventV2.Service const received = new Array() - const fiber = yield* events.live().pipe( + const fiber = yield* events.subscribe().pipe( Stream.take(1), Stream.runForEach(() => Effect.sync(() => received.push("stream"))), Effect.forkScoped, diff --git a/packages/core/test/session-runner-tool-events.test.ts b/packages/core/test/session-runner-tool-events.test.ts index 983dca8c2cd..de4700ca072 100644 --- a/packages/core/test/session-runner-tool-events.test.ts +++ b/packages/core/test/session-runner-tool-events.test.ts @@ -27,7 +27,6 @@ const capture = () => { return event }), subscribe: () => Stream.empty, - live: () => Stream.empty, log: () => Stream.empty, sequences: () => Effect.succeed(new Map()), listen: () => Effect.succeed(Effect.void), From 1a52e1118edf50a5fc0b0c116c5a842af25242ee Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Mon, 6 Jul 2026 13:55:47 -0400 Subject: [PATCH 12/46] refactor(core): remove unused session watermarks (#35579) --- packages/core/src/session.ts | 29 +++++-------------------- packages/core/test/session-log.test.ts | 30 -------------------------- 2 files changed, 5 insertions(+), 54 deletions(-) diff --git a/packages/core/src/session.ts b/packages/core/src/session.ts index 57ae67ce341..02359903e31 100644 --- a/packages/core/src/session.ts +++ b/packages/core/src/session.ts @@ -142,8 +142,6 @@ export type Error = export interface Interface { readonly list: (input?: ListInput) => Effect.Effect<{ readonly data: SessionSchema.Info[] - /** Per-session durable log watermark, read in the same transaction as the snapshot. Sessions without events are absent. */ - readonly watermarks: ReadonlyMap }> readonly create: (input: CreateInput) => Effect.Effect readonly fork: (input: ForkInput) => Effect.Effect @@ -177,8 +175,6 @@ export interface Interface { after?: number follow?: boolean }) => Stream.Stream - /** Latest durable log seq per session. Sessions without events are absent. */ - readonly watermarks: (sessionIDs: ReadonlyArray) => Effect.Effect> readonly switchAgent: (input: { sessionID: SessionSchema.ID; agent: string }) => Effect.Effect readonly switchModel: (input: { sessionID: SessionSchema.ID @@ -394,21 +390,10 @@ const layer = Layer.effect( order === "asc" ? asc(sortColumn) : desc(sortColumn), order === "asc" ? asc(SessionTable.id) : desc(SessionTable.id), ) - // Watermarks must pair with the snapshot exactly, so both reads share a transaction: - // a higher watermark would let an attached tail skip events missing from the snapshot. - const snapshot = yield* db - .transaction(() => - Effect.gen(function* () { - const rows = yield* (input.limit === undefined ? query.all() : query.limit(input.limit).all()).pipe( - Effect.orDie, - ) - const watermarks = yield* events.sequences(rows.map((row) => row.id)) - return { rows, watermarks } - }), - ) - .pipe(Effect.orDie) - const rows = direction === "previous" ? snapshot.rows.toReversed() : snapshot.rows - return { data: rows.map((row) => fromRow(row)), watermarks: snapshot.watermarks } + const rows = yield* (input.limit === undefined ? query.all() : query.limit(input.limit).all()).pipe( + Effect.orDie, + ) + return { data: (direction === "previous" ? rows.toReversed() : rows).map((row) => fromRow(row)) } }), messages: Effect.fn("V2Session.messages")(function* (input) { yield* result.get(input.sessionID) @@ -463,9 +448,6 @@ const layer = Layer.effect( EventV2.isSynced(item) || isDurableSessionEvent(item), ), ), - watermarks: Effect.fn("V2Session.watermarks")(function* (sessionIDs) { - return yield* events.sequences(sessionIDs) - }), prompt: Effect.fn("V2Session.prompt")((input) => Effect.uninterruptible( Effect.gen(function* () { @@ -540,8 +522,7 @@ const layer = Layer.effect( const started = yield* Effect.gen(function* () { const shell = yield* Shell.Service return yield* shell.create({ command: input.command, cwd: session.location.directory }) - }) - .pipe(Effect.provide(locations.get(session.location))) + }).pipe(Effect.provide(locations.get(session.location))) yield* events.publish( SessionEvent.Shell.Started, { diff --git a/packages/core/test/session-log.test.ts b/packages/core/test/session-log.test.ts index ef0865f89ec..ac2fe59496e 100644 --- a/packages/core/test/session-log.test.ts +++ b/packages/core/test/session-log.test.ts @@ -130,33 +130,3 @@ describe("SessionV2.log", () => { }), ) }) - -describe("SessionV2 watermarks", () => { - it.effect("list pairs each session snapshot with its durable log watermark", () => - Effect.gen(function* () { - const session = yield* SessionV2.Service - const events = yield* EventV2.Service - const first = yield* session.create({ location }) - const second = yield* session.create({ location }) - yield* session.rename({ sessionID: first.id, title: "session.renamed" }) - - const page = yield* session.list() - const sequences = yield* events.sequences([first.id, second.id]) - - expect(page.data.map((info) => info.id).toSorted()).toEqual([first.id, second.id].toSorted()) - expect(page.watermarks).toEqual(sequences) - expect(page.watermarks.get(first.id)).toBeGreaterThan(page.watermarks.get(second.id)!) - }), - ) - - it.effect("watermarks omits sessions without durable events", () => - Effect.gen(function* () { - const session = yield* SessionV2.Service - const created = yield* session.create({ location }) - - const watermarks = yield* session.watermarks([created.id, SessionV2.ID.create()]) - - expect(Array.from(watermarks.keys())).toEqual([created.id]) - }), - ) -}) From 91f181573224b41d2fa2daa873d0746a9a822db8 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Mon, 6 Jul 2026 14:29:29 -0400 Subject: [PATCH 13/46] refactor(core): rename system context to instructions (#35583) --- AGENTS.md | 4 +- CONTEXT.md | 137 +++++---- packages/client/src/effect/api/api.ts | 30 +- .../client/src/effect/generated/client.ts | 16 +- packages/client/src/promise/api.ts | 6 +- .../client/src/promise/generated/client.ts | 84 +++--- .../client/src/promise/generated/types.ts | 16 +- packages/client/test/api.types.ts | 32 +- packages/client/test/effect.test.ts | 51 ++++ packages/client/test/promise.test.ts | 45 +++ .../test/fixtures/opencode-v2-openapi.json | 42 +-- packages/codemode/test/openapi.test.ts | 56 ++-- packages/core/package.json | 2 +- packages/core/schema.json | 284 +++++++++--------- packages/core/src/database/migration.gen.ts | 1 + .../20260705180000_rename_instructions.ts | 17 ++ packages/core/src/database/schema.gen.ts | 40 +-- ...on-context.ts => instruction-discovery.ts} | 28 +- .../builtins.ts | 20 +- .../{system-context => instructions}/index.ts | 66 ++-- packages/core/src/location-services.ts | 12 +- packages/core/src/mcp/guidance.ts | 16 +- packages/core/src/reference/guidance.ts | 12 +- packages/core/src/session/history.ts | 8 +- ...heckpoint.ts => instruction-checkpoint.ts} | 58 ++-- ...{context-entry.ts => instruction-entry.ts} | 48 ++- packages/core/src/session/message-updater.ts | 3 +- packages/core/src/session/projector.ts | 16 +- packages/core/src/session/runner/index.ts | 4 +- packages/core/src/session/runner/llm.ts | 36 +-- packages/core/src/session/sql.ts | 11 +- packages/core/src/skill/guidance.ts | 14 +- packages/core/src/tool/skill.ts | 4 +- packages/core/test/database-migration.test.ts | 51 +++- packages/core/test/event.test.ts | 6 +- ....test.ts => instruction-discovery.test.ts} | 36 +-- .../core/test/instructions/builtins.test.ts | 83 +++++ .../index.test.ts | 88 +++--- packages/core/test/reference-guidance.test.ts | 16 +- packages/core/test/session-projector.test.ts | 6 +- .../core/test/session-runner-recorded.test.ts | 28 +- packages/core/test/session-runner.test.ts | 78 ++--- packages/core/test/skill/guidance.test.ts | 54 ++-- .../core/test/system-context/builtins.test.ts | 133 -------- packages/httpapi-codegen/src/index.ts | 194 +++++++++--- .../httpapi-codegen/test/generate.test.ts | 212 ++++++++++++- packages/protocol/src/client.ts | 6 +- packages/protocol/src/groups/session.ts | 33 +- packages/schema/src/instruction-entry.ts | 20 ++ packages/schema/src/session-context-entry.ts | 20 -- packages/schema/src/session-event.ts | 8 +- packages/schema/test/event-manifest.test.ts | 3 +- packages/sdk-next/test/embedded.test.ts | 12 +- packages/sdk/js/script/build.ts | 4 +- packages/sdk/js/src/v2/gen/sdk.gen.ts | 56 ++-- packages/sdk/js/src/v2/gen/types.gen.ts | 96 +++--- packages/server/src/handlers/session.ts | 20 +- packages/tui/src/context/data.tsx | 2 +- packages/tui/src/routes/session/rows.ts | 2 +- packages/tui/test/cli/tui/data.test.tsx | 12 +- specs/v2/schema-changelog.md | 13 + specs/v2/session.md | 106 ++++--- 62 files changed, 1547 insertions(+), 1070 deletions(-) create mode 100644 packages/core/src/database/migration/20260705180000_rename_instructions.ts rename packages/core/src/{instruction-context.ts => instruction-discovery.ts} (77%) rename packages/core/src/{system-context => instructions}/builtins.ts (75%) rename packages/core/src/{system-context => instructions}/index.ts (82%) rename packages/core/src/session/{context-checkpoint.ts => instruction-checkpoint.ts} (61%) rename packages/core/src/session/{context-entry.ts => instruction-entry.ts} (65%) rename packages/core/test/{instruction-context.test.ts => instruction-discovery.test.ts} (89%) create mode 100644 packages/core/test/instructions/builtins.test.ts rename packages/core/test/{system-context => instructions}/index.test.ts (80%) delete mode 100644 packages/core/test/system-context/builtins.test.ts create mode 100644 packages/schema/src/instruction-entry.ts delete mode 100644 packages/schema/src/session-context-entry.ts diff --git a/AGENTS.md b/AGENTS.md index 0ea4055ce21..c89653ba95a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -161,5 +161,5 @@ const table = sqliteTable("session", { - Keep delivery vocabulary explicit. Prompts steer by default and promote at the next safe step boundary while the current drain requires continuation. An explicit `queue` input remains pending until the Session would otherwise become idle; promote one queued input at that boundary, then reevaluate continuation before promoting another. Promoting any new user input resets the selected agent's step allowance; a batch of steers resets it once. - One step is one logical LLM call; its durable record covers only the model-visible span. Do not write "provider turn", and do not use bare "turn" for a single call: "turn" is reserved for the future assistant-turn unit containing all steps from prompt promotion until the session would go idle. - Keep EventV2 replay owner claims separate from clustered Session execution ownership. -- Keep the System Context algebra and built-ins in `src/system-context`; keep Context Source producers with their observed domains, and keep Session History selection plus Context Checkpoint persistence Session-owned. The runner composes all context producers explicitly in `loadSystemContext`; there is no context registry. -- The durable Applied record is what the model was last told, per source. Reconcile narrates drift as chronological System updates and never rewrites the baseline; only completed compaction rebaselines, and move or committed revert resets the checkpoint. Unavailable sources keep the model's prior belief, blocking only a session's first baseline. +- Keep the Instructions algebra and built-ins in `src/instructions`; keep instruction producers with their observed domains, and keep Session History selection plus `InstructionCheckpoint` and `InstructionEntry` persistence Session-owned. `InstructionDiscovery` observes ambient global and upward-project instructions. The runner composes built-ins, discovery, guidance, and entries explicitly in `loadInstructions`; there is no instruction registry. +- The durable `Instructions.Applied` record is what the model was last told, per instruction source. Reconciliation narrates drift through `session.instructions.updated` and never rewrites the baseline; only completed compaction rebaselines, while Session movement or committed revert resets the `InstructionCheckpoint`. Unavailable sources keep the model's prior belief, blocking only a Session's first instruction baseline. diff --git a/CONTEXT.md b/CONTEXT.md index 712e91bf109..ce880380d19 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -4,40 +4,47 @@ OpenCode sessions preserve durable conversational history while assembling the r ## Language -**System Context**: -The structured collection of contextual facts presented to the model as initial instructions and chronological updates. -_Avoid_: System prompt +**Model Context**: +The complete model-visible input assembled for one **Step**, including system instructions, **Session History**, tool definitions, and step-local additions. **Instructions** are one component of Model Context, not a synonym for it. +_Avoid_: System Context + +**Instructions**: +The opaque algebra of independently refreshable typed instruction sources that render the durable instruction baseline and chronological updates shown to the model. +_Avoid_: Model Context, System Context **Session History**: -The projected chronological conversation selected for a **Step** after applying the active compaction and **Context Epoch** cutoffs. +The projected chronological conversation selected for a **Step** after applying the active compaction and **InstructionCheckpoint** baseline cutoffs. _Avoid_: Session Context -**Context Source**: -One independently observed typed value within the **System Context**, represented by a stable key, JSON codec, infallible loader, pure baseline/update renderers, and an optional removal renderer for dynamic sources. +**Instruction Source**: +One independently observed typed value within **Instructions**, represented by a stable namespaced key, JSON codec, loader, pure baseline/update renderers, and an optional removal renderer. _Avoid_: Prompt fragment -**System Context Registry**: -The Location-scoped registry of ordered, scoped producers that contribute to the current **System Context**. +**InstructionEntry**: +One API-managed, durable, per-Session instruction value. Its slash-free client key maps to the `api/` **Instruction Source** key. Entries deliberately render to the model as mechanism-neutral `` blocks: the model sees session context, not how it was attached. -**Mid-Conversation System Message**: -A durable chronological instruction that tells the model the newly effective state of a changed **Context Source**. -_Avoid_: System update, system notification, raw text diff +**InstructionDiscovery**: +The Location-scoped service that observes ambient global and upward-project `AGENTS.md` files as one ordered aggregate **Instruction Source**. -**Context Epoch**: -The span during which one initially rendered **System Context** remains the immutable provider-cache baseline, ending at completed compaction, Session movement, or an incompatible context transition that requires a fresh baseline. +**InstructionCheckpoint**: +The Session-owned durable instruction baseline, baseline sequence, and `Instructions.Applied` record used to prepare later Steps. -**Baseline System Context**: -The full **System Context** rendered at the start of a **Context Epoch**. +**Instruction Update**: +A durable chronological System message published as `session.instructions.updated` that tells the model the newly effective state of one or more changed **Instruction Sources**. +_Avoid_: System notification, raw text diff + +**Instruction Baseline**: +The exact joined instruction text stored by **InstructionCheckpoint** and sent as immutable provider-cache prefix state until completed compaction rebaselines it or Session movement or committed revert resets it. _Avoid_: Live system prompt -**Context Snapshot**: -The overwriteable model-hidden JSON state used to compare each **Context Source** with the value last admitted to a **Step**. +**Applied Instructions**: +The overwriteable model-hidden `Instructions.Applied` record in **InstructionCheckpoint**, containing what the model was last told per **Instruction Source**. -**Unavailable Context**: -An expected temporary inability to observe a **Context Source** value; the runtime retains its prior effective state and emits no update, or omits it until first successfully loaded. +**Unavailable Instruction Source**: +An expected temporary inability to observe an **Instruction Source** value; the runtime retains its prior effective state and emits no update, while an unavailable source blocks creation of the first complete **Instruction Baseline**. **Safe Step Boundary**: -The point immediately before a provider request, after durable input promotion and any required tool settlement, where context changes may be admitted chronologically. +The point during Step preparation, after prior tool settlement and before durable input promotion, where instruction changes may be admitted chronologically. **Admitted Prompt**: A durable user input accepted into the Session inbox but not yet included in **Session History**. @@ -46,7 +53,7 @@ A durable user input accepted into the Session inbox but not yet included in **S The durable transition that removes an **Admitted Prompt** from pending input and appends its user message to **Session History**. **Step**: -One logical LLM call spanning pre-flight context checkpoint preparation, input promotion, request build, and compaction check; the provider stream; and tool settlement. +One logical LLM call spanning pre-flight instruction checkpoint preparation, input promotion, request build, and compaction check; the provider stream; and tool settlement. _Avoid_: provider turn, turn (unqualified) **Physical Attempt**: @@ -100,16 +107,22 @@ _Avoid_: Response envelope ## Relationships -- A **System Context** is an opaque carrier composed from zero or more **Context Sources**. -- **Session History** contains projected conversational messages and admitted **Mid-Conversation System Messages**; the active **Baseline System Context** remains separate provider-request state. -- The **System Context Registry** uses stable-keyed scoped contributions to assemble the current **System Context**; contributor removal naturally removes its sources at the next **Safe Step Boundary**. -- A changed **Context Source** may produce one **Mid-Conversation System Message** containing its newly effective state. -- A **Mid-Conversation System Message** persists the exact combined rendered text sent to the model. -- The current **Context Snapshot** advances atomically with the corresponding durable **Mid-Conversation System Message**. -- A **Context Snapshot** stores one codec-encoded JSON value and, for removable dynamic sources, a pre-rendered removal message per stable **Context Source** key. -- Changes from multiple **Context Sources** admitted at one safe boundary combine into one **Mid-Conversation System Message**. -- Context changes are sampled and admitted lazily at a **Safe Step Boundary**, never pushed asynchronously when their source changes. -- At a **Safe Step Boundary**, newly promoted user input or settled tool results precede any combined **Mid-Conversation System Message**. +- **Instructions** is an opaque carrier composed from zero or more **Instruction Sources**. +- **Model Context** is broader than **Instructions**. For each **Step**, the runner assembles the selected agent or provider system text, the **Instruction Baseline**, **Session History**, available tools, and step-local additions into one model request. +- **Session History** contains projected conversational messages and admitted **Instruction Updates**; the active **Instruction Baseline** remains separate provider-request state. +- The runner explicitly loads and combines instruction built-ins, **InstructionDiscovery**, selected-agent skill guidance, reference guidance, MCP guidance, and **InstructionEntry** values. There is no instruction registry. +- `Instructions.combine(...)` preserves caller order and rejects duplicate stable namespaced source keys. The runner loads its producers concurrently, then combines them in its fixed declared order. +- Each **Instruction Source** loader returns one coherent typed value or explicitly reports unavailability. `Instructions.make(...)` hides the value type so differently typed sources compose uniformly; its codec compares and stores the value, while pure renderers produce baseline, update, and optional removal text. +- `Instructions.initialize(...)` observes composed **Instructions** once and produces a complete **Instruction Baseline** with **Applied Instructions**. +- `Instructions.reconcile(...)` observes composed **Instructions** once and returns either unchanged or one combined chronological update. It never rewrites the baseline. +- `Instructions.rebaseline(...)` renders a fresh baseline after completed compaction, recalling previously applied values for sources that are temporarily unavailable. +- A changed **Instruction Source** may contribute text to one **Instruction Update** containing the newly effective state. +- An **Instruction Update** persists the exact combined rendered text sent to the model through `session.instructions.updated`. +- **Applied Instructions** advances atomically with the corresponding durable **Instruction Update**. +- **Applied Instructions** stores one codec-encoded JSON value and, for removable sources, a pre-rendered removal message per stable **Instruction Source** key. +- Changes from multiple **Instruction Sources** admitted at one safe boundary combine into one **Instruction Update**. +- Instruction changes are sampled and admitted lazily at a **Safe Step Boundary**, never pushed asynchronously when their source changes. +- At a **Safe Step Boundary**, prior tool results are already settled; instruction preparation completes before newly admitted user input promotes. - An **Admitted Prompt** is replayable pending input, not yet model-visible **Session History**. - **Prompt Promotion** atomically consumes the pending inbox entry and appends its model-visible user message. - Steering prompts promote at the next **Safe Step Boundary** while the current **Session Drain** still requires continuation. Promoting any newly admitted user input resets the selected agent's step allowance; multiple prompts promoted at one boundary reset it once. @@ -117,36 +130,28 @@ _Avoid_: Response envelope - A **Session Drain** is process-local coordination rather than a durable domain entity. Durable recovery must reason from prompts, projected history, physical attempts, and tool state rather than inventing an enclosing execution identity. - An **Execution** contains one or more **Session Drains**; a **Session Drain** contains one reserved assistant-turn span at a time; that span contains **Steps**; and each **Step** contains one or more **Physical Attempts** plus any tool calls it requires. - A **Step** record covers only the model-visible span from first assistant output through tool settlement; pre-flight leaves no record, and one Step settles at most one record. -- The first **Step** renders the latest complete **Baseline System Context** and initializes its **Context Snapshot** without emitting a redundant **Mid-Conversation System Message**; unavailable initial context blocks the Step instead of persisting an incomplete baseline. -- Initial **System Context** preparation precedes the first durable input promotion so an unavailable baseline leaves that input pending and retryable; ordinary reconciliation remains after promotion. -- Compaction starts a new **Context Epoch** with a freshly rendered **Baseline System Context** and **Context Snapshot**; prior **Mid-Conversation System Messages** remain durable audit history but leave projected model history. -- A newly registered core or plugin-defined **Context Source** absent from the current snapshot emits its baseline rendering once at the next **Safe Step Boundary**. -- **Context Source** keys are stable and namespaced; duplicate keys fail composition. `SystemContext.combine(...)` preserves caller order; the **System Context Registry** evaluates producers concurrently and combines them in stable contribution-key order so rendered context remains deterministic. -- Each **Context Source** loader returns one coherent typed value. `SystemContext.make(...)` hides that value type so differently typed sources compose uniformly. Its codec compares and stores that value; its pure renderers produce model-visible baseline, update, and removal text only when needed. -- `SystemContext.initialize(...)` observes a composed **System Context** once and produces a fresh **Baseline System Context** with its **Context Snapshot**. -- `SystemContext.reconcile(...)` observes a composed **System Context** once and returns exactly one next action: unchanged, updated, replacement ready, or replacement blocked. -- `SystemContext.replace(...)` renders a fresh generation after completed compaction or another baseline-replacing transition; it reports replacement blocked while previously admitted context is unavailable. -- **Unavailable Context** uses stale-while-revalidate semantics and is distinct from a successfully loaded absence, which may emit removal text. -- Ordinary **Context Source** loaders return values directly; loaders that intentionally use stale-while-revalidate may explicitly return **Unavailable Context**. -- Nested project instruction discovery after successful reads remains a follow-up; when implemented, discovered instructions must be admitted durably at the next **Safe Step Boundary**. -- Location-scoped services naturally re-resolve effective context when a moved session next runs in its destination location. -- Moving a Session clears its active **Context Epoch**, so the destination must initialize a complete baseline before another prompt can promote. -- Instruction discovery, source identity, persistence, and file loading belong to the instruction service; the **System Context** abstraction only composes effectful producers and renders loaded values. -- The first instruction-service slice observes global and upward project `AGENTS.md` files as one ordered aggregate **Context Source** at each **Safe Step Boundary**. -- Built-in and instruction context producers register through the **System Context Registry** with stable contribution keys. Plugin-defined context registration and hot-reload lifecycle remain a follow-up built on the same scoped registry seam. -- Selected-agent available-skill guidance is a **Context Source** composed with Location-wide registry sources immediately before Context Epoch admission. It lists only names and descriptions permitted for that agent; skill bodies and locations are exposed only through the permission-checked `skill` tool. +- The first **Step** renders the latest complete **Instruction Baseline** and creates its **InstructionCheckpoint** without emitting a redundant **Instruction Update**; an unavailable initial source blocks the Step instead of persisting an incomplete baseline. +- Instruction preparation precedes durable input promotion on every Step so an unavailable first baseline leaves pending input untouched and later updates enter history before newly promoted input. +- Completed compaction rebaselines the **InstructionCheckpoint** from current **Instructions** and removes earlier **Instruction Updates** from active projected model history while preserving durable audit history. +- A newly composed **Instruction Source** absent from **Applied Instructions** emits its baseline rendering once at the next **Safe Step Boundary**. +- **Unavailable Instruction Source** uses stale-while-revalidate semantics and is distinct from a successfully loaded absence, which may emit removal text. +- **InstructionDiscovery** observes ambient instructions as one ordered aggregate **Instruction Source**. +- Ambient discovery reads global and upward-project `AGENTS.md` files and honors `OPENCODE_DISABLE_PROJECT_CONFIG` for project files. +- After a successful internal file or directory read, nearby `AGENTS.md` files toward the Location root are injected once per Session as durable synthetic instruction messages. +- **InstructionEntry** stores API-managed per-Session JSON values. Each entry contributes one `api/` **Instruction Source**, so adding, replacing, or removing an entry is reconciled at the next **Safe Step Boundary**. +- Location-scoped instruction producers naturally re-resolve when a moved Session next runs in its destination Location. +- Moving a Session resets its **InstructionCheckpoint**, so the destination must initialize a complete baseline before another prompt can promote. Committed revert also resets the checkpoint. +- Selected-agent available-skill guidance is an **Instruction Source** composed explicitly by the runner. It lists only names and descriptions permitted for that agent; skill bodies and locations are exposed only through the permission-checked `skill` tool. - The selected agent and model are sampled when a **Step** starts. Changes admitted after that boundary apply to the next Step and do not restart the current Step. -- Selected-agent available-skill guidance remains a **Context Source**. An agent switch that changes that guidance produces a **Mid-Conversation System Message** while preserving the current baseline. +- An agent switch that changes selected-agent guidance produces an **Instruction Update** while preserving the current baseline. - Local tool authorization and pending permission requests retain the effective agent of the **Step** that issued the call; a later agent switch cannot change that call's policy. -- Context source changes never wake idle sessions; the next naturally scheduled **Safe Step Boundary** loads and compares current values lazily. -- Once admitted, a **Mid-Conversation System Message** remains durable even if the following **Physical Attempt** fails and is replayed unchanged on retry. -- **Mid-Conversation System Messages** remain durable Session-message history; normal user-facing transcript surfaces may hide them. -- The date **Context Source** initially preserves host-local calendar-date behavior; a configured user timezone may replace that default later. -- A **Context Epoch** begins with one immutable **Baseline System Context**. -- A **Baseline System Context** is stored durably and reused verbatim across process restarts within its **Context Epoch**. -- A **Baseline System Context** durably preserves the exact joined text used for the active provider-cache prefix. -- Completed compaction starts a new **Context Epoch** on the next **Physical Attempt**, folding the current complete **System Context** into a fresh baseline and removing earlier **Mid-Conversation System Messages** from active model history. -- A model/provider switch preserves the current **Context Epoch** and chronological conversation history; the new selection applies to the next **Step**. +- Instruction source changes never wake idle Sessions; the next naturally scheduled **Safe Step Boundary** loads and compares current values lazily. +- Once admitted, an **Instruction Update** remains durable even if the following **Physical Attempt** fails and is replayed unchanged on retry. +- **Instruction Updates** remain durable Session-message history; normal user-facing transcript surfaces may hide them. +- The date **Instruction Source** initially preserves host-local calendar-date behavior; a configured user timezone may replace that default later. +- An **Instruction Baseline** is stored durably and reused verbatim across process restarts until rebaseline or reset. +- An **Instruction Baseline** durably preserves the exact joined text used for its part of the active provider-cache prefix. +- A model/provider switch preserves the current **InstructionCheckpoint** and chronological conversation history; the new selection applies to the next **Step**. - **Native Continuation Metadata** remains in durable history. Step projection includes it only for a successful exact originating provider/model match; failed Steps and incompatible models omit opaque metadata, while non-empty visible reasoning lowers to ordinary assistant text after a model switch. This conservative relation may widen only when recorded provider tests establish compatibility. - **Model Request Options** remain provider-semantic through Catalog resolution. The Session runner maps them into the LLM package's provider-option namespace; the selected protocol adapter alone owns provider wire encoding. - **Generation Controls**, protocol-semantic **Model Request Options**, and compatibility request body fields are separate Catalog domains. A shared ingestion adapter partitions legacy and models.dev AI-SDK-shaped options before routing. @@ -190,16 +195,16 @@ _Avoid_: Response envelope - `sessions.message({ sessionID, messageID })` is a required resource lookup. An unknown Session fails with `SessionNotFoundError`; a known Session with an absent or differently owned message fails with `MessageNotFoundError` without disclosing cross-Session ownership. Absence is not represented as `undefined` across the public HTTP boundary. - `sessions.interrupt({ sessionID })` first verifies that the durable Session exists, failing with `SessionNotFoundError` otherwise. For a known Session, interruption is idempotent: idle, already-settled, or locally unowned execution is a no-op. - `sessions.active()` snapshots the current process's foreground Session drain registry as a record of Session IDs to `{ type: "running" }`. Missing IDs are inactive; background subagents and tasks do not make their parent Session active, and process restart clears the registry. -- `sessions.context({ sessionID })` preserves the existing message-only operation. It returns projected conversational messages selected as Session context; it does not include or represent the complete provider request context, whose baseline system context and other contributions remain separate. -- **Open question**: Should a future, separately named operation expose the complete provider request context, including baseline system context, selected source contributions, and context-epoch metadata? +- `sessions.context({ sessionID })` preserves the existing message-only operation. It returns projected **Session History**; it does not include or represent the complete **Model Context**, whose system text, **Instruction Baseline**, tools, and step-local additions remain separate. +- **Open question**: Should a future, separately named operation expose complete **Model Context**, including the instruction baseline, applied instruction metadata, tools, and step-local additions? - `sessions.prompt(...)` exposes `resume?: boolean`. Omitting it preserves durable admission followed by an advisory execution wake; `resume: false` requests durable admit-only behavior. - The public operation remains `sessions.prompt(...)`; `SessionInput.admit` is the internal primitive, while the public `Admission` result and `resume` option express its durable admission semantics. - `sessions.create(...)` accepts an optional `location`. Omission resolves through the connected OpenCode instance's default or current location; an explicit value selects a known location. Networked and embedded transports use the same handler semantics. - `sessions.switchAgent({ sessionID, agent })` is part of the common client alongside `sessions.switchModel(...)`. It affects subsequent Session activity and fails with `SessionNotFoundError` for an unknown Session. - The **Embedded OpenCode** Layer delegates to the same scoped creation path; it does not define a second implementation. - A **PTY Environment** adapter observes plugins in the request Location while passing the resolved PTY working directory to the hook; standalone servers use an empty adapter. -- A **Mid-Conversation System Message** lowers to the provider's native chronological instruction role when supported and to a wrapped chronological fallback otherwise. -- When the effective aggregate instruction set changes, its **Mid-Conversation System Message** includes the complete current ordered set and supersedes the prior aggregate value; when no ambient instructions remain, the message states that previously loaded instructions no longer apply. +- An **Instruction Update** lowers to the provider's native chronological instruction role when supported and to a wrapped chronological fallback otherwise. +- When the aggregate discovered instruction set changes, its **Instruction Update** includes the complete current ordered set and supersedes the prior aggregate value; when no discovered instructions remain, the message states that previously loaded instructions no longer apply. - Ambient project instruction discovery honors `OPENCODE_DISABLE_PROJECT_CONFIG`; global instructions remain eligible. - Oversized textual **Model Tool Output** retains a bounded preview in Session history while its complete text moves to managed tool-output storage. Arbitrary structured-result size is a separate concern. - One tool settlement receives one aggregate textual limit, using the configured maximum lines or UTF-8 bytes, whichever is reached first. The limit is provider-independent; token pressure belongs to context assembly and compaction. @@ -232,9 +237,9 @@ Before stabilizing the client API: ## Example dialogue -> **Dev:** "The date changed while the session was active. Should the **Mid-Conversation System Message** say what the old date was?" -> **Domain expert:** "No. Emit the newly effective date so the agent can act on the current **System Context**." +> **Dev:** "The date changed while the session was active. Should the **Instruction Update** say what the old date was?" +> **Domain expert:** "No. Emit the newly effective date so the agent can act on the current instructions." ## Flagged ambiguities -- Legacy `experimental.chat.system.transform` can mutate the assembled baseline system prompt arbitrarily, but V2 plugins do not yet expose an equivalent hook. Decide separately whether to port it, replace dynamic uses with plugin-defined **Context Sources**, or narrow its semantics. +- Legacy `experimental.chat.system.transform` can mutate assembled system text arbitrarily, but V2 plugins do not yet expose an equivalent hook. Decide separately whether to port it, model dynamic uses as explicit **Instruction Sources**, or narrow its semantics. diff --git a/packages/client/src/effect/api/api.ts b/packages/client/src/effect/api/api.ts index 9523d3f8bae..76f243c3dc1 100644 --- a/packages/client/src/effect/api/api.ts +++ b/packages/client/src/effect/api/api.ts @@ -196,33 +196,35 @@ export type Endpoint4_18Input = { readonly sessionID: Endpoint4_18Request["param export type Endpoint4_18Output = EffectValue>["data"] export type SessionContextOperation = (input: Endpoint4_18Input) => Effect.Effect -type Endpoint4_19Request = Parameters[0] +type Endpoint4_19Request = Parameters[0] export type Endpoint4_19Input = { readonly sessionID: Endpoint4_19Request["params"]["sessionID"] } export type Endpoint4_19Output = EffectValue< - ReturnType + ReturnType >["data"] -export type SessionListContextEntriesOperation = ( +export type SessionInstructionsEntryListOperation = ( input: Endpoint4_19Input, ) => Effect.Effect -type Endpoint4_20Request = Parameters[0] +type Endpoint4_20Request = Parameters[0] export type Endpoint4_20Input = { readonly sessionID: Endpoint4_20Request["params"]["sessionID"] readonly key: Endpoint4_20Request["params"]["key"] readonly value: Endpoint4_20Request["payload"]["value"] } -export type Endpoint4_20Output = EffectValue> -export type SessionPutContextEntryOperation = ( +export type Endpoint4_20Output = EffectValue> +export type SessionInstructionsEntryPutOperation = ( input: Endpoint4_20Input, ) => Effect.Effect -type Endpoint4_21Request = Parameters[0] +type Endpoint4_21Request = Parameters[0] export type Endpoint4_21Input = { readonly sessionID: Endpoint4_21Request["params"]["sessionID"] readonly key: Endpoint4_21Request["params"]["key"] } -export type Endpoint4_21Output = EffectValue> -export type SessionRemoveContextEntryOperation = ( +export type Endpoint4_21Output = EffectValue< + ReturnType +> +export type SessionInstructionsEntryRemoveOperation = ( input: Endpoint4_21Input, ) => Effect.Effect @@ -273,9 +275,13 @@ export interface SessionApi { readonly revertClear: SessionRevertClearOperation readonly revertCommit: SessionRevertCommitOperation readonly context: SessionContextOperation - readonly listContextEntries: SessionListContextEntriesOperation - readonly putContextEntry: SessionPutContextEntryOperation - readonly removeContextEntry: SessionRemoveContextEntryOperation + readonly instructions: { + readonly entry: { + readonly list: SessionInstructionsEntryListOperation + readonly put: SessionInstructionsEntryPutOperation + readonly remove: SessionInstructionsEntryRemoveOperation + } + } readonly log: SessionLogOperation readonly interrupt: SessionInterruptOperation readonly background: SessionBackgroundOperation diff --git a/packages/client/src/effect/generated/client.ts b/packages/client/src/effect/generated/client.ts index b7dc996abae..514f70a9236 100644 --- a/packages/client/src/effect/generated/client.ts +++ b/packages/client/src/effect/generated/client.ts @@ -266,33 +266,33 @@ const Endpoint4_18 = (raw: RawClient["server.session"]) => (input: Endpoint4_18I Effect.map((value) => value.data), ) -type Endpoint4_19Request = Parameters[0] +type Endpoint4_19Request = Parameters[0] type Endpoint4_19Input = { readonly sessionID: Endpoint4_19Request["params"]["sessionID"] } const Endpoint4_19 = (raw: RawClient["server.session"]) => (input: Endpoint4_19Input) => - raw["session.context.entry.list"]({ params: { sessionID: input["sessionID"] } }).pipe( + raw["session.instructions.entry.list"]({ params: { sessionID: input["sessionID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint4_20Request = Parameters[0] +type Endpoint4_20Request = Parameters[0] type Endpoint4_20Input = { readonly sessionID: Endpoint4_20Request["params"]["sessionID"] readonly key: Endpoint4_20Request["params"]["key"] readonly value: Endpoint4_20Request["payload"]["value"] } const Endpoint4_20 = (raw: RawClient["server.session"]) => (input: Endpoint4_20Input) => - raw["session.context.entry.put"]({ + raw["session.instructions.entry.put"]({ params: { sessionID: input["sessionID"], key: input["key"] }, payload: { value: input["value"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint4_21Request = Parameters[0] +type Endpoint4_21Request = Parameters[0] type Endpoint4_21Input = { readonly sessionID: Endpoint4_21Request["params"]["sessionID"] readonly key: Endpoint4_21Request["params"]["key"] } const Endpoint4_21 = (raw: RawClient["server.session"]) => (input: Endpoint4_21Input) => - raw["session.context.entry.remove"]({ params: { sessionID: input["sessionID"], key: input["key"] } }).pipe( + raw["session.instructions.entry.remove"]({ params: { sessionID: input["sessionID"], key: input["key"] } }).pipe( Effect.mapError(mapClientError), ) @@ -354,9 +354,7 @@ const adaptGroup4 = (raw: RawClient["server.session"]) => ({ revertClear: Endpoint4_16(raw), revertCommit: Endpoint4_17(raw), context: Endpoint4_18(raw), - listContextEntries: Endpoint4_19(raw), - putContextEntry: Endpoint4_20(raw), - removeContextEntry: Endpoint4_21(raw), + instructions: { entry: { list: Endpoint4_19(raw), put: Endpoint4_20(raw), remove: Endpoint4_21(raw) } }, log: Endpoint4_22(raw), interrupt: Endpoint4_23(raw), background: Endpoint4_24(raw), diff --git a/packages/client/src/promise/api.ts b/packages/client/src/promise/api.ts index e7d1c27d259..d31a1881fa8 100644 --- a/packages/client/src/promise/api.ts +++ b/packages/client/src/promise/api.ts @@ -18,7 +18,11 @@ type PromisifyOperation = Operation extends ( ? (...args: Args) => Promise : Operation extends (...args: infer Args) => Stream.Stream ? (...args: Args) => AsyncIterable - : Operation + : Operation extends (...args: infer _Args) => unknown + ? Operation + : Operation extends object + ? PromisifyApi + : Operation type PromisifyApi = { readonly [Name in keyof Api]: PromisifyOperation diff --git a/packages/client/src/promise/generated/client.ts b/packages/client/src/promise/generated/client.ts index ad94f07fd37..929bc2ecb6d 100644 --- a/packages/client/src/promise/generated/client.ts +++ b/packages/client/src/promise/generated/client.ts @@ -43,12 +43,12 @@ import type { SessionRevertCommitOutput, SessionContextInput, SessionContextOutput, - SessionListContextEntriesInput, - SessionListContextEntriesOutput, - SessionPutContextEntryInput, - SessionPutContextEntryOutput, - SessionRemoveContextEntryInput, - SessionRemoveContextEntryOutput, + SessionInstructionsEntryListInput, + SessionInstructionsEntryListOutput, + SessionInstructionsEntryPutInput, + SessionInstructionsEntryPutOutput, + SessionInstructionsEntryRemoveInput, + SessionInstructionsEntryRemoveOutput, SessionLogInput, SessionLogOutput, SessionInterruptInput, @@ -607,40 +607,44 @@ export function make(options: ClientOptions) { }, requestOptions, ).then((value) => value.data), - listContextEntries: (input: SessionListContextEntriesInput, requestOptions?: RequestOptions) => - request<{ readonly data: SessionListContextEntriesOutput }>( - { - method: "GET", - path: `/api/session/${encodeURIComponent(input.sessionID)}/context-entry`, - successStatus: 200, - declaredStatuses: [404, 400, 401], - empty: false, - }, - requestOptions, - ).then((value) => value.data), - putContextEntry: (input: SessionPutContextEntryInput, requestOptions?: RequestOptions) => - request( - { - method: "PUT", - path: `/api/session/${encodeURIComponent(input.sessionID)}/context-entry/${encodeURIComponent(input.key)}`, - body: { value: input["value"] }, - successStatus: 204, - declaredStatuses: [404, 400, 401], - empty: true, - }, - requestOptions, - ), - removeContextEntry: (input: SessionRemoveContextEntryInput, requestOptions?: RequestOptions) => - request( - { - method: "DELETE", - path: `/api/session/${encodeURIComponent(input.sessionID)}/context-entry/${encodeURIComponent(input.key)}`, - successStatus: 204, - declaredStatuses: [404, 400, 401], - empty: true, - }, - requestOptions, - ), + instructions: { + entry: { + list: (input: SessionInstructionsEntryListInput, requestOptions?: RequestOptions) => + request<{ readonly data: SessionInstructionsEntryListOutput }>( + { + method: "GET", + path: `/api/session/${encodeURIComponent(input.sessionID)}/instructions/entries`, + successStatus: 200, + declaredStatuses: [404, 400, 401], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + put: (input: SessionInstructionsEntryPutInput, requestOptions?: RequestOptions) => + request( + { + method: "PUT", + path: `/api/session/${encodeURIComponent(input.sessionID)}/instructions/entries/${encodeURIComponent(input.key)}`, + body: { value: input["value"] }, + successStatus: 204, + declaredStatuses: [404, 400, 401], + empty: true, + }, + requestOptions, + ), + remove: (input: SessionInstructionsEntryRemoveInput, requestOptions?: RequestOptions) => + request( + { + method: "DELETE", + path: `/api/session/${encodeURIComponent(input.sessionID)}/instructions/entries/${encodeURIComponent(input.key)}`, + successStatus: 204, + declaredStatuses: [404, 400, 401], + empty: true, + }, + requestOptions, + ), + }, + }, log: (input: SessionLogInput, requestOptions?: RequestOptions): AsyncIterable => sse( { diff --git a/packages/client/src/promise/generated/types.ts b/packages/client/src/promise/generated/types.ts index dc28955f49d..0473ce4a5ed 100644 --- a/packages/client/src/promise/generated/types.ts +++ b/packages/client/src/promise/generated/types.ts @@ -1091,26 +1091,26 @@ export type SessionContextOutput = { > }["data"] -export type SessionListContextEntriesInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] } +export type SessionInstructionsEntryListInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] } -export type SessionListContextEntriesOutput = { +export type SessionInstructionsEntryListOutput = { readonly data: ReadonlyArray<{ readonly key: string; readonly value: JsonValue }> }["data"] -export type SessionPutContextEntryInput = { +export type SessionInstructionsEntryPutInput = { readonly sessionID: { readonly sessionID: string; readonly key: string }["sessionID"] readonly key: { readonly sessionID: string; readonly key: string }["key"] readonly value: { readonly value: JsonValue }["value"] } -export type SessionPutContextEntryOutput = void +export type SessionInstructionsEntryPutOutput = void -export type SessionRemoveContextEntryInput = { +export type SessionInstructionsEntryRemoveInput = { readonly sessionID: { readonly sessionID: string; readonly key: string }["sessionID"] readonly key: { readonly sessionID: string; readonly key: string }["key"] } -export type SessionRemoveContextEntryOutput = void +export type SessionInstructionsEntryRemoveOutput = void export type SessionLogInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] @@ -1212,7 +1212,7 @@ export type SessionLogOutput = readonly id: string readonly created: number readonly metadata?: { readonly [x: string]: unknown } - readonly type: "session.context.updated" + readonly type: "session.instructions.updated" readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly data: { readonly sessionID: string; readonly text: string } @@ -4506,7 +4506,7 @@ export type EventSubscribeOutput = readonly id: string readonly created: number readonly metadata?: { readonly [x: string]: unknown } - readonly type: "session.context.updated" + readonly type: "session.instructions.updated" readonly durable: { readonly aggregateID: string; readonly seq: number; readonly version: number } readonly location?: { readonly directory: string; readonly workspaceID?: string } readonly data: { readonly sessionID: string; readonly text: string } diff --git a/packages/client/test/api.types.ts b/packages/client/test/api.types.ts index 5b17b23c096..ba95bb42970 100644 --- a/packages/client/test/api.types.ts +++ b/packages/client/test/api.types.ts @@ -2,9 +2,39 @@ import { Effect } from "effect" import { OpenCode as EffectOpenCode, type AppApi as EffectApi } from "../src/effect" type EffectClient = Effect.Success> +type PromiseClient = ReturnType declare const effectClient: EffectClient +declare const promiseClient: PromiseClient const effectApi: EffectApi = effectClient -void effectApi +declare const sessionID: Parameters[0]["sessionID"] + +const effectList: Effect.Effect< + ReadonlyArray<{ readonly key: string; readonly value: unknown }>, + unknown +> = effectApi.session.instructions.entry.list({ sessionID }) +const effectPut: Effect.Effect = effectApi.session.instructions.entry.put({ + sessionID, + key: "review-notes", + value: { text: "Check the diff" }, +}) +const effectRemove: Effect.Effect = effectApi.session.instructions.entry.remove({ + sessionID, + key: "review-notes", +}) + +const promiseList: Promise> = + promiseClient.session.instructions.entry.list({ sessionID: "ses_test" }) +const promisePut: Promise = promiseClient.session.instructions.entry.put({ + sessionID: "ses_test", + key: "review-notes", + value: { text: "Check the diff" }, +}) +const promiseRemove: Promise = promiseClient.session.instructions.entry.remove({ + sessionID: "ses_test", + key: "review-notes", +}) + +void [effectList, effectPut, effectRemove, promiseList, promisePut, promiseRemove] diff --git a/packages/client/test/effect.test.ts b/packages/client/test/effect.test.ts index 2073af42ac1..4c5ea512d79 100644 --- a/packages/client/test/effect.test.ts +++ b/packages/client/test/effect.test.ts @@ -27,6 +27,57 @@ test("session.get returns the decoded Effect projection", async () => { expect(DateTime.toEpochMillis(result.time.created)).toBe(1_717_171_717_000) }) +test("session instructions methods use the public HTTP contract", async () => { + const requests: Array<{ method: string; url: string; body?: unknown }> = [] + const instructions = [{ key: "review-notes", value: { text: "Check the diff", priority: 1 } }] + const httpClient = HttpClient.make((request) => { + requests.push({ + method: request.method, + url: request.url, + body: request.body._tag === "Uint8Array" ? JSON.parse(new TextDecoder().decode(request.body.body)) : undefined, + }) + return Effect.succeed( + HttpClientResponse.fromWeb( + request, + request.method === "GET" ? Response.json({ data: instructions }) : new Response(null, { status: 204 }), + ), + ) + }) + const result = await Effect.gen(function* () { + const client = yield* OpenCode.make({ baseUrl: "http://localhost:3000" }) + const listed = yield* client.session.instructions.entry.list({ sessionID: Session.ID.make("ses_test") }) + yield* client.session.instructions.entry.put({ + sessionID: Session.ID.make("ses_test"), + key: "review-notes", + value: instructions[0].value, + }) + yield* client.session.instructions.entry.remove({ + sessionID: Session.ID.make("ses_test"), + key: "review-notes", + }) + return listed + }).pipe(Effect.provideService(HttpClient.HttpClient, httpClient), Effect.runPromise) + + expect(result).toEqual(instructions) + expect(requests).toEqual([ + { + method: "GET", + url: "http://localhost:3000/api/session/ses_test/instructions/entries", + body: undefined, + }, + { + method: "PUT", + url: "http://localhost:3000/api/session/ses_test/instructions/entries/review-notes", + body: { value: { text: "Check the diff", priority: 1 } }, + }, + { + method: "DELETE", + url: "http://localhost:3000/api/session/ses_test/instructions/entries/review-notes", + body: undefined, + }, + ]) +}) + test("event.subscribe exposes and decodes the native Effect event stream", async () => { const httpClient = HttpClient.make((request) => Effect.succeed( diff --git a/packages/client/test/promise.test.ts b/packages/client/test/promise.test.ts index 04737612e25..21b191fd2ab 100644 --- a/packages/client/test/promise.test.ts +++ b/packages/client/test/promise.test.ts @@ -148,6 +148,51 @@ test("session.get returns the wire projection", async () => { expect(result.time.created).toBe(1_717_171_717_000) }) +test("session instructions methods use the public HTTP contract", async () => { + const requests: Array<{ method: string; url: string; body?: unknown }> = [] + const instructions = [{ key: "review-notes", value: { text: "Check the diff", priority: 1 } }] + const client = OpenCode.make({ + baseUrl: "http://localhost:3000", + fetch: async (input, init) => { + const request = input instanceof Request ? input : new Request(input, init) + requests.push({ + method: request.method, + url: request.url, + body: request.method === "PUT" ? await request.json() : undefined, + }) + if (request.method === "GET") return Response.json({ data: instructions }) + return new Response(null, { status: 204 }) + }, + }) + + const result = await client.session.instructions.entry.list({ sessionID: "ses_test" }) + await client.session.instructions.entry.put({ + sessionID: "ses_test", + key: "review-notes", + value: instructions[0].value, + }) + await client.session.instructions.entry.remove({ sessionID: "ses_test", key: "review-notes" }) + + expect(result).toEqual(instructions) + expect(requests).toEqual([ + { + method: "GET", + url: "http://localhost:3000/api/session/ses_test/instructions/entries", + body: undefined, + }, + { + method: "PUT", + url: "http://localhost:3000/api/session/ses_test/instructions/entries/review-notes", + body: { value: { text: "Check the diff", priority: 1 } }, + }, + { + method: "DELETE", + url: "http://localhost:3000/api/session/ses_test/instructions/entries/review-notes", + body: undefined, + }, + ]) +}) + test("event.subscribe exposes the Promise event stream wire projection", async () => { const client = OpenCode.make({ baseUrl: "http://localhost:3000", diff --git a/packages/codemode/test/fixtures/opencode-v2-openapi.json b/packages/codemode/test/fixtures/opencode-v2-openapi.json index 4d1d3af7082..b20a25b25e1 100644 --- a/packages/codemode/test/fixtures/opencode-v2-openapi.json +++ b/packages/codemode/test/fixtures/opencode-v2-openapi.json @@ -2350,12 +2350,12 @@ "summary": "Get session context" } }, - "/api/session/{sessionID}/context-entry": { + "/api/session/{sessionID}/instructions/entries": { "get": { "tags": [ "sessions" ], - "operationId": "v2.session.context.entry.list", + "operationId": "v2.session.instructions.entry.list", "parameters": [ { "name": "sessionID", @@ -2383,7 +2383,7 @@ "data": { "type": "array", "items": { - "$ref": "#/components/schemas/SessionContextEntry.Info" + "$ref": "#/components/schemas/InstructionEntry.Info" } } }, @@ -2433,16 +2433,16 @@ } } }, - "description": "List API-managed context entries attached to the session's system context.", - "summary": "List context entries" + "description": "List API-managed instruction entries attached to the session.", + "summary": "List instruction entries" } }, - "/api/session/{sessionID}/context-entry/{key}": { + "/api/session/{sessionID}/instructions/entries/{key}": { "put": { "tags": [ "sessions" ], - "operationId": "v2.session.context.entry.put", + "operationId": "v2.session.instructions.entry.put", "parameters": [ { "name": "sessionID", @@ -2461,7 +2461,7 @@ "name": "key", "in": "path", "schema": { - "$ref": "#/components/schemas/SessionContextEntry.Key" + "$ref": "#/components/schemas/InstructionEntry.Key" }, "required": true } @@ -2509,8 +2509,8 @@ } } }, - "description": "Attach or replace one durable context entry. The value is rendered into the session's system context; changes announce as updates at the next turn boundary.", - "summary": "Put context entry", + "description": "Attach or replace one durable instruction entry. Changes announce as updates at the next step boundary.", + "summary": "Put instruction entry", "requestBody": { "content": { "application/json": { @@ -2533,7 +2533,7 @@ "tags": [ "sessions" ], - "operationId": "v2.session.context.entry.remove", + "operationId": "v2.session.instructions.entry.remove", "parameters": [ { "name": "sessionID", @@ -2552,7 +2552,7 @@ "name": "key", "in": "path", "schema": { - "$ref": "#/components/schemas/SessionContextEntry.Key" + "$ref": "#/components/schemas/InstructionEntry.Key" }, "required": true } @@ -2600,8 +2600,8 @@ } } }, - "description": "Remove one context entry; the removal is announced to the model at the next turn boundary.", - "summary": "Remove context entry" + "description": "Remove one instruction entry; the removal is announced to the model at the next step boundary.", + "summary": "Remove instruction entry" } }, "/api/session/{sessionID}/log": { @@ -11692,7 +11692,7 @@ } ] }, - "SessionContextEntry.Key": { + "InstructionEntry.Key": { "type": "string", "allOf": [ { @@ -11701,11 +11701,11 @@ } ] }, - "SessionContextEntry.Info": { + "InstructionEntry.Info": { "type": "object", "properties": { "key": { - "$ref": "#/components/schemas/SessionContextEntry.Key" + "$ref": "#/components/schemas/InstructionEntry.Key" }, "value": {} }, @@ -12385,7 +12385,7 @@ ], "additionalProperties": false }, - "session.next.context.updated": { + "session.next.instructions.updated": { "type": "object", "properties": { "id": { @@ -12402,7 +12402,7 @@ "type": { "type": "string", "enum": [ - "session.next.context.updated" + "session.next.instructions.updated" ] }, "durable": { @@ -14917,7 +14917,7 @@ "$ref": "#/components/schemas/session.next.prompt.admitted" }, { - "$ref": "#/components/schemas/session.next.context.updated" + "$ref": "#/components/schemas/session.next.instructions.updated" }, { "$ref": "#/components/schemas/session.next.synthetic" @@ -26060,7 +26060,7 @@ "$ref": "#/components/schemas/session.next.execution.settled" }, { - "$ref": "#/components/schemas/session.next.context.updated" + "$ref": "#/components/schemas/session.next.instructions.updated" }, { "$ref": "#/components/schemas/session.next.synthetic" diff --git a/packages/codemode/test/openapi.test.ts b/packages/codemode/test/openapi.test.ts index 7ad3d486247..db799e58943 100644 --- a/packages/codemode/test/openapi.test.ts +++ b/packages/codemode/test/openapi.test.ts @@ -54,7 +54,9 @@ const json = (value: unknown, status = 200) => const singleOperation = (operation: Record, method = "get"): Document => ({ openapi: "3.1.0", - paths: { "/test": { [method]: { operationId: "test", responses: { 200: { description: "Success" } }, ...operation } } }, + paths: { + "/test": { [method]: { operationId: "test", responses: { 200: { description: "Success" } }, ...operation } }, + }, }) describe("OpenAPI.fromSpec", () => { @@ -94,7 +96,12 @@ describe("OpenAPI.fromSpec", () => { const remove = toolAt(api.tools, "users.remove") expect(api.skipped).toEqual([]) - if (!Tool.isDefinition(get) || !Tool.isDefinition(create) || !Tool.isDefinition(search) || !Tool.isDefinition(remove)) { + if ( + !Tool.isDefinition(get) || + !Tool.isDefinition(create) || + !Tool.isDefinition(search) || + !Tool.isDefinition(remove) + ) { throw new Error("happy-path fixture did not generate every operation") } expect(inputTypeScript(get)).toBe( @@ -110,7 +117,8 @@ describe("OpenAPI.fromSpec", () => { const result = await Effect.runPromise( CodeMode.make({ tools: { api: api.tools } }) - .execute(` + .execute( + ` const user = await tools.api.users.get({ userId: "user-1", include: ["profile", "permissions"], @@ -128,7 +136,8 @@ describe("OpenAPI.fromSpec", () => { }) const removed = await tools.api.users.remove({ userId: "user-1" }) return { user, created, summary, removed } - `) + `, + ) .pipe(Effect.provide(client.layer)), ) @@ -196,11 +205,11 @@ describe("OpenAPI.fromSpec", () => { if (!Tool.isDefinition(switchAgent)) throw new Error("v2.session.switchAgent was not generated") expect(inputTypeScript(switchAgent)).toBe("{ sessionID: string; agent: string }") - const contextEntryPut = toolAt(result.tools, "v2.session.contextEntry.put") - expect(Tool.isDefinition(contextEntryPut)).toBe(true) - if (!Tool.isDefinition(contextEntryPut)) throw new Error("v2.session.contextEntry.put was not generated") - expect(inputTypeScript(contextEntryPut)).toBe("{ sessionID: string; key: string; value: unknown }") - expect(toolAt(result.tools, "v2_session_context_entry_put_2")).toBeUndefined() + const instructionPut = toolAt(result.tools, "v2.session.instructions.entry.put") + expect(Tool.isDefinition(instructionPut)).toBe(true) + if (!Tool.isDefinition(instructionPut)) throw new Error("v2.session.instructions.entry.put was not generated") + expect(inputTypeScript(instructionPut)).toBe("{ sessionID: string; key: string; value: unknown }") + expect(toolAt(result.tools, "v2_session_instructions_entry_put_2")).toBeUndefined() expect(toolAt(result.tools, "v2.pty.connect")).toBeUndefined() expect(toolAt(result.tools, "v2.session.log")).toBeUndefined() expect(toolAt(result.tools, "v2.event.subscribe")).toBeUndefined() @@ -481,9 +490,9 @@ describe("OpenAPI.fromSpec", () => { expect(url.searchParams.get("nullable")).toBe("null") expect(url.searchParams.get("constructor")).toBe("safe") expect(client.requests[0]!.headers.meta).toBe("a=b,c=d") - await expect( - Effect.runPromise(tool.run({ keys: [undefined] }).pipe(Effect.provide(client.layer))), - ).rejects.toThrow("unsupported nested value") + await expect(Effect.runPromise(tool.run({ keys: [undefined] }).pipe(Effect.provide(client.layer)))).rejects.toThrow( + "unsupported nested value", + ) }) test("skips unsupported parameter encodings and malformed security", () => { @@ -585,7 +594,10 @@ describe("OpenAPI.fromSpec", () => { test("applies authentication carriers without prototype or collision loss", async () => { const client = recordingClient(() => json({ ok: true })) - const authenticated = (security: ReadonlyArray>>, schemes: Record) => + const authenticated = ( + security: ReadonlyArray>>, + schemes: Record, + ) => OpenAPI.fromSpec({ baseUrl, spec: { ...singleOperation({}), security, components: { securitySchemes: schemes } }, @@ -601,13 +613,10 @@ describe("OpenAPI.fromSpec", () => { expect(new URL(client.requests[0]!.url).searchParams.get("__proto__")).toBe("secret") const duplicate = toolAt( - authenticated( - [{ first: [], second: [] }], - { - first: { type: "apiKey", in: "header", name: "x-key" }, - second: { type: "apiKey", in: "header", name: "x-key" }, - }, - ).tools, + authenticated([{ first: [], second: [] }], { + first: { type: "apiKey", in: "header", name: "x-key" }, + second: { type: "apiKey", in: "header", name: "x-key" }, + }).tools, "test", ) if (!Tool.isDefinition(duplicate)) throw new Error("duplicate auth tool was not generated") @@ -632,8 +641,7 @@ describe("OpenAPI.fromSpec", () => { }, }, auth: { - resolve: ({ name }) => - Effect.succeed(name === "bearer" ? { type: "bearer", token: "secret" } : undefined), + resolve: ({ name }) => Effect.succeed(name === "bearer" ? { type: "bearer", token: "secret" } : undefined), }, }) const alternativeTool = toolAt(alternative.tools, "test") @@ -765,9 +773,7 @@ describe("OpenAPI.fromSpec", () => { const oversized = recordingClient( () => new Response(null, { headers: { "content-length": String(50 * 1024 * 1024 + 1) } }), ) - const malformed = recordingClient( - () => new Response("{", { headers: { "content-type": "application/json" } }), - ) + const malformed = recordingClient(() => new Response("{", { headers: { "content-type": "application/json" } })) const chunked = recordingClient(() => new Response(new Uint8Array(50 * 1024 * 1024 + 1))) await expect(Effect.runPromise(tool.run({}).pipe(Effect.provide(oversized.layer)))).rejects.toThrow( diff --git a/packages/core/package.json b/packages/core/package.json index 84a51e61d2c..23771daaa71 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -19,7 +19,7 @@ "./effect/layer-node": "./src/effect/layer-node.ts", "./effect/app-node": "./src/effect/app-node.ts", "./session/runner": "./src/session/runner/index.ts", - "./system-context": "./src/system-context/index.ts", + "./instructions": "./src/instructions/index.ts", "./*": "./src/*.ts" }, "imports": { diff --git a/packages/core/schema.json b/packages/core/schema.json index d9e0b20b22f..222cc7b3992 100644 --- a/packages/core/schema.json +++ b/packages/core/schema.json @@ -1,9 +1,9 @@ { "version": "7", "dialect": "sqlite", - "id": "96e9fe64-d810-4102-8f79-3317a88bb6d2", + "id": "992b24b9-f3e9-41f5-87a5-4917d1423169", "prevIds": [ - "22e57fed-b9b8-4e94-a3b4-f94bece680a8" + "96e9fe64-660f-4a73-9414-b38bb7eac290" ], "ddl": [ { @@ -50,6 +50,14 @@ "name": "project", "entityType": "tables" }, + { + "name": "instruction_checkpoint", + "entityType": "tables" + }, + { + "name": "instruction_entry", + "entityType": "tables" + }, { "name": "message", "entityType": "tables" @@ -58,14 +66,6 @@ "name": "part", "entityType": "tables" }, - { - "name": "session_context_epoch", - "entityType": "tables" - }, - { - "name": "session_context_entry", - "entityType": "tables" - }, { "name": "session_input", "entityType": "tables" @@ -786,6 +786,96 @@ "entityType": "columns", "table": "project" }, + { + "type": "text", + "notNull": false, + "autoincrement": false, + "default": null, + "generated": null, + "name": "session_id", + "entityType": "columns", + "table": "instruction_checkpoint" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "baseline", + "entityType": "columns", + "table": "instruction_checkpoint" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "snapshot", + "entityType": "columns", + "table": "instruction_checkpoint" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "baseline_seq", + "entityType": "columns", + "table": "instruction_checkpoint" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "session_id", + "entityType": "columns", + "table": "instruction_entry" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "key", + "entityType": "columns", + "table": "instruction_entry" + }, + { + "type": "text", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "value", + "entityType": "columns", + "table": "instruction_entry" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_created", + "entityType": "columns", + "table": "instruction_entry" + }, + { + "type": "integer", + "notNull": true, + "autoincrement": false, + "default": null, + "generated": null, + "name": "time_updated", + "entityType": "columns", + "table": "instruction_entry" + }, { "type": "text", "notNull": false, @@ -896,96 +986,6 @@ "entityType": "columns", "table": "part" }, - { - "type": "text", - "notNull": false, - "autoincrement": false, - "default": null, - "generated": null, - "name": "session_id", - "entityType": "columns", - "table": "session_context_epoch" - }, - { - "type": "text", - "notNull": true, - "autoincrement": false, - "default": null, - "generated": null, - "name": "baseline", - "entityType": "columns", - "table": "session_context_epoch" - }, - { - "type": "text", - "notNull": true, - "autoincrement": false, - "default": null, - "generated": null, - "name": "snapshot", - "entityType": "columns", - "table": "session_context_epoch" - }, - { - "type": "integer", - "notNull": true, - "autoincrement": false, - "default": null, - "generated": null, - "name": "baseline_seq", - "entityType": "columns", - "table": "session_context_epoch" - }, - { - "type": "text", - "notNull": true, - "autoincrement": false, - "default": null, - "generated": null, - "name": "session_id", - "entityType": "columns", - "table": "session_context_entry" - }, - { - "type": "text", - "notNull": true, - "autoincrement": false, - "default": null, - "generated": null, - "name": "key", - "entityType": "columns", - "table": "session_context_entry" - }, - { - "type": "text", - "notNull": true, - "autoincrement": false, - "default": null, - "generated": null, - "name": "value", - "entityType": "columns", - "table": "session_context_entry" - }, - { - "type": "integer", - "notNull": true, - "autoincrement": false, - "default": null, - "generated": null, - "name": "time_created", - "entityType": "columns", - "table": "session_context_entry" - }, - { - "type": "integer", - "notNull": true, - "autoincrement": false, - "default": null, - "generated": null, - "name": "time_updated", - "entityType": "columns", - "table": "session_context_entry" - }, { "type": "text", "notNull": false, @@ -1621,6 +1621,36 @@ "entityType": "fks", "table": "project_directory" }, + { + "columns": [ + "session_id" + ], + "tableTo": "session", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_instruction_checkpoint_session_id_session_id_fk", + "entityType": "fks", + "table": "instruction_checkpoint" + }, + { + "columns": [ + "session_id" + ], + "tableTo": "session", + "columnsTo": [ + "id" + ], + "onUpdate": "NO ACTION", + "onDelete": "CASCADE", + "nameExplicit": false, + "name": "fk_instruction_entry_session_id_session_id_fk", + "entityType": "fks", + "table": "instruction_entry" + }, { "columns": [ "session_id" @@ -1651,36 +1681,6 @@ "entityType": "fks", "table": "part" }, - { - "columns": [ - "session_id" - ], - "tableTo": "session", - "columnsTo": [ - "id" - ], - "onUpdate": "NO ACTION", - "onDelete": "CASCADE", - "nameExplicit": false, - "name": "fk_session_context_epoch_session_id_session_id_fk", - "entityType": "fks", - "table": "session_context_epoch" - }, - { - "columns": [ - "session_id" - ], - "tableTo": "session", - "columnsTo": [ - "id" - ], - "onUpdate": "NO ACTION", - "onDelete": "CASCADE", - "nameExplicit": false, - "name": "fk_session_context_entry_session_id_session_id_fk", - "entityType": "fks", - "table": "session_context_entry" - }, { "columns": [ "session_id" @@ -1782,9 +1782,9 @@ "key" ], "nameExplicit": false, - "name": "session_context_entry_pk", + "name": "instruction_entry_pk", "entityType": "pks", - "table": "session_context_entry" + "table": "instruction_entry" }, { "columns": [ @@ -1877,6 +1877,15 @@ "table": "project", "entityType": "pks" }, + { + "columns": [ + "session_id" + ], + "nameExplicit": false, + "name": "instruction_checkpoint_pk", + "table": "instruction_checkpoint", + "entityType": "pks" + }, { "columns": [ "id" @@ -1895,15 +1904,6 @@ "table": "part", "entityType": "pks" }, - { - "columns": [ - "session_id" - ], - "nameExplicit": false, - "name": "session_context_epoch_pk", - "table": "session_context_epoch", - "entityType": "pks" - }, { "columns": [ "id" @@ -2252,4 +2252,4 @@ } ], "renames": [] -} \ No newline at end of file +} diff --git a/packages/core/src/database/migration.gen.ts b/packages/core/src/database/migration.gen.ts index e6a236f5271..9d3e4e673f9 100644 --- a/packages/core/src/database/migration.gen.ts +++ b/packages/core/src/database/migration.gen.ts @@ -44,5 +44,6 @@ export const migrations = ( import("./migration/20260703090000_reset_v2_event_rename_sweep"), import("./migration/20260703181610_event_created_column"), import("./migration/20260703190000_reset_v2_shell_event_payloads"), + import("./migration/20260705180000_rename_instructions"), ]) ).map((module) => module.default) satisfies DatabaseMigration.Migration[] diff --git a/packages/core/src/database/migration/20260705180000_rename_instructions.ts b/packages/core/src/database/migration/20260705180000_rename_instructions.ts new file mode 100644 index 00000000000..93cb71330e4 --- /dev/null +++ b/packages/core/src/database/migration/20260705180000_rename_instructions.ts @@ -0,0 +1,17 @@ +import { Effect } from "effect" +import type { DatabaseMigration } from "../migration" + +export default { + id: "20260705180000_rename_instructions", + up(tx) { + return Effect.gen(function* () { + yield* tx.run(`ALTER TABLE \`session_context_entry\` RENAME TO \`instruction_entry\``) + yield* tx.run(`ALTER TABLE \`session_context_epoch\` RENAME TO \`instruction_checkpoint\``) + yield* tx.run(` + UPDATE \`event\` + SET \`type\` = 'session.instructions.updated.1' + WHERE \`type\` = 'session.context.updated.1' + `) + }) + }, +} satisfies DatabaseMigration.Migration diff --git a/packages/core/src/database/schema.gen.ts b/packages/core/src/database/schema.gen.ts index 17a7d12aedd..dfa24f9b944 100644 --- a/packages/core/src/database/schema.gen.ts +++ b/packages/core/src/database/schema.gen.ts @@ -125,6 +125,26 @@ export default { \`commands\` text ); `) + yield* tx.run(` + CREATE TABLE \`instruction_checkpoint\` ( + \`session_id\` text PRIMARY KEY, + \`baseline\` text NOT NULL, + \`snapshot\` text NOT NULL, + \`baseline_seq\` integer NOT NULL, + CONSTRAINT \`fk_instruction_checkpoint_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE + ); + `) + yield* tx.run(` + CREATE TABLE \`instruction_entry\` ( + \`session_id\` text NOT NULL, + \`key\` text NOT NULL, + \`value\` text NOT NULL, + \`time_created\` integer NOT NULL, + \`time_updated\` integer NOT NULL, + CONSTRAINT \`instruction_entry_pk\` PRIMARY KEY(\`session_id\`, \`key\`), + CONSTRAINT \`fk_instruction_entry_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE + ); + `) yield* tx.run(` CREATE TABLE \`message\` ( \`id\` text PRIMARY KEY, @@ -146,26 +166,6 @@ export default { CONSTRAINT \`fk_part_message_id_message_id_fk\` FOREIGN KEY (\`message_id\`) REFERENCES \`message\`(\`id\`) ON DELETE CASCADE ); `) - yield* tx.run(` - CREATE TABLE \`session_context_epoch\` ( - \`session_id\` text PRIMARY KEY, - \`baseline\` text NOT NULL, - \`snapshot\` text NOT NULL, - \`baseline_seq\` integer NOT NULL, - CONSTRAINT \`fk_session_context_epoch_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE - ); - `) - yield* tx.run(` - CREATE TABLE \`session_context_entry\` ( - \`session_id\` text NOT NULL, - \`key\` text NOT NULL, - \`value\` text NOT NULL, - \`time_created\` integer NOT NULL, - \`time_updated\` integer NOT NULL, - CONSTRAINT \`session_context_entry_pk\` PRIMARY KEY(\`session_id\`, \`key\`), - CONSTRAINT \`fk_session_context_entry_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE - ); - `) yield* tx.run(` CREATE TABLE \`session_input\` ( \`id\` text PRIMARY KEY, diff --git a/packages/core/src/instruction-context.ts b/packages/core/src/instruction-discovery.ts similarity index 77% rename from packages/core/src/instruction-context.ts rename to packages/core/src/instruction-discovery.ts index 66d9e14c016..0ac7b8a12d6 100644 --- a/packages/core/src/instruction-context.ts +++ b/packages/core/src/instruction-discovery.ts @@ -1,4 +1,4 @@ -export * as InstructionContext from "./instruction-context" +export * as InstructionDiscovery from "./instruction-discovery" import { Array, Context, Effect, Layer, Schema } from "effect" import { isAbsolute, join, relative, sep } from "path" @@ -7,22 +7,22 @@ import { Flag } from "./flag/flag" import { Global } from "./global" import { Location } from "./location" import { AbsolutePath } from "./schema" -import { SystemContext } from "./system-context/index" +import { Instructions } from "./instructions/index" import { makeLocationNode } from "./effect/app-node" -class File extends Schema.Class("InstructionContext.File")({ +class File extends Schema.Class("InstructionDiscovery.File")({ path: AbsolutePath, content: Schema.String, }) {} const Files = Schema.Array(File) -const key = SystemContext.Key.make("core/instructions") +const key = Instructions.Key.make("core/instructions") export interface Interface { - readonly load: () => Effect.Effect + readonly load: () => Effect.Effect } -export class Service extends Context.Service()("@opencode/v2/InstructionContext") {} +export class Service extends Context.Service()("@opencode/v2/InstructionDiscovery") {} const layer = Layer.effect( Service, @@ -31,8 +31,8 @@ const layer = Layer.effect( const global = yield* Global.Service const location = yield* Location.Service - const source = (value: ReadonlyArray | SystemContext.Unavailable) => - SystemContext.make({ + const source = (value: ReadonlyArray | Instructions.Unavailable) => + Instructions.make({ key, codec: Schema.toCodecJson(Files), load: Effect.succeed(value), @@ -42,7 +42,7 @@ const layer = Layer.effect( removed: () => "Previously loaded instructions no longer apply.", }) - const observe = Effect.fn("InstructionContext.observe")(function* () { + const observe = Effect.fn("InstructionDiscovery.observe")(function* () { const start = yield* fs.resolve(location.directory) const stop = yield* fs.resolve(location.project.directory) const fromProject = relative(stop, start) @@ -74,7 +74,7 @@ const layer = Layer.effect( { concurrency: "unbounded" }, ) if (files.some((file, index) => file === undefined && discovered.has(paths[index]))) - return SystemContext.unavailable + return Instructions.unavailable return files.filter((file): file is File => file !== undefined) }) @@ -82,14 +82,14 @@ const layer = Layer.effect( load: () => observe().pipe( Effect.map((files) => - files === SystemContext.unavailable + files === Instructions.unavailable ? source(files) : files.length === 0 - ? SystemContext.empty + ? Instructions.empty : source(files), ), - Effect.catch(() => Effect.succeed(source(SystemContext.unavailable))), - Effect.catchDefect(() => Effect.succeed(source(SystemContext.unavailable))), + Effect.catch(() => Effect.succeed(source(Instructions.unavailable))), + Effect.catchDefect(() => Effect.succeed(source(Instructions.unavailable))), ), }) }), diff --git a/packages/core/src/system-context/builtins.ts b/packages/core/src/instructions/builtins.ts similarity index 75% rename from packages/core/src/system-context/builtins.ts rename to packages/core/src/instructions/builtins.ts index 1cf470fb4a3..0414cc98c11 100644 --- a/packages/core/src/system-context/builtins.ts +++ b/packages/core/src/instructions/builtins.ts @@ -1,15 +1,15 @@ -export * as SystemContextBuiltIns from "./builtins" +export * as InstructionBuiltIns from "./builtins" import { makeLocationNode } from "../effect/app-node" import { Context, DateTime, Effect, Layer, Schema } from "effect" import { Location } from "../location" -import { SystemContext } from "./index" +import { Instructions } from "./index" export interface Interface { - readonly load: () => Effect.Effect + readonly load: () => Effect.Effect } -export class Service extends Context.Service()("@opencode/v2/SystemContextBuiltIns") {} +export class Service extends Context.Service()("@opencode/v2/InstructionBuiltIns") {} const layer = Layer.effect( Service, @@ -23,17 +23,17 @@ const layer = Layer.effect( ` Platform: ${process.platform}`, "", ].join("\n") - const context = SystemContext.combine([ - SystemContext.make({ - key: SystemContext.Key.make("core/environment"), + const instructions = Instructions.combine([ + Instructions.make({ + key: Instructions.Key.make("core/environment"), codec: Schema.toCodecJson(Schema.String), load: Effect.succeed(environment), baseline: (environment) => ["Here is some useful information about the environment you are running in:", environment].join("\n"), update: (_previous, environment) => ["The environment you are running in is now:", environment].join("\n"), }), - SystemContext.make({ - key: SystemContext.Key.make("core/date"), + Instructions.make({ + key: Instructions.Key.make("core/date"), codec: Schema.toCodecJson(Schema.String), load: DateTime.nowAsDate.pipe(Effect.map((date) => date.toDateString())), baseline: (date) => `Today's date: ${date}`, @@ -41,7 +41,7 @@ const layer = Layer.effect( }), ]) - return Service.of({ load: () => Effect.succeed(context) }) + return Service.of({ load: () => Effect.succeed(instructions) }) }), ) diff --git a/packages/core/src/system-context/index.ts b/packages/core/src/instructions/index.ts similarity index 82% rename from packages/core/src/system-context/index.ts rename to packages/core/src/instructions/index.ts index d86efceb91a..7fe86cfa166 100644 --- a/packages/core/src/system-context/index.ts +++ b/packages/core/src/instructions/index.ts @@ -1,13 +1,13 @@ -export * as SystemContext from "./index" +export * as Instructions from "./index" import { Effect, Option, Schema } from "effect" /** - * Models privileged system context as independently refreshable typed sources. + * Models privileged instructions as independently refreshable typed sources. * * `Source` describes how to observe, compare, and render one value. `make` - * closes over `A`, producing an opaque `SystemContext` that composes uniformly - * with contexts built from other value types. + * closes over `A`, producing opaque `Instructions` that compose uniformly with + * instructions built from other value types. * * The durable `Applied` record tracks what the model was last told, per source: * it is the model's current belief. Interpreters uphold one invariant — @@ -16,21 +16,21 @@ import { Effect, Option, Schema } from "effect" * baseline text. * * Returning `unavailable` means observation failed temporarily. It differs from - * removing a source from the context: the model's prior belief stands. + * removing a source from the instructions: the model's prior belief stands. * `reconcile` retains the applied value silently, and `rebaseline` restates the * belief by rendering the last-applied value instead of a live observation. * * @module */ -/** Stable namespaced identity for one independently refreshable context source. */ +/** Stable namespaced identity for one independently refreshable instruction source. */ export const Key = Schema.String.check(Schema.isPattern(/^[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._/-]*$/)).pipe( - Schema.brand("SystemContext.Key"), + Schema.brand("Instructions.Key"), ) export type Key = typeof Key.Type /** Indicates that a source could not be observed without treating it as removed. */ -export const unavailable = Symbol.for("@opencode/SystemContext.Unavailable") +export const unavailable = Symbol.for("@opencode/Instructions.Unavailable") export type Unavailable = typeof unavailable /** Defines one typed source before its value type is hidden by `make`. */ @@ -43,11 +43,11 @@ export interface Source { readonly removed?: (previous: A) => string } -const ContextTypeId: unique symbol = Symbol.for("@opencode/SystemContext") +const InstructionsTypeId: unique symbol = Symbol.for("@opencode/Instructions") -/** Opaque carrier for composable system context sources. */ -export interface SystemContext { - readonly [ContextTypeId]: ReadonlyArray +/** Opaque carrier for composable instruction sources. */ +export interface Instructions { + readonly [InstructionsTypeId]: ReadonlyArray } /** The value last applied to the model for one admitted source. */ @@ -76,19 +76,19 @@ export interface Updated { export type ReconcileResult = { readonly _tag: "Unchanged" } | Updated export class InitializationBlocked extends Schema.TaggedErrorClass()( - "SystemContext.InitializationBlocked", + "Instructions.InitializationBlocked", { keys: Schema.Array(Key) }, ) { override get message() { - return `System context initialization blocked by unavailable sources: ${this.keys.join(", ")}` + return `Instruction initialization blocked by unavailable sources: ${this.keys.join(", ")}` } } -export class DuplicateKeyError extends Schema.TaggedErrorClass()("SystemContext.DuplicateKeyError", { +export class DuplicateKeyError extends Schema.TaggedErrorClass()("Instructions.DuplicateKeyError", { key: Key, }) { override get message() { - return `Duplicate system context key: ${this.key}` + return `Duplicate instruction key: ${this.key}` } } @@ -112,16 +112,16 @@ interface Entry { readonly observed: Observed | Unavailable } -/** The identity context. */ -export const empty = context([]) +/** The identity instruction set. */ +export const empty = instructions([]) -/** Closes a typed source into a context that composes with differently typed sources. */ -export function make(source: Source): SystemContext { +/** Closes a typed source into instructions that compose with differently typed sources. */ +export function make(source: Source): Instructions { const decode = Schema.decodeUnknownOption(source.codec) const encode = Schema.encodeSync(source.codec) const equivalent = Schema.toEquivalence(source.codec) const baseline = (value: A) => requireText(source.key, "baseline", source.baseline(value)) - return context([ + return instructions([ { key: source.key, recall: (stored) => @@ -179,23 +179,23 @@ export function diffByKey( } } -/** Combines contexts in order and rejects duplicate source keys immediately. */ -export function combine(values: ReadonlyArray): SystemContext { - const sources = values.flatMap((value) => value[ContextTypeId]) +/** Combines instructions in order and rejects duplicate source keys immediately. */ +export function combine(values: ReadonlyArray): Instructions { + const sources = values.flatMap((value) => value[InstructionsTypeId]) assertUniqueKeys(sources) - return context(sources) + return instructions(sources) } -const observe = (value: SystemContext) => +const observe = (value: Instructions) => Effect.forEach( - value[ContextTypeId], + value[InstructionsTypeId], (source) => source.load.pipe(Effect.map((observed): Entry => ({ key: source.key, recall: source.recall, observed }))), { concurrency: "unbounded" }, ) /** Creates the first baseline. Blocks rather than admit a baseline missing an unobservable source. */ -export function initialize(value: SystemContext): Effect.Effect { +export function initialize(value: Instructions): Effect.Effect { return observe(value).pipe( Effect.flatMap((entries) => { const blocked = entries.flatMap((entry) => (entry.observed === unavailable ? [entry.key] : [])) @@ -213,7 +213,7 @@ export function initialize(value: SystemContext): Effect.Effect { +export function reconcile(value: Instructions, previous: Applied): Effect.Effect { return observe(value).pipe( Effect.map((entries): ReconcileResult => { const updates: string[] = [] @@ -253,7 +253,7 @@ export function reconcile(value: SystemContext, previous: Applied): Effect.Effec } /** Rebuilds the baseline, restating unobservable sources from the model's last-applied beliefs. */ -export function rebaseline(value: SystemContext, previous: Applied): Effect.Effect { +export function rebaseline(value: Instructions, previous: Applied): Effect.Effect { return observe(value).pipe( Effect.map((entries): Baseline => { const parts: string[] = [] @@ -277,8 +277,8 @@ export function rebaseline(value: SystemContext, previous: Applied): Effect.Effe ) } -function context(sources: ReadonlyArray): SystemContext { - return { [ContextTypeId]: sources } +function instructions(sources: ReadonlyArray): Instructions { + return { [InstructionsTypeId]: sources } } function render(parts: ReadonlyArray) { @@ -294,7 +294,7 @@ function isUnavailable(value: unknown): value is Unavailable { } function requireText(key: Key, kind: string, text: string) { - if (text.length === 0) throw new Error(`System context source ${key} rendered an empty ${kind}`) + if (text.length === 0) throw new Error(`Instruction source ${key} rendered an empty ${kind}`) return text } diff --git a/packages/core/src/location-services.ts b/packages/core/src/location-services.ts index 21823f583b2..fe2301651f7 100644 --- a/packages/core/src/location-services.ts +++ b/packages/core/src/location-services.ts @@ -44,9 +44,9 @@ import { SessionTodo } from "./session/todo" import { SkillV2 } from "./skill" import { SkillGuidance } from "./skill/guidance" import { Snapshot } from "./snapshot" -import { InstructionContext } from "./instruction-context" -import { SystemContextBuiltIns } from "./system-context/builtins" -import { SessionContextEntry } from "./session/context-entry" +import { InstructionDiscovery } from "./instruction-discovery" +import { InstructionBuiltIns } from "./instructions/builtins" +import { InstructionEntry } from "./session/instruction-entry" import { SessionInstructions } from "./session/instructions" import { McpTool } from "./tool/mcp" import { ReadToolFileSystem } from "./tool/read-filesystem" @@ -112,8 +112,8 @@ const locationServiceNodes = [ Pty.node, Shell.node, SkillV2.node, - SystemContextBuiltIns.node, - InstructionContext.node, + InstructionBuiltIns.node, + InstructionDiscovery.node, LocationMutation.node, FileMutation.node, MCP.node, @@ -125,7 +125,7 @@ const locationServiceNodes = [ SkillGuidance.node, ReferenceGuidance.node, SessionTodo.node, - SessionContextEntry.node, + InstructionEntry.node, Form.node, QuestionV2.node, Generate.node, diff --git a/packages/core/src/mcp/guidance.ts b/packages/core/src/mcp/guidance.ts index 0963a69d234..4f2c13b72c8 100644 --- a/packages/core/src/mcp/guidance.ts +++ b/packages/core/src/mcp/guidance.ts @@ -7,7 +7,7 @@ import { AgentV2 } from "../agent" import { PermissionV2 } from "../permission" import { McpTool } from "../tool/mcp" import { MCP } from "./index" -import { SystemContext } from "../system-context/index" +import { Instructions } from "../instructions/index" const Summary = Schema.Struct({ server: Schema.String, @@ -31,7 +31,7 @@ const render = (servers: ReadonlyArray) => ["", ...entries(servers), ""].join("\n") const update = (previous: ReadonlyArray, current: ReadonlyArray) => { - const diff = SystemContext.diffByKey( + const diff = Instructions.diffByKey( previous, current, (server) => server.server, @@ -56,7 +56,7 @@ const update = (previous: ReadonlyArray, current: ReadonlyArray Effect.Effect + readonly load: (agent: AgentV2.Selection) => Effect.Effect } export class Service extends Context.Service()("@opencode/v2/McpGuidance") {} @@ -69,9 +69,9 @@ export const layer = Layer.effect( return Service.of({ load: Effect.fn("McpGuidance.load")(function* (selection) { const agent = selection.info - if (!agent) return SystemContext.empty + if (!agent) return Instructions.empty if (Flag.CODEMODE_ENABLED && PermissionV2.evaluate("execute", "*", agent.permissions).effect === "deny") - return SystemContext.empty + return Instructions.empty const [instructions, tools] = yield* Effect.all([mcp.instructions(), mcp.tools()], { concurrency: "unbounded", }) @@ -88,9 +88,9 @@ export const layer = Layer.effect( ) }) .map((item) => ({ server: item.server, instructions: item.instructions })) - if (visible.length === 0) return SystemContext.empty - return SystemContext.make({ - key: SystemContext.Key.make("core/mcp-guidance"), + if (visible.length === 0) return Instructions.empty + return Instructions.make({ + key: Instructions.Key.make("core/mcp-guidance"), codec: Schema.toCodecJson(Schema.Array(Summary)), load: Effect.succeed(visible), baseline: render, diff --git a/packages/core/src/reference/guidance.ts b/packages/core/src/reference/guidance.ts index 7fc4fc486cb..1ddc1a3a8b6 100644 --- a/packages/core/src/reference/guidance.ts +++ b/packages/core/src/reference/guidance.ts @@ -3,7 +3,7 @@ export * as ReferenceGuidance from "./guidance" import { makeLocationNode } from "../effect/app-node" import { Context, Effect, Layer, Schema } from "effect" import { Reference } from "../reference" -import { SystemContext } from "../system-context/index" +import { Instructions } from "../instructions/index" const Summary = Schema.Struct({ name: Schema.String, @@ -29,7 +29,7 @@ const render = (references: ReadonlyArray) => ].join("\n") const update = (previous: ReadonlyArray, current: ReadonlyArray) => { - const diff = SystemContext.diffByKey( + const diff = Instructions.diffByKey( previous, current, (reference) => reference.name, @@ -54,7 +54,7 @@ const update = (previous: ReadonlyArray, current: ReadonlyA } export interface Interface { - readonly load: () => Effect.Effect + readonly load: () => Effect.Effect } export class Service extends Context.Service()("@opencode/v2/ReferenceGuidance") {} @@ -74,9 +74,9 @@ const layer = Layer.effect( description: reference.description, })) .toSorted((a, b) => a.name.localeCompare(b.name)) - if (available.length === 0) return SystemContext.empty - return SystemContext.make({ - key: SystemContext.Key.make("core/reference-guidance"), + if (available.length === 0) return Instructions.empty + return Instructions.make({ + key: Instructions.Key.make("core/reference-guidance"), codec: Schema.toCodecJson(Schema.Array(Summary)), load: Effect.succeed(available), baseline: render, diff --git a/packages/core/src/session/history.ts b/packages/core/src/session/history.ts index 9a6a75fe2f3..b3f0b6c741d 100644 --- a/packages/core/src/session/history.ts +++ b/packages/core/src/session/history.ts @@ -4,7 +4,7 @@ import { Database } from "../database/database" import { MessageDecodeError } from "./error" import { SessionMessage } from "./message" import { SessionSchema } from "./schema" -import { SessionContextCheckpointTable, SessionMessageTable } from "./sql" +import { InstructionCheckpointTable, SessionMessageTable } from "./sql" type DatabaseService = Database.Interface["db"] @@ -70,9 +70,9 @@ export const load = Effect.fn("SessionHistory.load")(function* (db: DatabaseServ const [epoch, compaction] = yield* Effect.all( [ db - .select({ baselineSeq: SessionContextCheckpointTable.baseline_seq }) - .from(SessionContextCheckpointTable) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) + .select({ baselineSeq: InstructionCheckpointTable.baseline_seq }) + .from(InstructionCheckpointTable) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) .get() .pipe(Effect.orDie), latestCompaction(db, sessionID), diff --git a/packages/core/src/session/context-checkpoint.ts b/packages/core/src/session/instruction-checkpoint.ts similarity index 61% rename from packages/core/src/session/context-checkpoint.ts rename to packages/core/src/session/instruction-checkpoint.ts index 977514e8cac..47cd006d52e 100644 --- a/packages/core/src/session/context-checkpoint.ts +++ b/packages/core/src/session/instruction-checkpoint.ts @@ -1,37 +1,37 @@ -export * as SessionContextCheckpoint from "./context-checkpoint" +export * as InstructionCheckpoint from "./instruction-checkpoint" import { eq } from "drizzle-orm" import { Effect, Option, Schema } from "effect" import type { Database } from "../database/database" import { EventV2 } from "../event" -import { SystemContext } from "../system-context/index" +import { Instructions } from "../instructions/index" import { SessionEvent } from "./event" import { SessionHistory } from "./history" import { SessionSchema } from "./schema" -import { SessionContextCheckpointTable } from "./sql" +import { InstructionCheckpointTable } from "./sql" type DatabaseService = Database.Interface["db"] -const decodeApplied = Schema.decodeUnknownOption(SystemContext.Applied) +const decodeApplied = Schema.decodeUnknownOption(Instructions.Applied) /** - * Loads or creates the session's durable context checkpoint, narrating any + * Loads or creates the session's durable instruction checkpoint, narrating any * drift since the model was last told as a chronological update. Completed * compaction rebaselines; nothing else rewrites the baseline. Runs before * input promotion so a blocked first step leaves pending inputs untouched. */ -export const prepare = Effect.fn("SessionContextCheckpoint.prepare")(function* ( +export const prepare = Effect.fn("InstructionCheckpoint.prepare")(function* ( db: DatabaseService, events: EventV2.Interface, - context: Effect.Effect, + instructions: Effect.Effect, sessionID: SessionSchema.ID, ) { const [value, stored, compaction] = yield* Effect.all( - [context, find(db, sessionID), SessionHistory.latestCompaction(db, sessionID)], + [instructions, find(db, sessionID), SessionHistory.latestCompaction(db, sessionID)], { concurrency: "unbounded" }, ) if (!stored) { - const baseline = yield* SystemContext.initialize(value) + const baseline = yield* Instructions.initialize(value) const baselineSeq = yield* insert(db, sessionID, baseline) return { baseline: baseline.text, baselineSeq } } @@ -40,28 +40,28 @@ export const prepare = Effect.fn("SessionContextCheckpoint.prepare")(function* ( // treating every source as new, re-announcing baselines as updates. const applied = Option.getOrElse(decodeApplied(stored.snapshot), () => ({})) if (compaction !== undefined && compaction.seq > stored.baseline_seq) { - const baseline = yield* SystemContext.rebaseline(value, applied) + const baseline = yield* Instructions.rebaseline(value, applied) yield* rewrite(db, sessionID, compaction.seq, baseline) return { baseline: baseline.text, baselineSeq: compaction.seq } } - const result = yield* SystemContext.reconcile(value, applied) + const result = yield* Instructions.reconcile(value, applied) if (result._tag === "Unchanged") return { baseline: stored.baseline, baselineSeq: stored.baseline_seq } yield* events.publish( - SessionEvent.ContextUpdated, + SessionEvent.InstructionsUpdated, { sessionID, text: result.text }, { commit: () => advance(db, sessionID, result.applied).pipe(Effect.orDie) }, ) return { baseline: stored.baseline, baselineSeq: stored.baseline_seq } }) -export const reset = Effect.fn("SessionContextCheckpoint.reset")(function* ( +export const reset = Effect.fn("InstructionCheckpoint.reset")(function* ( db: DatabaseService, sessionID: SessionSchema.ID, ) { yield* db - .delete(SessionContextCheckpointTable) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) + .delete(InstructionCheckpointTable) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) .run() .pipe(Effect.orDie) }) @@ -69,8 +69,8 @@ export const reset = Effect.fn("SessionContextCheckpoint.reset")(function* ( const find = Effect.fnUntraced(function* (db: DatabaseService, sessionID: SessionSchema.ID) { return yield* db .select() - .from(SessionContextCheckpointTable) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) + .from(InstructionCheckpointTable) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) .get() .pipe(Effect.orDie) }) @@ -78,11 +78,11 @@ const find = Effect.fnUntraced(function* (db: DatabaseService, sessionID: Sessio const insert = Effect.fnUntraced(function* ( db: DatabaseService, sessionID: SessionSchema.ID, - baseline: SystemContext.Baseline, + baseline: Instructions.Baseline, ) { const baselineSeq = yield* EventV2.latestSequence(db, sessionID) yield* db - .insert(SessionContextCheckpointTable) + .insert(InstructionCheckpointTable) .values({ session_id: sessionID, baseline: baseline.text, @@ -98,33 +98,33 @@ const rewrite = Effect.fnUntraced(function* ( db: DatabaseService, sessionID: SessionSchema.ID, baselineSeq: number, - baseline: SystemContext.Baseline, + baseline: Instructions.Baseline, ) { const updated = yield* db - .update(SessionContextCheckpointTable) + .update(InstructionCheckpointTable) .set({ baseline: baseline.text, snapshot: baseline.applied, baseline_seq: baselineSeq, }) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) - .returning({ sessionID: SessionContextCheckpointTable.session_id }) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) + .returning({ sessionID: InstructionCheckpointTable.session_id }) .get() .pipe(Effect.orDie) - if (!updated) return yield* Effect.die(new Error("Context checkpoint not found")) + if (!updated) return yield* Effect.die(new Error("Instruction checkpoint not found")) }) const advance = Effect.fnUntraced(function* ( db: DatabaseService, sessionID: SessionSchema.ID, - applied: SystemContext.Applied, + applied: Instructions.Applied, ) { const updated = yield* db - .update(SessionContextCheckpointTable) + .update(InstructionCheckpointTable) .set({ snapshot: applied }) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) - .returning({ sessionID: SessionContextCheckpointTable.session_id }) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) + .returning({ sessionID: InstructionCheckpointTable.session_id }) .get() .pipe(Effect.orDie) - if (!updated) return yield* Effect.die(new Error("Context checkpoint not found")) + if (!updated) return yield* Effect.die(new Error("Instruction checkpoint not found")) }) diff --git a/packages/core/src/session/context-entry.ts b/packages/core/src/session/instruction-entry.ts similarity index 65% rename from packages/core/src/session/context-entry.ts rename to packages/core/src/session/instruction-entry.ts index 1f3ffdb0531..a74a174d12d 100644 --- a/packages/core/src/session/context-entry.ts +++ b/packages/core/src/session/instruction-entry.ts @@ -1,17 +1,17 @@ -export * as SessionContextEntry from "./context-entry" +export * as InstructionEntry from "./instruction-entry" import { and, asc, eq } from "drizzle-orm" import { Context, Effect, Layer, Schema } from "effect" -import { SessionContextEntry } from "@opencode-ai/schema/session-context-entry" +import { InstructionEntry } from "@opencode-ai/schema/instruction-entry" import { Database } from "../database/database" import { makeLocationNode } from "../effect/app-node" -import { SystemContext } from "../system-context/index" +import { Instructions } from "../instructions/index" import { SessionSchema } from "./schema" -import { SessionContextEntryTable } from "./sql" +import { InstructionEntryTable } from "./sql" -export const Key = SessionContextEntry.Key +export const Key = InstructionEntry.Key export type Key = typeof Key.Type -export const Info = SessionContextEntry.Info +export const Info = InstructionEntry.Info export type Info = typeof Info.Type export interface Interface { @@ -22,11 +22,11 @@ export interface Interface { readonly value: Schema.Json }) => Effect.Effect readonly remove: (input: { readonly sessionID: SessionSchema.ID; readonly key: Key }) => Effect.Effect - /** Produces one SystemContext source per stored entry, keyed `api/`. */ - readonly load: (sessionID: SessionSchema.ID) => Effect.Effect + /** Produces one Instructions source per stored entry, keyed `api/`. */ + readonly load: (sessionID: SessionSchema.ID) => Effect.Effect } -export class Service extends Context.Service()("@opencode/v2/SessionContextEntry") {} +export class Service extends Context.Service()("@opencode/v2/InstructionEntry") {} const renderValue = (value: Schema.Json) => (typeof value === "string" ? value : JSON.stringify(value, null, 2)) @@ -36,8 +36,8 @@ const renderBlock = (key: Key, value: Schema.Json) => // Rendering stays mechanism-neutral: the model sees session context, not how // it was attached. Only chronological updates and removals carry narration. const source = (entry: Info) => - SystemContext.make({ - key: SystemContext.Key.make(`api/${entry.key}`), + Instructions.make({ + key: Instructions.Key.make(`api/${entry.key}`), codec: Schema.toCodecJson(Schema.Json), load: Effect.succeed(entry.value), baseline: (value) => renderBlock(entry.key, value), @@ -54,49 +54,47 @@ const layer = Layer.effect( Effect.gen(function* () { const { db } = yield* Database.Service - const list = Effect.fn("SessionContextEntry.list")(function* (sessionID: SessionSchema.ID) { + const list = Effect.fn("InstructionEntry.list")(function* (sessionID: SessionSchema.ID) { const rows = yield* db .select() - .from(SessionContextEntryTable) - .where(eq(SessionContextEntryTable.session_id, sessionID)) - .orderBy(asc(SessionContextEntryTable.key)) + .from(InstructionEntryTable) + .where(eq(InstructionEntryTable.session_id, sessionID)) + .orderBy(asc(InstructionEntryTable.key)) .all() .pipe(Effect.orDie) return rows.map((row) => ({ key: row.key, value: row.value })) }) - const put = Effect.fn("SessionContextEntry.put")(function* (input: { + const put = Effect.fn("InstructionEntry.put")(function* (input: { readonly sessionID: SessionSchema.ID readonly key: Key readonly value: Schema.Json }) { yield* db - .insert(SessionContextEntryTable) + .insert(InstructionEntryTable) .values({ session_id: input.sessionID, key: input.key, value: input.value }) .onConflictDoUpdate({ - target: [SessionContextEntryTable.session_id, SessionContextEntryTable.key], + target: [InstructionEntryTable.session_id, InstructionEntryTable.key], set: { value: input.value, time_updated: Date.now() }, }) .run() .pipe(Effect.orDie) }) - const remove = Effect.fn("SessionContextEntry.remove")(function* (input: { + const remove = Effect.fn("InstructionEntry.remove")(function* (input: { readonly sessionID: SessionSchema.ID readonly key: Key }) { yield* db - .delete(SessionContextEntryTable) - .where( - and(eq(SessionContextEntryTable.session_id, input.sessionID), eq(SessionContextEntryTable.key, input.key)), - ) + .delete(InstructionEntryTable) + .where(and(eq(InstructionEntryTable.session_id, input.sessionID), eq(InstructionEntryTable.key, input.key))) .run() .pipe(Effect.orDie) }) - const load = Effect.fn("SessionContextEntry.load")(function* (sessionID: SessionSchema.ID) { + const load = Effect.fn("InstructionEntry.load")(function* (sessionID: SessionSchema.ID) { const entries = yield* list(sessionID) - return SystemContext.combine(entries.map(source)) + return Instructions.combine(entries.map(source)) }) return Service.of({ list, put, remove, load }) diff --git a/packages/core/src/session/message-updater.ts b/packages/core/src/session/message-updater.ts index 2a8ade7b1a8..4bf4e438258 100644 --- a/packages/core/src/session/message-updater.ts +++ b/packages/core/src/session/message-updater.ts @@ -145,7 +145,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) { "session.prompt.promoted": () => Effect.void, "session.prompt.admitted": () => Effect.void, "session.execution.settled": () => Effect.void, - "session.context.updated": (event) => + "session.instructions.updated": (event) => adapter.appendMessage( SessionMessage.System.make({ id: SessionMessage.ID.fromEvent(event.id), @@ -154,6 +154,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) { time: { created: event.created }, }), ), + "session.instructions.discovered": () => Effect.void, "session.synthetic": (event) => { return adapter.appendMessage( SessionMessage.Synthetic.make({ diff --git a/packages/core/src/session/projector.ts b/packages/core/src/session/projector.ts index 3cbd40c2967..bbe9ce53b14 100644 --- a/packages/core/src/session/projector.ts +++ b/packages/core/src/session/projector.ts @@ -13,11 +13,11 @@ import { SessionMessage } from "./message" import { SessionMessageUpdater } from "./message-updater" import { SessionInput } from "./input" import { WorkspaceV2 } from "../workspace" -import { SessionContextCheckpoint } from "./context-checkpoint" +import { InstructionCheckpoint } from "./instruction-checkpoint" import { MessageTable, PartTable, - SessionContextCheckpointTable, + InstructionCheckpointTable, SessionInputTable, SessionMessageTable, SessionTable, @@ -220,13 +220,13 @@ const projectFork = Effect.fn("SessionProjector.projectFork")(function* ( // folding at the same baseline horizon. const checkpoint = yield* db .select() - .from(SessionContextCheckpointTable) - .where(eq(SessionContextCheckpointTable.session_id, event.data.parentID)) + .from(InstructionCheckpointTable) + .where(eq(InstructionCheckpointTable.session_id, event.data.parentID)) .get() .pipe(Effect.orDie) if (checkpoint) { yield* db - .insert(SessionContextCheckpointTable) + .insert(InstructionCheckpointTable) .values({ ...checkpoint, session_id: event.data.sessionID }) .run() .pipe(Effect.orDie) @@ -497,7 +497,7 @@ const layer = Layer.effectDiscard( .where(eq(SessionTable.id, event.data.sessionID)) .run() .pipe(Effect.orDie) - yield* SessionContextCheckpoint.reset(db, event.data.sessionID) + yield* InstructionCheckpoint.reset(db, event.data.sessionID) }), ) yield* events.project(SessionV1.Event.Deleted, (event) => @@ -634,7 +634,7 @@ const layer = Layer.effectDiscard( }) }), ) - yield* events.project(SessionEvent.ContextUpdated, (event) => run(db, event)) + yield* events.project(SessionEvent.InstructionsUpdated, (event) => run(db, event)) yield* events.project(SessionEvent.Synthetic, (event) => run(db, event)) yield* events.project(SessionEvent.Skill.Activated, (event) => insertMessage(db, event, { @@ -718,7 +718,7 @@ const layer = Layer.effectDiscard( .where(eq(SessionTable.id, event.data.sessionID)) .run() .pipe(Effect.orDie) - yield* SessionContextCheckpoint.reset(db, event.data.sessionID) + yield* InstructionCheckpoint.reset(db, event.data.sessionID) }), ) }), diff --git a/packages/core/src/session/runner/index.ts b/packages/core/src/session/runner/index.ts index 7c2a6f463da..3decb42f052 100644 --- a/packages/core/src/session/runner/index.ts +++ b/packages/core/src/session/runner/index.ts @@ -5,11 +5,11 @@ import { Context, Effect } from "effect" import { SessionSchema } from "../schema" import type { MessageDecodeError } from "../error" import { SessionRunnerModel } from "./model" -import type { SystemContext } from "../../system-context/index" +import type { Instructions } from "../../instructions/index" import type { ToolOutputStore } from "../../tool-output-store" export type RunError = - LLMError | SessionRunnerModel.Error | MessageDecodeError | SystemContext.InitializationBlocked | ToolOutputStore.Error + LLMError | SessionRunnerModel.Error | MessageDecodeError | Instructions.InitializationBlocked | ToolOutputStore.Error /** Runs one local continuation from already-recorded Session history. */ export interface Interface { diff --git a/packages/core/src/session/runner/llm.ts b/packages/core/src/session/runner/llm.ts index d4b2c5250ca..40d43a7bfdc 100644 --- a/packages/core/src/session/runner/llm.ts +++ b/packages/core/src/session/runner/llm.ts @@ -10,23 +10,23 @@ import { isContextOverflowFailure, type ProviderErrorEvent, } from "@opencode-ai/llm" -import { Cause, DateTime, Effect, Exit, FiberSet, Layer, Option, Semaphore, Stream } from "effect" +import { Cause, Effect, Exit, FiberSet, Layer, Option, Semaphore, Stream } from "effect" import { AgentV2 } from "../../agent" import { Config } from "../../config" import { Database } from "../../database/database" import { EventV2 } from "../../event" import { Location } from "../../location" -import { SystemContext } from "../../system-context/index" -import { SystemContextBuiltIns } from "../../system-context/builtins" -import { InstructionContext } from "../../instruction-context" +import { Instructions } from "../../instructions/index" +import { InstructionBuiltIns } from "../../instructions/builtins" +import { InstructionDiscovery } from "../../instruction-discovery" import { SkillGuidance } from "../../skill/guidance" import { ReferenceGuidance } from "../../reference/guidance" import { McpGuidance } from "../../mcp/guidance" -import { SessionContextEntry } from "../context-entry" +import { InstructionEntry } from "../instruction-entry" import { QuestionTool } from "../../tool/question" import { ToolRegistry } from "../../tool/registry" import { ToolOutputStore } from "../../tool-output-store" -import { SessionContextCheckpoint } from "../context-checkpoint" +import { InstructionCheckpoint } from "../instruction-checkpoint" import { SessionCompaction } from "../compaction" import { SessionEvent } from "../event" import { SessionHistory } from "../history" @@ -104,12 +104,12 @@ const layer = Layer.effect( const models = yield* SessionRunnerModel.Service const store = yield* SessionStore.Service const location = yield* Location.Service - const builtins = yield* SystemContextBuiltIns.Service - const instructions = yield* InstructionContext.Service + const builtins = yield* InstructionBuiltIns.Service + const discovery = yield* InstructionDiscovery.Service const skillGuidance = yield* SkillGuidance.Service const referenceGuidance = yield* ReferenceGuidance.Service const mcpGuidance = yield* McpGuidance.Service - const contextEntries = yield* SessionContextEntry.Service + const entries = yield* InstructionEntry.Service const snapshots = yield* Snapshot.Service const db = (yield* Database.Service).db const compaction = yield* SessionCompaction.Service @@ -152,18 +152,18 @@ const layer = Layer.effect( const isQuestionCancelled = (cause: Cause.Cause) => cause.reasons.some((reason) => Cause.isDieReason(reason) && reason.defect instanceof QuestionTool.CancelledError) - const loadSystemContext = (agent: AgentV2.Selection, sessionID: SessionSchema.ID) => + const loadInstructions = (agent: AgentV2.Selection, sessionID: SessionSchema.ID) => Effect.all( [ builtins.load(), - instructions.load(), + discovery.load(), skillGuidance.load(agent), referenceGuidance.load(), mcpGuidance.load(agent), - contextEntries.load(sessionID), + entries.load(sessionID), ], { concurrency: "unbounded" }, - ).pipe(Effect.map(SystemContext.combine)) + ).pipe(Effect.map(Instructions.combine)) const attemptStep = Effect.fn("SessionRunner.attemptStep")(function* ( sessionID: SessionSchema.ID, @@ -177,10 +177,10 @@ const layer = Layer.effect( const agent = yield* agents.select(session.agent) // Establish what the model knows before admitting what the user said, so // a blocked first step leaves pending inputs untouched. - const checkpoint = yield* SessionContextCheckpoint.prepare( + const checkpoint = yield* InstructionCheckpoint.prepare( db, events, - loadSystemContext(agent, session.id), + loadInstructions(agent, session.id), session.id, ) const toolFibers = yield* FiberSet.make() @@ -458,12 +458,12 @@ export const node = makeLocationNode({ SessionRunnerModel.node, SessionStore.node, Location.node, - SystemContextBuiltIns.node, - InstructionContext.node, + InstructionBuiltIns.node, + InstructionDiscovery.node, SkillGuidance.node, ReferenceGuidance.node, McpGuidance.node, - SessionContextEntry.node, + InstructionEntry.node, SessionCompaction.node, SessionTitle.node, Config.node, diff --git a/packages/core/src/session/sql.ts b/packages/core/src/session/sql.ts index 739d3f18880..ceef6fe040b 100644 --- a/packages/core/src/session/sql.ts +++ b/packages/core/src/session/sql.ts @@ -11,8 +11,7 @@ import type { SessionSchema } from "./schema" import type { MessageID, PartID, SessionV1 } from "../v1/session" import { WorkspaceV2 } from "../workspace" import { Timestamps } from "../database/schema.sql" -import type { SystemContext } from "../system-context/index" -import { AgentV2 } from "../agent" +import type { Instructions } from "../instructions/index" import type { Revert } from "@opencode-ai/schema/revert" import type { Schema } from "effect" @@ -166,8 +165,8 @@ export const SessionInputTable = sqliteTable( ], ) -export const SessionContextEntryTable = sqliteTable( - "session_context_entry", +export const InstructionEntryTable = sqliteTable( + "instruction_entry", { session_id: text() .$type() @@ -180,12 +179,12 @@ export const SessionContextEntryTable = sqliteTable( (table) => [primaryKey({ columns: [table.session_id, table.key] })], ) -export const SessionContextCheckpointTable = sqliteTable("session_context_epoch", { +export const InstructionCheckpointTable = sqliteTable("instruction_checkpoint", { session_id: text() .$type() .primaryKey() .references(() => SessionTable.id, { onDelete: "cascade" }), baseline: text().notNull(), - snapshot: text({ mode: "json" }).notNull().$type(), + snapshot: text({ mode: "json" }).notNull().$type(), baseline_seq: integer().notNull(), }) diff --git a/packages/core/src/skill/guidance.ts b/packages/core/src/skill/guidance.ts index a95a1ab0b88..95ebe87eedb 100644 --- a/packages/core/src/skill/guidance.ts +++ b/packages/core/src/skill/guidance.ts @@ -5,7 +5,7 @@ import { Context, Effect, Layer, Schema } from "effect" import { AgentV2 } from "../agent" import { PermissionV2 } from "../permission" import { SkillV2 } from "../skill" -import { SystemContext } from "../system-context/index" +import { Instructions } from "../instructions/index" const Summary = Schema.Struct({ name: Schema.String, @@ -31,7 +31,7 @@ const render = (skills: ReadonlyArray) => ].join("\n") const update = (previous: ReadonlyArray, current: ReadonlyArray) => { - const diff = SystemContext.diffByKey( + const diff = Instructions.diffByKey( previous, current, (skill) => skill.name, @@ -56,7 +56,7 @@ const update = (previous: ReadonlyArray, current: ReadonlyArray Effect.Effect + readonly load: (agent: AgentV2.Selection) => Effect.Effect } export class Service extends Context.Service()("@opencode/v2/SkillGuidance") {} @@ -69,10 +69,10 @@ const layer = Layer.effect( return Service.of({ load: Effect.fn("SkillGuidance.load")(function* (selection) { const agent = selection.info - if (!agent) return SystemContext.empty + if (!agent) return Instructions.empty const permitted = SkillV2.available(yield* skills.list(), agent) if (permitted.length === 0 && PermissionV2.evaluate("skill", "*", agent.permissions).effect === "deny") - return SystemContext.empty + return Instructions.empty const available = permitted .flatMap((skill) => skill.description === undefined || skill.autoinvoke === false @@ -80,8 +80,8 @@ const layer = Layer.effect( : [{ name: skill.name, description: skill.description }], ) .toSorted((a, b) => a.name.localeCompare(b.name)) - return SystemContext.make({ - key: SystemContext.Key.make("core/skill-guidance"), + return Instructions.make({ + key: Instructions.Key.make("core/skill-guidance"), codec: Schema.toCodecJson(Schema.Array(Summary)), load: Effect.succeed(available), baseline: render, diff --git a/packages/core/src/tool/skill.ts b/packages/core/src/tool/skill.ts index d3a2407f32d..95c68cb2571 100644 --- a/packages/core/src/tool/skill.ts +++ b/packages/core/src/tool/skill.ts @@ -23,11 +23,11 @@ export const Output = Schema.Struct({ }) export const description = [ - "Load a specialized skill when the task at hand matches one of the available skills in the system context.", + "Load a specialized skill when the task at hand matches one of the available skills in the instructions.", "", "Use this tool to inject the skill's instructions and resources into the current conversation. The output may contain detailed workflow guidance as well as references to scripts, files, etc. in the same directory as the skill.", "", - "The skill name must match one of the available skills in the system context.", + "The skill name must match one of the available skills in the instructions.", ].join("\n") export const toModelOutput = (skill: SkillV2.Info, files: ReadonlyArray) => { diff --git a/packages/core/test/database-migration.test.ts b/packages/core/test/database-migration.test.ts index b36de1abacb..eda14d14b10 100644 --- a/packages/core/test/database-migration.test.ts +++ b/packages/core/test/database-migration.test.ts @@ -15,6 +15,7 @@ import eventSourcedSessionInputMigration from "@opencode-ai/core/database/migrat import contextEpochAgentMigration from "@opencode-ai/core/database/migration/20260605042240_add_context_epoch_agent" import simplifyIntegrationCredentialsMigration from "@opencode-ai/core/database/migration/20260611192811_lush_chimera" import simplifySessionInputMigration from "@opencode-ai/core/database/migration/20260622202450_simplify_session_input" +import renameInstructionsMigration from "@opencode-ai/core/database/migration/20260705180000_rename_instructions" import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { EventV2 } from "@opencode-ai/core/event" @@ -73,11 +74,11 @@ describe("DatabaseMigration", () => { yield* db.get(sql`SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'session_input'`), ).toEqual({ name: "session_input" }) expect( - yield* db.get(sql`SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'session_context_epoch'`), - ).toEqual({ name: "session_context_epoch" }) + yield* db.get(sql`SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'instruction_checkpoint'`), + ).toEqual({ name: "instruction_checkpoint" }) expect( yield* db.get( - sql`SELECT name FROM pragma_table_info('session_context_epoch') WHERE name IN ('agent', 'replacement_seq', 'revision')`, + sql`SELECT name FROM pragma_table_info('instruction_checkpoint') WHERE name IN ('agent', 'replacement_seq', 'revision')`, ), ).toBeUndefined() expect(yield* db.get(sql`SELECT count(*) as count FROM migration`)).toEqual({ count: migrations.length }) @@ -131,6 +132,42 @@ describe("DatabaseMigration", () => { ) }) + test("renames instruction state without losing rows or durable updates", async () => { + await run( + Effect.gen(function* () { + const db = yield* makeDb + yield* db.run(sql`CREATE TABLE session (id text PRIMARY KEY)`) + yield* db.run( + sql`CREATE TABLE session_context_entry (session_id text NOT NULL, key text NOT NULL, value text NOT NULL, time_created integer NOT NULL, time_updated integer NOT NULL, PRIMARY KEY(session_id, key))`, + ) + yield* db.run( + sql`CREATE TABLE session_context_epoch (session_id text PRIMARY KEY, baseline text NOT NULL, snapshot text NOT NULL, baseline_seq integer NOT NULL)`, + ) + yield* db.run(sql`CREATE TABLE event (type text NOT NULL)`) + yield* db.run(sql`INSERT INTO session_context_entry VALUES ('ses_test', 'plan', '"ready"', 1, 2)`) + yield* db.run(sql`INSERT INTO session_context_epoch VALUES ('ses_test', 'baseline', '{}', 7)`) + yield* db.run(sql`INSERT INTO event VALUES ('session.context.updated.1')`) + + yield* DatabaseMigration.applyOnly(db, [renameInstructionsMigration]) + + expect(yield* db.get(sql`SELECT * FROM instruction_entry`)).toEqual({ + session_id: "ses_test", + key: "plan", + value: '"ready"', + time_created: 1, + time_updated: 2, + }) + expect(yield* db.get(sql`SELECT * FROM instruction_checkpoint`)).toEqual({ + session_id: "ses_test", + baseline: "baseline", + snapshot: "{}", + baseline_seq: 7, + }) + expect(yield* db.get(sql`SELECT type FROM event`)).toEqual({ type: "session.instructions.updated.1" }) + }), + ) + }) + test("keeps legacy credential fields nullable", async () => { await run( Effect.gen(function* () { @@ -264,10 +301,12 @@ describe("DatabaseMigration", () => { sql`INSERT INTO session_message (id, session_id, type, seq, time_created, time_updated, data) VALUES ('projected', 'session', 'user', 9, 1, 1, '{}')`, ) yield* db.run( - sql`INSERT INTO session_context_epoch (session_id, baseline, snapshot, baseline_seq) VALUES ('session', 'baseline', '{}', 9)`, + sql`INSERT INTO instruction_checkpoint (session_id, baseline, snapshot, baseline_seq) VALUES ('session', 'baseline', '{}', 9)`, ) + yield* db.run(sql`ALTER TABLE instruction_checkpoint RENAME TO session_context_epoch`) yield* db.run(sql`DELETE FROM migration WHERE id = ${simplifySessionInputMigration.id}`) yield* DatabaseMigration.applyOnly(db, [simplifySessionInputMigration]) + yield* db.run(sql`ALTER TABLE session_context_epoch RENAME TO instruction_checkpoint`) const database = Layer.succeed(Database.Service, { db }) yield* EventV2.Service.use((service) => @@ -299,7 +338,7 @@ describe("DatabaseMigration", () => { (SELECT COUNT(*) FROM workspace) AS workspaces, (SELECT COUNT(*) FROM session_input) AS sessionInputs, (SELECT COUNT(*) FROM session_message) AS sessionMessages, - (SELECT COUNT(*) FROM session_context_epoch) AS contextEpochs, + (SELECT COUNT(*) FROM instruction_checkpoint) AS instructionCheckpoints, (SELECT seq FROM event_sequence WHERE aggregate_id = 'session') AS seq, (SELECT type FROM event WHERE aggregate_id = 'session') AS eventType `), @@ -311,7 +350,7 @@ describe("DatabaseMigration", () => { workspaces: 0, sessionInputs: 0, sessionMessages: 0, - contextEpochs: 0, + instructionCheckpoints: 0, seq: 0, eventType: "session.updated.1", }) diff --git a/packages/core/test/event.test.ts b/packages/core/test/event.test.ts index 4bff6a7abfb..f531ea7990e 100644 --- a/packages/core/test/event.test.ts +++ b/packages/core/test/event.test.ts @@ -712,8 +712,8 @@ describe("EventV2", () => { Effect.gen(function* () { const events = yield* EventV2.Service const aggregateID = Session.ID.create() - const received = new Array() - yield* events.project(SessionEvent.ContextUpdated, (event) => + const received = new Array() + yield* events.project(SessionEvent.InstructionsUpdated, (event) => Effect.sync(() => { received.push(event) }), @@ -722,7 +722,7 @@ describe("EventV2", () => { yield* events.replay({ id: EventV2.ID.create(), created: DateTime.makeUnsafe(0), - type: EventV2.versionedType(SessionEvent.ContextUpdated.type, 1), + type: EventV2.versionedType(SessionEvent.InstructionsUpdated.type, 1), seq: 0, aggregateID, data: { sessionID: aggregateID, text: "context" }, diff --git a/packages/core/test/instruction-context.test.ts b/packages/core/test/instruction-discovery.test.ts similarity index 89% rename from packages/core/test/instruction-context.test.ts rename to packages/core/test/instruction-discovery.test.ts index 8bd04d305ae..2477d051246 100644 --- a/packages/core/test/instruction-context.test.ts +++ b/packages/core/test/instruction-discovery.test.ts @@ -6,10 +6,10 @@ import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { FSUtil } from "@opencode-ai/core/fs-util" import { Global } from "@opencode-ai/core/global" -import { InstructionContext } from "@opencode-ai/core/instruction-context" +import { InstructionDiscovery } from "@opencode-ai/core/instruction-discovery" import { Location } from "@opencode-ai/core/location" import { AbsolutePath } from "@opencode-ai/core/schema" -import { SystemContext } from "@opencode-ai/core/system-context" +import { Instructions } from "@opencode-ai/core/instructions" import { location } from "./fixture/location" import { tmpdir } from "./fixture/tmpdir" import { testEffect } from "./lib/effect" @@ -21,13 +21,13 @@ const instructionLayer = (input: { locationServiceLayer: Layer.Layer filesystemLayer?: Layer.Layer }) => - AppNodeBuilder.build(InstructionContext.node, [ + AppNodeBuilder.build(InstructionDiscovery.node, [ [Global.node, Global.layerWith({ config: input.config })], [Location.node, input.locationServiceLayer], ...(input.filesystemLayer ? [[FSUtil.node, input.filesystemLayer] as const] : []), ]) -describe("InstructionContext", () => { +describe("InstructionDiscovery", () => { it.live("loads global and upward project AGENTS.md files as one aggregate context", () => Effect.acquireRelease( Effect.promise(() => tmpdir()), @@ -51,7 +51,7 @@ describe("InstructionContext", () => { await fs.writeFile(packageFile, "package") }) - const load = InstructionContext.Service.pipe( + const load = InstructionDiscovery.Service.pipe( Effect.flatMap((service) => service.load()), Effect.provide( instructionLayer({ @@ -69,7 +69,7 @@ describe("InstructionContext", () => { ), ) - const initialized = yield* SystemContext.initialize(yield* load) + const initialized = yield* Instructions.initialize(yield* load) expect(initialized.text).toBe( [ `Instructions from: ${globalFile}\nglobal`, @@ -80,13 +80,13 @@ describe("InstructionContext", () => { expect(initialized.text).not.toContain("outside") yield* Effect.promise(() => fs.writeFile(packageFile, "changed")) - expect(yield* SystemContext.reconcile(yield* load, initialized.applied)).toMatchObject({ + expect(yield* Instructions.reconcile(yield* load, initialized.applied)).toMatchObject({ _tag: "Updated", text: expect.stringContaining(`Instructions from: ${packageFile}\nchanged`), }) yield* Effect.promise(() => fs.rm(packageFile)) - const partial = yield* SystemContext.reconcile(yield* load, initialized.applied) + const partial = yield* Instructions.reconcile(yield* load, initialized.applied) expect(partial).toEqual({ _tag: "Updated", text: [ @@ -98,7 +98,7 @@ describe("InstructionContext", () => { }) yield* Effect.promise(() => Promise.all([fs.rm(globalFile), fs.rm(projectFile)])) - expect(yield* SystemContext.reconcile(yield* load, initialized.applied)).toEqual({ + expect(yield* Instructions.reconcile(yield* load, initialized.applied)).toEqual({ _tag: "Updated", text: "Previously loaded instructions no longer apply.", applied: {}, @@ -117,7 +117,7 @@ describe("InstructionContext", () => { Effect.gen(function* () { const file = path.join(tmp.path, "AGENTS.md") yield* Effect.promise(() => fs.writeFile(file, "")) - const context = yield* InstructionContext.Service.pipe( + const context = yield* InstructionDiscovery.Service.pipe( Effect.flatMap((service) => service.load()), Effect.provide( instructionLayer({ @@ -130,7 +130,7 @@ describe("InstructionContext", () => { ), ) - expect((yield* SystemContext.initialize(context)).text).toBe(`Instructions from: ${file}\n`) + expect((yield* Instructions.initialize(context)).text).toBe(`Instructions from: ${file}\n`) }), ), ), @@ -146,7 +146,7 @@ describe("InstructionContext", () => { ), ), ).pipe(Layer.provide(LayerNode.compile(FSUtil.node))) - const context = yield* InstructionContext.Service.pipe( + const context = yield* InstructionDiscovery.Service.pipe( Effect.flatMap((service) => service.load()), Effect.provide( instructionLayer({ @@ -161,7 +161,7 @@ describe("InstructionContext", () => { ) expect( - yield* SystemContext.reconcile(context, { + yield* Instructions.reconcile(context, { "core/instructions": { value: [{ path: "/repo/AGENTS.md", content: "old" }], removed: "Previously loaded instructions no longer apply.", @@ -186,7 +186,7 @@ describe("InstructionContext", () => { ), ), ).pipe(Layer.provide(LayerNode.compile(FSUtil.node))) - const context = yield* InstructionContext.Service.pipe( + const context = yield* InstructionDiscovery.Service.pipe( Effect.flatMap((service) => service.load()), Effect.provide( instructionLayer({ @@ -201,7 +201,7 @@ describe("InstructionContext", () => { ) expect( - yield* SystemContext.reconcile(context, { + yield* Instructions.reconcile(context, { "core/instructions": { value: [{ path: file, content: "old" }], removed: "Previously loaded instructions no longer apply.", @@ -230,7 +230,7 @@ describe("InstructionContext", () => { ), ).pipe(Layer.provide(LayerNode.compile(FSUtil.node))) - yield* InstructionContext.Service.pipe( + yield* InstructionDiscovery.Service.pipe( Effect.flatMap((service) => service.load()), Effect.provide( instructionLayer({ @@ -260,7 +260,7 @@ describe("InstructionContext", () => { let scanned = false process.env.OPENCODE_DISABLE_PROJECT_CONFIG = "1" - yield* InstructionContext.Service.pipe( + yield* InstructionDiscovery.Service.pipe( Effect.flatMap((service) => service.load()), Effect.provide( instructionLayer({ @@ -292,7 +292,7 @@ describe("InstructionContext", () => { it.effect("does not discover project instructions outside the canonical project root", () => Effect.gen(function* () { let scanned = false - yield* InstructionContext.Service.pipe( + yield* InstructionDiscovery.Service.pipe( Effect.flatMap((service) => service.load()), Effect.provide( instructionLayer({ diff --git a/packages/core/test/instructions/builtins.test.ts b/packages/core/test/instructions/builtins.test.ts new file mode 100644 index 00000000000..f66ebb1b81b --- /dev/null +++ b/packages/core/test/instructions/builtins.test.ts @@ -0,0 +1,83 @@ +import { describe, expect } from "bun:test" +import { Effect, Layer } from "effect" +import * as TestClock from "effect/testing/TestClock" +import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" +import { Location } from "@opencode-ai/core/location" +import { FSUtil } from "@opencode-ai/core/fs-util" +import { Global } from "@opencode-ai/core/global" +import { AbsolutePath } from "@opencode-ai/core/schema" +import { Instructions } from "@opencode-ai/core/instructions" +import { InstructionBuiltIns } from "@opencode-ai/core/instructions/builtins" +import { location } from "../fixture/location" +import { testEffect } from "../lib/effect" + +const directory = AbsolutePath.make(FSUtil.resolve("/repo/packages/core")) +const projectDirectory = AbsolutePath.make(FSUtil.resolve("/repo")) +const timestamp = Date.parse("2026-06-03T12:00:00.000Z") +const localDate = (time: number) => new Date(time).toDateString() +const locationLayer = Layer.succeed( + Location.Service, + Location.Service.of( + location( + { directory }, + { projectDirectory, vcs: { type: "git", store: AbsolutePath.make(FSUtil.resolve("/repo/.git")) } }, + ), + ), +) +const it = testEffect( + AppNodeBuilder.build(InstructionBuiltIns.node, [ + [Location.node, locationLayer], + [Global.node, Global.layerWith({ config: "/global" })], + ]), +) + +describe("InstructionBuiltIns", () => { + it.effect("loads location-scoped environment and host-local date instructions", () => + Effect.gen(function* () { + yield* TestClock.setTime(timestamp) + const context = yield* InstructionBuiltIns.Service + const initialized = yield* Instructions.initialize(yield* context.load()) + + expect(initialized.text).toBe( + [ + "Here is some useful information about the environment you are running in:", + "", + ` Working directory: ${directory}`, + ` Workspace root folder: ${projectDirectory}`, + " Is directory a git repo: yes", + ` Platform: ${process.platform}`, + "", + "", + `Today's date: ${localDate(timestamp)}`, + ].join("\n"), + ) + }), + ) + + it.effect("reconciles the date without repeating unchanged environment instructions", () => + Effect.gen(function* () { + yield* TestClock.setTime(timestamp) + const context = yield* InstructionBuiltIns.Service + const initialized = yield* Instructions.initialize(yield* context.load()) + + yield* TestClock.setTime(timestamp + 24 * 60 * 60 * 1000) + const refreshed = yield* Instructions.reconcile(yield* context.load(), initialized.applied) + + expect(refreshed).toMatchObject({ + _tag: "Updated", + text: `Today's date is now: ${localDate(timestamp + 24 * 60 * 60 * 1000)}`, + }) + }), + ) + + it.effect("does not update again within the same local calendar day", () => + Effect.gen(function* () { + yield* TestClock.setTime(timestamp) + const context = yield* InstructionBuiltIns.Service + const initialized = yield* Instructions.initialize(yield* context.load()) + + yield* TestClock.setTime(timestamp + 60 * 60 * 1000) + expect(yield* Instructions.reconcile(yield* context.load(), initialized.applied)).toEqual({ _tag: "Unchanged" }) + }), + ) +}) diff --git a/packages/core/test/system-context/index.test.ts b/packages/core/test/instructions/index.test.ts similarity index 80% rename from packages/core/test/system-context/index.test.ts rename to packages/core/test/instructions/index.test.ts index f62053b0884..2d0a3b801a0 100644 --- a/packages/core/test/system-context/index.test.ts +++ b/packages/core/test/instructions/index.test.ts @@ -1,17 +1,17 @@ import { describe, expect } from "bun:test" import { Cause, Effect, Exit, Schema } from "effect" -import { SystemContext } from "@opencode-ai/core/system-context" +import { Instructions } from "@opencode-ai/core/instructions" import { it } from "../lib/effect" -const key = SystemContext.Key.make +const key = Instructions.Key.make const stringContext = (input: { key: string - value: string | SystemContext.Unavailable + value: string | Instructions.Unavailable baseline?: (value: string) => string update?: (previous: string, current: string) => string removed?: (value: string) => string }) => - SystemContext.make({ + Instructions.make({ key: key(input.key), codec: Schema.toCodecJson(Schema.String), load: Effect.succeed(input.value), @@ -20,10 +20,10 @@ const stringContext = (input: { removed: input.removed, }) -describe("SystemContext", () => { +describe("Instructions", () => { it.effect("stores the canonical JSON encoding of the loaded value", () => Effect.gen(function* () { - const context = SystemContext.make({ + const context = Instructions.make({ key: key("core/date"), codec: Schema.toCodecJson(Schema.DateFromString), load: Effect.succeed(new Date("2026-06-03T12:00:00.000Z")), @@ -32,15 +32,15 @@ describe("SystemContext", () => { removed: () => "Date removed", }) - expect((yield* SystemContext.initialize(context)).applied["core/date"].value).toBe("2026-06-03T12:00:00.000Z") + expect((yield* Instructions.initialize(context)).applied["core/date"].value).toBe("2026-06-03T12:00:00.000Z") }), ) it.effect("loads once and initializes a baseline with the applied values", () => Effect.gen(function* () { let loads = 0 - const context = SystemContext.combine([ - SystemContext.make({ + const context = Instructions.combine([ + Instructions.make({ key: key("core/date"), codec: Schema.toCodecJson(Schema.String), load: Effect.sync(() => { @@ -54,7 +54,7 @@ describe("SystemContext", () => { stringContext({ key: "core/location", value: "/repo", baseline: (value) => `Directory: ${value}` }), ]) - expect(yield* SystemContext.initialize(context)).toEqual({ + expect(yield* Instructions.initialize(context)).toEqual({ text: "Today's date is 2026-06-03.\n\nDirectory: /repo", applied: { "core/date": { value: "2026-06-03", removed: "The date was removed." }, @@ -71,7 +71,7 @@ describe("SystemContext", () => { "core/date": { value: "2026-06-03", removed: "The date was removed." }, "core/location": { value: "/repo", removed: "Removed: /repo" }, } - const changed = SystemContext.combine([ + const changed = Instructions.combine([ stringContext({ key: "core/date", value: "2026-06-04", @@ -81,7 +81,7 @@ describe("SystemContext", () => { stringContext({ key: "core/location", value: "/repo" }), ]) - expect(yield* SystemContext.reconcile(changed, previous)).toEqual({ + expect(yield* Instructions.reconcile(changed, previous)).toEqual({ _tag: "Updated", text: "The date changed from 2026-06-03 to 2026-06-04.", applied: { @@ -91,8 +91,8 @@ describe("SystemContext", () => { }) expect( - yield* SystemContext.reconcile( - SystemContext.combine([ + yield* Instructions.reconcile( + Instructions.combine([ stringContext({ key: "core/date", value: "2026-06-03", removed: () => "The date was removed." }), stringContext({ key: "core/location", value: "/repo" }), ]), @@ -110,7 +110,7 @@ describe("SystemContext", () => { baseline: (skill) => `Available skill: ${skill}`, }) - expect(yield* SystemContext.reconcile(context, {})).toEqual({ + expect(yield* Instructions.reconcile(context, {})).toEqual({ _tag: "Updated", text: "Available skill: effect", applied: { "core/skills": { value: "effect" } }, @@ -121,30 +121,28 @@ describe("SystemContext", () => { it.effect("retains the belief while a source is temporarily unavailable", () => Effect.gen(function* () { const previous = { "core/remote": { value: "instructions", removed: "Instructions removed" } } - const context = stringContext({ key: "core/remote", value: SystemContext.unavailable }) + const context = stringContext({ key: "core/remote", value: Instructions.unavailable }) - expect(yield* SystemContext.reconcile(context, previous)).toEqual({ _tag: "Unchanged" }) + expect(yield* Instructions.reconcile(context, previous)).toEqual({ _tag: "Unchanged" }) }), ) it.effect("blocks initialization while a source is unavailable", () => Effect.gen(function* () { - const exit = yield* SystemContext.initialize( - stringContext({ key: "core/remote", value: SystemContext.unavailable }), + const exit = yield* Instructions.initialize( + stringContext({ key: "core/remote", value: Instructions.unavailable }), ).pipe(Effect.exit) expect(Exit.isFailure(exit)).toBe(true) if (Exit.isFailure(exit)) - expect(Cause.squash(exit.cause)).toEqual( - new SystemContext.InitializationBlocked({ keys: [key("core/remote")] }), - ) + expect(Cause.squash(exit.cause)).toEqual(new Instructions.InitializationBlocked({ keys: [key("core/remote")] })) }), ) it.effect("emits the previously stored removal message", () => Effect.gen(function* () { expect( - yield* SystemContext.reconcile(SystemContext.empty, { + yield* Instructions.reconcile(Instructions.empty, { "core/instructions": { value: "contents", removed: "Instructions removed; stop applying them." }, }), ).toEqual({ @@ -157,13 +155,13 @@ describe("SystemContext", () => { it.effect("retains an unannounced removal silently", () => Effect.gen(function* () { - expect(yield* SystemContext.reconcile(SystemContext.empty, { "core/date": { value: "2026-06-04" } })).toEqual({ + expect(yield* Instructions.reconcile(Instructions.empty, { "core/date": { value: "2026-06-04" } })).toEqual({ _tag: "Unchanged", }) // The retained belief survives alongside other updates. expect( - yield* SystemContext.reconcile(stringContext({ key: "core/skills", value: "effect" }), { + yield* Instructions.reconcile(stringContext({ key: "core/skills", value: "effect" }), { "core/date": { value: "2026-06-04" }, }), ).toEqual({ @@ -180,7 +178,7 @@ describe("SystemContext", () => { it.effect("renders multiple removals in stable key order", () => Effect.gen(function* () { expect( - yield* SystemContext.reconcile(SystemContext.empty, { + yield* Instructions.reconcile(Instructions.empty, { "core/z": { value: "z", removed: "Removed z" }, "core/a": { value: "a", removed: "Removed a" }, }), @@ -190,7 +188,7 @@ describe("SystemContext", () => { it.effect("rejects empty model-visible renderings", () => Effect.gen(function* () { - const exit = yield* SystemContext.initialize( + const exit = yield* Instructions.initialize( stringContext({ key: "core/empty", value: "value", baseline: () => "" }), ).pipe(Effect.exit) @@ -202,7 +200,7 @@ describe("SystemContext", () => { it.effect("re-announces the baseline when a stored value no longer decodes", () => Effect.gen(function* () { expect( - yield* SystemContext.reconcile(stringContext({ key: "core/date", value: "2026-06-04" }), { + yield* Instructions.reconcile(stringContext({ key: "core/date", value: "2026-06-04" }), { "core/date": { value: 42, removed: "Date removed" }, }), ).toEqual({ @@ -215,7 +213,7 @@ describe("SystemContext", () => { it.effect("renders undecodable re-announcements alongside other updates", () => Effect.gen(function* () { - const context = SystemContext.combine([ + const context = Instructions.combine([ stringContext({ key: "core/date", value: "2026-06-04", @@ -225,7 +223,7 @@ describe("SystemContext", () => { ]) expect( - yield* SystemContext.reconcile(context, { + yield* Instructions.reconcile(context, { "core/date": { value: "2026-06-03" }, "core/location": { value: 42 }, }), @@ -243,7 +241,7 @@ describe("SystemContext", () => { it.effect("rebaselines from one coherent source observation", () => Effect.gen(function* () { let loads = 0 - const context = SystemContext.make({ + const context = Instructions.make({ key: key("core/date"), codec: Schema.toCodecJson(Schema.String), load: Effect.sync(() => { @@ -254,7 +252,7 @@ describe("SystemContext", () => { update: (_previous, current) => current, }) - expect(yield* SystemContext.rebaseline(context, { "core/date": { value: "2026-06-03" } })).toEqual({ + expect(yield* Instructions.rebaseline(context, { "core/date": { value: "2026-06-03" } })).toEqual({ text: "2026-06-04", applied: { "core/date": { value: "2026-06-04" } }, }) @@ -264,17 +262,17 @@ describe("SystemContext", () => { it.effect("rebaselines an unavailable source from the last-applied belief", () => Effect.gen(function* () { - const context = SystemContext.combine([ + const context = Instructions.combine([ stringContext({ key: "core/date", value: "2026-06-04" }), stringContext({ key: "core/remote", - value: SystemContext.unavailable, + value: Instructions.unavailable, baseline: (value) => `Instructions: ${value}`, }), ]) expect( - yield* SystemContext.rebaseline(context, { + yield* Instructions.rebaseline(context, { "core/remote": { value: "contents", removed: "Instructions removed" }, }), ).toEqual({ @@ -289,11 +287,11 @@ describe("SystemContext", () => { it.effect("drops undecodable beliefs and removed sources at rebaseline", () => Effect.gen(function* () { - const context = stringContext({ key: "core/remote", value: SystemContext.unavailable }) + const context = stringContext({ key: "core/remote", value: Instructions.unavailable }) // Undecodable belief cannot be restated; removed source entries self-clean. expect( - yield* SystemContext.rebaseline(context, { + yield* Instructions.rebaseline(context, { "core/remote": { value: 42 }, "core/gone": { value: "gone" }, }), @@ -315,7 +313,7 @@ describe("SystemContext", () => { ] expect( - SystemContext.diffByKey( + Instructions.diffByKey( previous, current, (value) => value.name, @@ -337,19 +335,19 @@ describe("SystemContext", () => { it.effect("rejects duplicate source keys", () => Effect.sync(() => { expect(() => - SystemContext.combine([ + Instructions.combine([ stringContext({ key: "core/date", value: "one" }), stringContext({ key: "core/date", value: "two" }), ]), - ).toThrow(new SystemContext.DuplicateKeyError({ key: key("core/date") })) + ).toThrow(new Instructions.DuplicateKeyError({ key: key("core/date") })) }), ) - it.effect("combines contexts in order", () => + it.effect("combines instructions in order", () => Effect.gen(function* () { expect( - (yield* SystemContext.initialize( - SystemContext.combine([ + (yield* Instructions.initialize( + Instructions.combine([ stringContext({ key: "core/date", value: "date" }), stringContext({ key: "core/location", value: "location" }), ]), @@ -360,7 +358,7 @@ describe("SystemContext", () => { it.effect("requires namespaced source keys", () => Effect.sync(() => { - const decodeKey = Schema.decodeUnknownSync(SystemContext.Key) + const decodeKey = Schema.decodeUnknownSync(Instructions.Key) expect(decodeKey("core/date")).toBe(key("core/date")) expect(() => decodeKey("date")).toThrow() @@ -369,7 +367,7 @@ describe("SystemContext", () => { it.effect("requires namespaced applied keys", () => Effect.sync(() => { - const decodeApplied = Schema.decodeUnknownSync(SystemContext.Applied) + const decodeApplied = Schema.decodeUnknownSync(Instructions.Applied) expect(Object.keys(decodeApplied({ "core/date": { value: "date" } }))).toEqual(["core/date"]) expect(() => decodeApplied({ date: { value: "date" } })).toThrow() diff --git a/packages/core/test/reference-guidance.test.ts b/packages/core/test/reference-guidance.test.ts index 3db3212c3c0..fe34873f969 100644 --- a/packages/core/test/reference-guidance.test.ts +++ b/packages/core/test/reference-guidance.test.ts @@ -4,17 +4,17 @@ import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { AbsolutePath } from "@opencode-ai/core/schema" import { Reference } from "@opencode-ai/core/reference" import { ReferenceGuidance } from "@opencode-ai/core/reference/guidance" -import { SystemContext } from "@opencode-ai/core/system-context/index" +import { Instructions } from "@opencode-ai/core/instructions/index" import { it } from "./lib/effect" const guidanceLayer = (referenceLayer: Layer.Layer) => AppNodeBuilder.build(ReferenceGuidance.node, [[Reference.node, referenceLayer]]) describe("ReferenceGuidance", () => { - it.effect("lists available references in the system context", () => + it.effect("lists available references in the instructions", () => Effect.gen(function* () { const guidance = yield* ReferenceGuidance.Service - const generation = yield* SystemContext.initialize(yield* guidance.load()) + const generation = yield* Instructions.initialize(yield* guidance.load()) expect(generation.text).toContain("") expect(generation.text).toContain("docs") @@ -46,7 +46,7 @@ describe("ReferenceGuidance", () => { it.effect("omits guidance when no references are available", () => Effect.gen(function* () { const guidance = yield* ReferenceGuidance.Service - const generation = yield* SystemContext.initialize(yield* guidance.load()) + const generation = yield* Instructions.initialize(yield* guidance.load()) expect(generation.text).toBe("") }).pipe(Effect.provide(guidanceLayer(Layer.mock(Reference.Service, { list: () => Effect.succeed([]) })))), ) @@ -54,7 +54,7 @@ describe("ReferenceGuidance", () => { it.effect("omits references without descriptions", () => Effect.gen(function* () { const guidance = yield* ReferenceGuidance.Service - const generation = yield* SystemContext.initialize(yield* guidance.load()) + const generation = yield* Instructions.initialize(yield* guidance.load()) expect(generation.text).toBe("") }).pipe( Effect.provide( @@ -85,10 +85,10 @@ describe("ReferenceGuidance", () => { let references = [reference("docs", "Use for product documentation")] return Effect.gen(function* () { const guidance = yield* ReferenceGuidance.Service - const initialized = yield* SystemContext.initialize(yield* guidance.load()) + const initialized = yield* Instructions.initialize(yield* guidance.load()) references = [reference("docs", "Use for product documentation"), reference("examples", "Use for examples")] - const added = yield* SystemContext.reconcile(yield* guidance.load(), initialized.applied) + const added = yield* Instructions.reconcile(yield* guidance.load(), initialized.applied) expect(added).toMatchObject({ _tag: "Updated", text: [ @@ -103,7 +103,7 @@ describe("ReferenceGuidance", () => { references = [reference("examples", "Use for examples")] expect( - yield* SystemContext.reconcile(yield* guidance.load(), added._tag === "Updated" ? added.applied : {}), + yield* Instructions.reconcile(yield* guidance.load(), added._tag === "Updated" ? added.applied : {}), ).toMatchObject({ _tag: "Updated", text: "The following project references are no longer available and must not be used: docs.", diff --git a/packages/core/test/session-projector.test.ts b/packages/core/test/session-projector.test.ts index bb53c134057..da2e494731e 100644 --- a/packages/core/test/session-projector.test.ts +++ b/packages/core/test/session-projector.test.ts @@ -21,7 +21,7 @@ import { SessionExecution } from "@opencode-ai/core/session/execution" import { SessionInput } from "@opencode-ai/core/session/input" import { Shell } from "@opencode-ai/schema/shell" import { - SessionContextCheckpointTable, + InstructionCheckpointTable, SessionInputTable, SessionMessageTable, SessionTable, @@ -80,7 +80,7 @@ describe("SessionProjector", () => { ]) .run() yield* db - .insert(SessionContextCheckpointTable) + .insert(InstructionCheckpointTable) .values({ session_id: sessionID, baseline: "baseline", snapshot: {}, baseline_seq: 0 }) .run() const events = yield* EventV2.Service @@ -107,7 +107,7 @@ describe("SessionProjector", () => { (yield* db.select({ id: SessionMessageTable.id }).from(SessionMessageTable).all()).map((row) => row.id), ).toEqual([earlier]) // A committed revert resets the context checkpoint so the next turn re-initializes. - expect(yield* db.select().from(SessionContextCheckpointTable).get().pipe(Effect.orDie)).toBeUndefined() + expect(yield* db.select().from(InstructionCheckpointTable).get().pipe(Effect.orDie)).toBeUndefined() }), ) diff --git a/packages/core/test/session-runner-recorded.test.ts b/packages/core/test/session-runner-recorded.test.ts index 35e84fcb6c7..15a1b35fd46 100644 --- a/packages/core/test/session-runner-recorded.test.ts +++ b/packages/core/test/session-runner-recorded.test.ts @@ -31,9 +31,9 @@ import { ToolOutputStore } from "@opencode-ai/core/tool-output-store" import { SessionTable } from "@opencode-ai/core/session/sql" import { SessionStore } from "@opencode-ai/core/session/store" import { Location } from "@opencode-ai/core/location" -import { SystemContextBuiltIns } from "@opencode-ai/core/system-context/builtins" -import { InstructionContext } from "@opencode-ai/core/instruction-context" -import { SystemContext } from "@opencode-ai/core/system-context" +import { InstructionBuiltIns } from "@opencode-ai/core/instructions/builtins" +import { InstructionDiscovery } from "@opencode-ai/core/instruction-discovery" +import { Instructions } from "@opencode-ai/core/instructions" import { SkillGuidance } from "@opencode-ai/core/skill/guidance" import { ReferenceGuidance } from "@opencode-ai/core/reference/guidance" import { McpGuidance } from "@opencode-ai/core/mcp/guidance" @@ -73,18 +73,18 @@ const model = OpenAIChat.route }) .model({ id: "gpt-4o-mini" }) const models = SessionRunnerModel.layerWith(() => Effect.succeed(SessionRunnerModel.resolved(model))) -const systemContext = Layer.mock(SystemContextBuiltIns.Service, { load: () => Effect.succeed(SystemContext.empty) }) -const instructionContext = Layer.mock(InstructionContext.Service, { load: () => Effect.succeed(SystemContext.empty) }) -const skillGuidance = Layer.mock(SkillGuidance.Service, { load: () => Effect.succeed(SystemContext.empty) }) -const referenceGuidance = Layer.mock(ReferenceGuidance.Service, { load: () => Effect.succeed(SystemContext.empty) }) -const mcpGuidance = Layer.mock(McpGuidance.Service, { load: () => Effect.succeed(SystemContext.empty) }) +const systemContext = Layer.mock(InstructionBuiltIns.Service, { load: () => Effect.succeed(Instructions.empty) }) +const instructionContext = Layer.mock(InstructionDiscovery.Service, { load: () => Effect.succeed(Instructions.empty) }) +const skillGuidance = Layer.mock(SkillGuidance.Service, { load: () => Effect.succeed(Instructions.empty) }) +const referenceGuidance = Layer.mock(ReferenceGuidance.Service, { load: () => Effect.succeed(Instructions.empty) }) +const mcpGuidance = Layer.mock(McpGuidance.Service, { load: () => Effect.succeed(Instructions.empty) }) const config = Layer.succeed(Config.Service, Config.Service.of({ entries: () => Effect.succeed([]) })) const runnerLayer = AppNodeBuilder.build(SessionRunnerLLM.node, [ [Snapshot.node, Snapshot.noopLayer], [LayerNodePlatform.llmClient, client], [SessionRunnerModel.node, models], - [SystemContextBuiltIns.node, systemContext], - [InstructionContext.node, instructionContext], + [InstructionBuiltIns.node, systemContext], + [InstructionDiscovery.node, instructionContext], [Location.node, Location.boundNode({ directory: AbsolutePath.make("/project") })], [SkillGuidance.node, skillGuidance], [ReferenceGuidance.node, referenceGuidance], @@ -119,8 +119,8 @@ const it = testEffect( AgentV2.node, ToolRegistry.node, SessionRunnerModel.node, - SystemContextBuiltIns.node, - InstructionContext.node, + InstructionBuiltIns.node, + InstructionDiscovery.node, SkillGuidance.node, ReferenceGuidance.node, Config.node, @@ -133,8 +133,8 @@ const it = testEffect( [PermissionV2.node, permission], [ToolOutputStore.node, ToolOutputStore.nodeWithoutConfig], [SessionRunnerModel.node, models], - [SystemContextBuiltIns.node, systemContext], - [InstructionContext.node, instructionContext], + [InstructionBuiltIns.node, systemContext], + [InstructionDiscovery.node, instructionContext], [Location.node, Location.boundNode({ directory: AbsolutePath.make("/project") })], [SkillGuidance.node, skillGuidance], [ReferenceGuidance.node, referenceGuidance], diff --git a/packages/core/test/session-runner.test.ts b/packages/core/test/session-runner.test.ts index cdf1ae37d44..99ccf338d28 100644 --- a/packages/core/test/session-runner.test.ts +++ b/packages/core/test/session-runner.test.ts @@ -46,16 +46,16 @@ import { Config } from "@opencode-ai/core/config" import { ConfigCompaction } from "@opencode-ai/core/config/compaction" import { Tool } from "@opencode-ai/core/tool/tool" import { - SessionContextCheckpointTable, + InstructionCheckpointTable, SessionInputTable, SessionMessageTable, SessionTable, } from "@opencode-ai/core/session/sql" -import { SessionContextEntry } from "@opencode-ai/core/session/context-entry" +import { InstructionEntry } from "@opencode-ai/core/session/instruction-entry" import { SessionStore } from "@opencode-ai/core/session/store" -import { SystemContext } from "@opencode-ai/core/system-context" -import { SystemContextBuiltIns } from "@opencode-ai/core/system-context/builtins" -import { InstructionContext } from "@opencode-ai/core/instruction-context" +import { Instructions } from "@opencode-ai/core/instructions" +import { InstructionBuiltIns } from "@opencode-ai/core/instructions/builtins" +import { InstructionDiscovery } from "@opencode-ai/core/instruction-discovery" import { SkillGuidance } from "@opencode-ai/core/skill/guidance" import { ReferenceGuidance } from "@opencode-ai/core/reference/guidance" import { McpGuidance } from "@opencode-ai/core/mcp/guidance" @@ -180,24 +180,24 @@ const models = SessionRunnerModel.layerWith((session) => ), ), ) -const systemContextKey = SystemContext.Key.make("test/context") +const systemContextKey = Instructions.Key.make("test/context") let systemBaseline = "Initial context" let systemRemoved = false let systemUnavailable = false let systemLoadHook = Effect.void const skillBaselines = new Map() -const systemContext = Layer.mock(SystemContextBuiltIns.Service, { +const systemContext = Layer.mock(InstructionBuiltIns.Service, { load: () => Effect.sync(() => - SystemContext.combine( + Instructions.combine( systemRemoved ? [] : [ - SystemContext.make({ + Instructions.make({ key: systemContextKey, codec: Schema.toCodecJson(Schema.String), load: systemLoadHook.pipe( - Effect.andThen(Effect.sync(() => (systemUnavailable ? SystemContext.unavailable : systemBaseline))), + Effect.andThen(Effect.sync(() => (systemUnavailable ? Instructions.unavailable : systemBaseline))), ), baseline: String, update: (_previous, current) => current, @@ -207,24 +207,24 @@ const systemContext = Layer.mock(SystemContextBuiltIns.Service, { ), ), }) -const instructionContext = Layer.mock(InstructionContext.Service, { load: () => Effect.succeed(SystemContext.empty) }) +const instructionContext = Layer.mock(InstructionDiscovery.Service, { load: () => Effect.succeed(Instructions.empty) }) const skillGuidance = Layer.mock(SkillGuidance.Service, { load: (agent) => Effect.succeed( skillBaselines.has(agent.id) - ? SystemContext.make({ - key: SystemContext.Key.make("test/skill-guidance"), + ? Instructions.make({ + key: Instructions.Key.make("test/skill-guidance"), codec: Schema.toCodecJson(Schema.String), load: Effect.succeed(skillBaselines.get(agent.id)!), baseline: String, update: (_previous, current) => current, removed: () => "Skill guidance removed", }) - : SystemContext.empty, + : Instructions.empty, ), }) -const referenceGuidance = Layer.mock(ReferenceGuidance.Service, { load: () => Effect.succeed(SystemContext.empty) }) -const mcpGuidance = Layer.mock(McpGuidance.Service, { load: () => Effect.succeed(SystemContext.empty) }) +const referenceGuidance = Layer.mock(ReferenceGuidance.Service, { load: () => Effect.succeed(Instructions.empty) }) +const mcpGuidance = Layer.mock(McpGuidance.Service, { load: () => Effect.succeed(Instructions.empty) }) const config = Layer.succeed( Config.Service, Config.Service.of({ @@ -246,8 +246,8 @@ const runnerLayer = AppNodeBuilder.build(SessionRunnerLLM.node, [ [Snapshot.node, Snapshot.noopLayer], [LayerNodePlatform.llmClient, client], [SessionRunnerModel.node, models], - [SystemContextBuiltIns.node, systemContext], - [InstructionContext.node, instructionContext], + [InstructionBuiltIns.node, systemContext], + [InstructionDiscovery.node, instructionContext], [Location.node, Location.boundNode({ directory: AbsolutePath.make("/project") })], [SkillGuidance.node, skillGuidance], [ReferenceGuidance.node, referenceGuidance], @@ -285,9 +285,9 @@ const it = testEffect( ToolRegistry.toolsNode, echoNode, SessionRunnerModel.node, - SystemContextBuiltIns.node, - InstructionContext.node, - SessionContextEntry.node, + InstructionBuiltIns.node, + InstructionDiscovery.node, + InstructionEntry.node, SkillGuidance.node, ReferenceGuidance.node, Config.node, @@ -300,8 +300,8 @@ const it = testEffect( [LayerNodePlatform.llmClient, client], [PermissionV2.node, permission], [SessionRunnerModel.node, models], - [SystemContextBuiltIns.node, systemContext], - [InstructionContext.node, instructionContext], + [InstructionBuiltIns.node, systemContext], + [InstructionDiscovery.node, instructionContext], [Location.node, Location.boundNode({ directory: AbsolutePath.make("/project") })], [SkillGuidance.node, skillGuidance], [ReferenceGuidance.node, referenceGuidance], @@ -709,14 +709,14 @@ describe("SessionRunnerLLM", () => { const exit = yield* session.resume(sessionID).pipe(Effect.exit) expect(Exit.isFailure(exit)).toBe(true) - if (Exit.isFailure(exit)) expect(Cause.squash(exit.cause)).toBeInstanceOf(SystemContext.InitializationBlocked) + if (Exit.isFailure(exit)) expect(Cause.squash(exit.cause)).toBeInstanceOf(Instructions.InitializationBlocked) expect(requests).toHaveLength(0) expect(yield* SessionInput.hasPending(db, sessionID, "steer")).toBe(true) expect( yield* db .select() - .from(SessionContextCheckpointTable) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) + .from(InstructionCheckpointTable) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) .get(), ).toBeUndefined() @@ -747,8 +747,8 @@ describe("SessionRunnerLLM", () => { expect( yield* db .select() - .from(SessionContextCheckpointTable) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) + .from(InstructionCheckpointTable) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) .get(), ).toBeUndefined() @@ -774,16 +774,16 @@ describe("SessionRunnerLLM", () => { const parent = yield* db .select() - .from(SessionContextCheckpointTable) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) + .from(InstructionCheckpointTable) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) .get() .pipe(Effect.orDie) expect(parent).toBeDefined() expect( yield* db .select() - .from(SessionContextCheckpointTable) - .where(eq(SessionContextCheckpointTable.session_id, forked.id)) + .from(InstructionCheckpointTable) + .where(eq(InstructionCheckpointTable.session_id, forked.id)) .get() .pipe(Effect.orDie), ).toEqual({ ...parent!, session_id: forked.id }) @@ -799,9 +799,9 @@ describe("SessionRunnerLLM", () => { response = [] yield* session.resume(sessionID) yield* db - .update(SessionContextCheckpointTable) + .update(InstructionCheckpointTable) .set({ snapshot: { invalid: { value: "bad" } } }) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) .run() .pipe(Effect.orDie) yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) @@ -815,9 +815,9 @@ describe("SessionRunnerLLM", () => { expect(requests[0]?.messages.map((message) => message.role)).toEqual(["user", "system", "user"]) expect(requests[0]?.messages.at(1)?.content).toEqual([{ type: "text", text: "Initial context" }]) const healed = yield* db - .select({ snapshot: SessionContextCheckpointTable.snapshot }) - .from(SessionContextCheckpointTable) - .where(eq(SessionContextCheckpointTable.session_id, sessionID)) + .select({ snapshot: InstructionCheckpointTable.snapshot }) + .from(InstructionCheckpointTable) + .where(eq(InstructionCheckpointTable.session_id, sessionID)) .get() .pipe(Effect.orDie) expect(healed?.snapshot).toEqual({ "test/context": { value: "Initial context", removed: expect.any(String) } }) @@ -849,7 +849,7 @@ describe("SessionRunnerLLM", () => { yield* db .select({ id: EventTable.id }) .from(EventTable) - .where(eq(EventTable.type, "session.context.updated.1")) + .where(eq(EventTable.type, "session.instructions.updated.1")) .all() .pipe(Effect.orDie), ).toHaveLength(1) @@ -1109,7 +1109,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - const contextEntries = yield* SessionContextEntry.Service + const contextEntries = yield* InstructionEntry.Service yield* contextEntries.put({ sessionID, key: "deploy-target", value: "production" }) yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) diff --git a/packages/core/test/skill/guidance.test.ts b/packages/core/test/skill/guidance.test.ts index b26b75fe711..704f42b803b 100644 --- a/packages/core/test/skill/guidance.test.ts +++ b/packages/core/test/skill/guidance.test.ts @@ -5,7 +5,7 @@ import { AgentV2 } from "@opencode-ai/core/agent" import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { AbsolutePath } from "@opencode-ai/core/schema" import { SkillV2 } from "@opencode-ai/core/skill" -import { SystemContext } from "@opencode-ai/core/system-context" +import { Instructions } from "@opencode-ai/core/instructions" import { SkillGuidance } from "@opencode-ai/core/skill/guidance" import { it } from "../lib/effect" @@ -51,7 +51,7 @@ describe("SkillGuidance", () => { const guidance = yield* SkillGuidance.Service const initialized = yield* guidance .load({ id: agent.id, info: agent }) - .pipe(Effect.flatMap(SystemContext.initialize)) + .pipe(Effect.flatMap(Instructions.initialize)) expect(initialized.text).toBe( [ @@ -71,7 +71,7 @@ describe("SkillGuidance", () => { expect( yield* guidance .load({ id: agent.id, info: agent }) - .pipe(Effect.flatMap((context) => SystemContext.reconcile(context, initialized.applied))), + .pipe(Effect.flatMap((context) => Instructions.reconcile(context, initialized.applied))), ).toMatchObject({ _tag: "Updated", text: "The following skills are no longer available and must not be used: effect.", @@ -92,12 +92,12 @@ describe("SkillGuidance", () => { const guidance = yield* SkillGuidance.Service const initialized = yield* guidance .load({ id: agent.id, info: agent }) - .pipe(Effect.flatMap(SystemContext.initialize)) + .pipe(Effect.flatMap(Instructions.initialize)) skills = [effect, debugging] const added = yield* guidance .load({ id: agent.id, info: agent }) - .pipe(Effect.flatMap((context) => SystemContext.reconcile(context, initialized.applied))) + .pipe(Effect.flatMap((context) => Instructions.reconcile(context, initialized.applied))) expect(added).toMatchObject({ _tag: "Updated", text: [ @@ -113,7 +113,7 @@ describe("SkillGuidance", () => { const removed = yield* guidance .load({ id: agent.id, info: agent }) .pipe( - Effect.flatMap((context) => SystemContext.reconcile(context, added._tag === "Updated" ? added.applied : {})), + Effect.flatMap((context) => Instructions.reconcile(context, added._tag === "Updated" ? added.applied : {})), ) expect(removed).toMatchObject({ _tag: "Updated", @@ -129,13 +129,13 @@ describe("SkillGuidance", () => { const guidance = yield* SkillGuidance.Service const initialized = yield* guidance .load({ id: agent.id, info: agent }) - .pipe(Effect.flatMap(SystemContext.initialize)) + .pipe(Effect.flatMap(Instructions.initialize)) skills = [SkillV2.Info.make({ ...effect, description: "Build applications with Effect v4" })] expect( yield* guidance .load({ id: agent.id, info: agent }) - .pipe(Effect.flatMap((context) => SystemContext.reconcile(context, initialized.applied))), + .pipe(Effect.flatMap((context) => Instructions.reconcile(context, initialized.applied))), ).toMatchObject({ _tag: "Updated", text: expect.stringContaining( @@ -152,12 +152,12 @@ describe("SkillGuidance", () => { }) return Effect.gen(function* () { const guidance = yield* SkillGuidance.Service - expect( - yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(SystemContext.initialize)), - ).toEqual({ - text: "", - applied: {}, - }) + expect(yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(Instructions.initialize))).toEqual( + { + text: "", + applied: {}, + }, + ) }).pipe(Effect.provide(layer(() => [effect]))) }) @@ -171,12 +171,12 @@ describe("SkillGuidance", () => { }) return Effect.gen(function* () { const guidance = yield* SkillGuidance.Service - expect( - yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(SystemContext.initialize)), - ).toEqual({ - text: "", - applied: {}, - }) + expect(yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(Instructions.initialize))).toEqual( + { + text: "", + applied: {}, + }, + ) }).pipe(Effect.provide(layer(() => [effect]))) }) @@ -191,7 +191,7 @@ describe("SkillGuidance", () => { return Effect.gen(function* () { const guidance = yield* SkillGuidance.Service expect( - (yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(SystemContext.initialize))).text, + (yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(Instructions.initialize))).text, ).toContain("effect") }).pipe(Effect.provide(layer(() => [effect]))) }) @@ -207,12 +207,12 @@ describe("SkillGuidance", () => { }) return Effect.gen(function* () { const guidance = yield* SkillGuidance.Service - expect( - yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(SystemContext.initialize)), - ).toEqual({ - text: "", - applied: {}, - }) + expect(yield* guidance.load({ id: agent.id, info: agent }).pipe(Effect.flatMap(Instructions.initialize))).toEqual( + { + text: "", + applied: {}, + }, + ) }).pipe(Effect.provide(layer(() => [effect]))) }) }) diff --git a/packages/core/test/system-context/builtins.test.ts b/packages/core/test/system-context/builtins.test.ts deleted file mode 100644 index 2d4ac356b9b..00000000000 --- a/packages/core/test/system-context/builtins.test.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { describe, expect } from "bun:test" -import { Effect, Layer } from "effect" -import * as TestClock from "effect/testing/TestClock" -import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" -import { LayerNode } from "@opencode-ai/core/effect/layer-node" -import { Location } from "@opencode-ai/core/location" -import { FSUtil } from "@opencode-ai/core/fs-util" -import { Global } from "@opencode-ai/core/global" -import { AbsolutePath } from "@opencode-ai/core/schema" -import { SystemContext } from "@opencode-ai/core/system-context" -import { SystemContextBuiltIns } from "@opencode-ai/core/system-context/builtins" -import { InstructionContext } from "@opencode-ai/core/instruction-context" -import { location } from "../fixture/location" -import { testEffect } from "../lib/effect" - -const directory = AbsolutePath.make(FSUtil.resolve("/repo/packages/core")) -const projectDirectory = AbsolutePath.make(FSUtil.resolve("/repo")) -const instructionFile = FSUtil.resolve("/repo/AGENTS.md") -const timestamp = Date.parse("2026-06-03T12:00:00.000Z") -const localDate = (time: number) => new Date(time).toDateString() -const locationLayer = Layer.succeed( - Location.Service, - Location.Service.of( - location( - { directory }, - { projectDirectory, vcs: { type: "git", store: AbsolutePath.make(FSUtil.resolve("/repo/.git")) } }, - ), - ), -) -const builtInsNode = LayerNode.group([SystemContextBuiltIns.node, InstructionContext.node]) -const it = testEffect( - AppNodeBuilder.build(builtInsNode, [ - [Location.node, locationLayer], - [Global.node, Global.layerWith({ config: "/global" })], - ]), -) -const instructionFS = Layer.effect( - FSUtil.Service, - FSUtil.Service.pipe( - Effect.map((fs) => - FSUtil.Service.of({ - ...fs, - up: () => Effect.succeed([instructionFile]), - readFileStringSafe: (path) => Effect.succeed(path === instructionFile ? "Be precise." : undefined), - }), - ), - ), -).pipe(Layer.provide(LayerNode.compile(FSUtil.node))) -const itWithInstructions = testEffect( - AppNodeBuilder.build(builtInsNode, [ - [Location.node, locationLayer], - [FSUtil.node, instructionFS], - [Global.node, Global.layerWith({ config: "/global" })], - ]), -) - -describe("SystemContextBuiltIns", () => { - it.effect("loads location-scoped environment and host-local date context", () => - Effect.gen(function* () { - yield* TestClock.setTime(timestamp) - const context = yield* SystemContextBuiltIns.Service - const initialized = yield* SystemContext.initialize(yield* context.load()) - - expect(initialized.text).toBe( - [ - "Here is some useful information about the environment you are running in:", - "", - ` Working directory: ${directory}`, - ` Workspace root folder: ${projectDirectory}`, - " Is directory a git repo: yes", - ` Platform: ${process.platform}`, - "", - "", - `Today's date: ${localDate(timestamp)}`, - ].join("\n"), - ) - }), - ) - - it.effect("reconciles the date without repeating unchanged environment context", () => - Effect.gen(function* () { - yield* TestClock.setTime(timestamp) - const context = yield* SystemContextBuiltIns.Service - const initialized = yield* SystemContext.initialize(yield* context.load()) - - yield* TestClock.setTime(timestamp + 24 * 60 * 60 * 1000) - const refreshed = yield* SystemContext.reconcile(yield* context.load(), initialized.applied) - - expect(refreshed).toMatchObject({ - _tag: "Updated", - text: `Today's date is now: ${localDate(timestamp + 24 * 60 * 60 * 1000)}`, - }) - }), - ) - - it.effect("does not update again within the same local calendar day", () => - Effect.gen(function* () { - yield* TestClock.setTime(timestamp) - const context = yield* SystemContextBuiltIns.Service - const initialized = yield* SystemContext.initialize(yield* context.load()) - - yield* TestClock.setTime(timestamp + 60 * 60 * 1000) - expect(yield* SystemContext.reconcile(yield* context.load(), initialized.applied)).toEqual({ _tag: "Unchanged" }) - }), - ) - - itWithInstructions.effect("composes ambient instructions after built-in context", () => - Effect.gen(function* () { - yield* TestClock.setTime(timestamp) - const builtIns = yield* SystemContextBuiltIns.Service - const instructions = yield* InstructionContext.Service - const context = { - load: () => Effect.all([builtIns.load(), instructions.load()]).pipe(Effect.map(SystemContext.combine)), - } - - expect((yield* SystemContext.initialize(yield* context.load())).text).toBe( - [ - "Here is some useful information about the environment you are running in:", - "", - ` Working directory: ${directory}`, - ` Workspace root folder: ${projectDirectory}`, - " Is directory a git repo: yes", - ` Platform: ${process.platform}`, - "", - "", - `Today's date: ${localDate(timestamp)}`, - "", - `Instructions from: ${instructionFile}\nBe precise.`, - ].join("\n"), - ) - }), - ) -}) diff --git a/packages/httpapi-codegen/src/index.ts b/packages/httpapi-codegen/src/index.ts index 8f22b4553f3..f6ad6b02d7f 100644 --- a/packages/httpapi-codegen/src/index.ts +++ b/packages/httpapi-codegen/src/index.ts @@ -35,6 +35,8 @@ export type Contract = { readonly groups: ReadonlyArray } +export type EndpointName = string | readonly [string, ...Array] + export class GenerationError extends Schema.TaggedErrorClass()("GenerationError", { reason: Schema.String, }) { @@ -53,6 +55,7 @@ export type Endpoint = { readonly headers: Schema.Top | undefined readonly payloads: ReadonlyArray readonly operation: Operation + readonly clientPath: readonly [string, ...Array] readonly input: ReadonlyArray readonly unwrapData: boolean readonly errors: ReadonlyArray<{ readonly status: number; readonly schema: Schema.Top }> @@ -86,7 +89,7 @@ export function compile( api: HttpApi.HttpApi, options?: { readonly groupNames?: Readonly> - readonly endpointNames?: Readonly> + readonly endpointNames?: Readonly> readonly omitEndpoints?: ReadonlySet }, ): Contract { @@ -148,6 +151,9 @@ export function compile( for (const [path, schema] of schemaPaths) assertPortable(schema, path, portable) } + const clientPath = normalizeClientPath( + options?.endpointNames?.[endpoint.name] ?? clientEndpointName(endpoint.name), + ) endpoints.push({ group: groupName, sourceGroup: group.identifier, @@ -158,13 +164,14 @@ export function compile( headers: headers?.schema, payloads: payloads.map((item) => item.schema), input: inputs, + clientPath, unwrapData: isDataEnvelope(success.schema), successes: [success.schema], errors: errorSchemas.map((item) => ({ status: item.status, schema: item.schema })), effectPortable, operation: { group: groupName, - name: options?.endpointNames?.[endpoint.name] ?? clientEndpointName(endpoint.name), + name: clientPath.join("."), input: inputs.map(({ name, source }) => ({ name, source })), inputMode: inputs.length === 0 ? "none" : inputs.every((field) => field.optional) ? "optional" : "required", success: isStreamSchema(success.schema) @@ -200,20 +207,51 @@ export function compile( }, ) const publicNames = new Set() + const groupTypeNames = new Set() + const endpointTypeNames = new Set() + const operationKeys = new Set() for (const group of groups) { - const endpointNames = new Set() - for (const endpoint of group.endpoints) { - if (endpointNames.has(endpoint.operation.name)) { - throw new GenerationError({ - reason: `Client endpoint name collision: ${group.identifier}.${endpoint.operation.name}`, - }) - } - endpointNames.add(endpoint.operation.name) + if (group.identifier === "__proto__") { + throw new GenerationError({ reason: "Client group name cannot be __proto__" }) } - const names = group.endpoints[0]?.topLevel ? group.endpoints.map((item) => item.operation.name) : [group.identifier] - for (const name of names) { - if (publicNames.has(name)) throw new GenerationError({ reason: `Client name collision: ${name}` }) - publicNames.add(name) + const groupTypeName = identifierPart(group.identifier) + if (groupTypeNames.has(groupTypeName)) { + throw new GenerationError({ reason: `Client group type collision: ${groupTypeName}` }) + } + groupTypeNames.add(groupTypeName) + assertUniqueClientPaths( + group.endpoints.map((endpoint) => endpoint.clientPath), + (path) => `Client endpoint name collision: ${group.identifier}.${path.join(".")}`, + ) + const typeNames = new Set() + for (const endpoint of group.endpoints) { + const operationKey = clientOperationKey(group, endpoint) + if (operationKeys.has(operationKey)) { + throw new GenerationError({ reason: `Client operation key collision: ${operationKey}` }) + } + operationKeys.add(operationKey) + const name = endpoint.clientPath.map(identifierPart).join("") + const endpointTypeName = `${groupTypeName}${name}` + if (endpointTypeNames.has(endpointTypeName)) { + throw new GenerationError({ reason: `Client endpoint type collision: ${endpointTypeName}` }) + } + endpointTypeNames.add(endpointTypeName) + if (typeNames.has(name)) { + throw new GenerationError({ reason: `Client endpoint type collision: ${group.identifier}.${name}` }) + } + typeNames.add(name) + } + const paths = group.endpoints[0]?.topLevel + ? [...new Set(group.endpoints.map((item) => item.clientPath[0]))].map((name) => [name]) + : [[group.identifier]] + for (const path of paths) { + const key = path.join("\0") + for (const existing of publicNames) { + if (existing === key || existing.startsWith(`${key}\0`) || key.startsWith(`${existing}\0`)) { + throw new GenerationError({ reason: `Client name collision: ${path.join(".")}` }) + } + } + publicNames.add(key) } } return { @@ -314,19 +352,24 @@ function renderEffectShape(groups: ReadonlyArray, options: { readonly mod .filter(Boolean) .join("\n") }) - const methods = group.endpoints - .map( - (endpoint) => `readonly ${JSON.stringify(endpoint.operation.name)}: ${groupShapeTypeName(group, endpoint)}`, - ) - .join("\n") + const methods = renderClientTree( + group.endpoints, + (endpoint) => `${groupShapeTypeName(group, endpoint)}`, + (name, value) => `readonly ${JSON.stringify(name)}: ${value}`, + "\n", + ) return `${endpoints.join("\n\n")}\n\nexport interface ${groupShapeName(group)} {\n${methods}\n}` }) const clientFields = groups.flatMap((group) => group.endpoints[0]?.topLevel - ? group.endpoints.map( - (endpoint) => - `readonly ${JSON.stringify(endpoint.operation.name)}: ${groupShapeTypeName(group, endpoint)}`, - ) + ? [ + renderClientTree( + group.endpoints, + (endpoint) => `${groupShapeTypeName(group, endpoint)}`, + (name, value) => `readonly ${JSON.stringify(name)}: ${value}`, + "\n", + ), + ] : [`readonly ${JSON.stringify(group.identifier)}: ${groupShapeName(group)}`], ) return `// Generated by @opencode-ai/httpapi-codegen. Do not edit. @@ -351,7 +394,7 @@ function groupShapeName(group: Group) { } function groupShapeTypeName(group: Group, endpoint: Endpoint) { - return `${identifierPart(group.identifier)}${identifierPart(endpoint.operation.name)}Operation` + return `${identifierPart(group.identifier)}${endpoint.clientPath.map(identifierPart).join("")}Operation` } function assertPromiseEndpoint(endpoint: Endpoint) { @@ -453,7 +496,13 @@ function renderImportedEffectFiles( const mapped = `${rawCall}.pipe(Effect.mapError(mapClientError)${item.unwrapData ? ", Effect.map((value) => value.data)" : ""})` return `${item.operation.inputMode === "none" ? "" : `type ${prefix}Request = Parameters<${rawGroup}[${JSON.stringify(item.endpoint.name)}]>[0]\ntype ${prefix}Input = { ${input} }\n`}const ${prefix} = (raw: ${rawGroup}) => (${argument}) => ${item.operation.success === "stream" ? `Stream.unwrap(${rawCall}.pipe(Effect.mapError(mapClientError), Effect.map((stream) => stream.pipe(Stream.mapError(mapClientError)))))` : mapped}` }) - return `${methods.join("\n\n")}\n\nconst adaptGroup${groupIndex} = (raw: ${rawGroup}) => ({ ${group.endpoints.map((item, endpointIndex) => `${JSON.stringify(item.operation.name)}: Endpoint${groupIndex}_${endpointIndex}(raw)`).join(", ")} })` + const fields = renderClientTree( + group.endpoints, + (_item, endpointIndex) => `Endpoint${groupIndex}_${endpointIndex}(raw)`, + (name, value) => `${JSON.stringify(name)}: ${value}`, + ", ", + ) + return `${methods.join("\n\n")}\n\nconst adaptGroup${groupIndex} = (raw: ${rawGroup}) => ({ ${fields} })` }) const fields = groups.flatMap((group, index) => group.endpoints[0]?.topLevel @@ -548,7 +597,7 @@ function renderPromiseTypes( const operations = groups .flatMap((group) => group.endpoints.flatMap((endpoint) => { - const prefix = promiseTypePrefix(group.identifier, endpoint.operation.name) + const prefix = promiseTypePrefix(group.identifier, endpoint.clientPath) const schemas = { params: endpoint.params, query: endpoint.query, @@ -566,7 +615,7 @@ function renderPromiseTypes( .join("; ") const successSchema = endpoint.successes[0] const success = - outputTypes?.[`${group.identifier}.${endpoint.operation.name}`]?.name ?? + outputTypes?.[clientOperationKey(group, endpoint)]?.name ?? typeOf( isStreamSchema(successSchema) && successSchema._tag === "StreamSse" ? successSchema.sseMode === "data" @@ -591,13 +640,13 @@ function renderPromiseTypes( function renderPromiseClient(groups: ReadonlyArray) { const imports = groups.flatMap((group) => group.endpoints.flatMap((endpoint) => { - const prefix = promiseTypePrefix(group.identifier, endpoint.operation.name) + const prefix = promiseTypePrefix(group.identifier, endpoint.clientPath) return [...(promiseInputMode(endpoint) === "none" ? [] : [`${prefix}Input`]), `${prefix}Output`] }), ) const fields = groups.map((group) => { const methods = group.endpoints.map((endpoint) => { - const prefix = promiseTypePrefix(group.identifier, endpoint.operation.name) + const prefix = promiseTypePrefix(group.identifier, endpoint.clientPath) const inputMode = promiseInputMode(endpoint) const argument = inputMode === "none" @@ -625,25 +674,91 @@ function renderPromiseClient(groups: ReadonlyArray) { reason: `Promise stream emission is not implemented: ${group.identifier}.${endpoint.endpoint.name}`, }) } - return `${JSON.stringify(endpoint.operation.name)}: (${argument}): AsyncIterable<${prefix}Output> => sse<${prefix}Output>(${descriptor}, requestOptions)` + return `(${argument}): AsyncIterable<${prefix}Output> => sse<${prefix}Output>(${descriptor}, requestOptions)` } const unwrap = endpoint.unwrapData ? ".then((value) => value.data)" : "" - return `${JSON.stringify(endpoint.operation.name)}: (${argument}) => request<${endpoint.unwrapData ? `{ readonly data: ${prefix}Output }` : `${prefix}Output`}>(${descriptor}, requestOptions)${unwrap}` + return `(${argument}) => request<${endpoint.unwrapData ? `{ readonly data: ${prefix}Output }` : `${prefix}Output`}>(${descriptor}, requestOptions)${unwrap}` }) - if (group.endpoints[0]?.topLevel) return methods.join(", ") - return `${JSON.stringify(group.identifier)}: { ${methods.join(", ")} }` + const fields = renderClientTree( + group.endpoints, + (_endpoint, endpointIndex) => methods[endpointIndex], + (name, value) => `${JSON.stringify(name)}: ${value}`, + ", ", + ) + if (group.endpoints[0]?.topLevel) return fields + return `${JSON.stringify(group.identifier)}: { ${fields} }` }) return `import type { ${imports.join(", ")} } from "./types"\nimport { ClientError } from "./client-error"\n\nexport interface ClientOptions {\n readonly baseUrl: string\n readonly fetch?: typeof globalThis.fetch\n readonly headers?: HeadersInit\n}\n\nexport interface RequestOptions {\n readonly signal?: AbortSignal\n readonly headers?: HeadersInit\n}\n\ninterface RequestDescriptor {\n readonly method: string\n readonly path: string\n readonly query?: Record\n readonly headers?: Record\n readonly body?: unknown\n readonly successStatus: number\n readonly declaredStatuses: ReadonlyArray\n readonly empty: boolean\n}\n\nexport function make(options: ClientOptions) {\n const fetch = options.fetch ?? globalThis.fetch\n\n const prepare = (descriptor: RequestDescriptor, requestOptions?: RequestOptions) => {\n const url = new URL(descriptor.path, options.baseUrl)\n for (const [key, value] of Object.entries(descriptor.query ?? {})) appendQuery(url.searchParams, key, value)\n const headers = new Headers(options.headers)\n for (const [key, value] of Object.entries(descriptor.headers ?? {})) {\n if (value !== undefined && value !== null) headers.set(key, String(value))\n }\n for (const [key, value] of new Headers(requestOptions?.headers)) headers.set(key, value)\n if (descriptor.body !== undefined && !headers.has("content-type")) headers.set("content-type", "application/json")\n return {\n url,\n init: {\n method: descriptor.method,\n signal: requestOptions?.signal,\n headers,\n body: descriptor.body === undefined ? undefined : JSON.stringify(descriptor.body),\n } satisfies RequestInit,\n }\n }\n\n const execute = async (descriptor: RequestDescriptor, requestOptions?: RequestOptions) => {\n try {\n const prepared = prepare(descriptor, requestOptions)\n return await fetch(prepared.url, prepared.init)\n } catch (cause) {\n throw new ClientError("Transport", { cause })\n }\n }\n\n const responseError = async (response: Response, descriptor: RequestDescriptor): Promise => {\n if (descriptor.declaredStatuses.includes(response.status)) throw await json(response)\n try {\n await response.body?.cancel()\n } catch {}\n throw new ClientError("UnexpectedStatus", { cause: { status: response.status } })\n }\n\n const request = async (descriptor: RequestDescriptor, requestOptions?: RequestOptions): Promise => {\n const response = await execute(descriptor, requestOptions)\n if (response.status !== descriptor.successStatus) return responseError(response, descriptor)\n if (descriptor.empty) {\n try {\n await response.body?.cancel()\n } catch {}\n return undefined as A\n }\n return await json(response) as A\n }\n\n const sse = (descriptor: RequestDescriptor, requestOptions?: RequestOptions): AsyncIterable => ({\n async *[Symbol.asyncIterator]() {\n const response = await execute(descriptor, requestOptions)\n if (response.status !== descriptor.successStatus) await responseError(response, descriptor)\n if (!isContentType(response, "text/event-stream")) {\n try {\n await response.body?.cancel()\n } catch {}\n throw new ClientError("UnsupportedContentType")\n }\n if (response.body === null) throw new ClientError("MalformedResponse")\n const reader = response.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ""\n try {\n while (true) {\n let next: ReadableStreamReadResult\n try {\n next = await reader.read()\n } catch (cause) {\n throw new ClientError("Transport", { cause })\n }\n buffer += decoder.decode(next.value, { stream: !next.done })\n if (buffer.length > 1_048_576) throw new ClientError("MalformedResponse")\n const trailingCarriageReturn = !next.done && buffer.endsWith("\\r")\n if (trailingCarriageReturn) buffer = buffer.slice(0, -1)\n buffer = buffer.replaceAll("\\r\\n", "\\n").replaceAll("\\r", "\\n")\n if (trailingCarriageReturn) buffer += "\\r"\n if (next.done && buffer !== "") buffer += "\\n\\n"\n let boundary = buffer.indexOf("\\n\\n")\n while (boundary >= 0) {\n const block = buffer.slice(0, boundary)\n buffer = buffer.slice(boundary + 2)\n const data = block.split("\\n").flatMap((line) => line.startsWith("data:") ? [line.slice(5).trimStart()] : []).join("\\n")\n if (data !== "") {\n try {\n yield JSON.parse(data) as A\n } catch (cause) {\n throw new ClientError("MalformedResponse", { cause })\n }\n }\n boundary = buffer.indexOf("\\n\\n")\n }\n if (next.done) return\n }\n } finally {\n try {\n await reader.cancel()\n } catch {}\n reader.releaseLock()\n }\n },\n })\n\n return { ${fields.join(", ")} }\n}\n\nfunction appendQuery(params: URLSearchParams, key: string, value: unknown): void {\n if (value === undefined) return\n if (value === null) {\n params.append(key, "null")\n return\n }\n if (Array.isArray(value)) {\n for (const item of value) appendQuery(params, key, item)\n return\n }\n if (typeof value === "object") {\n for (const [child, item] of Object.entries(value)) appendQuery(params, \`\${key}[\${child}]\`, item)\n return\n }\n params.append(key, String(value))\n}\n\nasync function json(response: Response): Promise {\n if (!isContentType(response, "application/json") && !response.headers.get("content-type")?.includes("+json")) {\n try {\n await response.body?.cancel()\n } catch {}\n throw new ClientError("UnsupportedContentType")\n }\n let text: string\n try {\n text = await response.text()\n } catch (cause) {\n throw new ClientError("Transport", { cause })\n }\n if (text === "") throw new ClientError("MalformedResponse")\n try {\n return JSON.parse(text)\n } catch (cause) {\n throw new ClientError("MalformedResponse", { cause })\n }\n}\n\nfunction isContentType(response: Response, expected: string) {\n return response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase() === expected\n}\n` } -function promiseTypePrefix(group: string, endpoint: string) { - return `${identifierPart(group)}${identifierPart(endpoint)}` +function promiseTypePrefix(group: string, path: ReadonlyArray) { + return `${identifierPart(group)}${path.map(identifierPart).join("")}` +} + +function clientOperationKey(group: Group, endpoint: Endpoint) { + return [group.identifier, ...endpoint.clientPath].join(".") } function clientEndpointName(name: string) { return name.slice(name.lastIndexOf(".") + 1) } +function normalizeClientPath(path: EndpointName) { + const result = typeof path === "string" ? [path] : [...path] + if (result.length === 0 || result.some((part) => part.length === 0)) { + throw new GenerationError({ reason: "Client endpoint path must contain non-empty names" }) + } + if (result.some((part) => part === "__proto__")) { + throw new GenerationError({ reason: "Client endpoint path cannot contain __proto__" }) + } + if (typeof path !== "string" && result.some((part) => part.includes("."))) { + throw new GenerationError({ reason: "Nested client endpoint path segments cannot contain dots" }) + } + return result as [string, ...Array] +} + +function assertUniqueClientPaths( + paths: ReadonlyArray>, + reason: (path: ReadonlyArray) => string, +) { + const seen = new Set() + for (const path of paths) { + const key = path.join("\0") + for (const existing of seen) { + if (existing === key || existing.startsWith(`${key}\0`) || key.startsWith(`${existing}\0`)) { + throw new GenerationError({ reason: reason(path) }) + } + } + seen.add(key) + } +} + +function renderClientTree( + endpoints: ReadonlyArray, + leaf: (endpoint: Endpoint, index: number) => string, + field: (name: string, value: string) => string, + separator: string, +) { + type Node = { endpoint?: { readonly value: Endpoint; readonly index: number }; readonly children: Map } + const root: Node = { children: new Map() } + endpoints.forEach((endpoint, index) => { + const node = endpoint.clientPath.reduce((parent, name) => { + const child: Node = parent.children.get(name) ?? { children: new Map() } + parent.children.set(name, child) + return child + }, root) + node.endpoint = { value: endpoint, index } + }) + const render = (node: Node): string => + Array.from(node.children, ([name, child]) => + field( + name, + child.endpoint === undefined ? `{ ${render(child)} }` : leaf(child.endpoint.value, child.endpoint.index), + ), + ).join(separator) + return render(root) +} + function identifierPart(value: string) { return value .split(/[^A-Za-z0-9]+/) @@ -1266,9 +1381,12 @@ function renderGroup(group: Group, groupIndex: number) { const declarations = renderSchemas(slots) const groupSource = `HttpApiGroup.make(${JSON.stringify(group.identifier)}, { topLevel: ${group.endpoints[0]?.topLevel ?? false} })${endpointSources.map((endpoint) => `.add(${endpoint})`).join("")}` const usesHttpApiSchema = endpointSources.some((source) => source.includes("HttpApiSchema.")) - const methods = group.endpoints - .map((item, index) => `${JSON.stringify(item.operation.name)}: Endpoint${index}(raw)`) - .join(", ") + const methods = renderClientTree( + group.endpoints, + (_item, index) => `Endpoint${index}(raw)`, + (name, value) => `${JSON.stringify(name)}: ${value}`, + ", ", + ) const rawGroup = group.endpoints[0]?.topLevel ? `HttpApiClient.Client` : `HttpApiClient.Client.Group` diff --git a/packages/httpapi-codegen/test/generate.test.ts b/packages/httpapi-codegen/test/generate.test.ts index 4ee5749b1d6..f6a55e73a0d 100644 --- a/packages/httpapi-codegen/test/generate.test.ts +++ b/packages/httpapi-codegen/test/generate.test.ts @@ -9,6 +9,7 @@ import { compile as compileContract, emitEffect, emitEffectImported, + emitEffectShape, emitPromise, generate, GenerationError, @@ -151,6 +152,201 @@ describe("HttpApiCodegen.generate", () => { expect(contract.groups[0]?.endpoints.map((endpoint) => endpoint.operation.name)).toEqual(["listRequests", "list"]) }) + test("supports explicit nested endpoint paths while string aliases remain flat", () => { + const source = HttpApi.make("test").add( + HttpApiGroup.make("server.session") + .add(HttpApiEndpoint.get("session.instructions.list", "/session/instructions", { success: Schema.String })) + .add(HttpApiEndpoint.put("session.instructions.put", "/session/instructions", { success: Schema.String })) + .add(HttpApiEndpoint.delete("session.instructions.remove", "/session/instructions", { success: Schema.String })) + .add(HttpApiEndpoint.get("session.messages", "/session/message", { success: Schema.String })), + ) + const contract = compileContract(source, { + groupNames: { "server.session": "session" }, + endpointNames: { + "session.instructions.list": ["instructions", "list"], + "session.instructions.put": ["instructions", "put"], + "session.instructions.remove": ["instructions", "remove"], + "session.messages": "instructions.flat", + }, + }) + + expect(contract.groups[0]?.endpoints.map((endpoint) => endpoint.clientPath)).toEqual([ + ["instructions", "list"], + ["instructions", "put"], + ["instructions", "remove"], + ["instructions.flat"], + ]) + expect(contract.groups[0]?.endpoints.map((endpoint) => endpoint.operation.name)).toEqual([ + "instructions.list", + "instructions.put", + "instructions.remove", + "instructions.flat", + ]) + + const promise = emitPromise(contract, { + outputTypes: { + "session.instructions.list": { + name: "InstructionListWire", + import: 'import type { InstructionListWire } from "./instruction-list-wire"', + }, + }, + }) + const promiseClient = promise.files.find((file) => file.path === "client.ts")?.content + const promiseTypes = promise.files.find((file) => file.path === "types.ts")?.content + expect(promiseClient).toContain('"session": { "instructions": { "list": (requestOptions?: RequestOptions)') + expect(promiseClient).toContain('"put": (requestOptions?: RequestOptions)') + expect(promiseClient).toContain('"remove": (requestOptions?: RequestOptions)') + expect(promiseClient).toContain('"instructions.flat": (requestOptions?: RequestOptions)') + expect(promiseTypes).toContain('import type { InstructionListWire } from "./instruction-list-wire"') + expect(promiseTypes).toContain("export type SessionInstructionsListOutput = InstructionListWire") + expect(promiseTypes).toContain("export type SessionInstructionsPutOutput = string") + expect(promiseTypes).toContain("export type SessionInstructionsRemoveOutput = string") + + const effect = emitEffect(contract) + expect(effect.files.find((file) => file.path === "session.ts")?.content).toContain( + '"instructions": { "list": Endpoint0(raw), "put": Endpoint1(raw), "remove": Endpoint2(raw) }, "instructions.flat": Endpoint3(raw)', + ) + + const imported = emitEffectImported(contract, { module: "@example/api", api: "Api" }) + expect(imported.files.find((file) => file.path === "client.ts")?.content).toContain( + '"instructions": { "list": Endpoint0_0(raw), "put": Endpoint0_1(raw), "remove": Endpoint0_2(raw) }, "instructions.flat": Endpoint0_3(raw)', + ) + + const shape = emitEffectShape(contract, { module: "@example/api", api: "Api" }) + const apiShape = shape.files.find((file) => file.path === "api.ts")?.content + expect(apiShape).toContain('readonly "instructions": { readonly "list": SessionInstructionsListOperation') + expect(apiShape).toContain('readonly "put": SessionInstructionsPutOperation') + expect(apiShape).toContain('readonly "remove": SessionInstructionsRemoveOperation') + expect(apiShape).toContain('readonly "instructions.flat": SessionInstructionsFlatOperation') + }) + + test("executes nested Promise endpoint aliases", async () => { + const source = HttpApi.make("test").add( + HttpApiGroup.make("session") + .add(HttpApiEndpoint.get("instructions.list", "/session/instructions", { success: Schema.String })) + .add(HttpApiEndpoint.put("instructions.put", "/session/instructions", { success: Schema.String })) + .add(HttpApiEndpoint.delete("instructions.remove", "/session/instructions", { success: Schema.String })), + ) + const output = emitPromise( + compileContract(source, { + endpointNames: { + "instructions.list": ["instructions", "list"], + "instructions.put": ["instructions", "put"], + "instructions.remove": ["instructions", "remove"], + }, + }), + ) + const directory = await mkdtemp(join(tmpdir(), "opencode-httpapi-codegen-")) + const methods: Array = [] + + try { + await Promise.all(output.files.map((file) => Bun.write(join(directory, file.path), file.content))) + const generated = await import(`${join(directory, "index.ts")}?t=${crypto.randomUUID()}`) + const client = generated.OpenCode.make({ + baseUrl: "https://example.com", + fetch: async (_input: RequestInfo | URL, init?: RequestInit) => { + methods.push(init?.method ?? "GET") + return Response.json("ok") + }, + }) + + expect(await client.session.instructions.list()).toBe("ok") + expect(await client.session.instructions.put()).toBe("ok") + expect(await client.session.instructions.remove()).toBe("ok") + expect(methods).toEqual(["GET", "PUT", "DELETE"]) + } finally { + await rm(directory, { recursive: true, force: true }) + } + }) + + test("rejects duplicate and leaf-namespace endpoint paths", () => { + const source = HttpApi.make("test").add( + HttpApiGroup.make("session") + .add(HttpApiEndpoint.get("first", "/first", { success: Schema.String })) + .add(HttpApiEndpoint.get("second", "/second", { success: Schema.String })), + ) + + expect(() => + compileContract(source, { endpointNames: { first: ["instructions", "list"], second: ["instructions", "list"] } }), + ).toThrow("Client endpoint name collision: session.instructions.list") + expect(() => + compileContract(source, { endpointNames: { first: "instructions", second: ["instructions", "list"] } }), + ).toThrow("Client endpoint name collision: session.instructions.list") + }) + + test("rejects nested root collisions across top-level groups", () => { + const source = HttpApi.make("test") + .add( + HttpApiGroup.make("first", { topLevel: true }).add( + HttpApiEndpoint.get("first.list", "/first", { success: Schema.String }), + ), + ) + .add( + HttpApiGroup.make("second", { topLevel: true }).add( + HttpApiEndpoint.get("second.put", "/second", { success: Schema.String }), + ), + ) + + expect(() => + compileContract(source, { + endpointNames: { "first.list": ["instructions", "list"], "second.put": ["instructions", "put"] }, + }), + ).toThrow("Client name collision: instructions") + }) + + test("rejects nested paths that collide after type-name normalization", () => { + const source = HttpApi.make("test").add( + HttpApiGroup.make("session") + .add(HttpApiEndpoint.get("first", "/first", { success: Schema.String })) + .add(HttpApiEndpoint.get("second", "/second", { success: Schema.String })), + ) + + expect(() => compileContract(source, { endpointNames: { first: ["foo", "bar"], second: "foo-bar" } })).toThrow( + "Client endpoint type collision: SessionFooBar", + ) + }) + + test("rejects ambiguous and prototype-mutating nested path segments", () => { + const source = api(HttpApiEndpoint.get("get", "/session", { success: Schema.String })) + + expect(() => compileContract(source, { endpointNames: { get: ["a.b", "get"] } })).toThrow( + "Nested client endpoint path segments cannot contain dots", + ) + expect(() => compileContract(source, { endpointNames: { get: ["__proto__", "get"] } })).toThrow( + "Client endpoint path cannot contain __proto__", + ) + }) + + test("rejects normalized group, operation-key, and group prototype collisions", () => { + const normalized = HttpApi.make("test") + .add(HttpApiGroup.make("foo-bar").add(HttpApiEndpoint.get("get", "/first", { success: Schema.String }))) + .add(HttpApiGroup.make("foo.bar").add(HttpApiEndpoint.get("get", "/second", { success: Schema.String }))) + expect(() => compileContract(normalized)).toThrow("Client group type collision: FooBar") + + const endpointType = HttpApi.make("test") + .add(HttpApiGroup.make("foo").add(HttpApiEndpoint.get("first", "/first", { success: Schema.String }))) + .add(HttpApiGroup.make("fooBar").add(HttpApiEndpoint.get("second", "/second", { success: Schema.String }))) + expect(() => + compileContract(endpointType, { + endpointNames: { first: ["bar", "baz"], second: ["baz"] }, + }), + ).toThrow("Client endpoint type collision: FooBarBaz") + + const operationKey = HttpApi.make("test") + .add(HttpApiGroup.make("a.b").add(HttpApiEndpoint.get("get", "/first", { success: Schema.String }))) + .add(HttpApiGroup.make("a").add(HttpApiEndpoint.get("b.c", "/second", { success: Schema.String }))) + expect(() => compileContract(operationKey, { endpointNames: { get: "c", "b.c": ["b", "c"] } })).toThrow( + "Client operation key collision: a.b.c", + ) + + const prototype = HttpApi.make("test").add( + HttpApiGroup.make("session").add(HttpApiEndpoint.get("get", "/session", { success: Schema.String })), + ) + expect(() => compileContract(prototype, { groupNames: { session: "__proto__" } })).toThrow( + "Client group name cannot be __proto__", + ) + }) + test("omits custom transport endpoints", () => { const source = HttpApi.make("test").add( HttpApiGroup.make("server.pty") @@ -358,22 +554,6 @@ describe("HttpApiCodegen.generate", () => { emitPromise(compileContract(api(HttpApiEndpoint.get("read", "/file/*/tail", { success: Schema.String })))), ).toThrow("Unsupported Promise path wildcard: /file/*/tail") - expect(() => - emitPromise( - compileContract( - api( - HttpApiEndpoint.get("binary", "/binary", { - success: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()), - }), - ), - ), - ), - ).toThrow("Unsupported Promise success encoding: session.binary") - - expect(() => - emitPromise(compileContract(api(HttpApiEndpoint.get("read", "/file/*", { success: Schema.String })))), - ).toThrow("Unsupported Promise path wildcard: /file/*") - expect(() => emitPromise( compileContract( diff --git a/packages/protocol/src/client.ts b/packages/protocol/src/client.ts index 3d2993a02bf..1abf6667966 100644 --- a/packages/protocol/src/client.ts +++ b/packages/protocol/src/client.ts @@ -67,9 +67,9 @@ export const endpointNames = { "integration.attempt.status": "attemptStatus", "integration.attempt.complete": "attemptComplete", "integration.attempt.cancel": "attemptCancel", - "session.context.entry.list": "listContextEntries", - "session.context.entry.put": "putContextEntry", - "session.context.entry.remove": "removeContextEntry", + "session.instructions.entry.list": ["instructions", "entry", "list"], + "session.instructions.entry.put": ["instructions", "entry", "put"], + "session.instructions.entry.remove": ["instructions", "entry", "remove"], "session.revert.stage": "revertStage", "session.revert.clear": "revertClear", "session.revert.commit": "revertCommit", diff --git a/packages/protocol/src/groups/session.ts b/packages/protocol/src/groups/session.ts index 3d82cd3297d..4e2cc5dd9bb 100644 --- a/packages/protocol/src/groups/session.ts +++ b/packages/protocol/src/groups/session.ts @@ -2,7 +2,7 @@ import { SessionMessage } from "@opencode-ai/schema/session-message" import { SessionInput } from "@opencode-ai/schema/session-input" import { PromptInput } from "@opencode-ai/schema/prompt-input" import { Session } from "@opencode-ai/schema/session" -import { SessionContextEntry } from "@opencode-ai/schema/session-context-entry" +import { InstructionEntry } from "@opencode-ai/schema/instruction-entry" import { Project } from "@opencode-ai/schema/project" import { AbsolutePath, PositiveInt, RelativePath, statics } from "@opencode-ai/schema/schema" import { Event } from "@opencode-ai/schema/event" @@ -444,23 +444,23 @@ export const makeSessionGroup = (sessionLo ), ) .add( - HttpApiEndpoint.get("session.context.entry.list", "/api/session/:sessionID/context-entry", { + HttpApiEndpoint.get("session.instructions.entry.list", "/api/session/:sessionID/instructions/entries", { params: { sessionID: Session.ID }, - success: Schema.Struct({ data: Schema.Array(SessionContextEntry.Info) }), + success: Schema.Struct({ data: Schema.Array(InstructionEntry.Info) }), error: SessionNotFoundError, }) .middleware(sessionLocationMiddleware) .annotateMerge( OpenApi.annotations({ - identifier: "v2.session.context.entry.list", - summary: "List context entries", - description: "List API-managed context entries attached to the session's system context.", + identifier: "v2.session.instructions.entry.list", + summary: "List instruction entries", + description: "List API-managed instruction entries attached to the session.", }), ), ) .add( - HttpApiEndpoint.put("session.context.entry.put", "/api/session/:sessionID/context-entry/:key", { - params: { sessionID: Session.ID, key: SessionContextEntry.Key }, + HttpApiEndpoint.put("session.instructions.entry.put", "/api/session/:sessionID/instructions/entries/:key", { + params: { sessionID: Session.ID, key: InstructionEntry.Key }, payload: Schema.Struct({ value: Schema.Json }), success: HttpApiSchema.NoContent, error: SessionNotFoundError, @@ -468,25 +468,26 @@ export const makeSessionGroup = (sessionLo .middleware(sessionLocationMiddleware) .annotateMerge( OpenApi.annotations({ - identifier: "v2.session.context.entry.put", - summary: "Put context entry", + identifier: "v2.session.instructions.entry.put", + summary: "Put instruction entry", description: - "Attach or replace one durable context entry. The value is rendered into the session's system context; changes announce as updates at the next turn boundary.", + "Attach or replace one durable instruction entry. Changes announce as updates at the next step boundary.", }), ), ) .add( - HttpApiEndpoint.delete("session.context.entry.remove", "/api/session/:sessionID/context-entry/:key", { - params: { sessionID: Session.ID, key: SessionContextEntry.Key }, + HttpApiEndpoint.delete("session.instructions.entry.remove", "/api/session/:sessionID/instructions/entries/:key", { + params: { sessionID: Session.ID, key: InstructionEntry.Key }, success: HttpApiSchema.NoContent, error: SessionNotFoundError, }) .middleware(sessionLocationMiddleware) .annotateMerge( OpenApi.annotations({ - identifier: "v2.session.context.entry.remove", - summary: "Remove context entry", - description: "Remove one context entry; the removal is announced to the model at the next turn boundary.", + identifier: "v2.session.instructions.entry.remove", + summary: "Remove instruction entry", + description: + "Remove one instruction entry; the removal is announced to the model at the next step boundary.", }), ), ) diff --git a/packages/schema/src/instruction-entry.ts b/packages/schema/src/instruction-entry.ts new file mode 100644 index 00000000000..09c7e39de18 --- /dev/null +++ b/packages/schema/src/instruction-entry.ts @@ -0,0 +1,20 @@ +export * as InstructionEntry from "./instruction-entry.js" + +import { Schema } from "effect" + +/** + * Slash-free client-facing key for one API-managed instruction entry. The server + * derives the namespaced Instructions key as `api/`, keeping the + * `api/*` namespace enforced by construction. + */ +export const Key = Schema.String.check(Schema.isPattern(/^[a-z0-9][a-z0-9._-]*$/)).annotate({ + identifier: "InstructionEntry.Key", + description: "Instruction entry key (lowercase alphanumerics plus . _ -)", +}) +export type Key = typeof Key.Type + +export const Info = Schema.Struct({ + key: Key, + value: Schema.Json.annotate({ description: "JSON value attached to the session's instructions" }), +}).annotate({ identifier: "InstructionEntry.Info" }) +export interface Info extends Schema.Schema.Type {} diff --git a/packages/schema/src/session-context-entry.ts b/packages/schema/src/session-context-entry.ts deleted file mode 100644 index fbaeb530628..00000000000 --- a/packages/schema/src/session-context-entry.ts +++ /dev/null @@ -1,20 +0,0 @@ -export * as SessionContextEntry from "./session-context-entry.js" - -import { Schema } from "effect" - -/** - * Slash-free client-facing key for one API-managed context entry. The server - * derives the namespaced SystemContext key as `api/`, keeping the - * `api/*` namespace enforced by construction. - */ -export const Key = Schema.String.check(Schema.isPattern(/^[a-z0-9][a-z0-9._-]*$/)).annotate({ - identifier: "SessionContextEntry.Key", - description: "Context entry key (lowercase alphanumerics plus . _ -)", -}) -export type Key = typeof Key.Type - -export const Info = Schema.Struct({ - key: Key, - value: Schema.Json.annotate({ description: "JSON value attached to the session's system context" }), -}).annotate({ identifier: "SessionContextEntry.Info" }) -export interface Info extends Schema.Schema.Type {} diff --git a/packages/schema/src/session-event.ts b/packages/schema/src/session-event.ts index 824b1690db2..c79b0da7462 100644 --- a/packages/schema/src/session-event.ts +++ b/packages/schema/src/session-event.ts @@ -130,15 +130,15 @@ export const ExecutionSettled = Event.ephemeral({ }) export type ExecutionSettled = typeof ExecutionSettled.Type -export const ContextUpdated = Event.durable({ - type: "session.context.updated", +export const InstructionsUpdated = Event.durable({ + type: "session.instructions.updated", ...options, schema: { ...Base, text: Schema.String, }, }) -export type ContextUpdated = typeof ContextUpdated.Type +export type InstructionsUpdated = typeof InstructionsUpdated.Type export const Synthetic = Event.durable({ type: "session.synthetic", @@ -494,7 +494,7 @@ export const Definitions = Event.inventory( PromptPromoted, PromptAdmitted, ExecutionSettled, - ContextUpdated, + InstructionsUpdated, Synthetic, Skill.Activated, Shell.Started, diff --git a/packages/schema/test/event-manifest.test.ts b/packages/schema/test/event-manifest.test.ts index da344ba5289..51400b2e39f 100644 --- a/packages/schema/test/event-manifest.test.ts +++ b/packages/schema/test/event-manifest.test.ts @@ -104,7 +104,8 @@ describe("public event manifest", () => { "session.forked.1", "session.prompt.promoted.1", "session.prompt.admitted.1", - "session.context.updated.1", + + "session.instructions.updated.1", "session.synthetic.1", "session.skill.activated.1", "session.shell.started.1", diff --git a/packages/sdk-next/test/embedded.test.ts b/packages/sdk-next/test/embedded.test.ts index 72edfdbc91e..cd9cd6a50dc 100644 --- a/packages/sdk-next/test/embedded.test.ts +++ b/packages/sdk-next/test/embedded.test.ts @@ -185,11 +185,11 @@ it.live( resume: false, }) const context = yield* opencode.sessions.context({ sessionID: id }) - yield* opencode.sessions.putContextEntry({ sessionID: id, key: "deploy-target", value: "production" }) - yield* opencode.sessions.putContextEntry({ sessionID: id, key: "flags", value: { beta: true } }) - const contextEntries = yield* opencode.sessions.listContextEntries({ sessionID: id }) - yield* opencode.sessions.removeContextEntry({ sessionID: id, key: "flags" }) - const remainingContextEntries = yield* opencode.sessions.listContextEntries({ sessionID: id }) + yield* opencode.sessions.instructions.entry.put({ sessionID: id, key: "deploy-target", value: "production" }) + yield* opencode.sessions.instructions.entry.put({ sessionID: id, key: "flags", value: { beta: true } }) + const contextEntries = yield* opencode.sessions.instructions.entry.list({ sessionID: id }) + yield* opencode.sessions.instructions.entry.remove({ sessionID: id, key: "flags" }) + const remainingContextEntries = yield* opencode.sessions.instructions.entry.list({ sessionID: id }) const wake = yield* opencode.sessions.prompt({ sessionID: id, prompt: fixture.sdk.Prompt.make({ text: "Promote this input" }), @@ -219,7 +219,7 @@ it.live( opencode.sessions.log({ sessionID: missingSessionID }).pipe(Stream.runHead, Effect.flip), opencode.sessions.interrupt({ sessionID: missingSessionID }).pipe(Effect.flip), opencode.sessions.message({ sessionID: missingSessionID, messageID: modelMessage.id }).pipe(Effect.flip), - opencode.sessions.listContextEntries({ sessionID: missingSessionID }).pipe(Effect.flip), + opencode.sessions.instructions.entry.list({ sessionID: missingSessionID }).pipe(Effect.flip), ], { concurrency: "unbounded" }, ) diff --git a/packages/sdk/js/script/build.ts b/packages/sdk/js/script/build.ts index 220bf43da3c..fdc1d76bc62 100755 --- a/packages/sdk/js/script/build.ts +++ b/packages/sdk/js/script/build.ts @@ -60,7 +60,7 @@ if (schemas) { visit({ ...document, components: { ...document.components, schemas: undefined } }) for (const name of Object.keys(schemas)) { if ( - /^(SessionAgentSelected|SessionModelSelected|SessionMoved|SessionRenamed|SessionForked|SessionPromptPromoted|SessionPromptAdmitted|SessionExecutionSettled|SessionContextUpdated|SessionSynthetic|SessionSkillActivated|SessionShellStarted|SessionShellEnded|SessionStepStarted|SessionStepEnded|SessionStepFailed|SessionTextStarted|SessionTextDelta|SessionTextEnded|SessionReasoningStarted|SessionReasoningDelta|SessionReasoningEnded|SessionToolInputStarted|SessionToolInputDelta|SessionToolInputEnded|SessionToolCalled|SessionToolProgress|SessionToolSuccess|SessionToolFailed|SessionRetried|SessionCompactionStarted|SessionCompactionDelta|SessionCompactionEnded|SessionRevertStaged|SessionRevertCleared|SessionRevertCommitted)1$/.test( + /^(SessionAgentSelected|SessionModelSelected|SessionMoved|SessionRenamed|SessionForked|SessionPromptPromoted|SessionPromptAdmitted|SessionExecutionSettled|SessionInstructionsUpdated|SessionSynthetic|SessionSkillActivated|SessionShellStarted|SessionShellEnded|SessionStepStarted|SessionStepEnded|SessionStepFailed|SessionTextStarted|SessionTextDelta|SessionTextEnded|SessionToolInputStarted|SessionToolInputDelta|SessionToolInputEnded|SessionToolCalled|SessionToolProgress|SessionToolSuccess|SessionToolFailed|SessionRetried|SessionCompactionStarted|SessionCompactionDelta|SessionCompactionEnded|SessionRevertStaged|SessionRevertCleared|SessionRevertCommitted)1$/.test( name, ) && !reachable.has(name) @@ -100,7 +100,7 @@ await createClient({ const generatedTypesPath = "./src/v2/gen/types.gen.ts" const generatedTypes = await Bun.file(generatedTypesPath).text() if ( - /export type (SessionAgentSelected|SessionModelSelected|SessionMoved|SessionRenamed|SessionForked|SessionPromptPromoted|SessionPromptAdmitted|SessionExecutionSettled|SessionContextUpdated|SessionSynthetic|SessionSkillActivated|SessionShellStarted|SessionShellEnded|SessionStepStarted|SessionStepEnded|SessionStepFailed|SessionTextStarted|SessionTextDelta|SessionTextEnded|SessionReasoningStarted|SessionReasoningDelta|SessionReasoningEnded|SessionToolInputStarted|SessionToolInputDelta|SessionToolInputEnded|SessionToolCalled|SessionToolProgress|SessionToolSuccess|SessionToolFailed|SessionRetried|SessionCompactionStarted|SessionCompactionDelta|SessionCompactionEnded|SessionRevertStaged|SessionRevertCleared|SessionRevertCommitted)1 =/.test( + /export type (SessionAgentSelected|SessionModelSelected|SessionMoved|SessionRenamed|SessionForked|SessionPromptPromoted|SessionPromptAdmitted|SessionExecutionSettled|SessionInstructionsUpdated|SessionSynthetic|SessionSkillActivated|SessionShellStarted|SessionShellEnded|SessionStepStarted|SessionStepEnded|SessionStepFailed|SessionTextStarted|SessionTextDelta|SessionTextEnded|SessionToolInputStarted|SessionToolInputDelta|SessionToolInputEnded|SessionToolCalled|SessionToolProgress|SessionToolSuccess|SessionToolFailed|SessionRetried|SessionCompactionStarted|SessionCompactionDelta|SessionCompactionEnded|SessionRevertStaged|SessionRevertCleared|SessionRevertCommitted)1 =/.test( generatedTypes, ) ) { diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index 2243f8e89db..67fd49d378c 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -92,6 +92,7 @@ import type { GlobalUpgradeResponses, InstanceDisposeErrors, InstanceDisposeResponses, + InstructionEntryKey2, LocationRef2, LspStatusErrors, LspStatusResponses, @@ -185,7 +186,6 @@ import type { SessionChildrenResponses, SessionCommandErrors, SessionCommandResponses, - SessionContextEntryKey2, SessionCreateErrors, SessionCreateResponses, SessionDeleteErrors, @@ -364,12 +364,6 @@ import type { V2SessionCommandResponses, V2SessionCompactErrors, V2SessionCompactResponses, - V2SessionContextEntryListErrors, - V2SessionContextEntryListResponses, - V2SessionContextEntryPutErrors, - V2SessionContextEntryPutResponses, - V2SessionContextEntryRemoveErrors, - V2SessionContextEntryRemoveResponses, V2SessionContextErrors, V2SessionContextResponses, V2SessionCreateErrors, @@ -390,6 +384,12 @@ import type { V2SessionFormStateResponses, V2SessionGetErrors, V2SessionGetResponses, + V2SessionInstructionsEntryListErrors, + V2SessionInstructionsEntryListResponses, + V2SessionInstructionsEntryPutErrors, + V2SessionInstructionsEntryPutResponses, + V2SessionInstructionsEntryRemoveErrors, + V2SessionInstructionsEntryRemoveResponses, V2SessionInterruptErrors, V2SessionInterruptResponses, V2SessionListErrors, @@ -5262,9 +5262,9 @@ export class Revert extends HeyApiClient { export class Entry extends HeyApiClient { /** - * List context entries + * List instruction entries * - * List API-managed context entries attached to the session's system context. + * List API-managed instruction entries attached to the session. */ public list( parameters: { @@ -5274,25 +5274,25 @@ export class Entry extends HeyApiClient { ) { const params = buildClientParams([parameters], [{ args: [{ in: "path", key: "sessionID" }] }]) return (options?.client ?? this.client).get< - V2SessionContextEntryListResponses, - V2SessionContextEntryListErrors, + V2SessionInstructionsEntryListResponses, + V2SessionInstructionsEntryListErrors, ThrowOnError >({ - url: "/api/session/{sessionID}/context-entry", + url: "/api/session/{sessionID}/instructions/entries", ...options, ...params, }) } /** - * Remove context entry + * Remove instruction entry * - * Remove one context entry; the removal is announced to the model at the next turn boundary. + * Remove one instruction entry; the removal is announced to the model at the next step boundary. */ public remove( parameters: { sessionID: string - key: SessionContextEntryKey2 + key: InstructionEntryKey2 }, options?: Options, ) { @@ -5308,25 +5308,25 @@ export class Entry extends HeyApiClient { ], ) return (options?.client ?? this.client).delete< - V2SessionContextEntryRemoveResponses, - V2SessionContextEntryRemoveErrors, + V2SessionInstructionsEntryRemoveResponses, + V2SessionInstructionsEntryRemoveErrors, ThrowOnError >({ - url: "/api/session/{sessionID}/context-entry/{key}", + url: "/api/session/{sessionID}/instructions/entries/{key}", ...options, ...params, }) } /** - * Put context entry + * Put instruction entry * - * Attach or replace one durable context entry. The value is rendered into the session's system context; changes announce as updates at the next turn boundary. + * Attach or replace one durable instruction entry. Changes announce as updates at the next step boundary. */ public put( parameters: { sessionID: string - key: SessionContextEntryKey2 + key: InstructionEntryKey2 value?: unknown }, options?: Options, @@ -5344,11 +5344,11 @@ export class Entry extends HeyApiClient { ], ) return (options?.client ?? this.client).put< - V2SessionContextEntryPutResponses, - V2SessionContextEntryPutErrors, + V2SessionInstructionsEntryPutResponses, + V2SessionInstructionsEntryPutErrors, ThrowOnError >({ - url: "/api/session/{sessionID}/context-entry/{key}", + url: "/api/session/{sessionID}/instructions/entries/{key}", ...options, ...params, headers: { @@ -5360,7 +5360,7 @@ export class Entry extends HeyApiClient { } } -export class Context extends HeyApiClient { +export class Instructions extends HeyApiClient { private _entry?: Entry get entry(): Entry { return (this._entry ??= new Entry({ client: this.client })) @@ -6479,9 +6479,9 @@ export class Session3 extends HeyApiClient { return (this._revert ??= new Revert({ client: this.client })) } - private _context?: Context - get context2(): Context { - return (this._context ??= new Context({ client: this.client })) + private _instructions?: Instructions + get instructions(): Instructions { + return (this._instructions ??= new Instructions({ client: this.client })) } private _form?: Form diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index de17b34bb65..443d4d4cce9 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -25,7 +25,7 @@ export type Event = | EventSessionPromptPromoted | EventSessionPromptAdmitted | EventSessionExecutionSettled - | EventSessionContextUpdated + | EventSessionInstructionsUpdated | EventSessionSynthetic | EventSessionSkillActivated | EventSessionShellStarted @@ -929,7 +929,7 @@ export type GlobalEvent = { } | { id: string - type: "session.context.updated" + type: "session.instructions.updated" properties: { sessionID: string text: string @@ -1731,7 +1731,7 @@ export type GlobalEvent = { | SyncEventSessionForked | SyncEventSessionPromptPromoted | SyncEventSessionPromptAdmitted - | SyncEventSessionContextUpdated + | SyncEventSessionInstructionsUpdated | SyncEventSessionSynthetic | SyncEventSessionSkillActivated | SyncEventSessionShellStarted @@ -2894,7 +2894,7 @@ export type SessionDurableEvent = | SessionForked | SessionPromptPromoted | SessionPromptAdmitted - | SessionContextUpdated + | SessionInstructionsUpdated | SessionSynthetic | SessionSkillActivated | SessionShellStarted @@ -3035,7 +3035,7 @@ export type V2Event = | SessionPromptPromoted | SessionPromptAdmitted | SessionExecutionSettled - | SessionContextUpdated + | SessionInstructionsUpdated | SessionSynthetic | SessionSkillActivated | SessionShellStarted @@ -3731,11 +3731,11 @@ export type SyncEventSessionPromptAdmitted = { } } -export type SyncEventSessionContextUpdated = { +export type SyncEventSessionInstructionsUpdated = { type: "sync" id: string syncEvent: { - type: "session.context.updated.1" + type: "session.instructions.updated.1" id: string seq: number aggregateID: string @@ -4527,10 +4527,10 @@ export type SessionMessage = | SessionMessageAssistant | SessionMessageCompaction -export type SessionContextEntryKey = string +export type InstructionEntryKey = string -export type SessionContextEntryInfo = { - key: SessionContextEntryKey +export type InstructionEntryInfo = { + key: InstructionEntryKey value: unknown } @@ -4671,13 +4671,13 @@ export type SessionPromptAdmitted = { } } -export type SessionContextUpdated = { +export type SessionInstructionsUpdated = { id: string created: number metadata?: { [key: string]: unknown } - type: "session.context.updated" + type: "session.instructions.updated" durable: { aggregateID: string seq: number @@ -6839,9 +6839,9 @@ export type EventSessionExecutionSettled = { } } -export type EventSessionContextUpdated = { +export type EventSessionInstructionsUpdated = { id: string - type: "session.context.updated" + type: "session.instructions.updated" properties: { sessionID: string text: string @@ -8246,12 +8246,12 @@ export type SessionMessage2 = | SessionMessageCompaction2 /** - * Context entry key (lowercase alphanumerics plus . _ -) + * Instruction entry key (lowercase alphanumerics plus . _ -) */ -export type SessionContextEntryKey2 = string +export type InstructionEntryKey2 = string -export type SessionContextEntryInfo2 = { - key: SessionContextEntryKey2 +export type InstructionEntryInfo2 = { + key: InstructionEntryKey2 value: unknown } @@ -8392,13 +8392,13 @@ export type SessionPromptAdmitted2 = { } } -export type SessionContextUpdated2 = { +export type SessionInstructionsUpdated2 = { id: string created: number metadata?: { [key: string]: unknown } - type: "session.context.updated" + type: "session.instructions.updated" durable: { aggregateID: string seq: number @@ -8991,7 +8991,7 @@ export type SessionDurableEventV2 = | SessionForked2 | SessionPromptPromoted2 | SessionPromptAdmitted2 - | SessionContextUpdated2 + | SessionInstructionsUpdated2 | SessionSynthetic2 | SessionSkillActivated2 | SessionShellStarted2 @@ -11207,7 +11207,7 @@ export type V2EventV2 = | SessionPromptPromoted2 | SessionPromptAdmitted2 | SessionExecutionSettled2 - | SessionContextUpdated2 + | SessionInstructionsUpdated2 | SessionSynthetic2 | SessionSkillActivated2 | SessionShellStarted2 @@ -16421,16 +16421,16 @@ export type V2SessionContextResponses = { export type V2SessionContextResponse = V2SessionContextResponses[keyof V2SessionContextResponses] -export type V2SessionContextEntryListData = { +export type V2SessionInstructionsEntryListData = { body?: never path: { sessionID: string } query?: never - url: "/api/session/{sessionID}/context-entry" + url: "/api/session/{sessionID}/instructions/entries" } -export type V2SessionContextEntryListErrors = { +export type V2SessionInstructionsEntryListErrors = { /** * InvalidRequestError */ @@ -16445,31 +16445,32 @@ export type V2SessionContextEntryListErrors = { 404: SessionNotFoundErrorV2 } -export type V2SessionContextEntryListError = V2SessionContextEntryListErrors[keyof V2SessionContextEntryListErrors] +export type V2SessionInstructionsEntryListError = + V2SessionInstructionsEntryListErrors[keyof V2SessionInstructionsEntryListErrors] -export type V2SessionContextEntryListResponses = { +export type V2SessionInstructionsEntryListResponses = { /** * Success */ 200: { - data: Array + data: Array } } -export type V2SessionContextEntryListResponse = - V2SessionContextEntryListResponses[keyof V2SessionContextEntryListResponses] +export type V2SessionInstructionsEntryListResponse = + V2SessionInstructionsEntryListResponses[keyof V2SessionInstructionsEntryListResponses] -export type V2SessionContextEntryRemoveData = { +export type V2SessionInstructionsEntryRemoveData = { body?: never path: { sessionID: string - key: SessionContextEntryKey2 + key: InstructionEntryKey2 } query?: never - url: "/api/session/{sessionID}/context-entry/{key}" + url: "/api/session/{sessionID}/instructions/entries/{key}" } -export type V2SessionContextEntryRemoveErrors = { +export type V2SessionInstructionsEntryRemoveErrors = { /** * InvalidRequestError */ @@ -16484,32 +16485,32 @@ export type V2SessionContextEntryRemoveErrors = { 404: SessionNotFoundErrorV2 } -export type V2SessionContextEntryRemoveError = - V2SessionContextEntryRemoveErrors[keyof V2SessionContextEntryRemoveErrors] +export type V2SessionInstructionsEntryRemoveError = + V2SessionInstructionsEntryRemoveErrors[keyof V2SessionInstructionsEntryRemoveErrors] -export type V2SessionContextEntryRemoveResponses = { +export type V2SessionInstructionsEntryRemoveResponses = { /** * */ 204: void } -export type V2SessionContextEntryRemoveResponse = - V2SessionContextEntryRemoveResponses[keyof V2SessionContextEntryRemoveResponses] +export type V2SessionInstructionsEntryRemoveResponse = + V2SessionInstructionsEntryRemoveResponses[keyof V2SessionInstructionsEntryRemoveResponses] -export type V2SessionContextEntryPutData = { +export type V2SessionInstructionsEntryPutData = { body: { value: unknown } path: { sessionID: string - key: SessionContextEntryKey2 + key: InstructionEntryKey2 } query?: never - url: "/api/session/{sessionID}/context-entry/{key}" + url: "/api/session/{sessionID}/instructions/entries/{key}" } -export type V2SessionContextEntryPutErrors = { +export type V2SessionInstructionsEntryPutErrors = { /** * InvalidRequestError */ @@ -16524,17 +16525,18 @@ export type V2SessionContextEntryPutErrors = { 404: SessionNotFoundErrorV2 } -export type V2SessionContextEntryPutError = V2SessionContextEntryPutErrors[keyof V2SessionContextEntryPutErrors] +export type V2SessionInstructionsEntryPutError = + V2SessionInstructionsEntryPutErrors[keyof V2SessionInstructionsEntryPutErrors] -export type V2SessionContextEntryPutResponses = { +export type V2SessionInstructionsEntryPutResponses = { /** * */ 204: void } -export type V2SessionContextEntryPutResponse = - V2SessionContextEntryPutResponses[keyof V2SessionContextEntryPutResponses] +export type V2SessionInstructionsEntryPutResponse = + V2SessionInstructionsEntryPutResponses[keyof V2SessionInstructionsEntryPutResponses] export type V2SessionLogData = { body?: never diff --git a/packages/server/src/handlers/session.ts b/packages/server/src/handlers/session.ts index 72d238e6842..2bb45d52ed1 100644 --- a/packages/server/src/handlers/session.ts +++ b/packages/server/src/handlers/session.ts @@ -1,5 +1,5 @@ import { SessionV2 } from "@opencode-ai/core/session" -import { SessionContextEntry } from "@opencode-ai/core/session/context-entry" +import { InstructionEntry } from "@opencode-ai/core/session/instruction-entry" import { DateTime, Effect, Stream } from "effect" import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi" import { Api } from "../api" @@ -541,25 +541,25 @@ export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handl }), ) .handle( - "session.context.entry.list", + "session.instructions.entry.list", Effect.fn(function* (ctx) { - const contextEntries = yield* SessionContextEntry.Service - return { data: yield* contextEntries.list(ctx.params.sessionID) } + const instructions = yield* InstructionEntry.Service + return { data: yield* instructions.list(ctx.params.sessionID) } }), ) .handle( - "session.context.entry.put", + "session.instructions.entry.put", Effect.fn(function* (ctx) { - const contextEntries = yield* SessionContextEntry.Service - yield* contextEntries.put({ sessionID: ctx.params.sessionID, key: ctx.params.key, value: ctx.payload.value }) + const instructions = yield* InstructionEntry.Service + yield* instructions.put({ sessionID: ctx.params.sessionID, key: ctx.params.key, value: ctx.payload.value }) return HttpApiSchema.NoContent.make() }), ) .handle( - "session.context.entry.remove", + "session.instructions.entry.remove", Effect.fn(function* (ctx) { - const contextEntries = yield* SessionContextEntry.Service - yield* contextEntries.remove({ sessionID: ctx.params.sessionID, key: ctx.params.key }) + const instructions = yield* InstructionEntry.Service + yield* instructions.remove({ sessionID: ctx.params.sessionID, key: ctx.params.key }) return HttpApiSchema.NoContent.make() }), ) diff --git a/packages/tui/src/context/data.tsx b/packages/tui/src/context/data.tsx index ae6626be394..7fdde0d49ac 100644 --- a/packages/tui/src/context/data.tsx +++ b/packages/tui/src/context/data.tsx @@ -302,7 +302,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ }) }) break - case "session.context.updated": + case "session.instructions.updated": message.update(event.data.sessionID, (draft, index) => { message.append(draft, index, { id: messageIDFromEvent(event.id), diff --git a/packages/tui/src/routes/session/rows.ts b/packages/tui/src/routes/session/rows.ts index fc0b38b1ade..c0d44c3d80e 100644 --- a/packages/tui/src/routes/session/rows.ts +++ b/packages/tui/src/routes/session/rows.ts @@ -149,7 +149,7 @@ export function createSessionRows(sessionID: Accessor) { } const subscriptions = [ data.on("session.prompt.admitted", input), - data.on("session.context.updated", message), + data.on("session.instructions.updated", message), data.on("session.synthetic", (event) => { if (event.data.sessionID === sessionID() && event.data.description?.trim()) appendMessage(event.id.replace(/^evt_/, "msg_")) diff --git a/packages/tui/test/cli/tui/data.test.tsx b/packages/tui/test/cli/tui/data.test.tsx index 0e43377657a..b9beb0e5360 100644 --- a/packages/tui/test/cli/tui/data.test.tsx +++ b/packages/tui/test/cli/tui/data.test.tsx @@ -1169,7 +1169,7 @@ test("renders admitted prompts immediately with queued marker and clears when pr } }) -test("projects live context updates with their message ID", async () => { +test("projects live instruction updates with their message ID", async () => { const events = createEventStream() const calls = createFetch(undefined, events) let sync!: ReturnType @@ -1199,21 +1199,21 @@ test("projects live context updates with their message ID", async () => { try { await mounted emitEvent(events, { - id: "evt_context_1", + id: "evt_instructions_1", created: 0, - type: "session.context.updated", + type: "session.instructions.updated", durable: durable("session-1"), data: { sessionID: "session-1", - text: "Updated context", + text: "Updated instructions", }, }) await wait(() => sync.session.message.list("session-1")?.length === 1) expect(sync.session.message.list("session-1")?.[0]).toMatchObject({ - id: SessionMessage.ID.fromEvent(EventV2.ID.make("evt_context_1")), + id: SessionMessage.ID.fromEvent(EventV2.ID.make("evt_instructions_1")), type: "system", - text: "Updated context", + text: "Updated instructions", time: { created: 0 }, }) } finally { diff --git a/specs/v2/schema-changelog.md b/specs/v2/schema-changelog.md index 3fd4fb4a172..62c85ef3e83 100644 --- a/specs/v2/schema-changelog.md +++ b/specs/v2/schema-changelog.md @@ -1,5 +1,18 @@ # V2 Schema Changelog +## 2026-07-05: Rename Session Context Contracts To Instructions + +- Rename the System Context algebra to `Instructions`, API-managed `SessionContextEntry` records to `InstructionEntry`, and the session-owned context checkpoint to `InstructionCheckpoint`. +- Rename the tables `session_context_entry` and `session_context_epoch` to `instruction_entry` and `instruction_checkpoint`. +- Rename the durable update event from `session.context.updated` to `session.instructions.updated`; the migration rewrites existing durable event types in place. +- Rename the API-managed entry routes from `/api/session/:sessionID/context-entry` to `/api/session/:sessionID/instructions/entries` and their operation identifiers from `session.context.entry.*` to `session.instructions.entry.*`, keeping bare `session.instructions.*` free for the composed instruction surface. + +Compatibility: + +- The V2 contracts remain experimental. The renamed tables, event, endpoints, schemas, and generated client names are intentionally breaking changes for beta consumers. +- Existing changelog entries retain the names that were accurate when those changes occurred. +- Behavior is unchanged: this is a vocabulary and contract rename only. + ## 2026-07-03: Require Durable Envelope On Durable Events - Make the wire `durable` envelope required on durable event definitions. diff --git a/specs/v2/session.md b/specs/v2/session.md index c4307b6897b..7ba277139b4 100644 --- a/specs/v2/session.md +++ b/specs/v2/session.md @@ -51,61 +51,71 @@ The local runner issues one explicit `llm.stream(request)` per step, projects ea Projected hosted tools preserve call-side and settlement-side provider metadata separately so settlement and interruption recovery cannot erase continuation identifiers. Provider-native reasoning and provider metadata replay only while the historical assistant model matches the selected continuation model; after a model switch, visible reasoning text remains ordinary assistant text and provider-native metadata is omitted. -## Context Epochs +## Instruction Checkpoints -V2 Sessions persist the exact privileged System Context shown to the model. A Context Epoch stores one immutable provider-cache baseline and a model-hidden structured snapshot used to compare independently observed Context Sources. Environment facts, the host-local date, ambient global/upward-project `AGENTS.md` files, and selected-agent available-skill guidance are the initial sources. Location-wide sources come from the System Context Registry; selected-agent guidance composes with them immediately before Context Epoch admission. +V2 Sessions persist the exact privileged instructions shown to the model. `InstructionCheckpoint` stores one immutable instruction baseline, its baseline event sequence, and a model-hidden `Instructions.Applied` record used to compare independently observed instruction sources. Instructions are only one part of Model Context: the runner separately assembles agent or provider system text, Session History, tool definitions, and step-local additions for each request. -The first complete observation initializes the epoch before any pending prompt becomes model-visible. If initial context is temporarily unavailable, execution stops while the prompt remains pending and retryable. On later steps, the runner promotes eligible input first, then reconciles current sources at the safe boundary. Changed context becomes one durable chronological System message, and its event commit advances the epoch snapshot atomically. +The runner has no instruction registry. `loadInstructions` explicitly loads these producers concurrently and combines them in this fixed order: + +1. Instruction built-ins, currently environment facts and the host-local date. +2. `InstructionDiscovery`, observing ambient `AGENTS.md` files. +3. Selected-agent available-skill guidance. +4. Reference guidance. +5. Selected-agent MCP guidance. +6. API-managed `InstructionEntry` values for the Session. + +`Instructions.combine(...)` preserves that caller order and rejects duplicate namespaced source keys. Each source owns its typed observation, JSON codec, and pure baseline, update, and optional removal renderers. + +The first complete observation initializes `InstructionCheckpoint` before any pending prompt becomes model-visible. If an initial source is temporarily unavailable, execution stops while the prompt remains pending and retryable. Every later step attempt also prepares instructions before input promotion. Changed instructions publish one durable chronological System message through `session.instructions.updated`, and that event commit advances `Instructions.Applied` atomically. ```text -Client Runner System Context Registry Context Epoch Store Session History LLM - │ │ │ │ │ │ - ├─ Admit prompt ─────────────────────────────────────────────────────────────────────────────────────────────▶ │ - │ │ │ │ │ │ - │ ├─ Observe initial context ────────────▶ │ │ │ - │ │ │ │ │ │ - │ ◀─ Complete baseline or unavailable ───┤ │ │ │ - │ │ │ │ │ │ - │ ├─ Initialize missing epoch ───────────────────────────────────────▶ │ │ - │ │ │ │ │ │ - │ ├─ Promote eligible input ─────────────────────────────────────────────────────────────────▶ │ - │ │ │ │ │ │ - │ ├─ Reconcile at safe boundary ─────────▶ │ │ │ - │ │ │ │ │ │ - │ ◀─ Unchanged or chronological update ──┤ │ │ │ - │ │ │ │ │ │ - │ ├─ Advance snapshot atomically with update ────────────────────────▶ │ │ - │ │ │ │ │ │ - │ ├─ Baseline + chronological history ─────────────────────────────────────────────────────────────────────────▶ +Client Runner Explicit producers InstructionCheckpoint Inbox / History LLM + │ │ │ │ │ │ + ├─ Admit prompt ────────────────────────────────────────────────────────────────────────────────▶ │ + │ │ │ │ │ │ + │ ├─ Load instructions ───────▶ │ │ │ + │ │ │ │ │ │ + │ ◀─ Combined sources ─────────┤ │ │ │ + │ │ │ │ │ │ + │ ├─ Initialize or reconcile ────────────────────────────▶ │ │ + │ │ │ │ │ │ + │ ├─ Publish update + advance Applied atomically ───────────────────────────────▶ │ + │ │ │ │ │ │ + │ ├─ Promote eligible input ────────────────────────────────────────────────────▶ │ + │ │ │ │ │ │ + │ ├─ System text + instruction baseline + history + tools ──────────────────────────────────────▶ ``` -Agent and model selection are step-scoped. A switch admitted after the current safe step boundary applies to the next step without restarting the current step or replacing the baseline. Agent-specific skill guidance remains a Context Source, so changed guidance is admitted as a chronological System message. A completed compaction causes the next physical attempt to render a fresh baseline directly from current complete context. A Session move clears the epoch so the destination Location initializes a complete baseline on its next run. +Agent and model selection are step-scoped. The runner selects the agent before loading agent-specific guidance; a switch admitted after the current boundary applies to the next step without restarting the current one. Changed guidance is admitted through `session.instructions.updated` while preserving the baseline. Model selection affects Model Context assembly but is not an instruction source and does not itself replace the instruction baseline. + +A completed compaction causes the next physical attempt to rebaseline from current instructions. Temporarily unavailable sources are restated from the model's last applied belief where possible. A Session move resets `InstructionCheckpoint` so the destination Location initializes a complete baseline on its next run. Committed revert also resets the checkpoint. ```text -Session Epoch - │ │ - ├─ initialize complete baseline ──▶ - │ │ - │ ├─────────────────────────────────╮ - │ │ reconcile chronological update │ - │ ◀─────────────────────────────────╯ - │ │ - ├─ completed compaction ──────────▶ - │ ├─ render fresh baseline - │ │ - ├─ clear after Location move ─────▶ +Session InstructionCheckpoint + │ │ + ├─ initialize complete baseline ────▶ + │ │ + │ ├──────────────────────────────╮ + │ │ reconcile instruction update │ + │ ◀──────────────────────────────╯ + │ │ + ├─ completed compaction ────────────▶ rebaseline + │ │ + ├─ move or committed revert ────────▶ reset ``` -Ambient project discovery canonicalizes and contains traversal within the project root and honors `OPENCODE_DISABLE_PROJECT_CONFIG`. An unavailable observation preserves the previously admitted value. A confirmed partial instruction removal emits the complete remaining aggregate with explicit supersession text; removing the final instruction emits a revocation message. +`InstructionDiscovery` observes ambient instructions as one ordered aggregate source. Ambient discovery canonicalizes traversal within the project root, reads global and upward-project `AGENTS.md` files, and honors `OPENCODE_DISABLE_PROJECT_CONFIG` for project files. -Current Context Epoch follow-ups: +An unavailable observation preserves the previously applied value. A confirmed partial instruction removal emits the complete remaining aggregate with explicit supersession text; removing the final instruction emits a revocation message. -- Add configured, remote, and nested instruction sources with explicit precedence and removal semantics. +Current instruction follow-ups: + +- Add configured and remote instruction sources with explicit precedence and removal semantics. - Add durable post-crash continuation recovery for promoted or provider-dispatched work. - Add explicit manual compaction on top of automatic request-budget compaction. - Add operational metrics for observation latency, unavailable sources, contention, baseline size, and chronological-update growth. -- Consider watcher-backed per-file caching only if measurements show direct safe-boundary observation is too expensive. -- Expose plugin-defined Context Sources only after plugin reload and scoped cleanup semantics are designed. +- Consider watcher-backed per-file caching only if measurements show direct step-boundary observation is too expensive. +- Design any plugin-defined instruction contribution as an explicit runner composition boundary; do not reintroduce a registry implicitly. - Add clustered Session execution ownership and stale-runtime fencing. ## Automatic Compaction @@ -114,25 +124,25 @@ Before each step, the runner estimates the complete model-visible request and co Compaction keeps the full transcript durable while replacing its active model representation with one hidden checkpoint containing a structured rolling summary and token-bounded serialized recent context. Provider-native assistant, reasoning, and tool messages never survive across the boundary, avoiding signature and encrypted-reasoning failures when the earlier prefix changes. -`session.compaction.started.1` durably identifies the attempt. Compaction deltas are live-only progress. `session.compaction.ended.1` durably stores the final summary and serialized recent context; only this completed event projects a model-visible compaction message. On the next physical attempt, the runner observes that completed compaction and directly renders a fresh Context Epoch baseline. A failed or interrupted attempt therefore leaves the previous history boundary active. +`session.compaction.started.1` durably identifies the attempt. Compaction deltas are live-only progress. `session.compaction.ended.1` durably stores the final summary and serialized recent context; only this completed event projects a model-visible compaction message. On the next physical attempt, the runner observes that completed compaction and directly renders a fresh instruction baseline through `InstructionCheckpoint`. A failed or interrupted attempt therefore leaves the previous history boundary active. Repeated compactions update the previous structured summary with newly compacted messages. The runner then reloads projected history and executes the original pending step. When a provider rejects a request as context overflow before durable assistant output or tool execution, the runner attempts one overflow-triggered compaction even when the local estimate did not predict pressure. A completed checkpoint rebuilds the same logical step with one remaining physical attempt. A second overflow, unavailable compaction, or overflow after durable output becomes the ordinary terminal failure; recovery never loops or replays partial side effects. Deterministic old tool-result pruning remains a separate follow-up. -## V1 Runtime Context Parity +## V1 Model Context Parity -This is the canonical checklist for model-visible runtime context still needed before the V2 runner replaces V1. Keep each behavior in its owning boundary rather than treating all model-visible text as a durable Context Source. Update this table in the PR that changes a status. +This is the canonical checklist for Model Context still needed before the V2 runner replaces V1. Keep each behavior in its owning boundary rather than treating all model-visible text as durable Instructions. Update this table in the PR that changes a status. Status: `complete` is usable in the native V2 path, `partial` covers only part of V1 behavior, and `missing` has no native V2 equivalent. | Boundary | Behavior | Status | Remaining V2 work | | -------------------------- | ------------------------------------------------------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| Durable Context Source | Environment facts and host-local date | partial | Add selected provider/model identity without making model selection a stale Location-wide value. | -| Durable Context Source | Global and upward project instructions | partial | Decide whether V2 also discovers legacy `CLAUDE.md` and deprecated `CONTEXT.md`. | -| Durable Context Source | Configured local/glob and remote URL instructions | missing | Add independent sources with explicit precedence, unavailable, and removal semantics. | -| Durable Context Source | Nearby nested instructions discovered after successful reads | missing | Persist discoveries and admit them at the next safe step boundary. | -| Durable Context Source | Selected-agent available skill guidance and skill-body loading | partial | Guidance and body exposure are permission-filtered; remove globally denied skill definitions during request-time tool materialization. | +| Durable Instruction Source | Environment facts and host-local date | partial | Keep selected provider/model identity in step request assembly rather than a stale Location-wide instruction value. | +| Durable Instruction Source | Global and upward project instructions | partial | Decide whether V2 also discovers legacy `CLAUDE.md` and deprecated `CONTEXT.md`. | +| Durable Instruction Source | Configured local/glob and remote URL instructions | missing | Add independent sources with explicit precedence, unavailable, and removal semantics. | +| Durable Instruction Source | Nearby nested instructions discovered after successful reads | missing | Persist discoveries and admit them at the next safe step boundary. | +| Durable Instruction Source | Selected-agent available skill guidance and skill-body loading | partial | Guidance and body exposure are permission-filtered; remove globally denied skill definitions during request-time tool materialization. | | Step request assembly | Placement, selected model, chronological history, and canonical lowering | complete | None. | | Step request assembly | Selected agent, agent prompt, and effective permissions | partial | V2 uses selected-agent permissions for skill guidance and tool authorization; still apply the agent system prompt and request policy. | | Step request assembly | Provider/model-specific base instructions | complete | Native V2 selects the provider-family baseline unless the effective agent overrides it. | From c13f06c30cd08b01fe331f18fc1a4d0655a18cba Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 6 Jul 2026 14:34:57 -0400 Subject: [PATCH 14/46] feat(tui): use canonical prompt attachments --- .../client/src/promise/generated/types.ts | 10 + packages/core/src/mime.ts | 88 ++++ packages/core/src/session.ts | 63 ++- .../core/src/session/runner/to-llm-message.ts | 41 +- packages/core/test/session-prompt.test.ts | 58 ++- .../core/test/session-runner-message.test.ts | 61 +++ packages/docs/config.mdx | 4 + packages/plugin/src/tui.ts | 29 +- packages/schema/src/prompt.ts | 2 + packages/sdk/js/src/v2/gen/types.gen.ts | 2 + packages/tui/src/app.tsx | 2 +- packages/tui/src/component/dialog-stash.tsx | 4 +- .../tui/src/component/prompt/autocomplete.tsx | 118 +++-- packages/tui/src/component/prompt/index.tsx | 425 ++++++------------ packages/tui/src/prompt/history.tsx | 51 ++- packages/tui/src/prompt/part.ts | 24 +- packages/tui/src/prompt/stash.tsx | 12 +- packages/tui/src/routes/home.tsx | 4 +- .../session/dialog-fork-from-timeline.tsx | 22 +- packages/tui/src/routes/session/index.tsx | 4 +- .../test/cli/tui/prompt-submit-race.test.ts | 4 +- packages/tui/test/prompt/history.test.ts | 24 +- packages/tui/test/prompt/jsonl.test.ts | 4 +- packages/tui/test/prompt/part.test.ts | 21 +- 24 files changed, 611 insertions(+), 466 deletions(-) create mode 100644 packages/core/src/mime.ts diff --git a/packages/client/src/promise/generated/types.ts b/packages/client/src/promise/generated/types.ts index 0473ce4a5ed..0f35a342ea7 100644 --- a/packages/client/src/promise/generated/types.ts +++ b/packages/client/src/promise/generated/types.ts @@ -604,6 +604,7 @@ export type SessionPromptOutput = { readonly files?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } @@ -804,6 +805,7 @@ export type SessionCommandOutput = { readonly files?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } @@ -934,6 +936,7 @@ export type SessionContextOutput = { readonly files?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } @@ -1037,6 +1040,7 @@ export type SessionContextOutput = { readonly attachments?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } @@ -1196,6 +1200,7 @@ export type SessionLogOutput = readonly files?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } @@ -1628,6 +1633,7 @@ export type SessionMessageOutput = { readonly files?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } @@ -1731,6 +1737,7 @@ export type SessionMessageOutput = { readonly attachments?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } @@ -1828,6 +1835,7 @@ export type MessageListOutput = { readonly files?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } @@ -1931,6 +1939,7 @@ export type MessageListOutput = { readonly attachments?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } @@ -4478,6 +4487,7 @@ export type EventSubscribeOutput = readonly files?: ReadonlyArray<{ readonly uri: string readonly mime: string + readonly content?: string readonly name?: string readonly description?: string readonly source?: { readonly start: number; readonly end: number; readonly text: string } diff --git a/packages/core/src/mime.ts b/packages/core/src/mime.ts new file mode 100644 index 00000000000..50963d925bf --- /dev/null +++ b/packages/core/src/mime.ts @@ -0,0 +1,88 @@ +export * as Mime from "./mime.js" + +import { Effect, FileSystem, Option } from "effect" +import { fileURLToPath } from "url" +import { FSUtil } from "./fs-util" + +const SAMPLE_BYTES = 8192 + +export const resolve = Effect.fn("Mime.resolve")(function* (uri: string) { + const data = dataSample(uri) + if (data) return detect(data) + + const target = yield* Effect.try({ + try: () => localPath(uri), + catch: () => new Error("Invalid file URI"), + }).pipe(Effect.catch(() => Effect.succeed(undefined))) + if (!target) return "application/octet-stream" + + const fs = yield* FSUtil.Service + const local = yield* Effect.scoped( + Effect.gen(function* () { + const info = yield* fs.stat(target) + if (info.type === "Directory") return { type: "directory" as const } + if (info.type !== "File") return + const file = yield* fs.open(target) + return { + type: "file" as const, + sample: Option.getOrElse(yield* file.readAlloc(FileSystem.Size(SAMPLE_BYTES)), () => new Uint8Array()), + } + }), + ).pipe(Effect.catch(() => Effect.succeed(undefined))) + + if (local?.type === "directory") return "application/x-directory" + if (local?.type === "file") return detect(local.sample) + return "application/octet-stream" +}) + +function detect(bytes: Uint8Array) { + if (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) return "image/png" + if (startsWith(bytes, [0xff, 0xd8, 0xff])) return "image/jpeg" + if (startsWith(bytes, [0x47, 0x49, 0x46, 0x38])) return "image/gif" + if (startsWith(bytes, [0x42, 0x4d])) return "image/bmp" + if (startsWith(bytes, [0x25, 0x50, 0x44, 0x46, 0x2d])) return "application/pdf" + if (startsWith(bytes, [0x52, 0x49, 0x46, 0x46]) && startsWith(bytes.subarray(8), [0x57, 0x45, 0x42, 0x50])) + return "image/webp" + if ( + startsWith(bytes.subarray(4), [0x66, 0x74, 0x79, 0x70]) && + (startsWith(bytes.subarray(8), [0x61, 0x76, 0x69, 0x66]) || + startsWith(bytes.subarray(8), [0x61, 0x76, 0x69, 0x73])) + ) + return "image/avif" + return isText(bytes) ? "text/plain" : "application/octet-stream" +} + +function dataSample(uri: string) { + if (!uri.startsWith("data:")) return + const comma = uri.indexOf(",") + if (comma === -1) return new Uint8Array() + const metadata = uri.slice(5, comma) + const payload = uri.slice(comma + 1) + if (metadata.split(";").some((part) => part.toLowerCase() === "base64")) { + return Buffer.from(payload.slice(0, Math.ceil((SAMPLE_BYTES * 4) / 3) + 4), "base64").subarray(0, SAMPLE_BYTES) + } + return new TextEncoder().encode(payload.slice(0, SAMPLE_BYTES)) +} + +function localPath(uri: string) { + if (!URL.canParse(uri)) return + const url = new URL(uri) + if (url.protocol !== "file:") return + return fileURLToPath(url) +} + +function startsWith(bytes: Uint8Array, prefix: number[]) { + return prefix.every((value, index) => bytes[index] === value) +} + +function isText(bytes: Uint8Array) { + if (bytes.length === 0) return true + if (bytes.includes(0)) return false + try { + new TextDecoder("utf-8", { fatal: true }).decode(bytes, { stream: true }) + } catch { + return false + } + const controls = bytes.reduce((count, byte) => count + Number(byte < 9 || (byte > 13 && byte < 32)), 0) + return controls / bytes.length <= 0.3 +} diff --git a/packages/core/src/session.ts b/packages/core/src/session.ts index 02359903e31..6f05f7b1f2d 100644 --- a/packages/core/src/session.ts +++ b/packages/core/src/session.ts @@ -37,6 +37,7 @@ import { SessionCompaction } from "./session/compaction" import { SessionRevert } from "./session/revert" import { Revert } from "@opencode-ai/schema/revert" import { FSUtil } from "./fs-util" +import { Mime } from "./mime" import type { EventLog } from "@opencode-ai/schema/event-log" import { SkillV2 } from "./skill" import { Job } from "./job" @@ -44,6 +45,7 @@ import { CommandV2 } from "./command" import { Shell } from "./shell" import { Shell as ShellSchema } from "@opencode-ai/schema/shell" import { KeyedMutex } from "./effect/keyed-mutex" +import { fileURLToPath } from "url" export const RevertState = Revert.State export type RevertState = Revert.State @@ -251,6 +253,7 @@ const layer = Layer.effect( const execution = yield* SessionExecution.Service const store = yield* SessionStore.Service const locations = yield* LocationServiceMap.Service + const fs = yield* FSUtil.Service const jobs = yield* Job.Service const scope = yield* Scope.Scope const activeShells = new Set() @@ -456,7 +459,7 @@ const layer = Layer.effect( // continues from the reverted boundary rather than stale post-boundary history. if (session.revert) yield* SessionRevert.commit(session).pipe(Effect.provideService(EventV2.Service, events)) - const prompt = resolvePrompt(input.prompt) + const prompt = yield* resolvePrompt(input.prompt).pipe(Effect.provideService(FSUtil.Service, fs)) const messageID = input.id ?? SessionMessage.ID.create() const delivery = input.delivery ?? "steer" const expected = { sessionID: input.sessionID, messageID, prompt, delivery } @@ -713,19 +716,52 @@ function synthesizeTerminalShellInfo(started: ShellSchema.Info): ShellSchema.Inf } } -const resolvePrompt = (input: PromptInput.Prompt) => - Prompt.make({ - text: input.text, - agents: input.agents, - files: input.files?.map((file) => { - const dataMime = file.uri.match(/^data:([^;,]+)[;,]/i)?.[1] - const target = URL.canParse(file.uri) ? new URL(file.uri).pathname : (file.name ?? file.uri) - return { - ...file, - mime: dataMime ?? (target.endsWith("/") ? "application/x-directory" : FSUtil.mimeType(target)), - } +const resolvePrompt = Effect.fn("V2Session.resolvePrompt")(function* (input: PromptInput.Prompt) { + const fs = yield* FSUtil.Service + const files = input.files + ? yield* Effect.forEach( + input.files, + (file) => + Effect.gen(function* () { + const mime = yield* Mime.resolve(file.uri) + const content = mime === "text/plain" ? yield* readTextAttachment(fs, file.uri) : undefined + return { ...file, mime, ...(content === undefined ? {} : { content }) } + }), + { concurrency: 8 }, + ) + : undefined + return Prompt.make({ text: input.text, agents: input.agents, files }) +}) + +function readTextAttachment(fs: FSUtil.Interface, uri: string) { + if (uri.startsWith("data:")) return Effect.succeed(undefined) + return Effect.try({ + try: () => new URL(uri), + catch: () => new Error("Invalid attachment URI"), + }).pipe( + Effect.flatMap((url) => { + if (url.protocol !== "file:") return Effect.succeed(undefined) + const start = positiveInt(url.searchParams.get("start")) + const end = positiveInt(url.searchParams.get("end")) + url.search = "" + url.hash = "" + return Effect.try({ + try: () => fileURLToPath(url), + catch: () => new Error("Invalid file URI"), + }).pipe( + Effect.flatMap((target) => fs.readFileString(target)), + Effect.map((content) => (start === undefined ? content : content.split("\n").slice(start - 1, end).join("\n"))), + ) }), - }) + Effect.catch(() => Effect.succeed(undefined)), + ) +} + +function positiveInt(value: string | null) { + if (value === null) return + const parsed = Number(value) + return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined +} // Mirrors the shell tool's in-memory preview safety limit. const SHELL_MAX_CAPTURE_BYTES = 1024 * 1024 @@ -742,5 +778,6 @@ export const node = makeGlobalNode({ SessionStore.node, LocationServiceMap.node, SessionProjector.node, + FSUtil.node, ], }) diff --git a/packages/core/src/session/runner/to-llm-message.ts b/packages/core/src/session/runner/to-llm-message.ts index e6a91a9ef16..c9bdcbd2e19 100644 --- a/packages/core/src/session/runner/to-llm-message.ts +++ b/packages/core/src/session/runner/to-llm-message.ts @@ -19,6 +19,41 @@ const media = (file: FileAttachment): ContentPart => ({ metadata: file.description === undefined ? undefined : { description: file.description }, }) +const textAttachment = (file: FileAttachment) => + Message.make({ + role: "user", + content: [ + `Attached file: ${file.name ?? file.uri}`, + `Source: ${file.uri}`, + file.description === undefined ? undefined : `Description: ${file.description}`, + "", + file.content ?? readTextData(file.uri) ?? "[Attachment content unavailable]", + ] + .filter((line): line is string => line !== undefined) + .join("\n"), + metadata: { + attachment: { + uri: file.uri, + name: file.name, + description: file.description, + }, + }, + }) + +function readTextData(uri: string) { + if (!uri.startsWith("data:")) return + const comma = uri.indexOf(",") + if (comma === -1) return + const metadata = uri.slice(5, comma) + const payload = uri.slice(comma + 1) + if (metadata.split(";").some((part) => part.toLowerCase() === "base64")) return Buffer.from(payload, "base64").toString("utf8") + try { + return decodeURIComponent(payload) + } catch { + return + } +} + const decodeToolInput = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) const toolInput = (tool: SessionMessage.AssistantTool) => @@ -117,11 +152,15 @@ function toLLMMessage(message: SessionMessage.Message, model: Model): Message[] case "model-switched": return [] case "user": + const files = message.files ?? [] return [ + ...files + .filter((file) => file.mime === "text/plain") + .map(textAttachment), Message.make({ id: message.id, role: "user", - content: [{ type: "text", text: message.text }, ...(message.files ?? []).map(media)], + content: [{ type: "text", text: message.text }, ...files.filter((file) => file.mime !== "text/plain").map(media)], metadata: { ...message.metadata, ...(message.agents?.length ? { agents: message.agents } : {}), diff --git a/packages/core/test/session-prompt.test.ts b/packages/core/test/session-prompt.test.ts index 9ef5b5d822b..163d831a5e9 100644 --- a/packages/core/test/session-prompt.test.ts +++ b/packages/core/test/session-prompt.test.ts @@ -1,5 +1,7 @@ import { describe, expect } from "bun:test" import { DateTime, Effect, Fiber, Layer, Schema, Stream } from "effect" +import path from "path" +import { pathToFileURL } from "url" import { eq } from "drizzle-orm" import { Database } from "@opencode-ai/core/database/database" import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" @@ -221,20 +223,70 @@ describe("SessionV2.prompt", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service + const uri = + "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=" const message = yield* session.prompt({ sessionID, prompt: { text: "Inspect this image", - files: [{ uri: "data:image/png;base64,aGVsbG8=", name: "image.png" }], + files: [{ uri, name: "image.png" }], + }, + resume: false, + }) + + expect(message.prompt.files).toEqual([{ uri, name: "image.png", mime: "image/png" }]) + expect((yield* admitted(message.id))?.prompt.files).toEqual(message.prompt.files) + }), + ) + + it.effect("classifies source files and directories from local content", () => + Effect.gen(function* () { + yield* setup + const session = yield* SessionV2.Service + const directory = import.meta.dir + const source = path.join(directory, "session-prompt.test.ts") + const sourceUri = pathToFileURL(source) + sourceUri.searchParams.set("start", "1") + sourceUri.searchParams.set("end", "1") + + const message = yield* session.prompt({ + sessionID, + prompt: { + text: "Inspect these", + files: [ + { uri: sourceUri.href, name: "main.ts" }, + { uri: pathToFileURL(directory).href, name: "source" }, + ], }, resume: false, }) expect(message.prompt.files).toEqual([ - { uri: "data:image/png;base64,aGVsbG8=", name: "image.png", mime: "image/png" }, + { + uri: sourceUri.href, + name: "main.ts", + mime: "text/plain", + content: 'import { describe, expect } from "bun:test"', + }, + { uri: pathToFileURL(directory).href, name: "source", mime: "application/x-directory" }, ]) - expect((yield* admitted(message.id))?.prompt.files).toEqual(message.prompt.files) + }), + ) + + it.effect("sniffs data URL content instead of trusting its declared MIME", () => + Effect.gen(function* () { + yield* setup + const session = yield* SessionV2.Service + const uri = `data:video/mp2t;base64,${Buffer.from("export const value = 1\n").toString("base64")}` + + const message = yield* session.prompt({ + sessionID, + prompt: { text: "Inspect this", files: [{ uri, name: "main.ts" }] }, + resume: false, + }) + + expect(message.prompt.files).toEqual([{ uri, name: "main.ts", mime: "text/plain" }]) }), ) diff --git a/packages/core/test/session-runner-message.test.ts b/packages/core/test/session-runner-message.test.ts index 9aed4848581..8fdc53631eb 100644 --- a/packages/core/test/session-runner-message.test.ts +++ b/packages/core/test/session-runner-message.test.ts @@ -149,6 +149,67 @@ Recent work ]) }) + test("lowers text attachments as separate user messages", () => { + const file = FileAttachment.make({ + uri: "file:///project/main.ts", + mime: "text/plain", + content: "export const value = 1", + name: "main.ts", + }) + const messages = toLLMMessages( + [ + SessionMessage.User.make({ + id: id("user-text-file"), + type: "user", + text: "Review this file", + files: [file], + time: { created }, + }), + ], + model, + ) + + expect(messages).toHaveLength(2) + expect(messages[0]).toMatchObject({ + role: "user", + content: [ + { + type: "text", + text: "Attached file: main.ts\nSource: file:///project/main.ts\n\nexport const value = 1", + }, + ], + metadata: { attachment: { uri: "file:///project/main.ts", name: "main.ts" } }, + }) + expect(messages[1]).toMatchObject({ + id: id("user-text-file"), + role: "user", + content: [{ type: "text", text: "Review this file" }], + }) + }) + + test("derives text attachment content from durable data URLs", () => { + const uri = `data:text/plain;base64,${Buffer.from("inline content").toString("base64")}` + const messages = toLLMMessages( + [ + SessionMessage.User.make({ + id: id("user-data-file"), + type: "user", + text: "Review this file", + files: [FileAttachment.make({ uri, mime: "text/plain", name: "inline.txt" })], + time: { created }, + }), + ], + model, + ) + + expect(messages[0]?.content).toEqual([ + { + type: "text", + text: `Attached file: inline.txt\nSource: ${uri}\n\ninline content`, + }, + ]) + }) + test("replays durable tool media into canonical tool messages without structured base64", () => { const messages = toLLMMessages( [ diff --git a/packages/docs/config.mdx b/packages/docs/config.mdx index a084c1a819a..42028fd726e 100644 --- a/packages/docs/config.mdx +++ b/packages/docs/config.mdx @@ -2,3 +2,7 @@ title: "Config" description: "Configure OpenCode." --- + + + You shouldn't have to configure OpenCode manually. Ask OpenCode to update its configuration for you. + diff --git a/packages/plugin/src/tui.ts b/packages/plugin/src/tui.ts index f218f8ec3f0..a9d8d7dcd3e 100644 --- a/packages/plugin/src/tui.ts +++ b/packages/plugin/src/tui.ts @@ -1,8 +1,6 @@ import type { - AgentPart, OpencodeClient, V2Event, - FilePart, LspStatus, McpStatus, Todo, @@ -13,9 +11,10 @@ import type { QuestionRequest, Session, SessionStatus, - TextPart, Config as SdkConfig, } from "@opencode-ai/sdk/v2" +import type { PromptInput } from "@opencode-ai/schema" +import type { Types } from "effect" import type { CliRenderer, KeyEvent, RGBA, Renderable, SlotMode } from "@opentui/core" import type { Binding, Keymap } from "@opentui/keymap" import { @@ -180,22 +179,16 @@ export type TuiDialogSelectProps = { current?: Value } -export type TuiPromptInfo = { - input: string +export type TuiPromptInfo = Types.DeepMutable & { + pasted: { + text: string + source: { + start: number + end: number + text: string + } + }[] mode?: "normal" | "shell" - parts: ( - | Omit - | Omit - | (Omit & { - source?: { - text: { - start: number - end: number - value: string - } - } - }) - )[] } export type TuiPromptRef = { diff --git a/packages/schema/src/prompt.ts b/packages/schema/src/prompt.ts index ffffebbdf72..2438df2e985 100644 --- a/packages/schema/src/prompt.ts +++ b/packages/schema/src/prompt.ts @@ -13,6 +13,7 @@ export interface FileAttachment extends Schema.Schema.Type Promise; pluginHost: TuiPlugi enabled: () => { const current = promptRef.current if (!current?.focused) return true - return current.current.input === "" + return current.current.text === "" }, bindings: tuiConfig.keybinds.gather("app_exit", ["app.exit"]), })) diff --git a/packages/tui/src/component/dialog-stash.tsx b/packages/tui/src/component/dialog-stash.tsx index b306087c91d..b08886f79fa 100644 --- a/packages/tui/src/component/dialog-stash.tsx +++ b/packages/tui/src/component/dialog-stash.tsx @@ -40,9 +40,9 @@ export function DialogStash(props: { onSelect: (entry: StashEntry) => void }) { return entries .map((entry, index) => { const isDeleting = toDelete() === index - const lineCount = (entry.input.match(/\n/g)?.length ?? 0) + 1 + const lineCount = (entry.prompt.text.match(/\n/g)?.length ?? 0) + 1 return { - title: isDeleting ? `Press ${deleteHint()} again to confirm` : getStashPreview(entry.input), + title: isDeleting ? `Press ${deleteHint()} again to confirm` : getStashPreview(entry.prompt.text), bg: isDeleting ? theme.error : undefined, value: index, description: getRelativeTime(entry.timestamp), diff --git a/packages/tui/src/component/prompt/autocomplete.tsx b/packages/tui/src/component/prompt/autocomplete.tsx index fb9d1537e92..50bf0a64a26 100644 --- a/packages/tui/src/component/prompt/autocomplete.tsx +++ b/packages/tui/src/component/prompt/autocomplete.tsx @@ -18,7 +18,7 @@ import { useTheme, selectedForeground } from "../../context/theme" import { SplitBorder } from "../../ui/border" import { useTerminalDimensions } from "@opentui/solid" import { Locale } from "../../util/locale" -import type { PromptInfo } from "../../prompt/history" +import type { PromptInfo, PromptPartRef } from "../../prompt/history" import { useFrecency } from "../../prompt/frecency" import { useBindings, useCommandSlashes, useOpencodeModeStack } from "../../keymap" import { displayCharAt, mentionTriggerIndex } from "../../prompt/display" @@ -76,7 +76,7 @@ export function Autocomplete(props: { value: string sessionID?: string setPrompt: (input: (prompt: PromptInfo) => void) => void - setExtmark: (partIndex: number, extmarkId: number) => void + setExtmark: (part: PromptPartRef, extmarkId: number) => void anchor: () => BoxRenderable input: () => TextareaRenderable ref: (ref: AutocompleteRef) => void @@ -169,7 +169,12 @@ export function Autocomplete(props: { setStore("input", "keyboard") }) - function insertPart(text: string, part: PromptInfo["parts"][number]) { + function insertPart( + text: string, + part: + | { type: "file"; value: NonNullable[number]; path?: string } + | { type: "agent"; value: NonNullable[number] }, + ) { const input = props.input() const currentCursorOffset = input.cursorOffset @@ -189,7 +194,7 @@ export function Autocomplete(props: { const extmarkStart = store.index const extmarkEnd = extmarkStart + Bun.stringWidth(virtualText) - const styleId = part.type === "file" ? props.fileStyleId : part.type === "agent" ? props.agentStyleId : undefined + const styleId = part.type === "file" ? props.fileStyleId : props.agentStyleId const extmarkId = input.extmarks.create({ start: extmarkStart, @@ -201,42 +206,40 @@ export function Autocomplete(props: { props.setPrompt((draft) => { if (part.type === "file") { - const existingIndex = draft.parts.findIndex((p) => p.type === "file" && "url" in p && p.url === part.url) + const files = (draft.files ??= []) + const existingIndex = files.findIndex((file) => file.uri === part.value.uri) if (existingIndex !== -1) { - const existing = draft.parts[existingIndex] - if ( - part.source?.text && - existing && - "source" in existing && - existing.source && - "text" in existing.source && - existing.source.text - ) { - existing.source.text.start = extmarkStart - existing.source.text.end = extmarkEnd - existing.source.text.value = virtualText + const existing = files[existingIndex] + if (existing?.source) { + existing.source.start = extmarkStart + existing.source.end = extmarkEnd + existing.source.text = virtualText } return } + if (part.value.source) { + part.value.source.start = extmarkStart + part.value.source.end = extmarkEnd + part.value.source.text = virtualText + } + const index = files.length + files.push(part.value) + props.setExtmark({ type: "file", index }, extmarkId) + return } - if (part.type === "file" && part.source?.text) { - part.source.text.start = extmarkStart - part.source.text.end = extmarkEnd - part.source.text.value = virtualText - } else if (part.type === "agent" && part.source) { - part.source.start = extmarkStart - part.source.end = extmarkEnd - part.source.value = virtualText + const agents = (draft.agents ??= []) + if (part.value.source) { + part.value.source.start = extmarkStart + part.value.source.end = extmarkEnd + part.value.source.text = virtualText } - const partIndex = draft.parts.length - draft.parts.push(part) - props.setExtmark(partIndex, extmarkId) + const index = agents.length + agents.push(part.value) + props.setExtmark({ type: "agent", index }, extmarkId) }) - if (part.type === "file" && part.source && part.source.type === "file") { - frecency.updateFrecency(part.source.path) - } + if (part.type === "file" && part.path) frecency.updateFrecency(part.path) } function createFilePart( @@ -261,17 +264,11 @@ export function Autocomplete(props: { filename, part: { type: "file" as const, - mime: item.type === "directory" ? "application/x-directory" : "text/plain", - filename, - url: urlObj.href, - source: { - type: "file" as const, - text: { - start: 0, - end: 0, - value: "", - }, - path: item.path, + path: item.path, + value: { + uri: urlObj.href, + name: filename, + source: { start: 0, end: 0, text: "" }, }, }, } @@ -375,18 +372,11 @@ export function Autocomplete(props: { onSelect: () => { insertPart(res.name, { type: "file", - mime: res.mimeType ?? "text/plain", - filename: res.name, - url: res.uri, - source: { - type: "resource", - text: { - start: 0, - end: 0, - value: "", - }, - clientName: res.client, + value: { uri: res.uri, + name: res.name, + description: res.description, + source: { start: 0, end: 0, text: "" }, }, }) }, @@ -405,11 +395,9 @@ export function Autocomplete(props: { onSelect: () => { insertPart(agent.id, { type: "agent", - name: agent.id, - source: { - start: 0, - end: 0, - value: "", + value: { + name: agent.id, + source: { start: 0, end: 0, text: "" }, }, }) }, @@ -427,13 +415,11 @@ export function Autocomplete(props: { onSelect: () => { insertPart(reference.name, { type: "file", - mime: "application/x-directory", - filename: reference.name, - url: pathToFileURL(reference.path).href, - source: { - type: "file", - text: { start: 0, end: 0, value: "" }, - path: reference.name, + path: reference.name, + value: { + uri: pathToFileURL(reference.path).href, + name: reference.name, + source: { start: 0, end: 0, text: "" }, }, }) }, @@ -667,7 +653,7 @@ export function Autocomplete(props: { props.input().deleteRange(0, 0, cursor.row, cursor.col) // Sync the prompt store immediately since onContentChange is async props.setPrompt((draft) => { - draft.input = props.input().plainText + draft.text = props.input().plainText }) } setStore("visible", false) diff --git a/packages/tui/src/component/prompt/index.tsx b/packages/tui/src/component/prompt/index.tsx index 9fad2eb21c8..c7276206a90 100644 --- a/packages/tui/src/component/prompt/index.tsx +++ b/packages/tui/src/component/prompt/index.tsx @@ -30,14 +30,14 @@ import { normalizePromptContent, openEditor } from "../../editor" import { useExit } from "../../context/exit" import { promptOffsetWidth } from "../../prompt/display" import { createStore, produce, unwrap } from "solid-js/store" -import { usePromptHistory, type PromptInfo } from "../../prompt/history" +import { emptyPrompt, usePromptHistory, type PromptInfo, type PromptPartRef } from "../../prompt/history" import { computePromptTraits } from "../../prompt/traits" import { expandPastedTextPlaceholders, expandTrackedPastedText } from "../../prompt/part" import { usePromptStash } from "../../prompt/stash" import { DialogStash } from "../dialog-stash" import { type AutocompleteRef, Autocomplete } from "./autocomplete" import { useRenderer, useTerminalDimensions, type JSX } from "@opentui/solid" -import type { AssistantMessage, FilePart, SessionV2Info, UserMessage } from "@opencode-ai/sdk/v2" +import type { AssistantMessage, SessionV2Info, UserMessage } from "@opencode-ai/sdk/v2" import { Locale } from "../../util/locale" import { errorMessage } from "../../util/error" import { createColors, createFrames } from "../../ui/spinner" @@ -311,17 +311,14 @@ export function Prompt(props: PromptProps) { const [store, setStore] = createStore<{ prompt: PromptInfo mode: "normal" | "shell" - extmarkToPartIndex: Map + extmarkToPart: Map interrupt: number placeholder: number }>({ placeholder: randomIndex(list().length), - prompt: { - input: "", - parts: [], - }, + prompt: emptyPrompt(), mode: "normal", - extmarkToPartIndex: new Map(), + extmarkToPart: new Map(), interrupt: 0, }) @@ -398,8 +395,7 @@ export function Prompt(props: PromptProps) { if (content?.mime.startsWith("image/")) { await pasteAttachment({ filename: "clipboard", - mime: content.mime, - content: content.data, + uri: `data:${content.mime};base64,${content.data}`, }) return } @@ -465,14 +461,10 @@ export function Prompt(props: PromptProps) { dialog.clear() // replace summarized text parts with the actual text - const text = store.prompt.parts - .filter((p) => p.type === "text") - .reduce((acc, p) => { - if (!p.source) return acc - return acc.replace(p.source.text.value, p.text) - }, store.prompt.input) - - const nonTextParts = store.prompt.parts.filter((p) => p.type !== "text") + const text = store.prompt.pasted.reduce( + (result, part) => result.replace(part.source.text, part.text), + store.prompt.text, + ) const value = text const content = await openEditor({ @@ -488,63 +480,23 @@ export function Prompt(props: PromptProps) { input.setText(normalized) - // Update positions for nonTextParts based on their location in new content - // Filter out parts whose virtual text was deleted + // Update attachment positions and drop virtual text deleted in the editor. // this handles a case where the user edits the text in the editor // such that the virtual text moves around or is deleted - const updatedNonTextParts = nonTextParts - .map((part) => { - let virtualText = "" - if (part.type === "file" && part.source?.text) { - virtualText = part.source.text.value - } else if (part.type === "agent" && part.source) { - virtualText = part.source.value - } - - if (!virtualText) return part - - const newStart = normalized.indexOf(virtualText) - // if the virtual text is deleted, remove the part - if (newStart === -1) return null - - const newEnd = newStart + virtualText.length - - if (part.type === "file" && part.source?.text) { - return { - ...part, - source: { - ...part.source, - text: { - ...part.source.text, - start: newStart, - end: newEnd, - }, - }, - } - } - - if (part.type === "agent" && part.source) { - return { - ...part, - source: { - ...part.source, - start: newStart, - end: newEnd, - }, - } - } - - return part - }) - .filter((part) => part !== null) + const moveSource = (part: Part) => { + if (!part.source?.text) return part + const start = normalized.indexOf(part.source.text) + if (start === -1) return + return { ...part, source: { ...part.source, start, end: start + part.source.text.length } } + } setStore("prompt", { - input: normalized, - // keep only the non-text parts because the text parts were - // already expanded inline - parts: updatedNonTextParts, + text: normalized, + files: store.prompt.files?.map(moveSource).filter((part) => part !== undefined), + agents: store.prompt.agents?.map(moveSource).filter((part) => part !== undefined), + pasted: [], }) - restoreExtmarksFromParts(updatedNonTextParts) + restoreExtmarksFromPrompt(store.prompt) input.cursorOffset = Bun.stringWidth(normalized) }, }, @@ -560,8 +512,8 @@ export function Prompt(props: PromptProps) { onSelect={(skill) => { input.setText(`/${skill} `) setStore("prompt", { - input: `/${skill} `, - parts: [], + ...emptyPrompt(), + text: `/${skill} `, }) input.gotoBufferEnd() }} @@ -631,19 +583,16 @@ export function Prompt(props: PromptProps) { input.blur() }, set(prompt) { - input.setText(prompt.input) + input.setText(prompt.text) setStore("prompt", prompt) - restoreExtmarksFromParts(prompt.parts) + restoreExtmarksFromPrompt(prompt) input.gotoBufferEnd() }, reset() { input.clear() input.extmarks.clear() - setStore("prompt", { - input: "", - parts: [], - }) - setStore("extmarkToPartIndex", new Map()) + setStore("prompt", emptyPrompt()) + setStore("extmarkToPart", new Map()) }, submit() { void submit() @@ -653,17 +602,17 @@ export function Prompt(props: PromptProps) { onMount(() => { const saved = stashed stashed = undefined - if (store.prompt.input) return - if (saved && saved.prompt.input) { - input.setText(saved.prompt.input) + if (store.prompt.text) return + if (saved && saved.prompt.text) { + input.setText(saved.prompt.text) setStore("prompt", saved.prompt) - restoreExtmarksFromParts(saved.prompt.parts) + restoreExtmarksFromPrompt(saved.prompt) input.cursorOffset = saved.cursor } }) onCleanup(() => { - if (store.prompt.input) { + if (store.prompt.text) { stashed = { prompt: unwrap(store.prompt), cursor: input.cursorOffset } } setInputTarget(undefined) @@ -693,44 +642,28 @@ export function Prompt(props: PromptProps) { } }) - function restoreExtmarksFromParts(parts: PromptInfo["parts"]) { + function restoreExtmarksFromPrompt(prompt: PromptInfo) { input.extmarks.clear() - setStore("extmarkToPartIndex", new Map()) + setStore("extmarkToPart", new Map()) - parts.forEach((part, partIndex) => { - let start = 0 - let end = 0 - let virtualText = "" - let styleId: number | undefined + const parts = [ + ...(prompt.files ?? []).map((part, index) => ({ part, ref: { type: "file" as const, index }, styleId: fileStyleId })), + ...(prompt.agents ?? []).map((part, index) => ({ part, ref: { type: "agent" as const, index }, styleId: agentStyleId })), + ...prompt.pasted.map((part, index) => ({ part, ref: { type: "pasted" as const, index }, styleId: pasteStyleId })), + ] - if (part.type === "file" && part.source?.text) { - start = part.source.text.start - end = part.source.text.end - virtualText = part.source.text.value - styleId = fileStyleId - } else if (part.type === "agent" && part.source) { - start = part.source.start - end = part.source.end - virtualText = part.source.value - styleId = agentStyleId - } else if (part.type === "text" && part.source?.text) { - start = part.source.text.start - end = part.source.text.end - virtualText = part.source.text.value - styleId = pasteStyleId - } - - if (virtualText) { + parts.forEach(({ part, ref, styleId }) => { + if (part.source?.text) { const extmarkId = input.extmarks.create({ - start, - end, + start: part.source.start, + end: part.source.end, virtual: true, styleId, typeId: promptPartTypeId, }) - setStore("extmarkToPartIndex", (map: Map) => { + setStore("extmarkToPart", (map: Map) => { const newMap = new Map(map) - newMap.set(extmarkId, partIndex) + newMap.set(extmarkId, ref) return newMap }) } @@ -741,32 +674,47 @@ export function Prompt(props: PromptProps) { const allExtmarks = input.extmarks.getAllForTypeId(promptPartTypeId) setStore( produce((draft) => { - const newMap = new Map() - const newParts: typeof draft.prompt.parts = [] + const newMap = new Map() + const files: NonNullable = [] + const agents: NonNullable = [] + const pasted: PromptInfo["pasted"] = [] for (const extmark of allExtmarks) { - const partIndex = draft.extmarkToPartIndex.get(extmark.id) - if (partIndex !== undefined) { - const part = draft.prompt.parts[partIndex] - if (part) { - if (part.type === "agent" && part.source) { - part.source.start = extmark.start - part.source.end = extmark.end - } else if (part.type === "file" && part.source?.text) { - part.source.text.start = extmark.start - part.source.text.end = extmark.end - } else if (part.type === "text" && part.source?.text) { - part.source.text.start = extmark.start - part.source.text.end = extmark.end - } - newMap.set(extmark.id, newParts.length) - newParts.push(part) - } + const ref = draft.extmarkToPart.get(extmark.id) + if (!ref) continue + if (ref.type === "file") { + const part = draft.prompt.files?.[ref.index] + if (!part?.source) continue + part.source.start = extmark.start + part.source.end = extmark.end + const index = files.length + files.push(part) + newMap.set(extmark.id, { type: "file", index }) + continue } + if (ref.type === "agent") { + const part = draft.prompt.agents?.[ref.index] + if (!part?.source) continue + part.source.start = extmark.start + part.source.end = extmark.end + const index = agents.length + agents.push(part) + newMap.set(extmark.id, { type: "agent", index }) + continue + } + const part = draft.prompt.pasted[ref.index] + if (!part) continue + part.source.start = extmark.start + part.source.end = extmark.end + const index = pasted.length + pasted.push(part) + newMap.set(extmark.id, { type: "pasted", index }) } - draft.extmarkToPartIndex = newMap - draft.prompt.parts = newParts + draft.extmarkToPart = newMap + draft.prompt.files = files + draft.prompt.agents = agents + draft.prompt.pasted = pasted }), ) } @@ -777,17 +725,14 @@ export function Prompt(props: PromptProps) { title: "Stash prompt", name: "prompt.stash", category: "Prompt", - enabled: !!store.prompt.input, + enabled: !!store.prompt.text, run: () => { - if (!store.prompt.input) return - stash.push({ - input: store.prompt.input, - parts: store.prompt.parts, - }) + if (!store.prompt.text) return + stash.push({ prompt: store.prompt }) input.extmarks.clear() input.clear() - setStore("prompt", { input: "", parts: [] }) - setStore("extmarkToPartIndex", new Map()) + setStore("prompt", emptyPrompt()) + setStore("extmarkToPart", new Map()) dialog.clear() }, }, @@ -799,9 +744,9 @@ export function Prompt(props: PromptProps) { run: () => { const entry = stash.pop() if (entry) { - input.setText(entry.input) - setStore("prompt", { input: entry.input, parts: entry.parts }) - restoreExtmarksFromParts(entry.parts) + input.setText(entry.prompt.text) + setStore("prompt", entry.prompt) + restoreExtmarksFromPrompt(entry.prompt) input.gotoBufferEnd() } dialog.clear() @@ -816,9 +761,9 @@ export function Prompt(props: PromptProps) { dialog.replace(() => ( { - input.setText(entry.input) - setStore("prompt", { input: entry.input, parts: entry.parts }) - restoreExtmarksFromParts(entry.parts) + input.setText(entry.prompt.text) + setStore("prompt", entry.prompt) + restoreExtmarksFromPrompt(entry.prompt) input.gotoBufferEnd() }} /> @@ -846,7 +791,7 @@ export function Prompt(props: PromptProps) { useBindings(() => { return { target: inputTarget, - enabled: inputTarget() !== undefined && !props.disabled && store.prompt.input !== "", + enabled: inputTarget() !== undefined && !props.disabled && store.prompt.text !== "", bindings: tuiConfig.keybinds.get("prompt.clear"), } }) @@ -917,10 +862,10 @@ export function Prompt(props: PromptProps) { const item = history.move(-1, input.plainText) if (!item) return false - input.setText(item.input) + input.setText(item.text) setStore("prompt", item) setStore("mode", item.mode ?? "normal") - restoreExtmarksFromParts(item.parts) + restoreExtmarksFromPrompt(item) input.cursorOffset = 0 }, }, @@ -953,10 +898,10 @@ export function Prompt(props: PromptProps) { const item = history.move(1, input.plainText) if (!item) return false - input.setText(item.input) + input.setText(item.text) setStore("prompt", item) setStore("mode", item.mode ?? "normal") - restoreExtmarksFromParts(item.parts) + restoreExtmarksFromPrompt(item) input.cursorOffset = input.plainText.length }, }, @@ -970,7 +915,7 @@ export function Prompt(props: PromptProps) { // Prevent overlapping invocations (e.g. a double-pressed Enter, or the // input's native onSubmit racing another dispatch). Without this guard, // a second call slips past the empty-input check before the first call - // clears `store.prompt.input`, then awaits its own `session.create` and + // clears `store.prompt.text`, then awaits its own `session.create` and // ultimately reads the now-empty store — sending a phantom empty prompt // to a freshly created session. if (submitting) return false @@ -988,17 +933,17 @@ export function Prompt(props: PromptProps) { // IME: double-defer may fire before onContentChange flushes the last // composed character (e.g. Korean hangul) to the store, so read // plainText directly and sync before any downstream reads. - if (input && !input.isDestroyed && input.plainText !== store.prompt.input) { - setStore("prompt", "input", input.plainText) + if (input && !input.isDestroyed && input.plainText !== store.prompt.text) { + setStore("prompt", "text", input.plainText) syncExtmarksWithPromptParts() } if (props.disabled) return false if (workspace.creating() || move.creating()) return false if (auto()?.visible) return false - if (!store.prompt.input) return false + if (!store.prompt.text) return false const agent = local.agent.current() if (!agent) return false - const trimmed = store.prompt.input.trim() + const trimmed = store.prompt.text.trim() if (trimmed === "exit" || trimmed === "quit" || trimmed === ":q") { void exit() return true @@ -1032,7 +977,7 @@ export function Prompt(props: PromptProps) { const selectedWorkspace = workspace.selection() const workspaceID = selectedWorkspace?.type === "existing" ? selectedWorkspace.workspaceID : undefined - const directory = await move.getDirectory(store.prompt.input) + const directory = await move.getDirectory(store.prompt.text) if (move.pending() && !directory) return false finishMoveProgress = Boolean(move.progress()) const location = data.location.default() @@ -1067,18 +1012,16 @@ export function Prompt(props: PromptProps) { } const inputText = expandTrackedPastedText( - store.prompt.input, + store.prompt.text, input.extmarks.getAllForTypeId(promptPartTypeId).flatMap((extmark) => { - const partIndex = store.extmarkToPartIndex.get(extmark.id) - const part = partIndex === undefined ? undefined : store.prompt.parts[partIndex] - if (part?.type !== "text") return [] + const ref = store.extmarkToPart.get(extmark.id) + if (ref?.type !== "pasted") return [] + const part = store.prompt.pasted[ref.index] + if (!part) return [] return [{ start: extmark.start, end: extmark.end, text: part.text }] }), ) - // Filter out text parts (pasted content) since they're now expanded inline - const nonTextParts = store.prompt.parts.filter((part) => part.type !== "text") - // Capture mode before it gets reset const currentMode = store.mode const editorSelection = editorContext() @@ -1127,35 +1070,8 @@ export function Prompt(props: PromptProps) { arguments: args, agent: agent.id, model: { providerID: selectedModel.providerID, id: selectedModel.modelID, variant }, - files: nonTextParts.flatMap((part) => - part.type === "file" - ? [ - { - uri: part.url, - name: part.filename, - source: part.source - ? { - start: part.source.text.start, - end: part.source.text.end, - text: part.source.text.value, - } - : undefined, - }, - ] - : [], - ), - agents: nonTextParts.flatMap((part) => - part.type === "agent" - ? [ - { - name: part.name, - source: part.source - ? { start: part.source.start, end: part.source.end, text: part.source.value } - : undefined, - }, - ] - : [], - ), + files: store.prompt.files, + agents: store.prompt.agents, }) .catch((error) => { toast.show({ title: "Failed to run command", message: errorMessage(error), variant: "error" }) @@ -1205,35 +1121,8 @@ export function Prompt(props: PromptProps) { sessionID, prompt: { text: [...editorParts.map((part) => part.text), inputText].filter(Boolean).join("\n\n"), - files: nonTextParts.flatMap((part) => - part.type === "file" - ? [ - { - uri: part.url, - name: part.filename, - source: part.source - ? { - start: part.source.text.start, - end: part.source.text.end, - text: part.source.text.value, - } - : undefined, - }, - ] - : [], - ), - agents: nonTextParts.flatMap((part) => - part.type === "agent" - ? [ - { - name: part.name, - source: part.source - ? { start: part.source.start, end: part.source.end, text: part.source.value } - : undefined, - }, - ] - : [], - ), + files: store.prompt.files, + agents: store.prompt.agents, }, }) .then( @@ -1251,11 +1140,8 @@ export function Prompt(props: PromptProps) { mode: currentMode, }) input.extmarks.clear() - setStore("prompt", { - input: "", - parts: [], - }) - setStore("extmarkToPartIndex", new Map()) + setStore("prompt", emptyPrompt()) + setStore("extmarkToPart", new Map()) props.onSubmit?.() // temporary hack to make sure the message is sent @@ -1290,19 +1176,12 @@ export function Prompt(props: PromptProps) { setStore( produce((draft) => { - const partIndex = draft.prompt.parts.length - draft.prompt.parts.push({ - type: "text" as const, + const index = draft.prompt.pasted.length + draft.prompt.pasted.push({ text, - source: { - text: { - start: extmarkStart, - end: extmarkEnd, - value: virtualText, - }, - }, + source: { start: extmarkStart, end: extmarkEnd, text: virtualText }, }) - draft.extmarkToPartIndex.set(extmarkId, partIndex) + draft.extmarkToPart.set(extmarkId, { type: "pasted", index }) }), ) } @@ -1322,9 +1201,7 @@ export function Prompt(props: PromptProps) { if (attachment?.type === "binary") { await pasteAttachment({ filename, - filepath, - mime: attachment.mime, - content: Buffer.from(attachment.content).toString("base64"), + uri: `data:${attachment.mime};base64,${Buffer.from(attachment.content).toString("base64")}`, }) return } @@ -1348,15 +1225,12 @@ export function Prompt(props: PromptProps) { }, 0) } - async function pasteAttachment(file: { filename?: string; filepath?: string; content: string; mime: string }) { + async function pasteAttachment(file: { filename?: string; uri: string }) { const currentOffset = input.cursorOffset const extmarkStart = currentOffset - const pdf = file.mime === "application/pdf" - const count = store.prompt.parts.filter((x) => { - if (x.type !== "file") return false - if (pdf) return x.mime === "application/pdf" - return x.mime.startsWith("image/") - }).length + const pdf = file.uri.startsWith("data:application/pdf;") + const prefix = pdf ? "data:application/pdf;" : "data:image/" + const count = store.prompt.files?.filter((attachment) => attachment.uri.startsWith(prefix)).length ?? 0 const virtualText = pdf ? `[PDF ${count + 1}]` : `[Image ${count + 1}]` const extmarkEnd = extmarkStart + virtualText.length const textToInsert = virtualText + " " @@ -1371,33 +1245,33 @@ export function Prompt(props: PromptProps) { typeId: promptPartTypeId, }) - const part: Omit = { - type: "file" as const, - mime: file.mime, - filename: file.filename, - url: `data:${file.mime};base64,${file.content}`, + const part: NonNullable[number] = { + uri: file.uri, + name: file.filename, source: { - type: "file", - path: file.filepath ?? file.filename ?? "", - text: { - start: extmarkStart, - end: extmarkEnd, - value: virtualText, - }, + start: extmarkStart, + end: extmarkEnd, + text: virtualText, }, } setStore( produce((draft) => { - const partIndex = draft.prompt.parts.length - draft.prompt.parts.push(part) - draft.extmarkToPartIndex.set(extmarkId, partIndex) + const files = (draft.prompt.files ??= []) + const index = files.length + files.push(part) + draft.extmarkToPart.set(extmarkId, { type: "file", index }) }), ) return } function clearPrompt() { - if (store.prompt.input.trim().length >= DRAFT_RETENTION_MIN_CHARS || store.prompt.parts.length > 0) { + if ( + store.prompt.text.trim().length >= DRAFT_RETENTION_MIN_CHARS || + store.prompt.pasted.length > 0 || + (store.prompt.files?.length ?? 0) > 0 || + (store.prompt.agents?.length ?? 0) > 0 + ) { history.append({ ...store.prompt, mode: store.mode, @@ -1405,11 +1279,8 @@ export function Prompt(props: PromptProps) { } input.clear() input.extmarks.clear() - setStore("prompt", { - input: "", - parts: [], - }) - setStore("extmarkToPartIndex", new Map()) + setStore("prompt", emptyPrompt()) + setStore("extmarkToPart", new Map()) } const highlight = createMemo(() => { @@ -1503,7 +1374,7 @@ export function Prompt(props: PromptProps) { maxHeight={maxHeight()} onContentChange={() => { const value = input.plainText - setStore("prompt", "input", value) + setStore("prompt", "text", value) auto()?.onInput(value) syncExtmarksWithPromptParts() setCursorVersion((value) => value + 1) @@ -1548,7 +1419,7 @@ export function Prompt(props: PromptProps) { ref={(r: TextareaRenderable) => { input = r Object.assign(r, { - getClipboardText: (text: string) => expandPastedTextPlaceholders(text, store.prompt.parts), + getClipboardText: (text: string) => expandPastedTextPlaceholders(text, store.prompt.pasted), }) setInputTarget(r) if (promptPartTypeId === 0) { @@ -1761,14 +1632,14 @@ export function Prompt(props: PromptProps) { setPrompt={(cb) => { setStore("prompt", produce(cb)) }} - setExtmark={(partIndex, extmarkId) => { - setStore("extmarkToPartIndex", (map: Map) => { + setExtmark={(part, extmarkId) => { + setStore("extmarkToPart", (map: Map) => { const newMap = new Map(map) - newMap.set(extmarkId, partIndex) + newMap.set(extmarkId, part) return newMap }) }} - value={store.prompt.input} + value={store.prompt.text} fileStyleId={fileStyleId} agentStyleId={agentStyleId} promptPartTypeId={() => promptPartTypeId} diff --git a/packages/tui/src/prompt/history.tsx b/packages/tui/src/prompt/history.tsx index e795d11da48..fa69fedbb2f 100644 --- a/packages/tui/src/prompt/history.tsx +++ b/packages/tui/src/prompt/history.tsx @@ -1,29 +1,33 @@ import path from "path" import { onMount } from "solid-js" import { createStore, produce, unwrap } from "solid-js/store" -import type { AgentPart, FilePart, TextPart } from "@opencode-ai/sdk/v2" +import type { SessionPromptInput } from "@opencode-ai/client/promise" +import type { Types } from "effect" import { createSimpleContext } from "../context/helper" import { useTuiPaths } from "../context/runtime" import { appendText, readText, writeText } from "../util/persistence" -export type PromptInfo = { - input: string - mode?: "normal" | "shell" - parts: ( - | Omit - | Omit - | (Omit & { - source?: { - text: { - start: number - end: number - value: string - } - } - }) - )[] +export type PastedText = { + text: string + source: { + start: number + end: number + text: string + } } +export type PromptInfo = Types.DeepMutable & { + pasted: PastedText[] + mode?: "normal" | "shell" +} + +export type PromptPartRef = { + type: "file" | "agent" | "pasted" + index: number +} + +export const emptyPrompt = (): PromptInfo => ({ text: "", files: [], agents: [], pasted: [] }) + export const MAX_HISTORY_ENTRIES = 50 export function parsePromptHistory(text: string) { @@ -32,7 +36,7 @@ export function parsePromptHistory(text: string) { .filter(Boolean) .map((line) => { try { - return JSON.parse(line) as PromptInfo + return parsePromptInfo(JSON.parse(line)) } catch { return undefined } @@ -46,6 +50,13 @@ export function isDuplicateEntry(previous: PromptInfo | undefined, next: PromptI return JSON.stringify(previous) === JSON.stringify(next) } +export function parsePromptInfo(value: unknown): PromptInfo | undefined { + if (!value || typeof value !== "object") return + const input = value as Record + if (typeof input.text !== "string" || !Array.isArray(input.pasted)) return + return input as PromptInfo +} + export const { use: usePromptHistory, provider: PromptHistoryProvider } = createSimpleContext({ name: "PromptHistory", init: () => { @@ -70,7 +81,7 @@ export const { use: usePromptHistory, provider: PromptHistoryProvider } = create if (!store.history.length) return undefined const current = store.history.at(store.index) if (!current) return undefined - if (current.input !== input && input.length) return + if (current.text !== input && input.length) return setStore( produce((draft) => { const next = store.index + direction @@ -79,7 +90,7 @@ export const { use: usePromptHistory, provider: PromptHistoryProvider } = create draft.index = next }), ) - if (store.index === 0) return { input: "", parts: [] } + if (store.index === 0) return emptyPrompt() return store.history.at(store.index) }, append(item: PromptInfo) { diff --git a/packages/tui/src/prompt/part.ts b/packages/tui/src/prompt/part.ts index 0027b9aaed7..179c5272422 100644 --- a/packages/tui/src/prompt/part.ts +++ b/packages/tui/src/prompt/part.ts @@ -1,24 +1,10 @@ import { displaySlice } from "./display" -export function stripPromptPartIDs(part: Part) { - const { id: _id, messageID: _messageID, sessionID: _sessionID, ...rest } = part - return rest -} - -export function expandPastedTextPlaceholders(text: string, parts: readonly unknown[]) { - return parts.reduce((result, part) => { - if (!isPastedTextPart(part)) return result - return result.replace(part.source.text.value, part.text) - }, text) -} - -function isPastedTextPart(part: unknown): part is { type: "text"; text: string; source: { text: { value: string } } } { - if (!part || typeof part !== "object" || !("type" in part) || part.type !== "text") return false - if (!("text" in part) || typeof part.text !== "string" || !("source" in part)) return false - const source = part.source - if (!source || typeof source !== "object" || !("text" in source)) return false - const text = source.text - return Boolean(text && typeof text === "object" && "value" in text && typeof text.value === "string") +export function expandPastedTextPlaceholders( + text: string, + pasted: readonly { text: string; source: { text: string } }[], +) { + return pasted.reduce((result, part) => result.replace(part.source.text, part.text), text) } export function expandTrackedPastedText(text: string, ranges: { start: number; end: number; text: string }[]) { diff --git a/packages/tui/src/prompt/stash.tsx b/packages/tui/src/prompt/stash.tsx index d43ee0eb423..46a44ccfd6d 100644 --- a/packages/tui/src/prompt/stash.tsx +++ b/packages/tui/src/prompt/stash.tsx @@ -4,11 +4,10 @@ import { createStore, produce, unwrap } from "solid-js/store" import { createSimpleContext } from "../context/helper" import { useTuiPaths } from "../context/runtime" import { appendText, readText, writeText } from "../util/persistence" -import type { PromptInfo } from "./history" +import { parsePromptInfo, type PromptInfo } from "./history" export type StashEntry = { - input: string - parts: PromptInfo["parts"] + prompt: PromptInfo timestamp: number } @@ -20,7 +19,12 @@ export function parsePromptStash(text: string) { .filter(Boolean) .map((line) => { try { - return JSON.parse(line) as StashEntry + const value = JSON.parse(line) as unknown + if (!value || typeof value !== "object") return + const entry = value as Record + const prompt = parsePromptInfo(entry.prompt) + if (!prompt || typeof entry.timestamp !== "number") return + return { prompt, timestamp: entry.timestamp } } catch { return undefined } diff --git a/packages/tui/src/routes/home.tsx b/packages/tui/src/routes/home.tsx index d4145e2d87b..d4074da3a5d 100644 --- a/packages/tui/src/routes/home.tsx +++ b/packages/tui/src/routes/home.tsx @@ -51,7 +51,7 @@ export function Home() { return } if (!args.prompt) return - r.set({ input: args.prompt, parts: [] }) + r.set({ text: args.prompt, files: [], agents: [], pasted: [] }) once = true } @@ -62,7 +62,7 @@ export function Home() { if (!r) return if (!sync.ready || !local.model.ready) return if (!args.prompt) return - if (r.current.input !== args.prompt) return + if (r.current.text !== args.prompt) return sent = true r.submit() }) diff --git a/packages/tui/src/routes/session/dialog-fork-from-timeline.tsx b/packages/tui/src/routes/session/dialog-fork-from-timeline.tsx index 4cc9b59c00a..d056ad5bae1 100644 --- a/packages/tui/src/routes/session/dialog-fork-from-timeline.tsx +++ b/packages/tui/src/routes/session/dialog-fork-from-timeline.tsx @@ -6,8 +6,7 @@ import { Locale } from "../../util/locale" import { useSDK } from "../../context/sdk" import { useRoute } from "../../context/route" import { useDialog, type DialogContext } from "../../ui/dialog" -import type { PromptInfo } from "../../component/prompt/history" -import { stripPromptPartIDs as strip } from "../../prompt/part" +import { emptyPrompt, type PromptInfo } from "../../component/prompt/history" export function DialogForkFromTimeline(props: { sessionID: string; onMove: (messageID?: string) => void }) { const sync = useSync() @@ -53,12 +52,25 @@ export function DialogForkFromTimeline(props: { sessionID: string; onMove: (mess const prompt = parts.reduce( (agg, part) => { if (part.type === "text") { - if (!part.synthetic) agg.input += part.text + if (!part.synthetic) agg.text += part.text + } + if (part.type === "file") { + const files = (agg.files ??= []) + files.push({ + uri: part.url, + name: part.filename, + source: part.source?.text + ? { + start: part.source.text.start, + end: part.source.text.end, + text: part.source.text.value, + } + : undefined, + }) } - if (part.type === "file") agg.parts.push(strip(part)) return agg }, - { input: "", parts: [] as PromptInfo["parts"] }, + emptyPrompt() as PromptInfo, ) route.navigate({ sessionID: forked.data!.id, diff --git a/packages/tui/src/routes/session/index.tsx b/packages/tui/src/routes/session/index.tsx index 194ab498cf6..5a52f11c873 100644 --- a/packages/tui/src/routes/session/index.tsx +++ b/packages/tui/src/routes/session/index.tsx @@ -1420,11 +1420,11 @@ function UserMessage(props: { message: SessionMessageUser }) { {(file) => { - const directory = file.mime === "application/x-directory" + const label = file.mime === "application/x-directory" ? "Directory" : file.mime return ( - {directory ? " Directory " : " File "} + {` ${label} `} {" "} diff --git a/packages/tui/test/cli/tui/prompt-submit-race.test.ts b/packages/tui/test/cli/tui/prompt-submit-race.test.ts index fb85a7f5b12..c758762bfb0 100644 --- a/packages/tui/test/cli/tui/prompt-submit-race.test.ts +++ b/packages/tui/test/cli/tui/prompt-submit-race.test.ts @@ -5,9 +5,9 @@ import { describe, expect, test } from "bun:test" // // Before the fix, two concurrent `submit()` calls (e.g. a double-pressed // Enter, or the input's native onSubmit racing another dispatch) each -// passed the `if (!store.prompt.input) return false` guard, each +// passed the `if (!store.prompt.text) return false` guard, each // `await sdk.client.session.create(...)`, and each only captured -// `inputText = store.prompt.input` AFTER that await. The first invocation +// `inputText = store.prompt.text` AFTER that await. The first invocation // finished, sent the prompt, and cleared the store; the second invocation, // now past its await, read the cleared store and sent an empty prompt to a // second freshly-created session - leaving an orphaned session with the diff --git a/packages/tui/test/prompt/history.test.ts b/packages/tui/test/prompt/history.test.ts index ebd3660d405..1442f8fdf9e 100644 --- a/packages/tui/test/prompt/history.test.ts +++ b/packages/tui/test/prompt/history.test.ts @@ -1,7 +1,12 @@ import { describe, expect, test } from "bun:test" import { isDuplicateEntry, MAX_HISTORY_ENTRIES, parsePromptHistory, type PromptInfo } from "../../src/prompt/history" -const entry = (input: string, parts: PromptInfo["parts"] = []): PromptInfo => ({ input, parts }) +const entry = (text: string, files: PromptInfo["files"] = []): PromptInfo => ({ + text, + files, + agents: [], + pasted: [], +}) describe("prompt history", () => { test("recovers valid JSONL entries around corruption", () => { @@ -11,13 +16,17 @@ describe("prompt history", () => { ]) }) + test("ignores the legacy parts shape", () => { + expect(parsePromptHistory(JSON.stringify({ input: "old", parts: [] }))).toEqual([]) + }) + test("retains only the newest entries", () => { const input = Array.from({ length: MAX_HISTORY_ENTRIES + 5 }, (_, index) => JSON.stringify(entry(String(index))), ).join("\n") const result = parsePromptHistory(input) expect(result).toHaveLength(MAX_HISTORY_ENTRIES) - expect(result[0]?.input).toBe("5") + expect(result[0]?.text).toBe("5") }) test("dedupes only identical consecutive entries", () => { @@ -27,13 +36,10 @@ describe("prompt history", () => { expect(isDuplicateEntry({ ...entry("ls"), mode: "normal" }, { ...entry("ls"), mode: "shell" })).toBe(false) }) - test("does not dedupe entries with different parts", () => { - const a = entry("describe this", [ - { type: "file", mime: "image/png", filename: "a.png", url: "data:image/png;base64,AAA" }, - ]) - const b = entry("describe this", [ - { type: "file", mime: "image/png", filename: "b.png", url: "data:image/png;base64,BBB" }, - ]) + test("does not dedupe entries with different attachments", () => { + const a = entry("describe this", [{ name: "a.png", uri: "data:image/png;base64,AAA" }]) + const b = entry("describe this", [{ name: "b.png", uri: "data:image/png;base64,BBB" }]) expect(isDuplicateEntry(a, b)).toBe(false) }) + }) diff --git a/packages/tui/test/prompt/jsonl.test.ts b/packages/tui/test/prompt/jsonl.test.ts index e8afd4aefb9..347a359144d 100644 --- a/packages/tui/test/prompt/jsonl.test.ts +++ b/packages/tui/test/prompt/jsonl.test.ts @@ -4,12 +4,12 @@ import { MAX_STASH_ENTRIES, parsePromptStash } from "../../src/prompt/stash" test("stash JSONL skips corruption and retains newest entries", () => { const entries = Array.from({ length: MAX_STASH_ENTRIES + 2 }, (_, index) => - JSON.stringify({ input: String(index), parts: [], timestamp: index }), + JSON.stringify({ prompt: { text: String(index), files: [], agents: [], pasted: [] }, timestamp: index }), ) entries.splice(2, 0, "broken") const result = parsePromptStash(entries.join("\n")) expect(result).toHaveLength(MAX_STASH_ENTRIES) - expect(result[0]?.input).toBe("2") + expect(result[0]?.prompt.text).toBe("2") }) test("frecency JSONL skips corruption, keeps latest path state, and limits entries", () => { diff --git a/packages/tui/test/prompt/part.test.ts b/packages/tui/test/prompt/part.test.ts index 2d5605ac0c4..91bbc8e258a 100644 --- a/packages/tui/test/prompt/part.test.ts +++ b/packages/tui/test/prompt/part.test.ts @@ -1,26 +1,7 @@ import { describe, expect, test } from "bun:test" -import { expandTrackedPastedText, stripPromptPartIDs } from "../../src/prompt/part" +import { expandTrackedPastedText } from "../../src/prompt/part" describe("prompt part", () => { - test("strips persisted IDs from reused parts", () => { - expect( - stripPromptPartIDs({ - id: "prt_old", - sessionID: "ses_old", - messageID: "msg_old", - type: "file" as const, - mime: "image/png", - filename: "tiny.png", - url: "data:image/png;base64,abc", - }), - ).toEqual({ - type: "file", - mime: "image/png", - filename: "tiny.png", - url: "data:image/png;base64,abc", - }) - }) - test("preserves wide characters around pasted text", () => { const marker = "[Pasted ~3 lines]" const prefix = "你好你好\n" From 4d100de1944764f6d2dbfbeafb859655b45832ca Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 6 Jul 2026 15:04:23 -0400 Subject: [PATCH 15/46] feat(core): resolve prompt attachments --- .../client/src/promise/generated/client.ts | 4 +- .../client/src/promise/generated/types.ts | 126 +++++----- .../client/test/contract-identity.test.ts | 2 - packages/core/src/mime.ts | 56 +---- packages/core/src/session.ts | 117 +++++++-- packages/core/src/session/compaction.ts | 6 +- packages/core/src/session/input.ts | 2 +- packages/core/src/session/prompt.ts | 1 - .../core/src/session/runner/to-llm-message.ts | 32 +-- packages/core/src/session/sql.ts | 2 +- packages/core/test/session-compact.test.ts | 2 +- packages/core/test/session-create.test.ts | 16 +- packages/core/test/session-projector.test.ts | 2 +- packages/core/test/session-prompt.test.ts | 160 +++++++++--- .../core/test/session-runner-message.test.ts | 62 ++++- .../core/test/session-runner-recorded.test.ts | 4 +- packages/core/test/session-runner.test.ts | 238 +++++++++--------- packages/core/test/session-title.test.ts | 2 +- packages/core/test/shared-schema.test.ts | 8 +- packages/protocol/src/groups/session.ts | 10 +- packages/schema/src/index.ts | 2 +- packages/schema/src/prompt-input.ts | 4 +- packages/schema/src/prompt.ts | 33 ++- packages/sdk/js/src/v2/gen/types.gen.ts | 50 ++-- packages/server/src/handlers/session.ts | 7 + .../tui/src/component/prompt/autocomplete.tsx | 32 +-- packages/tui/src/component/prompt/index.tsx | 52 ++-- .../session/dialog-fork-from-timeline.tsx | 2 +- packages/tui/src/routes/session/index.tsx | 2 +- 29 files changed, 610 insertions(+), 426 deletions(-) delete mode 100644 packages/core/src/session/prompt.ts diff --git a/packages/client/src/promise/generated/client.ts b/packages/client/src/promise/generated/client.ts index 929bc2ecb6d..e042859b91d 100644 --- a/packages/client/src/promise/generated/client.ts +++ b/packages/client/src/promise/generated/client.ts @@ -477,7 +477,7 @@ export function make(options: ClientOptions) { path: `/api/session/${encodeURIComponent(input.sessionID)}/prompt`, body: { id: input["id"], prompt: input["prompt"], delivery: input["delivery"], resume: input["resume"] }, successStatus: 200, - declaredStatuses: [409, 404, 400, 401], + declaredStatuses: [409, 400, 404, 401], empty: false, }, requestOptions, @@ -499,7 +499,7 @@ export function make(options: ClientOptions) { resume: input["resume"], }, successStatus: 200, - declaredStatuses: [409, 404, 500, 400, 401], + declaredStatuses: [409, 400, 404, 500, 401], empty: false, }, requestOptions, diff --git a/packages/client/src/promise/generated/types.ts b/packages/client/src/promise/generated/types.ts index 0f35a342ea7..afe02c11c0b 100644 --- a/packages/client/src/promise/generated/types.ts +++ b/packages/client/src/promise/generated/types.ts @@ -528,11 +528,11 @@ export type SessionPromptInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> } readonly delivery?: "steer" | "queue" | null @@ -546,11 +546,11 @@ export type SessionPromptInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> } readonly delivery?: "steer" | "queue" | null @@ -564,11 +564,11 @@ export type SessionPromptInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> } readonly delivery?: "steer" | "queue" | null @@ -582,11 +582,11 @@ export type SessionPromptInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> } readonly delivery?: "steer" | "queue" | null @@ -602,16 +602,16 @@ export type SessionPromptOutput = { readonly prompt: { readonly text: string readonly files?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> } readonly delivery: "steer" | "queue" @@ -632,11 +632,11 @@ export type SessionCommandInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly delivery?: "steer" | "queue" | null readonly resume?: boolean | null @@ -651,11 +651,11 @@ export type SessionCommandInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly delivery?: "steer" | "queue" | null readonly resume?: boolean | null @@ -670,11 +670,11 @@ export type SessionCommandInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly delivery?: "steer" | "queue" | null readonly resume?: boolean | null @@ -689,11 +689,11 @@ export type SessionCommandInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly delivery?: "steer" | "queue" | null readonly resume?: boolean | null @@ -708,11 +708,11 @@ export type SessionCommandInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly delivery?: "steer" | "queue" | null readonly resume?: boolean | null @@ -727,11 +727,11 @@ export type SessionCommandInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly delivery?: "steer" | "queue" | null readonly resume?: boolean | null @@ -746,11 +746,11 @@ export type SessionCommandInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly delivery?: "steer" | "queue" | null readonly resume?: boolean | null @@ -765,11 +765,11 @@ export type SessionCommandInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly delivery?: "steer" | "queue" | null readonly resume?: boolean | null @@ -784,11 +784,11 @@ export type SessionCommandInput = { readonly uri: string readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly delivery?: "steer" | "queue" | null readonly resume?: boolean | null @@ -803,16 +803,16 @@ export type SessionCommandOutput = { readonly prompt: { readonly text: string readonly files?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> } readonly delivery: "steer" | "queue" @@ -934,16 +934,16 @@ export type SessionContextOutput = { readonly time: { readonly created: number } readonly text: string readonly files?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly type: "user" } @@ -1038,12 +1038,12 @@ export type SessionContextOutput = { readonly status: "completed" readonly input: { readonly [x: string]: JsonValue } readonly attachments?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly content: ReadonlyArray< | { readonly type: "text"; readonly text: string } @@ -1198,16 +1198,16 @@ export type SessionLogOutput = readonly prompt: { readonly text: string readonly files?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> } readonly delivery: "steer" | "queue" @@ -1631,16 +1631,16 @@ export type SessionMessageOutput = { readonly time: { readonly created: number } readonly text: string readonly files?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly type: "user" } @@ -1735,12 +1735,12 @@ export type SessionMessageOutput = { readonly status: "completed" readonly input: { readonly [x: string]: JsonValue } readonly attachments?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly content: ReadonlyArray< | { readonly type: "text"; readonly text: string } @@ -1833,16 +1833,16 @@ export type MessageListOutput = { readonly time: { readonly created: number } readonly text: string readonly files?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly type: "user" } @@ -1937,12 +1937,12 @@ export type MessageListOutput = { readonly status: "completed" readonly input: { readonly [x: string]: JsonValue } readonly attachments?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly content: ReadonlyArray< | { readonly type: "text"; readonly text: string } @@ -4485,16 +4485,16 @@ export type EventSubscribeOutput = readonly prompt: { readonly text: string readonly files?: ReadonlyArray<{ - readonly uri: string + readonly data: string readonly mime: string - readonly content?: string + readonly source: { readonly type: "inline" } | { readonly type: "uri"; readonly uri: string } readonly name?: string readonly description?: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> readonly agents?: ReadonlyArray<{ readonly name: string - readonly source?: { readonly start: number; readonly end: number; readonly text: string } + readonly mention?: { readonly start: number; readonly end: number; readonly text: string } }> } readonly delivery: "steer" | "queue" diff --git a/packages/client/test/contract-identity.test.ts b/packages/client/test/contract-identity.test.ts index b2c5cb7c8aa..90ac5d8cfc9 100644 --- a/packages/client/test/contract-identity.test.ts +++ b/packages/client/test/contract-identity.test.ts @@ -7,7 +7,6 @@ import { ProjectV2 } from "@opencode-ai/core/project" import { SessionV2 } from "@opencode-ai/core/session" import { SessionInput as CoreSessionInput } from "@opencode-ai/core/session/input" import { SessionMessage as CoreSessionMessage } from "@opencode-ai/core/session/message" -import { Prompt as CorePrompt } from "@opencode-ai/core/session/prompt" import { Agent } from "@opencode-ai/schema/agent" import { Location } from "@opencode-ai/schema/location" import { Model } from "@opencode-ai/schema/model" @@ -32,7 +31,6 @@ test("Core and Server reuse the authoritative Schema and Protocol values", () => expect(ProjectV2.Directories).toBe(Project.Directories) expect(CoreSessionInput.Admitted).toBe(SessionInput.Admitted) expect(CoreSessionMessage.Message).toBe(SessionMessage.Message) - expect(CorePrompt).toBe(Prompt) expect(Api.groups["server.session"].identifier).toBe("server.session") expect(Api.groups["server.project"].identifier).toBe("server.project") expect(Object.keys(ClientApi.groups)).toEqual(Object.keys(Api.groups)) diff --git a/packages/core/src/mime.ts b/packages/core/src/mime.ts index 50963d925bf..6ad8de5a605 100644 --- a/packages/core/src/mime.ts +++ b/packages/core/src/mime.ts @@ -1,41 +1,6 @@ export * as Mime from "./mime.js" -import { Effect, FileSystem, Option } from "effect" -import { fileURLToPath } from "url" -import { FSUtil } from "./fs-util" - -const SAMPLE_BYTES = 8192 - -export const resolve = Effect.fn("Mime.resolve")(function* (uri: string) { - const data = dataSample(uri) - if (data) return detect(data) - - const target = yield* Effect.try({ - try: () => localPath(uri), - catch: () => new Error("Invalid file URI"), - }).pipe(Effect.catch(() => Effect.succeed(undefined))) - if (!target) return "application/octet-stream" - - const fs = yield* FSUtil.Service - const local = yield* Effect.scoped( - Effect.gen(function* () { - const info = yield* fs.stat(target) - if (info.type === "Directory") return { type: "directory" as const } - if (info.type !== "File") return - const file = yield* fs.open(target) - return { - type: "file" as const, - sample: Option.getOrElse(yield* file.readAlloc(FileSystem.Size(SAMPLE_BYTES)), () => new Uint8Array()), - } - }), - ).pipe(Effect.catch(() => Effect.succeed(undefined))) - - if (local?.type === "directory") return "application/x-directory" - if (local?.type === "file") return detect(local.sample) - return "application/octet-stream" -}) - -function detect(bytes: Uint8Array) { +export function detect(bytes: Uint8Array) { if (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) return "image/png" if (startsWith(bytes, [0xff, 0xd8, 0xff])) return "image/jpeg" if (startsWith(bytes, [0x47, 0x49, 0x46, 0x38])) return "image/gif" @@ -52,25 +17,6 @@ function detect(bytes: Uint8Array) { return isText(bytes) ? "text/plain" : "application/octet-stream" } -function dataSample(uri: string) { - if (!uri.startsWith("data:")) return - const comma = uri.indexOf(",") - if (comma === -1) return new Uint8Array() - const metadata = uri.slice(5, comma) - const payload = uri.slice(comma + 1) - if (metadata.split(";").some((part) => part.toLowerCase() === "base64")) { - return Buffer.from(payload.slice(0, Math.ceil((SAMPLE_BYTES * 4) / 3) + 4), "base64").subarray(0, SAMPLE_BYTES) - } - return new TextEncoder().encode(payload.slice(0, SAMPLE_BYTES)) -} - -function localPath(uri: string) { - if (!URL.canParse(uri)) return - const url = new URL(uri) - if (url.protocol !== "file:") return - return fileURLToPath(url) -} - function startsWith(bytes: Uint8Array, prefix: number[]) { return prefix.every((value, index) => bytes[index] === value) } diff --git a/packages/core/src/session.ts b/packages/core/src/session.ts index 6f05f7b1f2d..b26b072dcf9 100644 --- a/packages/core/src/session.ts +++ b/packages/core/src/session.ts @@ -9,7 +9,7 @@ import { WorkspaceV2 } from "./workspace" import { ModelV2 } from "./model" import { Location } from "./location" import { SessionMessage } from "./session/message" -import { Prompt } from "./session/prompt" +import { Base64, FileAttachment, Prompt } from "@opencode-ai/schema/prompt" import { PromptInput } from "@opencode-ai/schema/prompt-input" import { EventV2 } from "./event" import { Database } from "./database/database" @@ -121,6 +121,10 @@ export class PromptConflictError extends Schema.TaggedErrorClass()("Session.AttachmentError", { + uri: Schema.String, + message: Schema.String, +}) {} export class BusyError extends Schema.TaggedErrorClass()("Session.BusyError", { sessionID: SessionSchema.ID, }) {} @@ -135,6 +139,7 @@ export type Error = | MessageDecodeError | OperationUnavailableError | PromptConflictError + | AttachmentError | BusyError | SkillNotFoundError | CommandV2.NotFoundError @@ -189,7 +194,7 @@ export interface Interface { prompt: PromptInput.Prompt delivery?: SessionInput.Delivery resume?: boolean - }) => Effect.Effect + }) => Effect.Effect readonly command: (input: { id?: SessionMessage.ID sessionID: SessionSchema.ID @@ -203,7 +208,7 @@ export interface Interface { resume?: boolean }) => Effect.Effect< SessionInput.Admitted, - NotFoundError | PromptConflictError | CommandV2.NotFoundError | CommandV2.EvaluationError + NotFoundError | PromptConflictError | AttachmentError | CommandV2.NotFoundError | CommandV2.EvaluationError > readonly shell: (input: { id?: EventV2.ID @@ -721,40 +726,98 @@ const resolvePrompt = Effect.fn("V2Session.resolvePrompt")(function* (input: Pro const files = input.files ? yield* Effect.forEach( input.files, - (file) => - Effect.gen(function* () { - const mime = yield* Mime.resolve(file.uri) - const content = mime === "text/plain" ? yield* readTextAttachment(fs, file.uri) : undefined - return { ...file, mime, ...(content === undefined ? {} : { content }) } - }), + (file) => materializeAttachment(fs, file), { concurrency: 8 }, ) : undefined return Prompt.make({ text: input.text, agents: input.agents, files }) }) -function readTextAttachment(fs: FSUtil.Interface, uri: string) { - if (uri.startsWith("data:")) return Effect.succeed(undefined) - return Effect.try({ +const MAX_ATTACHMENT_BYTES = 20 * 1024 * 1024 + +const materializeAttachment = Effect.fn("V2Session.materializeAttachment")(function* ( + fs: FSUtil.Interface, + input: PromptInput.FileAttachment, +) { + const resolved = input.uri.startsWith("data:") + ? { + bytes: yield* decodeDataURL(input.uri), + source: { type: "inline" as const }, + start: undefined, + end: undefined, + name: undefined, + } + : yield* readFileAttachment(fs, input.uri) + if (resolved.bytes.byteLength > MAX_ATTACHMENT_BYTES) + return yield* new AttachmentError({ + uri: input.uri, + message: `Attachment exceeds the ${MAX_ATTACHMENT_BYTES} byte limit: ${input.uri}`, + }) + + const mime = Mime.detect(resolved.bytes) + const content = + mime === "text/plain" && resolved.start !== undefined + ? Buffer.from( + Buffer.from(resolved.bytes).toString("utf8").split("\n").slice(resolved.start - 1, resolved.end).join("\n"), + ) + : resolved.bytes + return FileAttachment.create({ + data: Base64.make(Buffer.from(content).toString("base64")), + mime, + source: resolved.source, + name: input.name ?? resolved.name, + description: input.description, + mention: input.mention, + }) +}) + +const readFileAttachment = Effect.fn("V2Session.readFileAttachment")(function* (fs: FSUtil.Interface, uri: string) { + const url = yield* Effect.try({ try: () => new URL(uri), - catch: () => new Error("Invalid attachment URI"), - }).pipe( - Effect.flatMap((url) => { - if (url.protocol !== "file:") return Effect.succeed(undefined) - const start = positiveInt(url.searchParams.get("start")) - const end = positiveInt(url.searchParams.get("end")) + catch: () => new AttachmentError({ uri, message: `Invalid attachment URI: ${uri}` }), + }) + if (url.protocol !== "file:") + return yield* new AttachmentError({ uri, message: `Unsupported attachment URI: ${uri}` }) + const start = positiveInt(url.searchParams.get("start")) + const end = positiveInt(url.searchParams.get("end")) + const target = yield* Effect.try({ + try: () => { url.search = "" url.hash = "" - return Effect.try({ - try: () => fileURLToPath(url), - catch: () => new Error("Invalid file URI"), - }).pipe( - Effect.flatMap((target) => fs.readFileString(target)), - Effect.map((content) => (start === undefined ? content : content.split("\n").slice(start - 1, end).join("\n"))), - ) - }), - Effect.catch(() => Effect.succeed(undefined)), + return fileURLToPath(url) + }, + catch: () => new AttachmentError({ uri, message: `Invalid file URI: ${uri}` }), + }) + const info = yield* fs.stat(target).pipe( + Effect.mapError(() => new AttachmentError({ uri, message: `Unable to read attachment: ${uri}` })), ) + if (info.type !== "File") return yield* new AttachmentError({ uri, message: `Attachment is not a file: ${uri}` }) + if (Number(info.size) > MAX_ATTACHMENT_BYTES) + return yield* new AttachmentError({ + uri, + message: `Attachment exceeds the ${MAX_ATTACHMENT_BYTES} byte limit: ${uri}`, + }) + const bytes = yield* fs.readFile(target).pipe( + Effect.mapError(() => new AttachmentError({ uri, message: `Unable to read attachment: ${uri}` })), + ) + return { bytes, source: { type: "uri" as const, uri }, start, end, name: path.basename(target) } +}) + +function decodeDataURL(uri: string) { + return Effect.try({ + try: () => { + const comma = uri.indexOf(",") + if (comma === -1) throw new Error("Invalid data URL") + const metadata = uri.slice(5, comma) + const payload = uri.slice(comma + 1) + if (!metadata.split(";").some((part) => part.toLowerCase() === "base64")) + return Buffer.from(decodeURIComponent(payload)) + const bytes = Buffer.from(payload, "base64") + if (bytes.toString("base64") !== payload) throw new Error("Non-canonical base64") + return bytes + }, + catch: () => new AttachmentError({ uri, message: "Invalid attachment data URL" }), + }) } function positiveInt(value: string | null) { diff --git a/packages/core/src/session/compaction.ts b/packages/core/src/session/compaction.ts index 9ad9ddc81a0..4c5bbb4a6e3 100644 --- a/packages/core/src/session/compaction.ts +++ b/packages/core/src/session/compaction.ts @@ -106,7 +106,11 @@ export const serializeToolContent = (content: SessionMessage.ToolStateCompleted[ const serialize = (message: SessionMessage.Message) => { if (message.type === "user") { - const files = message.files?.map((file) => `[Attached ${file.mime}: ${file.name ?? file.uri}]`) ?? [] + const files = + message.files?.map( + (file) => + `[Attached ${file.mime}: ${file.name ?? (file.source.type === "uri" ? file.source.uri : "inline attachment")}]`, + ) ?? [] return [`[User]: ${message.text}`, ...files].join("\n") } if (message.type === "assistant") { diff --git a/packages/core/src/session/input.ts b/packages/core/src/session/input.ts index 1d0dfc71c3b..72622d32ef7 100644 --- a/packages/core/src/session/input.ts +++ b/packages/core/src/session/input.ts @@ -7,7 +7,7 @@ import type { Database } from "../database/database" import type { EventV2 } from "../event" import { SessionEvent } from "./event" import { SessionMessage } from "./message" -import { Prompt } from "./prompt" +import { Prompt } from "@opencode-ai/schema/prompt" import { SessionSchema } from "./schema" import { SessionInputTable, SessionMessageTable } from "./sql" diff --git a/packages/core/src/session/prompt.ts b/packages/core/src/session/prompt.ts deleted file mode 100644 index b079349c566..00000000000 --- a/packages/core/src/session/prompt.ts +++ /dev/null @@ -1 +0,0 @@ -export { AgentAttachment, FileAttachment, Prompt, Source } from "@opencode-ai/schema/prompt" diff --git a/packages/core/src/session/runner/to-llm-message.ts b/packages/core/src/session/runner/to-llm-message.ts index c9bdcbd2e19..d2eaee413b6 100644 --- a/packages/core/src/session/runner/to-llm-message.ts +++ b/packages/core/src/session/runner/to-llm-message.ts @@ -9,12 +9,14 @@ import { } from "@opencode-ai/llm" import { Option, Schema } from "effect" import { SessionMessage } from "../message" -import type { FileAttachment } from "../prompt" +import type { FileAttachment } from "@opencode-ai/schema/prompt" + +const imageMimes = new Set(["image/png", "image/jpeg", "image/gif", "image/webp"]) const media = (file: FileAttachment): ContentPart => ({ type: "media", mediaType: file.mime, - data: file.uri, + data: file.data, filename: file.name, metadata: file.description === undefined ? undefined : { description: file.description }, }) @@ -23,37 +25,22 @@ const textAttachment = (file: FileAttachment) => Message.make({ role: "user", content: [ - `Attached file: ${file.name ?? file.uri}`, - `Source: ${file.uri}`, + `Attached file: ${file.name ?? (file.source.type === "uri" ? file.source.uri : "inline attachment")}`, file.description === undefined ? undefined : `Description: ${file.description}`, "", - file.content ?? readTextData(file.uri) ?? "[Attachment content unavailable]", + Buffer.from(file.data, "base64").toString("utf8"), ] .filter((line): line is string => line !== undefined) .join("\n"), metadata: { attachment: { - uri: file.uri, + source: file.source, name: file.name, description: file.description, }, }, }) -function readTextData(uri: string) { - if (!uri.startsWith("data:")) return - const comma = uri.indexOf(",") - if (comma === -1) return - const metadata = uri.slice(5, comma) - const payload = uri.slice(comma + 1) - if (metadata.split(";").some((part) => part.toLowerCase() === "base64")) return Buffer.from(payload, "base64").toString("utf8") - try { - return decodeURIComponent(payload) - } catch { - return - } -} - const decodeToolInput = Schema.decodeUnknownOption(Schema.UnknownFromJsonString) const toolInput = (tool: SessionMessage.AssistantTool) => @@ -160,7 +147,10 @@ function toLLMMessage(message: SessionMessage.Message, model: Model): Message[] Message.make({ id: message.id, role: "user", - content: [{ type: "text", text: message.text }, ...files.filter((file) => file.mime !== "text/plain").map(media)], + content: [ + { type: "text", text: message.text }, + ...files.filter((file) => imageMimes.has(file.mime)).map(media), + ], metadata: { ...message.metadata, ...(message.agents?.length ? { agents: message.agents } : {}), diff --git a/packages/core/src/session/sql.ts b/packages/core/src/session/sql.ts index ceef6fe040b..3e6f79863c2 100644 --- a/packages/core/src/session/sql.ts +++ b/packages/core/src/session/sql.ts @@ -2,7 +2,7 @@ import { sqliteTable, text, integer, index, primaryKey, real, uniqueIndex } from import { directoryColumn, pathColumn } from "../database/path" import { ProjectTable } from "../project/sql" import type { SessionMessage } from "./message" -import type { Prompt } from "./prompt" +import type { Prompt } from "@opencode-ai/schema/prompt" import type { SessionInput } from "./input" import type { Snapshot } from "../snapshot" import { PermissionV1 } from "../v1/permission" diff --git a/packages/core/test/session-compact.test.ts b/packages/core/test/session-compact.test.ts index 98551e9f225..df63072fb9a 100644 --- a/packages/core/test/session-compact.test.ts +++ b/packages/core/test/session-compact.test.ts @@ -16,7 +16,7 @@ import { SessionV2 } from "@opencode-ai/core/session" import { SessionCompaction } from "@opencode-ai/core/session/compaction" import { SessionEvent } from "@opencode-ai/core/session/event" import { SessionMessage } from "@opencode-ai/core/session/message" -import { Prompt } from "@opencode-ai/core/session/prompt" +import { Prompt } from "@opencode-ai/schema/prompt" import { SessionProjector } from "@opencode-ai/core/session/projector" import { SessionExecution } from "@opencode-ai/core/session/execution" import { SessionRunnerModel } from "@opencode-ai/core/session/runner/model" diff --git a/packages/core/test/session-create.test.ts b/packages/core/test/session-create.test.ts index 1b07937ebdf..fc3b4d127d4 100644 --- a/packages/core/test/session-create.test.ts +++ b/packages/core/test/session-create.test.ts @@ -16,7 +16,7 @@ import { ProviderV2 } from "@opencode-ai/core/provider" import { AbsolutePath } from "@opencode-ai/core/schema" import { SessionV2 } from "@opencode-ai/core/session" import { SessionV1 } from "@opencode-ai/core/v1/session" -import { Prompt } from "@opencode-ai/core/session/prompt" +import { PromptInput } from "@opencode-ai/schema/prompt-input" import { SessionMessage } from "@opencode-ai/core/session/message" import { SessionProjector } from "@opencode-ai/core/session/projector" import { SessionExecution } from "@opencode-ai/core/session/execution" @@ -192,7 +192,7 @@ describe("SessionV2.create", () => { const parent = yield* session.create({ location, title: "Parent" }) const admitted = yield* session.prompt({ sessionID: parent.id, - prompt: Prompt.make({ text: "First" }), + prompt: PromptInput.Prompt.make({ text: "First" }), resume: false, }) yield* SessionInput.promoteSteers(db, events, parent.id) @@ -224,9 +224,9 @@ describe("SessionV2.create", () => { promotedSeq: 2, }) - yield* session.prompt({ sessionID: parent.id, prompt: Prompt.make({ text: "Parent changed" }), resume: false }) + yield* session.prompt({ sessionID: parent.id, prompt: PromptInput.Prompt.make({ text: "Parent changed" }), resume: false }) yield* SessionInput.promoteSteers(db, events, parent.id) - yield* session.prompt({ sessionID: forked.id, prompt: Prompt.make({ text: "Child continues" }), resume: false }) + yield* session.prompt({ sessionID: forked.id, prompt: PromptInput.Prompt.make({ text: "Child continues" }), resume: false }) yield* SessionInput.promoteSteers(db, events, forked.id) expect((yield* session.context(parent.id)).map((message) => message.type)).toEqual(["user", "synthetic", "user"]) @@ -249,13 +249,13 @@ describe("SessionV2.create", () => { const parent = yield* session.create({ location }) const first = yield* session.prompt({ sessionID: parent.id, - prompt: Prompt.make({ text: "First" }), + prompt: PromptInput.Prompt.make({ text: "First" }), resume: false, }) yield* SessionInput.promoteSteers(db, events, parent.id) const second = yield* session.prompt({ sessionID: parent.id, - prompt: Prompt.make({ text: "Second" }), + prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false, }) yield* SessionInput.promoteSteers(db, events, parent.id) @@ -373,7 +373,7 @@ describe("SessionV2.create", () => { const events = yield* EventV2.Service const { db } = yield* Database.Service const created = yield* session.create({ location }) - yield* session.prompt({ sessionID: created.id, prompt: Prompt.make({ text: "Hello" }), resume: false }) + yield* session.prompt({ sessionID: created.id, prompt: PromptInput.Prompt.make({ text: "Hello" }), resume: false }) yield* SessionInput.promoteSteers(db, events, created.id) expect( @@ -393,7 +393,7 @@ describe("SessionV2.create", () => { const created = yield* session.create({ id: SessionV2.ID.make("ses_fresh_target_replay"), location }) const admitted = yield* session.prompt({ sessionID: created.id, - prompt: Prompt.make({ text: "Replay lifecycle" }), + prompt: PromptInput.Prompt.make({ text: "Replay lifecycle" }), resume: false, }) yield* SessionInput.promoteSteers(sourceDb, sourceEvents, created.id) diff --git a/packages/core/test/session-projector.test.ts b/packages/core/test/session-projector.test.ts index da2e494731e..77dd272b120 100644 --- a/packages/core/test/session-projector.test.ts +++ b/packages/core/test/session-projector.test.ts @@ -14,7 +14,7 @@ import { AbsolutePath } from "@opencode-ai/core/schema" import { SessionV2 } from "@opencode-ai/core/session" import { SessionEvent } from "@opencode-ai/core/session/event" import { SessionMessage } from "@opencode-ai/core/session/message" -import { Prompt } from "@opencode-ai/core/session/prompt" +import { Prompt } from "@opencode-ai/schema/prompt" import { SessionMessageUpdater } from "@opencode-ai/core/session/message-updater" import { SessionProjector } from "@opencode-ai/core/session/projector" import { SessionExecution } from "@opencode-ai/core/session/execution" diff --git a/packages/core/test/session-prompt.test.ts b/packages/core/test/session-prompt.test.ts index 163d831a5e9..0b41dd37353 100644 --- a/packages/core/test/session-prompt.test.ts +++ b/packages/core/test/session-prompt.test.ts @@ -1,5 +1,7 @@ import { describe, expect } from "bun:test" import { DateTime, Effect, Fiber, Layer, Schema, Stream } from "effect" +import { mkdtemp, rm } from "fs/promises" +import { tmpdir } from "os" import path from "path" import { pathToFileURL } from "url" import { eq } from "drizzle-orm" @@ -15,7 +17,7 @@ import { Project } from "@opencode-ai/core/project" import { ProjectTable } from "@opencode-ai/core/project/sql" import { AbsolutePath } from "@opencode-ai/core/schema" import { SessionV2 } from "@opencode-ai/core/session" -import { Prompt } from "@opencode-ai/core/session/prompt" +import { PromptInput } from "@opencode-ai/schema/prompt-input" import { SessionMessage } from "@opencode-ai/core/session/message" import { SessionProjector } from "@opencode-ai/core/session/projector" import { SessionExecution } from "@opencode-ai/core/session/execution" @@ -171,7 +173,7 @@ describe("SessionV2.prompt", () => { const message = yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Fix the failing tests" }), + prompt: PromptInput.Prompt.make({ text: "Fix the failing tests" }), resume: false, }) @@ -195,7 +197,7 @@ describe("SessionV2.prompt", () => { const boundary = yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "boundary" }), + prompt: PromptInput.Prompt.make({ text: "boundary" }), resume: false, }) yield* SessionInput.promoteSteers(db, events, sessionID) @@ -207,7 +209,7 @@ describe("SessionV2.prompt", () => { }) expect((yield* session.get(sessionID)).revert?.messageID).toBe(boundary.id) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "after revert" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "after revert" }), resume: false }) expect((yield* session.get(sessionID)).revert).toBeUndefined() expect( @@ -230,17 +232,25 @@ describe("SessionV2.prompt", () => { sessionID, prompt: { text: "Inspect this image", - files: [{ uri, name: "image.png" }], + files: [{ uri, name: "image.png", mention: { start: 8, end: 17, text: "[Image 1]" } }], }, resume: false, }) - expect(message.prompt.files).toEqual([{ uri, name: "image.png", mime: "image/png" }]) + expect(message.prompt.files).toEqual([ + { + data: uri.slice(uri.indexOf(",") + 1), + mime: "image/png", + source: { type: "inline" }, + name: "image.png", + mention: { start: 8, end: 17, text: "[Image 1]" }, + }, + ]) expect((yield* admitted(message.id))?.prompt.files).toEqual(message.prompt.files) }), ) - it.effect("classifies source files and directories from local content", () => + it.effect("materializes selected source file content", () => Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service @@ -253,27 +263,78 @@ describe("SessionV2.prompt", () => { const message = yield* session.prompt({ sessionID, prompt: { - text: "Inspect these", - files: [ - { uri: sourceUri.href, name: "main.ts" }, - { uri: pathToFileURL(directory).href, name: "source" }, - ], + text: "Inspect this", + files: [{ uri: sourceUri.href, name: "main.ts" }], }, resume: false, }) expect(message.prompt.files).toEqual([ { - uri: sourceUri.href, - name: "main.ts", + data: Buffer.from('import { describe, expect } from "bun:test"').toString("base64"), mime: "text/plain", - content: 'import { describe, expect } from "bun:test"', + source: { type: "uri", uri: sourceUri.href }, + name: "main.ts", }, - { uri: pathToFileURL(directory).href, name: "source", mime: "application/x-directory" }, ]) }), ) + it.effect("rejects directories as file attachments", () => + Effect.gen(function* () { + yield* setup + const session = yield* SessionV2.Service + const uri = pathToFileURL(import.meta.dir).href + + const error = yield* session + .prompt({ + sessionID, + prompt: { text: "Inspect this", files: [{ uri, name: "source" }] }, + resume: false, + }) + .pipe(Effect.flip) + + expect(error).toMatchObject({ + _tag: "Session.AttachmentError", + uri, + message: `Attachment is not a file: ${uri}`, + }) + }), + ) + + it.effect("materializes local image content before admission", () => + Effect.gen(function* () { + yield* setup + const session = yield* SessionV2.Service + const directory = yield* Effect.acquireRelease( + Effect.promise(() => mkdtemp(path.join(tmpdir(), "opencode-session-prompt-"))), + (directory) => Effect.promise(() => rm(directory, { recursive: true, force: true })), + ) + const source = path.join(directory, "image.png") + const bytes = Buffer.from( + "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=", + "base64", + ) + yield* Effect.promise(() => Bun.write(source, bytes)) + + const message = yield* session.prompt({ + sessionID, + prompt: { text: "Inspect this image", files: [{ uri: pathToFileURL(source).href }] }, + resume: false, + }) + + expect(message.prompt.files).toEqual([ + { + data: bytes.toString("base64"), + mime: "image/png", + source: { type: "uri", uri: pathToFileURL(source).href }, + name: "image.png", + }, + ]) + expect((yield* admitted(message.id))?.prompt.files).toEqual(message.prompt.files) + }), + ) + it.effect("sniffs data URL content instead of trusting its declared MIME", () => Effect.gen(function* () { yield* setup @@ -286,7 +347,36 @@ describe("SessionV2.prompt", () => { resume: false, }) - expect(message.prompt.files).toEqual([{ uri, name: "main.ts", mime: "text/plain" }]) + expect(message.prompt.files).toEqual([ + { + data: Buffer.from("export const value = 1\n").toString("base64"), + mime: "text/plain", + source: { type: "inline" }, + name: "main.ts", + }, + ]) + }), + ) + + it.effect("rejects malformed base64 data URLs", () => + Effect.gen(function* () { + yield* setup + const session = yield* SessionV2.Service + const uri = "data:image/png;base64,not-base64" + + const error = yield* session + .prompt({ + sessionID, + prompt: { text: "Inspect this", files: [{ uri, name: "image.png" }] }, + resume: false, + }) + .pipe(Effect.flip) + + expect(error).toMatchObject({ + _tag: "Session.AttachmentError", + uri, + message: "Invalid attachment data URL", + }) }), ) @@ -303,8 +393,8 @@ describe("SessionV2.prompt", () => { const fiber = yield* publicEvents({ sessionID }).pipe(Stream.take(4), Stream.runCollect, Effect.forkScoped) yield* Effect.yieldNow - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) yield* SessionInput.promoteSteers(db, events, sessionID) const streamed = Array.from(yield* Fiber.join(fiber)) @@ -328,7 +418,7 @@ describe("SessionV2.prompt", () => { const session = yield* SessionV2.Service const message = yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Fix the failing tests" }), + prompt: PromptInput.Prompt.make({ text: "Fix the failing tests" }), resume: false, }) @@ -347,7 +437,7 @@ describe("SessionV2.prompt", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - const input = { sessionID, prompt: Prompt.make({ text: "Fix the failing tests" }), resume: false } + const input = { sessionID, prompt: PromptInput.Prompt.make({ text: "Fix the failing tests" }), resume: false } const first = yield* session.prompt(input) const second = yield* session.prompt(input) @@ -365,7 +455,7 @@ describe("SessionV2.prompt", () => { const input = { sessionID, id: messageID, - prompt: Prompt.make({ text: "Fix the failing tests" }), + prompt: PromptInput.Prompt.make({ text: "Fix the failing tests" }), resume: false, } @@ -385,7 +475,7 @@ describe("SessionV2.prompt", () => { const input = { sessionID, id: messageID, - prompt: Prompt.make({ text: "Recover committed prompt" }), + prompt: PromptInput.Prompt.make({ text: "Recover committed prompt" }), resume: false, } const first = yield* session.prompt(input) @@ -406,13 +496,13 @@ describe("SessionV2.prompt", () => { yield* session.prompt({ sessionID, id: messageID, - prompt: Prompt.make({ text: "Fix the failing tests" }), + prompt: PromptInput.Prompt.make({ text: "Fix the failing tests" }), }) const failure = yield* session .prompt({ sessionID, id: messageID, - prompt: Prompt.make({ text: "Delete the failing tests" }), + prompt: PromptInput.Prompt.make({ text: "Delete the failing tests" }), resume: false, }) .pipe(Effect.flip) @@ -431,14 +521,14 @@ describe("SessionV2.prompt", () => { yield* session.prompt({ id: messageID, sessionID, - prompt: Prompt.make({ text: "Fix the failing tests" }), + prompt: PromptInput.Prompt.make({ text: "Fix the failing tests" }), resume: false, }) const failure = yield* session .prompt({ id: messageID, sessionID, - prompt: Prompt.make({ text: "Fix the failing tests" }), + prompt: PromptInput.Prompt.make({ text: "Fix the failing tests" }), delivery: "queue", resume: false, }) @@ -455,7 +545,7 @@ describe("SessionV2.prompt", () => { const input = { sessionID, id: messageID, - prompt: Prompt.make({ text: "Fix the failing tests" }), + prompt: PromptInput.Prompt.make({ text: "Fix the failing tests" }), resume: false, } @@ -474,7 +564,7 @@ describe("SessionV2.prompt", () => { const { db } = yield* Database.Service const session = yield* SessionV2.Service const events = yield* EventV2.Service - yield* session.prompt({ id: messageID, sessionID, prompt: Prompt.make({ text: "Promote once" }), resume: false }) + yield* session.prompt({ id: messageID, sessionID, prompt: PromptInput.Prompt.make({ text: "Promote once" }), resume: false }) yield* Effect.all( [SessionInput.promoteSteers(db, events, sessionID), SessionInput.promoteSteers(db, events, sessionID)], @@ -499,7 +589,7 @@ describe("SessionV2.prompt", () => { yield* session.prompt({ id: messageID, sessionID, - prompt: Prompt.make({ text: "Replay pending" }), + prompt: PromptInput.Prompt.make({ text: "Replay pending" }), resume: false, }) const recorded = yield* db @@ -552,7 +642,7 @@ describe("SessionV2.prompt", () => { .onConflictDoNothing() .run() .pipe(Effect.orDie) - const prompt = Prompt.make({ text: "Fix the failing tests" }) + const prompt = PromptInput.Prompt.make({ text: "Fix the failing tests" }) yield* session.prompt({ id: messageID, sessionID, prompt, resume: false }) const failure = yield* session @@ -586,7 +676,7 @@ describe("SessionV2.prompt", () => { .pipe(Effect.orDie) const failure = yield* session - .prompt({ id: messageID, sessionID, prompt: Prompt.make({ text: "Conflicting prompt" }), resume: false }) + .prompt({ id: messageID, sessionID, prompt: PromptInput.Prompt.make({ text: "Conflicting prompt" }), resume: false }) .pipe(Effect.flip) expect(failure).toMatchObject({ _tag: "Session.PromptConflictError", sessionID, messageID }) @@ -601,7 +691,7 @@ describe("SessionV2.prompt", () => { executionCalls.length = 0 wakeCalls.length = 0 - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run by default" }) }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Run by default" }) }) expect(executionCalls).toEqual([]) expect(wakeCalls).toEqual([sessionID]) @@ -617,7 +707,7 @@ describe("SessionV2.prompt", () => { yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Run explicitly" }), + prompt: PromptInput.Prompt.make({ text: "Run explicitly" }), resume: true, }) @@ -633,7 +723,7 @@ describe("SessionV2.prompt", () => { executionCalls.length = 0 wakeCalls.length = 0 - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Do not run" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Do not run" }), resume: false }) expect(executionCalls).toEqual([]) expect(wakeCalls).toEqual([]) diff --git a/packages/core/test/session-runner-message.test.ts b/packages/core/test/session-runner-message.test.ts index 8fdc53631eb..469d5e0360a 100644 --- a/packages/core/test/session-runner-message.test.ts +++ b/packages/core/test/session-runner-message.test.ts @@ -4,7 +4,7 @@ import * as OpenAIChat from "@opencode-ai/llm/protocols/openai-chat" import { ModelV2 } from "@opencode-ai/core/model" import { ProviderV2 } from "@opencode-ai/core/provider" import { SessionMessage } from "@opencode-ai/core/session/message" -import { AgentAttachment, FileAttachment } from "@opencode-ai/core/session/prompt" +import { AgentAttachment, Base64, FileAttachment } from "@opencode-ai/schema/prompt" import { toLLMMessages } from "@opencode-ai/core/session/runner/to-llm-message" import { SessionV2 } from "@opencode-ai/core/session" import { Shell } from "@opencode-ai/schema/shell" @@ -49,7 +49,12 @@ describe("toLLMMessages", () => { }) test("maps every top-level V2 Session message type", () => { - const file = FileAttachment.make({ uri: "data:image/png;base64,aGVsbG8=", mime: "image/png", name: "hello.png" }) + const file = FileAttachment.make({ + data: Base64.make("aGVsbG8="), + mime: "image/png", + source: { type: "inline" }, + name: "hello.png", + }) const messages = toLLMMessages( [ SessionMessage.AgentSelected.make({ @@ -122,7 +127,7 @@ describe("toLLMMessages", () => { role: "user", content: [ { type: "text", text: "Inspect this image" }, - { type: "media", mediaType: "image/png", data: "data:image/png;base64,aGVsbG8=", filename: "hello.png" }, + { type: "media", mediaType: "image/png", data: "aGVsbG8=", filename: "hello.png" }, ], metadata: { agents: [{ name: "build" }] }, }), @@ -151,9 +156,9 @@ Recent work test("lowers text attachments as separate user messages", () => { const file = FileAttachment.make({ - uri: "file:///project/main.ts", + data: Base64.make(Buffer.from("export const value = 1").toString("base64")), mime: "text/plain", - content: "export const value = 1", + source: { type: "uri", uri: "file:///project/main.ts" }, name: "main.ts", }) const messages = toLLMMessages( @@ -175,10 +180,10 @@ Recent work content: [ { type: "text", - text: "Attached file: main.ts\nSource: file:///project/main.ts\n\nexport const value = 1", + text: "Attached file: main.ts\n\nexport const value = 1", }, ], - metadata: { attachment: { uri: "file:///project/main.ts", name: "main.ts" } }, + metadata: { attachment: { source: file.source, name: "main.ts" } }, }) expect(messages[1]).toMatchObject({ id: id("user-text-file"), @@ -187,15 +192,21 @@ Recent work }) }) - test("derives text attachment content from durable data URLs", () => { - const uri = `data:text/plain;base64,${Buffer.from("inline content").toString("base64")}` + test("decodes inline text attachment content", () => { const messages = toLLMMessages( [ SessionMessage.User.make({ id: id("user-data-file"), type: "user", text: "Review this file", - files: [FileAttachment.make({ uri, mime: "text/plain", name: "inline.txt" })], + files: [ + FileAttachment.make({ + data: Base64.make(Buffer.from("inline content").toString("base64")), + mime: "text/plain", + source: { type: "inline" }, + name: "inline.txt", + }), + ], time: { created }, }), ], @@ -205,11 +216,40 @@ Recent work expect(messages[0]?.content).toEqual([ { type: "text", - text: `Attached file: inline.txt\nSource: ${uri}\n\ninline content`, + text: "Attached file: inline.txt\n\ninline content", }, ]) }) + test("uses materialized image data as provider media and drops unsupported attachments", () => { + const data = Base64.make("AAECAw==") + const messages = toLLMMessages( + [ + SessionMessage.User.make({ + id: id("user-local-image"), + type: "user", + text: "Inspect this image", + files: [ + FileAttachment.make({ data, mime: "image/png", source: { type: "inline" }, name: "image.png" }), + FileAttachment.make({ + data: Base64.make("JVBERg=="), + mime: "application/pdf", + source: { type: "inline" }, + name: "document.pdf", + }), + ], + time: { created }, + }), + ], + model, + ) + + expect(messages[0]?.content).toEqual([ + { type: "text", text: "Inspect this image" }, + { type: "media", mediaType: "image/png", data, filename: "image.png" }, + ]) + }) + test("replays durable tool media into canonical tool messages without structured base64", () => { const messages = toLLMMessages( [ diff --git a/packages/core/test/session-runner-recorded.test.ts b/packages/core/test/session-runner-recorded.test.ts index 15a1b35fd46..aa2484d34f8 100644 --- a/packages/core/test/session-runner-recorded.test.ts +++ b/packages/core/test/session-runner-recorded.test.ts @@ -19,7 +19,7 @@ import { SessionV2 } from "@opencode-ai/core/session" import { Snapshot } from "@opencode-ai/core/snapshot" import { SessionCompaction } from "@opencode-ai/core/session/compaction" import { SessionTitle } from "@opencode-ai/core/session/title" -import { Prompt } from "@opencode-ai/core/session/prompt" +import { PromptInput } from "@opencode-ai/schema/prompt-input" import { SessionProjector } from "@opencode-ai/core/session/projector" import { SessionExecution } from "@opencode-ai/core/session/execution" import { SessionRunCoordinator } from "@opencode-ai/core/session/run-coordinator" @@ -172,7 +172,7 @@ describe("SessionRunnerLLM recorded", () => { const session = yield* SessionV2.Service const prompt = yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Say hello in one short sentence." }), + prompt: PromptInput.Prompt.make({ text: "Say hello in one short sentence." }), resume: false, }) diff --git a/packages/core/test/session-runner.test.ts b/packages/core/test/session-runner.test.ts index 99ccf338d28..3c66bbb5202 100644 --- a/packages/core/test/session-runner.test.ts +++ b/packages/core/test/session-runner.test.ts @@ -30,7 +30,7 @@ import { SessionCompaction } from "@opencode-ai/core/session/compaction" import { SessionTitle } from "@opencode-ai/core/session/title" import { SessionInput } from "@opencode-ai/core/session/input" import { SessionMessage } from "@opencode-ai/core/session/message" -import { Prompt } from "@opencode-ai/core/session/prompt" +import { PromptInput } from "@opencode-ai/schema/prompt-input" import { SessionProjector } from "@opencode-ai/core/session/projector" import { SessionExecution } from "@opencode-ai/core/session/execution" import { SessionRunCoordinator } from "@opencode-ai/core/session/run-coordinator" @@ -375,7 +375,7 @@ const setupOverflowRecovery = Effect.gen(function* () { response = fragmentFixture("text", "text-earlier", ["Earlier answer"]).completeEvents yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Earlier question ".repeat(700) }), + prompt: PromptInput.Prompt.make({ text: "Earlier question ".repeat(700) }), resume: false, }) yield* session.resume(sessionID) @@ -516,7 +516,7 @@ const verifyEphemeralDeltas = (kind: FragmentKind) => const chunks = Array.from({ length: 32 }, (_, index) => `${index},`) const fixture = fragmentFixture(kind, fragmentID(kind, "many"), chunks) const expectedContext = [{ type: "user", text: prompt }, fixture.expectedAssistant] - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: prompt }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: prompt }), resume: false }) const events = yield* EventV2.Service const live = yield* events.subscribe(fixture.delta).pipe(Stream.take(32), Stream.runCollect, Effect.forkScoped) yield* Effect.yieldNow @@ -547,7 +547,7 @@ const verifyPartialFlushOnFailure = (kind: FragmentKind) => const prompt = `Fail after ${kind}` const fixture = fragmentFixture(kind, fragmentID(kind, "partial"), ["Partial"]) const failure = providerUnavailable() - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: prompt }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: prompt }), resume: false }) responseStream = Stream.concat(Stream.fromIterable(fixture.partialEvents), Stream.fail(failure)) expect(yield* session.resume(sessionID).pipe(Effect.flip)).toBe(failure) @@ -569,7 +569,7 @@ const verifyPartialFlushOnInterruption = (kind: FragmentKind) => const prompt = `Interrupt after ${kind}` const fixture = fragmentFixture(kind, fragmentID(kind, "interrupted"), ["Partial"]) const streamed = yield* Deferred.make() - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: prompt }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: prompt }), resume: false }) responseStream = Stream.concat( Stream.fromIterable(fixture.partialEvents), Stream.fromEffect(Deferred.succeed(streamed, undefined)).pipe(Stream.flatMap(() => Stream.never)), @@ -613,7 +613,7 @@ describe("SessionRunnerLLM", () => { }), }), }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Use application context" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Use application context" }), resume: false }) responses = [ [ LLMEvent.stepStart({ index: 0 }), @@ -661,7 +661,7 @@ describe("SessionRunnerLLM", () => { streamStarted = undefined response = [] - const message = yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run automatically" }) }) + const message = yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Run automatically" }) }) yield* session.wait(sessionID) expect(requests).toHaveLength(1) @@ -675,8 +675,8 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) requests.length = 0 responses = undefined @@ -703,7 +703,7 @@ describe("SessionRunnerLLM", () => { const { db } = yield* Database.Service const messageID = SessionMessage.ID.create() systemUnavailable = true - yield* session.prompt({ id: messageID, sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ id: messageID, sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 const exit = yield* session.resume(sessionID).pipe(Effect.exit) @@ -721,7 +721,7 @@ describe("SessionRunnerLLM", () => { ).toBeUndefined() systemUnavailable = false - yield* session.prompt({ id: messageID, sessionID, prompt: Prompt.make({ text: "First" }) }) + yield* session.prompt({ id: messageID, sessionID, prompt: PromptInput.Prompt.make({ text: "First" }) }) yield* session.wait(sessionID) expect(requests).toHaveLength(1) @@ -735,7 +735,7 @@ describe("SessionRunnerLLM", () => { const session = yield* SessionV2.Service const events = yield* EventV2.Service const { db } = yield* Database.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] yield* session.resume(sessionID) @@ -752,7 +752,7 @@ describe("SessionRunnerLLM", () => { .get(), ).toBeUndefined() - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) const exit = yield* session.resume(sessionID).pipe(Effect.exit) expect(Exit.isFailure(exit) && Cause.hasInterruptsOnly(exit.cause)).toBe(true) @@ -766,7 +766,7 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const { db } = yield* Database.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) response = [] yield* session.resume(sessionID) @@ -795,7 +795,7 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const { db } = yield* Database.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) response = [] yield* session.resume(sessionID) yield* db @@ -804,7 +804,7 @@ describe("SessionRunnerLLM", () => { .where(eq(InstructionCheckpointTable.session_id, sessionID)) .run() .pipe(Effect.orDie) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) requests.length = 0 yield* session.resume(sessionID) @@ -828,13 +828,13 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] yield* session.resume(sessionID) systemBaseline = "Changed context" - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) yield* session.resume(sessionID) expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([ @@ -863,7 +863,7 @@ describe("SessionRunnerLLM", () => { yield* setup currentModel = Model.make({ id: "gpt-5", provider: "openai", route: OpenAIChat.route }) const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = fragmentFixture("text", "text-provider-prompt", ["Done"]).completeEvents @@ -888,7 +888,7 @@ describe("SessionRunnerLLM", () => { }), ) const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = fragmentFixture("text", "text-empty-agent-system", ["Done"]).completeEvents @@ -912,7 +912,7 @@ describe("SessionRunnerLLM", () => { }), ) const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = fragmentFixture("text", "text-build", ["Done"]).completeEvents @@ -938,7 +938,7 @@ describe("SessionRunnerLLM", () => { editor.default(AgentV2.ID.make("reviewer")) }) const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = fragmentFixture("text", "text-reviewer", ["Done"]).completeEvents @@ -960,7 +960,7 @@ describe("SessionRunnerLLM", () => { }), ) const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = fragmentFixture("text", "text-no-system", ["Done"]).completeEvents @@ -988,7 +988,7 @@ describe("SessionRunnerLLM", () => { .run() .pipe(Effect.orDie) const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = fragmentFixture("text", "text-selected", ["Done"]).completeEvents @@ -1005,7 +1005,7 @@ describe("SessionRunnerLLM", () => { const session = yield* SessionV2.Service const events = yield* EventV2.Service skillBaselines.set(AgentV2.ID.make("build"), "Build skills") - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] @@ -1015,7 +1015,7 @@ describe("SessionRunnerLLM", () => { sessionID, agent: "reviewer", }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) yield* session.resume(sessionID) expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([ @@ -1044,7 +1044,7 @@ describe("SessionRunnerLLM", () => { }) .pipe(Effect.asVoid) }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] @@ -1072,7 +1072,7 @@ describe("SessionRunnerLLM", () => { }) .pipe(Effect.asVoid) }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] @@ -1088,13 +1088,13 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] yield* session.resume(sessionID) systemRemoved = true - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) yield* session.resume(sessionID) expect(requests[1]?.messages.map((message) => message.role)).toEqual(["user", "system", "user"]) @@ -1111,7 +1111,7 @@ describe("SessionRunnerLLM", () => { const session = yield* SessionV2.Service const contextEntries = yield* InstructionEntry.Service yield* contextEntries.put({ sessionID, key: "deploy-target", value: "production" }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] @@ -1125,7 +1125,7 @@ describe("SessionRunnerLLM", () => { // Non-string JSON pretty-prints; the change narrates as a System update. yield* contextEntries.put({ sessionID, key: "deploy-target", value: { region: "us-east-1" } }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) yield* session.resume(sessionID) expect(requests[1]?.messages.map((message) => message.role)).toEqual(["user", "system", "user"]) @@ -1146,7 +1146,7 @@ describe("SessionRunnerLLM", () => { // Deleting the row announces removal through the stored removal text. yield* contextEntries.remove({ sessionID, key: "deploy-target" }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Third" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Third" }), resume: false }) yield* session.resume(sessionID) expect(requests[2]?.messages.map((message) => message.role)).toEqual(["user", "system", "user", "system", "user"]) @@ -1162,20 +1162,20 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const events = yield* EventV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] yield* session.resume(sessionID) systemBaseline = "Changed context" - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) yield* session.resume(sessionID) yield* events.publish(SessionEvent.ModelSelected, { sessionID, model: { id: ModelV2.ID.make("replacement"), providerID: ProviderV2.ID.make("fake") }, }) systemBaseline = "Replacement context" - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Third" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Third" }), resume: false }) yield* session.resume(sessionID) expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([ @@ -1195,7 +1195,7 @@ describe("SessionRunnerLLM", () => { ]) yield* replaySessionProjection(sessionID) expect(yield* session.messages({ sessionID })).toHaveLength(6) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fourth" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Fourth" }), resume: false }) yield* session.resume(sessionID) }), ) @@ -1205,7 +1205,7 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const events = yield* EventV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] @@ -1215,11 +1215,11 @@ describe("SessionRunnerLLM", () => { model: { id: ModelV2.ID.make("replacement"), providerID: ProviderV2.ID.make("fake") }, }) systemUnavailable = true - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) yield* session.resume(sessionID) systemUnavailable = false systemBaseline = "Replacement context" - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Third" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Third" }), resume: false }) yield* session.resume(sessionID) expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([ @@ -1235,7 +1235,7 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const events = yield* EventV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] @@ -1252,7 +1252,7 @@ describe("SessionRunnerLLM", () => { recent: "", }) systemBaseline = "Replacement context" - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) yield* session.resume(sessionID) expect(requests.map((request) => request.system.map((part) => part.text))).toEqual([ @@ -1260,7 +1260,7 @@ describe("SessionRunnerLLM", () => { [defaultSystem, "Replacement context"], ]) yield* replaySessionProjection(sessionID) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Third" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Third" }), resume: false }) yield* session.resume(sessionID) }), ) @@ -1272,7 +1272,7 @@ describe("SessionRunnerLLM", () => { response = fragmentFixture("text", "text-first", ["Earlier answer"]).completeEvents yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Earlier question ".repeat(180) }), + prompt: PromptInput.Prompt.make({ text: "Earlier question ".repeat(180) }), resume: false, }) yield* session.resume(sessionID) @@ -1285,7 +1285,7 @@ describe("SessionRunnerLLM", () => { ] yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Recent exact request ".repeat(180) }), + prompt: PromptInput.Prompt.make({ text: "Recent exact request ".repeat(180) }), resume: false, }) yield* session.resume(sessionID) @@ -1311,7 +1311,7 @@ describe("SessionRunnerLLM", () => { ] yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Newest exact request ".repeat(180) }), + prompt: PromptInput.Prompt.make({ text: "Newest exact request ".repeat(180) }), resume: false, }) yield* session.resume(sessionID) @@ -1339,7 +1339,7 @@ describe("SessionRunnerLLM", () => { fragmentFixture("text", "text-summary", ["## Goal\n- Recover overflow"]).completeEvents, fragmentFixture("text", "text-final", ["Recovered"]).completeEvents, ] - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Continue" }), resume: false }) yield* session.resume(sessionID) expect(requests).toHaveLength(3) @@ -1369,7 +1369,7 @@ describe("SessionRunnerLLM", () => { fragmentFixture("text", "text-summary", ["## Goal\n- Recover once"]).completeEvents, overflow(), ] - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Continue" }), resume: false }) yield* session.resume(sessionID) expect(requests).toHaveLength(3) @@ -1397,7 +1397,7 @@ describe("SessionRunnerLLM", () => { fragmentFixture("text", "text-summary", ["## Goal\n- Recover raw overflow"]).completeEvents, fragmentFixture("text", "text-final", ["Recovered"]).completeEvents, ] - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Continue" }), resume: false }) yield* session.resume(sessionID) expect(requests).toHaveLength(3) @@ -1415,7 +1415,7 @@ describe("SessionRunnerLLM", () => { [LLMEvent.providerError({ message: "prompt too long", classification: "context-overflow" })], [LLMEvent.providerError({ message: "summary unavailable" })], ] - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Continue" }), resume: false }) yield* session.resume(sessionID) expect(requests).toHaveLength(2) @@ -1438,7 +1438,7 @@ describe("SessionRunnerLLM", () => { const firstGate = yield* Deferred.make() const summaryGate = yield* Deferred.make() streamGate = firstGate - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Continue" }), resume: false }) const run = yield* session.resume(sessionID).pipe(Effect.forkChild) while (requests.length < 1) yield* Effect.yieldNow streamGate = summaryGate @@ -1458,13 +1458,13 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const events = yield* EventV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First" }), resume: false }) requests.length = 0 response = [] yield* session.resume(sessionID) systemBaseline = "Changed context" - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second" }), resume: false }) yield* session.resume(sessionID) const compactionID = SessionMessage.ID.create() yield* events.publish(SessionEvent.Compaction.Started, { @@ -1478,7 +1478,7 @@ describe("SessionRunnerLLM", () => { recent: "", }) systemUnavailable = true - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Third" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Third" }), resume: false }) yield* session.resume(sessionID) // The rebaseline proceeds while the source is unobservable, restating the model's belief. @@ -1491,7 +1491,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Use tools" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Use tools" }), resume: false }) requests.length = 0 responses = undefined @@ -1589,7 +1589,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Echo this" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Echo this" }), resume: false }) requests.length = 0 authorizations.length = 0 @@ -1648,7 +1648,7 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const events = yield* EventV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Echo this" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Echo this" }), resume: false }) requests.length = 0 responses = [ @@ -1690,7 +1690,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Think first" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Think first" }), resume: false }) requests.length = 0 response = [ @@ -1728,7 +1728,7 @@ describe("SessionRunnerLLM", () => { }, ]) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Continue" }), resume: false }) response = [] yield* session.resume(sessionID) @@ -1747,7 +1747,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Search first" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Search first" }), resume: false }) requests.length = 0 response = [ @@ -1772,7 +1772,7 @@ describe("SessionRunnerLLM", () => { yield* session.resume(sessionID) yield* replaySessionProjection(sessionID) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Continue" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Continue" }), resume: false }) response = [] yield* session.resume(sessionID) @@ -1802,7 +1802,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Echo five times" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Echo five times" }), resume: false }) requests.length = 0 executions.length = 0 @@ -1863,7 +1863,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Echo twice" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Echo twice" }), resume: false }) requests.length = 0 executions.length = 0 @@ -1951,7 +1951,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run once" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Run once" }), resume: false }) requests.length = 0 responses = undefined @@ -1990,7 +1990,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Start working" }), resume: false }) requests.length = 0 responses = [ @@ -2010,7 +2010,7 @@ describe("SessionRunnerLLM", () => { const first = yield* session.resume(sessionID).pipe(Effect.forkChild) yield* Deferred.await(streamStarted) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Change direction" }) }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Change direction" }) }) yield* Deferred.succeed(streamGate, undefined) yield* Fiber.join(first) streamGate = undefined @@ -2033,7 +2033,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Start working" }), resume: false }) requests.length = 0 responses = [ @@ -2061,7 +2061,7 @@ describe("SessionRunnerLLM", () => { yield* Deferred.await(streamStarted) yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Wait until continuation ends" }), + prompt: PromptInput.Prompt.make({ text: "Wait until continuation ends" }), delivery: "queue", }) yield* Deferred.succeed(streamGate, undefined) @@ -2081,7 +2081,7 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const { db } = yield* Database.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt current work" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Interrupt current work" }), resume: false }) requests.length = 0 responses = [ @@ -2099,7 +2099,7 @@ describe("SessionRunnerLLM", () => { yield* Deferred.await(streamStarted) yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Run after interrupt" }), + prompt: PromptInput.Prompt.make({ text: "Run after interrupt" }), delivery: "queue", }) yield* session.interrupt(sessionID) @@ -2124,7 +2124,7 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const { db } = yield* Database.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt current work" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Interrupt current work" }), resume: false }) requests.length = 0 responses = [ @@ -2142,7 +2142,7 @@ describe("SessionRunnerLLM", () => { yield* Deferred.await(streamStarted) yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Steer after interrupt" }), + prompt: PromptInput.Prompt.make({ text: "Steer after interrupt" }), }) yield* session.interrupt(sessionID) expect(yield* Fiber.await(run)).toMatchObject({ _tag: "Failure" }) @@ -2166,7 +2166,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Start working" }), resume: false }) requests.length = 0 responses = [ @@ -2191,8 +2191,8 @@ describe("SessionRunnerLLM", () => { const first = yield* session.resume(sessionID).pipe(Effect.forkChild) yield* Deferred.await(streamStarted) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Queue first" }), delivery: "queue" }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Queue second" }), delivery: "queue" }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Queue first" }), delivery: "queue" }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Queue second" }), delivery: "queue" }) yield* Deferred.succeed(streamGate, undefined) yield* Fiber.join(first) streamGate = undefined @@ -2209,10 +2209,10 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start steering" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Start steering" }), resume: false }) yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Queue for later" }), + prompt: PromptInput.Prompt.make({ text: "Queue for later" }), delivery: "queue", resume: false, }) @@ -2243,7 +2243,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Start working" }), resume: false }) requests.length = 0 responses = [ @@ -2274,13 +2274,13 @@ describe("SessionRunnerLLM", () => { const first = yield* session.resume(sessionID).pipe(Effect.forkChild) while (requests.length < 1) yield* Effect.yieldNow - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Queue first" }), delivery: "queue" }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Queue second" }), delivery: "queue" }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Queue first" }), delivery: "queue" }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Queue second" }), delivery: "queue" }) streamGate = secondGate yield* Deferred.succeed(firstGate, undefined) while (requests.length < 2) yield* Effect.yieldNow - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Steer before next queued input" }) }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Also steer before next queued input" }) }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Steer before next queued input" }) }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Also steer before next queued input" }) }) yield* Deferred.succeed(secondGate, undefined) yield* Fiber.join(first) streamGate = undefined @@ -2308,7 +2308,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Start working" }), resume: false }) requests.length = 0 responses = [ @@ -2328,8 +2328,8 @@ describe("SessionRunnerLLM", () => { const first = yield* session.resume(sessionID).pipe(Effect.forkChild) yield* Deferred.await(streamStarted) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "First steer" }) }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Second steer" }) }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "First steer" }) }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Second steer" }) }) yield* Deferred.succeed(streamGate, undefined) yield* Fiber.join(first) streamGate = undefined @@ -2348,7 +2348,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start working" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Start working" }), resume: false }) requests.length = 0 responses = undefined @@ -2359,7 +2359,7 @@ describe("SessionRunnerLLM", () => { const first = yield* session.resume(sessionID).pipe(Effect.forkChild) yield* Deferred.await(streamStarted) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Recover with this" }) }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Recover with this" }) }) yield* Deferred.succeed(streamGate, undefined) expect(yield* Fiber.join(first).pipe(Effect.flip)).toBe(streamFailure) @@ -2378,7 +2378,7 @@ describe("SessionRunnerLLM", () => { yield* setup const session = yield* SessionV2.Service const events = yield* EventV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Recover interrupted tool" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Recover interrupted tool" }), resume: false }) yield* SessionInput.promoteSteers((yield* Database.Service).db, events, sessionID) const assistantMessageID = SessionMessage.ID.create() yield* events.publish(SessionEvent.Step.Started, { @@ -2436,7 +2436,7 @@ describe("SessionRunnerLLM", () => { const events = yield* EventV2.Service yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Recover interrupted hosted tool" }), + prompt: PromptInput.Prompt.make({ text: "Recover interrupted hosted tool" }), resume: false, }) yield* SessionInput.promoteSteers((yield* Database.Service).db, events, sessionID) @@ -2492,7 +2492,7 @@ describe("SessionRunnerLLM", () => { const events = yield* EventV2.Service yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Recover interrupted tool input" }), + prompt: PromptInput.Prompt.make({ text: "Recover interrupted tool input" }), resume: false, }) yield* SessionInput.promoteSteers((yield* Database.Service).db, events, sessionID) @@ -2528,7 +2528,7 @@ describe("SessionRunnerLLM", () => { const session = yield* SessionV2.Service yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Wait in queue" }), + prompt: PromptInput.Prompt.make({ text: "Wait in queue" }), delivery: "queue", resume: false, }) @@ -2550,7 +2550,7 @@ describe("SessionRunnerLLM", () => { const defect = new Error("fail after prompt promotion") let fail = true yield* events.project(SessionEvent.PromptPromoted, () => (fail ? Effect.die(defect) : Effect.void)) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Recover promoted input" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Recover promoted input" }), resume: false }) expect(yield* session.resume(sessionID).pipe(Effect.catchDefect(Effect.succeed))).toBe(defect) fail = false @@ -2580,7 +2580,7 @@ describe("SessionRunnerLLM", () => { ) yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Run committed promotion" }), + prompt: PromptInput.Prompt.make({ text: "Run committed promotion" }), resume: false, }) @@ -2597,8 +2597,8 @@ describe("SessionRunnerLLM", () => { yield* setup yield* insertSession(otherSessionID) const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Run first" }), resume: false }) - yield* session.prompt({ sessionID: otherSessionID, prompt: Prompt.make({ text: "Run second" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Run first" }), resume: false }) + yield* session.prompt({ sessionID: otherSessionID, prompt: PromptInput.Prompt.make({ text: "Run second" }), resume: false }) requests.length = 0 responses = undefined @@ -2635,12 +2635,12 @@ describe("SessionRunnerLLM", () => { const session = yield* SessionV2.Service yield* session.prompt({ sessionID: longSessionID, - prompt: Prompt.make({ text: "Run long session" }), + prompt: PromptInput.Prompt.make({ text: "Run long session" }), resume: false, }) yield* session.prompt({ sessionID: otherLongSessionID, - prompt: Prompt.make({ text: "Run other long session" }), + prompt: PromptInput.Prompt.make({ text: "Run other long session" }), resume: false, }) @@ -2659,7 +2659,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Retry after failure" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Retry after failure" }), resume: false }) requests.length = 0 responses = undefined @@ -2690,7 +2690,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Call missing" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Call missing" }), resume: false }) requests.length = 0 responses = [ @@ -2736,7 +2736,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Call defect" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Call defect" }), resume: false }) requests.length = 0 responses = [ @@ -2784,7 +2784,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Call storefail" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Call storefail" }), resume: false }) requests.length = 0 responses = [ @@ -2836,7 +2836,7 @@ describe("SessionRunnerLLM", () => { execute: () => Effect.die(new QuestionTool.CancelledError()), }), }) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Ask then stop" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Ask then stop" }), resume: false }) requests.length = 0 responses = [ @@ -2875,7 +2875,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Settle before failing" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Settle before failing" }), resume: false }) const failure = providerUnavailable() toolExecutionGate = yield* Deferred.make() responseStream = Stream.concat( @@ -2909,7 +2909,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt blocked tool" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Interrupt blocked tool" }), resume: false }) executions.length = 0 toolExecutionGate = yield* Deferred.make() responseStream = Stream.concat( @@ -2959,7 +2959,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt provider" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Interrupt provider" }), resume: false }) requests.length = 0 response = [] streamGate = yield* Deferred.make() @@ -2987,7 +2987,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Interrupt tool settlement" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Interrupt tool settlement" }), resume: false }) executions.length = 0 toolExecutionGate = yield* Deferred.make() toolExecutionsStarted = yield* Deferred.make() @@ -3037,7 +3037,7 @@ describe("SessionRunnerLLM", () => { }), ) const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Finish at the limit" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Finish at the limit" }), resume: false }) requests.length = 0 executions.length = 0 @@ -3085,7 +3085,7 @@ describe("SessionRunnerLLM", () => { }), ) const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Start work" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Start work" }), resume: false }) requests.length = 0 executions.length = 0 @@ -3113,7 +3113,7 @@ describe("SessionRunnerLLM", () => { const run = yield* session.resume(sessionID).pipe(Effect.forkChild) yield* Deferred.await(streamStarted) - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Change direction" }) }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Change direction" }) }) yield* Deferred.succeed(streamGate, undefined) yield* Fiber.join(run) streamGate = undefined @@ -3131,7 +3131,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail durably" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Fail durably" }), resume: false }) requests.length = 0 responses = undefined @@ -3153,7 +3153,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail before step" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Fail before step" }), resume: false }) requests.length = 0 response = [LLMEvent.providerError({ message: "Provider unavailable" })] @@ -3172,7 +3172,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail after output" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Fail after output" }), resume: false }) requests.length = 0 response = [ @@ -3201,7 +3201,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail raw stream durably" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Fail raw stream durably" }), resume: false }) const failure = providerUnavailable() responseStream = Stream.fail(failure) @@ -3220,7 +3220,7 @@ describe("SessionRunnerLLM", () => { const session = yield* SessionV2.Service yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Do not continue failed provider" }), + prompt: PromptInput.Prompt.make({ text: "Do not continue failed provider" }), resume: false, }) @@ -3243,7 +3243,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail hosted tool durably" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Fail hosted tool durably" }), resume: false }) requests.length = 0 response = [ @@ -3274,7 +3274,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Fail hosted tool at EOF" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Fail hosted tool at EOF" }), resume: false }) response = [ LLMEvent.stepStart({ index: 0 }), LLMEvent.toolCall({ @@ -3301,7 +3301,7 @@ describe("SessionRunnerLLM", () => { const session = yield* SessionV2.Service yield* session.prompt({ sessionID, - prompt: Prompt.make({ text: "Fail hosted tool on raw failure" }), + prompt: PromptInput.Prompt.make({ text: "Fail hosted tool on raw failure" }), resume: false, }) const failure = providerUnavailable() @@ -3336,7 +3336,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Two blocks" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Two blocks" }), resume: false }) responses = undefined streamGate = undefined @@ -3400,7 +3400,7 @@ describe("SessionRunnerLLM", () => { Effect.gen(function* () { yield* setup const session = yield* SessionV2.Service - yield* session.prompt({ sessionID, prompt: Prompt.make({ text: "Call provider tool" }), resume: false }) + yield* session.prompt({ sessionID, prompt: PromptInput.Prompt.make({ text: "Call provider tool" }), resume: false }) responses = undefined streamGate = undefined diff --git a/packages/core/test/session-title.test.ts b/packages/core/test/session-title.test.ts index 59abb8fabc9..f962672494c 100644 --- a/packages/core/test/session-title.test.ts +++ b/packages/core/test/session-title.test.ts @@ -9,7 +9,7 @@ import { LayerNode } from "@opencode-ai/core/effect/layer-node" import { EventV2 } from "@opencode-ai/core/event" import { SessionEvent } from "@opencode-ai/core/session/event" import { SessionMessage } from "@opencode-ai/core/session/message" -import { Prompt } from "@opencode-ai/core/session/prompt" +import { Prompt } from "@opencode-ai/schema/prompt" import { SessionProjector } from "@opencode-ai/core/session/projector" import { SessionRunnerModel } from "@opencode-ai/core/session/runner/model" import { SessionTable } from "@opencode-ai/core/session/sql" diff --git a/packages/core/test/shared-schema.test.ts b/packages/core/test/shared-schema.test.ts index 7d227aac19b..d96f6e5bd52 100644 --- a/packages/core/test/shared-schema.test.ts +++ b/packages/core/test/shared-schema.test.ts @@ -6,11 +6,11 @@ import { SessionV2 } from "@opencode-ai/core/session" import { Agent } from "@opencode-ai/schema/agent" import { Location } from "@opencode-ai/schema/location" import { Model } from "@opencode-ai/schema/model" -import { AgentAttachment, FileAttachment, Prompt, Source } from "@opencode-ai/schema/prompt" import { Provider } from "@opencode-ai/schema/provider" import { Project } from "@opencode-ai/schema/project" import { ProjectDirectories } from "@opencode-ai/schema/project-directories" import { PermissionV1 } from "@opencode-ai/schema/permission-v1" +import { Prompt } from "@opencode-ai/schema/prompt" import { Session } from "@opencode-ai/schema/session" import { SessionInput } from "@opencode-ai/schema/session-input" import { SessionMessage } from "@opencode-ai/schema/session-message" @@ -47,7 +47,6 @@ test("Core reuses the canonical shared schemas", async () => { coreSessionInput, coreSessionMessage, coreSessionTodo, - corePrompt, coreSkill, coreV2Schema, coreSchema, @@ -69,7 +68,6 @@ test("Core reuses the canonical shared schemas", async () => { import("@opencode-ai/core/session/input"), import("@opencode-ai/core/session/message"), import("@opencode-ai/core/session/todo"), - import("@opencode-ai/core/session/prompt"), import("@opencode-ai/core/skill"), import("@opencode-ai/core/v2-schema"), import("@opencode-ai/core/schema"), @@ -164,10 +162,6 @@ test("Core reuses the canonical shared schemas", async () => { [coreSessionMessage.Message, SessionMessage.Message], [coreSessionTodo.Info, SessionTodo.Info], [coreSessionTodo.Event, SessionTodo.Event], - [corePrompt.Source, Source], - [corePrompt.FileAttachment, FileAttachment], - [corePrompt.AgentAttachment, AgentAttachment], - [corePrompt.Prompt, Prompt], [coreSkill.DirectorySource, Skill.DirectorySource], [coreSkill.UrlSource, Skill.UrlSource], [coreSkill.EmbeddedSource, Skill.EmbeddedSource], diff --git a/packages/protocol/src/groups/session.ts b/packages/protocol/src/groups/session.ts index 4e2cc5dd9bb..8819d7d9e4e 100644 --- a/packages/protocol/src/groups/session.ts +++ b/packages/protocol/src/groups/session.ts @@ -264,7 +264,7 @@ export const makeSessionGroup = (sessionLo resume: Schema.Boolean.pipe(Schema.optional), }), success: Schema.Struct({ data: SessionInput.Admitted }), - error: [ConflictError, SessionNotFoundError], + error: [ConflictError, InvalidRequestError, SessionNotFoundError], }) .middleware(sessionLocationMiddleware) .annotateMerge( @@ -290,7 +290,13 @@ export const makeSessionGroup = (sessionLo resume: Schema.Boolean.pipe(Schema.optional), }), success: Schema.Struct({ data: SessionInput.Admitted }), - error: [ConflictError, SessionNotFoundError, CommandNotFoundError, CommandEvaluationError], + error: [ + ConflictError, + InvalidRequestError, + SessionNotFoundError, + CommandNotFoundError, + CommandEvaluationError, + ], }) .middleware(sessionLocationMiddleware) .annotateMerge( diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts index 1454fab1cf4..831f97b0664 100644 --- a/packages/schema/src/index.ts +++ b/packages/schema/src/index.ts @@ -27,6 +27,6 @@ export { Pty } from "./pty.js" export { PtyTicket } from "./pty-ticket.js" export { Question } from "./question.js" export { Workspace } from "./workspace.js" -export { Prompt, Source, FileAttachment, AgentAttachment } from "./prompt.js" +export { Prompt, PromptMention, FileSource, FileAttachment, AgentAttachment } from "./prompt.js" export { PromptInput } from "./prompt-input.js" export * from "./schema.js" diff --git a/packages/schema/src/prompt-input.ts b/packages/schema/src/prompt-input.ts index d573f385550..a52aa23c83c 100644 --- a/packages/schema/src/prompt-input.ts +++ b/packages/schema/src/prompt-input.ts @@ -1,7 +1,7 @@ export * as PromptInput from "./prompt-input.js" import { Schema } from "effect" -import { AgentAttachment, Source } from "./prompt.js" +import { AgentAttachment, PromptMention } from "./prompt.js" import { optional, statics } from "./schema.js" export interface FileAttachment extends Schema.Schema.Type {} @@ -9,7 +9,7 @@ export const FileAttachment = Schema.Struct({ uri: Schema.String, name: Schema.String.pipe(optional), description: Schema.String.pipe(optional), - source: Source.pipe(optional), + mention: PromptMention.pipe(optional), }) .annotate({ identifier: "PromptInput.FileAttachment" }) .pipe( diff --git a/packages/schema/src/prompt.ts b/packages/schema/src/prompt.ts index 2438df2e985..3b3a5ac2712 100644 --- a/packages/schema/src/prompt.ts +++ b/packages/schema/src/prompt.ts @@ -2,33 +2,46 @@ import { Schema } from "effect" import { optional } from "./schema.js" import { statics } from "./schema.js" -export interface Source extends Schema.Schema.Type {} -export const Source = Schema.Struct({ +export interface PromptMention extends Schema.Schema.Type {} +export const PromptMention = Schema.Struct({ start: Schema.Finite, end: Schema.Finite, text: Schema.String, -}).annotate({ identifier: "Prompt.Source" }) +}).annotate({ identifier: "Prompt.Mention" }) + +export const FileSource = Schema.Union([ + Schema.Struct({ type: Schema.Literal("inline") }), + Schema.Struct({ type: Schema.Literal("uri"), uri: Schema.String }), +]) + .pipe(Schema.toTaggedUnion("type")) + .annotate({ identifier: "Prompt.FileSource" }) +export type FileSource = typeof FileSource.Type + +export const Base64 = Schema.String.check( + Schema.isPattern(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/), +).annotate({ identifier: "Prompt.Base64" }) +export type Base64 = typeof Base64.Type export interface FileAttachment extends Schema.Schema.Type {} export const FileAttachment = Schema.Struct({ - uri: Schema.String, + data: Base64, mime: Schema.String, - content: Schema.String.pipe(optional), + source: FileSource, name: Schema.String.pipe(optional), description: Schema.String.pipe(optional), - source: Source.pipe(optional), + mention: PromptMention.pipe(optional), }) .annotate({ identifier: "Prompt.FileAttachment" }) .pipe( statics((schema) => ({ create: (input: FileAttachment) => schema.make({ - uri: input.uri, + data: input.data, mime: input.mime, - content: input.content, + source: input.source, name: input.name, description: input.description, - source: input.source, + mention: input.mention, }), })), ) @@ -36,7 +49,7 @@ export const FileAttachment = Schema.Struct({ export interface AgentAttachment extends Schema.Schema.Type {} export const AgentAttachment = Schema.Struct({ name: Schema.String, - source: Source.pipe(optional), + mention: PromptMention.pipe(optional), }).annotate({ identifier: "Prompt.AgentAttachment" }) export interface Prompt extends Schema.Schema.Type {} diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index fc7bedea1f0..f1215bf713a 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -3255,24 +3255,35 @@ export type LocationRef = { workspaceID?: string } -export type PromptSource = { +export type PromptBase64 = string + +export type PromptFileSource = + | { + type: "inline" + } + | { + type: "uri" + uri: string + } + +export type PromptMention = { start: number end: number text: string } export type PromptFileAttachment = { - uri: string + data: PromptBase64 mime: string - content?: string + source: PromptFileSource name?: string description?: string - source?: PromptSource + mention?: PromptMention } export type PromptAgentAttachment = { name: string - source?: PromptSource + mention?: PromptMention } export type SessionErrorUnknown = { @@ -4279,7 +4290,7 @@ export type PromptInputFileAttachment = { uri: string name?: string description?: string - source?: PromptSource + mention?: PromptMention } export type SessionInputAdmitted = { @@ -7877,7 +7888,7 @@ export type MessageNotFoundErrorV2 = { message: string } -export type PromptSource2 = { +export type PromptMention2 = { start: number end: number text: string @@ -7887,12 +7898,12 @@ export type PromptInputFileAttachment2 = { uri: string name?: string description?: string - source?: PromptSource2 + mention?: PromptMention2 } export type PromptAgentAttachment2 = { name: string - source?: PromptSource2 + mention?: PromptMention2 } export type PromptInputV2 = { @@ -7901,13 +7912,24 @@ export type PromptInputV2 = { agents?: Array } +export type PromptBase642 = string + +export type PromptFileSource2 = + | { + type: "inline" + } + | { + type: "uri" + uri: string + } + export type PromptFileAttachment2 = { - uri: string + data: PromptBase642 mime: string - content?: string + source: PromptFileSource2 name?: string description?: string - source?: PromptSource2 + mention?: PromptMention2 } export type PromptV2 = { @@ -15965,7 +15987,7 @@ export type V2SessionPromptErrors = { /** * InvalidRequestError */ - 400: InvalidRequestErrorV2 + 400: InvalidRequestError1 | InvalidRequestErrorV2 /** * UnauthorizedError */ @@ -16016,7 +16038,7 @@ export type V2SessionCommandErrors = { /** * InvalidRequestError */ - 400: InvalidRequestErrorV2 + 400: InvalidRequestError1 | InvalidRequestErrorV2 /** * UnauthorizedError */ diff --git a/packages/server/src/handlers/session.ts b/packages/server/src/handlers/session.ts index 2bb45d52ed1..aa79b8bd51e 100644 --- a/packages/server/src/handlers/session.ts +++ b/packages/server/src/handlers/session.ts @@ -9,6 +9,7 @@ import { CommandEvaluationError, CommandNotFoundError, InvalidCursorError, + InvalidRequestError, MessageNotFoundError, ServiceUnavailableError, SessionBusyError, @@ -213,6 +214,9 @@ export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handl }), ), ), + Effect.catchTag("Session.AttachmentError", (error) => + Effect.fail(new InvalidRequestError({ message: error.message, field: "prompt.files" })), + ), ), } }), @@ -267,6 +271,9 @@ export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handl }), ), ), + Effect.catchTag("Session.AttachmentError", (error) => + Effect.fail(new InvalidRequestError({ message: error.message, field: "files" })), + ), ), } }), diff --git a/packages/tui/src/component/prompt/autocomplete.tsx b/packages/tui/src/component/prompt/autocomplete.tsx index 50bf0a64a26..65bff40838d 100644 --- a/packages/tui/src/component/prompt/autocomplete.tsx +++ b/packages/tui/src/component/prompt/autocomplete.tsx @@ -210,17 +210,17 @@ export function Autocomplete(props: { const existingIndex = files.findIndex((file) => file.uri === part.value.uri) if (existingIndex !== -1) { const existing = files[existingIndex] - if (existing?.source) { - existing.source.start = extmarkStart - existing.source.end = extmarkEnd - existing.source.text = virtualText + if (existing?.mention) { + existing.mention.start = extmarkStart + existing.mention.end = extmarkEnd + existing.mention.text = virtualText } return } - if (part.value.source) { - part.value.source.start = extmarkStart - part.value.source.end = extmarkEnd - part.value.source.text = virtualText + if (part.value.mention) { + part.value.mention.start = extmarkStart + part.value.mention.end = extmarkEnd + part.value.mention.text = virtualText } const index = files.length files.push(part.value) @@ -229,10 +229,10 @@ export function Autocomplete(props: { } const agents = (draft.agents ??= []) - if (part.value.source) { - part.value.source.start = extmarkStart - part.value.source.end = extmarkEnd - part.value.source.text = virtualText + if (part.value.mention) { + part.value.mention.start = extmarkStart + part.value.mention.end = extmarkEnd + part.value.mention.text = virtualText } const index = agents.length agents.push(part.value) @@ -268,7 +268,7 @@ export function Autocomplete(props: { value: { uri: urlObj.href, name: filename, - source: { start: 0, end: 0, text: "" }, + mention: { start: 0, end: 0, text: "" }, }, }, } @@ -376,7 +376,7 @@ export function Autocomplete(props: { uri: res.uri, name: res.name, description: res.description, - source: { start: 0, end: 0, text: "" }, + mention: { start: 0, end: 0, text: "" }, }, }) }, @@ -397,7 +397,7 @@ export function Autocomplete(props: { type: "agent", value: { name: agent.id, - source: { start: 0, end: 0, text: "" }, + mention: { start: 0, end: 0, text: "" }, }, }) }, @@ -419,7 +419,7 @@ export function Autocomplete(props: { value: { uri: pathToFileURL(reference.path).href, name: reference.name, - source: { start: 0, end: 0, text: "" }, + mention: { start: 0, end: 0, text: "" }, }, }) }, diff --git a/packages/tui/src/component/prompt/index.tsx b/packages/tui/src/component/prompt/index.tsx index c7276206a90..cccb9e6bf01 100644 --- a/packages/tui/src/component/prompt/index.tsx +++ b/packages/tui/src/component/prompt/index.tsx @@ -483,17 +483,17 @@ export function Prompt(props: PromptProps) { // Update attachment positions and drop virtual text deleted in the editor. // this handles a case where the user edits the text in the editor // such that the virtual text moves around or is deleted - const moveSource = (part: Part) => { - if (!part.source?.text) return part - const start = normalized.indexOf(part.source.text) + const moveMention = (part: Part) => { + if (!part.mention?.text) return part + const start = normalized.indexOf(part.mention.text) if (start === -1) return - return { ...part, source: { ...part.source, start, end: start + part.source.text.length } } + return { ...part, mention: { ...part.mention, start, end: start + part.mention.text.length } } } setStore("prompt", { text: normalized, - files: store.prompt.files?.map(moveSource).filter((part) => part !== undefined), - agents: store.prompt.agents?.map(moveSource).filter((part) => part !== undefined), + files: store.prompt.files?.map(moveMention).filter((part) => part !== undefined), + agents: store.prompt.agents?.map(moveMention).filter((part) => part !== undefined), pasted: [], }) restoreExtmarksFromPrompt(store.prompt) @@ -647,16 +647,28 @@ export function Prompt(props: PromptProps) { setStore("extmarkToPart", new Map()) const parts = [ - ...(prompt.files ?? []).map((part, index) => ({ part, ref: { type: "file" as const, index }, styleId: fileStyleId })), - ...(prompt.agents ?? []).map((part, index) => ({ part, ref: { type: "agent" as const, index }, styleId: agentStyleId })), - ...prompt.pasted.map((part, index) => ({ part, ref: { type: "pasted" as const, index }, styleId: pasteStyleId })), + ...(prompt.files ?? []).map((part, index) => ({ + mention: part.mention, + ref: { type: "file" as const, index }, + styleId: fileStyleId, + })), + ...(prompt.agents ?? []).map((part, index) => ({ + mention: part.mention, + ref: { type: "agent" as const, index }, + styleId: agentStyleId, + })), + ...prompt.pasted.map((part, index) => ({ + mention: part.source, + ref: { type: "pasted" as const, index }, + styleId: pasteStyleId, + })), ] - parts.forEach(({ part, ref, styleId }) => { - if (part.source?.text) { + parts.forEach(({ mention, ref, styleId }) => { + if (mention?.text) { const extmarkId = input.extmarks.create({ - start: part.source.start, - end: part.source.end, + start: mention.start, + end: mention.end, virtual: true, styleId, typeId: promptPartTypeId, @@ -684,9 +696,9 @@ export function Prompt(props: PromptProps) { if (!ref) continue if (ref.type === "file") { const part = draft.prompt.files?.[ref.index] - if (!part?.source) continue - part.source.start = extmark.start - part.source.end = extmark.end + if (!part?.mention) continue + part.mention.start = extmark.start + part.mention.end = extmark.end const index = files.length files.push(part) newMap.set(extmark.id, { type: "file", index }) @@ -694,9 +706,9 @@ export function Prompt(props: PromptProps) { } if (ref.type === "agent") { const part = draft.prompt.agents?.[ref.index] - if (!part?.source) continue - part.source.start = extmark.start - part.source.end = extmark.end + if (!part?.mention) continue + part.mention.start = extmark.start + part.mention.end = extmark.end const index = agents.length agents.push(part) newMap.set(extmark.id, { type: "agent", index }) @@ -1248,7 +1260,7 @@ export function Prompt(props: PromptProps) { const part: NonNullable[number] = { uri: file.uri, name: file.filename, - source: { + mention: { start: extmarkStart, end: extmarkEnd, text: virtualText, diff --git a/packages/tui/src/routes/session/dialog-fork-from-timeline.tsx b/packages/tui/src/routes/session/dialog-fork-from-timeline.tsx index d056ad5bae1..d0952a907e6 100644 --- a/packages/tui/src/routes/session/dialog-fork-from-timeline.tsx +++ b/packages/tui/src/routes/session/dialog-fork-from-timeline.tsx @@ -59,7 +59,7 @@ export function DialogForkFromTimeline(props: { sessionID: string; onMove: (mess files.push({ uri: part.url, name: part.filename, - source: part.source?.text + mention: part.source?.text ? { start: part.source.text.start, end: part.source.text.end, diff --git a/packages/tui/src/routes/session/index.tsx b/packages/tui/src/routes/session/index.tsx index 5a52f11c873..b1d036cd68a 100644 --- a/packages/tui/src/routes/session/index.tsx +++ b/packages/tui/src/routes/session/index.tsx @@ -1428,7 +1428,7 @@ function UserMessage(props: { message: SessionMessageUser }) { {" "} - {file.name ?? file.uri}{" "} + {file.name ?? (file.source.type === "uri" ? file.source.uri : "attachment")}{" "} ) From 36d17c30a7f906eace05e005f4ce285faf45799e Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 6 Jul 2026 15:05:43 -0400 Subject: [PATCH 16/46] fix(sdk): expose prompt input contract --- packages/cli/src/mini/session.shared.ts | 12 ++++++------ packages/client/src/effect/index.ts | 1 + packages/sdk-next/src/index.ts | 1 + packages/sdk-next/test/embedded.test.ts | 6 +++--- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/packages/cli/src/mini/session.shared.ts b/packages/cli/src/mini/session.shared.ts index e68df9e6c26..b6f1f6dd11c 100644 --- a/packages/cli/src/mini/session.shared.ts +++ b/packages/cli/src/mini/session.shared.ts @@ -176,22 +176,22 @@ export async function resolveCurrentSession( parts: [ ...(message.files ?? []).map((file) => ({ type: "file" as const, - url: file.uri, + url: file.source.type === "uri" ? file.source.uri : `data:${file.mime};base64,${file.data}`, mime: file.mime, filename: file.name, - source: file.source + source: file.mention ? { type: "file" as const, - path: file.name ?? file.uri, - text: { start: file.source.start, end: file.source.end, value: file.source.text }, + path: file.name ?? (file.source.type === "uri" ? file.source.uri : "inline attachment"), + text: { start: file.mention.start, end: file.mention.end, value: file.mention.text }, } : undefined, })), ...(message.agents ?? []).map((agent) => ({ type: "agent" as const, name: agent.name, - source: agent.source - ? { start: agent.source.start, end: agent.source.end, value: agent.source.text } + source: agent.mention + ? { start: agent.mention.start, end: agent.mention.end, value: agent.mention.text } : undefined, })), ], diff --git a/packages/client/src/effect/index.ts b/packages/client/src/effect/index.ts index 8cde84695c9..3e47320953f 100644 --- a/packages/client/src/effect/index.ts +++ b/packages/client/src/effect/index.ts @@ -42,5 +42,6 @@ export { SessionInput } from "@opencode-ai/schema/session-input" export { SessionMessage } from "@opencode-ai/schema/session-message" export { Skill } from "@opencode-ai/schema/skill" export { Prompt } from "@opencode-ai/schema/prompt" +export { PromptInput } from "@opencode-ai/schema/prompt-input" export type { OpenCodeEvent } from "@opencode-ai/protocol/groups/event" export type OpenCodeClient = Effect.Success> diff --git a/packages/sdk-next/src/index.ts b/packages/sdk-next/src/index.ts index fc23219fc40..41010211521 100644 --- a/packages/sdk-next/src/index.ts +++ b/packages/sdk-next/src/index.ts @@ -8,6 +8,7 @@ export { Location, Model, Prompt, + PromptInput, Provider, RelativePath, Session, diff --git a/packages/sdk-next/test/embedded.test.ts b/packages/sdk-next/test/embedded.test.ts index cd9cd6a50dc..b0efa629097 100644 --- a/packages/sdk-next/test/embedded.test.ts +++ b/packages/sdk-next/test/embedded.test.ts @@ -181,7 +181,7 @@ it.live( const active = yield* opencode.sessions.active() const admitted = yield* opencode.sessions.prompt({ sessionID: id, - prompt: fixture.sdk.Prompt.make({ text: "Do not run" }), + prompt: fixture.sdk.PromptInput.Prompt.make({ text: "Do not run" }), resume: false, }) const context = yield* opencode.sessions.context({ sessionID: id }) @@ -192,7 +192,7 @@ it.live( const remainingContextEntries = yield* opencode.sessions.instructions.entry.list({ sessionID: id }) const wake = yield* opencode.sessions.prompt({ sessionID: id, - prompt: fixture.sdk.Prompt.make({ text: "Promote this input" }), + prompt: fixture.sdk.PromptInput.Prompt.make({ text: "Promote this input" }), }) const prompted = yield* opencode.sessions.log({ sessionID: id, follow: true }).pipe( Stream.filter((event) => event.type === "session.prompt.promoted" && event.data.inputID === wake.id), @@ -282,7 +282,7 @@ it.live( yield* opencode.sessions.create({ id, location: location(fixture) }) yield* opencode.sessions.prompt({ sessionID: id, - prompt: fixture.sdk.Prompt.make({ text: "Observe this input" }), + prompt: fixture.sdk.PromptInput.Prompt.make({ text: "Observe this input" }), }) const event = yield* Deferred.await(prompted).pipe(Effect.timeout("4 seconds")) From 6ffe61b9fee00bfc84de3fa16b81f61a53db7a43 Mon Sep 17 00:00:00 2001 From: James Long Date: Mon, 6 Jul 2026 15:39:03 -0400 Subject: [PATCH 17/46] feat(simulation): isolate filesystem and disconnect llm (#35590) --- packages/simulation/src/backend/control.ts | 6 + packages/simulation/src/backend/fs-util.ts | 148 ++++++++++++++++-- .../simulation/src/backend/llm-exchange.ts | 8 + packages/simulation/src/protocol/index.ts | 4 + 4 files changed, 155 insertions(+), 11 deletions(-) diff --git a/packages/simulation/src/backend/control.ts b/packages/simulation/src/backend/control.ts index 10bded13af9..28bb18c0090 100644 --- a/packages/simulation/src/backend/control.ts +++ b/packages/simulation/src/backend/control.ts @@ -17,6 +17,7 @@ import { SimulationNetwork } from "./network" * as `llm.request` notifications * - `llm.chunk` { id, items } append response items to an exchange * - `llm.finish` { id, reason? } finish an exchange + * - `llm.disconnect` { id } abruptly terminate an exchange without a finish * - `llm.pending` list open exchanges * - `network.log` simulated network request log */ @@ -54,6 +55,11 @@ async function handle(socket: ControlSocket, request: SimulationProtocol.JsonRpc await Effect.runPromise(SimulationLLMExchange.push(params.id, [{ type: "finish", reason: params.reason }])) return { ok: true } } + case "llm.disconnect": { + const params = await SimulationProtocol.Backend.decodeDisconnectParams(request.params) + await Effect.runPromise(SimulationLLMExchange.disconnect(params.id)) + return { ok: true } + } case "llm.pending": return { exchanges: SimulationLLMExchange.pending() } case "network.log": diff --git a/packages/simulation/src/backend/fs-util.ts b/packages/simulation/src/backend/fs-util.ts index e24d0c9c4be..4ee267fd649 100644 --- a/packages/simulation/src/backend/fs-util.ts +++ b/packages/simulation/src/backend/fs-util.ts @@ -8,22 +8,100 @@ import path from "path" /** * Simulation replacement for `FSUtil`. * - * The real `FSUtil` layer builds most helpers on the injected - * `FileSystem.FileSystem`, but `readDirectoryEntries`, `glob`, and `globUp` - * reach for node `fs/promises` and the `glob` package directly, and `resolve` - * canonicalizes through the host filesystem. This wraps the real layer and - * reroutes those through the injected `FileSystem`/lexical path resolution so - * every read observes the in-memory tree. + * This implementation is intentionally self-contained and only uses the + * injected simulated `FileSystem.FileSystem`. The default FSUtil layer has a + * few helpers that reach host-node APIs directly; depending on it here makes it + * easy for mutation paths to escape or miss the in-memory project tree. */ const layer = Layer.effect( FSUtil.Service, Effect.gen(function* () { - const base = yield* FSUtil.Service const fs = yield* FileSystem.FileSystem - const resolve = Effect.fn("SimulationFSUtil.resolve")(function* (input: string) { - return input + const existsSafe = Effect.fn("SimulationFSUtil.existsSafe")(function* (file: string) { + return yield* fs.exists(file).pipe(Effect.orElseSucceed(() => false)) + }) + + const isDir = Effect.fn("SimulationFSUtil.isDir")(function* (file: string) { + const info = yield* fs.stat(file).pipe(Effect.catch(() => Effect.succeed(undefined))) + return info?.type === "Directory" + }) + + const isFile = Effect.fn("SimulationFSUtil.isFile")(function* (file: string) { + const info = yield* fs.stat(file).pipe(Effect.catch(() => Effect.succeed(undefined))) + return info?.type === "File" + }) + + const realPath = Effect.fn("SimulationFSUtil.realPath")(function* (file: string) { + return yield* fs.realPath(file) + }) + + const stat = Effect.fn("SimulationFSUtil.stat")(function* (file: string) { + return yield* fs.stat(file) + }) + + const readFile = Effect.fn("SimulationFSUtil.readFile")(function* (file: string) { + return yield* fs.readFile(file) + }) + + const readFileString = Effect.fn("SimulationFSUtil.readFileString")(function* (file: string) { + return yield* fs.readFileString(file) + }) + + const readFileStringSafe = Effect.fn("SimulationFSUtil.readFileStringSafe")(function* (file: string) { + return yield* fs + .readFileString(file) + .pipe(Effect.catchReason("PlatformError", "NotFound", () => Effect.succeed(undefined))) + }) + + const readJson = Effect.fn("SimulationFSUtil.readJson")(function* (file: string) { + const text = yield* readFileString(file) + return JSON.parse(text) as unknown + }) + + const writeFile = Effect.fn("SimulationFSUtil.writeFile")(function* ( + file: string, + data: Uint8Array, + options?: Parameters[2], + ) { + return yield* fs.writeFile(file, data, options) + }) + + const writeFileString = Effect.fn("SimulationFSUtil.writeFileString")(function* ( + file: string, + data: string, + options?: Parameters[2], + ) { + return yield* fs.writeFileString(file, data, options) + }) + + const makeDirectory: FileSystem.FileSystem["makeDirectory"] = (file, options) => fs.makeDirectory(file, options) + + const ensureDir = Effect.fn("SimulationFSUtil.ensureDir")(function* (file: string) { + yield* fs.makeDirectory(file, { recursive: true }) + }) + + const writeWithDirs = Effect.fn("SimulationFSUtil.writeWithDirs")(function* ( + file: string, + content: string | Uint8Array, + mode?: number, + ) { + const write = + typeof content === "string" + ? fs.writeFileString(file, content) + : fs.writeFile(file, content) + yield* write.pipe( + Effect.catchReason("PlatformError", "NotFound", () => + fs.makeDirectory(path.dirname(file), { recursive: true }).pipe(Effect.andThen(write)), + ), + ) + if (mode !== undefined) yield* fs.chmod(file, mode) + }) + + const writeJson = Effect.fn("SimulationFSUtil.writeJson")(function* (file: string, data: unknown, mode?: number) { + yield* writeFileString(file, JSON.stringify(data, null, 2)) + if (mode !== undefined) yield* fs.chmod(file, mode) }) const readDirectoryEntries = Effect.fn("SimulationFSUtil.readDirectoryEntries")(function* (dirPath: string) { @@ -48,6 +126,10 @@ const layer = Layer.effect( ) }) + const resolve = Effect.fn("SimulationFSUtil.resolve")(function* (input: string) { + return path.resolve(input) + }) + const glob = Effect.fn("SimulationFSUtil.glob")(function* (pattern: string, options?: Glob.Options) { const cwd = path.resolve(options?.cwd ?? process.cwd()) const entries = yield* fs @@ -80,9 +162,53 @@ const layer = Layer.effect( return result }) - return FSUtil.Service.of({ ...base, readDirectoryEntries, resolve, glob, globUp }) + const up = Effect.fn("SimulationFSUtil.up")(function* (options: { targets: string[]; start: string; stop?: string }) { + const result: string[] = [] + let current = path.resolve(options.start) + while (true) { + for (const target of options.targets) { + const search = path.join(current, target) + if (yield* fs.exists(search)) result.push(search) + } + if (options.stop === current) break + const parent = path.dirname(current) + if (parent === current) break + current = parent + } + return result + }) + + const findUp = Effect.fn("SimulationFSUtil.findUp")(function* (target: string, start: string, stop?: string) { + return yield* up({ targets: [target], start, stop }) + }) + + return FSUtil.Service.of({ + ...fs, + realPath, + stat, + readFile, + readFileString, + writeFile, + writeFileString, + makeDirectory, + isDir, + isFile, + existsSafe, + readFileStringSafe, + readJson, + writeJson, + ensureDir, + writeWithDirs, + readDirectoryEntries, + resolve, + findUp, + up, + globUp, + glob, + globMatch: Glob.match, + }) }), -).pipe(Layer.provide(FSUtil.layer)) +) export const node = makeGlobalNode({ service: FSUtil.Service, layer, deps: [filesystem] }) diff --git a/packages/simulation/src/backend/llm-exchange.ts b/packages/simulation/src/backend/llm-exchange.ts index 759f52866c5..97b7b71b1ff 100644 --- a/packages/simulation/src/backend/llm-exchange.ts +++ b/packages/simulation/src/backend/llm-exchange.ts @@ -80,6 +80,14 @@ export const push = (id: string, chunks: readonly Chunk[]) => yield* Queue.offerAll(exchange.queue, chunks) }) +/** Abruptly ends the provider body without a finish chunk or SSE sentinel. */ +export const disconnect = (id: string) => + Effect.gen(function* () { + const exchange = state.exchanges.get(id) + if (!exchange) return yield* Effect.fail(new ExchangeNotFoundError(id)) + yield* Queue.shutdown(exchange.queue) + }) + /** * Registers a listener for newly opened exchanges and immediately replays * currently-pending ones, so a late-attaching driver observes requests that diff --git a/packages/simulation/src/protocol/index.ts b/packages/simulation/src/protocol/index.ts index 6ff63c9bb3c..b05f24d501a 100644 --- a/packages/simulation/src/protocol/index.ts +++ b/packages/simulation/src/protocol/index.ts @@ -127,6 +127,9 @@ export namespace Backend { }) export interface FinishParams extends Schema.Schema.Type {} + export const DisconnectParams = Schema.Struct({ id: Schema.String }) + export interface DisconnectParams extends Schema.Schema.Type {} + export const OpenedExchange = Schema.Struct({ id: Schema.String, url: Schema.String, body: Schema.Json }) export interface OpenedExchange extends Schema.Schema.Type {} @@ -140,6 +143,7 @@ export namespace Backend { export const decodeChunkParams = Schema.decodeUnknownPromise(ChunkParams) export const decodeFinishParams = Schema.decodeUnknownPromise(FinishParams) + export const decodeDisconnectParams = Schema.decodeUnknownPromise(DisconnectParams) } export * as SimulationProtocol from "./index" From dc99c600b671f77d0e273c1610c29f26461fc240 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Mon, 6 Jul 2026 15:45:46 -0400 Subject: [PATCH 18/46] feat(v2): expose canonical schema contracts (#35595) --- bun.lock | 1 + .../client/test/contract-identity.test.ts | 8 ++++ packages/core/src/session/store.ts | 10 ++--- packages/core/src/tool/hooks.ts | 22 ++++++---- packages/plugin/package.json | 1 + packages/plugin/src/v2/effect/agent.ts | 2 +- packages/plugin/src/v2/effect/aisdk.ts | 6 +-- packages/plugin/src/v2/effect/index.ts | 10 +++++ packages/plugin/src/v2/promise/aisdk.ts | 6 +-- packages/plugin/src/v2/promise/index.ts | 10 +++++ .../plugin/test/contract-identity.test.ts | 41 +++++++++++++++++++ packages/schema/AGENTS.md | 7 ++++ packages/sdk-next/package.json | 1 + packages/sdk-next/src/index.ts | 35 ++++++++++------ .../sdk-next/test/contract-identity.test.ts | 40 ++++++++++++++++++ 15 files changed, 167 insertions(+), 33 deletions(-) create mode 100644 packages/plugin/test/contract-identity.test.ts create mode 100644 packages/sdk-next/test/contract-identity.test.ts diff --git a/bun.lock b/bun.lock index c6862dc4bda..75f5ce7594f 100644 --- a/bun.lock +++ b/bun.lock @@ -775,6 +775,7 @@ "@opencode-ai/client": "workspace:*", "@opencode-ai/core": "workspace:*", "@opencode-ai/plugin": "workspace:*", + "@opencode-ai/schema": "workspace:*", "@opencode-ai/server": "workspace:*", "effect": "catalog:", }, diff --git a/packages/client/test/contract-identity.test.ts b/packages/client/test/contract-identity.test.ts index 90ac5d8cfc9..a2afc9a0023 100644 --- a/packages/client/test/contract-identity.test.ts +++ b/packages/client/test/contract-identity.test.ts @@ -21,6 +21,14 @@ import { Api } from "@opencode-ai/server/api" import { compile, emitPromise } from "@opencode-ai/httpapi-codegen" import { ClientApi, endpointNames, groupNames, promiseOmitEndpoints } from "../src/contract" +const Client = await import("../src/effect") + +test("effect entrypoint exposes canonical Schema contracts", () => { + expect(Client.Agent).toBe(Agent) + expect(Client.Model).toBe(Model) + expect(Client.Session).toBe(Session) +}) + test("Core and Server reuse the authoritative Schema and Protocol values", () => { expect(AgentV2.ID).toBe(Agent.ID) expect(CoreLocation.Ref).toBe(Location.Ref) diff --git a/packages/core/src/session/store.ts b/packages/core/src/session/store.ts index c3ffeedc3ca..6458aa85fb7 100644 --- a/packages/core/src/session/store.ts +++ b/packages/core/src/session/store.ts @@ -7,16 +7,16 @@ import { makeGlobalNode } from "../effect/app-node" import { SessionHistory } from "./history" import { MessageDecodeError } from "./error" import { SessionMessage } from "./message" -import { SessionSchema } from "./schema" +import { Session } from "@opencode-ai/schema/session" import { SessionMessageTable, SessionTable } from "./sql" import { fromRow } from "./info" export interface Interface { - readonly get: (sessionID: SessionSchema.ID) => Effect.Effect - readonly context: (sessionID: SessionSchema.ID) => Effect.Effect + readonly get: (sessionID: Session.ID) => Effect.Effect + readonly context: (sessionID: Session.ID) => Effect.Effect readonly message: ( messageID: SessionMessage.ID, - ) => Effect.Effect<{ readonly sessionID: SessionSchema.ID; readonly message: SessionMessage.Message } | undefined> + ) => Effect.Effect<{ readonly sessionID: Session.ID; readonly message: SessionMessage.Message } | undefined> } export class Service extends Context.Service()("@opencode/v2/SessionStore") {} @@ -44,7 +44,7 @@ const layer = Layer.effect( .pipe(Effect.orDie) return row ? { - sessionID: SessionSchema.ID.make(row.session_id), + sessionID: Session.ID.make(row.session_id), message: yield* decodeMessage({ ...row.data, id: row.id, type: row.type }).pipe(Effect.orDie), } : undefined diff --git a/packages/core/src/tool/hooks.ts b/packages/core/src/tool/hooks.ts index d71be015dc7..4b491c57cdb 100644 --- a/packages/core/src/tool/hooks.ts +++ b/packages/core/src/tool/hooks.ts @@ -1,17 +1,17 @@ export * as ToolHooks from "./hooks" import { makeLocationNode } from "../effect/app-node" -import { AgentV2 } from "../agent" +import { Agent } from "@opencode-ai/schema/agent" +import { Session } from "@opencode-ai/schema/session" import { SessionMessage } from "../session/message" -import { SessionSchema } from "../session/schema" import { State } from "../state" import { Context, Effect, Layer, Scope } from "effect" import type { ToolOutput, ToolResultValue } from "@opencode-ai/llm" export interface BeforeEvent { readonly tool: string - readonly sessionID: SessionSchema.ID - readonly agent: AgentV2.ID + readonly sessionID: Session.ID + readonly agent: Agent.ID readonly assistantMessageID: SessionMessage.ID readonly toolCallID: string input: unknown @@ -19,8 +19,8 @@ export interface BeforeEvent { export interface AfterEvent { readonly tool: string - readonly sessionID: SessionSchema.ID - readonly agent: AgentV2.ID + readonly sessionID: Session.ID + readonly agent: Agent.ID readonly assistantMessageID: SessionMessage.ID readonly toolCallID: string readonly input: unknown @@ -80,8 +80,14 @@ const layer = Layer.effect( return Service.of({ hook: { - before: register(() => beforeHooks, (next) => (beforeHooks = next)), - after: register(() => afterHooks, (next) => (afterHooks = next)), + before: register( + () => beforeHooks, + (next) => (beforeHooks = next), + ), + after: register( + () => afterHooks, + (next) => (afterHooks = next), + ), }, runBefore: (event) => run(beforeHooks, event), runAfter: (event) => run(afterHooks, event), diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 93214e61bfb..21f68ad682c 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -5,6 +5,7 @@ "type": "module", "license": "MIT", "scripts": { + "test": "bun test --timeout 5000", "typecheck": "tsgo --noEmit", "build": "tsc" }, diff --git a/packages/plugin/src/v2/effect/agent.ts b/packages/plugin/src/v2/effect/agent.ts index ce56cbe7779..aadacf99d59 100644 --- a/packages/plugin/src/v2/effect/agent.ts +++ b/packages/plugin/src/v2/effect/agent.ts @@ -1,5 +1,5 @@ -import type { AgentV2Info } from "@opencode-ai/sdk/v2/types" import type { AgentApi } from "@opencode-ai/client/effect/api" +import type { AgentV2Info } from "@opencode-ai/sdk/v2/types" import type { Effect } from "effect" import type { TransformHook } from "./registration.js" diff --git a/packages/plugin/src/v2/effect/aisdk.ts b/packages/plugin/src/v2/effect/aisdk.ts index ddc292e3842..2934edc27d0 100644 --- a/packages/plugin/src/v2/effect/aisdk.ts +++ b/packages/plugin/src/v2/effect/aisdk.ts @@ -1,16 +1,16 @@ import type { LanguageModelV3 } from "@ai-sdk/provider" -import type { ModelV2Info } from "@opencode-ai/sdk/v2/types" +import type { Model } from "@opencode-ai/schema/model" import type { Hooks } from "./registration.js" export type AISDKHooks = Hooks<{ sdk: { - readonly model: ModelV2Info + readonly model: Model.Info readonly package: string readonly options: Record sdk?: any } language: { - readonly model: ModelV2Info + readonly model: Model.Info readonly sdk: any readonly options: Record language?: LanguageModelV3 diff --git a/packages/plugin/src/v2/effect/index.ts b/packages/plugin/src/v2/effect/index.ts index 5468dcd82f9..1332ce27521 100644 --- a/packages/plugin/src/v2/effect/index.ts +++ b/packages/plugin/src/v2/effect/index.ts @@ -12,3 +12,13 @@ export type { SkillDraft, SkillHooks } from "./skill.js" export * as Tool from "./tool.js" export type { ToolDomain, ToolDraft, ToolExecuteBeforeEvent, ToolExecuteAfterEvent } from "./tool.js" export type { SessionHooks } from "./runtime.js" + +export { Agent } from "@opencode-ai/schema/agent" +export { Command } from "@opencode-ai/schema/command" +export { Connection } from "@opencode-ai/schema/connection" +export { Credential } from "@opencode-ai/schema/credential" +export { Integration } from "@opencode-ai/schema/integration" +export { Model } from "@opencode-ai/schema/model" +export { Provider } from "@opencode-ai/schema/provider" +export { Reference } from "@opencode-ai/schema/reference" +export { Skill } from "@opencode-ai/schema/skill" diff --git a/packages/plugin/src/v2/promise/aisdk.ts b/packages/plugin/src/v2/promise/aisdk.ts index ddc292e3842..2934edc27d0 100644 --- a/packages/plugin/src/v2/promise/aisdk.ts +++ b/packages/plugin/src/v2/promise/aisdk.ts @@ -1,16 +1,16 @@ import type { LanguageModelV3 } from "@ai-sdk/provider" -import type { ModelV2Info } from "@opencode-ai/sdk/v2/types" +import type { Model } from "@opencode-ai/schema/model" import type { Hooks } from "./registration.js" export type AISDKHooks = Hooks<{ sdk: { - readonly model: ModelV2Info + readonly model: Model.Info readonly package: string readonly options: Record sdk?: any } language: { - readonly model: ModelV2Info + readonly model: Model.Info readonly sdk: any readonly options: Record language?: LanguageModelV3 diff --git a/packages/plugin/src/v2/promise/index.ts b/packages/plugin/src/v2/promise/index.ts index 594ff7da3c4..4f5d5754eae 100644 --- a/packages/plugin/src/v2/promise/index.ts +++ b/packages/plugin/src/v2/promise/index.ts @@ -11,3 +11,13 @@ export type { IntegrationDraft, IntegrationHooks, IntegrationMethodRegistration export type { ReferenceDraft, ReferenceHooks } from "./reference.js" export type { SessionHooks } from "./runtime.js" export type { SkillDraft, SkillHooks } from "./skill.js" + +export { Agent } from "@opencode-ai/schema/agent" +export { Command } from "@opencode-ai/schema/command" +export { Connection } from "@opencode-ai/schema/connection" +export { Credential } from "@opencode-ai/schema/credential" +export { Integration } from "@opencode-ai/schema/integration" +export { Model } from "@opencode-ai/schema/model" +export { Provider } from "@opencode-ai/schema/provider" +export { Reference } from "@opencode-ai/schema/reference" +export { Skill } from "@opencode-ai/schema/skill" diff --git a/packages/plugin/test/contract-identity.test.ts b/packages/plugin/test/contract-identity.test.ts new file mode 100644 index 00000000000..00efbd2affe --- /dev/null +++ b/packages/plugin/test/contract-identity.test.ts @@ -0,0 +1,41 @@ +import { expect, test } from "bun:test" +import { Agent } from "@opencode-ai/schema/agent" +import { Command } from "@opencode-ai/schema/command" +import { Connection } from "@opencode-ai/schema/connection" +import { Credential } from "@opencode-ai/schema/credential" +import { Integration } from "@opencode-ai/schema/integration" +import { Model } from "@opencode-ai/schema/model" +import { Provider } from "@opencode-ai/schema/provider" +import { Reference } from "@opencode-ai/schema/reference" +import { Skill } from "@opencode-ai/schema/skill" + +const Plugin = await import("../src/v2/effect/index") +const PromisePlugin = await import("../src/v2/promise/index") + +test.each([ + ["effect", Plugin], + ["promise", PromisePlugin], +])("%s entrypoint exposes its canonical Schema contracts", (name, entrypoint) => { + expect(entrypoint.Agent).toBe(Agent) + expect(entrypoint.Command).toBe(Command) + expect(entrypoint.Connection).toBe(Connection) + expect(entrypoint.Credential).toBe(Credential) + expect(entrypoint.Integration).toBe(Integration) + expect(entrypoint.Model).toBe(Model) + expect(entrypoint.Provider).toBe(Provider) + expect(entrypoint.Reference).toBe(Reference) + expect(entrypoint.Skill).toBe(Skill) + expect(Object.keys(entrypoint).sort()).toEqual([ + "Agent", + "Command", + "Connection", + "Credential", + "Integration", + "Model", + "Provider", + "Reference", + "Skill", + ...(name === "effect" ? ["Tool"] : []), + "define", + ]) +}) diff --git a/packages/schema/AGENTS.md b/packages/schema/AGENTS.md index 1d5747d5399..400b4b312b8 100644 --- a/packages/schema/AGENTS.md +++ b/packages/schema/AGENTS.md @@ -34,6 +34,13 @@ - Use flat top-level exports plus the package's existing namespace projection pattern, for example `export * as SessionMessage from "./session-message"`. - Keep standalone ID modules only when they prevent real cycles or heavy dependency edges. Inline one-off IDs into their owning contract module when no cycle exists. +## Public Re-exports + +- Public leaf packages re-export the canonical domain namespaces used by their APIs so consumers install and version one package. Keep the list curated by public API reachability rather than mirroring the Schema root. +- Re-export directly from `@opencode-ai/schema/` and preserve the exact canonical values and types. Do not wrap schemas, duplicate definitions, or route exports through another facade package. +- Internal packages import contracts directly from their canonical Schema owner. Import a Core domain facade only when runtime behavior from that facade is required. +- Resolve name collisions by retaining the domain namespace and qualifying its members, such as `Session.Info` and `Agent.Info`. Do not introduce aliases such as `SessionSchema`, `AgentSchema`, or `ModelSchema`. + ## Naming - Exported schema values and namespace objects use `PascalCase`. diff --git a/packages/sdk-next/package.json b/packages/sdk-next/package.json index 2200251099c..3b092e17455 100644 --- a/packages/sdk-next/package.json +++ b/packages/sdk-next/package.json @@ -15,6 +15,7 @@ "@opencode-ai/client": "workspace:*", "@opencode-ai/core": "workspace:*", "@opencode-ai/plugin": "workspace:*", + "@opencode-ai/schema": "workspace:*", "@opencode-ai/server": "workspace:*", "effect": "catalog:" }, diff --git a/packages/sdk-next/src/index.ts b/packages/sdk-next/src/index.ts index 41010211521..d8ce5f656be 100644 --- a/packages/sdk-next/src/index.ts +++ b/packages/sdk-next/src/index.ts @@ -2,17 +2,26 @@ export * as OpenCode from "./opencode" export * as Tool from "./tool" export { ClientError } from "@opencode-ai/client/effect" -export { - AbsolutePath, - Agent, - Location, - Model, - Prompt, - PromptInput, - Provider, - RelativePath, - Session, - SessionInput, - SessionMessage, -} from "@opencode-ai/client/effect" export type { OpenCodeEvent } from "@opencode-ai/client/effect" +export { Agent } from "@opencode-ai/schema/agent" +export { Command } from "@opencode-ai/schema/command" +export { Credential } from "@opencode-ai/schema/credential" +export { FileSystem } from "@opencode-ai/schema/filesystem" +export { Integration } from "@opencode-ai/schema/integration" +export { Location } from "@opencode-ai/schema/location" +export { Model } from "@opencode-ai/schema/model" +export { Permission } from "@opencode-ai/schema/permission" +export { PermissionSaved } from "@opencode-ai/schema/permission-saved" +export { Project } from "@opencode-ai/schema/project" +export { ProjectCopy } from "@opencode-ai/schema/project-copy" +export { Prompt } from "@opencode-ai/schema/prompt" +export { PromptInput } from "@opencode-ai/schema/prompt-input" +export { Provider } from "@opencode-ai/schema/provider" +export { Pty } from "@opencode-ai/schema/pty" +export { Question } from "@opencode-ai/schema/question" +export { Reference } from "@opencode-ai/schema/reference" +export { AbsolutePath, RelativePath } from "@opencode-ai/schema/schema" +export { Session } from "@opencode-ai/schema/session" +export { SessionInput } from "@opencode-ai/schema/session-input" +export { SessionMessage } from "@opencode-ai/schema/session-message" +export { Skill } from "@opencode-ai/schema/skill" diff --git a/packages/sdk-next/test/contract-identity.test.ts b/packages/sdk-next/test/contract-identity.test.ts new file mode 100644 index 00000000000..830fe5f43b2 --- /dev/null +++ b/packages/sdk-next/test/contract-identity.test.ts @@ -0,0 +1,40 @@ +import { expect, test } from "bun:test" +import { Agent } from "@opencode-ai/schema/agent" +import { Model } from "@opencode-ai/schema/model" +import { Session } from "@opencode-ai/schema/session" + +const SDK = await import("../src/index") + +test("re-exports canonical contracts directly from Schema", () => { + expect(SDK.Agent).toBe(Agent) + expect(SDK.Model).toBe(Model) + expect(SDK.Session).toBe(Session) + expect(Object.keys(SDK).sort()).toEqual([ + "AbsolutePath", + "Agent", + "ClientError", + "Command", + "Credential", + "FileSystem", + "Integration", + "Location", + "Model", + "OpenCode", + "Permission", + "PermissionSaved", + "Project", + "ProjectCopy", + "Prompt", + "PromptInput", + "Provider", + "Pty", + "Question", + "Reference", + "RelativePath", + "Session", + "SessionInput", + "SessionMessage", + "Skill", + "Tool", + ]) +}) From 0e1c0414c2f375161bbd948d76367917cb4d5f74 Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Mon, 6 Jul 2026 15:55:32 -0400 Subject: [PATCH 19/46] fix(codemode): align mutable JavaScript semantics (#35598) --- packages/codemode/src/interpreter/runtime.ts | 115 ++++++++++++------- packages/codemode/src/stdlib/object.ts | 10 +- packages/codemode/test/parity.test.ts | 40 +++++++ packages/codemode/test/stdlib.test.ts | 20 ++++ 4 files changed, 138 insertions(+), 47 deletions(-) diff --git a/packages/codemode/src/interpreter/runtime.ts b/packages/codemode/src/interpreter/runtime.ts index 093f5777651..403edd34f51 100644 --- a/packages/codemode/src/interpreter/runtime.ts +++ b/packages/codemode/src/interpreter/runtime.ts @@ -1804,25 +1804,31 @@ class Interpreter { if (operator === "??=" || operator === "||=" || operator === "&&=") { return yield* self.evaluateLogicalAssignment(node, left, operator) } - const rightValue = yield* self.evaluateExpression(getNode(node, "right")) if (left.type === "Identifier") { const name = getString(left, "name") - if (operator === "=") return self.setIdentifierValue(name, rightValue, left) - const next = boundedData( - self.applyCompoundAssignment(operator, self.getIdentifierValue(name, left), rightValue, node), - "Assignment result", - ) - return self.setIdentifierValue(name, next, left) - } - if (left.type === "MemberExpression") { - if (operator === "=") return yield* self.writeMember(left, rightValue) - return yield* self.modifyMember(left, (current) => { + if (operator !== "=") { + const current = self.getIdentifierValue(name, left) + const rightValue = yield* self.evaluateExpression(getNode(node, "right")) const next = boundedData( self.applyCompoundAssignment(operator, current, rightValue, node), "Assignment result", ) - return Effect.succeed({ write: true, next, result: next }) - }) + return self.setIdentifierValue(name, next, left) + } + const rightValue = yield* self.evaluateExpression(getNode(node, "right")) + if (operator === "=") return self.setIdentifierValue(name, rightValue, left) + } + if (left.type === "MemberExpression") { + return yield* self.modifyMember(left, (current) => + Effect.map(self.evaluateExpression(getNode(node, "right")), (rightValue) => { + if (operator === "=") return { write: true, next: rightValue, result: rightValue } + const next = boundedData( + self.applyCompoundAssignment(operator, current, rightValue, node), + "Assignment result", + ) + return { write: true, next, result: next } + }), + ) } throw new InterpreterRuntimeError("Assignment target must be an Identifier or MemberExpression.", left) }) @@ -1923,6 +1929,9 @@ class Interpreter { if (callable.namespace === "Object" && args[0] instanceof ToolReference) { return self.invokeObjectMethodOnTools(callable.name, args[0] as ToolReference, node) } + if (callable.namespace === "Object" && callable.name === "assign") { + return invokeGlobalMethod(callable, args, node) + } return boundedData(invokeGlobalMethod(callable, args, node), `${callable.namespace}.${callable.name} result`) } if (callable instanceof CoercionFunction) { @@ -2575,8 +2584,12 @@ class Interpreter { case "flat": return Effect.succeed(target.flat(optNumber(args[0], "depth") ?? 1)) case "reverse": - return Effect.succeed([...target].reverse()) + return Effect.succeed(target.reverse()) case "sort": + return Effect.map(this.sortArray(target, args[0], node), (sorted) => { + target.splice(0, target.length, ...sorted) + return target + }) case "toSorted": return this.sortArray(target, args[0], node) case "toReversed": @@ -2659,19 +2672,24 @@ class Interpreter { ? Effect.succeed(invokeUriFunction(callback, callbackArgs, node)) : self.invokeFunction(callback, callbackArgs) return Effect.gen(function* () { - // Iterate a snapshot taken at call time so a callback that mutates the array can't - // self-extend the loop - matching JS, where elements appended during iteration are not visited. - const items = target.slice() + // Capture the initial length, but read the receiver live so callbacks observe mutations + // without visiting elements appended after iteration begins. + const length = target.length switch (name) { case "map": { const values: Array = [] - for (const [index, item] of items.entries()) values.push(yield* apply([item, index, items])) + values.length = length + for (let index = 0; index < length; index += 1) { + if (!(index in target)) continue + values[index] = yield* apply([target[index], index, target]) + } return values } case "flatMap": { const values: Array = [] - for (const [index, item] of items.entries()) { - const mapped = yield* apply([item, index, items]) + for (let index = 0; index < length; index += 1) { + if (!(index in target)) continue + const mapped = yield* apply([target[index], index, target]) if (Array.isArray(mapped)) values.push(...mapped) else values.push(mapped) } @@ -2679,33 +2697,40 @@ class Interpreter { } case "filter": { const values: Array = [] - for (const [index, item] of items.entries()) { - if (yield* apply([item, index, items])) values.push(item) + for (let index = 0; index < length; index += 1) { + if (!(index in target)) continue + const item = target[index] + if (yield* apply([item, index, target])) values.push(item) } return values } case "find": - for (const [index, item] of items.entries()) { - if (yield* apply([item, index, items])) return item + for (let index = 0; index < length; index += 1) { + const item = target[index] + if (yield* apply([item, index, target])) return item } return undefined case "findIndex": - for (const [index, item] of items.entries()) { - if (yield* apply([item, index, items])) return index + for (let index = 0; index < length; index += 1) { + if (yield* apply([target[index], index, target])) return index } return -1 case "some": - for (const [index, item] of items.entries()) { - if (yield* apply([item, index, items])) return true + for (let index = 0; index < length; index += 1) { + if (!(index in target)) continue + if (yield* apply([target[index], index, target])) return true } return false case "every": - for (const [index, item] of items.entries()) { - if (!(yield* apply([item, index, items]))) return false + for (let index = 0; index < length; index += 1) { + if (!(index in target)) continue + if (!(yield* apply([target[index], index, target]))) return false } return true case "forEach": - for (const [index, item] of items.entries()) yield* apply([item, index, items]) + for (let index = 0; index < length; index += 1) { + if (index in target) yield* apply([target[index], index, target]) + } return undefined case "reduce": { let accumulator: unknown @@ -2714,13 +2739,14 @@ class Interpreter { accumulator = args[1] start = 0 } else { - if (items.length === 0) + if (length === 0) throw new InterpreterRuntimeError("Array.reduce of an empty array with no initial value.", node) - accumulator = items[0] + accumulator = target[0] start = 1 } - for (let index = start; index < items.length; index += 1) { - accumulator = yield* apply([accumulator, items[index], index, items]) + for (let index = start; index < length; index += 1) { + if (!(index in target)) continue + accumulator = yield* apply([accumulator, target[index], index, target]) } return accumulator } @@ -2729,26 +2755,27 @@ class Interpreter { let start: number if (args.length >= 2) { accumulator = args[1] - start = items.length - 1 + start = length - 1 } else { - if (items.length === 0) + if (length === 0) throw new InterpreterRuntimeError("Array.reduceRight of an empty array with no initial value.", node) - accumulator = items[items.length - 1] - start = items.length - 2 + accumulator = target[length - 1] + start = length - 2 } for (let index = start; index >= 0; index -= 1) { - accumulator = yield* apply([accumulator, items[index], index, items]) + if (!(index in target)) continue + accumulator = yield* apply([accumulator, target[index], index, target]) } return accumulator } case "findLast": - for (let index = items.length - 1; index >= 0; index -= 1) { - if (yield* apply([items[index], index, items])) return items[index] + for (let index = length - 1; index >= 0; index -= 1) { + if (yield* apply([target[index], index, target])) return target[index] } return undefined case "findLastIndex": - for (let index = items.length - 1; index >= 0; index -= 1) { - if (yield* apply([items[index], index, items])) return index + for (let index = length - 1; index >= 0; index -= 1) { + if (yield* apply([target[index], index, target])) return index } return -1 } diff --git a/packages/codemode/src/stdlib/object.ts b/packages/codemode/src/stdlib/object.ts index 2beda0bf5ca..4d454cbda25 100644 --- a/packages/codemode/src/stdlib/object.ts +++ b/packages/codemode/src/stdlib/object.ts @@ -36,10 +36,14 @@ export const invokeObjectMethod = (name: string, args: Array, node: Ast case "hasOwn": return Object.hasOwn(requireObject(), String(args[1])) case "assign": { - const out: Record = Object.create(null) - for (const source of args) { + const target = args[0] + if (target === null || typeof target !== "object" || Array.isArray(target) || isSandboxValue(target)) { + throw new InterpreterRuntimeError("Object.assign expects a data object target.", node) + } + const out = target as Record + for (const source of args.slice(1)) { if (source === null || source === undefined) continue - const value = boundedData(source, "Object.assign input") + const value = source if (isSandboxValue(value)) continue if (value === null || typeof value !== "object" || Array.isArray(value)) { throw new InterpreterRuntimeError("Object.assign expects data objects.", node) diff --git a/packages/codemode/test/parity.test.ts b/packages/codemode/test/parity.test.ts index dfa85831837..39f2ba02af7 100644 --- a/packages/codemode/test/parity.test.ts +++ b/packages/codemode/test/parity.test.ts @@ -264,6 +264,46 @@ describe("Error values and instanceof", () => { }) describe("array methods: splice, fill, copyWithin, keys/values/entries", () => { + test("sort and reverse mutate and return the receiver", async () => { + expect( + await value(` + const sorted = [3, 1, 2] + const sortResult = sorted.sort((a, b) => a - b) + const reversed = [1, 2, 3] + const reverseResult = reversed.reverse() + return { sorted, sameSort: sorted === sortResult, reversed, sameReverse: reversed === reverseResult } + `), + ).toEqual({ sorted: [1, 2, 3], sameSort: true, reversed: [3, 2, 1], sameReverse: true }) + }) + + test("array callbacks receive the receiver and observe later mutations", async () => { + expect( + await value(` + const values = [1, 2, 3] + const seen = values.map((value, index, receiver) => { + if (index === 0) values[1] = 9 + return [value, receiver === values] + }) + return seen + `), + ).toEqual([ + [1, true], + [9, true], + [3, true], + ]) + expect( + await value(` + const values = [1, 2, 3] + const seen = [] + values.forEach((value, index) => { + seen.push(value) + if (index === 0) values.pop() + }) + return seen + `), + ).toEqual([1, 2]) + }) + test("splice removes in place and returns the removed elements", async () => { expect(await value(`const a = [1,2,3,4]; const removed = a.splice(1, 2); return { removed, a }`)).toEqual({ removed: [2, 3], diff --git a/packages/codemode/test/stdlib.test.ts b/packages/codemode/test/stdlib.test.ts index f7831a06033..489de451a79 100644 --- a/packages/codemode/test/stdlib.test.ts +++ b/packages/codemode/test/stdlib.test.ts @@ -586,6 +586,26 @@ describe("Set", () => { }) describe("stdlib integration", () => { + test("Object.assign mutates and returns its target", async () => { + expect( + await value(` + const target = { a: 1 } + const result = Object.assign(target, { b: 2 }) + return { target, result, same: target === result } + `), + ).toEqual({ target: { a: 1, b: 2 }, result: { a: 1, b: 2 }, same: true }) + expect(await value(`try { Object.assign(null, { a: 1 }); return false } catch { return true }`)).toBe(true) + }) + + test("assignment resolves and reads its left side before evaluating the right side", async () => { + expect(await value(`let x = 1; x += (x = 5); return x`)).toBe(6) + expect(await value(`let i = 0; const values = [9]; values[i++] = i; return [values, i]`)).toEqual([[1], 1]) + expect(await value(`let i = 0; const values = [10, 20]; values[i++] += i; return [values, i]`)).toEqual([ + [11, 20], + 1, + ]) + }) + test("typeof reports constructors as functions and never throws", async () => { expect(await value(`return typeof Map`)).toBe("function") expect(await value(`return typeof ((x) => x)`)).toBe("function") From d603eed5a10ebbecd93c39713f493bf729e0be6b Mon Sep 17 00:00:00 2001 From: Kit Langton Date: Mon, 6 Jul 2026 15:56:52 -0400 Subject: [PATCH 20/46] feat(codemode): support destructuring assignment (#35600) --- packages/codemode/src/interpreter/runtime.ts | 83 ++++++++++++++++++++ packages/codemode/test/parity.test.ts | 35 +++++++++ 2 files changed, 118 insertions(+) diff --git a/packages/codemode/src/interpreter/runtime.ts b/packages/codemode/src/interpreter/runtime.ts index 403edd34f51..f34e3949e12 100644 --- a/packages/codemode/src/interpreter/runtime.ts +++ b/packages/codemode/src/interpreter/runtime.ts @@ -1403,6 +1403,84 @@ class Interpreter { }) } + private assignPattern(pattern: AstNode, value: unknown, node: AstNode): Effect.Effect { + const self = this + return Effect.gen(function* () { + if (pattern.type === "Identifier") { + self.setIdentifierValue(getString(pattern, "name"), value, pattern) + return + } + + if (pattern.type === "MemberExpression") { + yield* self.writeMember(pattern, value) + return + } + + if (pattern.type === "AssignmentPattern") { + const resolved = value === undefined ? yield* self.evaluateExpression(getNode(pattern, "right")) : value + yield* self.assignPattern(getNode(pattern, "left"), resolved, node) + return + } + + if (pattern.type === "ObjectPattern") { + if (value === null || typeof value !== "object" || Array.isArray(value) || isRuntimeReference(value)) { + throw new InterpreterRuntimeError( + "Object destructuring requires a data object value.", + pattern, + "InvalidDataValue", + ) + } + + const source = value as SafeObject + const consumed = new Set() + for (const propertyValue of getArray(pattern, "properties")) { + const property = asNode(propertyValue, "properties") + if (property.type === "RestElement") { + const rest: SafeObject = Object.create(null) as SafeObject + for (const [key, item] of Object.entries(source)) { + if (!consumed.has(key) && !isBlockedMember(key)) rest[key] = item + } + yield* self.assignPattern(getNode(property, "argument"), rest, property) + continue + } + if ( + property.type !== "Property" || + getBoolean(property, "computed") || + getString(property, "kind") !== "init" + ) { + throw new InterpreterRuntimeError("Only named object destructuring properties are supported.", property) + } + const keyNode = getNode(property, "key") + const key = keyNode.type === "Identifier" ? getString(keyNode, "name") : String(keyNode.value) + if (isBlockedMember(key)) { + throw new InterpreterRuntimeError(`Property '${key}' is not available in CodeMode.`, keyNode) + } + consumed.add(key) + yield* self.assignPattern(getNode(property, "value"), source[key], property) + } + return + } + + if (pattern.type === "ArrayPattern") { + if (!Array.isArray(value)) { + throw new InterpreterRuntimeError("Array destructuring requires an array value.", pattern) + } + for (const [index, item] of getArray(pattern, "elements").entries()) { + if (item === null) continue + const element = asNode(item, `elements[${index}]`) + if (element.type === "RestElement") { + yield* self.assignPattern(getNode(element, "argument"), value.slice(index), element) + break + } + yield* self.assignPattern(element, value[index], pattern) + } + return + } + + throw new InterpreterRuntimeError(`Unsupported assignment pattern '${pattern.type}'.`, node) + }) + } + private evaluateExpression(node: AstNode): Effect.Effect { switch (node.type) { case "Literal": { @@ -1804,6 +1882,11 @@ class Interpreter { if (operator === "??=" || operator === "||=" || operator === "&&=") { return yield* self.evaluateLogicalAssignment(node, left, operator) } + if (operator === "=" && (left.type === "ObjectPattern" || left.type === "ArrayPattern")) { + const rightValue = yield* self.evaluateExpression(getNode(node, "right")) + yield* self.assignPattern(left, rightValue, node) + return rightValue + } if (left.type === "Identifier") { const name = getString(left, "name") if (operator !== "=") { diff --git a/packages/codemode/test/parity.test.ts b/packages/codemode/test/parity.test.ts index 39f2ba02af7..1831a7222df 100644 --- a/packages/codemode/test/parity.test.ts +++ b/packages/codemode/test/parity.test.ts @@ -463,3 +463,38 @@ describe("H5: builtin coercion functions work as array callbacks", () => { expect(err.message).toContain("callback") }) }) + +describe("destructuring assignment", () => { + test("assigns object and array patterns to existing bindings", async () => { + expect( + await value(` + let a = 0 + let b = 0 + ;({ a } = { a: 2 }) + ;[a, b] = [3, 4] + return [a, b] + `), + ).toEqual([3, 4]) + }) + + test("supports defaults, nesting, rest, and member targets", async () => { + expect( + await value(` + let first = 0 + let fallback = 0 + let rest = {} + const target = {} + ;[first, fallback = 2, ...target.tail] = [1] + ;({ nested: { value: target.value }, kept: target.kept = 3, ...rest } = { + nested: { value: 4 }, + extra: 5, + }) + return { first, fallback, target, rest } + `), + ).toEqual({ first: 1, fallback: 2, target: { tail: [], value: 4, kept: 3 }, rest: { extra: 5 } }) + }) + + test("returns the assigned value", async () => { + expect(await value(`let a = 0; const result = ([a] = [7]); return [a, result]`)).toEqual([7, [7]]) + }) +}) From e57d9ca39039764e569a6776e13ef75f0c4ff237 Mon Sep 17 00:00:00 2001 From: Shoubhit Dash Date: Tue, 7 Jul 2026 01:48:56 +0530 Subject: [PATCH 21/46] feat(core): flatten provider config and load native packages (#35563) Co-authored-by: Dax Raad --- packages/cli/src/mini/catalog.shared.ts | 7 +- .../client/src/promise/generated/types.ts | 96 +--- packages/core/src/aisdk.ts | 474 +++++++++++++++++- packages/core/src/catalog.ts | 30 +- packages/core/src/config.ts | 3 +- packages/core/src/config/agent.ts | 4 +- packages/core/src/config/command.ts | 4 +- packages/core/src/config/model.ts | 38 ++ packages/core/src/config/plugin/agent.ts | 28 +- packages/core/src/config/plugin/command.ts | 14 +- packages/core/src/config/plugin/provider.ts | 47 +- packages/core/src/config/provider.ts | 42 +- packages/core/src/model.ts | 14 +- packages/core/src/plugin/models-dev.ts | 67 ++- .../src/plugin/provider/amazon-bedrock.ts | 20 +- .../core/src/plugin/provider/anthropic.ts | 11 +- packages/core/src/plugin/provider/azure.ts | 31 +- packages/core/src/plugin/provider/cerebras.ts | 7 +- .../plugin/provider/cloudflare-workers-ai.ts | 19 +- .../src/plugin/provider/github-copilot.ts | 7 +- packages/core/src/plugin/provider/gitlab.ts | 22 +- .../core/src/plugin/provider/google-vertex.ts | 42 +- packages/core/src/plugin/provider/kilo.ts | 10 +- .../core/src/plugin/provider/llmgateway.ts | 16 +- packages/core/src/plugin/provider/nvidia.ts | 16 +- packages/core/src/plugin/provider/openai.ts | 8 +- packages/core/src/plugin/provider/opencode.ts | 44 +- .../core/src/plugin/provider/openrouter.ts | 8 +- .../core/src/plugin/provider/sap-ai-core.ts | 2 +- packages/core/src/plugin/provider/vercel.ts | 8 +- packages/core/src/plugin/provider/xai.ts | 2 +- packages/core/src/plugin/provider/zenmux.ts | 14 +- packages/core/src/plugin/variant.ts | 26 +- packages/core/src/provider.ts | 127 ++++- packages/core/src/session/runner/llm.ts | 5 +- packages/core/src/session/runner/model.ts | 212 +++++--- .../core/src/session/runner/to-llm-message.ts | 10 +- packages/core/src/v1/config/migrate.ts | 81 +-- .../core/src/v1/config/provider-options.ts | 228 +-------- packages/core/test/aisdk.test.ts | 85 ++++ packages/core/test/catalog.test.ts | 88 ++-- packages/core/test/config/agent.test.ts | 4 +- packages/core/test/config/command.test.ts | 3 +- packages/core/test/config/config.test.ts | 75 +-- packages/core/test/config/model.test.ts | 28 ++ .../core/test/config/provider-options.test.ts | 218 +------- packages/core/test/config/provider.test.ts | 49 +- packages/core/test/location-layer.test.ts | 12 +- .../plugin/fixtures/variant-source-plugin.ts | 10 +- packages/core/test/plugin/host.ts | 29 +- packages/core/test/plugin/models-dev.test.ts | 37 +- .../core/test/plugin/provider-alibaba.test.ts | 16 +- .../plugin/provider-amazon-bedrock.test.ts | 112 ++--- .../test/plugin/provider-anthropic.test.ts | 22 +- .../provider-azure-cognitive-services.test.ts | 48 +- .../core/test/plugin/provider-azure.test.ts | 65 +-- .../test/plugin/provider-cerebras.test.ts | 29 +- .../provider-cloudflare-ai-gateway.test.ts | 37 +- .../provider-cloudflare-workers-ai.test.ts | 73 ++- .../core/test/plugin/provider-cohere.test.ts | 12 +- .../test/plugin/provider-deepinfra.test.ts | 24 +- .../core/test/plugin/provider-dynamic.test.ts | 26 +- .../core/test/plugin/provider-gateway.test.ts | 16 +- .../plugin/provider-github-copilot.test.ts | 39 +- .../core/test/plugin/provider-gitlab.test.ts | 41 +- .../provider-google-vertex-anthropic.test.ts | 51 +- .../plugin/provider-google-vertex.test.ts | 135 +++-- .../core/test/plugin/provider-google.test.ts | 31 +- .../core/test/plugin/provider-groq.test.ts | 23 +- .../core/test/plugin/provider-kilo.test.ts | 47 +- .../test/plugin/provider-llmgateway.test.ts | 22 +- .../core/test/plugin/provider-mistral.test.ts | 19 +- .../core/test/plugin/provider-nvidia.test.ts | 37 +- .../plugin/provider-openai-compatible.test.ts | 15 +- .../core/test/plugin/provider-openai.test.ts | 28 +- .../test/plugin/provider-opencode.test.ts | 74 +-- .../test/plugin/provider-openrouter.test.ts | 16 +- .../test/plugin/provider-perplexity.test.ts | 15 +- .../test/plugin/provider-sap-ai-core.test.ts | 3 +- .../plugin/provider-snowflake-cortex.test.ts | 18 +- .../test/plugin/provider-togetherai.test.ts | 23 +- .../core/test/plugin/provider-venice.test.ts | 15 +- .../core/test/plugin/provider-vercel.test.ts | 19 +- .../core/test/plugin/provider-xai.test.ts | 17 +- .../core/test/plugin/provider-zenmux.test.ts | 37 +- packages/core/test/plugin/variant.test.ts | 16 +- .../core/test/session-instructions.test.ts | 5 +- .../core/test/session-runner-message.test.ts | 36 +- .../core/test/session-runner-model.test.ts | 336 +++++++++---- packages/core/test/shared-schema.test.ts | 4 - packages/llm/package.json | 3 + packages/llm/src/index.ts | 2 + packages/llm/src/provider-package.ts | 16 + packages/llm/src/providers/amazon-bedrock.ts | 27 +- packages/llm/src/providers/anthropic.ts | 16 +- .../llm/src/providers/openai-compatible.ts | 17 + packages/llm/src/providers/openai.ts | 38 +- packages/llm/src/providers/openai/chat.ts | 2 + .../llm/src/providers/openai/responses.ts | 2 + packages/llm/test/exports.test.ts | 1 - packages/llm/test/provider-package.test.ts | 52 ++ .../test/cli/run/catalog.shared.test.ts | 19 +- packages/schema/src/model.ts | 43 +- packages/schema/src/provider.ts | 42 +- packages/schema/test/contract-hygiene.test.ts | 16 +- packages/sdk/js/src/v2/gen/types.gen.ts | 192 +++---- packages/tui/src/context/local.tsx | 11 +- 107 files changed, 2596 insertions(+), 1987 deletions(-) create mode 100644 packages/core/src/config/model.ts create mode 100644 packages/core/test/aisdk.test.ts create mode 100644 packages/core/test/config/model.test.ts create mode 100644 packages/llm/src/provider-package.ts create mode 100644 packages/llm/src/providers/openai/chat.ts create mode 100644 packages/llm/src/providers/openai/responses.ts create mode 100644 packages/llm/test/provider-package.test.ts diff --git a/packages/cli/src/mini/catalog.shared.ts b/packages/cli/src/mini/catalog.shared.ts index d810c47077e..535147e6519 100644 --- a/packages/cli/src/mini/catalog.shared.ts +++ b/packages/cli/src/mini/catalog.shared.ts @@ -84,7 +84,7 @@ export function runProviders(providers: CurrentProvider[], models: CurrentModel[ cost: defaultCost(model), limit: model.limit, status: model.status, - variants: Object.fromEntries(model.variants.map((variant) => [variant.id, {}])), + variants: Object.fromEntries((model.variants ?? []).map((variant) => [variant.id, {}])), } grouped.set(provider.id, provider) } @@ -141,10 +141,7 @@ export async function loadRunCommands(sdk: OpenCodeClient, directory: string): P sdk.command.list(location(directory)), sdk.skill.list(location(directory)), ]) - return [ - ...commands.data.map(runCommand), - ...skills.data.filter((skill) => skill.slash !== false).map(runSkill), - ] + return [...commands.data.map(runCommand), ...skills.data.filter((skill) => skill.slash !== false).map(runSkill)] } export async function loadRunReferences(sdk: OpenCodeClient, directory: string): Promise { diff --git a/packages/client/src/promise/generated/types.ts b/packages/client/src/promise/generated/types.ts index afe02c11c0b..5b3d6c165fe 100644 --- a/packages/client/src/promise/generated/types.ts +++ b/packages/client/src/promise/generated/types.ts @@ -2009,39 +2009,24 @@ export type ModelListOutput = { } readonly data: ReadonlyArray<{ readonly id: string + readonly modelID: string readonly providerID: string readonly family?: string readonly name: string - readonly api: - | { - readonly id: string - readonly type: "aisdk" - readonly package: string - readonly url?: string - readonly settings?: { readonly [x: string]: JsonValue } - } - | { - readonly id: string - readonly type: "native" - readonly url?: string - readonly settings: { readonly [x: string]: JsonValue } - } + readonly package?: string + readonly settings?: { readonly [x: string]: JsonValue } + readonly headers?: { readonly [x: string]: string } + readonly body?: { readonly [x: string]: JsonValue } readonly capabilities: { readonly tools: boolean readonly input: ReadonlyArray readonly output: ReadonlyArray } - readonly request: { - readonly settings: { readonly [x: string]: JsonValue } - readonly headers: { readonly [x: string]: string } - readonly body: { readonly [x: string]: JsonValue } - readonly variant?: string - } readonly variants: ReadonlyArray<{ readonly id: string - readonly settings: { readonly [x: string]: JsonValue } - readonly headers: { readonly [x: string]: string } - readonly body: { readonly [x: string]: JsonValue } + readonly settings?: { readonly [x: string]: JsonValue } + readonly headers?: { readonly [x: string]: string } + readonly body?: { readonly [x: string]: JsonValue } }> readonly time: { readonly released: number } readonly cost: ReadonlyArray<{ @@ -2070,39 +2055,24 @@ export type ModelDefaultOutput = { } readonly data: { readonly id: string + readonly modelID: string readonly providerID: string readonly family?: string readonly name: string - readonly api: - | { - readonly id: string - readonly type: "aisdk" - readonly package: string - readonly url?: string - readonly settings?: { readonly [x: string]: JsonValue } - } - | { - readonly id: string - readonly type: "native" - readonly url?: string - readonly settings: { readonly [x: string]: JsonValue } - } + readonly package?: string + readonly settings?: { readonly [x: string]: JsonValue } + readonly headers?: { readonly [x: string]: string } + readonly body?: { readonly [x: string]: JsonValue } readonly capabilities: { readonly tools: boolean readonly input: ReadonlyArray readonly output: ReadonlyArray } - readonly request: { - readonly settings: { readonly [x: string]: JsonValue } - readonly headers: { readonly [x: string]: string } - readonly body: { readonly [x: string]: JsonValue } - readonly variant?: string - } readonly variants: ReadonlyArray<{ readonly id: string - readonly settings: { readonly [x: string]: JsonValue } - readonly headers: { readonly [x: string]: string } - readonly body: { readonly [x: string]: JsonValue } + readonly settings?: { readonly [x: string]: JsonValue } + readonly headers?: { readonly [x: string]: string } + readonly body?: { readonly [x: string]: JsonValue } }> readonly time: { readonly released: number } readonly cost: ReadonlyArray<{ @@ -2150,19 +2120,10 @@ export type ProviderListOutput = { readonly integrationID?: string readonly name: string readonly disabled?: boolean - readonly api: - | { - readonly type: "aisdk" - readonly package: string - readonly url?: string - readonly settings?: { readonly [x: string]: JsonValue } - } - | { readonly type: "native"; readonly url?: string; readonly settings: { readonly [x: string]: JsonValue } } - readonly request: { - readonly settings: { readonly [x: string]: JsonValue } - readonly headers: { readonly [x: string]: string } - readonly body: { readonly [x: string]: JsonValue } - } + readonly package: string + readonly settings?: { readonly [x: string]: JsonValue } + readonly headers?: { readonly [x: string]: string } + readonly body?: { readonly [x: string]: JsonValue } }> } @@ -2184,19 +2145,10 @@ export type ProviderGetOutput = { readonly integrationID?: string readonly name: string readonly disabled?: boolean - readonly api: - | { - readonly type: "aisdk" - readonly package: string - readonly url?: string - readonly settings?: { readonly [x: string]: JsonValue } - } - | { readonly type: "native"; readonly url?: string; readonly settings: { readonly [x: string]: JsonValue } } - readonly request: { - readonly settings: { readonly [x: string]: JsonValue } - readonly headers: { readonly [x: string]: string } - readonly body: { readonly [x: string]: JsonValue } - } + readonly package: string + readonly settings?: { readonly [x: string]: JsonValue } + readonly headers?: { readonly [x: string]: string } + readonly body?: { readonly [x: string]: JsonValue } } } diff --git a/packages/core/src/aisdk.ts b/packages/core/src/aisdk.ts index 9215e2473b1..f7474b244a1 100644 --- a/packages/core/src/aisdk.ts +++ b/packages/core/src/aisdk.ts @@ -1,13 +1,43 @@ export * as AISDK from "./aisdk" import { makeLocationNode } from "./effect/app-node" -import type { LanguageModelV3 } from "@ai-sdk/provider" -import { Cause, Context, Effect, Layer, Schema, Scope } from "effect" +import type { + JSONSchema7, + JSONValue, + LanguageModelV3, + LanguageModelV3CallOptions, + LanguageModelV3FunctionTool, + LanguageModelV3Message, + LanguageModelV3Prompt, + LanguageModelV3StreamPart, + LanguageModelV3ToolChoice, + SharedV3ProviderOptions, +} from "@ai-sdk/provider" +import { + FinishReason, + InvalidProviderOutputReason, + LLMEvent, + LLMError, + Model, + ProviderID, + ProviderMetadata, + ToolResultValue, + UnknownProviderReason, + type ContentPart, + type LLMRequest, + type ToolDefinition, + type UsageInput, +} from "@opencode-ai/llm" +import { Auth, Endpoint, type AnyRoute } from "@opencode-ai/llm/route" +import { Cause, Context, Effect, Layer, Option, Schema, Scope, Stream } from "effect" import { ModelV2 } from "./model" import { ProviderV2 } from "./provider" import { State } from "./state" type SDK = any +type UserContent = Extract["content"] +type AssistantContent = Extract["content"] +type ToolResultContent = Extract export interface SDKEvent { readonly model: ModelV2.Info @@ -74,10 +104,10 @@ function wrapSSE(res: Response, ms: number, ctl: AbortController) { function prepareOptions(model: ModelV2.Info, pkg: string) { const options: Record = { name: model.providerID, - ...(model.api.type === "aisdk" ? (model.api.settings ?? {}) : {}), - ...model.request.body, + ...(model.settings ?? {}), + headers: model.headers, + body: model.body, } - if (model.api.type === "aisdk" && model.api.url) options.baseURL = model.api.url const customFetch = options.fetch const chunkTimeout = options.chunkTimeout @@ -110,6 +140,13 @@ function prepareOptions(model: ModelV2.Info, pkg: string) { } } + if (typeof opts.body === "string" && model.body !== undefined) { + const decoded = Option.getOrUndefined(Schema.decodeUnknownOption(Schema.UnknownFromJsonString)(opts.body)) + if (Schema.is(Schema.Record(Schema.String, Schema.Json))(decoded)) { + opts.body = JSON.stringify(ProviderV2.mergeOverlay(decoded, model.body)) + } + } + const res = await (typeof customFetch === "function" ? customFetch : fetch)(input, { ...opts, timeout: false, @@ -142,17 +179,29 @@ export interface Interface { readonly runSDK: (event: SDKEvent) => Effect.Effect readonly runLanguage: (event: LanguageEvent) => Effect.Effect readonly language: (model: ModelV2.Info) => Effect.Effect + readonly model: (model: ModelV2.Info) => Effect.Effect } export class Service extends Context.Service()("@opencode/v2/AISDK") {} -const layer = Layer.effect( +export const locationLayer = Layer.effect( Service, Effect.gen(function* () { let sdkHooks: ((event: SDKEvent) => Effect.Effect | void)[] = [] let languageHooks: ((event: LanguageEvent) => Effect.Effect | void)[] = [] const languages = new Map() const sdks = new Map() + const functionIDs = new WeakMap() + let nextFunctionID = 0 + const cacheKey = (input: unknown) => + JSON.stringify(input, (_key, value: unknown) => { + if (typeof value !== "function") return value + const existing = functionIDs.get(value) + if (existing !== undefined) return `function:${existing}` + const id = nextFunctionID++ + functionIDs.set(value, id) + return `function:${id}` + }) ?? "" const register = ( hooks: () => ((event: Event) => Effect.Effect | void)[], @@ -196,24 +245,36 @@ const layer = Layer.effect( runSDK: (event) => run(sdkHooks, event), runLanguage: (event) => run(languageHooks, event), language: Effect.fn("AISDK.language")(function* (model) { - const key = `${model.providerID}/${model.id}/${model.request.variant ?? "default"}` + const key = cacheKey({ + providerID: model.providerID, + id: model.id, + modelID: model.modelID, + package: model.package, + settings: model.settings, + headers: model.headers, + body: model.body, + limit: model.limit, + }) const existing = languages.get(key) if (existing) return existing - if (model.api.type !== "aisdk") + if (!ProviderV2.isAISDK(model.package)) return yield* new InitError({ providerID: model.providerID, - cause: new Error(`Unsupported api ${model.api.type}`), + cause: new Error(`Unsupported package ${model.package}`), }) - const options = prepareOptions(model, model.api.package) - const sdkKey = JSON.stringify({ + const packageName = ProviderV2.packageName(model.package) ?? "" + const options = prepareOptions(model, packageName) + const sdkKey = cacheKey({ providerID: model.providerID, - api: model.api, - options, + package: packageName, + settings: model.settings, + headers: model.headers, + body: model.body, }) const sdk = sdks.get(sdkKey) ?? - (yield* service.runSDK({ model, package: model.api.package, options }).pipe(initError(model.providerID))).sdk + (yield* service.runSDK({ model, package: packageName, options }).pipe(initError(model.providerID))).sdk if (!sdk) return yield* new InitError({ providerID: model.providerID, @@ -221,15 +282,396 @@ const layer = Layer.effect( }) sdks.set(sdkKey, sdk) const result = yield* service.runLanguage({ model, sdk, options }).pipe(initError(model.providerID)) - const language = yield* Effect.sync(() => result.language ?? sdk.languageModel(model.api.id)).pipe( + const language = yield* Effect.sync(() => result.language ?? sdk.languageModel(model.modelID ?? model.id)).pipe( initError(model.providerID), ) languages.set(key, language) return language }), + model: Effect.fn("AISDK.model")(function* (model) { + return modelFromLanguage(model, yield* service.language(model)) + }), }) return service }), ) -export const node = makeLocationNode({ service: Service, layer, deps: [] }) +export const defaultLayer = locationLayer + +function modelFromLanguage(info: ModelV2.Info, language: LanguageModelV3) { + const settings = requestSettings(info.settings) + const optionKey = providerOptionKey(ProviderV2.packageName(info.package), info.providerID) + const route: AnyRoute = { + id: `ai-sdk:${ProviderV2.packageName(info.package) ?? "unknown"}`, + provider: ProviderID.make(info.providerID), + protocol: "ai-sdk", + endpoint: Endpoint.path("/", { baseURL: "https://ai-sdk.local" }), + auth: Auth.none, + transport: { + id: "ai-sdk", + prepare: (input) => Effect.succeed(input.body), + frames: () => Stream.empty, + }, + defaults: { + headers: info.headers, + http: + info.body === undefined && info.headers === undefined + ? undefined + : { body: info.body === undefined ? undefined : { ...info.body }, headers: info.headers }, + limits: { context: info.limit.context, output: info.limit.output }, + providerOptions: settings === undefined ? undefined : { [optionKey]: settings }, + }, + body: { + schema: Schema.Unknown, + from: (request) => Effect.succeed(callOptions(request)), + }, + with: () => route, + model: (input) => Model.make({ ...input, provider: "provider" in input ? input.provider : info.providerID, route }), + prepareTransport: (body) => Effect.succeed(body), + streamPrepared: (prepared) => streamLanguage(language, prepared as LanguageModelV3CallOptions), + } + return Model.make({ id: info.modelID ?? info.id, provider: info.providerID, route }) +} + +function providerOptionKey(packageName: string | undefined, providerID: ProviderV2.ID) { + if (packageName === "@ai-sdk/google") return "google" + if (packageName === "@ai-sdk/google-vertex") return "vertex" + if (packageName === "@ai-sdk/google-vertex/anthropic") return "anthropic" + if (packageName === "@ai-sdk/amazon-bedrock" || packageName === "@ai-sdk/amazon-bedrock/mantle") return "bedrock" + if (packageName === "@ai-sdk/azure") return "azure" + if (packageName === "@openrouter/ai-sdk-provider") return "openrouter" + if (packageName?.startsWith("@ai-sdk/")) return packageName.slice("@ai-sdk/".length) + return providerID +} + +function requestSettings(settings: Readonly> | undefined) { + if (settings === undefined) return undefined + const result = Object.fromEntries( + Object.entries(settings).filter( + ([key]) => !["apiKey", "authToken", "baseURL", "chunkTimeout", "fetch", "timeout"].includes(key), + ), + ) + return Object.keys(result).length === 0 ? undefined : result +} + +function callOptions(request: LLMRequest): LanguageModelV3CallOptions { + return { + prompt: prompt(request), + maxOutputTokens: request.generation?.maxTokens ?? request.model.route.defaults.limits?.output, + temperature: request.generation?.temperature, + stopSequences: request.generation?.stop === undefined ? undefined : [...request.generation.stop], + topP: request.generation?.topP, + topK: request.generation?.topK, + presencePenalty: request.generation?.presencePenalty, + frequencyPenalty: request.generation?.frequencyPenalty, + seed: request.generation?.seed, + responseFormat: responseFormat(request), + tools: request.tools.map(tool), + toolChoice: toolChoice(request.toolChoice), + headers: request.http?.headers, + providerOptions: providerOptions(request.providerOptions), + } +} + +function prompt(request: LLMRequest): LanguageModelV3Prompt { + const system = request.system + .map((part) => part.text) + .filter(Boolean) + .join("\n\n") + const messages = request.messages.flatMap(message) + if (!system.length) return messages + return [{ role: "system", content: system }, ...messages] +} + +function message(input: LLMRequest["messages"][number]): LanguageModelV3Message[] { + switch (input.role) { + case "system": + return [{ role: "system", content: input.content.flatMap(text).join("\n\n") }] + case "user": + return [{ role: "user", content: input.content.flatMap(userPart) }] + case "assistant": + return [{ role: "assistant", content: input.content.flatMap(assistantPart) }] + case "tool": { + const content = input.content.flatMap(toolResultPart) + return content.length ? [{ role: "tool", content }] : [] + } + } +} + +function text(part: ContentPart) { + return part.type === "text" ? [part.text] : [] +} + +function userPart(part: ContentPart): UserContent { + if (part.type === "text") return [{ type: "text", text: part.text }] + if (part.type === "media") + return [{ type: "file", mediaType: part.mediaType, data: part.data, filename: part.filename }] + return [] +} + +function assistantPart(part: ContentPart): AssistantContent { + switch (part.type) { + case "text": + return [{ type: "text", text: part.text }] + case "media": + return [{ type: "file", mediaType: part.mediaType, data: part.data, filename: part.filename }] + case "reasoning": + return [{ type: "reasoning", text: part.text }] + case "tool-call": + return [ + { + type: "tool-call", + toolCallId: part.id, + toolName: part.name, + input: part.input, + providerExecuted: part.providerExecuted, + }, + ] + case "tool-result": + return toolResultPart(part) + } +} + +function toolResultPart(part: ContentPart): ToolResultContent[] { + if (part.type !== "tool-result") return [] + return [ + { + type: "tool-result", + toolCallId: part.id, + toolName: part.name, + output: toolOutput(part.result), + }, + ] +} + +function toolOutput(result: ToolResultValue) { + switch (result.type) { + case "text": + case "error": + return { type: "text" as const, value: messageValue(result.value) } + } + return { type: "json" as const, value: jsonValue(result.value) } +} + +function tool(input: ToolDefinition): LanguageModelV3FunctionTool { + return { + type: "function", + name: input.name, + description: input.description, + inputSchema: input.inputSchema as JSONSchema7, + } +} + +function toolChoice(input: LLMRequest["toolChoice"]): LanguageModelV3ToolChoice | undefined { + if (!input) return undefined + if (input.type === "tool") return input.name === undefined ? undefined : { type: "tool", toolName: input.name } + return { type: input.type } +} + +function responseFormat(request: LLMRequest): LanguageModelV3CallOptions["responseFormat"] { + if (request.responseFormat?.type === "json") + return { type: "json", schema: request.responseFormat.schema as JSONSchema7 } + if (request.responseFormat) return { type: "text" } +} + +function providerOptions(input: LLMRequest["providerOptions"]): SharedV3ProviderOptions | undefined { + if (!input) return undefined + return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, jsonObject(value)])) +} + +function streamLanguage(language: LanguageModelV3, options: LanguageModelV3CallOptions) { + const state = { step: 0, toolNames: {} as Record } + return Stream.concat( + Stream.make(LLMEvent.stepStart({ index: state.step })), + Stream.unwrap( + Effect.tryPromise({ + try: () => language.doStream(options), + catch: (error) => llmError("doStream", error), + }).pipe( + Effect.map((result) => + Stream.fromReadableStream({ + evaluate: () => result.stream, + onError: (error) => llmError("readStream", error), + }).pipe( + Stream.mapEffect((event) => streamPartEvents(state, event)), + Stream.flatMap((events) => Stream.fromIterable(events)), + ), + ), + ), + ), + ) +} + +function streamPartEvents( + state: { step: number; toolNames: Record }, + event: LanguageModelV3StreamPart, +): Effect.Effect, LLMError> { + switch (event.type) { + case "stream-start": + case "response-metadata": + case "raw": + case "file": + case "source": + case "tool-approval-request": + return Effect.succeed([]) + case "text-start": + return Effect.succeed([ + LLMEvent.textStart({ id: event.id, providerMetadata: providerMetadata(event.providerMetadata) }), + ]) + case "text-delta": + return Effect.succeed([ + LLMEvent.textDelta({ + id: event.id, + text: event.delta, + providerMetadata: providerMetadata(event.providerMetadata), + }), + ]) + case "text-end": + return Effect.succeed([ + LLMEvent.textEnd({ id: event.id, providerMetadata: providerMetadata(event.providerMetadata) }), + ]) + case "reasoning-start": + return Effect.succeed([ + LLMEvent.reasoningStart({ id: event.id, providerMetadata: providerMetadata(event.providerMetadata) }), + ]) + case "reasoning-delta": + return Effect.succeed([ + LLMEvent.reasoningDelta({ + id: event.id, + text: event.delta, + providerMetadata: providerMetadata(event.providerMetadata), + }), + ]) + case "reasoning-end": + return Effect.succeed([ + LLMEvent.reasoningEnd({ id: event.id, providerMetadata: providerMetadata(event.providerMetadata) }), + ]) + case "tool-input-start": + state.toolNames[event.id] = event.toolName + return Effect.succeed([ + LLMEvent.toolInputStart({ + id: event.id, + name: event.toolName, + providerMetadata: providerMetadata(event.providerMetadata), + }), + ]) + case "tool-input-delta": + return Effect.succeed([ + LLMEvent.toolInputDelta({ id: event.id, name: state.toolNames[event.id] ?? "unknown", text: event.delta }), + ]) + case "tool-input-end": + return Effect.succeed([ + LLMEvent.toolInputEnd({ + id: event.id, + name: state.toolNames[event.id] ?? "unknown", + providerMetadata: providerMetadata(event.providerMetadata), + }), + ]) + case "tool-call": + state.toolNames[event.toolCallId] = event.toolName + return Effect.succeed([ + LLMEvent.toolCall({ + id: event.toolCallId, + name: event.toolName, + input: parseToolInput(event.input), + providerExecuted: event.providerExecuted, + providerMetadata: providerMetadata(event.providerMetadata), + }), + ]) + case "tool-result": + delete state.toolNames[event.toolCallId] + return Effect.succeed([ + LLMEvent.toolResult({ + id: event.toolCallId, + name: event.toolName, + result: ToolResultValue.make(event.result, event.isError ? "error" : "json"), + providerExecuted: true, + providerMetadata: providerMetadata(event.providerMetadata), + }), + ]) + case "finish": + return Effect.succeed([ + LLMEvent.stepFinish({ + index: state.step++, + reason: finishReason(event.finishReason), + usage: usage(event.usage), + providerMetadata: providerMetadata(event.providerMetadata), + }), + LLMEvent.finish({ + reason: finishReason(event.finishReason), + usage: usage(event.usage), + providerMetadata: providerMetadata(event.providerMetadata), + }), + ]) + case "error": + return Effect.fail(llmError("stream", event.error)) + } +} + +function usage(input: Extract["usage"]): UsageInput | undefined { + const output = { + inputTokens: input.inputTokens.total, + nonCachedInputTokens: input.inputTokens.noCache, + cacheReadInputTokens: input.inputTokens.cacheRead, + cacheWriteInputTokens: input.inputTokens.cacheWrite, + outputTokens: input.outputTokens.total, + reasoningTokens: input.outputTokens.reasoning, + totalTokens: + input.inputTokens.total === undefined || input.outputTokens.total === undefined + ? undefined + : input.inputTokens.total + input.outputTokens.total, + } + return Object.values(output).some((value) => value !== undefined) ? output : undefined +} + +function finishReason(value: unknown): FinishReason { + return Schema.is(FinishReason)(value) ? value : "unknown" +} + +function providerMetadata(value: unknown) { + return Schema.is(ProviderMetadata)(value) ? value : undefined +} + +function parseToolInput(value: string) { + try { + return JSON.parse(value) as unknown + } catch { + return value + } +} + +function jsonObject(input: Record) { + return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, jsonValue(value)])) +} + +function jsonValue(input: unknown): JSONValue { + try { + const encoded = JSON.stringify(input) + return encoded === undefined ? null : (JSON.parse(encoded) as JSONValue) + } catch { + return messageValue(input) + } +} + +function messageValue(input: unknown) { + if (typeof input === "string") return input + try { + return JSON.stringify(input) ?? String(input) + } catch { + return String(input) + } +} + +function llmError(method: string, error: unknown) { + const reason = + error instanceof LLMError + ? new InvalidProviderOutputReason({ message: error.message }) + : new UnknownProviderReason({ message: error instanceof Error ? error.message : String(error) }) + return new LLMError({ + module: "AISDK", + method, + reason, + }) +} + +export const node = makeLocationNode({ service: Service, layer: locationLayer, deps: [] }) diff --git a/packages/core/src/catalog.ts b/packages/core/src/catalog.ts index ab34db8ea45..2441f037895 100644 --- a/packages/core/src/catalog.ts +++ b/packages/core/src/catalog.ts @@ -66,39 +66,21 @@ const layer = Layer.effect( const available = (provider: ProviderV2.Info, integration: Integration.Info | undefined) => { if (provider.disabled) return false - if (typeof provider.request.body.apiKey === "string") return true + if (typeof provider.settings?.apiKey === "string") return true if (integration?.connections.length) return true return provider.integrationID === undefined && !integration } const projectModel = (model: ModelV2.Info, provider: ProviderV2.Info) => { - const api = - model.api.type === "native" && !model.api.url && Object.keys(model.api.settings).length === 0 - ? { ...provider.api, id: model.api.id } - : model.api.type === "aisdk" && provider.api.type === "aisdk" && !model.api.url - ? { ...model.api, url: provider.api.url, settings: { ...provider.api.settings, ...model.api.settings } } - : model.api.type === "aisdk" && provider.api.type === "aisdk" - ? { ...model.api, settings: { ...provider.api.settings, ...model.api.settings } } - : model.api - const request = { - settings: { ...provider.request.settings, ...model.request.settings }, - headers: { ...provider.request.headers, ...model.request.headers }, - body: { ...provider.request.body, ...model.request.body }, - variant: model.request.variant, - } return ModelV2.Info.make({ ...model, - api, - request, + package: model.package ?? provider.package, + settings: ProviderV2.mergeOverlay(provider.settings, model.settings), + headers: ProviderV2.mergeHeaders(provider.headers, model.headers), + body: ProviderV2.mergeOverlay(provider.body, model.body), }) } - const normalizeApi = (item: ProviderV2.MutableInfo | ModelV2.MutableInfo) => { - if (typeof item.request.body.baseURL !== "string") return - item.api.url = item.request.body.baseURL - delete item.request.body.baseURL - } - const state = State.create({ initial: () => ({ providers: new Map() }), draft: (draft) => { @@ -116,7 +98,6 @@ const layer = Layer.effect( draft.providers.set(providerID, current) } fn(current.provider) - normalizeApi(current.provider) }, remove: (providerID) => { draft.providers.delete(providerID) @@ -139,7 +120,6 @@ const layer = Layer.effect( fn(model) model.id = modelID model.providerID = providerID - normalizeApi(model) }, remove: (providerID, modelID) => { draft.providers.get(providerID)?.models.delete(modelID) diff --git a/packages/core/src/config.ts b/packages/core/src/config.ts index 4bd33ca2402..ae05ddef7d8 100644 --- a/packages/core/src/config.ts +++ b/packages/core/src/config.ts @@ -19,6 +19,7 @@ import { ConfigCommand } from "./config/command" import { ConfigFormatter } from "./config/formatter" import { ConfigLSP } from "./config/lsp" import { ConfigMCP } from "./config/mcp" +import { ConfigModel } from "./config/model" import { ConfigPlugin } from "./config/plugin" import { ConfigProvider } from "./config/provider" import { ConfigReference } from "./config/reference" @@ -35,7 +36,7 @@ export class Info extends Schema.Class("Config.Info")({ shell: Schema.String.pipe(Schema.optional).annotate({ description: "Default shell to use for terminal and shell tool execution", }), - model: Schema.String.pipe(Schema.optional).annotate({ + model: ConfigModel.Selection.pipe(Schema.optional).annotate({ description: "Default model to use when no session or agent model is selected", }), default_agent: Schema.String.pipe(Schema.optional).annotate({ diff --git a/packages/core/src/config/agent.ts b/packages/core/src/config/agent.ts index 63df995f859..fc5edf51192 100644 --- a/packages/core/src/config/agent.ts +++ b/packages/core/src/config/agent.ts @@ -3,6 +3,7 @@ export * as ConfigAgent from "./agent" import { Schema } from "effect" import { Permission } from "@opencode-ai/schema/permission" import { ConfigProvider } from "./provider" +import { ConfigModel } from "./model" import { PositiveInt } from "../schema" export const Color = Schema.Union([ @@ -11,8 +12,7 @@ export const Color = Schema.Union([ ]) export class Info extends Schema.Class("ConfigV2.Agent")({ - model: Schema.String.pipe(Schema.optional), - variant: Schema.String.pipe(Schema.optional), + model: ConfigModel.Selection.pipe(Schema.optional), request: ConfigProvider.Request.pipe(Schema.optional), system: Schema.String.pipe(Schema.optional), description: Schema.String.pipe(Schema.optional), diff --git a/packages/core/src/config/command.ts b/packages/core/src/config/command.ts index 394079b1e98..8168107fd15 100644 --- a/packages/core/src/config/command.ts +++ b/packages/core/src/config/command.ts @@ -1,12 +1,12 @@ export * as ConfigCommand from "./command" import { Schema } from "effect" +import { ConfigModel } from "./model" export class Info extends Schema.Class("ConfigV2.Command")({ template: Schema.String, description: Schema.String.pipe(Schema.optional), agent: Schema.String.pipe(Schema.optional), - model: Schema.String.pipe(Schema.optional), - variant: Schema.String.pipe(Schema.optional), + model: ConfigModel.Selection.pipe(Schema.optional), subtask: Schema.Boolean.pipe(Schema.optional), }) {} diff --git a/packages/core/src/config/model.ts b/packages/core/src/config/model.ts new file mode 100644 index 00000000000..a1ee46a5f11 --- /dev/null +++ b/packages/core/src/config/model.ts @@ -0,0 +1,38 @@ +export * as ConfigModel from "./model" + +import { Schema, SchemaGetter } from "effect" +import { Model } from "@opencode-ai/schema/model" +import { Provider } from "@opencode-ai/schema/provider" + +const ProviderID = Provider.ID.check(Schema.isPattern(/^[^/#]+$/)) +const ModelID = Model.ID.check(Schema.isPattern(/^[^#]+$/)) +const VariantID = Model.VariantID.check(Schema.isPattern(/^[^#]+$/)) + +const Explicit = Schema.Struct({ + providerID: ProviderID, + model: ModelID, + variant: VariantID.pipe(Schema.optional), +}) + +const Short = Schema.String.check(Schema.isPattern(/^[^/#]+\/[^#]+(?:#[^#]+)?$/)) + +export interface Selection extends Schema.Schema.Type {} +export const Selection = Schema.Union([Short, Explicit]) + .pipe( + Schema.decodeTo(Explicit, { + decode: SchemaGetter.transform((input) => (typeof input === "string" ? parse(input) : input)), + encode: SchemaGetter.passthrough({ strict: false }), + }), + ) + .annotate({ identifier: "Config.ModelSelection" }) + +function parse(input: string): Selection { + const providerEnd = input.indexOf("/") + const variantStart = input.lastIndexOf("#") + const hasVariant = variantStart > providerEnd + return { + providerID: Provider.ID.make(input.slice(0, providerEnd)), + model: Model.ID.make(input.slice(providerEnd + 1, hasVariant ? variantStart : undefined)), + ...(hasVariant ? { variant: Model.VariantID.make(input.slice(variantStart + 1)) } : {}), + } +} diff --git a/packages/core/src/config/plugin/agent.ts b/packages/core/src/config/plugin/agent.ts index fa8b61ce182..e6ed0b0ed8b 100644 --- a/packages/core/src/config/plugin/agent.ts +++ b/packages/core/src/config/plugin/agent.ts @@ -8,7 +8,6 @@ import { Config } from "../../config" import { ConfigAgent } from "../agent" import { ConfigMarkdown } from "../markdown" import { FSUtil } from "../../fs-util" -import { ModelV2 } from "../../model" import { ConfigAgentV1 } from "../../v1/config/agent" import { ConfigMigrateV1 } from "../../v1/config/migrate" @@ -76,13 +75,12 @@ export const Plugin = define({ const exists = draft.get(agentID) !== undefined draft.update(agentID, (agent) => { if (!exists) agent.permissions.push(...global) - if (item.model !== undefined) { - const model = ModelV2.parse(item.model) - agent.model = { id: model.modelID, providerID: model.providerID, variant: agent.model?.variant } - } - if (item.variant !== undefined && agent.model !== undefined) { - agent.model.variant = ModelV2.VariantID.make(item.variant) - } + if (item.model !== undefined) + agent.model = { + id: item.model.model, + providerID: item.model.providerID, + ...(item.model.variant === undefined ? {} : { variant: item.model.variant }), + } if (item.request !== undefined) { Object.assign(agent.request.headers, item.request.headers ?? {}) Object.assign(agent.request.body, item.request.body ?? {}) @@ -134,14 +132,16 @@ function decode(file: { directory: string; filepath: string; primary: boolean }, .replace(/\.md$/, "") const body = markdown.content.trim() const legacy = Object.keys(markdown.data).some((key) => !agentKeys.has(key)) - const agent = Option.getOrUndefined( - legacy - ? Option.map( + const agent = legacy + ? Option.getOrUndefined( + Option.map( decodeLegacyAgent({ name, ...markdown.data, prompt: body }, { errors: "all", propertyOrder: "original" }), ConfigMigrateV1.migrateAgent, - ) - : decodeAgent({ ...markdown.data, system: body }, { errors: "all", propertyOrder: "original" }), - ) + ), + ) + : Option.getOrUndefined( + decodeAgent({ ...markdown.data, system: body }, { errors: "all", propertyOrder: "original" }), + ) if (!agent) return const info = Option.getOrUndefined( decodeConfig({ diff --git a/packages/core/src/config/plugin/command.ts b/packages/core/src/config/plugin/command.ts index a7babbb5aa7..b294ab15b94 100644 --- a/packages/core/src/config/plugin/command.ts +++ b/packages/core/src/config/plugin/command.ts @@ -6,7 +6,6 @@ import { Effect, Option, Schema, Stream } from "effect" import { CommandV2 } from "../../command" import { Config } from "../../config" import { FSUtil } from "../../fs-util" -import { ModelV2 } from "../../model" import { ConfigCommand } from "../command" import { ConfigMarkdown } from "../markdown" @@ -35,13 +34,12 @@ export const Plugin = define({ item.template = command.template if (command.description !== undefined) item.description = command.description if (command.agent !== undefined) item.agent = command.agent - if (command.model !== undefined) { - const model = ModelV2.parse(command.model) - item.model = { id: model.modelID, providerID: model.providerID, variant: item.model?.variant } - } - if (command.variant !== undefined && item.model !== undefined) { - item.model.variant = ModelV2.VariantID.make(command.variant) - } + if (command.model !== undefined) + item.model = { + id: command.model.model, + providerID: command.model.providerID, + ...(command.model.variant === undefined ? {} : { variant: command.model.variant }), + } if (command.subtask !== undefined) item.subtask = command.subtask }) } diff --git a/packages/core/src/config/plugin/provider.ts b/packages/core/src/config/plugin/provider.ts index 320895d1289..3cfc799d72f 100644 --- a/packages/core/src/config/plugin/provider.ts +++ b/packages/core/src/config/plugin/provider.ts @@ -4,6 +4,7 @@ import { define } from "@opencode-ai/plugin/v2/effect/plugin" import { Effect, Stream } from "effect" import { Config } from "../../config" import { ModelV2 } from "../../model" +import { ProviderV2 } from "../../provider" export const Plugin = define({ id: "opencode.config.provider", @@ -39,27 +40,29 @@ export const Plugin = define({ yield* ctx.catalog.transform((catalog) => { const files = loaded.entries.filter((entry): entry is Config.Document => entry.type === "document") const configuredDefault = Config.latest(loaded.entries, "model") - if (configuredDefault !== undefined) { - const model = ModelV2.parse(configuredDefault) - catalog.model.default.set(model.providerID, model.modelID) - } + if (configuredDefault !== undefined) + catalog.model.default.set(configuredDefault.providerID, configuredDefault.model) for (const file of files) { for (const [id, item] of Object.entries(file.info.providers ?? {})) { const providerID = id catalog.provider.update(providerID, (provider) => { if (item.name !== undefined) provider.name = item.name - if (item.api !== undefined) provider.api = { ...item.api } - if (item.request !== undefined) { - Object.assign(provider.request.settings, item.request.settings) - Object.assign(provider.request.headers, item.request.headers) - Object.assign(provider.request.body, item.request.body) - } + if (item.package !== undefined) provider.package = item.package + if (item.settings !== undefined) + provider.settings = ProviderV2.mergeOverlay(provider.settings, item.settings) + if (item.headers !== undefined) provider.headers = ProviderV2.mergeHeaders(provider.headers, item.headers) + if (item.body !== undefined) provider.body = ProviderV2.mergeOverlay(provider.body, item.body) }) for (const [id, config] of Object.entries(item.models ?? {})) { catalog.model.update(providerID, id, (model) => { if (config.family !== undefined) model.family = config.family if (config.name !== undefined) model.name = config.name - if (config.api !== undefined) model.api = { ...model.api, ...config.api } + if (config.modelID !== undefined) model.modelID = config.modelID + if (config.package !== undefined) model.package = config.package + if (config.settings !== undefined) + model.settings = ProviderV2.mergeOverlay(model.settings, config.settings) + if (config.headers !== undefined) model.headers = ProviderV2.mergeHeaders(model.headers, config.headers) + if (config.body !== undefined) model.body = ProviderV2.mergeOverlay(model.body, config.body) if (config.capabilities !== undefined) { model.capabilities = { tools: config.capabilities.tools, @@ -67,27 +70,19 @@ export const Plugin = define({ output: [...config.capabilities.output], } } - if (config.request !== undefined) { - Object.assign(model.request.settings, config.request.settings) - Object.assign(model.request.headers, config.request.headers) - Object.assign(model.request.body, config.request.body) - if (config.request.variant !== undefined) model.request.variant = config.request.variant - } if (config.variants !== undefined) { + model.variants ??= [] for (const variant of config.variants) { let existing = model.variants.find((item) => item.id === variant.id) if (!existing) { - existing = { - id: variant.id, - settings: {}, - headers: {}, - body: {}, - } + existing = { id: variant.id } model.variants.push(existing) } - Object.assign(existing.settings, variant.settings) - Object.assign(existing.headers, variant.headers) - Object.assign(existing.body, variant.body) + if (variant.settings !== undefined) + existing.settings = ProviderV2.mergeOverlay(existing.settings, variant.settings) + if (variant.headers !== undefined) + existing.headers = ProviderV2.mergeHeaders(existing.headers, variant.headers) + if (variant.body !== undefined) existing.body = ProviderV2.mergeOverlay(existing.body, variant.body) } } if (config.cost !== undefined) { diff --git a/packages/core/src/config/provider.ts b/packages/core/src/config/provider.ts index c78d7979ae8..ec371823958 100644 --- a/packages/core/src/config/provider.ts +++ b/packages/core/src/config/provider.ts @@ -1,13 +1,19 @@ export * as ConfigProvider from "./provider" import { Schema } from "effect" -import { ProviderV2 } from "../provider" import { ModelV2 } from "../model" -export class Request extends Schema.Class("ConfigV2.Provider.Request")({ - settings: ProviderV2.Settings.pipe(Schema.optional), +const JsonRecord = Schema.Record(Schema.String, Schema.Json) + +export const Overlays = { + settings: JsonRecord.pipe(Schema.optional), headers: Schema.Record(Schema.String, Schema.String).pipe(Schema.optional), - body: Schema.Record(Schema.String, Schema.Unknown).pipe(Schema.optional), + body: JsonRecord.pipe(Schema.optional), +} + +export class Request extends Schema.Class("ConfigV2.Provider.Request")({ + headers: Overlays.headers, + body: Overlays.body, }) {} class Cache extends Schema.Class("ConfigV2.Model.Cost.Cache")({ @@ -31,32 +37,16 @@ class Limit extends Schema.Class("ConfigV2.Model.Limit")({ output: Schema.Int.pipe(Schema.optional), }) {} -const ModelApi = Schema.Union([ - Schema.Struct({ - id: ModelV2.ID.pipe(Schema.optional), - ...ProviderV2.AISDK.fields, - }), - Schema.Struct({ - id: ModelV2.ID.pipe(Schema.optional), - ...ProviderV2.Native.fields, - }), - Schema.Struct({ - id: ModelV2.ID, - }), -]) - class Model extends Schema.Class("ConfigV2.Model")({ + modelID: ModelV2.ID.pipe(Schema.optional), family: ModelV2.Family.pipe(Schema.optional), name: Schema.String.pipe(Schema.optional), - api: ModelApi.pipe(Schema.optional), + package: Schema.String.pipe(Schema.optional), + ...Overlays, capabilities: ModelV2.Capabilities.pipe(Schema.optional), - request: Schema.Struct({ - ...Request.fields, - variant: Schema.String.pipe(Schema.optional), - }).pipe(Schema.optional), variants: Schema.Struct({ id: ModelV2.VariantID, - ...Request.fields, + ...Overlays, }).pipe(Schema.Array, Schema.optional), cost: Schema.Union([Cost, Cost.pipe(Schema.Array)]).pipe(Schema.optional), disabled: Schema.Boolean.pipe(Schema.optional), @@ -66,7 +56,7 @@ class Model extends Schema.Class("ConfigV2.Model")({ export class Info extends Schema.Class("ConfigV2.Provider")({ name: Schema.String.pipe(Schema.optional), env: Schema.String.pipe(Schema.Array, Schema.optional), - api: ProviderV2.Api.pipe(Schema.optional), - request: Request.pipe(Schema.optional), + package: Schema.String.pipe(Schema.optional), + ...Overlays, models: Schema.Record(Schema.String, Model).pipe(Schema.optional), }) {} diff --git a/packages/core/src/model.ts b/packages/core/src/model.ts index 41abbcb2d25..3f264ecd9f4 100644 --- a/packages/core/src/model.ts +++ b/packages/core/src/model.ts @@ -1,6 +1,6 @@ -import { Types } from "effect" import { Model } from "@opencode-ai/schema/model" import { ProviderV2 } from "./provider" +import type { DeepMutable } from "./schema" export const ID = Model.ID export type ID = typeof ID.Type @@ -20,20 +20,10 @@ export const Cost = Model.Cost export const Ref = Model.Ref export type Ref = typeof Ref.Type -export const Api = Model.Api -export type Api = Model.Api - export const Info = Model.Info export type Info = Model.Info -export type MutableRequest = ProviderV2.MutableRequest & { variant?: string } -export type MutableVariant = ProviderV2.MutableRequest & { id: VariantID } - -export type MutableInfo = Omit, "api" | "request" | "variants"> & { - api: ProviderV2.MutableApi - request: MutableRequest - variants: MutableVariant[] -} +export type MutableInfo = DeepMutable export function parse(input: string): { providerID: ProviderV2.ID; modelID: ID } { const [providerID, ...modelID] = input.split("/") diff --git a/packages/core/src/plugin/models-dev.ts b/packages/core/src/plugin/models-dev.ts index 23a166e2679..67cf0069dc1 100644 --- a/packages/core/src/plugin/models-dev.ts +++ b/packages/core/src/plugin/models-dev.ts @@ -72,7 +72,7 @@ function mergeCost(base: ModelV2Info["cost"], override: ModelsDev.Model["cost"] const OPENAI_INCLUDE_ENCRYPTED_REASONING = ["reasoning.encrypted_content"] -function reasoningVariants(provider: ModelsDev.Provider, model: ModelsDev.Model): ModelV2Info["variants"] { +function reasoningVariants(provider: ModelsDev.Provider, model: ModelsDev.Model): NonNullable { const npm = model.provider?.npm ?? provider.npm const options = model.reasoning_options ?? [] const effort = options.find((option) => option.type === "effort") @@ -82,7 +82,7 @@ function reasoningVariants(provider: ModelsDev.Provider, model: ModelsDev.Model) const id = raw === null ? "none" : typeof raw === "string" ? raw : undefined if (id === undefined) return [] const settings = settingsForEffort(npm, id) - return settings ? [{ id, settings, headers: {}, body: {} }] : [] + return settings ? [{ id: ModelV2.VariantID.make(id), settings }] : [] }) } @@ -117,15 +117,18 @@ function settingsForEffort(npm: string | undefined, effort: string): ProviderV2. function budgetVariants( npm: string | undefined, option: Extract[number], { type: "budget_tokens" }>, -): ModelV2Info["variants"] { +): NonNullable { const max = option.max - const high = option.max === undefined ? Math.max(option.min ?? 0, 16_000) : Math.min(Math.max(option.min ?? 0, 16_000), option.max) + const high = + option.max === undefined + ? Math.max(option.min ?? 0, 16_000) + : Math.min(Math.max(option.min ?? 0, 16_000), option.max) return [ { id: "high", budget: high }, ...(max === undefined || max === high ? [] : [{ id: "max", budget: max }]), ].flatMap((item) => { const settings = settingsForBudget(npm, item.budget) - return settings ? [{ id: item.id, settings, headers: {}, body: {} }] : [] + return settings ? [{ id: ModelV2.VariantID.make(item.id), settings }] : [] }) } @@ -143,12 +146,13 @@ function modeName(model: ModelsDev.Model, mode: string) { return `${model.name} ${mode.charAt(0).toUpperCase()}${mode.slice(1)}` } -function mergeVariants(model: ModelV2Info, next: ModelV2Info["variants"]) { - const existing = new Map(model.variants.map((variant) => [variant.id, variant])) +function mergeVariants(model: ModelV2Info, next: NonNullable) { + const variants = model.variants ?? [] + const existing = new Map(variants.map((variant) => [variant.id, variant])) const nextIDs = new Set(next.map((variant) => variant.id)) model.variants = [ ...next.map((variant) => existing.get(variant.id) ?? variant), - ...model.variants.filter((variant) => !nextIDs.has(variant.id)), + ...variants.filter((variant) => !nextIDs.has(variant.id)), ] } @@ -159,24 +163,14 @@ function applyModel( readonly name?: string readonly cost?: ModelV2Info["cost"] readonly request?: NonNullable["modes"]>[string]["provider"] - readonly variants?: ModelV2Info["variants"] + readonly variants?: NonNullable } = {}, ) { draft.name = input.name ?? model.name + draft.modelID = model.id draft.family = model.family ? ModelV2.Family.make(model.family) : undefined - draft.api = model.provider?.npm - ? { - id: ModelV2.ID.make(model.id), - type: "aisdk", - package: model.provider.npm, - url: model.provider.api, - } - : { - id: ModelV2.ID.make(model.id), - type: "native", - url: model.provider?.api, - settings: {}, - } + draft.package = model.provider?.npm ? ProviderV2.aisdk(model.provider.npm) : undefined + draft.settings = model.provider?.api ? { ...draft.settings, baseURL: model.provider.api } : draft.settings draft.capabilities = { tools: model.tool_call, input: [...(model.modalities?.input ?? [])], @@ -184,7 +178,11 @@ function applyModel( } mergeVariants(draft, input.variants ?? []) draft.time.released = released(model.release_date) - draft.cost = input.cost ?? cost(model.cost) + draft.cost = (input.cost ?? cost(model.cost)).map((item) => ({ + ...item, + tier: item.tier && { ...item.tier }, + cache: { ...item.cache }, + })) draft.status = model.status ?? "active" draft.enabled = true draft.limit = { @@ -192,8 +190,8 @@ function applyModel( input: model.limit.input, output: model.limit.output, } - Object.assign(draft.request.headers, input.request?.headers ?? {}) - Object.assign(draft.request.body, input.request?.body ?? {}) + draft.headers = { ...draft.headers, ...input.request?.headers } + draft.body = { ...draft.body, ...input.request?.body } } export const ModelsDevPlugin = define({ @@ -222,25 +220,18 @@ export const ModelsDevPlugin = define({ const providerID = ProviderV2.ID.make(item.id) catalog.provider.update(providerID, (provider) => { provider.name = item.name - provider.api = item.npm - ? { - type: "aisdk", - package: item.npm, - url: item.api, - } - : { - type: "native", - url: item.api, - settings: {}, - } + provider.package = item.npm ? ProviderV2.aisdk(item.npm) : "" + provider.settings = item.api ? { ...provider.settings, baseURL: item.api } : provider.settings }) for (const model of Object.values(item.models)) { const baseCost = cost(model.cost) const variants = reasoningVariants(item, model) - catalog.model.update(providerID, model.id, (draft) => applyModel(draft, model, { cost: baseCost, variants })) + catalog.model.update(providerID, ModelV2.ID.make(model.id), (draft) => + applyModel(draft, model, { cost: baseCost, variants }), + ) for (const [mode, options] of Object.entries(model.experimental?.modes ?? {})) { - catalog.model.update(providerID, `${model.id}-${mode}`, (draft) => + catalog.model.update(providerID, ModelV2.ID.make(`${model.id}-${mode}`), (draft) => applyModel(draft, model, { name: modeName(model, mode), cost: mergeCost(baseCost, options.cost), diff --git a/packages/core/src/plugin/provider/amazon-bedrock.ts b/packages/core/src/plugin/provider/amazon-bedrock.ts index 0bc3ced4628..5bbe953f805 100644 --- a/packages/core/src/plugin/provider/amazon-bedrock.ts +++ b/packages/core/src/plugin/provider/amazon-bedrock.ts @@ -64,15 +64,14 @@ export const AmazonBedrockPlugin = define({ effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/amazon-bedrock") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/amazon-bedrock") continue evt.provider.update(item.provider.id, (provider) => { - if (provider.api.type !== "aisdk") return - if (typeof provider.request.body.endpoint !== "string") return + if (typeof provider.settings?.endpoint !== "string") return // The AI SDK expects a base URL, but users configure Bedrock private/VPC // endpoints as `endpoint`; move it into the catalog endpoint URL once. - provider.api.url = provider.request.body.endpoint - delete provider.request.body.endpoint + provider.settings.baseURL = provider.settings.endpoint + delete provider.settings.endpoint }) } }) @@ -112,12 +111,15 @@ export const AmazonBedrockPlugin = define({ yield* ctx.aisdk.language( Effect.fn(function* (evt) { if (evt.model.providerID !== ProviderV2.ID.amazonBedrock) return - if (evt.model.api.type === "aisdk" && evt.model.api.package === "@ai-sdk/amazon-bedrock/mantle") { - evt.language = selectMantleModel(evt.sdk, evt.model.api.id) + if ( + ProviderV2.isAISDK(evt.model.package) && + ProviderV2.packageName(evt.model.package) === "@ai-sdk/amazon-bedrock/mantle" + ) { + evt.language = selectMantleModel(evt.sdk, evt.model.modelID ?? evt.model.id) return } const region = typeof evt.options.region === "string" ? evt.options.region : process.env.AWS_REGION - evt.language = evt.sdk.languageModel(resolveModelID(evt.model.api.id, region)) + evt.language = evt.sdk.languageModel(resolveModelID(evt.model.modelID ?? evt.model.id, region)) }), ) }), diff --git a/packages/core/src/plugin/provider/anthropic.ts b/packages/core/src/plugin/provider/anthropic.ts index 3a8a7c86590..4c5938e51ff 100644 --- a/packages/core/src/plugin/provider/anthropic.ts +++ b/packages/core/src/plugin/provider/anthropic.ts @@ -1,16 +1,19 @@ import { Effect } from "effect" import { define } from "@opencode-ai/plugin/v2/effect/plugin" +import { ProviderV2 } from "../../provider" export const AnthropicPlugin = define({ id: "opencode.provider.anthropic", effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/anthropic") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/anthropic") continue evt.provider.update(item.provider.id, (provider) => { - provider.request.headers["anthropic-beta"] = - "interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14" + provider.headers = { + ...provider.headers, + "anthropic-beta": "interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14", + } }) } }) diff --git a/packages/core/src/plugin/provider/azure.ts b/packages/core/src/plugin/provider/azure.ts index 3269c7d2d92..65a40c023b2 100644 --- a/packages/core/src/plugin/provider/azure.ts +++ b/packages/core/src/plugin/provider/azure.ts @@ -15,14 +15,14 @@ export const AzurePlugin = define({ effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/azure") continue - const configured = item.provider.request.body.resourceName + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/azure") continue + const configured = item.provider.settings?.resourceName const resourceName = typeof configured === "string" && configured.trim() !== "" ? configured : process.env.AZURE_RESOURCE_NAME if (!resourceName) continue evt.provider.update(item.provider.id, (provider) => { - provider.request.body.resourceName = resourceName + provider.settings = { ...provider.settings, resourceName } }) } }) @@ -33,7 +33,7 @@ export const AzurePlugin = define({ if ( !evt.options.resourceName && !evt.options.baseURL && - (evt.model.api.type !== "aisdk" || !evt.model.api.url) + (!ProviderV2.isAISDK(evt.model.package) || typeof evt.model.settings?.baseURL !== "string") ) { throw new Error( "AZURE_RESOURCE_NAME is missing, set it using env var or reconnecting the azure provider and setting it", @@ -47,7 +47,11 @@ export const AzurePlugin = define({ yield* ctx.aisdk.language( Effect.fn(function* (evt) { if (evt.model.providerID !== ProviderV2.ID.azure) return - evt.language = selectLanguage(evt.sdk, evt.model.api.id, Boolean(evt.options.useCompletionUrls)) + evt.language = selectLanguage( + evt.sdk, + evt.model.modelID ?? evt.model.id, + Boolean(evt.options.useCompletionUrls), + ) }), ) }), @@ -60,18 +64,25 @@ export const AzureCognitiveServicesPlugin = define({ const resourceName = process.env.AZURE_COGNITIVE_SERVICES_RESOURCE_NAME if (!resourceName) return for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/openai-compatible") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/openai-compatible") continue if (!item.provider.id.includes("azure-cognitive-services")) continue evt.provider.update(item.provider.id, (provider) => { - provider.request.body.baseURL = `https://${resourceName}.cognitiveservices.azure.com/openai` + provider.settings = { + ...provider.settings, + baseURL: `https://${resourceName}.cognitiveservices.azure.com/openai`, + } }) } }) yield* ctx.aisdk.language( Effect.fn(function* (evt) { if (evt.model.providerID !== ProviderV2.ID.make("azure-cognitive-services")) return - evt.language = selectLanguage(evt.sdk, evt.model.api.id, Boolean(evt.options.useCompletionUrls)) + evt.language = selectLanguage( + evt.sdk, + evt.model.modelID ?? evt.model.id, + Boolean(evt.options.useCompletionUrls), + ) }), ) }), diff --git a/packages/core/src/plugin/provider/cerebras.ts b/packages/core/src/plugin/provider/cerebras.ts index 20e724d707c..42fea46550a 100644 --- a/packages/core/src/plugin/provider/cerebras.ts +++ b/packages/core/src/plugin/provider/cerebras.ts @@ -1,15 +1,16 @@ import { Effect } from "effect" import { define } from "@opencode-ai/plugin/v2/effect/plugin" +import { ProviderV2 } from "../../provider" export const CerebrasPlugin = define({ id: "opencode.provider.cerebras", effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/cerebras") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/cerebras") continue evt.provider.update(item.provider.id, (provider) => { - provider.request.headers["X-Cerebras-3rd-Party-Integration"] = "opencode" + provider.headers = { ...provider.headers, "X-Cerebras-3rd-Party-Integration": "opencode" } }) } }) diff --git a/packages/core/src/plugin/provider/cloudflare-workers-ai.ts b/packages/core/src/plugin/provider/cloudflare-workers-ai.ts index b2db49e4dbe..9b4558b5d17 100644 --- a/packages/core/src/plugin/provider/cloudflare-workers-ai.ts +++ b/packages/core/src/plugin/provider/cloudflare-workers-ai.ts @@ -13,10 +13,10 @@ export const CloudflareWorkersAIPlugin = define({ const item = evt.provider.get(providerID) if (!item) return evt.provider.update(item.provider.id, (provider) => { - if (provider.api.type !== "aisdk") return - if (provider.api.url) return - const accountId = resolveAccountId(provider.request.body) - if (accountId) provider.api.url = workersEndpoint(accountId) + if (!ProviderV2.isAISDK(provider.package)) return + if (typeof provider.settings?.baseURL === "string") return + const accountId = resolveAccountId(provider.settings ?? {}) + if (accountId) provider.settings = { ...provider.settings, baseURL: workersEndpoint(accountId) } }) }) yield* ctx.aisdk.sdk( @@ -25,7 +25,7 @@ export const CloudflareWorkersAIPlugin = define({ if (evt.package !== "@ai-sdk/openai-compatible") return const accountId = resolveAccountId(evt.options) - if (!hasWorkersEndpoint(evt.model.api) && !accountId) return + if (!hasWorkersEndpoint(evt.model) && !accountId) return const mod = yield* Effect.promise(() => import("@ai-sdk/openai-compatible")) evt.sdk = mod.createOpenAICompatible( sdkOptions({ @@ -38,7 +38,7 @@ export const CloudflareWorkersAIPlugin = define({ yield* ctx.aisdk.language( Effect.fn(function* (evt) { if (evt.model.providerID !== providerID) return - evt.language = evt.sdk.languageModel(evt.model.api.id) + evt.language = evt.sdk.languageModel(evt.model.modelID ?? evt.model.id) }), ) }), @@ -52,8 +52,11 @@ function workersEndpoint(accountId: string) { return `https://api.cloudflare.com/client/v4/accounts/${accountId}/ai/v1` } -function hasWorkersEndpoint(api: ProviderV2.Api) { - return api.type === "aisdk" && Boolean(api.url) +function hasWorkersEndpoint(model: { + readonly package?: string + readonly settings?: Readonly> +}) { + return ProviderV2.isAISDK(model.package) && typeof model.settings?.baseURL === "string" } function sdkOptions(options: Record) { diff --git a/packages/core/src/plugin/provider/github-copilot.ts b/packages/core/src/plugin/provider/github-copilot.ts index 2a4881edc0f..d9a50ab097a 100644 --- a/packages/core/src/plugin/provider/github-copilot.ts +++ b/packages/core/src/plugin/provider/github-copilot.ts @@ -34,12 +34,11 @@ export const GithubCopilotPlugin = define({ Effect.fn(function* (evt) { if (evt.model.providerID !== ProviderV2.ID.githubCopilot) return if (evt.sdk.responses === undefined && evt.sdk.chat === undefined) { - evt.language = evt.sdk.languageModel(evt.model.api.id) + evt.language = evt.sdk.languageModel(evt.model.modelID ?? evt.model.id) return } - evt.language = shouldUseResponses(evt.model.api.id) - ? evt.sdk.responses(evt.model.api.id) - : evt.sdk.chat(evt.model.api.id) + const id = evt.model.modelID ?? evt.model.id + evt.language = shouldUseResponses(id) ? evt.sdk.responses(id) : evt.sdk.chat(id) }), ) }), diff --git a/packages/core/src/plugin/provider/gitlab.ts b/packages/core/src/plugin/provider/gitlab.ts index 5cd4b948580..1a8a4a1231f 100644 --- a/packages/core/src/plugin/provider/gitlab.ts +++ b/packages/core/src/plugin/provider/gitlab.ts @@ -36,26 +36,24 @@ export const GitLabPlugin = define({ if (evt.model.providerID !== ProviderV2.ID.gitlab) return const featureFlags = typeof evt.options.featureFlags === "object" && evt.options.featureFlags ? evt.options.featureFlags : {} - if (evt.model.api.id.startsWith("duo-workflow-")) { + const id = evt.model.modelID ?? evt.model.id + if (id.startsWith("duo-workflow-")) { const gitlab = yield* Effect.promise(() => import("gitlab-ai-provider")).pipe(Effect.orDie) const workflowRef = - typeof evt.model.request.body.workflowRef === "string" ? evt.model.request.body.workflowRef : undefined + typeof evt.model.settings?.workflowRef === "string" ? evt.model.settings.workflowRef : undefined const workflowDefinition = - typeof evt.model.request.body.workflowDefinition === "string" - ? evt.model.request.body.workflowDefinition + typeof evt.model.settings?.workflowDefinition === "string" + ? evt.model.settings.workflowDefinition : undefined - const language = evt.sdk.workflowChat( - gitlab.isWorkflowModel(evt.model.api.id) ? evt.model.api.id : "duo-workflow", - { - featureFlags, - workflowDefinition, - }, - ) + const language = evt.sdk.workflowChat(gitlab.isWorkflowModel(id) ? id : "duo-workflow", { + featureFlags, + workflowDefinition, + }) if (workflowRef) language.selectedModelRef = workflowRef evt.language = language return } - evt.language = evt.sdk.agenticChat(evt.model.api.id, { + evt.language = evt.sdk.agenticChat(id, { aiGatewayHeaders: evt.options.aiGatewayHeaders, featureFlags, }) diff --git a/packages/core/src/plugin/provider/google-vertex.ts b/packages/core/src/plugin/provider/google-vertex.ts index 630e353ef0f..2c307a87256 100644 --- a/packages/core/src/plugin/provider/google-vertex.ts +++ b/packages/core/src/plugin/provider/google-vertex.ts @@ -59,25 +59,28 @@ export const GoogleVertexPlugin = define({ effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue if ( - item.provider.api.package !== "@ai-sdk/google-vertex" && + ProviderV2.packageName(item.provider.package) !== "@ai-sdk/google-vertex" && !( item.provider.id === ProviderV2.ID.googleVertex && - item.provider.api.package.includes("@ai-sdk/openai-compatible") + ProviderV2.packageName(item.provider.package)?.includes("@ai-sdk/openai-compatible") ) ) continue - const project = resolveProject(item.provider.request.body) - const location = String(resolveLocation(item.provider.request.body)) + const project = resolveProject(item.provider.settings ?? {}) + const location = String(resolveLocation(item.provider.settings ?? {})) evt.provider.update(item.provider.id, (provider) => { - if (project) provider.request.body.project = project - provider.request.body.location = location - if (provider.api.type === "aisdk" && provider.api.url) { - provider.api.url = replaceVertexVars(provider.api.url, project, location) - } - if (provider.api.type === "aisdk" && provider.api.package.includes("@ai-sdk/openai-compatible")) { - provider.request.body.fetch = authFetch(provider.request.body.fetch) + provider.settings = { + ...provider.settings, + ...(project ? { project } : {}), + location, + ...(typeof provider.settings?.baseURL === "string" + ? { baseURL: replaceVertexVars(provider.settings.baseURL, project, location) } + : {}), + ...(ProviderV2.packageName(provider.package)?.includes("@ai-sdk/openai-compatible") + ? { fetch: authFetch(provider.settings?.fetch) } + : {}), } }) } @@ -104,7 +107,7 @@ export const GoogleVertexPlugin = define({ yield* ctx.aisdk.language( Effect.fn(function* (evt) { if (evt.model.providerID !== ProviderV2.ID.googleVertex) return - evt.language = evt.sdk.languageModel(String(evt.model.api.id).trim()) + evt.language = evt.sdk.languageModel(String(evt.model.modelID ?? evt.model.id).trim()) }), ) }), @@ -115,21 +118,20 @@ export const GoogleVertexAnthropicPlugin = define({ effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/google-vertex/anthropic") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/google-vertex/anthropic") continue const project = - item.provider.request.body.project ?? + item.provider.settings?.project ?? process.env.GOOGLE_CLOUD_PROJECT ?? process.env.GCP_PROJECT ?? process.env.GCLOUD_PROJECT const location = - item.provider.request.body.location ?? + item.provider.settings?.location ?? process.env.GOOGLE_CLOUD_LOCATION ?? process.env.VERTEX_LOCATION ?? "global" evt.provider.update(item.provider.id, (provider) => { - if (project) provider.request.body.project = project - provider.request.body.location = location + provider.settings = { ...provider.settings, ...(project ? { project } : {}), location } }) } }) @@ -162,7 +164,7 @@ export const GoogleVertexAnthropicPlugin = define({ yield* ctx.aisdk.language( Effect.fn(function* (evt) { if (evt.model.providerID !== ProviderV2.ID.make("google-vertex-anthropic")) return - evt.language = evt.sdk.languageModel(String(evt.model.api.id).trim()) + evt.language = evt.sdk.languageModel(String(evt.model.modelID ?? evt.model.id).trim()) }), ) }), diff --git a/packages/core/src/plugin/provider/kilo.ts b/packages/core/src/plugin/provider/kilo.ts index d901474ef25..b1c53fca908 100644 --- a/packages/core/src/plugin/provider/kilo.ts +++ b/packages/core/src/plugin/provider/kilo.ts @@ -1,17 +1,17 @@ import { Effect } from "effect" import { define } from "@opencode-ai/plugin/v2/effect/plugin" +import { ProviderV2 } from "../../provider" export const KiloPlugin = define({ id: "opencode.provider.kilo", effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/openai-compatible") continue - if (item.provider.api.url !== "https://api.kilo.ai/api/gateway") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/openai-compatible") continue + if (item.provider.settings?.baseURL !== "https://api.kilo.ai/api/gateway") continue evt.provider.update(item.provider.id, (provider) => { - provider.request.headers["HTTP-Referer"] = "https://opencode.ai/" - provider.request.headers["X-Title"] = "opencode" + provider.headers = { ...provider.headers, "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode" } }) } }) diff --git a/packages/core/src/plugin/provider/llmgateway.ts b/packages/core/src/plugin/provider/llmgateway.ts index 68c319b6730..88a597164b4 100644 --- a/packages/core/src/plugin/provider/llmgateway.ts +++ b/packages/core/src/plugin/provider/llmgateway.ts @@ -1,6 +1,7 @@ import { Effect } from "effect" import { define } from "@opencode-ai/plugin/v2/effect/plugin" import { Integration } from "../../integration" +import { ProviderV2 } from "../../provider" export const LLMGatewayPlugin = define({ id: "opencode.provider.llmgateway", @@ -10,14 +11,17 @@ export const LLMGatewayPlugin = define({ yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { if (item.provider.disabled) continue - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/openai-compatible") continue - if (item.provider.api.url !== "https://api.llmgateway.io/v1") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/openai-compatible") continue + if (item.provider.settings?.baseURL !== "https://api.llmgateway.io/v1") continue if (!configured.has(Integration.ID.make(item.provider.id))) continue evt.provider.update(item.provider.id, (provider) => { - provider.request.headers["HTTP-Referer"] = "https://opencode.ai/" - provider.request.headers["X-Title"] = "opencode" - provider.request.headers["X-Source"] = "opencode" + provider.headers = { + ...provider.headers, + "HTTP-Referer": "https://opencode.ai/", + "X-Title": "opencode", + "X-Source": "opencode", + } }) } }) diff --git a/packages/core/src/plugin/provider/nvidia.ts b/packages/core/src/plugin/provider/nvidia.ts index 4597f3070ab..7363e88f52a 100644 --- a/packages/core/src/plugin/provider/nvidia.ts +++ b/packages/core/src/plugin/provider/nvidia.ts @@ -1,18 +1,22 @@ import { Effect } from "effect" import { define } from "@opencode-ai/plugin/v2/effect/plugin" +import { ProviderV2 } from "../../provider" export const NvidiaPlugin = define({ id: "opencode.provider.nvidia", effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/openai-compatible") continue - if (item.provider.api.url !== "https://integrate.api.nvidia.com/v1") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/openai-compatible") continue + if (item.provider.settings?.baseURL !== "https://integrate.api.nvidia.com/v1") continue evt.provider.update(item.provider.id, (provider) => { - provider.request.headers["HTTP-Referer"] = "https://opencode.ai/" - provider.request.headers["X-Title"] = "opencode" - provider.request.headers["X-BILLING-INVOKE-ORIGIN"] ??= "OpenCode" + provider.headers = { + ...provider.headers, + "HTTP-Referer": "https://opencode.ai/", + "X-Title": "opencode", + "X-BILLING-INVOKE-ORIGIN": provider.headers?.["X-BILLING-INVOKE-ORIGIN"] ?? "OpenCode", + } }) } }) diff --git a/packages/core/src/plugin/provider/openai.ts b/packages/core/src/plugin/provider/openai.ts index 1b27511e495..72fe8ed6469 100644 --- a/packages/core/src/plugin/provider/openai.ts +++ b/packages/core/src/plugin/provider/openai.ts @@ -178,8 +178,8 @@ export const OpenAIPlugin = define({ }) yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/openai") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/openai") continue if (!item.models.has(ModelV2.ID.make("gpt-5-chat-latest"))) continue evt.model.update(item.provider.id, ModelV2.ID.make("gpt-5-chat-latest"), (model) => { // OpenAIPlugin sends OpenAI models through Responses; this alias is a @@ -194,7 +194,7 @@ export const OpenAIPlugin = define({ // ChatGPT-plan tokens only authorize codex-eligible models, and the // subscription covers usage, so hide the rest and zero the cost. evt.model.update(item.provider.id, model.id, (draft) => { - if (!OpenAICodex.eligible(draft.api.id)) { + if (!OpenAICodex.eligible(draft.modelID ?? draft.id)) { draft.enabled = false return } @@ -220,7 +220,7 @@ export const OpenAIPlugin = define({ yield* ctx.aisdk.language( Effect.fn(function* (evt) { if (evt.model.providerID !== ProviderV2.ID.openai) return - evt.language = evt.sdk.responses(evt.model.api.id) + evt.language = evt.sdk.responses(evt.model.modelID ?? evt.model.id) }), ) }), diff --git a/packages/core/src/plugin/provider/opencode.ts b/packages/core/src/plugin/provider/opencode.ts index 1316c3e4d05..58690df0b28 100644 --- a/packages/core/src/plugin/provider/opencode.ts +++ b/packages/core/src/plugin/provider/opencode.ts @@ -112,45 +112,43 @@ export const OpencodePlugin = define { provider.integrationID = Integration.ID.make("opencode") if (item.name !== undefined) provider.name = item.name - provider.api = item.npm - ? { type: "aisdk", package: item.npm, url: item.api } - : { type: "native", url: item.api, settings: {} } - Object.assign(provider.request.headers, item.options?.headers) - Object.assign(provider.request.body, withoutCredentials(item.options)) + provider.package = item.npm ? ProviderV2.aisdk(item.npm) : "" + provider.settings = { + ...provider.settings, + ...withoutCredentials(item.options), + ...(item.api ? { baseURL: item.api } : {}), + } + provider.headers = { ...provider.headers, ...item.options?.headers } }) for (const [modelID, config] of Object.entries(item.models ?? {})) { catalog.model.update(providerID, modelID, (model) => { if (config.family !== undefined) model.family = config.family if (config.name !== undefined) model.name = config.name - if (config.id !== undefined) model.api.id = config.id + if (config.id !== undefined) model.modelID = config.id if (config.provider !== undefined) { - model.api = config.provider.npm - ? { - id: model.api.id, - type: "aisdk", - package: config.provider.npm, - url: config.provider.api, - } - : { id: model.api.id, type: "native", url: config.provider.api, settings: {} } + model.package = config.provider.npm ? ProviderV2.aisdk(config.provider.npm) : undefined + if (config.provider.api) model.settings = { ...model.settings, baseURL: config.provider.api } } if (config.tool_call !== undefined) model.capabilities.tools = config.tool_call if (config.modalities?.input !== undefined) model.capabilities.input = [...config.modalities.input] if (config.modalities?.output !== undefined) model.capabilities.output = [...config.modalities.output] - const packageName = config.provider?.npm ?? item.npm - const lowerer = ConfigProviderOptionsV1.get(packageName) - Object.assign(model.request.headers, config.headers) - Object.assign(model.request.body, lowerer.request(withoutCredentials(config.options))) + model.headers = { ...model.headers, ...config.headers } + model.settings = { ...model.settings, ...ConfigProviderOptionsV1.model(withoutCredentials(config.options)) } if (config.variants !== undefined) { + model.variants ??= [] for (const [id, options] of Object.entries(config.variants)) { const variantID = ModelV2.VariantID.make(id) let existing = model.variants.find((item) => item.id === variantID) if (!existing) { - existing = { id: variantID, settings: {}, headers: {}, body: {} } + existing = { id: variantID } model.variants.push(existing) } - Object.assign(existing.headers, options.headers) - Object.assign(existing.body, lowerer.request(withoutCredentials(options))) + existing.headers = { ...existing.headers, ...options.headers } + existing.settings = { + ...existing.settings, + ...ConfigProviderOptionsV1.model(withoutCredentials(options)), + } } } if (config.release_date !== undefined) { @@ -169,9 +167,9 @@ export const OpencodePlugin = define { - if (!hasKey) provider.request.body.apiKey = "public" + if (!hasKey) provider.settings = { ...provider.settings, apiKey: "public" } }) if (hasKey) return for (const model of item.models.values()) { diff --git a/packages/core/src/plugin/provider/openrouter.ts b/packages/core/src/plugin/provider/openrouter.ts index a255844fdb0..c27cc30207d 100644 --- a/packages/core/src/plugin/provider/openrouter.ts +++ b/packages/core/src/plugin/provider/openrouter.ts @@ -1,5 +1,6 @@ import { Effect } from "effect" import { ModelV2 } from "../../model" +import { ProviderV2 } from "../../provider" import { define } from "@opencode-ai/plugin/v2/effect/plugin" export const OpenRouterPlugin = define({ @@ -7,11 +8,10 @@ export const OpenRouterPlugin = define({ effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@openrouter/ai-sdk-provider") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@openrouter/ai-sdk-provider") continue evt.provider.update(item.provider.id, (provider) => { - provider.request.headers["HTTP-Referer"] = "https://opencode.ai/" - provider.request.headers["X-Title"] = "opencode" + provider.headers = { ...provider.headers, "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode" } }) for (const modelID of [ModelV2.ID.make("gpt-5-chat-latest"), ModelV2.ID.make("openai/gpt-5-chat")]) { if (!item.models.has(modelID)) continue diff --git a/packages/core/src/plugin/provider/sap-ai-core.ts b/packages/core/src/plugin/provider/sap-ai-core.ts index ede4e31d400..4a8c26e82a8 100644 --- a/packages/core/src/plugin/provider/sap-ai-core.ts +++ b/packages/core/src/plugin/provider/sap-ai-core.ts @@ -40,7 +40,7 @@ export const SapAICorePlugin = define({ yield* ctx.aisdk.language( Effect.fn(function* (evt) { if (evt.model.providerID !== ProviderV2.ID.make("sap-ai-core")) return - evt.language = evt.sdk(evt.model.api.id) + evt.language = evt.sdk(evt.model.modelID ?? evt.model.id) }), ) }), diff --git a/packages/core/src/plugin/provider/vercel.ts b/packages/core/src/plugin/provider/vercel.ts index 0df949b1bed..70a27c8f672 100644 --- a/packages/core/src/plugin/provider/vercel.ts +++ b/packages/core/src/plugin/provider/vercel.ts @@ -1,16 +1,16 @@ import { Effect } from "effect" import { define } from "@opencode-ai/plugin/v2/effect/plugin" +import { ProviderV2 } from "../../provider" export const VercelPlugin = define({ id: "opencode.provider.vercel", effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/vercel") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/vercel") continue evt.provider.update(item.provider.id, (provider) => { - provider.request.headers["http-referer"] = "https://opencode.ai/" - provider.request.headers["x-title"] = "opencode" + provider.headers = { ...provider.headers, "http-referer": "https://opencode.ai/", "x-title": "opencode" } }) } }) diff --git a/packages/core/src/plugin/provider/xai.ts b/packages/core/src/plugin/provider/xai.ts index 76ec1df1a7e..fb1d33e86ec 100644 --- a/packages/core/src/plugin/provider/xai.ts +++ b/packages/core/src/plugin/provider/xai.ts @@ -15,7 +15,7 @@ export const XAIPlugin = define({ yield* ctx.aisdk.language( Effect.fn(function* (evt) { if (evt.model.providerID !== ProviderV2.ID.make("xai")) return - evt.language = evt.sdk.responses(evt.model.api.id) + evt.language = evt.sdk.responses(evt.model.modelID ?? evt.model.id) }), ) }), diff --git a/packages/core/src/plugin/provider/zenmux.ts b/packages/core/src/plugin/provider/zenmux.ts index 099a3affca8..44619a1ac5b 100644 --- a/packages/core/src/plugin/provider/zenmux.ts +++ b/packages/core/src/plugin/provider/zenmux.ts @@ -1,17 +1,21 @@ import { Effect } from "effect" import { define } from "@opencode-ai/plugin/v2/effect/plugin" +import { ProviderV2 } from "../../provider" export const ZenmuxPlugin = define({ id: "opencode.provider.zenmux", effect: Effect.fn(function* (ctx) { yield* ctx.catalog.transform((evt) => { for (const item of evt.provider.list()) { - if (item.provider.api.type !== "aisdk") continue - if (item.provider.api.package !== "@ai-sdk/openai-compatible") continue - if (item.provider.api.url !== "https://zenmux.ai/api/v1") continue + if (!ProviderV2.isAISDK(item.provider.package)) continue + if (ProviderV2.packageName(item.provider.package) !== "@ai-sdk/openai-compatible") continue + if (item.provider.settings?.baseURL !== "https://zenmux.ai/api/v1") continue evt.provider.update(item.provider.id, (provider) => { - provider.request.headers["HTTP-Referer"] ??= "https://opencode.ai/" - provider.request.headers["X-Title"] ??= "opencode" + provider.headers = { + "HTTP-Referer": "https://opencode.ai/", + "X-Title": "opencode", + ...provider.headers, + } }) } }) diff --git a/packages/core/src/plugin/variant.ts b/packages/core/src/plugin/variant.ts index 499a2a32bfc..55c9667f9e8 100644 --- a/packages/core/src/plugin/variant.ts +++ b/packages/core/src/plugin/variant.ts @@ -1,8 +1,9 @@ export * as VariantPlugin from "./variant" -import type { ModelV2Info } from "@opencode-ai/sdk/v2/types" import { Effect } from "effect" import { define } from "@opencode-ai/plugin/v2/effect/plugin" +import { ModelV2 } from "../model" +import { ProviderV2 } from "../provider" export const Plugin = define({ id: "opencode.variant", @@ -11,14 +12,15 @@ export const Plugin = define({ for (const record of catalog.provider.list()) { for (const model of record.models.values()) { catalog.model.update(model.providerID, model.id, (draft) => { - const generated = generate(draft) + const generated = generate(draft, record.provider) if (generated.length === 0) return - const explicit = new Map(draft.variants.map((variant) => [variant.id, variant])) - const generatedIDs = new Set(generated.map((variant) => variant.id)) + const variants = draft.variants ?? [] + const explicit = new Map(variants.map((variant) => [variant.id, variant])) + const generatedIDs = new Set(generated.map((variant) => variant.id)) draft.variants = [ ...generated.map((variant) => explicit.get(variant.id) ?? variant), - ...draft.variants.filter((variant) => !generatedIDs.has(variant.id)), + ...variants.filter((variant) => !generatedIDs.has(variant.id)), ] }) } @@ -27,14 +29,16 @@ export const Plugin = define({ }), }) -export function generate(model: ModelV2Info): ModelV2Info["variants"] { - if (model.api.type !== "aisdk" || model.api.package !== "@ai-sdk/openai-compatible") return [] - const ids = `${model.id} ${model.api.id}`.toLowerCase() +export function generate( + model: { readonly id: string; readonly modelID?: string; readonly package?: string }, + provider?: { readonly package: string }, +): NonNullable { + const packageName = model.package ?? provider?.package + if (!ProviderV2.isAISDK(packageName) || ProviderV2.packageName(packageName) !== "@ai-sdk/openai-compatible") return [] + const ids = `${model.id} ${model.modelID ?? ""}`.toLowerCase() if (!["glm-5.2", "glm-5-2", "glm-5p2"].some((name) => ids.includes(name))) return [] return ["high", "max"].map((id) => ({ - id, + id: ModelV2.VariantID.make(id), settings: { reasoningEffort: id }, - headers: {}, - body: {}, })) } diff --git a/packages/core/src/provider.ts b/packages/core/src/provider.ts index eb443ca7106..165ffa516be 100644 --- a/packages/core/src/provider.ts +++ b/packages/core/src/provider.ts @@ -1,20 +1,106 @@ export * as ProviderV2 from "./provider" -import { Types } from "effect" +import { Effect, Schema } from "effect" +import { pathToFileURL } from "url" import { Provider } from "@opencode-ai/schema/provider" +import type { ProviderPackageDefinition } from "@opencode-ai/llm" +import { Npm } from "./npm" +import type { DeepMutable } from "./schema" export const ID = Provider.ID export type ID = typeof ID.Type -export const AISDK = Provider.AISDK +export const AISDK_PREFIX = "aisdk:" +export const isAISDK = (value: string | undefined) => value?.startsWith(AISDK_PREFIX) ?? false +export const aisdk = (value: string) => (isAISDK(value) ? value : `${AISDK_PREFIX}${value}`) +export const packageName = (value: string | undefined) => { + if (value === undefined || !isAISDK(value)) return value + return value.slice(AISDK_PREFIX.length) +} -export const Native = Provider.Native +type Json = Schema.Schema.Type +const JsonRecord = Schema.Record(Schema.String, Schema.Json) +const decodeJsonRecord = Schema.decodeUnknownSync(JsonRecord) -export const Api = Provider.Api -export type Api = Provider.Api -export type MutableApi = T extends Api - ? Omit, "settings"> & (undefined extends T["settings"] ? { settings?: any } : { settings: any }) - : never +export class LoadError extends Schema.TaggedErrorClass()("ProviderV2.LoadError", { + package: Schema.String, + cause: Schema.Defect(), +}) {} +export type ProviderPackage = ProviderPackageDefinition + +const packages = new Map>() + +export const loadPackage = Effect.fn("ProviderV2.loadPackage")(function* (specifier: string, npm?: Npm.Interface) { + const resolved = yield* Effect.sync(() => { + if (specifier.startsWith("file://") || specifier.startsWith("@opencode-ai/llm/")) return specifier + try { + return import.meta.resolve(specifier) + } catch { + return undefined + } + }) + if (resolved) return yield* importPackage(specifier, resolved) + if (!npm) { + return yield* new LoadError({ + package: specifier, + cause: new Error(`Provider package ${specifier} is not installed`), + }) + } + const parts = specifier.split("/") + const root = specifier.startsWith("@") ? parts.slice(0, 2).join("/") : (parts[0] ?? specifier) + const installed = yield* npm.add(root).pipe(Effect.mapError((cause) => new LoadError({ package: specifier, cause }))) + const entrypoint = yield* Effect.try({ + try: () => import.meta.resolve(specifier, pathToFileURL(`${installed.directory}/`).href), + catch: (cause) => new LoadError({ package: specifier, cause }), + }) + return yield* importPackage(specifier, entrypoint) +}) + +export function mergeOverlay( + base: Readonly> | undefined, + overlay: Readonly> | undefined, +): Record | undefined { + if (base === undefined) return overlay && decodeJsonRecord({ ...overlay }) + if (overlay === undefined) return decodeJsonRecord({ ...base }) + return decodeJsonRecord( + Object.fromEntries( + new Set([...Object.keys(base), ...Object.keys(overlay)]).values().map((key): [string, unknown] => { + const left = base[key] + const right = overlay[key] + if (right === undefined) return [key, left] + if ( + typeof left === "object" && + left !== null && + !Array.isArray(left) && + typeof right === "object" && + right !== null && + !Array.isArray(right) + ) + return [ + key, + mergeOverlay(left as Readonly>, right as Readonly>) ?? {}, + ] + return [key, right] + }), + ), + ) +} + +export function mergeHeaders( + base: Readonly> | undefined, + overlay: Readonly> | undefined, +) { + if (base === undefined) return overlay && { ...overlay } + if (overlay === undefined) return { ...base } + return Object.fromEntries( + [...Object.entries(base), ...Object.entries(overlay)] + .reduce((result, entry) => { + result.set(entry[0].toLowerCase(), entry) + return result + }, new Map()) + .values(), + ) +} export const Request = Provider.Request export type Request = Provider.Request @@ -25,9 +111,24 @@ export type Settings = Provider.Settings export const Info = Provider.Info export type Info = Provider.Info -export type MutableRequest = Types.DeepMutable +export type MutableInfo = DeepMutable -export type MutableInfo = Omit, "api" | "request"> & { - api: MutableApi - request: MutableRequest -} +const importPackage = Effect.fn("ProviderV2.importPackage")(function* (specifier: string, entrypoint: string) { + const module = yield* Effect.tryPromise({ + try: () => { + const existing = packages.get(entrypoint) + if (existing) return existing + const loaded = import(entrypoint) + packages.set(entrypoint, loaded) + return loaded + }, + catch: (cause) => new LoadError({ package: specifier, cause }), + }) + if (typeof module !== "object" || module === null || typeof (module as { model?: unknown }).model !== "function") { + return yield* new LoadError({ + package: specifier, + cause: new Error(`Provider package ${specifier} does not export model(modelID, settings)`), + }) + } + return module as ProviderPackageDefinition +}) diff --git a/packages/core/src/session/runner/llm.ts b/packages/core/src/session/runner/llm.ts index 40d43a7bfdc..4befc88331f 100644 --- a/packages/core/src/session/runner/llm.ts +++ b/packages/core/src/session/runner/llm.ts @@ -213,7 +213,10 @@ const layer = Layer.effect( ] .filter((part): part is string => part !== undefined && part.length > 0) .map(SystemPart.make), - messages: [...toLLMMessages(context, model), ...(isLastStep ? [Message.assistant(MAX_STEPS_PROMPT)] : [])], + messages: [ + ...toLLMMessages(context, resolved.ref), + ...(isLastStep ? [Message.assistant(MAX_STEPS_PROMPT)] : []), + ], tools: toolMaterialization?.definitions ?? [], toolChoice: isLastStep ? "none" : undefined, }) diff --git a/packages/core/src/session/runner/model.ts b/packages/core/src/session/runner/model.ts index 2b81e609ea5..6cc0d0845d5 100644 --- a/packages/core/src/session/runner/model.ts +++ b/packages/core/src/session/runner/model.ts @@ -1,7 +1,7 @@ export * as SessionRunnerModel from "./model" import { makeLocationNode } from "../../effect/app-node" -import { type Model } from "@opencode-ai/llm" +import { Model } from "@opencode-ai/llm" // ast-grep-ignore: no-star-import import * as AnthropicMessages from "@opencode-ai/llm/protocols/anthropic-messages" // ast-grep-ignore: no-star-import @@ -11,10 +11,12 @@ import * as OpenAIResponses from "@opencode-ai/llm/protocols/openai-responses" import { Auth, type AnyRoute } from "@opencode-ai/llm/route" import { Context, Effect, Layer, Schema } from "effect" import { produce } from "immer" +import { AISDK } from "../../aisdk" import { Catalog } from "../../catalog" import { Credential } from "../../credential" import { Integration } from "../../integration" import { ModelV2 } from "../../model" +import { Npm } from "../../npm" import { OpenAICodex } from "../../plugin/provider/openai-codex" import { ProviderV2 } from "../../provider" import { SessionSchema } from "../schema" @@ -55,16 +57,16 @@ export class VariantUnavailableError extends Schema.TaggedErrorClass()( - "SessionRunnerModel.UnsupportedApiError", +export class UnsupportedPackageError extends Schema.TaggedErrorClass()( + "SessionRunnerModel.UnsupportedPackageError", { providerID: ProviderV2.ID, modelID: ModelV2.ID, - api: Schema.String, + package: Schema.String, }, ) { override get message() { - return `Unsupported API for ${this.providerID}/${this.modelID}: ${this.api}` + return `Unsupported package for ${this.providerID}/${this.modelID}: ${this.package}` } } @@ -72,7 +74,7 @@ export type Error = | ModelNotSelectedError | ModelUnavailableError | VariantUnavailableError - | UnsupportedApiError + | UnsupportedPackageError | Integration.AuthorizationError export interface Resolved { @@ -104,41 +106,50 @@ export const resolved = (model: Model, variant?: ModelV2.VariantID): Resolved => const apiKey = (model: ModelV2.Info, credential?: Credential.Value) => { if (credential?.type === "key") return Auth.value(credential.key) if (credential?.type === "oauth") return Auth.value(credential.access) - const value = model.request.body.apiKey ?? model.api.settings?.apiKey + const value = model.settings?.apiKey if (typeof value === "string") return Auth.value(value) } -const withDefaults = (model: ModelV2.Info, route: AnyRoute) => { - const body = model.request.body - const httpBody = Object.hasOwn(body, "apiKey") - ? Object.fromEntries(Object.entries(body).filter(([key]) => key !== "apiKey")) - : body - return route.with({ +const withDefaults = (model: ModelV2.Info, route: AnyRoute) => + route.with({ provider: model.providerID, - endpoint: model.api.url === undefined ? undefined : { baseURL: model.api.url }, - headers: model.request.headers, + endpoint: typeof model.settings?.baseURL === "string" ? { baseURL: model.settings.baseURL } : undefined, + headers: providerHeaders(model), providerOptions: providerOptions(model), - http: { body: httpBody }, + http: model.body === undefined ? undefined : { body: model.body }, limits: { context: model.limit.context, output: model.limit.output }, }) + +const providerHeaders = (model: ModelV2.Info) => { + const packageName = ProviderV2.packageName(model.package) + const generated = new Map() + if (packageName === "@ai-sdk/openai" && typeof model.settings?.organization === "string") + generated.set("OpenAI-Organization", model.settings.organization) + if (packageName === "@ai-sdk/openai" && typeof model.settings?.project === "string") + generated.set("OpenAI-Project", model.settings.project) + if (packageName === "@ai-sdk/anthropic" && typeof model.settings?.authToken === "string") + generated.set("Authorization", `Bearer ${model.settings.authToken}`) + return ProviderV2.mergeHeaders(generated.size === 0 ? undefined : Object.fromEntries(generated), model.headers) } const providerOptions = ( model: ModelV2.Info, ): { readonly [key: string]: { readonly [key: string]: unknown } } | undefined => { - if (Object.keys(model.request.settings).length === 0) return undefined - if (model.api.type !== "aisdk") return undefined - if (model.api.package === "@ai-sdk/openai") return { openai: model.request.settings } - if (model.api.package === "@ai-sdk/anthropic") return { anthropic: model.request.settings } - if (model.api.package === "@ai-sdk/openai-compatible") return { openai: model.request.settings } + if (!ProviderV2.isAISDK(model.package) || model.settings === undefined) return undefined + const { apiKey: _, baseURL: _baseURL, ...settings } = model.settings + if (Object.keys(settings).length === 0) return undefined + const packageName = ProviderV2.packageName(model.package) + if (packageName === "@ai-sdk/openai") return { openai: settings } + if (packageName === "@ai-sdk/anthropic") return { anthropic: settings } + if (packageName === "@ai-sdk/openai-compatible") return { openai: settings } } export const withVariant = ( model: ModelV2.Info, variantID: ModelV2.VariantID | undefined, ): Effect.Effect => { - const id = variantID === "default" || variantID === undefined ? model.request.variant : variantID - const variant = model.variants.find((item) => item.id === id) + const id = variantID === "default" ? undefined : variantID + const variant = model.variants?.find((item) => item.id === id) if (!variant && variantID !== undefined && variantID !== "default") return Effect.fail( new VariantUnavailableError({ @@ -150,81 +161,140 @@ export const withVariant = ( return Effect.succeed( variant ? produce(model, (draft) => { - Object.assign(draft.request.settings, variant.settings) - Object.assign(draft.request.headers, variant.headers) - Object.assign(draft.request.body, variant.body) + draft.settings = ProviderV2.mergeOverlay(draft.settings, variant.settings) + draft.headers = ProviderV2.mergeHeaders(draft.headers, variant.headers) + draft.body = ProviderV2.mergeOverlay(draft.body, variant.body) }) : model, ) } -const apiName = (model: ModelV2.Info) => - model.api.type === "aisdk" ? `${model.api.type}:${model.api.package}` : model.api.type +export interface Dependencies { + readonly loadPackage?: (specifier: string) => Effect.Effect + readonly loadAISDK?: (model: ModelV2.Info) => Effect.Effect +} export const fromCatalogModel = ( model: ModelV2.Info, credential?: Credential.Value, -): Effect.Effect => { + dependencies: Dependencies = {}, +): Effect.Effect => { const resolved = credential?.type !== "key" || credential.metadata === undefined ? model : produce(model, (draft) => { - Object.assign(draft.request.body, credential.metadata) + draft.body = ProviderV2.mergeOverlay(draft.body, credential.metadata) }) + const packageName = ProviderV2.packageName(resolved.package) const key = apiKey(resolved, credential) - if (resolved.api.type === "aisdk" && resolved.api.package === "@ai-sdk/openai") { - // ChatGPT-plan OAuth tokens are not API-key credentials: the public API rejects - // them, so requests must target the codex backend with the account header. - if (OpenAICodex.isChatGPT(credential)) { - const account = OpenAICodex.accountID(credential) - return Effect.succeed( - withDefaults(resolved, OpenAIResponses.route) - .with({ - endpoint: { baseURL: OpenAICodex.baseURL }, - auth: (key === undefined ? Auth.none : Auth.bearer(key)).andThen( - account === undefined ? Auth.none : Auth.headers({ "chatgpt-account-id": account }), - ), - }) - .model({ id: resolved.api.id }), - ) - } + + if ( + OpenAICodex.isChatGPT(credential) && + !ProviderV2.isAISDK(resolved.package) && + isNativeOpenAI(resolved.package) + ) { + return Effect.succeed(codexModel(resolved, credential, key)) + } + + if (ProviderV2.isAISDK(resolved.package) && packageName === "@ai-sdk/openai") { + if (OpenAICodex.isChatGPT(credential)) return Effect.succeed(codexModel(resolved, credential, key)) return Effect.succeed( withDefaults(resolved, OpenAIResponses.route) .with({ auth: key === undefined ? Auth.none : Auth.bearer(key) }) - .model({ id: resolved.api.id }), + .model({ id: resolved.modelID ?? resolved.id }), ) } - if (resolved.api.type === "aisdk" && resolved.api.package === "@ai-sdk/anthropic") { + if (ProviderV2.isAISDK(resolved.package) && packageName === "@ai-sdk/anthropic") { return Effect.succeed( withDefaults(resolved, AnthropicMessages.route) .with({ auth: key === undefined ? Auth.none : Auth.header("x-api-key", key) }) - .model({ id: resolved.api.id }), + .model({ id: resolved.modelID ?? resolved.id }), ) } - if (resolved.api.type === "aisdk" && resolved.api.package === "@ai-sdk/openai-compatible" && resolved.api.url) { + if ( + ProviderV2.isAISDK(resolved.package) && + packageName === "@ai-sdk/openai-compatible" && + typeof resolved.settings?.baseURL === "string" + ) { return Effect.succeed( withDefaults(resolved, OpenAICompatibleChat.route) .with({ auth: key === undefined ? Auth.none : Auth.bearer(key) }) - .model({ id: resolved.api.id }), + .model({ id: resolved.modelID ?? resolved.id }), ) } - return Effect.fail( - new UnsupportedApiError({ - providerID: resolved.providerID, - modelID: resolved.id, - api: apiName(resolved), - }), - ) + if (ProviderV2.isAISDK(resolved.package)) { + if (!dependencies.loadAISDK) return Effect.fail(unsupported(resolved)) + const runtime = produce(resolved, (draft) => { + draft.settings = ProviderV2.mergeOverlay(draft.settings, { + ...(credential?.type === "key" ? { apiKey: credential.key } : {}), + ...(credential?.type === "oauth" ? { apiKey: credential.access } : {}), + ...credential?.metadata, + }) + }) + return dependencies.loadAISDK(runtime).pipe(Effect.mapError(() => unsupported(resolved))) + } + if (!resolved.package) return Effect.fail(unsupported(resolved)) + + const specifier = resolved.package + return Effect.gen(function* () { + const module = yield* (dependencies.loadPackage ?? ProviderV2.loadPackage)(specifier).pipe( + Effect.mapError(() => unsupported(resolved)), + ) + const settings = { + ...resolved.settings, + ...(credential?.type === "key" ? { apiKey: credential.key } : {}), + ...(credential?.type === "oauth" ? { apiKey: credential.access } : {}), + ...credential?.metadata, + headers: resolved.headers, + body: resolved.body, + limits: { context: resolved.limit.context, output: resolved.limit.output }, + } + return yield* Effect.try({ + try: () => + Model.update(module.model(resolved.modelID ?? resolved.id, settings), { provider: resolved.providerID }), + catch: () => unsupported(resolved), + }) + }) } -export const resolve = (session: SessionSchema.Info, model: ModelV2.Info, credential?: Credential.Value) => - withVariant(model, session.model?.variant).pipe(Effect.flatMap((model) => fromCatalogModel(model, credential))) +const isNativeOpenAI = (packageName: string | undefined) => + packageName === "@opencode-ai/llm/providers/openai" || + packageName?.startsWith("@opencode-ai/llm/providers/openai/") === true -export const supported = (model: ModelV2.Info) => - model.api.type === "aisdk" && - (model.api.package === "@ai-sdk/openai" || - model.api.package === "@ai-sdk/anthropic" || - (model.api.package === "@ai-sdk/openai-compatible" && model.api.url !== undefined)) +const codexModel = ( + model: ModelV2.Info, + credential: Credential.Value | undefined, + key: ReturnType | undefined, +) => { + const account = OpenAICodex.accountID(credential) + return withDefaults(model, OpenAIResponses.route) + .with({ + endpoint: { baseURL: OpenAICodex.baseURL }, + auth: (key === undefined ? Auth.none : Auth.bearer(key)).andThen( + account === undefined ? Auth.none : Auth.headers({ "chatgpt-account-id": account }), + ), + }) + .model({ id: model.modelID ?? model.id }) +} + +const unsupported = (model: ModelV2.Info) => + new UnsupportedPackageError({ + providerID: model.providerID, + modelID: model.id, + package: model.package ?? "unknown", + }) + +export const resolve = ( + session: SessionSchema.Info, + model: ModelV2.Info, + credential?: Credential.Value, + dependencies?: Dependencies, +) => + withVariant(model, session.model?.variant).pipe( + Effect.flatMap((model) => fromCatalogModel(model, credential, dependencies)), + ) + +export const supported = (model: ModelV2.Info) => Boolean(model.package) /** Resolves models from the catalog belonging to the current Location runtime. */ const layer = Layer.effect( @@ -232,6 +302,8 @@ const layer = Layer.effect( Effect.gen(function* () { const catalog = yield* Catalog.Service const integrations = yield* Integration.Service + const npm = yield* Npm.Service + const aisdk = yield* AISDK.Service return Service.of({ resolve: Effect.fn("SessionRunnerModel.resolve")(function* (session) { // Location plugins populate and filter the catalog asynchronously during layer startup. @@ -257,6 +329,10 @@ const layer = Layer.effect( session, selected, connection ? yield* integrations.connection.resolve(connection) : undefined, + { + loadPackage: (specifier) => ProviderV2.loadPackage(specifier, npm), + loadAISDK: (model) => aisdk.model(model), + }, ) return { model, @@ -271,4 +347,8 @@ const layer = Layer.effect( }), ) -export const node = makeLocationNode({ service: Service, layer, deps: [Catalog.node, Integration.node] }) +export const node = makeLocationNode({ + service: Service, + layer, + deps: [Catalog.node, Integration.node, Npm.node, AISDK.node], +}) diff --git a/packages/core/src/session/runner/to-llm-message.ts b/packages/core/src/session/runner/to-llm-message.ts index d2eaee413b6..0663ac8e6de 100644 --- a/packages/core/src/session/runner/to-llm-message.ts +++ b/packages/core/src/session/runner/to-llm-message.ts @@ -4,10 +4,10 @@ import { ToolOutput, ToolResultPart, type ContentPart, - type Model, type ProviderMetadata, } from "@opencode-ai/llm" import { Option, Schema } from "effect" +import type { ModelV2 } from "../../model" import { SessionMessage } from "../message" import type { FileAttachment } from "@opencode-ai/schema/prompt" @@ -88,9 +88,9 @@ const toolResult = (tool: SessionMessage.AssistantTool, providerMetadata: Provid } } -const assistant = (message: SessionMessage.Assistant, model: Model) => { +const assistant = (message: SessionMessage.Assistant, model: ModelV2.Ref) => { const sameModel = - String(message.model.providerID) === String(model.provider) && String(message.model.id) === String(model.id) + String(message.model.providerID) === String(model.providerID) && String(message.model.id) === String(model.id) const reuseProviderMetadata = sameModel && message.error === undefined const content = message.content.flatMap((item): ContentPart[] => { if (item.type === "text") return [{ type: "text", text: item.text }] @@ -133,7 +133,7 @@ const assistant = (message: SessionMessage.Assistant, model: Model) => { ] } -function toLLMMessage(message: SessionMessage.Message, model: Model): Message[] { +function toLLMMessage(message: SessionMessage.Message, model: ModelV2.Ref): Message[] { switch (message.type) { case "agent-switched": case "model-switched": @@ -197,5 +197,5 @@ ${message.recent} } /** Translate projected V2 Session history into canonical @opencode-ai/llm context. */ -export const toLLMMessages = (messages: readonly SessionMessage.Message[], model: Model) => +export const toLLMMessages = (messages: readonly SessionMessage.Message[], model: ModelV2.Ref) => messages.flatMap((message) => toLLMMessage(message, model)) diff --git a/packages/core/src/v1/config/migrate.ts b/packages/core/src/v1/config/migrate.ts index 046f29c4317..1e7e3464dc3 100644 --- a/packages/core/src/v1/config/migrate.ts +++ b/packages/core/src/v1/config/migrate.ts @@ -2,10 +2,12 @@ export * as ConfigMigrateV1 from "./migrate" import { ConfigV1 } from "./config" import { ConfigAgentV1 } from "./agent" +import { ConfigCommandV1 } from "./command" import { ConfigMCPV1 } from "./mcp" import { ConfigPermissionV1 } from "./permission" import { ConfigProviderV1 } from "./provider" import { ConfigProviderOptionsV1 } from "./provider-options" +import { ProviderV2 } from "../../provider" const keys = new Set([ "logLevel", @@ -48,7 +50,7 @@ export function migrate(info: typeof ConfigV1.Info.Type) { return { $schema: info.$schema, shell: info.shell, - model: info.model, + model: modelSelection(info.model), default_agent: info.default_agent, autoupdate: info.autoupdate, share: info.share ?? (info.autoshare ? "auto" : undefined), @@ -72,7 +74,7 @@ export function migrate(info: typeof ConfigV1.Info.Type) { buffer: info.compaction.reserved, }, skills: info.skills && [...(info.skills.paths ?? []), ...(info.skills.urls ?? [])], - commands: info.command, + commands: commands(info.command), instructions: info.instructions, references: info.references ?? info.reference, plugins: info.plugin?.map((plugin) => @@ -126,8 +128,7 @@ export function migrateAgent(info: ConfigAgentV1.Info) { ...(info.top_p === undefined ? {} : { top_p: info.top_p }), } return { - model: info.model, - variant: info.variant, + model: modelSelection(info.model, info.variant), request: Object.keys(body).length ? { body } : undefined, system: info.prompt, description: info.description, @@ -140,6 +141,32 @@ export function migrateAgent(info: ConfigAgentV1.Info) { } } +function commands(info?: Readonly>) { + if (!info) return undefined + return Object.fromEntries( + Object.entries(info).map(([id, command]) => [ + id, + { + template: command.template, + description: command.description, + agent: command.agent, + model: modelSelection(command.model, command.variant), + subtask: command.subtask, + }, + ]), + ) +} + +function modelSelection(input?: string, variant?: string) { + if (input === undefined || !/^[^/#]+\/[^#]+$/.test(input)) return undefined + const separator = input.indexOf("/") + return { + providerID: input.slice(0, separator), + model: input.slice(separator + 1), + ...(variant === undefined || variant.length === 0 || variant.includes("#") ? {} : { variant }), + } +} + function mcp(info: typeof ConfigV1.Info.Type) { const servers = Object.fromEntries( Object.entries(info.mcp ?? {}).flatMap(([name, server]) => @@ -184,31 +211,22 @@ function providers(info?: Readonly>) { } function migrateProvider(info: ConfigProviderV1.Info) { - const lowerer = ConfigProviderOptionsV1.get(info.npm) - const options = lowerer.provider(info.options ?? {}) - const url = info.api ?? options.url + const options = ConfigProviderOptionsV1.provider(info.options ?? {}) return { name: info.name, env: info.env, - api: info.npm - ? { - type: "aisdk" as const, - package: info.npm, - ...(url === undefined ? {} : { url }), - settings: options.settings ?? {}, - } - : undefined, - request: info.options && { headers: options.headers, body: options.body }, + package: info.npm ? ProviderV2.aisdk(info.npm) : undefined, + settings: info.api ? { ...options.settings, baseURL: info.api } : options.settings, + headers: info.options && options.headers, + body: info.options && options.body, models: info.models && - Object.fromEntries(Object.entries(info.models).map(([name, model]) => [name, migrateModel(model, info.npm)])), + Object.fromEntries(Object.entries(info.models).map(([name, model]) => [name, migrateModel(model)])), } } -function migrateModel(info: typeof ConfigProviderV1.Model.Type, packageName?: string) { - const packageID = info.provider?.npm ?? packageName - const lowerer = ConfigProviderOptionsV1.get(packageID) - const request = info.options && lowerer.request(info.options) +function migrateModel(info: typeof ConfigProviderV1.Model.Type) { + const settings = info.options && ConfigProviderOptionsV1.model(info.options) const costs = info.cost && [ { input: info.cost.input, @@ -231,29 +249,18 @@ function migrateModel(info: typeof ConfigProviderV1.Model.Type, packageName?: st ? { tools: info.tool_call ?? false, input: info.modalities?.input ?? [], output: info.modalities?.output ?? [] } : undefined return { + modelID: info.id, family: info.family, name: info.name, - api: info.provider?.npm - ? { - ...(info.id === undefined ? {} : { id: info.id }), - type: "aisdk" as const, - package: info.provider.npm, - ...(info.provider.api === undefined ? {} : { url: info.provider.api }), - settings: {}, - } - : info.id === undefined - ? undefined - : { id: info.id }, + package: info.provider?.npm ? ProviderV2.aisdk(info.provider.npm) : undefined, + settings: info.provider?.api ? { ...settings, baseURL: info.provider.api } : settings, capabilities, - request: (info.headers || request) && { - headers: info.headers, - body: request, - }, + headers: info.headers, variants: info.variants && Object.entries(info.variants).map(([id, options]) => ({ id, - body: lowerer.request(options), + settings: ConfigProviderOptionsV1.model(options), })), cost: costs, disabled: info.status === "deprecated" ? true : undefined, diff --git a/packages/core/src/v1/config/provider-options.ts b/packages/core/src/v1/config/provider-options.ts index 6bf0bd9e1aa..82d5bb1d506 100644 --- a/packages/core/src/v1/config/provider-options.ts +++ b/packages/core/src/v1/config/provider-options.ts @@ -3,225 +3,29 @@ export * as ConfigProviderOptionsV1 from "./provider-options" type Options = Readonly> export interface ProviderResult { + readonly settings: Record readonly headers?: Record readonly body?: Record - readonly url?: string - readonly settings?: Record } -export interface Lowerer { - readonly provider: (options: Options) => ProviderResult - readonly request: (options: Options) => Record -} - -export function get(packageName?: string): Lowerer { - const key = packageName ?? "" - return Object.hasOwn(lowerers, key) ? lowerers[key]! : raw -} - -const raw: Lowerer = { - provider(options) { - return { body: clone(options) } - }, - request: clone, -} - -const openai: Lowerer = { - provider(options) { - return { - url: string(options.baseURL), - headers: compact({ - Authorization: bearer(options.apiKey), - "OpenAI-Organization": string(options.organization), - "OpenAI-Project": string(options.project), - ...headers(options.headers), - }), - body: body(options.body), - settings: omit(options, ["apiKey", "baseURL", "organization", "project", "headers", "body"]), - } - }, - request(options) { - const result = snake(options) - if (options.reasoningEffort !== undefined || options.reasoningSummary !== undefined) { - result.reasoning = { - ...(isRecord(result.reasoning) ? result.reasoning : {}), - ...(options.reasoningEffort !== undefined ? { effort: options.reasoningEffort } : {}), - ...(options.reasoningSummary !== undefined ? { summary: options.reasoningSummary } : {}), - } - delete result.reasoning_effort - delete result.reasoning_summary - } - if (options.textVerbosity !== undefined) { - result.text = { ...(isRecord(result.text) ? result.text : {}), verbosity: options.textVerbosity } - delete result.text_verbosity - } - return result - }, -} - -const anthropic: Lowerer = { - provider(options) { - return { - url: string(options.baseURL), - headers: compact({ - "x-api-key": string(options.apiKey), - Authorization: options.authToken ? bearer(options.authToken) : undefined, - ...headers(options.headers), - }), - body: body(options.body), - settings: omit(options, ["apiKey", "authToken", "baseURL", "headers", "body"]), - } - }, - request(options) { - const result = snake(options) - if (options.effort !== undefined || options.taskBudget !== undefined) { - result.output_config = compactUnknown({ effort: options.effort, task_budget: options.taskBudget }) - delete result.effort - delete result.task_budget - } - if (isRecord(options.metadata) && options.metadata.userId !== undefined) { - result.metadata = { ...(isRecord(result.metadata) ? result.metadata : {}), user_id: options.metadata.userId } - } - return result - }, -} - -const google: Lowerer = { - provider(options) { - return { - url: string(options.baseURL), - headers: compact({ "x-goog-api-key": string(options.apiKey), ...headers(options.headers) }), - body: body(options.body), - settings: omit(options, ["apiKey", "baseURL", "headers", "body"]), - } - }, - request(options) { - const generationConfig = pick(options, ["thinkingConfig", "responseModalities", "mediaResolution", "imageConfig"]) - return { - ...omit(options, ["thinkingConfig", "responseModalities", "mediaResolution", "imageConfig"]), - ...(Object.keys(generationConfig).length ? { generationConfig } : {}), - } - }, -} - -const azure: Lowerer = { - provider(options) { - return { - url: string(options.baseURL), - headers: compact({ "api-key": string(options.apiKey), ...headers(options.headers) }), - body: body(options.body), - settings: omit(options, ["apiKey", "baseURL", "headers", "body"]), - } - }, - request: openai.request, -} - -const bedrock: Lowerer = { - provider(options) { - return direct(options) - }, - request(options) { - return { additionalModelRequestFields: clone(options) } - }, -} - -const openaiCompatible: Lowerer = { - provider(options) { - return { ...direct(options, ["baseURL"]), url: string(options.baseURL) } - }, - request(options) { - const result = clone(options) - if (options.reasoningEffort !== undefined) { - result.reasoning_effort = options.reasoningEffort - delete result.reasoningEffort - } - return result - }, -} - -const lowerers: Readonly> = { - "@ai-sdk/openai": openai, - "@ai-sdk/anthropic": anthropic, - "@ai-sdk/google-vertex/anthropic": anthropic, - "@ai-sdk/google": google, - "@ai-sdk/google-vertex": google, - "@ai-sdk/azure": azure, - "@ai-sdk/amazon-bedrock": bedrock, - "@ai-sdk/openai-compatible": openaiCompatible, - "@ai-sdk/cerebras": openaiCompatible, - "@ai-sdk/deepinfra": openaiCompatible, - "@ai-sdk/groq": openaiCompatible, - "@ai-sdk/mistral": openaiCompatible, - "@ai-sdk/togetherai": openaiCompatible, - "@ai-sdk/xai": openaiCompatible, - "@openrouter/ai-sdk-provider": openaiCompatible, - "ai-gateway-provider": openaiCompatible, - "venice-ai-sdk-provider": openaiCompatible, -} - -function direct(options: Options, extraKeys: ReadonlyArray = []): ProviderResult { +export function provider(options: Options): ProviderResult { + const headers = options.headers + const body = options.body + const settings = Object.fromEntries(Object.entries(options).filter(([key]) => key !== "headers" && key !== "body")) + const headerOverlay = + typeof headers === "object" && headers !== null && !Array.isArray(headers) + ? Object.fromEntries( + Object.entries(headers).filter((entry): entry is [string, string] => typeof entry[1] === "string"), + ) + : undefined + const bodyOverlay = typeof body === "object" && body !== null && !Array.isArray(body) ? { ...body } : undefined return { - headers: headers(options.headers), - body: body(options.body), - settings: omit(options, ["headers", "body", ...extraKeys]), + settings, + headers: headerOverlay, + body: bodyOverlay, } } -function body(input: unknown) { - if (!isRecord(input)) return undefined - return { ...input } -} - -function snake(options: Options) { - return Object.fromEntries(Object.entries(options).map(([key, value]) => [snakeKey(key), snakeValue(value)])) -} - -function snakeValue(value: unknown): unknown { - if (Array.isArray(value)) return value.map(snakeValue) - if (!isRecord(value)) return value - return Object.fromEntries(Object.entries(value).map(([key, value]) => [snakeKey(key), snakeValue(value)])) -} - -function snakeKey(key: string) { - return key.replace(/[A-Z]/g, (match) => "_" + match.toLowerCase()) -} - -function clone(options: Options) { +export function model(options: Options) { return { ...options } } - -function omit(options: Options, keys: ReadonlyArray) { - return Object.fromEntries(Object.entries(options).filter(([key]) => !keys.includes(key))) -} - -function pick(options: Options, keys: ReadonlyArray) { - return Object.fromEntries(Object.entries(options).filter(([key]) => keys.includes(key))) -} - -function headers(input: unknown) { - if (!isRecord(input)) return undefined - return Object.fromEntries( - Object.entries(input).filter((entry): entry is [string, string] => typeof entry[1] === "string"), - ) -} - -function compact(input: Record) { - const entries = Object.entries(input).filter((entry): entry is [string, string] => entry[1] !== undefined) - return entries.length ? Object.fromEntries(entries) : undefined -} - -function compactUnknown(input: Record) { - return Object.fromEntries(Object.entries(input).filter((entry) => entry[1] !== undefined)) -} - -function string(input: unknown) { - return typeof input === "string" && input ? input : undefined -} - -function bearer(input: unknown) { - return typeof input === "string" && input ? `Bearer ${input}` : undefined -} - -function isRecord(input: unknown): input is Record { - return typeof input === "object" && input !== null && !Array.isArray(input) -} diff --git a/packages/core/test/aisdk.test.ts b/packages/core/test/aisdk.test.ts new file mode 100644 index 00000000000..ecc9481a83b --- /dev/null +++ b/packages/core/test/aisdk.test.ts @@ -0,0 +1,85 @@ +import type { LanguageModelV3CallOptions } from "@ai-sdk/provider" +import { AISDK } from "@opencode-ai/core/aisdk" +import { ModelV2 } from "@opencode-ai/core/model" +import { ProviderV2 } from "@opencode-ai/core/provider" +import { LLM } from "@opencode-ai/llm" +import { LLMClient } from "@opencode-ai/llm/route" +import { expect } from "bun:test" +import { Effect } from "effect" +import { testEffect } from "./lib/effect" + +const it = testEffect(AISDK.locationLayer) +type Fetch = (input: Parameters[0], init?: RequestInit) => Promise + +const model = (packageName: string, settings: Record = {}) => + ModelV2.Info.make({ + ...ModelV2.Info.empty(ProviderV2.ID.make("test-provider"), ModelV2.ID.make("catalog-model")), + modelID: ModelV2.ID.make("api-model"), + package: ProviderV2.aisdk(packageName), + settings, + limit: { context: 100, output: 20 }, + }) + +it.effect("keys language models by package and flattened overlays", () => + Effect.gen(function* () { + const aisdk = yield* AISDK.Service + const loaded: string[] = [] + yield* aisdk.hook.sdk((event) => { + loaded.push(event.package) + event.sdk = { languageModel: () => ({ package: event.package }) } + }) + + const first = yield* aisdk.language(model("first", { region: "us-east-1" })) + const second = yield* aisdk.language(model("second", { region: "us-east-1" })) + const third = yield* aisdk.language( + model("second", { region: "us-east-1", fetch: async () => new Response("ok") }), + ) + + expect(first).not.toBe(second) + expect(second).not.toBe(third) + expect(loaded).toEqual(["first", "second", "second"]) + }), +) + +it.effect("projects request settings, headers, and raw body overlays", () => + Effect.gen(function* () { + const aisdk = yield* AISDK.Service + let wrappedFetch: Fetch | undefined + let body: unknown + const customFetch: Fetch = async (_input, init) => { + body = init?.body + return new Response("ok") + } + yield* aisdk.hook.sdk((event) => { + wrappedFetch = event.options.fetch + event.sdk = { languageModel: () => ({ provider: event.model.providerID }) } + }) + + const resolved = yield* aisdk.model( + ModelV2.Info.make({ + ...model("@ai-sdk/google", { + apiKey: "secret", + fetch: customFetch, + thinkingConfig: { thinkingBudget: 1024 }, + }), + headers: { "x-test": "header" }, + body: { safety_setting: "strict" }, + }), + ) + const prepared = yield* LLMClient.prepare( + LLM.request({ model: resolved, prompt: "Hello" }), + ) + + expect(prepared.body.providerOptions).toEqual({ + google: { thinkingConfig: { thinkingBudget: 1024 } }, + }) + expect(prepared.body.headers).toEqual({ "x-test": "header" }) + expect(wrappedFetch).toBeFunction() + if (wrappedFetch === undefined) return yield* Effect.die("Expected wrapped fetch") + const fetchRequest = wrappedFetch + yield* Effect.promise(() => + fetchRequest("https://provider.example", { method: "POST", body: JSON.stringify({ model: "api-model" }) }), + ) + expect(JSON.parse(String(body))).toEqual({ model: "api-model", safety_setting: "strict" }) + }), +) diff --git a/packages/core/test/catalog.test.ts b/packages/core/test/catalog.test.ts index 04bc0068881..83f71c33986 100644 --- a/packages/core/test/catalog.test.ts +++ b/packages/core/test/catalog.test.ts @@ -61,14 +61,14 @@ describe("CatalogV2", () => { }) expect((yield* catalog.provider.available()).map((provider) => provider.id)).toEqual([ProviderV2.ID.make("test")]) - expect(required(yield* catalog.provider.get(ProviderV2.ID.make("test"))).request.body).toEqual({}) + expect(required(yield* catalog.provider.get(ProviderV2.ID.make("test"))).body).toBeUndefined() yield* credentials.create({ integrationID, label: "Second", value: Credential.Key.make({ type: "key", key: "second", metadata: { tenant: "two" } }), }) expect((yield* catalog.provider.available()).map((provider) => provider.id)).toEqual([ProviderV2.ID.make("test")]) - expect(required(yield* catalog.provider.get(ProviderV2.ID.make("test"))).request.body).toEqual({}) + expect(required(yield* catalog.provider.get(ProviderV2.ID.make("test"))).body).toBeUndefined() }).pipe(Effect.provide(localCatalogLayer)) }) @@ -130,111 +130,91 @@ describe("CatalogV2", () => { ), ) - it.effect("normalizes provider baseURL into api url", () => + it.effect("stores provider package settings", () => Effect.gen(function* () { const catalog = yield* Catalog.Service const providerID = ProviderV2.ID.make("test") yield* catalog.transform((catalog) => catalog.provider.update(providerID, (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://default.example.com", - } - provider.request.body.baseURL = "https://override.example.com" + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://override.example.com" } }), ) - expect(required(yield* catalog.provider.get(providerID)).api).toEqual({ - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://override.example.com", + expect(required(yield* catalog.provider.get(providerID))).toMatchObject({ + package: ProviderV2.aisdk("@ai-sdk/openai-compatible"), + settings: { baseURL: "https://override.example.com" }, }) }), ) - it.effect("normalizes model baseURL into api url", () => + it.effect("uses model package settings over provider settings", () => Effect.gen(function* () { const catalog = yield* Catalog.Service const providerID = ProviderV2.ID.make("test") const modelID = ModelV2.ID.make("model") yield* catalog.transform((catalog) => { catalog.provider.update(providerID, (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://provider.example.com", - } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://provider.example.com" } }) catalog.model.update(providerID, modelID, (model) => { - model.api = { - id: modelID, - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://model.example.com", - } - model.request.body.baseURL = "https://override.example.com" + model.modelID = ModelV2.ID.make("upstream-model") + model.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + model.settings = { baseURL: "https://override.example.com" } }) }) - expect(required(yield* catalog.model.get(providerID, modelID)).api).toEqual({ - id: modelID, - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://override.example.com", - settings: {}, + expect(required(yield* catalog.model.get(providerID, modelID))).toMatchObject({ + modelID: ModelV2.ID.make("upstream-model"), + package: ProviderV2.aisdk("@ai-sdk/openai-compatible"), + settings: { baseURL: "https://override.example.com" }, }) }), ) - it.effect("resolves default model api from provider api", () => + it.effect("resolves default model package settings from the provider", () => Effect.gen(function* () { const catalog = yield* Catalog.Service const providerID = ProviderV2.ID.make("test") const modelID = ModelV2.ID.make("model") yield* catalog.transform((catalog) => { catalog.provider.update(providerID, (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://provider.example.com", - } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://provider.example.com" } }) catalog.model.update(providerID, modelID, () => {}) }) - expect(required(yield* catalog.model.get(providerID, modelID)).api).toEqual({ - id: modelID, - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://provider.example.com", + expect(required(yield* catalog.model.get(providerID, modelID))).toMatchObject({ + package: ProviderV2.aisdk("@ai-sdk/openai-compatible"), + settings: { baseURL: "https://provider.example.com" }, }) }), ) - it.effect("resolves provider and model request merges", () => + it.effect("resolves provider and model overlay merges", () => Effect.gen(function* () { const catalog = yield* Catalog.Service const providerID = ProviderV2.ID.make("test") const modelID = ModelV2.ID.make("model") yield* catalog.transform((catalog) => { catalog.provider.update(providerID, (provider) => { - provider.request.headers.provider = "provider" - provider.request.headers.shared = "provider" - provider.request.body.provider = true + provider.settings = { provider: true, shared: "provider" } + provider.headers = { provider: "provider", shared: "provider" } + provider.body = { provider: true, shared: "provider" } }) catalog.model.update(providerID, modelID, (model) => { - model.request.headers.model = "model" - model.request.headers.shared = "model" - model.request.body.model = true - model.request.body.request = true - model.request.body.shared = "model" + model.settings = { model: true, shared: "model" } + model.headers = { model: "model", shared: "model" } + model.body = { model: true, shared: "model" } }) }) const model = required(yield* catalog.model.get(providerID, modelID)) - expect(model.request.headers).toEqual({ provider: "provider", shared: "model", model: "model" }) - expect(model.request.body).toEqual({ provider: true, model: true, request: true, shared: "model" }) + expect(model.settings).toEqual({ provider: true, shared: "model", model: true }) + expect(model.headers).toEqual({ provider: "provider", shared: "model", model: "model" }) + expect(model.body).toEqual({ provider: true, shared: "model", model: true }) }), ) diff --git a/packages/core/test/config/agent.test.ts b/packages/core/test/config/agent.test.ts index 7f1d7ff0533..5537add3db0 100644 --- a/packages/core/test/config/agent.test.ts +++ b/packages/core/test/config/agent.test.ts @@ -62,7 +62,7 @@ describe("ConfigAgentPlugin.Plugin", () => { info: decode({ permissions: [{ action: "read", resource: "*", effect: "allow" }], agents: { - reviewer: { variant: "high", hidden: true }, + reviewer: { model: "openrouter/openai/gpt-5#high", hidden: true }, removed: { disabled: true }, late: { permissions: [{ action: "edit", resource: "*", effect: "allow" }], @@ -170,7 +170,7 @@ describe("ConfigAgentPlugin.Plugin", () => { hidden: true, color: "warning", steps: 12, - model: { providerID: "anthropic", id: "claude-sonnet", variant: undefined }, + model: { providerID: "anthropic", id: "claude-sonnet" }, }) expect(reviewer.request).toEqual({ settings: {}, diff --git a/packages/core/test/config/command.test.ts b/packages/core/test/config/command.test.ts index a8126d00f6e..f371e195438 100644 --- a/packages/core/test/config/command.test.ts +++ b/packages/core/test/config/command.test.ts @@ -44,8 +44,7 @@ describe("ConfigCommandPlugin.Plugin", () => { `--- description: File review agent: reviewer -model: anthropic/claude -variant: high +model: anthropic/claude#high subtask: true --- Review files`, diff --git a/packages/core/test/config/config.test.ts b/packages/core/test/config/config.test.ts index edf18d5add2..ae7322292cd 100644 --- a/packages/core/test/config/config.test.ts +++ b/packages/core/test/config/config.test.ts @@ -4,6 +4,7 @@ import { describe, expect } from "bun:test" import { Effect, Fiber, Layer, PubSub, Schema, Stream } from "effect" import { FastCheck } from "effect/testing" import { Config } from "@opencode-ai/core/config" +import { ConfigModel } from "@opencode-ai/core/config/model" import { Config as ConfigSchema } from "@opencode-ai/schema/config" import { ConfigProvider } from "@opencode-ai/core/config/provider" import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" @@ -16,12 +17,14 @@ import { EventV2 } from "@opencode-ai/core/event" import { Global } from "@opencode-ai/core/global" import { Location } from "@opencode-ai/core/location" import { Project } from "@opencode-ai/core/project" +import { ProviderV2 } from "@opencode-ai/core/provider" import { AbsolutePath } from "@opencode-ai/core/schema" import { location } from "../fixture/location" import { tmpdir } from "../fixture/tmpdir" import { testEffect } from "../lib/effect" const it = testEffect(Layer.empty) +const selection = Schema.decodeUnknownSync(ConfigModel.Selection) function testLayer( directory: string, @@ -47,11 +50,10 @@ function testLayer( } const provider = { - api: { type: "native", settings: {} }, - request: { - headers: {}, - body: {}, - }, + package: "native", + settings: {}, + headers: {}, + body: {}, models: {}, } @@ -105,13 +107,19 @@ describe("Config", () => { it.effect("returns the latest defined scalar from priority-ordered documents", () => Effect.sync(() => { const entries = [ - new Config.Document({ type: "document", info: new Config.Info({ model: "openrouter/openai/gpt-5" }) }), + new Config.Document({ + type: "document", + info: new Config.Info({ model: selection("openrouter/openai/gpt-5") }), + }), new Config.Directory({ type: "directory", path: AbsolutePath.make("/skills") }), new Config.Document({ type: "document", info: new Config.Info({}) }), - new Config.Document({ type: "document", info: new Config.Info({ model: "openrouter/openai/gpt-5.5" }) }), + new Config.Document({ + type: "document", + info: new Config.Info({ model: selection("openrouter/openai/gpt-5.5") }), + }), ] - expect(Config.latest(entries, "model")).toBe("openrouter/openai/gpt-5.5") + expect(Config.latest(entries, "model")).toEqual(selection("openrouter/openai/gpt-5.5")) expect(Config.latest(entries, "default_agent")).toBeUndefined() }), ) @@ -142,7 +150,12 @@ describe("Config", () => { Effect.sync(() => { FastCheck.assert( FastCheck.property(Schema.toArbitrary(ConfigV1.Info), (info) => { - Schema.decodeUnknownSync(Config.Info)(ConfigMigrateV1.migrate(info), { errors: "all" }) + const parsed = Schema.decodeUnknownSync(ConfigV1.Info)( + Schema.decodeUnknownSync(Schema.UnknownFromJsonString)( + Schema.encodeUnknownSync(Schema.UnknownFromJsonString)(info), + ), + ) + Schema.decodeUnknownSync(Config.Info)(ConfigMigrateV1.migrate(parsed), { errors: "all" }) }), { numRuns: 100 }, ) @@ -165,12 +178,9 @@ describe("Config", () => { }, }) - expect(migrated.providers?.bedrock?.api).toEqual({ - type: "aisdk", - package: "@ai-sdk/amazon-bedrock", + expect(migrated.providers?.bedrock).toMatchObject({ + package: ProviderV2.aisdk("@ai-sdk/amazon-bedrock"), settings: { region: "us-east-1", profile: "dev" }, - }) - expect(migrated.providers?.bedrock?.request).toEqual({ headers: { "x-test": "1" }, body: { trace: true }, }) @@ -197,8 +207,7 @@ describe("Config", () => { template: "Review changes", description: "Review code", agent: "reviewer", - model: "anthropic/claude", - variant: "high", + model: { providerID: "anthropic", model: "claude", variant: "high" }, subtask: true, }, }) @@ -431,8 +440,7 @@ describe("Config", () => { ], agents: { reviewer: { - model: "openrouter/openai/gpt-5", - variant: "high", + model: "openrouter/openai/gpt-5#high", request: { headers: { "x-agent": "reviewer" }, body: { reasoningEffort: "high" }, @@ -505,7 +513,7 @@ describe("Config", () => { expect(documents).toHaveLength(1) expect(documents[0]?.info.shell).toBe("/bin/bash") - expect(documents[0]?.info.model).toBe("anthropic/claude") + expect(documents[0]?.info.model).toEqual(selection("anthropic/claude")) expect(documents[0]?.info.default_agent).toBe("reviewer") expect(documents[0]?.info.autoupdate).toBe("notify") expect(documents[0]?.info.share).toBe("disabled") @@ -516,8 +524,7 @@ describe("Config", () => { { action: "bash", resource: "git status", effect: "allow" }, ]) const reviewer = documents[0]?.info.agents?.reviewer - expect(reviewer?.model).toBe("openrouter/openai/gpt-5") - expect(reviewer?.variant).toBe("high") + expect(reviewer?.model).toEqual(selection("openrouter/openai/gpt-5#high")) expect(reviewer?.request).toEqual({ headers: { "x-agent": "reviewer" }, body: { reasoningEffort: "high" }, @@ -748,34 +755,32 @@ describe("Config", () => { }) expect(documents[0]?.info.attachments).toEqual({ image: { auto_resize: false, max_width: 1200 } }) expect(documents[0]?.info.providers?.custom).toMatchObject({ - request: { body: { apiKey: "secret" } }, + settings: { apiKey: "secret" }, models: { model: { - request: { body: { reasoningEffort: "high" } }, - variants: [{ id: "fast", body: { temperature: 0.2 } }], + settings: { reasoningEffort: "high" }, + variants: [{ id: "fast", settings: { temperature: 0.2 } }], }, }, }) expect(documents[0]?.info.providers?.openai).toMatchObject({ - api: { settings: {} }, - request: { headers: { Authorization: "Bearer secret", "OpenAI-Organization": "org" } }, + package: ProviderV2.aisdk("@ai-sdk/openai"), + settings: { apiKey: "secret", organization: "org" }, models: { model: { - request: { - body: { temperature: 0.3, reasoning: { effort: "high" }, service_tier: "priority" }, - }, - variants: [{ id: "high", body: { reasoning: { effort: "high", summary: "auto" } } }], + settings: { temperature: 0.3, reasoningEffort: "high", serviceTier: "priority" }, + variants: [{ id: "high", settings: { reasoningEffort: "high", reasoningSummary: "auto" } }], }, }, }) expect(documents[0]?.info.providers?.anthropic).toMatchObject({ + package: ProviderV2.aisdk("@ai-sdk/anthropic"), models: { model: { - request: { - body: { - output_config: { effort: "high", task_budget: 4096 }, - metadata: { user_id: "user-1" }, - }, + settings: { + effort: "high", + taskBudget: 4096, + metadata: { userId: "user-1" }, }, }, }, diff --git a/packages/core/test/config/model.test.ts b/packages/core/test/config/model.test.ts new file mode 100644 index 00000000000..6ef8b2ac75f --- /dev/null +++ b/packages/core/test/config/model.test.ts @@ -0,0 +1,28 @@ +import { describe, expect, test } from "bun:test" +import { ConfigModel } from "@opencode-ai/core/config/model" +import { Model } from "@opencode-ai/schema/model" +import { Provider } from "@opencode-ai/schema/provider" +import { Schema } from "effect" + +const decode = Schema.decodeUnknownSync(ConfigModel.Selection) + +describe("ConfigModel.Selection", () => { + test("normalizes short and explicit model selections", () => { + expect(decode("openrouter/openai/gpt-5#high")).toEqual({ + providerID: Provider.ID.make("openrouter"), + model: Model.ID.make("openai/gpt-5"), + variant: Model.VariantID.make("high"), + }) + expect(decode({ providerID: "anthropic", model: "claude-sonnet", variant: "high" })).toEqual({ + providerID: Provider.ID.make("anthropic"), + model: Model.ID.make("claude-sonnet"), + variant: Model.VariantID.make("high"), + }) + }) + + test("rejects malformed selections and reserved fragments", () => { + expect(() => decode("gpt-5")).toThrow() + expect(() => decode("openai/gpt-5#")).toThrow() + expect(() => decode({ providerID: "openai", model: "gpt-5#high" })).toThrow() + }) +}) diff --git a/packages/core/test/config/provider-options.test.ts b/packages/core/test/config/provider-options.test.ts index 44a1c0c9db5..ac746e44417 100644 --- a/packages/core/test/config/provider-options.test.ts +++ b/packages/core/test/config/provider-options.test.ts @@ -2,223 +2,47 @@ import { describe, expect, test } from "bun:test" import { ConfigProviderOptionsV1 } from "@opencode-ai/core/v1/config/provider-options" describe("ConfigProviderOptionsV1", () => { - test("keeps raw provider and request options unchanged", () => { - const lowerer = ConfigProviderOptionsV1.get("custom-provider") - - expect(lowerer.provider({ apiKey: "secret", headers: { "x-test": "1" }, nested: { camelCase: true } })).toEqual({ - body: { apiKey: "secret", headers: { "x-test": "1" }, nested: { camelCase: true } }, - }) - expect(lowerer.request({ nested: { camelCase: true } })).toEqual({ nested: { camelCase: true } }) - }) - - test("falls back to raw lowering for prototype property package names", () => { - expect(ConfigProviderOptionsV1.get("toString").provider({ enabled: true })).toEqual({ body: { enabled: true } }) - }) - - test("lowers OpenAI provider and request options", () => { - const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/openai") - + test("splits provider overlays without changing package settings", () => { expect( - lowerer.provider({ + ConfigProviderOptionsV1.provider({ apiKey: "secret", baseURL: "https://openai.example/v1", organization: "org", - project: "project", - headers: { "x-test": "1" }, + headers: { "x-test": "1", invalid: true }, body: { store: true }, - timeout: 1000, + nested: { camelCase: true }, }), ).toEqual({ - url: "https://openai.example/v1", - headers: { - Authorization: "Bearer secret", - "OpenAI-Organization": "org", - "OpenAI-Project": "project", - "x-test": "1", + settings: { + apiKey: "secret", + baseURL: "https://openai.example/v1", + organization: "org", + nested: { camelCase: true }, }, + headers: { "x-test": "1" }, body: { store: true }, - settings: { timeout: 1000 }, }) + }) + + test("keeps model and variant options unchanged", () => { expect( - lowerer.request({ + ConfigProviderOptionsV1.model({ reasoningEffort: "high", - reasoningSummary: "auto", - reasoning: { encryptedContent: true }, - textVerbosity: "low", - text: { outputFormat: "plain" }, - nestedValue: { camelCase: true }, - }), - ).toEqual({ - reasoning: { encrypted_content: true, effort: "high", summary: "auto" }, - text: { output_format: "plain", verbosity: "low" }, - nested_value: { camel_case: true }, - }) - }) - - test("lowers Anthropic provider and request options", () => { - const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/anthropic") - - expect( - lowerer.provider({ - apiKey: "secret", - authToken: "token", - baseURL: "https://anthropic.example", - headers: { "x-test": "1" }, - body: { beta: true }, - generateId: "custom", - }), - ).toEqual({ - url: "https://anthropic.example", - headers: { "x-api-key": "secret", Authorization: "Bearer token", "x-test": "1" }, - body: { beta: true }, - settings: { generateId: "custom" }, - }) - expect( - lowerer.request({ - effort: "high", taskBudget: 1024, - metadata: { userId: "user", traceId: "trace" }, - nestedValue: { camelCase: true }, + metadata: { userId: "user" }, }), ).toEqual({ - output_config: { effort: "high", task_budget: 1024 }, - metadata: { user_id: "user", trace_id: "trace" }, - nested_value: { camel_case: true }, + reasoningEffort: "high", + taskBudget: 1024, + metadata: { userId: "user" }, }) }) - test("lowers Google provider and request options", () => { - const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/google") - - expect( - lowerer.provider({ - apiKey: "secret", - baseURL: "https://google.example", - headers: { "x-test": "1" }, - body: { trace: true }, - project: "project", - }), - ).toEqual({ - url: "https://google.example", - headers: { "x-goog-api-key": "secret", "x-test": "1" }, - body: { trace: true }, - settings: { project: "project" }, - }) - expect( - lowerer.request({ - thinkingConfig: { thinkingBudget: 1024 }, - responseModalities: ["TEXT"], - mediaResolution: "high", - imageConfig: { aspectRatio: "16:9" }, - safetySettings: ["safe"], - }), - ).toEqual({ - safetySettings: ["safe"], - generationConfig: { - thinkingConfig: { thinkingBudget: 1024 }, - responseModalities: ["TEXT"], - mediaResolution: "high", - imageConfig: { aspectRatio: "16:9" }, - }, - }) - }) - - test("lowers Azure provider options and uses OpenAI request lowering", () => { - const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/azure") - - expect( - lowerer.provider({ - apiKey: "secret", - baseURL: "https://azure.example", - headers: { "x-test": "1" }, - body: { trace: true }, - resourceName: "resource", - }), - ).toEqual({ - url: "https://azure.example", - headers: { "api-key": "secret", "x-test": "1" }, - body: { trace: true }, - settings: { resourceName: "resource" }, - }) - expect(lowerer.request({ reasoningEffort: "high", reasoningSummary: "auto", textVerbosity: "low" })).toEqual({ - reasoning: { effort: "high", summary: "auto" }, - text: { verbosity: "low" }, - }) - }) - - test("lowers Amazon Bedrock provider and request options", () => { - const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/amazon-bedrock") - - expect( - lowerer.provider({ - headers: { "x-test": "1" }, - body: { trace: true }, - region: "us-east-1", - profile: "dev", - }), - ).toEqual({ - headers: { "x-test": "1" }, - body: { trace: true }, - settings: { region: "us-east-1", profile: "dev" }, - }) - expect(lowerer.request({ temperature: 0.2 })).toEqual({ - additionalModelRequestFields: { temperature: 0.2 }, - }) - }) - - test("lowers OpenAI-compatible provider and request options", () => { - const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/openai-compatible") - - expect( - lowerer.provider({ - baseURL: "https://compatible.example/v1", - headers: { "x-test": "1" }, - body: { trace: true }, - apiKey: "secret", - }), - ).toEqual({ - url: "https://compatible.example/v1", - headers: { "x-test": "1" }, - body: { trace: true }, - settings: { apiKey: "secret" }, - }) - expect(lowerer.request({ reasoningEffort: "high", serviceTier: "priority" })).toEqual({ - reasoning_effort: "high", - serviceTier: "priority", - }) - }) - - test.each([ - "@ai-sdk/cerebras", - "@ai-sdk/deepinfra", - "@ai-sdk/groq", - "@ai-sdk/mistral", - "@ai-sdk/togetherai", - "@ai-sdk/xai", - "@openrouter/ai-sdk-provider", - "ai-gateway-provider", - "venice-ai-sdk-provider", - ])("uses OpenAI-compatible lowering for %s", (packageName) => { - const lowerer = ConfigProviderOptionsV1.get(packageName) - - expect(lowerer.provider({ baseURL: "https://example.test", apiKey: "secret" })).toEqual({ - url: "https://example.test", + test("uses mechanical lowering for custom provider options", () => { + expect(ConfigProviderOptionsV1.provider({ enabled: true })).toEqual({ + settings: { enabled: true }, headers: undefined, body: undefined, - settings: { apiKey: "secret" }, }) - expect(lowerer.request({ reasoningEffort: "high" })).toEqual({ reasoning_effort: "high" }) }) - - test.each(["@ai-sdk/google-vertex", "@ai-sdk/google-vertex/anthropic"])( - "uses provider family lowering for %s", - (packageName) => { - const lowerer = ConfigProviderOptionsV1.get(packageName) - - expect(lowerer.provider({ baseURL: "https://example.test", profile: "dev" })).toMatchObject({ - url: "https://example.test", - settings: { profile: "dev" }, - }) - }, - ) }) diff --git a/packages/core/test/config/provider.test.ts b/packages/core/test/config/provider.test.ts index 605bcd63cf9..d1d27dc6e9b 100644 --- a/packages/core/test/config/provider.test.ts +++ b/packages/core/test/config/provider.test.ts @@ -45,13 +45,6 @@ function withEnv(vars: Record, effect: () = ) } -function request(headers: Record, variant?: string) { - return { - headers, - variant, - } -} - const decode = Schema.decodeUnknownSync(Config.Info) describe("ConfigProviderPlugin.Plugin", () => { @@ -68,7 +61,8 @@ describe("ConfigProviderPlugin.Plugin", () => { info: decode({ providers: { opencode: { - api: { type: "aisdk", package: "@ai-sdk/openai", url: "https://opencode.test/v1" }, + package: "aisdk:@ai-sdk/openai", + settings: { baseURL: "https://opencode.test/v1" }, models: { "alpha-gpt-next": { variants: [ @@ -119,7 +113,8 @@ describe("ConfigProviderPlugin.Plugin", () => { info: decode({ providers: { opencode: { - api: { type: "aisdk", package: "@ai-sdk/openai", url: "https://opencode.test/v1" }, + package: "aisdk:@ai-sdk/openai", + settings: { baseURL: "https://opencode.test/v1" }, }, }, }), @@ -144,7 +139,7 @@ describe("ConfigProviderPlugin.Plugin", () => { yield* addPlugin(config) const model = required(yield* catalog.model.get(providerID, modelID)) - expect(model.variants[0]).toMatchObject({ + expect(model.variants?.[0]).toMatchObject({ id: "high", body: { reasoningEffort: "high" }, }) @@ -169,8 +164,8 @@ describe("ConfigProviderPlugin.Plugin", () => { custom: { name: "Configured", env: ["CUSTOM_API_KEY"], - api: { type: "native", settings: {} }, - request: request({ first: "first", shared: "first" }), + package: "native", + headers: { first: "first", shared: "first" }, models: { chat: { name: "First", @@ -178,7 +173,8 @@ describe("ConfigProviderPlugin.Plugin", () => { disabled: true, limit: { context: 100, output: 50 }, cost: { input: 1, output: 2 }, - request: request({ first: "first", shared: "first" }, "retained"), + settings: { retained: true }, + headers: { first: "first", shared: "first" }, variants: [ { id: "fast", @@ -197,17 +193,18 @@ describe("ConfigProviderPlugin.Plugin", () => { model: "custom/default", providers: { custom: { - api: { type: "aisdk", package: "custom-sdk", url: "https://example.test" }, - request: request({ last: "last", shared: "last" }), + package: "aisdk:custom-sdk", + settings: { baseURL: "https://example.test" }, + headers: { last: "last", shared: "last" }, models: { default: { name: "Default", }, chat: { - api: { id: "api-chat" }, + modelID: "api-chat", name: "Last", limit: { output: 75 }, - request: request({ last: "last", shared: "last" }), + headers: { last: "last", shared: "last" }, variants: [ { id: "fast", @@ -247,22 +244,24 @@ describe("ConfigProviderPlugin.Plugin", () => { }) expect((yield* integrations.get(Integration.ID.make("custom")))?.name).toBe("Renamed") expect(provider.disabled).toBeUndefined() - expect(provider.api).toEqual({ type: "aisdk", package: "custom-sdk", url: "https://example.test" }) - expect(provider.request.headers).toEqual({ first: "first", shared: "last", last: "last" }) - expect(model.api.id).toBe(ModelV2.ID.make("api-chat")) + expect(provider.package).toBe("aisdk:custom-sdk") + expect(provider.settings).toEqual({ baseURL: "https://example.test" }) + expect(provider.headers).toEqual({ first: "first", shared: "last", last: "last" }) + expect(model.id).toBe(modelID) + expect(model.modelID).toBe(ModelV2.ID.make("api-chat")) expect(model.name).toBe("Last") expect(model.capabilities).toEqual({ tools: true, input: ["text"], output: ["text"] }) expect(model.enabled).toBe(false) expect(model.limit).toEqual({ context: 100, output: 75 }) expect(model.cost).toEqual([{ input: 1, output: 2, cache: { read: 0, write: 0 }, tier: undefined }]) - expect(model.request.headers).toEqual({ first: "first", shared: "last", last: "last" }) - expect(model.request.variant).toBe("retained") - expect(model.variants.map((variant) => variant.id)).toEqual([ + expect(model.settings).toEqual({ baseURL: "https://example.test", retained: true }) + expect(model.headers).toEqual({ first: "first", shared: "last", last: "last" }) + expect(model.variants?.map((variant) => variant.id)).toEqual([ ModelV2.VariantID.make("fast"), ModelV2.VariantID.make("slow"), ]) - expect(model.variants[0]?.headers).toEqual({ first: "first", shared: "last", last: "last" }) - expect(model.variants[1]?.headers).toEqual({ slow: "slow" }) + expect(model.variants?.[0]?.headers).toEqual({ first: "first", shared: "last", last: "last" }) + expect(model.variants?.[1]?.headers).toEqual({ slow: "slow" }) }), ), ) diff --git a/packages/core/test/location-layer.test.ts b/packages/core/test/location-layer.test.ts index f0bef9fd325..f945cb2265c 100644 --- a/packages/core/test/location-layer.test.ts +++ b/packages/core/test/location-layer.test.ts @@ -271,7 +271,7 @@ describe("LocationServiceMap", () => { providers: { unavailable: { name: "Unavailable", - api: { type: "native", settings: {} }, + package: "test-provider", models: { chat: { disabled: true } }, }, }, @@ -306,7 +306,7 @@ describe("LocationServiceMap", () => { ), ) - it.live("preserves the selected catalog identity when the api model id differs", () => + it.live("preserves the selected catalog identity when the package model id differs", () => Effect.acquireRelease( Effect.promise(() => tmpdir()), (dir) => Effect.promise(() => dir[Symbol.asyncDispose]()), @@ -318,12 +318,12 @@ describe("LocationServiceMap", () => { const catalog = yield* Catalog.Service yield* catalog.transform((editor) => { editor.provider.update(ProviderV2.ID.make("aliased"), (provider) => { - provider.api = { type: "aisdk", package: "@ai-sdk/openai", settings: {} } + provider.package = ProviderV2.aisdk("@ai-sdk/openai") }) editor.model.update(ProviderV2.ID.make("aliased"), ModelV2.ID.make("fast"), (model) => { - // Catalog id and provider API id intentionally differ, like gpt-5.5-fast -> gpt-5.5. - model.api = { ...model.api, id: ModelV2.ID.make("base") } - model.variants.push({ id: ModelV2.VariantID.make("high"), settings: {}, headers: {}, body: {} }) + // Catalog id and package model id intentionally differ, like gpt-5.5-fast -> gpt-5.5. + model.modelID = ModelV2.ID.make("base") + model.variants = [{ id: ModelV2.VariantID.make("high") }] }) }) const models = yield* SessionRunnerModel.Service diff --git a/packages/core/test/plugin/fixtures/variant-source-plugin.ts b/packages/core/test/plugin/fixtures/variant-source-plugin.ts index 087a7142270..f799c968886 100644 --- a/packages/core/test/plugin/fixtures/variant-source-plugin.ts +++ b/packages/core/test/plugin/fixtures/variant-source-plugin.ts @@ -1,4 +1,5 @@ import { define } from "@opencode-ai/plugin/v2/effect" +import { ProviderV2 } from "@opencode-ai/core/provider" import { Effect } from "effect" export default define({ @@ -7,14 +8,11 @@ export default define({ ctx.catalog .transform((catalog) => { catalog.provider.update("configured", (provider) => { - provider.api = { type: "aisdk", package: "@ai-sdk/openai-compatible" } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") }) catalog.model.update("configured", "glm-5.2", (model) => { - model.api = { - id: "glm-5.2", - type: "aisdk", - package: "@ai-sdk/openai-compatible", - } + model.modelID = "glm-5.2" + model.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") model.variants = [ { id: "high", diff --git a/packages/core/test/plugin/host.ts b/packages/core/test/plugin/host.ts index 1f37dab47b0..2aa8789548a 100644 --- a/packages/core/test/plugin/host.ts +++ b/packages/core/test/plugin/host.ts @@ -162,7 +162,7 @@ export function catalogHost(catalog: Catalog.Interface): PluginContext["catalog" id: ModelV2.ID.make(current.id), providerID: ProviderV2.ID.make(current.providerID), family: current.family === undefined ? undefined : ModelV2.Family.make(current.family), - variants: current.variants.map((variant) => ({ + variants: current.variants?.map((variant) => ({ ...variant, id: ModelV2.VariantID.make(variant.id), })), @@ -327,35 +327,28 @@ function agentInfo(value: AgentV2.Info) { function providerInfo(value: ProviderV2.MutableInfo) { return { ...value, - api: { ...value.api, settings: value.api.settings && { ...value.api.settings } }, - request: { - settings: { ...value.request.settings }, - headers: { ...value.request.headers }, - body: { ...value.request.body }, - }, + settings: value.settings && { ...value.settings }, + headers: value.headers && { ...value.headers }, + body: value.body && { ...value.body }, } } function modelInfo(value: ModelV2.Info | ModelV2.MutableInfo) { return { ...value, - api: { ...value.api, settings: value.api.settings && { ...value.api.settings } }, + settings: value.settings && { ...value.settings }, + headers: value.headers && { ...value.headers }, + body: value.body && { ...value.body }, capabilities: { ...value.capabilities, input: [...value.capabilities.input], output: [...value.capabilities.output], }, - request: { - ...value.request, - settings: { ...value.request.settings }, - headers: { ...value.request.headers }, - body: { ...value.request.body }, - }, - variants: value.variants.map((variant) => ({ + variants: value.variants?.map((variant) => ({ ...variant, - settings: { ...variant.settings }, - headers: { ...variant.headers }, - body: { ...variant.body }, + settings: variant.settings && { ...variant.settings }, + headers: variant.headers && { ...variant.headers }, + body: variant.body && { ...variant.body }, })), time: { ...value.time }, cost: value.cost.map((cost) => ({ ...cost, tier: cost.tier && { ...cost.tier }, cache: { ...cost.cache } })), diff --git a/packages/core/test/plugin/models-dev.test.ts b/packages/core/test/plugin/models-dev.test.ts index b3dfe275ba8..545e09e0c38 100644 --- a/packages/core/test/plugin/models-dev.test.ts +++ b/packages/core/test/plugin/models-dev.test.ts @@ -94,16 +94,16 @@ describe("ModelsDevPlugin", () => { const fast = yield* catalog.model.get(providerID, ModelV2.ID.make("gpt-5.4-fast")) expect(base?.variants).toEqual([]) - expect(base?.request.body).toEqual({}) + expect(base?.body).toEqual({}) expect(fast).toMatchObject({ id: "gpt-5.4-fast", + modelID: "gpt-5.4", providerID: "acme", name: "GPT-5.4 Fast", - api: { id: "gpt-5.4" }, - request: { - headers: { "x-mode": "fast" }, - body: { service_tier: "priority" }, - }, + package: ProviderV2.aisdk("@ai-sdk/openai-compatible"), + settings: { baseURL: "https://api.acme.test/v1" }, + headers: { "x-mode": "fast" }, + body: { service_tier: "priority" }, variants: [], }) expect(fast?.cost).toEqual([ @@ -191,7 +191,7 @@ describe("ModelsDevPlugin", () => { ) const model = yield* catalog.model.get(ProviderV2.ID.openai, ModelV2.ID.make("gpt-reasoning")) - expect(model?.variants.map((variant) => variant.id)).toEqual([ + expect(model?.variants?.map((variant) => variant.id)).toEqual([ ModelV2.VariantID.make("low"), ModelV2.VariantID.make("high"), ]) @@ -202,8 +202,6 @@ describe("ModelsDevPlugin", () => { reasoningSummary: "auto", include: ["reasoning.encrypted_content"], }, - headers: {}, - body: {}, }) expect(model?.variants).toContainEqual({ id: ModelV2.VariantID.make("high"), @@ -212,20 +210,16 @@ describe("ModelsDevPlugin", () => { reasoningSummary: "auto", include: ["reasoning.encrypted_content"], }, - headers: {}, - body: {}, }) const mode = yield* catalog.model.get(ProviderV2.ID.openai, ModelV2.ID.make("gpt-reasoning-high")) expect(mode).toMatchObject({ id: "gpt-reasoning-high", name: "GPT Reasoning High", - request: { - headers: { "x-mode": "high" }, - body: { service_tier: "priority" }, - }, + headers: { "x-mode": "high" }, + body: { service_tier: "priority" }, }) - expect(mode?.variants.map((variant) => variant.id)).toEqual([ + expect(mode?.variants?.map((variant) => variant.id)).toEqual([ ModelV2.VariantID.make("low"), ModelV2.VariantID.make("high"), ]) @@ -234,22 +228,19 @@ describe("ModelsDevPlugin", () => { expect(budgetModel?.variants).toContainEqual({ id: ModelV2.VariantID.make("high"), settings: { thinking: { type: "enabled", budgetTokens: 16000 } }, - headers: {}, - body: {}, }) expect(budgetModel?.variants).toContainEqual({ id: ModelV2.VariantID.make("max"), settings: { thinking: { type: "enabled", budgetTokens: 64000 } }, - headers: {}, - body: {}, }) - const anthropicEffortModel = yield* catalog.model.get(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-effort")) + const anthropicEffortModel = yield* catalog.model.get( + ProviderV2.ID.anthropic, + ModelV2.ID.make("claude-effort"), + ) expect(anthropicEffortModel?.variants).toContainEqual({ id: ModelV2.VariantID.make("low"), settings: { thinking: { type: "adaptive", display: "summarized" }, effort: "low" }, - headers: {}, - body: {}, }) }).pipe(Effect.provide(AppNodeBuilder.build(ModelsDev.node))), (previous) => diff --git a/packages/core/test/plugin/provider-alibaba.test.ts b/packages/core/test/plugin/provider-alibaba.test.ts index 25d46bf83c6..bb7f922e524 100644 --- a/packages/core/test/plugin/provider-alibaba.test.ts +++ b/packages/core/test/plugin/provider-alibaba.test.ts @@ -28,7 +28,8 @@ describe("AlibabaPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("alibaba"), ModelV2.ID.make("qwen")), - api: { id: ModelV2.ID.make("qwen"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("qwen"), + package: "aisdk:test-provider", }), package: "@ai-sdk/alibaba", options: { name: "alibaba" }, @@ -45,7 +46,8 @@ describe("AlibabaPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("alibaba"), ModelV2.ID.make("qwen")), - api: { id: ModelV2.ID.make("qwen"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("qwen"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "alibaba" }, @@ -62,7 +64,8 @@ describe("AlibabaPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-alibaba"), ModelV2.ID.make("qwen")), - api: { id: ModelV2.ID.make("qwen"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("qwen"), + package: "aisdk:test-provider", }), package: "@ai-sdk/alibaba", options: { name: "custom-alibaba", apiKey: "test" }, @@ -74,17 +77,18 @@ describe("AlibabaPlugin", () => { }), ) - it.effect("uses the old default languageModel(api.id) behavior", () => + it.effect("uses the default languageModel(modelID) behavior", () => Effect.gen(function* () { const plugin = yield* PluginV2.Service const aisdk = yield* AISDK.Service yield* addPlugin() const item = ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("alibaba"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("qwen-plus"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("qwen-plus"), + package: "aisdk:test-provider", }) const result = yield* aisdk.runSDK({ model: item, package: "@ai-sdk/alibaba", options: {} }) - const language = result.sdk?.languageModel(item.api.id) + const language = result.sdk?.languageModel(item.modelID ?? item.id) expect(language?.modelId).toBe("qwen-plus") expect(language?.provider).toBe("alibaba.chat") }), diff --git a/packages/core/test/plugin/provider-amazon-bedrock.test.ts b/packages/core/test/plugin/provider-amazon-bedrock.test.ts index 31065c2e3da..db63910c33f 100644 --- a/packages/core/test/plugin/provider-amazon-bedrock.test.ts +++ b/packages/core/test/plugin/provider-amazon-bedrock.test.ts @@ -79,31 +79,24 @@ function openAIUrl(language: unknown, path: string, modelId: string) { } describe("AmazonBedrockPlugin", () => { - it.effect("moves endpoint option to api URL", () => + it.effect("moves endpoint setting to baseURL", () => Effect.gen(function* () { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { const bedrock = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.amazonBedrock), - api: { type: "aisdk", package: "@ai-sdk/amazon-bedrock" }, - request: { - headers: {}, - body: { endpoint: "https://bedrock.example" }, - }, + package: ProviderV2.aisdk("@ai-sdk/amazon-bedrock"), + settings: { endpoint: "https://bedrock.example" }, }) catalog.provider.update(bedrock.id, (item) => { - item.api = bedrock.api - item.request = { settings: {}, headers: {}, body: { endpoint: "https://bedrock.example" } } + item.package = bedrock.package + item.settings = { endpoint: "https://bedrock.example" } }) }) yield* addPlugin() const result = required(yield* catalog.provider.get(ProviderV2.ID.amazonBedrock)) - expect(result.api).toEqual({ - type: "aisdk", - package: "@ai-sdk/amazon-bedrock", - url: "https://bedrock.example", - }) - expect(result.request.body.endpoint).toBeUndefined() + expect(result.package).toBe(ProviderV2.aisdk("@ai-sdk/amazon-bedrock")) + expect(result.settings).toEqual({ baseURL: "https://bedrock.example" }) }), ) @@ -116,7 +109,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/amazon-bedrock", options: { @@ -141,7 +135,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/amazon-bedrock", options: { @@ -175,11 +170,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { - id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), - type: "aisdk", - package: "test-provider", - }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/amazon-bedrock", options: { name: "amazon-bedrock" }, @@ -199,7 +191,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/amazon-bedrock", options: { name: "amazon-bedrock", region: "eu-west-1" }, @@ -218,7 +211,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/amazon-bedrock", options: { name: "amazon-bedrock" }, @@ -237,7 +231,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/amazon-bedrock", options: { name: "amazon-bedrock" }, @@ -257,7 +252,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/amazon-bedrock", options: { @@ -286,7 +282,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/amazon-bedrock", options: { @@ -314,11 +311,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-5.5")), - api: { - id: ModelV2.ID.make("openai.gpt-5.5"), - type: "aisdk", - package: "@ai-sdk/amazon-bedrock/mantle", - }, + modelID: ModelV2.ID.make("openai.gpt-5.5"), + package: ProviderV2.aisdk("@ai-sdk/amazon-bedrock/mantle"), }), package: "@ai-sdk/amazon-bedrock/mantle", options: { @@ -345,11 +339,8 @@ describe("AmazonBedrockPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-5.5")), - api: { - id: ModelV2.ID.make("openai.gpt-5.5"), - type: "aisdk", - package: "@ai-sdk/amazon-bedrock/mantle", - }, + modelID: ModelV2.ID.make("openai.gpt-5.5"), + package: ProviderV2.aisdk("@ai-sdk/amazon-bedrock/mantle"), }), sdk: fakeSelectorSdk(calls), options: { baseURL: "https://bedrock-mantle.us-east-2.api.aws/openai/v1", region: "us-east-2" }, @@ -357,11 +348,8 @@ describe("AmazonBedrockPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("openai.gpt-oss-safeguard-120b")), - api: { - id: ModelV2.ID.make("openai.gpt-oss-safeguard-120b"), - type: "aisdk", - package: "@ai-sdk/amazon-bedrock/mantle", - }, + modelID: ModelV2.ID.make("openai.gpt-oss-safeguard-120b"), + package: ProviderV2.aisdk("@ai-sdk/amazon-bedrock/mantle"), }), sdk: fakeSelectorSdk(calls), options: { region: "us-east-1" }, @@ -378,11 +366,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { - id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), - type: "aisdk", - package: "@ai-sdk/amazon-bedrock/anthropic", - }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("@ai-sdk/amazon-bedrock/anthropic"), }), package: "@ai-sdk/amazon-bedrock/anthropic", options: { name: "amazon-bedrock" }, @@ -409,11 +394,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { - id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), - type: "aisdk", - package: "test-provider", - }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/amazon-bedrock", options: { @@ -444,7 +426,8 @@ describe("AmazonBedrockPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: {}, @@ -452,7 +435,8 @@ describe("AmazonBedrockPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: { region: "eu-west-1" }, @@ -460,11 +444,8 @@ describe("AmazonBedrockPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("global.anthropic.claude-sonnet-4-5")), - api: { - id: ModelV2.ID.make("global.anthropic.claude-sonnet-4-5"), - type: "aisdk", - package: "test-provider", - }, + modelID: ModelV2.ID.make("global.anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: { region: "eu-west-1" }, @@ -472,7 +453,8 @@ describe("AmazonBedrockPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: { region: "ap-northeast-1" }, @@ -480,7 +462,8 @@ describe("AmazonBedrockPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: { region: "ap-southeast-2" }, @@ -505,7 +488,8 @@ describe("AmazonBedrockPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: {}, @@ -591,7 +575,8 @@ describe("AmazonBedrockPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.amazonBedrock, ModelV2.ID.make(item.modelID)), - api: { id: ModelV2.ID.make(item.modelID), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make(item.modelID), + package: ProviderV2.aisdk("test-provider"), }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: { region: item.region }, @@ -610,7 +595,8 @@ describe("AmazonBedrockPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("anthropic.claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("anthropic.claude-sonnet-4-5"), + package: ProviderV2.aisdk("test-provider"), }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: { region: "eu-west-1" }, diff --git a/packages/core/test/plugin/provider-anthropic.test.ts b/packages/core/test/plugin/provider-anthropic.test.ts index df05a07f759..af7b80dc673 100644 --- a/packages/core/test/plugin/provider-anthropic.test.ts +++ b/packages/core/test/plugin/provider-anthropic.test.ts @@ -31,19 +31,19 @@ describe("AnthropicPlugin", () => { yield* catalog.transform((catalog) => { const item = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.anthropic), - api: { type: "aisdk", package: "@ai-sdk/anthropic" }, - request: { headers: { Existing: "1" }, body: {} }, + package: ProviderV2.aisdk("@ai-sdk/anthropic"), + headers: { Existing: "1" }, }) catalog.provider.update(item.id, (draft) => { - draft.api = item.api - draft.request = { settings: {}, headers: { Existing: "1" }, body: {} } + draft.package = item.package + draft.headers = { Existing: "1" } }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.anthropic)).request.headers["anthropic-beta"]).toBe( + expect(required(yield* catalog.provider.get(ProviderV2.ID.anthropic)).headers?.["anthropic-beta"]).toBe( "interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14", ) - expect(required(yield* catalog.provider.get(ProviderV2.ID.anthropic)).request.headers.Existing).toBe("1") + expect(required(yield* catalog.provider.get(ProviderV2.ID.anthropic)).headers?.Existing).toBe("1") }), ) @@ -52,9 +52,7 @@ describe("AnthropicPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.openai, () => {})) yield* addPlugin() - expect( - required(yield* catalog.provider.get(ProviderV2.ID.openai)).request.headers["anthropic-beta"], - ).toBeUndefined() + expect(required(yield* catalog.provider.get(ProviderV2.ID.openai)).headers?.["anthropic-beta"]).toBeUndefined() }), ) @@ -66,7 +64,8 @@ describe("AnthropicPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-anthropic"), ModelV2.ID.make("claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "@ai-sdk/anthropic" }, + modelID: ModelV2.ID.make("claude-sonnet-4-5"), + package: ProviderV2.aisdk("@ai-sdk/anthropic"), }), package: "@ai-sdk/anthropic", options: { name: "custom-anthropic", apiKey: "test" }, @@ -83,7 +82,8 @@ describe("AnthropicPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "@ai-sdk/anthropic" }, + modelID: ModelV2.ID.make("claude-sonnet-4-5"), + package: ProviderV2.aisdk("@ai-sdk/anthropic"), }), package: "@ai-sdk/anthropic", options: { name: "anthropic", apiKey: "test" }, diff --git a/packages/core/test/plugin/provider-azure-cognitive-services.test.ts b/packages/core/test/plugin/provider-azure-cognitive-services.test.ts index 6b3f6c6a382..f52f013105d 100644 --- a/packages/core/test/plugin/provider-azure-cognitive-services.test.ts +++ b/packages/core/test/plugin/provider-azure-cognitive-services.test.ts @@ -66,18 +66,16 @@ describe("AzureCognitiveServicesPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("azure-cognitive-services"), (item) => { - item.api = { type: "aisdk", package: "@ai-sdk/openai-compatible" } + item.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") }) }) yield* addPlugin() const result = required(yield* catalog.provider.get(ProviderV2.ID.make("azure-cognitive-services"))) - expect(result.api).toEqual({ - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://cognitive.cognitiveservices.azure.com/openai", + expect(result).toMatchObject({ + package: "aisdk:@ai-sdk/openai-compatible", + settings: { baseURL: "https://cognitive.cognitiveservices.azure.com/openai" }, }) - expect(result.request.body.baseURL).toBeUndefined() - expect(result.request.body.resourceName).toBeUndefined() + expect(result.settings?.resourceName).toBeUndefined() }), ), ) @@ -89,26 +87,28 @@ describe("AzureCognitiveServicesPlugin", () => { yield* catalog.transform((catalog) => { const azure = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services")), - api: { type: "aisdk", package: "@ai-sdk/openai-compatible" }, + package: "aisdk:@ai-sdk/openai-compatible", }) const openai = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.openai), - api: { type: "aisdk", package: "test-provider" }, + package: "aisdk:test-provider", }) catalog.provider.update(azure.id, (item) => { - item.api = azure.api + item.package = azure.package + item.package = azure.package }) catalog.provider.update(openai.id, (item) => { - item.api = openai.api + item.package = openai.package + item.package = openai.package }) }) yield* addPlugin() const azure = required(yield* catalog.provider.get(ProviderV2.ID.make("azure-cognitive-services"))) const openai = required(yield* catalog.provider.get(ProviderV2.ID.openai)) - expect(azure.request.body.baseURL).toBeUndefined() - expect(azure.api).toEqual({ type: "aisdk", package: "@ai-sdk/openai-compatible" }) - expect(openai.request.body.baseURL).toBeUndefined() - expect(openai.api).toEqual({ type: "aisdk", package: "test-provider" }) + expect(azure.settings?.baseURL).toBeUndefined() + expect(azure).toMatchObject({ package: "aisdk:@ai-sdk/openai-compatible" }) + expect(openai.settings?.baseURL).toBeUndefined() + expect(openai).toMatchObject({ package: "aisdk:test-provider" }) }), ), ) @@ -122,7 +122,8 @@ describe("AzureCognitiveServicesPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("deployment"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: { useCompletionUrls: true }, @@ -140,7 +141,8 @@ describe("AzureCognitiveServicesPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("deployment"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -148,7 +150,8 @@ describe("AzureCognitiveServicesPlugin", () => { const ignored = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("deployment"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -168,7 +171,8 @@ describe("AzureCognitiveServicesPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("messages-deployment")), - api: { id: ModelV2.ID.make("messages-deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("messages-deployment"), + package: "aisdk:test-provider", }), sdk: { messages: sdk.messages, chat: sdk.chat, languageModel: sdk.languageModel }, options: {}, @@ -176,7 +180,8 @@ describe("AzureCognitiveServicesPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("chat-deployment")), - api: { id: ModelV2.ID.make("chat-deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("chat-deployment"), + package: "aisdk:test-provider", }), sdk: { chat: sdk.chat, languageModel: sdk.languageModel }, options: {}, @@ -184,7 +189,8 @@ describe("AzureCognitiveServicesPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("azure-cognitive-services"), ModelV2.ID.make("language-deployment")), - api: { id: ModelV2.ID.make("language-deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("language-deployment"), + package: "aisdk:test-provider", }), sdk: { languageModel: sdk.languageModel }, options: {}, diff --git a/packages/core/test/plugin/provider-azure.test.ts b/packages/core/test/plugin/provider-azure.test.ts index 42af292e158..6cf515c0c60 100644 --- a/packages/core/test/plugin/provider-azure.test.ts +++ b/packages/core/test/plugin/provider-azure.test.ts @@ -66,11 +66,11 @@ describe("AzurePlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.azure, (item) => { - item.api = { type: "aisdk", package: "@ai-sdk/azure" } + item.package = ProviderV2.aisdk("@ai-sdk/azure") }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-env") + expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).settings?.resourceName).toBe("from-env") }), ), ) @@ -82,18 +82,18 @@ describe("AzurePlugin", () => { yield* catalog.transform((catalog) => { const azure = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.azure), - api: { type: "aisdk", package: "@ai-sdk/azure" }, - request: { headers: {}, body: { resourceName: "from-config" } }, + package: ProviderV2.aisdk("@ai-sdk/azure"), + settings: { resourceName: "from-config" }, }) catalog.provider.update(azure.id, (item) => { - item.api = azure.api - item.request = { settings: {}, headers: {}, body: { resourceName: "from-config" } } + item.package = azure.package + item.settings = { resourceName: "from-config" } }) catalog.provider.update(ProviderV2.ID.openai, () => {}) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-config") - expect(required(yield* catalog.provider.get(ProviderV2.ID.openai)).request.body.resourceName).toBeUndefined() + expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).settings?.resourceName).toBe("from-config") + expect(required(yield* catalog.provider.get(ProviderV2.ID.openai)).settings?.resourceName).toBeUndefined() }), ), ) @@ -105,16 +105,16 @@ describe("AzurePlugin", () => { yield* catalog.transform((catalog) => { const azure = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.azure), - api: { type: "aisdk", package: "@ai-sdk/azure" }, - request: { headers: {}, body: { resourceName: "" } }, + package: ProviderV2.aisdk("@ai-sdk/azure"), + settings: { resourceName: "" }, }) catalog.provider.update(azure.id, (item) => { - item.api = azure.api - item.request = { settings: {}, headers: {}, body: { resourceName: "" } } + item.package = azure.package + item.settings = { resourceName: "" } }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-env") + expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).settings?.resourceName).toBe("from-env") }), ), ) @@ -126,16 +126,16 @@ describe("AzurePlugin", () => { yield* catalog.transform((catalog) => { const azure = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.azure), - api: { type: "aisdk", package: "@ai-sdk/azure" }, - request: { headers: {}, body: { resourceName: " " } }, + package: ProviderV2.aisdk("@ai-sdk/azure"), + settings: { resourceName: " " }, }) catalog.provider.update(azure.id, (item) => { - item.api = azure.api - item.request = { settings: {}, headers: {}, body: { resourceName: " " } } + item.package = azure.package + item.settings = { resourceName: " " } }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).request.body.resourceName).toBe("from-env") + expect(required(yield* catalog.provider.get(ProviderV2.ID.azure)).settings?.resourceName).toBe("from-env") }), ), ) @@ -149,7 +149,8 @@ describe("AzurePlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("deployment"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/azure", options: { name: "azure", baseURL: "https://proxy.example.com/openai" }, @@ -168,7 +169,8 @@ describe("AzurePlugin", () => { .runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("deployment"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/azure", options: { name: "azure" }, @@ -188,7 +190,8 @@ describe("AzurePlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("deployment"), + package: ProviderV2.aisdk("test-provider"), }), sdk: fakeSelectorSdk(calls), options: { useCompletionUrls: true }, @@ -206,7 +209,8 @@ describe("AzurePlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("deployment"), + package: ProviderV2.aisdk("test-provider"), }), sdk: fakeSelectorSdk(calls), options: { useCompletionUrls: true }, @@ -224,8 +228,9 @@ describe("AzurePlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, - request: { headers: {}, body: { useCompletionUrls: true } }, + modelID: ModelV2.ID.make("deployment"), + package: ProviderV2.aisdk("test-provider"), + body: { useCompletionUrls: true }, }), sdk: fakeSelectorSdk(calls), options: {}, @@ -243,7 +248,8 @@ describe("AzurePlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("deployment"), + package: ProviderV2.aisdk("test-provider"), }), sdk: fakeSelectorSdk(calls), options: {}, @@ -251,7 +257,8 @@ describe("AzurePlugin", () => { const ignored = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("deployment")), - api: { id: ModelV2.ID.make("deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("deployment"), + package: ProviderV2.aisdk("test-provider"), }), sdk: fakeSelectorSdk(calls), options: {}, @@ -274,7 +281,8 @@ describe("AzurePlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("messages-deployment")), - api: { id: ModelV2.ID.make("messages-deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("messages-deployment"), + package: ProviderV2.aisdk("test-provider"), }), sdk: { messages: make("messages"), chat: make("chat"), languageModel: make("languageModel") }, options: {}, @@ -282,7 +290,8 @@ describe("AzurePlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.azure, ModelV2.ID.make("language-deployment")), - api: { id: ModelV2.ID.make("language-deployment"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("language-deployment"), + package: ProviderV2.aisdk("test-provider"), }), sdk: { languageModel: make("languageModel") }, options: {}, diff --git a/packages/core/test/plugin/provider-cerebras.test.ts b/packages/core/test/plugin/provider-cerebras.test.ts index adcc1779b0d..eb5c4ec1bf5 100644 --- a/packages/core/test/plugin/provider-cerebras.test.ts +++ b/packages/core/test/plugin/provider-cerebras.test.ts @@ -36,12 +36,12 @@ describe("CerebrasPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("cerebras"), (item) => { - item.api = { type: "aisdk", package: "@ai-sdk/cerebras" } - item.request.headers.Existing = "1" + item.package = ProviderV2.aisdk("@ai-sdk/cerebras") + item.headers = { ...item.headers, Existing: "1" } }) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("cerebras")))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.make("cerebras")))?.headers).toEqual({ Existing: "1", "X-Cerebras-3rd-Party-Integration": "opencode", }) @@ -53,7 +53,7 @@ describe("CerebrasPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("groq"), () => {})) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("groq")))?.request.headers).toEqual({}) + expect((yield* catalog.provider.get(ProviderV2.ID.make("groq")))?.headers).toBeUndefined() }), ) @@ -69,11 +69,8 @@ describe("CerebrasPlugin", () => { ProviderV2.ID.make("custom-cerebras"), ModelV2.ID.make("llama-4-scout-17b-16e-instruct"), ), - api: { - id: ModelV2.ID.make("llama-4-scout-17b-16e-instruct"), - type: "aisdk", - package: "test-provider", - }, + modelID: ModelV2.ID.make("llama-4-scout-17b-16e-instruct"), + package: "aisdk:test-provider", }), package: "@ai-sdk/cerebras", options: { name: "custom-cerebras", apiKey: "test" }, @@ -95,11 +92,8 @@ describe("CerebrasPlugin", () => { ProviderV2.ID.make("custom-cerebras"), ModelV2.ID.make("llama-4-scout-17b-16e-instruct"), ), - api: { - id: ModelV2.ID.make("llama-4-scout-17b-16e-instruct"), - type: "aisdk", - package: "test-provider", - }, + modelID: ModelV2.ID.make("llama-4-scout-17b-16e-instruct"), + package: "aisdk:test-provider", }), package: "@ai-sdk/cerebras", options: { name: "configured-cerebras", apiKey: "test" }, @@ -120,11 +114,8 @@ describe("CerebrasPlugin", () => { ProviderV2.ID.make("custom-cerebras"), ModelV2.ID.make("llama-4-scout-17b-16e-instruct"), ), - api: { - id: ModelV2.ID.make("llama-4-scout-17b-16e-instruct"), - type: "aisdk", - package: "test-provider", - }, + modelID: ModelV2.ID.make("llama-4-scout-17b-16e-instruct"), + package: "aisdk:test-provider", }), package: "@ai-sdk/groq", options: { name: "custom-cerebras", apiKey: "test" }, diff --git a/packages/core/test/plugin/provider-cloudflare-ai-gateway.test.ts b/packages/core/test/plugin/provider-cloudflare-ai-gateway.test.ts index 008b9a46a3e..cbd2b95c9eb 100644 --- a/packages/core/test/plugin/provider-cloudflare-ai-gateway.test.ts +++ b/packages/core/test/plugin/provider-cloudflare-ai-gateway.test.ts @@ -118,7 +118,8 @@ describe("CloudflareAIGatewayPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { name: "cloudflare-ai-gateway" }, @@ -139,7 +140,8 @@ describe("CloudflareAIGatewayPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { @@ -183,7 +185,8 @@ describe("CloudflareAIGatewayPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { @@ -212,7 +215,8 @@ describe("CloudflareAIGatewayPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { @@ -249,7 +253,8 @@ describe("CloudflareAIGatewayPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { @@ -280,7 +285,8 @@ describe("CloudflareAIGatewayPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { name: "cloudflare-ai-gateway" }, @@ -302,7 +308,8 @@ describe("CloudflareAIGatewayPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { name: "cloudflare-ai-gateway" }, @@ -325,7 +332,8 @@ describe("CloudflareAIGatewayPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { name: "cloudflare-ai-gateway" }, @@ -354,7 +362,8 @@ describe("CloudflareAIGatewayPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { name: "cloudflare-ai-gateway", baseURL: "https://proxy.example/v1" }, @@ -380,11 +389,8 @@ describe("CloudflareAIGatewayPlugin", () => { ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("anthropic/claude-sonnet-4-5"), ), - api: { - id: ModelV2.ID.make("anthropic/claude-sonnet-4-5"), - type: "aisdk", - package: "test-provider", - }, + modelID: ModelV2.ID.make("anthropic/claude-sonnet-4-5"), + package: "aisdk:test-provider", }), package: "ai-gateway-provider", options: { name: "cloudflare-ai-gateway" }, @@ -412,7 +418,8 @@ describe("CloudflareAIGatewayPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-ai-gateway"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "cloudflare-ai-gateway" }, diff --git a/packages/core/test/plugin/provider-cloudflare-workers-ai.test.ts b/packages/core/test/plugin/provider-cloudflare-workers-ai.test.ts index d1eeaa581ef..d67b8d91cc2 100644 --- a/packages/core/test/plugin/provider-cloudflare-workers-ai.test.ts +++ b/packages/core/test/plugin/provider-cloudflare-workers-ai.test.ts @@ -87,7 +87,7 @@ describe("CloudflareWorkersAIPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("cloudflare-workers-ai"), (provider) => { - provider.api = { type: "aisdk", package: "test-provider" } + provider.package = ProviderV2.aisdk("test-provider") }), ) yield* addPlugin() @@ -95,15 +95,16 @@ describe("CloudflareWorkersAIPlugin", () => { const sdk = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")), - api: { id: ModelV2.ID.make("@cf/model"), ...provider.api }, + modelID: ModelV2.ID.make("@cf/model"), + package: provider.package, + settings: provider.settings, }), package: "@ai-sdk/openai-compatible", options: { name: "cloudflare-workers-ai", headers: { custom: "header" } }, }) - expect(provider.api).toEqual({ - type: "aisdk", - package: "test-provider", - url: "https://api.cloudflare.com/client/v4/accounts/acct/ai/v1", + expect(provider).toMatchObject({ + package: "aisdk:test-provider", + settings: { baseURL: "https://api.cloudflare.com/client/v4/accounts/acct/ai/v1" }, }) expect(sdk.sdk).toBeDefined() }), @@ -116,14 +117,14 @@ describe("CloudflareWorkersAIPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("cloudflare-workers-ai"), (provider) => { - provider.api = { type: "aisdk", package: "test-provider", url: "https://proxy.example/v1" } + provider.package = ProviderV2.aisdk("test-provider") + provider.settings = { ...provider.settings, baseURL: "https://proxy.example/v1" } }), ) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.make("cloudflare-workers-ai"))).api).toEqual({ - type: "aisdk", - package: "test-provider", - url: "https://proxy.example/v1", + expect(required(yield* catalog.provider.get(ProviderV2.ID.make("cloudflare-workers-ai")))).toMatchObject({ + package: "aisdk:test-provider", + settings: { baseURL: "https://proxy.example/v1" }, }) }), ), @@ -138,12 +139,9 @@ describe("CloudflareWorkersAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")), - api: { - id: ModelV2.ID.make("@cf/model"), - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://proxy.example/v1", - }, + modelID: ModelV2.ID.make("@cf/model"), + package: "aisdk:@ai-sdk/openai-compatible", + settings: { baseURL: "https://proxy.example/v1" }, }), package: "@ai-sdk/openai-compatible", options: { name: "cloudflare-workers-ai", baseURL: "https://proxy.example/v1" }, @@ -159,15 +157,14 @@ describe("CloudflareWorkersAIPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("cloudflare-workers-ai"), (provider) => { - provider.api = { type: "aisdk", package: "test-provider" } - provider.request.body.accountId = "configured-acct" + provider.package = ProviderV2.aisdk("test-provider") + provider.settings = { ...provider.settings, accountId: "configured-acct" } }), ) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.make("cloudflare-workers-ai"))).api).toEqual({ - type: "aisdk", - package: "test-provider", - url: "https://api.cloudflare.com/client/v4/accounts/env-acct/ai/v1", + expect(required(yield* catalog.provider.get(ProviderV2.ID.make("cloudflare-workers-ai")))).toMatchObject({ + package: "aisdk:test-provider", + settings: { baseURL: "https://api.cloudflare.com/client/v4/accounts/env-acct/ai/v1" }, }) }), ), @@ -182,12 +179,9 @@ describe("CloudflareWorkersAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")), - api: { - id: ModelV2.ID.make("@cf/model"), - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://proxy.example/v1", - }, + modelID: ModelV2.ID.make("@cf/model"), + package: "aisdk:@ai-sdk/openai-compatible", + settings: { baseURL: "https://proxy.example/v1" }, }), package: "@ai-sdk/openai-compatible", options: { @@ -214,12 +208,9 @@ describe("CloudflareWorkersAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")), - api: { - id: ModelV2.ID.make("@cf/model"), - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/ai/v1", - }, + modelID: ModelV2.ID.make("@cf/model"), + package: "aisdk:@ai-sdk/openai-compatible", + settings: { baseURL: "https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/ai/v1" }, }), package: "@ai-sdk/openai-compatible", options: { @@ -243,7 +234,8 @@ describe("CloudflareWorkersAIPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("@cf/api-model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("@cf/api-model"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -262,12 +254,9 @@ describe("CloudflareWorkersAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("@cf/model")), - api: { - id: ModelV2.ID.make("@cf/model"), - type: "aisdk", - package: "@ai-sdk/anthropic", - url: "https://proxy.example/v1", - }, + modelID: ModelV2.ID.make("@cf/model"), + package: "aisdk:@ai-sdk/anthropic", + settings: { baseURL: "https://proxy.example/v1" }, }), package: "@ai-sdk/anthropic", options: { name: "cloudflare-workers-ai" }, diff --git a/packages/core/test/plugin/provider-cohere.test.ts b/packages/core/test/plugin/provider-cohere.test.ts index c001ad935f1..a4109f74bdb 100644 --- a/packages/core/test/plugin/provider-cohere.test.ts +++ b/packages/core/test/plugin/provider-cohere.test.ts @@ -56,7 +56,8 @@ describe("CoherePlugin", () => { const ignored = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cohere"), ModelV2.ID.make("command")), - api: { id: ModelV2.ID.make("command"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("command"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "cohere" }, @@ -66,7 +67,8 @@ describe("CoherePlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cohere"), ModelV2.ID.make("command")), - api: { id: ModelV2.ID.make("command"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("command"), + package: "aisdk:test-provider", }), package: "@ai-sdk/cohere", options: { name: "cohere" }, @@ -83,7 +85,8 @@ describe("CoherePlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-cohere"), ModelV2.ID.make("command-r-plus")), - api: { id: ModelV2.ID.make("command-r-plus"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("command-r-plus"), + package: "aisdk:test-provider", }), package: "@ai-sdk/cohere", options: { name: "custom-cohere", apiKey: "test", baseURL: "https://cohere.example" }, @@ -108,7 +111,8 @@ describe("CoherePlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cohere"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("command-r-plus"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("command-r-plus"), + package: "aisdk:test-provider", }), sdk, options: {}, diff --git a/packages/core/test/plugin/provider-deepinfra.test.ts b/packages/core/test/plugin/provider-deepinfra.test.ts index 9cb9a4866c2..14c41e550d7 100644 --- a/packages/core/test/plugin/provider-deepinfra.test.ts +++ b/packages/core/test/plugin/provider-deepinfra.test.ts @@ -48,7 +48,8 @@ describe("DeepInfraPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:@ai-sdk/deepinfra", }), package: "@ai-sdk/deepinfra", options: { name: "deepinfra" }, @@ -66,7 +67,8 @@ describe("DeepInfraPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-deepinfra"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:@ai-sdk/deepinfra", }), package: "@ai-sdk/deepinfra", options: { name: "custom-deepinfra", apiKey: "test" }, @@ -85,7 +87,8 @@ describe("DeepInfraPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:@ai-sdk/deepinfra", }), package: "@ai-sdk/deepinfra", options: { name: "deepinfra", apiKey: "test" }, @@ -111,7 +114,8 @@ describe("DeepInfraPlugin", () => { const ignored = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:@ai-sdk/deepinfra", }), package: item, options: { name: "deepinfra" }, @@ -122,7 +126,8 @@ describe("DeepInfraPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "@ai-sdk/deepinfra" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:@ai-sdk/deepinfra", }), package: "@ai-sdk/deepinfra", options: { name: "deepinfra" }, @@ -141,17 +146,14 @@ describe("DeepInfraPlugin", () => { const sdkEvent = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("deepinfra"), ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct")), - api: { - id: ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct"), - type: "aisdk", - package: "@ai-sdk/deepinfra", - }, + modelID: ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct"), + package: "aisdk:@ai-sdk/deepinfra", }), package: "@ai-sdk/deepinfra", options: { name: "deepinfra" }, }) const result = yield* aisdk.runLanguage({ model: sdkEvent.model, sdk: sdkEvent.sdk, options: sdkEvent.options }) - const language = result.language ?? result.sdk.languageModel(result.model.api.id) + const language = result.language ?? result.sdk.languageModel(result.model.modelID ?? result.model.id) expect(language.provider).toBe("deepinfra.chat") expect(deepinfraLanguageModels).toEqual(["meta-llama/Llama-3.3-70B-Instruct"]) }), diff --git a/packages/core/test/plugin/provider-dynamic.test.ts b/packages/core/test/plugin/provider-dynamic.test.ts index 9eda0351438..c5a598a8703 100644 --- a/packages/core/test/plugin/provider-dynamic.test.ts +++ b/packages/core/test/plugin/provider-dynamic.test.ts @@ -54,7 +54,8 @@ describe("DynamicProviderPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("test-model")), - api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: fixtureProvider }, + modelID: ModelV2.ID.make("test-model"), + package: ProviderV2.aisdk(fixtureProvider), }), package: fixtureProvider, options: { name: "custom", marker: "dynamic" }, @@ -72,7 +73,8 @@ describe("DynamicProviderPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("test-model")), - api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: fixtureProvider }, + modelID: ModelV2.ID.make("test-model"), + package: ProviderV2.aisdk(fixtureProvider), }), package: fixtureProvider, options: { name: "custom", marker: "dynamic" }, @@ -89,7 +91,8 @@ describe("DynamicProviderPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-provider"), ModelV2.ID.make("test-model")), - api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: fixtureProvider }, + modelID: ModelV2.ID.make("test-model"), + package: ProviderV2.aisdk(fixtureProvider), }), package: fixtureProvider, options: { name: "custom-provider", marker: "dynamic" }, @@ -105,7 +108,8 @@ describe("DynamicProviderPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("npm-provider"), ModelV2.ID.make("test-model")), - api: { id: ModelV2.ID.make("test-model"), type: "aisdk", package: "fixture-provider" }, + modelID: ModelV2.ID.make("test-model"), + package: "aisdk:fixture-provider", }), package: "fixture-provider", options: { name: "npm-provider", marker: "npm" }, @@ -122,7 +126,8 @@ describe("DynamicProviderPlugin", () => { .language( ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("missing-entrypoint"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "fixture-provider" }, + modelID: ModelV2.ID.make("alias"), + package: "aisdk:fixture-provider", }), ) .pipe(Effect.exit) @@ -139,7 +144,8 @@ describe("DynamicProviderPlugin", () => { .language( ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("bad-import"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "file:///missing/provider-factory.js" }, + modelID: ModelV2.ID.make("alias"), + package: "aisdk:file:///missing/provider-factory.js", }), ) .pipe(Effect.exit) @@ -158,7 +164,8 @@ describe("DynamicProviderPlugin", () => { .language( ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("missing-factory"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "fixture-provider" }, + modelID: ModelV2.ID.make("alias"), + package: "aisdk:fixture-provider", }), ) .pipe(Effect.exit) @@ -167,7 +174,7 @@ describe("DynamicProviderPlugin", () => { }), ) - itWithAISDK.effect("uses the model api.id for the default language model", () => + itWithAISDK.effect("uses the model modelID for the default language model", () => Effect.gen(function* () { const plugin = yield* PluginV2.Service const aisdk = yield* AISDK.Service @@ -175,7 +182,8 @@ describe("DynamicProviderPlugin", () => { const language = yield* aisdk.language( ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("test-model-api"), type: "aisdk", package: fixtureProvider }, + modelID: ModelV2.ID.make("test-model-api"), + package: ProviderV2.aisdk(fixtureProvider), }), ) expect(language).toMatchObject({ modelID: "test-model-api", options: { name: "custom" } }) diff --git a/packages/core/test/plugin/provider-gateway.test.ts b/packages/core/test/plugin/provider-gateway.test.ts index c6a0427cdb7..722bbde9b6f 100644 --- a/packages/core/test/plugin/provider-gateway.test.ts +++ b/packages/core/test/plugin/provider-gateway.test.ts @@ -45,7 +45,8 @@ describe("GatewayPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("gateway"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "@ai-sdk/gateway", options: { name: "gateway" }, @@ -65,11 +66,8 @@ describe("GatewayPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make("anthropic/claude-sonnet-4")), - api: { - id: ModelV2.ID.make("anthropic/claude-sonnet-4"), - type: "aisdk", - package: "test-provider", - }, + modelID: ModelV2.ID.make("anthropic/claude-sonnet-4"), + package: "aisdk:test-provider", }), package: "@ai-sdk/gateway", options: { name: "vercel", apiKey: "test-key" }, @@ -91,7 +89,8 @@ describe("GatewayPlugin", () => { const ignored = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make(modelID)), - api: { id: ModelV2.ID.make(modelID), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make(modelID), + package: "aisdk:test-provider", }), package: "@ai-sdk/vercel", options: { name: "vercel" }, @@ -101,7 +100,8 @@ describe("GatewayPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("vercel"), ModelV2.ID.make(modelID)), - api: { id: ModelV2.ID.make(modelID), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make(modelID), + package: "aisdk:test-provider", }), package: "@ai-sdk/gateway", options: { name: "vercel" }, diff --git a/packages/core/test/plugin/provider-github-copilot.test.ts b/packages/core/test/plugin/provider-github-copilot.test.ts index beef89ae8c0..4c5a3b11600 100644 --- a/packages/core/test/plugin/provider-github-copilot.test.ts +++ b/packages/core/test/plugin/provider-github-copilot.test.ts @@ -47,7 +47,8 @@ describe("GithubCopilotPlugin", () => { const ignored = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5")), - api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "github-copilot" }, @@ -55,7 +56,8 @@ describe("GithubCopilotPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5")), - api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5"), + package: "aisdk:test-provider", }), package: "@ai-sdk/github-copilot", options: { name: "github-copilot" }, @@ -74,7 +76,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("claude-sonnet-4")), - api: { id: ModelV2.ID.make("claude-sonnet-4"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4"), + package: "aisdk:test-provider", }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: {}, @@ -92,7 +95,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("claude-sonnet-4"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4"), + package: "aisdk:test-provider", }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: {}, @@ -110,7 +114,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5")), - api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -118,7 +123,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5.1-codex")), - api: { id: ModelV2.ID.make("gpt-5.1-codex"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5.1-codex"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -126,7 +132,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-4o")), - api: { id: ModelV2.ID.make("gpt-4o"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-4o"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -134,7 +141,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5-mini")), - api: { id: ModelV2.ID.make("gpt-5-mini"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5-mini"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -142,7 +150,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("gpt-5-mini-2025-08-07")), - api: { id: ModelV2.ID.make("gpt-5-mini-2025-08-07"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5-mini-2025-08-07"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -166,7 +175,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("default")), - api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -174,7 +184,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("small")), - api: { id: ModelV2.ID.make("gpt-5-mini"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5-mini"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -182,7 +193,8 @@ describe("GithubCopilotPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("github-copilot"), ModelV2.ID.make("sonnet")), - api: { id: ModelV2.ID.make("claude-sonnet-4"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -230,7 +242,8 @@ describe("GithubCopilotPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("openai"), ModelV2.ID.make("gpt-5")), - api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, diff --git a/packages/core/test/plugin/provider-gitlab.test.ts b/packages/core/test/plugin/provider-gitlab.test.ts index f9880844d3d..ae66a61aa81 100644 --- a/packages/core/test/plugin/provider-gitlab.test.ts +++ b/packages/core/test/plugin/provider-gitlab.test.ts @@ -70,7 +70,8 @@ describe("GitLabPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")), - api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude"), + package: "aisdk:test-provider", }), package: "gitlab-ai-provider", options: { name: "gitlab" }, @@ -107,7 +108,8 @@ describe("GitLabPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")), - api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude"), + package: "aisdk:test-provider", }), package: "gitlab-ai-provider", options: { name: "gitlab" }, @@ -132,7 +134,8 @@ describe("GitLabPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")), - api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude"), + package: "aisdk:test-provider", }), package: "gitlab-ai-provider", options: { @@ -173,7 +176,8 @@ describe("GitLabPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")), - api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai", options: { name: "gitlab" }, @@ -192,11 +196,10 @@ describe("GitLabPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("duo-workflow-custom")), - api: { id: ModelV2.ID.make("duo-workflow-custom"), type: "aisdk", package: "test-provider" }, - request: { - headers: {}, - body: { workflowRef: "ref", workflowDefinition: "definition" }, - }, + modelID: ModelV2.ID.make("duo-workflow-custom"), + package: "aisdk:test-provider", + headers: {}, + settings: { workflowRef: "ref", workflowDefinition: "definition" }, }), sdk: { workflowChat: (id: string, options: unknown) => { @@ -227,7 +230,8 @@ describe("GitLabPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("duo-workflow-exact")), - api: { id: ModelV2.ID.make("duo-workflow-exact"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("duo-workflow-exact"), + package: "aisdk:test-provider", }), sdk: { workflowChat: (id: string, options: unknown) => { @@ -245,7 +249,7 @@ describe("GitLabPlugin", () => { }), ) - it.effect("uses provider feature flags instead of request feature flags", () => + it.effect("uses provider feature flags instead of model settings feature flags", () => Effect.gen(function* () { const plugin = yield* PluginV2.Service const aisdk = yield* AISDK.Service @@ -254,11 +258,10 @@ describe("GitLabPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("duo-workflow-custom")), - api: { id: ModelV2.ID.make("duo-workflow-custom"), type: "aisdk", package: "test-provider" }, - request: { - headers: {}, - body: { featureFlags: { request_flag: true } }, - }, + modelID: ModelV2.ID.make("duo-workflow-custom"), + package: "aisdk:test-provider", + headers: {}, + settings: { featureFlags: { request_flag: true } }, }), sdk: { workflowChat: (id: string, options: unknown) => { @@ -282,8 +285,10 @@ describe("GitLabPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("gitlab"), ModelV2.ID.make("claude")), - api: { id: ModelV2.ID.make("claude"), type: "aisdk", package: "test-provider" }, - request: { headers: { h: "v" }, body: {} }, + modelID: ModelV2.ID.make("claude"), + package: "aisdk:test-provider", + headers: { h: "v" }, + settings: {}, }), sdk: { workflowChat: () => undefined, diff --git a/packages/core/test/plugin/provider-google-vertex-anthropic.test.ts b/packages/core/test/plugin/provider-google-vertex-anthropic.test.ts index d94321f3bd6..090abb945c2 100644 --- a/packages/core/test/plugin/provider-google-vertex-anthropic.test.ts +++ b/packages/core/test/plugin/provider-google-vertex-anthropic.test.ts @@ -64,16 +64,16 @@ describe("GoogleVertexAnthropicPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("google-vertex-anthropic"), (provider) => { - provider.api = { type: "aisdk", package: "@ai-sdk/google-vertex/anthropic" } + provider.package = ProviderV2.aisdk("@ai-sdk/google-vertex/anthropic") }), ) yield* addPlugin(GoogleVertexAnthropicPlugin) - expect( - (yield* catalog.provider.get(ProviderV2.ID.make("google-vertex-anthropic")))?.request.body.project, - ).toBe("cloud-project") - expect( - (yield* catalog.provider.get(ProviderV2.ID.make("google-vertex-anthropic")))?.request.body.location, - ).toBe("cloud-location") + expect((yield* catalog.provider.get(ProviderV2.ID.make("google-vertex-anthropic")))?.settings?.project).toBe( + "cloud-project", + ) + expect((yield* catalog.provider.get(ProviderV2.ID.make("google-vertex-anthropic")))?.settings?.location).toBe( + "cloud-location", + ) }), ), ) @@ -84,18 +84,17 @@ describe("GoogleVertexAnthropicPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("google-vertex-anthropic"), (provider) => { - provider.api = { type: "aisdk", package: "@ai-sdk/google-vertex/anthropic" } - provider.request.body.project = "configured-project" - provider.request.body.location = "configured-location" + provider.package = ProviderV2.aisdk("@ai-sdk/google-vertex/anthropic") + provider.settings = { ...provider.settings, project: "configured-project", location: "configured-location" } }), ) yield* addPlugin(GoogleVertexAnthropicPlugin) - expect((yield* catalog.provider.get(ProviderV2.ID.make("google-vertex-anthropic")))?.request.body.project).toBe( + expect((yield* catalog.provider.get(ProviderV2.ID.make("google-vertex-anthropic")))?.settings?.project).toBe( "configured-project", ) - expect( - (yield* catalog.provider.get(ProviderV2.ID.make("google-vertex-anthropic")))?.request.body.location, - ).toBe("configured-location") + expect((yield* catalog.provider.get(ProviderV2.ID.make("google-vertex-anthropic")))?.settings?.location).toBe( + "configured-location", + ) }), ), ) @@ -121,7 +120,8 @@ describe("GoogleVertexAnthropicPlugin", () => { ProviderV2.ID.make("google-vertex-anthropic"), ModelV2.ID.make("claude-sonnet-4-5"), ), - api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-5"), + package: "aisdk:test-provider", }), package: "@ai-sdk/google-vertex/anthropic", options: { name: "google-vertex-anthropic" }, @@ -147,7 +147,8 @@ describe("GoogleVertexAnthropicPlugin", () => { ProviderV2.ID.make("google-vertex-anthropic"), ModelV2.ID.make("claude-sonnet-4-5"), ), - api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-5"), + package: "aisdk:test-provider", }), package: "@ai-sdk/google-vertex/anthropic", options: { name: "google-vertex-anthropic" }, @@ -167,7 +168,8 @@ describe("GoogleVertexAnthropicPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-5"), + package: "aisdk:test-provider", }), package: "@ai-sdk/google-vertex/anthropic", options: { name: "google-vertex", project: "project", location: "eu" }, @@ -186,7 +188,8 @@ describe("GoogleVertexAnthropicPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-5"), + package: "aisdk:test-provider", }), package: "@ai-sdk/google-vertex/anthropic", options: { name: "google-vertex", project: "project", location: "eu", baseURL: "https://proxy.example/v1" }, @@ -204,7 +207,8 @@ describe("GoogleVertexAnthropicPlugin", () => { const sdkResult = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make(" claude-sonnet-4-5 ")), - api: { id: ModelV2.ID.make(" claude-sonnet-4-5 "), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make(" claude-sonnet-4-5 "), + package: "aisdk:test-provider", }), package: "@ai-sdk/google-vertex/anthropic", options: { name: "google-vertex", project: "project", location: "us" }, @@ -212,7 +216,8 @@ describe("GoogleVertexAnthropicPlugin", () => { const languageResult = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make(" claude-sonnet-4-5 ")), - api: { id: ModelV2.ID.make(" claude-sonnet-4-5 "), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make(" claude-sonnet-4-5 "), + package: "aisdk:test-provider", }), sdk: sdkResult.sdk, options: {}, @@ -234,7 +239,8 @@ describe("GoogleVertexAnthropicPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex-anthropic"), ModelV2.ID.make(" claude-sonnet-4-5 ")), - api: { id: ModelV2.ID.make(" claude-sonnet-4-5 "), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make(" claude-sonnet-4-5 "), + package: "aisdk:test-provider", }), sdk: { languageModel: selector(calls) }, options: {}, @@ -252,7 +258,8 @@ describe("GoogleVertexAnthropicPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("claude-sonnet-4-5")), - api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-5"), + package: "aisdk:test-provider", }), sdk: { languageModel: selector(calls) }, options: {}, diff --git a/packages/core/test/plugin/provider-google-vertex.test.ts b/packages/core/test/plugin/provider-google-vertex.test.ts index 388528bd65c..635beba3c1c 100644 --- a/packages/core/test/plugin/provider-google-vertex.test.ts +++ b/packages/core/test/plugin/provider-google-vertex.test.ts @@ -92,17 +92,14 @@ describe("GoogleVertexPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.opencode, (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://opencode.ai/zen/v1", - } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { ...provider.settings, baseURL: "https://opencode.ai/zen/v1" } }), ) yield* addPlugin() const provider = required(yield* catalog.provider.get(ProviderV2.ID.opencode)) - expect(provider.request.body).toEqual({}) + expect(provider.settings).toEqual({ baseURL: "https://opencode.ai/zen/v1" }) }), ) @@ -121,21 +118,24 @@ describe("GoogleVertexPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("google-vertex"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://${GOOGLE_VERTEX_ENDPOINT}/v1/projects/${GOOGLE_VERTEX_PROJECT}/locations/${GOOGLE_VERTEX_LOCATION}", + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { + ...provider.settings, + baseURL: + "https://${GOOGLE_VERTEX_ENDPOINT}/v1/projects/${GOOGLE_VERTEX_PROJECT}/locations/${GOOGLE_VERTEX_LOCATION}", } }), ) yield* addPlugin() const provider = required(yield* catalog.provider.get(ProviderV2.ID.make("google-vertex"))) - expect(provider.request.body.project).toBe("google-cloud-project") - expect(provider.request.body.location).toBe("google-vertex-location") - expect(provider.api).toEqual({ - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://google-vertex-location-aiplatform.googleapis.com/v1/projects/google-cloud-project/locations/google-vertex-location", + expect(provider.settings?.project).toBe("google-cloud-project") + expect(provider.settings?.location).toBe("google-vertex-location") + expect(provider).toMatchObject({ + package: "aisdk:@ai-sdk/openai-compatible", + settings: { + baseURL: + "https://google-vertex-location-aiplatform.googleapis.com/v1/projects/google-cloud-project/locations/google-vertex-location", + }, }) }), ), @@ -160,10 +160,11 @@ describe("GoogleVertexPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("google-vertex"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://${GOOGLE_VERTEX_ENDPOINT}/v1/projects/${GOOGLE_VERTEX_PROJECT}/locations/${GOOGLE_VERTEX_LOCATION}", + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { + ...provider.settings, + baseURL: + "https://${GOOGLE_VERTEX_ENDPOINT}/v1/projects/${GOOGLE_VERTEX_PROJECT}/locations/${GOOGLE_VERTEX_LOCATION}", } }), ) @@ -172,21 +173,20 @@ describe("GoogleVertexPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini")), - api: { - id: ModelV2.ID.make("gemini"), - type: "aisdk", - package: "@ai-sdk/google-vertex", - }, + modelID: ModelV2.ID.make("gemini"), + package: "aisdk:@ai-sdk/google-vertex", }), package: "@ai-sdk/google-vertex", options: { name: "google-vertex" }, }) - expect(provider.request.body.project).toBe("vertex-project") - expect(provider.api).toEqual({ - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://europe-west4-aiplatform.googleapis.com/v1/projects/vertex-project/locations/europe-west4", + expect(provider.settings?.project).toBe("vertex-project") + expect(provider).toMatchObject({ + package: "aisdk:@ai-sdk/openai-compatible", + settings: { + baseURL: + "https://europe-west4-aiplatform.googleapis.com/v1/projects/vertex-project/locations/europe-west4", + }, }) expect(vertexOptions[0].project).toBe("vertex-project") expect(vertexOptions[0].location).toBe("europe-west4") @@ -209,23 +209,22 @@ describe("GoogleVertexPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("google-vertex"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://${GOOGLE_VERTEX_ENDPOINT}/v1/projects/${GOOGLE_VERTEX_PROJECT}/locations/${GOOGLE_VERTEX_LOCATION}", + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { + ...provider.settings, + baseURL: + "https://${GOOGLE_VERTEX_ENDPOINT}/v1/projects/${GOOGLE_VERTEX_PROJECT}/locations/${GOOGLE_VERTEX_LOCATION}", } - provider.request.body.project = "config-project" - provider.request.body.location = "global" + provider.settings = { ...provider.settings, project: "config-project", location: "global" } }), ) yield* addPlugin() const provider = required(yield* catalog.provider.get(ProviderV2.ID.make("google-vertex"))) - expect(provider.request.body.project).toBe("config-project") - expect(provider.request.body.location).toBe("global") - expect(provider.api).toEqual({ - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://aiplatform.googleapis.com/v1/projects/config-project/locations/global", + expect(provider.settings?.project).toBe("config-project") + expect(provider.settings?.location).toBe("global") + expect(provider).toMatchObject({ + package: "aisdk:@ai-sdk/openai-compatible", + settings: { baseURL: "https://aiplatform.googleapis.com/v1/projects/config-project/locations/global" }, }) }), ), @@ -236,21 +235,20 @@ describe("GoogleVertexPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("google-vertex"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://${GOOGLE_VERTEX_ENDPOINT}/v1/projects/${GOOGLE_VERTEX_PROJECT}/locations/${GOOGLE_VERTEX_LOCATION}", + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { + ...provider.settings, + baseURL: + "https://${GOOGLE_VERTEX_ENDPOINT}/v1/projects/${GOOGLE_VERTEX_PROJECT}/locations/${GOOGLE_VERTEX_LOCATION}", } - provider.request.body.project = "config-project" - provider.request.body.location = "eu" + provider.settings = { ...provider.settings, project: "config-project", location: "eu" } }), ) yield* addPlugin() const provider = required(yield* catalog.provider.get(ProviderV2.ID.make("google-vertex"))) - expect(provider.api).toEqual({ - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://eu-aiplatform.googleapis.com/v1/projects/config-project/locations/eu", + expect(provider).toMatchObject({ + package: "aisdk:@ai-sdk/openai-compatible", + settings: { baseURL: "https://eu-aiplatform.googleapis.com/v1/projects/config-project/locations/eu" }, }) }), ) @@ -270,14 +268,14 @@ describe("GoogleVertexPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("google-vertex"), (provider) => { - provider.api = { type: "aisdk", package: "@ai-sdk/google-vertex" } - provider.request.body.project = "config-project" + provider.package = ProviderV2.aisdk("@ai-sdk/google-vertex") + provider.settings = { ...provider.settings, project: "config-project" } }), ) yield* addPlugin() const provider = required(yield* catalog.provider.get(ProviderV2.ID.make("google-vertex"))) - expect(provider.request.body.project).toBe("config-project") - expect(provider.request.body.location).toBe("us-central1") + expect(provider.settings?.project).toBe("config-project") + expect(provider.settings?.location).toBe("us-central1") }), ), ) @@ -297,11 +295,8 @@ describe("GoogleVertexPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini")), - api: { - id: ModelV2.ID.make("gemini"), - type: "aisdk", - package: "@ai-sdk/google-vertex", - }, + modelID: ModelV2.ID.make("gemini"), + package: "aisdk:@ai-sdk/google-vertex", }), package: "@ai-sdk/google-vertex", options: { name: "google-vertex" }, @@ -345,11 +340,8 @@ describe("GoogleVertexPlugin", () => { aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make("gemini")), - api: { - id: ModelV2.ID.make("gemini"), - type: "aisdk", - package: "@ai-sdk/openai-compatible", - }, + modelID: ModelV2.ID.make("gemini"), + package: "aisdk:@ai-sdk/openai-compatible", }), package: "@ai-sdk/openai-compatible", options: { name: "google-vertex" }, @@ -359,11 +351,11 @@ describe("GoogleVertexPlugin", () => { ;(globalThis as typeof globalThis & { fetch: typeof fetch }).fetch = originalFetch }), ) - expect(fetchCalls).toHaveLength(1) + const vertexCalls = fetchCalls.filter((call) => call.input === "https://vertex.example") + expect(vertexCalls).toHaveLength(1) expect(googleAuthOptions).toEqual([{ scopes: ["https://www.googleapis.com/auth/cloud-platform"] }]) - expect(fetchCalls[0].input).toBe("https://vertex.example") - expect(new Headers(fetchCalls[0].init?.headers).get("authorization")).toBe("Bearer vertex-token") - expect(new Headers(fetchCalls[0].init?.headers).get("x-test")).toBe("1") + expect(new Headers(vertexCalls[0].init?.headers).get("authorization")).toBe("Bearer vertex-token") + expect(new Headers(vertexCalls[0].init?.headers).get("x-test")).toBe("1") }), ) @@ -376,7 +368,8 @@ describe("GoogleVertexPlugin", () => { yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google-vertex"), ModelV2.ID.make(" gemini-2.5-pro ")), - api: { id: ModelV2.ID.make(" gemini-2.5-pro "), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make(" gemini-2.5-pro "), + package: "aisdk:test-provider", }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: {}, diff --git a/packages/core/test/plugin/provider-google.test.ts b/packages/core/test/plugin/provider-google.test.ts index 8c10689ca11..d04e00e3b32 100644 --- a/packages/core/test/plugin/provider-google.test.ts +++ b/packages/core/test/plugin/provider-google.test.ts @@ -27,7 +27,8 @@ describe("GooglePlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-google"), ModelV2.ID.make("gemini")), - api: { id: ModelV2.ID.make("gemini"), type: "aisdk", package: "@ai-sdk/google" }, + modelID: ModelV2.ID.make("gemini"), + package: "aisdk:@ai-sdk/google", }), package: "@ai-sdk/google", options: { name: "custom-google", apiKey: "test" }, @@ -45,7 +46,8 @@ describe("GooglePlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("google"), ModelV2.ID.make("gemini")), - api: { id: ModelV2.ID.make("gemini"), type: "aisdk", package: "@ai-sdk/google" }, + modelID: ModelV2.ID.make("gemini"), + package: "aisdk:@ai-sdk/google", }), package: "@ai-sdk/google-vertex", options: { name: "google" }, @@ -62,7 +64,8 @@ describe("GooglePlugin", () => { const sdkEvent = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-google"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("gemini-api"), type: "aisdk", package: "@ai-sdk/google" }, + modelID: ModelV2.ID.make("gemini-api"), + package: "aisdk:@ai-sdk/google", }), package: "@ai-sdk/google", options: { name: "custom-google", apiKey: "test" }, @@ -72,9 +75,29 @@ describe("GooglePlugin", () => { sdk: sdkEvent.sdk, options: sdkEvent.options, }) - const language = result.language ?? result.sdk.languageModel(result.model.api.id) + const language = result.language ?? result.sdk.languageModel(result.model.modelID ?? result.model.id) expect(language.modelId).toBe("gemini-api") expect(language.provider).toBe("custom-google") }), ) + + it.effect("wraps AI SDK language models for the native runner", () => + Effect.gen(function* () { + const aisdk = yield* AISDK.Service + yield* addPlugin() + + const resolved = yield* aisdk.model( + ModelV2.Info.make({ + ...ModelV2.Info.empty(ProviderV2.ID.make("custom-google"), ModelV2.ID.make("alias")), + modelID: ModelV2.ID.make("gemini-api"), + package: "aisdk:@ai-sdk/google", + settings: { apiKey: "test" }, + }), + ) + + expect(String(resolved.id)).toBe("gemini-api") + expect(String(resolved.provider)).toBe("custom-google") + expect(resolved.route.id).toBe("ai-sdk:@ai-sdk/google") + }), + ) }) diff --git a/packages/core/test/plugin/provider-groq.test.ts b/packages/core/test/plugin/provider-groq.test.ts index ac96ea98a3f..b8900384b7d 100644 --- a/packages/core/test/plugin/provider-groq.test.ts +++ b/packages/core/test/plugin/provider-groq.test.ts @@ -28,7 +28,8 @@ describe("GroqPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("llama")), - api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" }, + modelID: ModelV2.ID.make("llama"), + package: "aisdk:@ai-sdk/groq", }), package: "@ai-sdk/groq", options: { name: "groq" }, @@ -45,7 +46,8 @@ describe("GroqPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("llama")), - api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" }, + modelID: ModelV2.ID.make("llama"), + package: "aisdk:@ai-sdk/groq", }), package: "@ai-sdk/openai-compatible", options: { name: "groq" }, @@ -62,7 +64,8 @@ describe("GroqPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("llama")), - api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" }, + modelID: ModelV2.ID.make("llama"), + package: "aisdk:@ai-sdk/groq", }), package: "@ai-sdk/groq/compat", options: { name: "groq" }, @@ -79,7 +82,8 @@ describe("GroqPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-groq"), ModelV2.ID.make("llama")), - api: { id: ModelV2.ID.make("llama"), type: "aisdk", package: "@ai-sdk/groq" }, + modelID: ModelV2.ID.make("llama"), + package: "aisdk:@ai-sdk/groq", }), package: "@ai-sdk/groq", options: { name: "custom-groq", apiKey: "test" }, @@ -93,7 +97,7 @@ describe("GroqPlugin", () => { }), ) - it.effect("uses the default languageModel(api.id) behavior", () => + it.effect("uses the default languageModel(modelID) behavior", () => Effect.gen(function* () { const plugin = yield* PluginV2.Service const aisdk = yield* AISDK.Service @@ -104,16 +108,13 @@ describe("GroqPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("groq"), ModelV2.ID.make("alias")), - api: { - id: ModelV2.ID.make("llama-api"), - type: "aisdk", - package: "@ai-sdk/groq", - }, + modelID: ModelV2.ID.make("llama-api"), + package: "aisdk:@ai-sdk/groq", }), sdk, options: { name: "groq", apiKey: "test" }, }) - const language = result.language ?? sdk.languageModel(result.model.api.id) + const language = result.language ?? sdk.languageModel(result.model.modelID ?? result.model.id) expect(language.modelId).toBe("llama-api") expect(language.provider).toBe("groq.chat") }), diff --git a/packages/core/test/plugin/provider-kilo.test.ts b/packages/core/test/plugin/provider-kilo.test.ts index 1ff356523ca..e4af57cda6b 100644 --- a/packages/core/test/plugin/provider-kilo.test.ts +++ b/packages/core/test/plugin/provider-kilo.test.ts @@ -22,27 +22,24 @@ describe("KiloPlugin", () => { Effect.sync(() => expect(ProviderPlugins.map((item) => item.id)).toContain("opencode.provider.kilo")), ) - it.effect("applies legacy referer headers only to kilo", () => + it.effect("applies legacy referer headers only to Kilo endpoints", () => Effect.gen(function* () { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("kilo"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://api.kilo.ai/api/gateway", - } - provider.request = { settings: {}, headers: { Existing: "value" }, body: {} } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://api.kilo.ai/api/gateway" } + provider.headers = { Existing: "value" } }) catalog.provider.update(ProviderV2.ID.openrouter, () => {}) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.headers).toEqual({ Existing: "value", "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode", }) - expect((yield* catalog.provider.get(ProviderV2.ID.openrouter))?.request.headers).toEqual({}) + expect((yield* catalog.provider.get(ProviderV2.ID.openrouter))?.headers).toBeUndefined() }), ) @@ -51,49 +48,41 @@ describe("KiloPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("kilo"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://api.kilo.ai/api/gateway", - } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://api.kilo.ai/api/gateway" } }) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.headers).toEqual({ "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode", }) - expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.request.headers).not.toHaveProperty( - "http-referer", - ) - expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.request.headers).not.toHaveProperty("x-title") - expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.request.headers).not.toHaveProperty("X-Source") + expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.headers).not.toHaveProperty("http-referer") + expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.headers).not.toHaveProperty("x-title") + expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.headers).not.toHaveProperty("X-Source") }), ) - it.effect("uses the legacy provider-id guard instead of endpoint package matching", () => + it.effect("uses endpoint package matching instead of a provider ID guard", () => Effect.gen(function* () { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("kilo"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://api.kilo.ai/api/gateway", - } + provider.package = ProviderV2.aisdk("kilo") }) catalog.provider.update(ProviderV2.ID.make("custom-kilo"), (provider) => { - provider.api = { type: "aisdk", package: "kilo" } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://api.kilo.ai/api/gateway" } }) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.make("kilo")))?.headers).toBeUndefined() + expect((yield* catalog.provider.get(ProviderV2.ID.make("custom-kilo")))?.headers).toEqual({ "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode", }) - expect((yield* catalog.provider.get(ProviderV2.ID.make("custom-kilo")))?.request.headers).toEqual({}) }), ) }) diff --git a/packages/core/test/plugin/provider-llmgateway.test.ts b/packages/core/test/plugin/provider-llmgateway.test.ts index 8f4af578898..9ff6d2566e7 100644 --- a/packages/core/test/plugin/provider-llmgateway.test.ts +++ b/packages/core/test/plugin/provider-llmgateway.test.ts @@ -34,23 +34,20 @@ describe("LLMGatewayPlugin", () => { }) yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("llmgateway"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://api.llmgateway.io/v1", - } - provider.request = { settings: {}, headers: { Existing: "value" }, body: {} } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://api.llmgateway.io/v1" } + provider.headers = { Existing: "value" } }) catalog.provider.update(ProviderV2.ID.openrouter, () => {}) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("llmgateway")))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.make("llmgateway")))?.headers).toEqual({ Existing: "value", "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode", "X-Source": "opencode", }) - expect((yield* catalog.provider.get(ProviderV2.ID.openrouter))?.request.headers).toEqual({}) + expect((yield* catalog.provider.get(ProviderV2.ID.openrouter))?.headers).toBeUndefined() }), ) @@ -64,17 +61,14 @@ describe("LLMGatewayPlugin", () => { yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("llmgateway"), (provider) => { provider.disabled = true - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://api.llmgateway.io/v1", - } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://api.llmgateway.io/v1" } }) }) yield* addPlugin() expect((yield* catalog.provider.get(ProviderV2.ID.make("llmgateway")))?.disabled).toBe(true) - expect((yield* catalog.provider.get(ProviderV2.ID.make("llmgateway")))?.request.headers).toEqual({}) + expect((yield* catalog.provider.get(ProviderV2.ID.make("llmgateway")))?.headers).toBeUndefined() }), ) }) diff --git a/packages/core/test/plugin/provider-mistral.test.ts b/packages/core/test/plugin/provider-mistral.test.ts index b1b1bc0638c..182873482cf 100644 --- a/packages/core/test/plugin/provider-mistral.test.ts +++ b/packages/core/test/plugin/provider-mistral.test.ts @@ -28,7 +28,8 @@ describe("MistralPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("mistral-large")), - api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("mistral-large"), + package: "aisdk:test-provider", }), package: "@ai-sdk/mistral", options: { name: "mistral" }, @@ -45,7 +46,8 @@ describe("MistralPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("mistral-large")), - api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("mistral-large"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "mistral" }, @@ -68,7 +70,8 @@ describe("MistralPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("mistral-large")), - api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("mistral-large"), + package: "aisdk:test-provider", }), package: "@ai-sdk/mistral", options: { name: "mistral" }, @@ -92,7 +95,8 @@ describe("MistralPlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-mistral"), ModelV2.ID.make("mistral-large")), - api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("mistral-large"), + package: "aisdk:test-provider", }), package: "@ai-sdk/mistral", options: { name: "custom-mistral" }, @@ -101,7 +105,7 @@ describe("MistralPlugin", () => { }), ) - it.effect("leaves Mistral language selection on the default sdk.languageModel(api.id) path", () => + it.effect("leaves Mistral language selection on the default sdk.languageModel(modelID) path", () => Effect.gen(function* () { const plugin = yield* PluginV2.Service const aisdk = yield* AISDK.Service @@ -116,12 +120,13 @@ describe("MistralPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("mistral"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("mistral-large"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("mistral-large"), + package: "aisdk:test-provider", }), sdk, options: {}, }) - const language = result.language ?? sdk.languageModel(result.model.api.id) + const language = result.language ?? sdk.languageModel(result.model.modelID ?? result.model.id) expect(calls).toEqual(["languageModel:mistral-large"]) expect(language).toBeDefined() }), diff --git a/packages/core/test/plugin/provider-nvidia.test.ts b/packages/core/test/plugin/provider-nvidia.test.ts index c176cef4ac6..47f78fd0228 100644 --- a/packages/core/test/plugin/provider-nvidia.test.ts +++ b/packages/core/test/plugin/provider-nvidia.test.ts @@ -27,23 +27,20 @@ describe("NvidiaPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("nvidia"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://integrate.api.nvidia.com/v1", - } - provider.request = { settings: {}, headers: { Existing: "value" }, body: {} } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://integrate.api.nvidia.com/v1" } + provider.headers = { Existing: "value" } }) catalog.provider.update(ProviderV2.ID.openrouter, () => {}) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("nvidia")))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.make("nvidia")))?.headers).toEqual({ Existing: "value", "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode", "X-BILLING-INVOKE-ORIGIN": "OpenCode", }) - expect((yield* catalog.provider.get(ProviderV2.ID.openrouter))?.request.headers).toEqual({}) + expect((yield* catalog.provider.get(ProviderV2.ID.openrouter))?.headers).toBeUndefined() }), ) @@ -52,16 +49,13 @@ describe("NvidiaPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("nvidia"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://integrate.api.nvidia.com/v1", - } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://integrate.api.nvidia.com/v1" } }) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("nvidia")))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.make("nvidia")))?.headers).toEqual({ "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode", "X-BILLING-INVOKE-ORIGIN": "OpenCode", @@ -74,21 +68,14 @@ describe("NvidiaPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("nvidia"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://integrate.api.nvidia.com/v1", - } - provider.request = { - settings: {}, - headers: { "X-BILLING-INVOKE-ORIGIN": "CustomOrigin" }, - body: { baseURL: "https://integrate.api.nvidia.com/v1" }, - } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { baseURL: "https://integrate.api.nvidia.com/v1" } + provider.headers = { "X-BILLING-INVOKE-ORIGIN": "CustomOrigin" } }) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("nvidia")))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.make("nvidia")))?.headers).toEqual({ "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode", "X-BILLING-INVOKE-ORIGIN": "CustomOrigin", diff --git a/packages/core/test/plugin/provider-openai-compatible.test.ts b/packages/core/test/plugin/provider-openai-compatible.test.ts index 4e74a37125d..a954af9f00a 100644 --- a/packages/core/test/plugin/provider-openai-compatible.test.ts +++ b/packages/core/test/plugin/provider-openai-compatible.test.ts @@ -27,7 +27,8 @@ describe("OpenAICompatiblePlugin", () => { const defaulted = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "custom" }, @@ -35,7 +36,8 @@ describe("OpenAICompatiblePlugin", () => { const disabled = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "custom", includeUsage: false }, @@ -53,7 +55,8 @@ describe("OpenAICompatiblePlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "file:///tmp/@ai-sdk/openai-compatible-provider.js", options: { name: "custom" }, @@ -76,7 +79,8 @@ describe("OpenAICompatiblePlugin", () => { yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-provider"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "custom-provider", baseURL: "https://example.com/v1" }, @@ -96,7 +100,8 @@ describe("OpenAICompatiblePlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("cloudflare-workers-ai"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "cloudflare-workers-ai" }, diff --git a/packages/core/test/plugin/provider-openai.test.ts b/packages/core/test/plugin/provider-openai.test.ts index 44941a4aa1e..f20091d514d 100644 --- a/packages/core/test/plugin/provider-openai.test.ts +++ b/packages/core/test/plugin/provider-openai.test.ts @@ -82,7 +82,8 @@ describe("OpenAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-openai"), ModelV2.ID.make("gpt-5")), - api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/openai", options: { name: "custom-openai", apiKey: "test" }, @@ -99,7 +100,8 @@ describe("OpenAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("gpt-5")), - api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/openai-compatible", options: { name: "openai" }, @@ -117,7 +119,8 @@ describe("OpenAIPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5"), + package: ProviderV2.aisdk("test-provider"), }), sdk: fakeSelectorSdk(calls), options: {}, @@ -136,7 +139,8 @@ describe("OpenAIPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.anthropic, ModelV2.ID.make("gpt-5")), - api: { id: ModelV2.ID.make("gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-5"), + package: ProviderV2.aisdk("test-provider"), }), sdk: fakeSelectorSdk(calls), options: {}, @@ -152,10 +156,10 @@ describe("OpenAIPlugin", () => { yield* catalog.transform((catalog) => { const item = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.openai), - api: { type: "aisdk", package: "@ai-sdk/openai" }, + package: ProviderV2.aisdk("@ai-sdk/openai"), }) catalog.provider.update(item.id, (draft) => { - draft.api = item.api + draft.package = item.package }) catalog.model.update(item.id, ModelV2.ID.make("gpt-5"), () => {}) catalog.model.update(item.id, ModelV2.ID.make("gpt-5-chat-latest"), () => {}) @@ -175,10 +179,10 @@ describe("OpenAIPlugin", () => { yield* catalog.transform((catalog) => { const item = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.openai), - api: { type: "aisdk", package: "@ai-sdk/openai" }, + package: ProviderV2.aisdk("@ai-sdk/openai"), }) catalog.provider.update(item.id, (draft) => { - draft.api = item.api + draft.package = item.package }) catalog.model.update(item.id, ModelV2.ID.make("gpt-5.5"), (model) => { model.cost = [{ input: 1, output: 2, cache: { read: 0.1, write: 0 } }] @@ -220,10 +224,10 @@ describe("OpenAIPlugin", () => { yield* catalog.transform((catalog) => { const item = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.openai), - api: { type: "aisdk", package: "@ai-sdk/openai" }, + package: ProviderV2.aisdk("@ai-sdk/openai"), }) catalog.provider.update(item.id, (draft) => { - draft.api = item.api + draft.package = item.package }) catalog.model.update(item.id, ModelV2.ID.make("gpt-5.5"), () => {}) catalog.model.update(item.id, ModelV2.ID.make("gpt-4.1"), () => {}) @@ -248,10 +252,10 @@ describe("OpenAIPlugin", () => { yield* catalog.transform((catalog) => { const item = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.make("custom-openai")), - api: { type: "aisdk", package: "test-provider" }, + package: ProviderV2.aisdk("test-provider"), }) catalog.provider.update(item.id, (draft) => { - draft.api = item.api + draft.package = item.package }) catalog.model.update(item.id, ModelV2.ID.make("gpt-5-chat-latest"), () => {}) }) diff --git a/packages/core/test/plugin/provider-opencode.test.ts b/packages/core/test/plugin/provider-opencode.test.ts index d2b1f2bdaea..c8b3757d3d8 100644 --- a/packages/core/test/plugin/provider-opencode.test.ts +++ b/packages/core/test/plugin/provider-opencode.test.ts @@ -172,13 +172,10 @@ describe("OpencodePlugin", () => { expect(provider).toMatchObject({ name: "Remote", integrationID: "opencode", - api: { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: `${server.url.origin}/v1`, - }, + package: ProviderV2.aisdk("@ai-sdk/openai-compatible"), + settings: { baseURL: `${server.url.origin}/v1`, custom: "value" }, + headers: { "x-org-id": "org" }, }) - expect(provider.request).toEqual({ settings: {}, headers: { "x-org-id": "org" }, body: { custom: "value" } }) expect(yield* (yield* Integration.Service).get(Integration.ID.make("remote"))).toBeUndefined() const model = required(yield* catalog.model.get(ProviderV2.ID.make("remote"), ModelV2.ID.make("model"))) @@ -188,8 +185,10 @@ describe("OpencodePlugin", () => { capabilities: { tools: true, input: ["text", "image"], output: ["text"] }, cost: [{ input: 1, output: 2, cache: { read: 0.1, write: 0 } }], limit: { context: 1000, output: 100 }, + package: ProviderV2.aisdk("@ai-sdk/openai-compatible"), + settings: { baseURL: `${server.url.origin}/v1`, custom: "value", temperature: 0.5 }, + headers: { "x-org-id": "org" }, }) - expect(model.request.body).toEqual({ custom: "value", temperature: 0.5 }) expect(model.variants).toEqual([ { id: ModelV2.VariantID.make("custom"), @@ -199,9 +198,8 @@ describe("OpencodePlugin", () => { }, { id: ModelV2.VariantID.make("high"), - settings: {}, + settings: { temperature: 0.2 }, headers: {}, - body: { temperature: 0.2 }, }, ]) expect( @@ -221,11 +219,12 @@ describe("OpencodePlugin", () => { yield* catalog.transform((catalog) => { const provider = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.opencode), - api: { type: "aisdk", package: "test-provider" }, + package: ProviderV2.aisdk("test-provider"), }) const model = ModelV2.Info.make({ ...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")), - api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("paid"), + package: ProviderV2.aisdk("test-provider"), cost: cost(1), }) catalog.provider.update(provider.id, () => {}) @@ -234,7 +233,7 @@ describe("OpencodePlugin", () => { }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).request.body.apiKey).toBe("public") + expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).settings?.apiKey).toBe("public") expect(required(yield* catalog.model.get(ProviderV2.ID.opencode, ModelV2.ID.make("paid"))).enabled).toBe(false) }), ), @@ -247,11 +246,12 @@ describe("OpencodePlugin", () => { yield* catalog.transform((catalog) => { const provider = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.opencode), - api: { type: "aisdk", package: "test-provider" }, + package: ProviderV2.aisdk("test-provider"), }) const model = ModelV2.Info.make({ ...ModelV2.Info.empty(provider.id, ModelV2.ID.make("free")), - api: { id: ModelV2.ID.make("free"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("free"), + package: ProviderV2.aisdk("test-provider"), cost: cost(0), }) catalog.provider.update(provider.id, () => {}) @@ -260,7 +260,7 @@ describe("OpencodePlugin", () => { }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).request.body.apiKey).toBe("public") + expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).settings?.apiKey).toBe("public") expect(required(yield* catalog.model.get(ProviderV2.ID.opencode, ModelV2.ID.make("free"))).enabled).toBe(true) }), ), @@ -273,11 +273,12 @@ describe("OpencodePlugin", () => { yield* catalog.transform((catalog) => { const provider = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.opencode), - api: { type: "aisdk", package: "test-provider" }, + package: ProviderV2.aisdk("test-provider"), }) const model = ModelV2.Info.make({ ...ModelV2.Info.empty(provider.id, ModelV2.ID.make("output-only")), - api: { id: ModelV2.ID.make("output-only"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("output-only"), + package: ProviderV2.aisdk("test-provider"), cost: cost(0, 1), }) catalog.provider.update(provider.id, () => {}) @@ -286,7 +287,7 @@ describe("OpencodePlugin", () => { }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).request.body.apiKey).toBe("public") + expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).settings?.apiKey).toBe("public") expect(required(yield* catalog.model.get(ProviderV2.ID.opencode, ModelV2.ID.make("output-only"))).enabled).toBe( true, ) @@ -301,11 +302,12 @@ describe("OpencodePlugin", () => { yield* catalog.transform((catalog) => { const provider = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.opencode), - api: { type: "aisdk", package: "test-provider" }, + package: ProviderV2.aisdk("test-provider"), }) const model = ModelV2.Info.make({ ...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")), - api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("paid"), + package: ProviderV2.aisdk("test-provider"), cost: cost(1), }) catalog.provider.update(provider.id, () => {}) @@ -314,7 +316,7 @@ describe("OpencodePlugin", () => { }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).request.body.apiKey).toBeUndefined() + expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).settings?.apiKey).toBeUndefined() expect(required(yield* catalog.model.get(ProviderV2.ID.opencode, ModelV2.ID.make("paid"))).enabled).toBe(true) }), ), @@ -334,11 +336,12 @@ describe("OpencodePlugin", () => { yield* catalog.transform((catalog) => { const provider = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.opencode), - api: { type: "aisdk", package: "test-provider" }, + package: ProviderV2.aisdk("test-provider"), }) const model = ModelV2.Info.make({ ...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")), - api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("paid"), + package: ProviderV2.aisdk("test-provider"), cost: cost(1), }) catalog.provider.update(provider.id, () => {}) @@ -347,7 +350,7 @@ describe("OpencodePlugin", () => { }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).request.body.apiKey).toBeUndefined() + expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).settings?.apiKey).toBeUndefined() expect(required(yield* catalog.model.get(ProviderV2.ID.opencode, ModelV2.ID.make("paid"))).enabled).toBe(true) }), ), @@ -360,27 +363,25 @@ describe("OpencodePlugin", () => { yield* catalog.transform((catalog) => { const provider = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.opencode), - api: { type: "aisdk", package: "test-provider" }, - request: { - settings: {}, - headers: {}, - body: { apiKey: "configured" }, - }, + package: ProviderV2.aisdk("test-provider"), + settings: { apiKey: "configured" }, }) const model = ModelV2.Info.make({ ...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")), - api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("paid"), + package: ProviderV2.aisdk("test-provider"), cost: cost(1), }) catalog.provider.update(provider.id, (draft) => { - draft.request = { settings: {}, headers: {}, body: { apiKey: "configured" } } + draft.package = provider.package + draft.settings = { apiKey: "configured" } }) catalog.model.update(provider.id, model.id, (draft) => { draft.cost = [...model.cost] }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).request.body.apiKey).toBe("configured") + expect(required(yield* catalog.provider.get(ProviderV2.ID.opencode)).settings?.apiKey).toBe("configured") expect(required(yield* catalog.model.get(ProviderV2.ID.opencode, ModelV2.ID.make("paid"))).enabled).toBe(true) }), ), @@ -393,11 +394,12 @@ describe("OpencodePlugin", () => { yield* catalog.transform((catalog) => { const provider = ProviderV2.Info.make({ ...ProviderV2.Info.empty(ProviderV2.ID.openai), - api: { type: "aisdk", package: "test-provider" }, + package: ProviderV2.aisdk("test-provider"), }) const model = ModelV2.Info.make({ ...ModelV2.Info.empty(provider.id, ModelV2.ID.make("paid")), - api: { id: ModelV2.ID.make("paid"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("paid"), + package: ProviderV2.aisdk("test-provider"), cost: cost(1), }) catalog.provider.update(provider.id, () => {}) @@ -406,7 +408,7 @@ describe("OpencodePlugin", () => { }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.openai)).request.body.apiKey).toBeUndefined() + expect(required(yield* catalog.provider.get(ProviderV2.ID.openai)).settings?.apiKey).toBeUndefined() expect(required(yield* catalog.model.get(ProviderV2.ID.openai, ModelV2.ID.make("paid"))).enabled).toBe(true) }), ), diff --git a/packages/core/test/plugin/provider-openrouter.test.ts b/packages/core/test/plugin/provider-openrouter.test.ts index 60dfc67b51e..21ee3ae216a 100644 --- a/packages/core/test/plugin/provider-openrouter.test.ts +++ b/packages/core/test/plugin/provider-openrouter.test.ts @@ -30,19 +30,19 @@ describe("OpenRouterPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.openrouter, (provider) => { - provider.api = { type: "aisdk", package: "@openrouter/ai-sdk-provider" } - provider.request = { settings: {}, headers: { Existing: "value" }, body: {} } + provider.package = ProviderV2.aisdk("@openrouter/ai-sdk-provider") + provider.headers = { Existing: "value" } }) catalog.provider.update(ProviderV2.ID.make("nvidia"), () => {}) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.openrouter))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.openrouter))?.headers).toEqual({ Existing: "value", "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode", }) - expect((yield* catalog.provider.get(ProviderV2.ID.make("nvidia")))?.request.headers).toEqual({}) + expect((yield* catalog.provider.get(ProviderV2.ID.make("nvidia")))?.headers).toBeUndefined() }), ) @@ -55,7 +55,8 @@ describe("OpenRouterPlugin", () => { const ignored = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.openrouter, ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@ai-sdk/openai-compatible", options: { name: "openrouter" }, @@ -65,7 +66,8 @@ describe("OpenRouterPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom"), ModelV2.ID.make("openai/gpt-5")), - api: { id: ModelV2.ID.make("openai/gpt-5"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("openai/gpt-5"), + package: ProviderV2.aisdk("test-provider"), }), package: "@openrouter/ai-sdk-provider", options: { name: "custom" }, @@ -79,7 +81,7 @@ describe("OpenRouterPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.openrouter, (provider) => { - provider.api = { type: "aisdk", package: "@openrouter/ai-sdk-provider" } + provider.package = ProviderV2.aisdk("@openrouter/ai-sdk-provider") }) catalog.provider.update(ProviderV2.ID.openai, () => {}) catalog.model.update(ProviderV2.ID.openrouter, ModelV2.ID.make("openai/gpt-5-chat"), () => {}) diff --git a/packages/core/test/plugin/provider-perplexity.test.ts b/packages/core/test/plugin/provider-perplexity.test.ts index a2a39692330..d66f5dd71c4 100644 --- a/packages/core/test/plugin/provider-perplexity.test.ts +++ b/packages/core/test/plugin/provider-perplexity.test.ts @@ -41,7 +41,8 @@ describe("PerplexityPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("sonar")), - api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("sonar"), + package: "aisdk:test-provider", }), package: "@ai-sdk/perplexity", options: { name: "perplexity" }, @@ -58,7 +59,8 @@ describe("PerplexityPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("sonar")), - api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("sonar"), + package: "aisdk:test-provider", }), package: "@ai-sdk/perplexity-compatible", options: { name: "perplexity" }, @@ -75,7 +77,8 @@ describe("PerplexityPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("sonar")), - api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("sonar"), + package: "aisdk:test-provider", }), package: "@ai-sdk/perplexity", options: { name: "perplexity" }, @@ -92,7 +95,8 @@ describe("PerplexityPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-perplexity"), ModelV2.ID.make("sonar")), - api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("sonar"), + package: "aisdk:test-provider", }), package: "@ai-sdk/perplexity", options: { name: "custom-perplexity" }, @@ -110,7 +114,8 @@ describe("PerplexityPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("perplexity"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("sonar"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("sonar"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, diff --git a/packages/core/test/plugin/provider-sap-ai-core.test.ts b/packages/core/test/plugin/provider-sap-ai-core.test.ts index 5056c5dbb7e..8822866be8e 100644 --- a/packages/core/test/plugin/provider-sap-ai-core.test.ts +++ b/packages/core/test/plugin/provider-sap-ai-core.test.ts @@ -49,7 +49,8 @@ function withEnv(vars: Record, effect: () = function model(providerID: string) { return ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make(providerID), ModelV2.ID.make("sap-model")), - api: { id: ModelV2.ID.make("sap-model"), type: "aisdk", package: fixtureProvider }, + modelID: ModelV2.ID.make("sap-model"), + package: ProviderV2.aisdk(fixtureProvider), }) } diff --git a/packages/core/test/plugin/provider-snowflake-cortex.test.ts b/packages/core/test/plugin/provider-snowflake-cortex.test.ts index 4de00105b75..92af6237566 100644 --- a/packages/core/test/plugin/provider-snowflake-cortex.test.ts +++ b/packages/core/test/plugin/provider-snowflake-cortex.test.ts @@ -59,7 +59,8 @@ describe("SnowflakeCortexPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("openai"), ModelV2.ID.make("gpt-4")), - api: { id: ModelV2.ID.make("gpt-4"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("gpt-4"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai", options: { name: "openai" }, @@ -77,7 +78,8 @@ describe("SnowflakeCortexPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")), - api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-6"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "snowflake-cortex", baseURL: "https://test.snowflakecomputing.com/api/v2/cortex/v1" }, @@ -96,7 +98,8 @@ describe("SnowflakeCortexPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")), - api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-6"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { @@ -119,7 +122,8 @@ describe("SnowflakeCortexPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")), - api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-6"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "snowflake-cortex", baseURL: "https://test.snowflakecomputing.com/api/v2/cortex/v1" }, @@ -138,7 +142,8 @@ describe("SnowflakeCortexPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")), - api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-6"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { @@ -161,7 +166,8 @@ describe("SnowflakeCortexPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("snowflake-cortex"), ModelV2.ID.make("claude-sonnet-4-6")), - api: { id: ModelV2.ID.make("claude-sonnet-4-6"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("claude-sonnet-4-6"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "snowflake-cortex", baseURL: "https://test.snowflakecomputing.com/api/v2/cortex/v1" }, diff --git a/packages/core/test/plugin/provider-togetherai.test.ts b/packages/core/test/plugin/provider-togetherai.test.ts index 56bf7c96429..1fffb03156a 100644 --- a/packages/core/test/plugin/provider-togetherai.test.ts +++ b/packages/core/test/plugin/provider-togetherai.test.ts @@ -41,7 +41,8 @@ describe("TogetherAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("togetherai"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "@ai-sdk/togetherai", options: { name: "togetherai" }, @@ -59,7 +60,8 @@ describe("TogetherAIPlugin", () => { const ignored = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("togetherai"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "file:///tmp/@ai-sdk/togetherai-provider.js", options: { name: "togetherai" }, @@ -69,7 +71,8 @@ describe("TogetherAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("togetherai"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "@ai-sdk/togetherai", options: { name: "togetherai" }, @@ -87,7 +90,8 @@ describe("TogetherAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-togetherai"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "@ai-sdk/togetherai", options: { name: "custom-togetherai" }, @@ -110,11 +114,8 @@ describe("TogetherAIPlugin", () => { ProviderV2.ID.make("togetherai"), ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct-Turbo"), ), - api: { - id: ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct-Turbo"), - type: "aisdk", - package: "test-provider", - }, + modelID: ModelV2.ID.make("meta-llama/Llama-3.3-70B-Instruct-Turbo"), + package: "aisdk:test-provider", }), sdk: { languageModel: fakeSelectorSdk(calls).languageModel }, options: {}, @@ -122,7 +123,9 @@ describe("TogetherAIPlugin", () => { expect(result.language).toBeUndefined() expect(calls).toEqual([]) - expect(result.language ?? fakeSelectorSdk(calls).languageModel(result.model.api.id)).toBeDefined() + expect( + result.language ?? fakeSelectorSdk(calls).languageModel(result.model.modelID ?? result.model.id), + ).toBeDefined() expect(calls).toEqual(["languageModel:meta-llama/Llama-3.3-70B-Instruct-Turbo"]) }), ) diff --git a/packages/core/test/plugin/provider-venice.test.ts b/packages/core/test/plugin/provider-venice.test.ts index 3ed6c711c49..057d2c6ded9 100644 --- a/packages/core/test/plugin/provider-venice.test.ts +++ b/packages/core/test/plugin/provider-venice.test.ts @@ -41,7 +41,8 @@ describe("VenicePlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "venice-ai-sdk-provider", options: { name: "venice" }, @@ -58,7 +59,8 @@ describe("VenicePlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-venice"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "venice-ai-sdk-provider", options: { name: "custom-venice", apiKey: "test" }, @@ -76,7 +78,8 @@ describe("VenicePlugin", () => { const similar = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "file:///tmp/venice-ai-sdk-provider.js", options: { name: "venice" }, @@ -84,7 +87,8 @@ describe("VenicePlugin", () => { const other = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("model")), - api: { id: ModelV2.ID.make("model"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("model"), + package: "aisdk:test-provider", }), package: "@ai-sdk/openai-compatible", options: { name: "venice" }, @@ -103,7 +107,8 @@ describe("VenicePlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("venice"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("alias"), type: "aisdk", package: "test-provider" }, + modelID: ModelV2.ID.make("alias"), + package: "aisdk:test-provider", }), sdk: fakeSelectorSdk(calls), options: {}, diff --git a/packages/core/test/plugin/provider-vercel.test.ts b/packages/core/test/plugin/provider-vercel.test.ts index eb87b15132f..46d5fe25b80 100644 --- a/packages/core/test/plugin/provider-vercel.test.ts +++ b/packages/core/test/plugin/provider-vercel.test.ts @@ -25,12 +25,12 @@ describe("VercelPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("vercel"), (provider) => { - provider.api = { type: "aisdk", package: "@ai-sdk/vercel" } - provider.request.headers.Existing = "1" + provider.package = ProviderV2.aisdk("@ai-sdk/vercel") + provider.headers = { ...provider.headers, Existing: "1" } }) }) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("vercel")))?.request.headers).toEqual({ + expect((yield* catalog.provider.get(ProviderV2.ID.make("vercel")))?.headers).toEqual({ Existing: "1", "http-referer": "https://opencode.ai/", "x-title": "opencode", @@ -43,14 +43,12 @@ describe("VercelPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("vercel"), (provider) => { - provider.api = { type: "aisdk", package: "@ai-sdk/vercel" } + provider.package = ProviderV2.aisdk("@ai-sdk/vercel") }), ) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("vercel")))?.request.headers).not.toHaveProperty( - "HTTP-Referer", - ) - expect((yield* catalog.provider.get(ProviderV2.ID.make("vercel")))?.request.headers).not.toHaveProperty("X-Title") + expect((yield* catalog.provider.get(ProviderV2.ID.make("vercel")))?.headers).not.toHaveProperty("HTTP-Referer") + expect((yield* catalog.provider.get(ProviderV2.ID.make("vercel")))?.headers).not.toHaveProperty("X-Title") }), ) @@ -62,7 +60,8 @@ describe("VercelPlugin", () => { const event = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-vercel"), ModelV2.ID.make("v0-1.0-md")), - api: { id: ModelV2.ID.make("v0-1.0-md"), type: "aisdk", package: "@ai-sdk/vercel" }, + modelID: ModelV2.ID.make("v0-1.0-md"), + package: "aisdk:@ai-sdk/vercel", }), package: "@ai-sdk/vercel", options: { name: "custom-vercel" }, @@ -77,7 +76,7 @@ describe("VercelPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.make("gateway"), () => {})) yield* addPlugin() - expect((yield* catalog.provider.get(ProviderV2.ID.make("gateway")))?.request.headers).toEqual({}) + expect((yield* catalog.provider.get(ProviderV2.ID.make("gateway")))?.headers).toBeUndefined() }), ) }) diff --git a/packages/core/test/plugin/provider-xai.test.ts b/packages/core/test/plugin/provider-xai.test.ts index c4d1a5ece37..94824af3396 100644 --- a/packages/core/test/plugin/provider-xai.test.ts +++ b/packages/core/test/plugin/provider-xai.test.ts @@ -42,7 +42,8 @@ describe("XAIPlugin", () => { const ignored = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("xai"), ModelV2.ID.make("grok-4")), - api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" }, + modelID: ModelV2.ID.make("grok-4"), + package: "aisdk:@ai-sdk/xai", }), package: "@ai-sdk/openai-compatible", options: {}, @@ -51,7 +52,8 @@ describe("XAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("xai"), ModelV2.ID.make("grok-4")), - api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" }, + modelID: ModelV2.ID.make("grok-4"), + package: "aisdk:@ai-sdk/xai", }), package: "@ai-sdk/xai", options: {}, @@ -71,7 +73,8 @@ describe("XAIPlugin", () => { const result = yield* aisdk.runSDK({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("custom-xai"), ModelV2.ID.make("grok-4")), - api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" }, + modelID: ModelV2.ID.make("grok-4"), + package: "aisdk:@ai-sdk/xai", }), package: "@ai-sdk/xai", options: {}, @@ -81,7 +84,7 @@ describe("XAIPlugin", () => { }), ) - it.effect("uses responses with the model api.id for xAI language models", () => + it.effect("uses responses with the model modelID for xAI language models", () => Effect.gen(function* () { const plugin = yield* PluginV2.Service const aisdk = yield* AISDK.Service @@ -91,7 +94,8 @@ describe("XAIPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.make("xai"), ModelV2.ID.make("alias")), - api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" }, + modelID: ModelV2.ID.make("grok-4"), + package: "aisdk:@ai-sdk/xai", }), sdk: fakeSelectorSdk(calls), options: {}, @@ -112,7 +116,8 @@ describe("XAIPlugin", () => { const result = yield* aisdk.runLanguage({ model: ModelV2.Info.make({ ...ModelV2.Info.empty(ProviderV2.ID.openai, ModelV2.ID.make("grok-4")), - api: { id: ModelV2.ID.make("grok-4"), type: "aisdk", package: "@ai-sdk/xai" }, + modelID: ModelV2.ID.make("grok-4"), + package: "aisdk:@ai-sdk/xai", }), sdk: fakeSelectorSdk(calls), options: {}, diff --git a/packages/core/test/plugin/provider-zenmux.test.ts b/packages/core/test/plugin/provider-zenmux.test.ts index 9c44800ebc4..8f3bdd343a0 100644 --- a/packages/core/test/plugin/provider-zenmux.test.ts +++ b/packages/core/test/plugin/provider-zenmux.test.ts @@ -32,17 +32,14 @@ describe("ZenmuxPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("zenmux"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://zenmux.ai/api/v1", - } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { ...provider.settings, baseURL: "https://zenmux.ai/api/v1" } }) }) yield* addPlugin() const result = required(yield* catalog.provider.get(ProviderV2.ID.make("zenmux"))) - expect(result.request.headers).toEqual({ "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode" }) - expect(Object.keys(result.request.headers).sort()).toEqual(["HTTP-Referer", "X-Title"]) + expect(result.headers).toEqual({ "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode" }) + expect(Object.keys(required(result.headers)).sort()).toEqual(["HTTP-Referer", "X-Title"]) }), ) @@ -51,17 +48,14 @@ describe("ZenmuxPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("zenmux"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://zenmux.ai/api/v1", - } - provider.request.headers.Existing = "value" + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { ...provider.settings, baseURL: "https://zenmux.ai/api/v1" } + provider.headers = { ...provider.headers, Existing: "value" } }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.make("zenmux"))).request.headers).toEqual({ + expect(required(yield* catalog.provider.get(ProviderV2.ID.make("zenmux"))).headers).toEqual({ Existing: "value", "HTTP-Referer": "https://opencode.ai/", "X-Title": "opencode", @@ -74,17 +68,14 @@ describe("ZenmuxPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.make("zenmux"), (provider) => { - provider.api = { - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://zenmux.ai/api/v1", - } - provider.request.headers = { "HTTP-Referer": "https://example.com/", "X-Title": "custom-title" } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") + provider.settings = { ...provider.settings, baseURL: "https://zenmux.ai/api/v1" } + provider.headers = { "HTTP-Referer": "https://example.com/", "X-Title": "custom-title" } }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.make("zenmux"))).request.headers).toEqual({ + expect(required(yield* catalog.provider.get(ProviderV2.ID.make("zenmux"))).headers).toEqual({ "HTTP-Referer": "https://example.com/", "X-Title": "custom-title", }) @@ -96,12 +87,12 @@ describe("ZenmuxPlugin", () => { const catalog = yield* Catalog.Service yield* catalog.transform((catalog) => { catalog.provider.update(ProviderV2.ID.openrouter, (provider) => { - provider.request.headers = { "HTTP-Referer": "https://example.com/", "X-Title": "custom-title" } + provider.headers = { "HTTP-Referer": "https://example.com/", "X-Title": "custom-title" } }) }) yield* addPlugin() - expect(required(yield* catalog.provider.get(ProviderV2.ID.openrouter)).request.headers).toEqual({ + expect(required(yield* catalog.provider.get(ProviderV2.ID.openrouter)).headers).toEqual({ "HTTP-Referer": "https://example.com/", "X-Title": "custom-title", }) diff --git a/packages/core/test/plugin/variant.test.ts b/packages/core/test/plugin/variant.test.ts index 61f392caf8c..5f3dafd2099 100644 --- a/packages/core/test/plugin/variant.test.ts +++ b/packages/core/test/plugin/variant.test.ts @@ -24,14 +24,11 @@ describe("VariantPlugin", () => { const service = yield* Catalog.Service yield* service.transform((catalog) => { catalog.provider.update(ProviderV2.ID.opencode, (provider) => { - provider.api = { type: "aisdk", package: "@ai-sdk/openai-compatible" } + provider.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") }) catalog.model.update(ProviderV2.ID.opencode, ModelV2.ID.make("glm-5.2"), (model) => { - model.api = { - id: ModelV2.ID.make("glm-5.2"), - type: "aisdk", - package: "@ai-sdk/openai-compatible", - } + model.modelID = ModelV2.ID.make("glm-5.2") + model.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") }) }) yield* VariantPlugin.Plugin.effect(host({ catalog: catalogHost(service) })) @@ -48,11 +45,8 @@ describe("VariantPlugin", () => { const service = yield* Catalog.Service yield* service.transform((catalog) => { catalog.model.update(ProviderV2.ID.opencode, ModelV2.ID.make("glm-5.2"), (model) => { - model.api = { - id: ModelV2.ID.make("glm-5.2"), - type: "aisdk", - package: "@ai-sdk/openai-compatible", - } + model.modelID = ModelV2.ID.make("glm-5.2") + model.package = ProviderV2.aisdk("@ai-sdk/openai-compatible") model.variants = [{ id: ModelV2.VariantID.make("high"), settings: {}, headers: { custom: "true" }, body: {} }] }) }) diff --git a/packages/core/test/session-instructions.test.ts b/packages/core/test/session-instructions.test.ts index 19e717c8365..854cd73d4be 100644 --- a/packages/core/test/session-instructions.test.ts +++ b/packages/core/test/session-instructions.test.ts @@ -2,8 +2,7 @@ import { describe, expect, test } from "bun:test" import fs from "fs/promises" import path from "path" import { DateTime, Effect, Layer } from "effect" -import { Message, Model } from "@opencode-ai/llm" -import * as OpenAIChat from "@opencode-ai/llm/protocols/openai-chat" +import { Message } from "@opencode-ai/llm" import { AgentV2 } from "@opencode-ai/core/agent" import { AppNodeBuilder } from "@opencode-ai/core/effect/app-node-builder" import { LayerNode } from "@opencode-ai/core/effect/layer-node" @@ -300,7 +299,7 @@ describe("SessionInstructions", () => { test("toLLMMessages does not forward synthetic metadata to the provider", () => { const created = DateTime.makeUnsafe(0) - const model = Model.make({ id: "model", provider: "provider", route: OpenAIChat.route }) + const model = ModelV2.Ref.make({ id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") }) const synthetic = SessionMessage.Synthetic.make({ id: SessionMessage.ID.make("msg_synthetic"), type: "synthetic", diff --git a/packages/core/test/session-runner-message.test.ts b/packages/core/test/session-runner-message.test.ts index 469d5e0360a..f415614cf58 100644 --- a/packages/core/test/session-runner-message.test.ts +++ b/packages/core/test/session-runner-message.test.ts @@ -1,6 +1,5 @@ import { describe, expect, test } from "bun:test" -import { Message, Model } from "@opencode-ai/llm" -import * as OpenAIChat from "@opencode-ai/llm/protocols/openai-chat" +import { Message } from "@opencode-ai/llm" import { ModelV2 } from "@opencode-ai/core/model" import { ProviderV2 } from "@opencode-ai/core/provider" import { SessionMessage } from "@opencode-ai/core/session/message" @@ -12,7 +11,7 @@ import { DateTime } from "effect" const created = DateTime.makeUnsafe(0) const id = (value: string) => SessionMessage.ID.make(`msg_${value}`) -const model = Model.make({ id: "model", provider: "provider", route: OpenAIChat.route }) +const model = ModelV2.Ref.make({ id: ModelV2.ID.make("model"), providerID: ProviderV2.ID.make("provider") }) describe("toLLMMessages", () => { test("omits empty assistant turns", () => { @@ -609,4 +608,35 @@ Recent work }, ]) }) + + test("preserves provider metadata for a catalog alias with a different API model ID", () => { + const messages = toLLMMessages( + [ + SessionMessage.Assistant.make({ + id: id("assistant-alias"), + type: "assistant", + agent: "build", + model: { id: ModelV2.ID.make("fast"), providerID: ProviderV2.ID.make("provider") }, + content: [ + SessionMessage.AssistantReasoning.make({ + type: "reasoning", + id: "reasoning-alias", + text: "Visible thought", + providerMetadata: { openai: { reasoningEncryptedContent: "encrypted" } }, + }), + ], + time: { created, completed: created }, + }), + ], + ModelV2.Ref.make({ id: ModelV2.ID.make("fast"), providerID: ProviderV2.ID.make("provider") }), + ) + + expect(messages[0]?.content).toEqual([ + { + type: "reasoning", + text: "Visible thought", + providerMetadata: { openai: { reasoningEncryptedContent: "encrypted" } }, + }, + ]) + }) }) diff --git a/packages/core/test/session-runner-model.test.ts b/packages/core/test/session-runner-model.test.ts index 6d11bd877a5..14bfc37bbe6 100644 --- a/packages/core/test/session-runner-model.test.ts +++ b/packages/core/test/session-runner-model.test.ts @@ -1,5 +1,5 @@ import { describe, expect } from "bun:test" -import { LLM } from "@opencode-ai/llm" +import { LLM, Model } from "@opencode-ai/llm" import { LLMClient } from "@opencode-ai/llm/route" import { DateTime, Effect } from "effect" import { Headers } from "effect/unstable/http" @@ -13,28 +13,26 @@ import { SessionV2 } from "@opencode-ai/core/session" import { AbsolutePath } from "@opencode-ai/core/schema" import { it } from "./lib/effect" -type Api = - | { - readonly type: "aisdk" - readonly package: string - readonly url?: string - readonly settings?: Record - } - | { readonly type: "native"; readonly url?: string; readonly settings: Record } +interface ModelOptions { + readonly modelID?: string + readonly settings?: ModelV2.Info["settings"] + readonly headers?: ModelV2.Info["headers"] + readonly body?: ModelV2.Info["body"] + readonly variants?: ModelV2.Info["variants"] +} -const model = (api: Api, variants: ModelV2.Info["variants"] = []) => +const model = (packageName: string | undefined, options: ModelOptions = {}) => ModelV2.Info.make({ id: ModelV2.ID.make("test-model"), + modelID: ModelV2.ID.make(options.modelID ?? "api-test-model"), providerID: ProviderV2.ID.make("test-provider"), name: "Test model", - api: { id: ModelV2.ID.make("api-test-model"), ...api }, + package: packageName, + settings: options.settings ?? {}, + headers: options.headers ?? { "x-test": "header" }, + body: options.body ?? { custom_extension: { enabled: true } }, capabilities: { tools: true, input: ["text"], output: ["text"] }, - request: { - settings: {}, - headers: { "x-test": "header" }, - body: { apiKey: "secret", custom_extension: { enabled: true } }, - }, - variants, + variants: options.variants ?? [], time: { released: 0 }, cost: [], status: "active", @@ -43,12 +41,14 @@ const model = (api: Api, variants: ModelV2.Info["variants"] = []) => }) describe("SessionRunnerModel", () => { - it.effect("maps catalog OpenAI AI SDK models into native Responses routes", () => + it.effect("uses the API modelID instead of the catalog ID for native OpenAI routes", () => Effect.gen(function* () { - const resolved = yield* SessionRunnerModel.fromCatalogModel( - model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }), - ) + const catalog = model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + }) + const resolved = yield* SessionRunnerModel.fromCatalogModel(catalog) + expect(catalog.id).toBe(ModelV2.ID.make("test-model")) expect(resolved).toMatchObject({ id: "api-test-model", provider: "test-provider" }) expect(resolved.route).toMatchObject({ id: "openai-responses", @@ -65,7 +65,9 @@ describe("SessionRunnerModel", () => { it.effect("keeps catalog apiKey credentials out of provider JSON", () => Effect.gen(function* () { const resolved = yield* SessionRunnerModel.fromCatalogModel( - model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }), + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { apiKey: "secret", baseURL: "https://openai.example/v1" }, + }), ) const prepared = yield* LLMClient.prepare(LLM.request({ model: resolved, prompt: "Hello" })) @@ -77,14 +79,14 @@ describe("SessionRunnerModel", () => { it.effect("uses merged API settings for OpenAI-compatible auth and request defaults", () => Effect.gen(function* () { const resolved = yield* SessionRunnerModel.fromCatalogModel( - ModelV2.Info.make({ - ...model({ - type: "aisdk", - package: "@ai-sdk/openai-compatible", - url: "https://compatible.example/v1", - settings: { apiKey: "settings-secret", compatibility: "strict" }, - }), - request: { settings: {}, headers: {}, body: {} }, + model(ProviderV2.aisdk("@ai-sdk/openai-compatible"), { + settings: { + apiKey: "settings-secret", + baseURL: "https://compatible.example/v1", + compatibility: "strict", + }, + headers: {}, + body: {}, }), ) const request = LLM.request({ model: resolved, prompt: "Hello" }) @@ -97,24 +99,29 @@ describe("SessionRunnerModel", () => { }) expect(headers.authorization).toBe("Bearer settings-secret") + expect(resolved.route.id).toBe("openai-compatible-chat") + expect(resolved.route.endpoint.baseURL).toBe("https://compatible.example/v1") expect(resolved.route.defaults.http?.body).toEqual({}) }), ) it.effect("overlays selected OpenAI Session variant settings and bodies", () => Effect.gen(function* () { - const catalog = model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }, [ - { - id: ModelV2.VariantID.make("high"), - settings: { reasoningEffort: "high" }, - headers: { "x-variant": "high" }, - body: { - store: false, - service_tier: "priority", - temperature: 0.2, + const catalog = model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + variants: [ + { + id: ModelV2.VariantID.make("high"), + settings: { reasoningEffort: "high" }, + headers: { "x-variant": "high" }, + body: { + store: false, + service_tier: "priority", + temperature: 0.2, + }, }, - }, - ]) + ], + }) const session = SessionV2.Info.make({ id: SessionV2.ID.make("ses_model_variant"), projectID: ProjectV2.ID.global, @@ -147,9 +154,9 @@ describe("SessionRunnerModel", () => { it.effect("overlays selected OpenAI-compatible Session variant bodies", () => Effect.gen(function* () { - const catalog = model( - { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://compatible.example/v1" }, - [ + const catalog = model(ProviderV2.aisdk("@ai-sdk/openai-compatible"), { + settings: { baseURL: "https://compatible.example/v1" }, + variants: [ { id: ModelV2.VariantID.make("high"), settings: {}, @@ -157,7 +164,7 @@ describe("SessionRunnerModel", () => { body: { store: false, reasoning_effort: "high" }, }, ], - ) + }) const session = SessionV2.Info.make({ id: SessionV2.ID.make("ses_compatible_variant"), projectID: ProjectV2.ID.global, @@ -181,7 +188,9 @@ describe("SessionRunnerModel", () => { it.effect("rejects an explicit unavailable Session variant during model resolution", () => Effect.gen(function* () { - const catalog = model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }) + const catalog = model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + }) const session = SessionV2.Info.make({ id: SessionV2.ID.make("ses_model_variant_unavailable"), projectID: ProjectV2.ID.global, @@ -211,14 +220,17 @@ describe("SessionRunnerModel", () => { it.effect("overlays selected Anthropic Session variant settings", () => Effect.gen(function* () { - const catalog = model({ type: "aisdk", package: "@ai-sdk/anthropic", url: "https://anthropic.example/v1" }, [ - { - id: ModelV2.VariantID.make("high"), - settings: { thinking: { type: "enabled", budgetTokens: 12000 } }, - headers: {}, - body: {}, - }, - ]) + const catalog = model(ProviderV2.aisdk("@ai-sdk/anthropic"), { + settings: { baseURL: "https://anthropic.example/v1" }, + variants: [ + { + id: ModelV2.VariantID.make("high"), + settings: { thinking: { type: "enabled", budgetTokens: 12000 } }, + headers: {}, + body: {}, + }, + ], + }) const session = SessionV2.Info.make({ id: SessionV2.ID.make("ses_anthropic_variant"), projectID: ProjectV2.ID.global, @@ -244,7 +256,9 @@ describe("SessionRunnerModel", () => { it.effect("maps catalog Anthropic AI SDK models into native routes", () => Effect.gen(function* () { const resolved = yield* SessionRunnerModel.fromCatalogModel( - model({ type: "aisdk", package: "@ai-sdk/anthropic", url: "https://anthropic.example/v1" }), + model(ProviderV2.aisdk("@ai-sdk/anthropic"), { + settings: { baseURL: "https://anthropic.example/v1" }, + }), ) expect(resolved.route).toMatchObject({ @@ -257,9 +271,10 @@ describe("SessionRunnerModel", () => { it.effect("uses resolved credentials for bearer auth", () => Effect.gen(function* () { const resolved = yield* SessionRunnerModel.fromCatalogModel( - ModelV2.Info.make({ - ...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }), - request: { settings: {}, headers: {}, body: {} }, + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + headers: {}, + body: {}, }), Credential.Key.make({ type: "key", key: "secret" }), ) @@ -280,9 +295,10 @@ describe("SessionRunnerModel", () => { Effect.gen(function* () { const credential = Credential.Key.make({ type: "key", key: "stored-secret", metadata: { tenant: "work" } }) const resolved = yield* SessionRunnerModel.fromCatalogModel( - ModelV2.Info.make({ - ...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }), - request: { settings: {}, headers: {}, body: { apiKey: "configured-secret" } }, + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { apiKey: "configured-secret", baseURL: "https://openai.example/v1" }, + headers: {}, + body: {}, }), credential, ) @@ -302,9 +318,10 @@ describe("SessionRunnerModel", () => { it.effect("does not project OAuth account metadata into the request body", () => Effect.gen(function* () { const resolved = yield* SessionRunnerModel.fromCatalogModel( - ModelV2.Info.make({ - ...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }), - request: { settings: {}, headers: {}, body: {} }, + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + headers: {}, + body: {}, }), Credential.OAuth.make({ type: "oauth", @@ -323,9 +340,10 @@ describe("SessionRunnerModel", () => { it.effect("routes ChatGPT OAuth credentials to the codex backend", () => Effect.gen(function* () { const resolved = yield* SessionRunnerModel.fromCatalogModel( - ModelV2.Info.make({ - ...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }), - request: { headers: {}, body: {} }, + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + headers: {}, + body: {}, }), Credential.OAuth.make({ type: "oauth", @@ -354,12 +372,78 @@ describe("SessionRunnerModel", () => { }), ) + it.effect("routes native OpenAI provider packages with ChatGPT credentials to the codex backend", () => + Effect.gen(function* () { + const resolved = yield* SessionRunnerModel.fromCatalogModel( + model("@opencode-ai/llm/providers/openai", { + settings: { baseURL: "https://openai.example/v1" }, + }), + Credential.OAuth.make({ + type: "oauth", + methodID: Integration.MethodID.make("chatgpt-browser"), + access: "chatgpt-token", + refresh: "refresh", + expires: Date.now() + 60_000, + metadata: { accountID: "acct_123" }, + }), + ) + const headers = yield* resolved.route.auth.apply({ + request: LLM.request({ model: resolved, prompt: "Hello" }), + method: "POST", + url: "https://chatgpt.com/backend-api/codex/responses", + body: "{}", + headers: Headers.empty, + }) + + expect(resolved.route.endpoint.baseURL).toBe("https://chatgpt.com/backend-api/codex") + expect(headers.authorization).toBe("Bearer chatgpt-token") + expect(headers["chatgpt-account-id"]).toBe("acct_123") + }), + ) + + it.effect("does not route native OpenAI-compatible packages to the codex backend", () => + Effect.gen(function* () { + const resolved = yield* SessionRunnerModel.fromCatalogModel( + model("@opencode-ai/llm/providers/openai-compatible", { + settings: { baseURL: "https://compatible.example/v1" }, + }), + Credential.OAuth.make({ + type: "oauth", + methodID: Integration.MethodID.make("chatgpt-browser"), + access: "chatgpt-token", + refresh: "refresh", + expires: Date.now() + 60_000, + metadata: { accountID: "acct_123" }, + }), + ) + + expect(resolved.route.id).toBe("openai-compatible-chat") + expect(resolved.route.endpoint.baseURL).toBe("https://compatible.example/v1") + }), + ) + + it.effect("maps legacy OpenAI organization and project settings to headers", () => + Effect.gen(function* () { + const resolved = yield* SessionRunnerModel.fromCatalogModel( + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { organization: "org_123", project: "proj_123" }, + }), + ) + + expect(resolved.route.defaults.headers).toMatchObject({ + "OpenAI-Organization": "org_123", + "OpenAI-Project": "proj_123", + }) + }), + ) + it.effect("routes ChatGPT OAuth credentials without an account id to the codex backend", () => Effect.gen(function* () { const resolved = yield* SessionRunnerModel.fromCatalogModel( - ModelV2.Info.make({ - ...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }), - request: { headers: {}, body: {} }, + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + headers: {}, + body: {}, }), Credential.OAuth.make({ type: "oauth", @@ -387,9 +471,10 @@ describe("SessionRunnerModel", () => { it.effect("keeps non-ChatGPT OAuth credentials on the configured endpoint", () => Effect.gen(function* () { const resolved = yield* SessionRunnerModel.fromCatalogModel( - ModelV2.Info.make({ - ...model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }), - request: { headers: {}, body: {} }, + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + headers: {}, + body: {}, }), Credential.OAuth.make({ type: "oauth", @@ -415,35 +500,106 @@ describe("SessionRunnerModel", () => { }), ) - it.effect("rejects catalog APIs without a native route", () => + it.effect("loads dynamic native provider packages through the injected package loader", () => + Effect.gen(function* () { + const native = yield* SessionRunnerModel.fromCatalogModel( + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + }), + ) + const resolved = yield* SessionRunnerModel.fromCatalogModel( + model("@opencode-ai/llm/providers/custom", { + settings: { region: "test" }, + headers: { "x-package": "header" }, + body: { custom: true }, + }), + undefined, + { + loadPackage: (specifier) => { + expect(specifier).toBe("@opencode-ai/llm/providers/custom") + return Effect.succeed({ + model: (modelID, settings) => { + expect(modelID).toBe("api-test-model") + expect(settings).toEqual({ + region: "test", + headers: { "x-package": "header" }, + body: { custom: true }, + limits: { context: 100, output: 20 }, + }) + return Model.make({ id: modelID, provider: "package-provider", route: native.route }) + }, + }) + }, + }, + ) + + expect(resolved).toMatchObject({ id: "api-test-model", provider: "test-provider" }) + }), + ) + + it.effect("loads arbitrary AISDK packages through the injected AISDK loader", () => + Effect.gen(function* () { + const native = yield* SessionRunnerModel.fromCatalogModel( + model(ProviderV2.aisdk("@ai-sdk/openai"), { + settings: { baseURL: "https://openai.example/v1" }, + }), + ) + const resolved = yield* SessionRunnerModel.fromCatalogModel( + model(ProviderV2.aisdk("@ai-sdk/google"), { + modelID: "gemini-api-model", + settings: { project: "test" }, + headers: { "x-aisdk": "header" }, + body: { custom: true }, + }), + Credential.Key.make({ type: "key", key: "fallback-secret" }), + { + loadAISDK: (runtime) => + Effect.sync(() => { + expect(runtime).toMatchObject({ + id: "test-model", + modelID: "gemini-api-model", + providerID: "test-provider", + package: ProviderV2.aisdk("@ai-sdk/google"), + settings: { project: "test", apiKey: "fallback-secret" }, + headers: { "x-aisdk": "header" }, + body: { custom: true }, + }) + return Model.make({ + id: runtime.modelID ?? runtime.id, + provider: runtime.providerID, + route: native.route, + }) + }), + }, + ) + + expect(resolved).toMatchObject({ id: "gemini-api-model", provider: "test-provider" }) + }), + ) + + it.effect("rejects AISDK packages without an available loader", () => Effect.gen(function* () { const failure = yield* SessionRunnerModel.fromCatalogModel( - model({ type: "aisdk", package: "@ai-sdk/google", url: "https://google.example/v1" }), + model(ProviderV2.aisdk("@ai-sdk/google"), { + settings: { baseURL: "https://google.example/v1" }, + }), ).pipe(Effect.flip) expect(failure).toMatchObject({ - _tag: "SessionRunnerModel.UnsupportedApiError", + _tag: "SessionRunnerModel.UnsupportedPackageError", providerID: "test-provider", modelID: "test-model", - api: "aisdk:@ai-sdk/google", + package: "aisdk:@ai-sdk/google", }) - expect(failure.message).toBe("Unsupported API for test-provider/test-model: aisdk:@ai-sdk/google") + expect(failure.message).toBe("Unsupported package for test-provider/test-model: aisdk:@ai-sdk/google") }), ) - it.effect("reports whether a catalog model has a supported native route", () => + it.effect("reports whether a catalog model declares a provider package", () => Effect.sync(() => { - expect( - SessionRunnerModel.supported( - model({ type: "aisdk", package: "@ai-sdk/openai", url: "https://openai.example/v1" }), - ), - ).toBe(true) - expect( - SessionRunnerModel.supported( - model({ type: "aisdk", package: "@ai-sdk/google", url: "https://google.example/v1" }), - ), - ).toBe(false) - expect(SessionRunnerModel.supported(model({ type: "native", settings: {} }))).toBe(false) + expect(SessionRunnerModel.supported(model(ProviderV2.aisdk("@ai-sdk/openai")))).toBe(true) + expect(SessionRunnerModel.supported(model("@opencode-ai/llm/providers/custom"))).toBe(true) + expect(SessionRunnerModel.supported(model(undefined))).toBe(false) }), ) }) diff --git a/packages/core/test/shared-schema.test.ts b/packages/core/test/shared-schema.test.ts index d96f6e5bd52..9e48790dd0d 100644 --- a/packages/core/test/shared-schema.test.ts +++ b/packages/core/test/shared-schema.test.ts @@ -112,12 +112,8 @@ test("Core reuses the canonical shared schemas", async () => { [ModelV2.Family, Model.Family], [ModelV2.Capabilities, Model.Capabilities], [ModelV2.Cost, Model.Cost], - [ModelV2.Api, Model.Api], [ModelV2.Info, Model.Info], [ProviderV2.ID, Provider.ID], - [ProviderV2.AISDK, Provider.AISDK], - [ProviderV2.Native, Provider.Native], - [ProviderV2.Api, Provider.Api], [ProviderV2.Request, Provider.Request], [ProviderV2.Info, Provider.Info], [corePermission.Effect, Permission.Effect], diff --git a/packages/llm/package.json b/packages/llm/package.json index 0b4cd12e256..f9c2ba821c7 100644 --- a/packages/llm/package.json +++ b/packages/llm/package.json @@ -15,6 +15,7 @@ "./route": "./src/route/index.ts", "./provider": "./src/provider.ts", "./providers": "./src/providers/index.ts", + "./provider-package": "./src/provider-package.ts", "./providers/amazon-bedrock": "./src/providers/amazon-bedrock.ts", "./providers/anthropic": "./src/providers/anthropic.ts", "./providers/azure": "./src/providers/azure.ts", @@ -22,6 +23,8 @@ "./providers/github-copilot": "./src/providers/github-copilot.ts", "./providers/google": "./src/providers/google.ts", "./providers/openai": "./src/providers/openai.ts", + "./providers/openai/responses": "./src/providers/openai/responses.ts", + "./providers/openai/chat": "./src/providers/openai/chat.ts", "./providers/openai-compatible": "./src/providers/openai-compatible.ts", "./providers/openai-compatible-profile": "./src/providers/openai-compatible-profile.ts", "./providers/openrouter": "./src/providers/openrouter.ts", diff --git a/packages/llm/src/index.ts b/packages/llm/src/index.ts index 735520ff77c..83edee7155e 100644 --- a/packages/llm/src/index.ts +++ b/packages/llm/src/index.ts @@ -1,6 +1,7 @@ export { LLMClient } from "./route/client" export { Auth } from "./route/auth" export { Provider } from "./provider" +export { ProviderPackage } from "./provider-package" export { isContextOverflow, isContextOverflowFailure } from "./provider-error" export type { RouteModelInput, @@ -31,3 +32,4 @@ export type { ModelFactory as ProviderModelFactory, ModelOptions as ProviderModelOptions, } from "./provider" +export type { Definition as ProviderPackageDefinition, Settings as ProviderPackageSettings } from "./provider-package" diff --git a/packages/llm/src/provider-package.ts b/packages/llm/src/provider-package.ts new file mode 100644 index 00000000000..fd878a9d06c --- /dev/null +++ b/packages/llm/src/provider-package.ts @@ -0,0 +1,16 @@ +import type { Model } from "./schema" + +export interface Settings extends Readonly> { + readonly headers?: Readonly> + readonly body?: Readonly> + readonly limits?: { + readonly context: number + readonly output: number + } +} + +export interface Definition { + readonly model: (modelID: string, settings: ProviderSettings) => Model +} + +export * as ProviderPackage from "./provider-package" diff --git a/packages/llm/src/providers/amazon-bedrock.ts b/packages/llm/src/providers/amazon-bedrock.ts index 2f1791e0d62..4e5040c9ec0 100644 --- a/packages/llm/src/providers/amazon-bedrock.ts +++ b/packages/llm/src/providers/amazon-bedrock.ts @@ -1,5 +1,6 @@ import type { RouteDefaultsInput } from "../route/client" import { Auth } from "../route/auth" +import type { ProviderPackage } from "../provider-package" import { ProviderID, type ModelID } from "../schema" import * as BedrockConverse from "../protocols/bedrock-converse" import type { BedrockCredentials } from "../protocols/bedrock-converse" @@ -15,6 +16,15 @@ export type Config = RouteDefaultsInput & { /** Override the computed `https://bedrock-runtime..amazonaws.com` URL. */ readonly baseURL?: string } + +export interface Settings extends ProviderPackage.Settings { + readonly apiKey?: string + readonly auth?: "bearer" | "sigv4" + readonly baseURL?: string + readonly credentials?: BedrockCredentials + readonly region?: string + readonly topP?: number +} export const routes = [BedrockConverse.route] const bedrockBaseURL = (region: string) => `https://bedrock-runtime.${region}.amazonaws.com` @@ -40,4 +50,19 @@ export const configure = (input: Config = {}) => { } export const provider = configure() -export const model = provider.model +export const model: ProviderPackage.Definition["model"] = (modelID, settings) => { + if (settings.auth === "bearer" && settings.apiKey === undefined) + throw new Error("Amazon Bedrock bearer auth requires apiKey") + if (settings.auth === "sigv4" && settings.apiKey !== undefined) + throw new Error("Amazon Bedrock SigV4 auth does not accept apiKey") + return configure({ + apiKey: settings.auth === "sigv4" ? undefined : settings.apiKey, + baseURL: settings.baseURL, + credentials: settings.credentials, + generation: settings.topP === undefined ? undefined : { topP: settings.topP }, + headers: settings.headers === undefined ? undefined : { ...settings.headers }, + http: settings.body === undefined ? undefined : { body: { ...settings.body } }, + limits: settings.limits, + region: settings.region, + }).model(modelID) +} diff --git a/packages/llm/src/providers/anthropic.ts b/packages/llm/src/providers/anthropic.ts index 0c9640af5ea..84684e7d83d 100644 --- a/packages/llm/src/providers/anthropic.ts +++ b/packages/llm/src/providers/anthropic.ts @@ -1,6 +1,7 @@ import type { RouteDefaultsInput } from "../route/client" import { Auth } from "../route/auth" import type { ProviderAuthOption } from "../route/auth-options" +import type { ProviderPackage } from "../provider-package" import { ProviderID, type ModelID } from "../schema" import * as AnthropicMessages from "../protocols/anthropic-messages" @@ -10,6 +11,12 @@ export const routes = [AnthropicMessages.route] export type Config = RouteDefaultsInput & ProviderAuthOption<"optional"> & { readonly baseURL?: string } +export interface Settings extends ProviderPackage.Settings { + readonly apiKey?: string + readonly authToken?: string + readonly baseURL?: string +} + const auth = (options: ProviderAuthOption<"optional">) => { if ("auth" in options && options.auth) return options.auth return Auth.optional("apiKey" in options ? options.apiKey : undefined, "apiKey") @@ -32,4 +39,11 @@ export const configure = (input: Config = {}) => { } export const provider = configure() -export const model = provider.model +export const model: ProviderPackage.Definition["model"] = (modelID, settings) => + configure({ + ...(settings.authToken === undefined ? { apiKey: settings.apiKey } : { auth: Auth.bearer(settings.authToken) }), + baseURL: settings.baseURL, + headers: settings.headers === undefined ? undefined : { ...settings.headers }, + http: settings.body === undefined ? undefined : { body: { ...settings.body } }, + limits: settings.limits, + }).model(modelID) diff --git a/packages/llm/src/providers/openai-compatible.ts b/packages/llm/src/providers/openai-compatible.ts index a79f65f6dfe..8b5d23eed73 100644 --- a/packages/llm/src/providers/openai-compatible.ts +++ b/packages/llm/src/providers/openai-compatible.ts @@ -2,6 +2,7 @@ import { ProviderID, type ModelID } from "../schema" import * as OpenAICompatibleChat from "../protocols/openai-compatible-chat" import type { RouteDefaultsInput } from "../route/client" import { AuthOptions, type ProviderAuthOption } from "../route/auth-options" +import type { ProviderPackage } from "../provider-package" import { profiles, type OpenAICompatibleProfile } from "./openai-compatible-profile" export const id = ProviderID.make("openai-compatible") @@ -12,6 +13,12 @@ type GenericModelOptions = RouteDefaultsInput & readonly baseURL: string } +export interface Settings extends ProviderPackage.Settings { + readonly apiKey?: string + readonly baseURL: string + readonly provider?: string +} + export type FamilyModelOptions = RouteDefaultsInput & ProviderAuthOption<"optional"> & { readonly baseURL?: string @@ -56,6 +63,16 @@ export const provider = { configure, } +export const model: ProviderPackage.Definition["model"] = (modelID, settings) => + configure({ + apiKey: settings.apiKey, + baseURL: settings.baseURL, + headers: settings.headers === undefined ? undefined : { ...settings.headers }, + http: settings.body === undefined ? undefined : { body: { ...settings.body } }, + limits: settings.limits, + provider: settings.provider, + }).model(modelID) + export const baseten = define(profiles.baseten) export const cerebras = define(profiles.cerebras) export const deepinfra = define(profiles.deepinfra) diff --git a/packages/llm/src/providers/openai.ts b/packages/llm/src/providers/openai.ts index 098cad84939..73819eaf471 100644 --- a/packages/llm/src/providers/openai.ts +++ b/packages/llm/src/providers/openai.ts @@ -1,5 +1,6 @@ import { AuthOptions, type ProviderAuthOption } from "../route/auth-options" import type { Route, RouteDefaultsInput } from "../route/client" +import type { ProviderPackage } from "../provider-package" import { ProviderID, type ModelID } from "../schema" import * as OpenAIChat from "../protocols/openai-chat" import * as OpenAIResponses from "../protocols/openai-responses" @@ -21,6 +22,16 @@ export type Config = RouteDefaultsInput & readonly providerOptions?: OpenAIProviderOptionsInput } +export interface Settings extends ProviderPackage.Settings { + readonly apiKey?: string + readonly baseURL?: string + readonly organization?: string + readonly project?: string + readonly queryParams?: Readonly> + readonly transport?: "http" | "websocket" + readonly providerOptions?: OpenAIProviderOptionsInput +} + const auth = (options: ProviderAuthOption<"optional">) => AuthOptions.bearer(options, "OPENAI_API_KEY") const defaults = (input: Config) => { @@ -57,7 +68,32 @@ export const configure = (input: Config = {}) => { export const provider = configure() -export const model = provider.model +const config = (settings: Settings): Config => { + const headers = { + ...(settings.organization === undefined ? {} : { "OpenAI-Organization": settings.organization }), + ...(settings.project === undefined ? {} : { "OpenAI-Project": settings.project }), + ...settings.headers, + } + return { + apiKey: settings.apiKey, + baseURL: settings.baseURL, + headers: Object.keys(headers).length === 0 ? undefined : headers, + http: settings.body === undefined ? undefined : { body: { ...settings.body } }, + limits: settings.limits, + providerOptions: settings.providerOptions, + queryParams: settings.queryParams === undefined ? undefined : { ...settings.queryParams }, + } +} + +export const model: ProviderPackage.Definition["model"] = (modelID, settings) => { + const configured = configure(config(settings)) + if (settings.transport === undefined || settings.transport === "http") return configured.responses(modelID) + if (settings.transport === "websocket") return configured.responsesWebSocket(modelID) + throw new Error(`Unsupported OpenAI Responses transport: ${String(settings.transport)}`) +} + +export const chatModel: ProviderPackage.Definition["model"] = (modelID, settings) => + configure(config(settings)).chat(modelID) export const responses = provider.responses export const responsesWebSocket = provider.responsesWebSocket export const chat = provider.chat diff --git a/packages/llm/src/providers/openai/chat.ts b/packages/llm/src/providers/openai/chat.ts new file mode 100644 index 00000000000..eb92db8ac50 --- /dev/null +++ b/packages/llm/src/providers/openai/chat.ts @@ -0,0 +1,2 @@ +export { chatModel as model } from "../openai" +export type { Settings } from "../openai" diff --git a/packages/llm/src/providers/openai/responses.ts b/packages/llm/src/providers/openai/responses.ts new file mode 100644 index 00000000000..4db3a232c7b --- /dev/null +++ b/packages/llm/src/providers/openai/responses.ts @@ -0,0 +1,2 @@ +export { model } from "../openai" +export type { Settings } from "../openai" diff --git a/packages/llm/test/exports.test.ts b/packages/llm/test/exports.test.ts index 693a21638ba..6ed66a0d8e5 100644 --- a/packages/llm/test/exports.test.ts +++ b/packages/llm/test/exports.test.ts @@ -30,7 +30,6 @@ describe("public exports", () => { test("provider barrels expose user-facing facades", () => { expect(OpenAI.model).toBeFunction() - expect(OpenAI.provider.model).toBe(OpenAI.model) expect(OpenAI.provider.responses).toBe(OpenAI.responses) expect(OpenAI.provider.responsesWebSocket).toBe(OpenAI.responsesWebSocket) expect(OpenAI.configure({ apiKey: "fixture" }).responses).toBeFunction() diff --git a/packages/llm/test/provider-package.test.ts b/packages/llm/test/provider-package.test.ts new file mode 100644 index 00000000000..0d3ddc811c4 --- /dev/null +++ b/packages/llm/test/provider-package.test.ts @@ -0,0 +1,52 @@ +import { describe, expect, test } from "bun:test" +import { model } from "@opencode-ai/llm/providers/openai" + +describe("provider package entrypoints", () => { + test("semantic API aliases expose the same contract", async () => { + const modules = await Promise.all([ + import("@opencode-ai/llm/providers/openai"), + import("@opencode-ai/llm/providers/openai/responses"), + import("@opencode-ai/llm/providers/openai/chat"), + import("@opencode-ai/llm/providers/anthropic"), + import("@opencode-ai/llm/providers/openai-compatible"), + import("@opencode-ai/llm/providers/amazon-bedrock"), + ]) + + for (const module of modules) expect(module.model).toBeFunction() + expect(modules[0].model).toBe(modules[1].model) + }) + + test("maps package settings onto the executable model", () => { + const selected = model("gpt-5", { + apiKey: "fixture", + baseURL: "https://api.openai.test/v1", + headers: { "x-application": "opencode" }, + body: { service_tier: "priority" }, + limits: { context: 200_000, output: 64_000 }, + unrelatedInheritedSetting: true, + }) + + expect(selected.route.id).toBe("openai-responses") + expect(selected.route.defaults.headers).toEqual({ "x-application": "opencode" }) + expect(selected.route.defaults.http?.body).toEqual({ service_tier: "priority" }) + expect(selected.route.defaults.limits).toEqual({ context: 200_000, output: 64_000 }) + }) + + test("selects transport without changing the semantic API", () => { + expect(model("gpt-5", { apiKey: "fixture" }).route.id).toBe("openai-responses") + expect(model("gpt-5", { apiKey: "fixture", transport: "websocket" }).route.id).toBe("openai-responses-websocket") + }) + + test("maps legacy OpenAI organization and project settings to headers", () => { + const selected = model("gpt-5", { + apiKey: "fixture", + organization: "org_123", + project: "proj_123", + }) + + expect(selected.route.defaults.headers).toMatchObject({ + "OpenAI-Organization": "org_123", + "OpenAI-Project": "proj_123", + }) + }) +}) diff --git a/packages/opencode/test/cli/run/catalog.shared.test.ts b/packages/opencode/test/cli/run/catalog.shared.test.ts index 0f5ef225bf2..d5487cdfa91 100644 --- a/packages/opencode/test/cli/run/catalog.shared.test.ts +++ b/packages/opencode/test/cli/run/catalog.shared.test.ts @@ -59,34 +59,21 @@ describe("run catalog shared", () => { { id: "openai", name: "OpenAI", - api: { type: "native", settings: {} }, - request: { settings: {}, headers: {}, body: {} }, + package: "", }, ], [ { id: "gpt-5", + modelID: "openai", providerID: "openai", name: "Little Frank", - api: { id: "openai", type: "native", settings: {} }, capabilities: { tools: true, input: ["text"], output: ["text"], }, - request: { - settings: {}, - headers: {}, - body: {}, - }, - variants: [ - { - id: "high", - settings: {}, - headers: {}, - body: {}, - }, - ], + variants: [{ id: "high" }], time: { released: 1, }, diff --git a/packages/schema/src/model.ts b/packages/schema/src/model.ts index 19276b6d007..fc6b64712f3 100644 --- a/packages/schema/src/model.ts +++ b/packages/schema/src/model.ts @@ -1,9 +1,8 @@ export * as Model from "./model.js" import { Schema } from "effect" -import { optional } from "./schema.js" +import { optional, statics } from "./schema.js" import { Provider } from "./provider.js" -import { statics } from "./schema.js" export const ID = Schema.String.pipe(Schema.brand("ModelV2.ID")) export type ID = typeof ID.Type @@ -42,36 +41,23 @@ export const Cost = Schema.Struct({ }), }).annotate({ identifier: "Model.Cost" }) -export const Api = Schema.Union([ - Schema.Struct({ - id: ID, - ...Provider.AISDK.fields, - }), - Schema.Struct({ - id: ID, - ...Provider.Native.fields, - }), -]) - .pipe(Schema.toTaggedUnion("type")) - .annotate({ identifier: "Model.Api" }) -export type Api = typeof Api.Type +export interface Variant extends Schema.Schema.Type {} +export const Variant = Schema.Struct({ + id: VariantID, + ...Provider.Overlays, +}).annotate({ identifier: "Model.Variant" }) export interface Info extends Schema.Schema.Type {} export const Info = Schema.Struct({ id: ID, + modelID: ID, providerID: Provider.ID, family: Family.pipe(optional), name: Schema.String, - api: Api, + package: Provider.Package.pipe(optional), + ...Provider.Overlays, capabilities: Capabilities, - request: Schema.Struct({ - ...Provider.Request.fields, - variant: Schema.String.pipe(optional), - }), - variants: Schema.Struct({ - id: VariantID, - ...Provider.Request.fields, - }).pipe(Schema.Array), + variants: Schema.Array(Variant), time: Schema.Struct({ released: Schema.Finite, }), @@ -87,14 +73,13 @@ export const Info = Schema.Struct({ .annotate({ identifier: "ModelV2.Info" }) .pipe( statics((schema) => ({ - empty: (providerID: Provider.ID, modelID: ID) => + empty: (providerID: Provider.ID, id: ID) => schema.make({ - id: modelID, + id, + modelID: id, providerID, - name: modelID, - api: { id: modelID, type: "native", settings: {} }, + name: id, capabilities: { tools: false, input: [], output: [] }, - request: { settings: {}, headers: {}, body: {} }, variants: [], time: { released: 0 }, cost: [], diff --git a/packages/schema/src/provider.ts b/packages/schema/src/provider.ts index daa53f8430c..f426a197987 100644 --- a/packages/schema/src/provider.ts +++ b/packages/schema/src/provider.ts @@ -1,9 +1,8 @@ export * as Provider from "./provider.js" import { Effect, Schema } from "effect" -import { optional } from "./schema.js" import { Integration } from "./integration.js" -import { statics } from "./schema.js" +import { optional, statics } from "./schema.js" export const ID = Schema.String.pipe( Schema.brand("ProviderV2.ID"), @@ -23,27 +22,16 @@ export const ID = Schema.String.pipe( ) export type ID = typeof ID.Type -export interface AISDK extends Schema.Schema.Type {} -export const AISDK = Schema.Struct({ - type: Schema.Literal("aisdk"), - package: Schema.String, - url: Schema.String.pipe(optional), - settings: Schema.Record(Schema.String, Schema.Unknown).pipe(optional), -}).annotate({ identifier: "Provider.AISDK" }) +export const Package = Schema.String +export type Package = typeof Package.Type -export interface Native extends Schema.Schema.Type {} -export const Native = Schema.Struct({ - type: Schema.Literal("native"), - url: Schema.String.pipe(optional), - settings: Schema.Record(Schema.String, Schema.Unknown), -}).annotate({ identifier: "Provider.Native" }) +export const Overlays = { + settings: Schema.Record(Schema.String, Schema.Json).pipe(optional), + headers: Schema.Record(Schema.String, Schema.String).pipe(optional), + body: Schema.Record(Schema.String, Schema.Json).pipe(optional), +} -export const Api = Schema.Union([AISDK, Native]) - .pipe(Schema.toTaggedUnion("type")) - .annotate({ identifier: "Provider.Api" }) -export type Api = typeof Api.Type - -export const Settings = Schema.Record(Schema.String, Schema.Unknown).annotate({ identifier: "Provider.Settings" }) +export const Settings = Schema.Record(Schema.String, Schema.Json).annotate({ identifier: "Provider.Settings" }) export type Settings = typeof Settings.Type export interface Request extends Schema.Schema.Type {} @@ -59,18 +47,12 @@ export const Info = Schema.Struct({ integrationID: Integration.ID.pipe(optional), name: Schema.String, disabled: Schema.Boolean.pipe(optional), - api: Api, - request: Request, + package: Package, + ...Overlays, }) .annotate({ identifier: "ProviderV2.Info" }) .pipe( statics((schema) => ({ - empty: (id: ID) => - schema.make({ - id, - name: id, - api: { type: "native", settings: {} }, - request: { settings: {}, headers: {}, body: {} }, - }), + empty: (id: ID) => schema.make({ id, name: id, package: "" }), })), ) diff --git a/packages/schema/test/contract-hygiene.test.ts b/packages/schema/test/contract-hygiene.test.ts index edad66725ec..58ba6ba856f 100644 --- a/packages/schema/test/contract-hygiene.test.ts +++ b/packages/schema/test/contract-hygiene.test.ts @@ -4,6 +4,7 @@ import { Agent } from "../src/agent.js" import { FileSystem } from "../src/filesystem.js" import { Model } from "../src/model.js" import { Project } from "../src/project.js" +import { Provider } from "../src/provider.js" import { Pty } from "../src/pty.js" import { Question } from "../src/question.js" import { Session } from "../src/session.js" @@ -18,6 +19,19 @@ describe("contract hygiene", () => { expect(Schema.encodeSync(Value)({ value: undefined })).toEqual({}) }) + test("model defaults and provider overlays preserve public invariants", () => { + const id = Model.ID.make("model") + expect(Model.Info.empty(Provider.ID.make("provider"), id)).toMatchObject({ modelID: id, variants: [] }) + expect(() => + Schema.decodeUnknownSync(Provider.Info)({ + id: "provider", + name: "Provider", + package: "native", + settings: { invalid: 1n }, + }), + ).toThrow() + }) + test("todo status and priority preserve arbitrary strings", () => { const decode = Schema.decodeUnknownSync(SessionTodo.Info) expect(decode({ content: "ship", status: "waiting", priority: "urgent" })).toEqual({ @@ -39,7 +53,7 @@ describe("contract hygiene", () => { Model.Ref, Model.Capabilities, Model.Cost, - Model.Api, + Model.Variant, Project.Current, Project.Directory, Project.DirectoriesInput, diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index f1215bf713a..70b85f2e0bb 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -5219,31 +5219,25 @@ export type EventLogSynced = { seq?: number } -export type ModelApi = - | { - id: string - type: "aisdk" - package: string - url?: string - settings?: { - [key: string]: unknown - } - } - | { - id: string - type: "native" - url?: string - settings: { - [key: string]: unknown - } - } - export type ModelCapabilities = { tools: boolean input: Array output: Array } +export type ModelVariant = { + id: string + settings?: { + [key: string]: unknown + } + headers?: { + [key: string]: string + } + body?: { + [key: string]: unknown + } +} + export type ModelCost = { tier?: { type: "context" @@ -5259,31 +5253,22 @@ export type ModelCost = { export type ModelV2Info = { id: string + modelID: string providerID: string family?: string name: string - api: ModelApi - capabilities: ModelCapabilities - request: { - settings: ProviderSettings - headers: { - [key: string]: string - } - body: { - [key: string]: unknown - } - variant?: string + package?: string + settings?: { + [key: string]: unknown } - variants: Array<{ - id: string - settings: ProviderSettings - headers: { - [key: string]: string - } - body: { - [key: string]: unknown - } - }> + headers?: { + [key: string]: string + } + body?: { + [key: string]: unknown + } + capabilities: ModelCapabilities + variants: Array time: { released: number } @@ -5297,32 +5282,21 @@ export type ModelV2Info = { } } -export type ProviderAisdk = { - type: "aisdk" - package: string - url?: string - settings?: { - [key: string]: unknown - } -} - -export type ProviderNative = { - type: "native" - url?: string - settings: { - [key: string]: unknown - } -} - -export type ProviderApi = ProviderAisdk | ProviderNative - export type ProviderV2Info = { id: string integrationID?: string name: string disabled?: boolean - api: ProviderApi - request: ProviderRequest + package: string + settings?: { + [key: string]: unknown + } + headers?: { + [key: string]: string + } + body?: { + [key: string]: unknown + } } export type IntegrationWhen = { @@ -9061,31 +9035,25 @@ export type SessionMessagesResponseV2 = { } } -export type ModelApi2 = - | { - id: string - type: "aisdk" - package: string - url?: string - settings?: { - [key: string]: unknown - } - } - | { - id: string - type: "native" - url?: string - settings: { - [key: string]: unknown - } - } - export type ModelCapabilities2 = { tools: boolean input: Array output: Array } +export type ModelVariant2 = { + id: string + settings?: { + [key: string]: unknown + } + headers?: { + [key: string]: string + } + body?: { + [key: string]: unknown + } +} + export type ModelCost2 = { tier?: { type: "context" @@ -9101,31 +9069,22 @@ export type ModelCost2 = { export type ModelV2Info2 = { id: string + modelID: string providerID: string family?: string name: string - api: ModelApi2 - capabilities: ModelCapabilities2 - request: { - settings: ProviderSettings2 - headers: { - [key: string]: string - } - body: { - [key: string]: unknown - } - variant?: string + package?: string + settings?: { + [key: string]: unknown } - variants: Array<{ - id: string - settings: ProviderSettings2 - headers: { - [key: string]: string - } - body: { - [key: string]: unknown - } - }> + headers?: { + [key: string]: string + } + body?: { + [key: string]: unknown + } + capabilities: ModelCapabilities2 + variants: Array time: { released: number } @@ -9145,32 +9104,21 @@ export type GenerateTextResponseV2 = { } } -export type ProviderAisdk2 = { - type: "aisdk" - package: string - url?: string - settings?: { - [key: string]: unknown - } -} - -export type ProviderNative2 = { - type: "native" - url?: string - settings: { - [key: string]: unknown - } -} - -export type ProviderApi2 = ProviderAisdk2 | ProviderNative2 - export type ProviderV2Info2 = { id: string integrationID?: string name: string disabled?: boolean - api: ProviderApi2 - request: ProviderRequest2 + package: string + settings?: { + [key: string]: unknown + } + headers?: { + [key: string]: string + } + body?: { + [key: string]: unknown + } } export type ProviderNotFoundErrorV2 = { diff --git a/packages/tui/src/context/local.tsx b/packages/tui/src/context/local.tsx index 06427d60f69..efcaa8a01d2 100644 --- a/packages/tui/src/context/local.tsx +++ b/packages/tui/src/context/local.tsx @@ -272,7 +272,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ return { provider: provider?.name ?? value.providerID, model: info?.name ?? value.modelID, - reasoning: info?.variants.length !== 0, + reasoning: (info?.variants?.length ?? 0) !== 0, } }), cycle(direction: 1 | -1) { @@ -373,12 +373,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const v = this.selected() if (!v) return undefined if (v !== "default" && this.list().includes(v)) return v - const m = currentModel()! - return ( - data.location.model - .list() - ?.find((item) => item.providerID === m.providerID && item.id === m.modelID)?.request.variant ?? "default" - ) + return "default" }, list() { const m = currentModel() @@ -386,7 +381,7 @@ export const { use: useLocal, provider: LocalProvider } = createSimpleContext({ const info = data.location.model .list() ?.find((item) => item.providerID === m.providerID && item.id === m.modelID) - return info?.variants.map((variant) => variant.id) ?? [] + return info?.variants?.map((variant) => variant.id) ?? [] }, set(value: string | undefined) { const m = currentModel() From f87998f37fbe4d38b13544bcf6449e3734c7bc98 Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Mon, 6 Jul 2026 16:28:37 -0400 Subject: [PATCH 22/46] fix(cli): align prompt attachment mentions --- packages/cli/src/mini/stream-v2.transport.ts | 6 ++-- .../test/cli/run/session.shared.test.ts | 31 ++++++++++--------- .../test/cli/run/stream-v2.transport.test.ts | 10 +++--- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/cli/src/mini/stream-v2.transport.ts b/packages/cli/src/mini/stream-v2.transport.ts index d6998f200bc..2cb58ad5281 100644 --- a/packages/cli/src/mini/stream-v2.transport.ts +++ b/packages/cli/src/mini/stream-v2.transport.ts @@ -190,7 +190,7 @@ async function prepareFile(file: RunFilePart) { return { text: `\n${content}\n` } } -function promptFileSource(part: PromptFilePart) { +function promptFileMention(part: PromptFilePart) { if (!part.source?.text) return return { start: part.source.text.start, @@ -206,7 +206,7 @@ function promptFiles(next: SessionTurnInput) { { uri: part.url, name: part.filename, - source: promptFileSource(part), + mention: promptFileMention(part), }, ] : [], @@ -219,7 +219,7 @@ function promptAgents(next: SessionTurnInput) { ? [ { name: part.name, - source: part.source + mention: part.source ? { start: part.source.start, end: part.source.end, text: part.source.value } : undefined, }, diff --git a/packages/opencode/test/cli/run/session.shared.test.ts b/packages/opencode/test/cli/run/session.shared.test.ts index 2e098581acf..30a60958dc2 100644 --- a/packages/opencode/test/cli/run/session.shared.test.ts +++ b/packages/opencode/test/cli/run/session.shared.test.ts @@ -256,21 +256,22 @@ describe("run session shared", () => { spyOn(client.message, "list").mockImplementation(() => Promise.resolve({ data: [ - { - id: "msg_prompt", - type: "user", - text: "Review @note.ts", - files: [ - { - uri: "file:///tmp/note.ts", - mime: "text/plain", - name: "note.ts", - source: { start: 7, end: 15, text: "@note.ts" }, - }, - ], - agents: [], - time: { created: 1 }, - }, + { + id: "msg_prompt", + type: "user", + text: "Review @note.ts", + files: [ + { + data: "", + mime: "text/plain", + name: "note.ts", + source: { type: "uri", uri: "file:///tmp/note.ts" }, + mention: { start: 7, end: 15, text: "@note.ts" }, + }, + ], + agents: [], + time: { created: 1 }, + }, ], cursor: {}, }), diff --git a/packages/opencode/test/cli/run/stream-v2.transport.test.ts b/packages/opencode/test/cli/run/stream-v2.transport.test.ts index 623b93c24d5..5400c6c05e9 100644 --- a/packages/opencode/test/cli/run/stream-v2.transport.test.ts +++ b/packages/opencode/test/cli/run/stream-v2.transport.test.ts @@ -302,12 +302,12 @@ describe("V2 mini transport", () => { { uri: pathToFileURL(filePath).href, name: "note.ts", - source: { start: 7, end: 15, text: "@note.ts" }, + mention: { start: 7, end: 15, text: "@note.ts" }, }, { uri: pathToFileURL(`${directoryPath}${path.sep}`).href, name: "docs", - source: { start: 20, end: 25, text: "@docs" }, + mention: { start: 20, end: 25, text: "@docs" }, }, ]) await transport.close() @@ -398,12 +398,12 @@ describe("V2 mini transport", () => { { uri: "file:///remote/project/note.ts", name: "note.ts", - source: { start: 7, end: 15, text: "@note.ts" }, + mention: { start: 7, end: 15, text: "@note.ts" }, }, { uri: "file:///remote/project/docs", name: "docs", - source: { start: 20, end: 25, text: "@docs" }, + mention: { start: 20, end: 25, text: "@docs" }, }, ]) await transport.close() @@ -486,7 +486,7 @@ describe("V2 mini transport", () => { { name: "diagram.png", uri: pathToFileURL(filePath).href, - source: { start: 7, end: 19, text: "@diagram.png" }, + mention: { start: 7, end: 19, text: "@diagram.png" }, }, ]) await transport.close() From 9e0d3976e1b45a92e51dc9a8870ab28d9de11f81 Mon Sep 17 00:00:00 2001 From: Aiden Cline <63023139+rekram1-node@users.noreply.github.com> Date: Mon, 6 Jul 2026 16:05:29 -0500 Subject: [PATCH 23/46] chore: merge dev into v2 (#35591) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Frank Co-authored-by: Aarav Sareen <96787824+arvsrn@users.noreply.github.com> Co-authored-by: Brendan Allan Co-authored-by: opencode-agent[bot] Co-authored-by: Jack Co-authored-by: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Co-authored-by: Shoubhit Dash Co-authored-by: opencode-agent[bot] <219766164+opencode-agent[bot]@users.noreply.github.com> Co-authored-by: James Long Co-authored-by: Dustin Deus Co-authored-by: starptech Co-authored-by: Luke Parker <10430890+Hona@users.noreply.github.com> Co-authored-by: 𝓛𝓲𝓽𝓽𝓵𝓮 𝓕𝓻𝓪𝓷𝓴 Co-authored-by: Dax Co-authored-by: usrnk1 <7547651+usrnk1@users.noreply.github.com> Co-authored-by: Jay <53023+jayair@users.noreply.github.com> Co-authored-by: runvip <164729189+runvip@users.noreply.github.com> Co-authored-by: opencode Co-authored-by: Julian Coy Co-authored-by: Vladimir Glafirov Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com> Co-authored-by: Kit Langton Co-authored-by: Simon Klee Co-authored-by: Jay Co-authored-by: David Hill <1879069+iamdavidhill@users.noreply.github.com> --- README.zh.md | 2 +- README.zht.md | 2 +- artifacts/glm52-rise-video/.gitignore | 3 + artifacts/glm52-rise-video/bun.lock | 483 ++++ .../glm52-rise-video/out/flash-share.mp4 | Bin 0 -> 333945 bytes .../glm52-rise-video/out/glm-52-broke-out.mp4 | Bin 0 -> 1591636 bytes .../glm52-rise-video/out/june-totals.png | Bin 0 -> 65609 bytes .../glm52-rise-video/out/minimax-climb.mp4 | Bin 0 -> 349608 bytes artifacts/glm52-rise-video/out/novel-1984.mp4 | Bin 0 -> 2569837 bytes artifacts/glm52-rise-video/out/nz-sheep.mp4 | Bin 0 -> 2788751 bytes artifacts/glm52-rise-video/package.json | 24 + artifacts/glm52-rise-video/public/book.jpg | Bin 0 -> 163196 bytes artifacts/glm52-rise-video/public/sheep.jpg | Bin 0 -> 176501 bytes artifacts/glm52-rise-video/src/data.ts | 156 ++ artifacts/glm52-rise-video/src/flash.tsx | 185 ++ artifacts/glm52-rise-video/src/index.tsx | 36 + artifacts/glm52-rise-video/src/june.tsx | 144 ++ artifacts/glm52-rise-video/src/minimax.tsx | 201 ++ artifacts/glm52-rise-video/src/novel.tsx | 135 ++ artifacts/glm52-rise-video/src/sheep.tsx | 139 ++ artifacts/glm52-rise-video/src/video.tsx | 254 ++ bun.lock | 1146 +++++---- nix/hashes.json | 8 +- package.json | 2 +- .../performance/timeline-stability/README.md | 61 + .../timeline-stability/adverse.spec.ts | 250 ++ .../timeline-stability/context-matrix.spec.ts | 192 ++ .../environment-matrix.spec.ts | 113 + .../timeline-stability/file-matrix.spec.ts | 121 + .../timeline-stability/file-mutation.spec.ts | 113 + .../timeline-stability/fixture.test.ts | 68 + .../performance/timeline-stability/fixture.ts | 561 +++++ .../timeline-stability/interaction.spec.ts | 242 ++ .../timeline-stability/lifecycle.spec.ts | 157 ++ .../timeline-stability/oracle-browser.spec.ts | 75 + .../timeline-stability/playwright.config.ts | 17 + .../scroll-interaction.spec.ts | 353 +++ .../timeline-stability/shell-matrix.spec.ts | 255 ++ .../timeline-stability/tool-mutation.spec.ts | 106 + .../timeline-stability/tools.spec.ts | 198 ++ .../transition-matrix.spec.ts | 272 +++ .../review-pane-scaling-benchmark.spec.ts | 312 +++ ...session-parent-hydration-benchmark.spec.ts | 151 ++ .../session-tab-switch-benchmark.spec.ts | 71 +- .../timeline/session-tab-switch-metrics.ts | 15 +- .../timeline/session-tab-switch-probe.ts | 90 +- .../session-timeline-benchmark.fixture.ts | 45 +- .../session-timeline-benchmark.spec.ts | 321 ++- .../timeline/timeline-test-helpers.ts | 56 +- .../e2e/performance/unit/mock-server.test.ts | 46 + .../unit/session-tab-switch-metrics.test.ts | 32 + .../unit/session-tab-switch-probe.test.ts | 55 + .../performance/unit/visual-stability.test.ts | 392 +++ .../new-session-panel-corner.spec.ts | 83 + .../e2e/regression/remote-tab-busy.spec.ts | 109 + .../e2e/regression/review-image-flash.spec.ts | 202 ++ .../e2e/regression/review-tab-switch.spec.ts | 147 ++ .../review-terminal-stacked.spec.ts | 212 ++ .../session-timeline-accessibility.spec.ts | 22 + .../session-timeline-context-resize.spec.ts | 125 +- .../session-timeline-context-state.spec.ts | 31 + .../session-timeline-file-projection.spec.ts | 52 + .../session-timeline-file-state.spec.ts | 94 + .../session-timeline-history-root.spec.ts | 220 ++ .../session-timeline-lifecycle-state.spec.ts | 94 + ...session-timeline-locale-projection.spec.ts | 25 + .../session-timeline-projection.spec.ts | 284 +++ ...sion-timeline-reasoning-projection.spec.ts | 93 + ...ession-timeline-reducer-projection.spec.ts | 43 + .../session-timeline-tool-projection.spec.ts | 99 + .../session-timeline-tool-state.spec.ts | 77 + .../session-timeline-transport.spec.ts | 116 + .../subagent-child-navigation.spec.ts | 200 ++ .../regression/tab-navigate-mousedown.spec.ts | 108 + .../terminal-composer-focus.spec.ts | 89 + .../e2e/regression/terminal-hidden.spec.ts | 5 +- .../regression/terminal-tab-switch.spec.ts | 145 ++ packages/app/e2e/tsconfig.json | 10 +- packages/app/e2e/utils/mock-server.ts | 37 +- packages/app/e2e/utils/sse-transport.ts | 284 +++ packages/app/e2e/utils/visual-stability.ts | 54 + .../e2e/utils/visual-stability/analyzer.ts | 209 ++ .../app/e2e/utils/visual-stability/capture.ts | 51 + .../app/e2e/utils/visual-stability/index.ts | 8 + .../e2e/utils/visual-stability/invariant.ts | 112 + .../app/e2e/utils/visual-stability/model.ts | 47 + .../app/e2e/utils/visual-stability/probe.ts | 226 ++ .../app/e2e/utils/visual-stability/regions.ts | 18 + .../e2e/utils/visual-stability/reporter.ts | 63 + .../e2e/utils/visual-stability/scenario.ts | 20 + packages/app/package.json | 5 +- packages/app/src/app.tsx | 92 +- .../components/dialog-connect-provider.tsx | 309 ++- .../src/components/dialog-custom-provider.tsx | 335 ++- .../src/components/dialog-manage-models.tsx | 6 +- .../dialog-select-model-search.test.ts | 19 + .../components/dialog-select-model-search.ts | 18 + .../components/dialog-select-model-unpaid.tsx | 13 +- .../src/components/dialog-select-model.tsx | 53 +- .../src/components/dialog-select-provider.tsx | 87 - .../app/src/components/dialog-settings.tsx | 21 +- .../src/components/file-tree-v2-model.test.ts | 46 + .../app/src/components/file-tree-v2-model.ts | 77 + packages/app/src/components/file-tree-v2.tsx | 268 ++ packages/app/src/components/file-tree.tsx | 10 +- packages/app/src/components/prompt-input.tsx | 4 +- .../components/prompt-input/context-items.tsx | 6 +- .../prompt-input/submission-state.ts | 2 + .../components/prompt-project-selector.tsx | 34 +- .../src/components/session/session-header.tsx | 4 +- .../session-sortable-terminal-tab-v2.tsx | 271 +++ .../app/src/components/settings-keybinds.tsx | 14 +- .../app/src/components/settings-providers.tsx | 30 +- .../settings-v2/dialog-settings-v2.tsx | 20 +- .../src/components/settings-v2/providers.tsx | 30 +- .../components/settings-v2/settings-v2.css | 2 +- .../app/src/components/titlebar-tab-nav.tsx | 26 +- .../src/components/titlebar-tab-popover.css | 42 +- .../src/components/titlebar-tab-popover.tsx | 31 +- .../app/src/components/titlebar-tab-strip.tsx | 6 - packages/app/src/components/titlebar.tsx | 35 +- .../components/virtual-scroll-element.test.ts | 18 + .../src/components/virtual-scroll-element.ts | 4 + packages/app/src/context/closed-tabs.ts | 40 + packages/app/src/context/comments.tsx | 10 +- packages/app/src/context/file/tree-store.ts | 6 +- .../src/context/global-sync/bootstrap.test.ts | 133 +- .../app/src/context/global-sync/bootstrap.ts | 40 +- packages/app/src/context/global.tsx | 12 +- packages/app/src/context/layout.tsx | 13 +- .../app/src/context/server-session.test.ts | 306 +++ packages/app/src/context/server-session.ts | 142 +- packages/app/src/context/server.test.ts | 84 +- packages/app/src/context/server.tsx | 50 +- packages/app/src/context/tabs.test.ts | 81 + packages/app/src/context/tabs.tsx | 59 +- packages/app/src/i18n/en.ts | 2 + packages/app/src/index.ts | 6 + .../app/src/pages/home-session-open.test.ts | 12 + packages/app/src/pages/home-session-open.ts | 11 + packages/app/src/pages/home.tsx | 163 +- packages/app/src/pages/layout.tsx | 4 +- .../src/pages/layout/project-avatar-state.ts | 30 +- .../src/pages/layout/session-tab-avatar.tsx | 11 +- packages/app/src/pages/new-session.tsx | 34 +- packages/app/src/pages/session.tsx | 311 ++- .../app/src/pages/session/helpers.test.ts | 21 - packages/app/src/pages/session/helpers.ts | 7 - .../app/src/pages/session/session-lineage.ts | 69 + .../session/session-panel-layout.test.ts | 19 + .../src/pages/session/session-panel-layout.ts | 6 + .../src/pages/session/session-side-panel.tsx | 40 +- .../src/pages/session/terminal-panel-v2.tsx | 366 +++ .../session/timeline/message-timeline.tsx | 63 +- .../src/pages/session/timeline/model.test.ts | 8 +- .../app/src/pages/session/timeline/model.ts | 6 +- .../pages/session/timeline/projection.test.ts | 96 + .../src/pages/session/timeline/projection.ts | 15 +- .../session/timeline/row-reconciliation.ts | 56 + .../app/src/pages/session/timeline/rows.ts | 81 +- .../pages/session/timeline/timeline-row.ts | 80 + .../pages/session/usage-exceeded-dialogs.tsx | 8 +- .../pages/session/use-composer-commands.tsx | 17 +- .../session/v2/review-diff-kinds.test.ts | 30 + .../src/pages/session/v2/review-diff-kinds.ts | 43 + .../pages/session/v2/review-panel-v2-state.ts | 40 + .../src/pages/session/v2/review-panel-v2.tsx | 233 ++ .../pages/session/v2/session-file-list-v2.tsx | 156 ++ packages/app/src/utils/search-keydown.ts | 116 + packages/app/src/utils/server-errors.ts | 14 + packages/app/src/utils/session-route.test.ts | 15 +- packages/app/src/utils/session-route.ts | 9 - .../prompt-submission-state.test.ts | 17 + .../app/test-browser/session-lineage.test.ts | 231 ++ .../app/test-browser/solid-virtual.test.ts | 15 + packages/app/test-browser/toast-owner.test.ts | 26 + packages/cli/package.json | 2 +- packages/cli/src/mini/footer.subagent.tsx | 4 +- packages/cli/src/mini/footer.view.tsx | 4 +- packages/cli/src/mini/stream-v2.transport.ts | 2 +- packages/codemode/package.json | 2 +- packages/console/app/package.json | 2 +- packages/console/app/src/lib/stats-proxy.ts | 4 +- packages/console/app/src/routes/feishu.ts | 2 +- .../app/src/routes/zen/util/handler.ts | 72 +- packages/console/core/package.json | 2 +- packages/console/function/package.json | 2 +- packages/console/mail/package.json | 2 +- packages/console/support/package.json | 2 +- packages/core/package.json | 2 +- packages/core/src/permission.ts | 19 +- .../src/plugin/provider/github-copilot.ts | 8 + packages/core/src/session/compaction.ts | 38 +- packages/core/src/session/runner/llm.ts | 16 +- packages/core/test/aisdk.test.ts | 36 +- packages/core/test/command.test.ts | 1 - packages/core/test/mcp.test.ts | 8 +- packages/core/test/permission.test.ts | 24 +- .../plugin/provider-github-copilot.test.ts | 30 + packages/core/test/project.test.ts | 14 +- packages/core/test/session-prompt.test.ts | 17 +- packages/core/test/session-runner.test.ts | 172 +- packages/core/test/skill-discovery.test.ts | 21 +- packages/core/test/skill.test.ts | 4 +- packages/core/test/tool-apply-patch.test.ts | 2 +- packages/core/test/tool-edit.test.ts | 2 +- packages/core/test/tool-question.test.ts | 2 +- packages/core/test/tool-read.test.ts | 2 +- packages/core/test/tool-shell.test.ts | 2 +- packages/core/test/tool-skill.test.ts | 2 +- packages/core/test/tool-todowrite.test.ts | 2 +- packages/core/test/tool-write.test.ts | 2 +- packages/desktop/electron.vite.config.ts | 11 + packages/desktop/package.json | 2 +- packages/desktop/src/main/index.ts | 5 + packages/desktop/src/main/ipc.ts | 6 + packages/desktop/src/main/onboarding.ts | 28 + packages/desktop/src/main/store-keys.ts | 1 + packages/desktop/src/main/store.ts | 7 + packages/desktop/src/main/updater.ts | 19 +- .../desktop/src/main/window-registry.test.ts | 91 + packages/desktop/src/main/window-registry.ts | 47 + packages/desktop/src/main/windows.ts | 67 +- packages/desktop/src/preload/index.ts | 3 + packages/desktop/src/preload/types.ts | 2 + packages/desktop/src/renderer/index.tsx | 16 +- packages/desktop/src/renderer/onboarding.tsx | 79 + packages/effect-drizzle-sqlite/package.json | 2 +- packages/effect-sqlite-node/package.json | 2 +- packages/enterprise/package.json | 2 +- packages/function/package.json | 2 +- packages/http-recorder/package.json | 2 +- packages/llm/package.json | 2 +- packages/llm/src/providers/github-copilot.ts | 9 +- packages/llm/test/exports.test.ts | 14 + packages/opencode/package.json | 5 +- packages/opencode/src/cli/cmd/tui.ts | 9 +- packages/opencode/src/effect/runtime-flags.ts | 1 + packages/opencode/src/mcp/browser.ts | 37 + packages/opencode/src/mcp/index.ts | 40 +- packages/opencode/src/permission/index.ts | 5 + .../src/plugin/github-copilot/models.ts | 14 +- packages/opencode/src/provider/provider.ts | 6 +- packages/opencode/src/provider/transform.ts | 3 - .../instance/httpapi/handlers/experimental.ts | 3 +- .../instance/httpapi/handlers/session.ts | 4 +- packages/opencode/src/session/processor.ts | 2 + packages/opencode/src/session/prompt.ts | 1 + packages/opencode/src/session/tools.ts | 9 +- packages/opencode/src/tool/code-mode.ts | 310 +++ packages/opencode/src/tool/registry.ts | 34 +- .../test/fixture/mcp-lifecycle-stdio.ts | 26 + packages/opencode/test/mcp/headers.test.ts | 165 +- packages/opencode/test/mcp/lifecycle.test.ts | 1688 ++++--------- .../test/mcp/oauth-auto-connect.test.ts | 541 ++--- .../opencode/test/mcp/oauth-browser.test.ts | 398 ++- .../test/plugin/github-copilot-models.test.ts | 38 + .../opencode/test/provider/transform.test.ts | 6 +- .../test/server/httpapi-exercise/index.ts | 30 +- .../test/server/httpapi-session.test.ts | 73 + .../opencode/test/session/compaction.test.ts | 4 +- packages/opencode/test/session/llm.test.ts | 74 + .../test/tool/code-mode-integration.test.ts | 331 +++ packages/opencode/test/tool/code-mode.test.ts | 730 ++++++ packages/opencode/test/tool/registry.test.ts | 79 + packages/plugin/package.json | 2 +- packages/schema/test/v1-isolation.test.ts | 2 +- packages/sdk/js/package.json | 2 +- packages/sdk/openapi.json | 1 + packages/server/package.json | 2 +- packages/session-ui/package.json | 2 +- .../session-ui/src/components/basic-tool.css | 52 + .../session-ui/src/components/basic-tool.tsx | 25 +- .../session-ui/src/components/file-media.tsx | 64 +- packages/session-ui/src/components/file.tsx | 9 +- .../components/line-comment-annotations.tsx | 243 +- .../src/components/message-part.tsx | 135 +- .../session-ui/src/pierre/comment-hover.ts | 17 +- .../line-comment-annotations-v2.tsx | 212 ++ .../session-review-empty-changes-v2.tsx | 17 + .../session-review-empty-no-git-v2.tsx | 28 + ...-review-file-preview-v2-virtualize.test.ts | 13 + ...ssion-review-file-preview-v2-virtualize.ts | 5 + .../session-review-file-preview-v2.tsx | 287 +++ .../src/v2/components/session-review-v2.css | 432 ++++ .../src/v2/components/session-review-v2.tsx | 331 +++ packages/slack/package.json | 2 +- packages/stats/app/package.json | 2 +- packages/stats/app/src/context/language.tsx | 13 +- packages/stats/app/src/i18n.ts | 6 +- .../stats/app/src/routes/[lab]/[model].tsx | 741 +++--- packages/stats/app/src/routes/[lab]/index.tsx | 857 +++++-- packages/stats/app/src/routes/index.css | 2149 ++++++++++++++++- packages/stats/app/src/routes/index.tsx | 68 +- .../stats/app/src/routes/model-catalog.ts | 78 +- packages/stats/app/src/routes/stats-cache.ts | 4 +- packages/stats/core/package.json | 2 +- packages/stats/server/package.json | 2 +- packages/tui/package.json | 5 +- packages/tui/src/app.tsx | 21 +- packages/tui/src/component/dialog-debug.tsx | 90 + .../tui/src/component/error-component.tsx | 21 +- packages/tui/src/component/prompt/index.tsx | 4 +- .../tui/src/component/register-spinner.ts | 6 + packages/tui/src/component/spinner.tsx | 4 +- packages/tui/src/config/keybind.ts | 2 + .../src/feature-plugins/home/tips-view.tsx | 34 +- packages/tui/src/routes/session/index.tsx | 1 + packages/tui/src/ui/dialog.tsx | 3 + packages/tui/src/util/system.ts | 20 + packages/ui/package.json | 2 +- packages/ui/src/components/collapsible.css | 6 + .../ui/src/components/scroll-view.test.ts | 23 +- packages/ui/src/components/scroll-view.tsx | 74 +- packages/ui/src/components/tabs.css | 48 +- packages/ui/src/context/marked.tsx | 64 +- packages/ui/src/i18n/en.ts | 18 + packages/ui/src/styles/theme.css | 18 + packages/ui/src/theme/v2/mapping.ts | 26 + .../ui/src/v2/components/file-tree-v2.css | 120 + packages/ui/src/v2/components/icon.tsx | 24 + .../src/v2/components/project-avatar-v2.css | 7 + .../components/project-avatar-v2.stories.tsx | 10 +- .../src/v2/components/project-avatar-v2.tsx | 5 +- .../ui/src/v2/components/text-input-v2.css | 33 + .../ui/src/v2/components/text-input-v2.tsx | 36 +- packages/ui/src/v2/components/toast-v2.tsx | 76 +- packages/ui/src/v2/components/tooltip-v2.css | 5 + packages/ui/src/v2/styles/theme.css | 40 + packages/web/package.json | 2 +- sdks/vscode/package.json | 2 +- specs/v2/session.md | 4 + 332 files changed, 24650 insertions(+), 4497 deletions(-) create mode 100644 artifacts/glm52-rise-video/.gitignore create mode 100644 artifacts/glm52-rise-video/bun.lock create mode 100644 artifacts/glm52-rise-video/out/flash-share.mp4 create mode 100644 artifacts/glm52-rise-video/out/glm-52-broke-out.mp4 create mode 100644 artifacts/glm52-rise-video/out/june-totals.png create mode 100644 artifacts/glm52-rise-video/out/minimax-climb.mp4 create mode 100644 artifacts/glm52-rise-video/out/novel-1984.mp4 create mode 100644 artifacts/glm52-rise-video/out/nz-sheep.mp4 create mode 100644 artifacts/glm52-rise-video/package.json create mode 100644 artifacts/glm52-rise-video/public/book.jpg create mode 100644 artifacts/glm52-rise-video/public/sheep.jpg create mode 100644 artifacts/glm52-rise-video/src/data.ts create mode 100644 artifacts/glm52-rise-video/src/flash.tsx create mode 100644 artifacts/glm52-rise-video/src/index.tsx create mode 100644 artifacts/glm52-rise-video/src/june.tsx create mode 100644 artifacts/glm52-rise-video/src/minimax.tsx create mode 100644 artifacts/glm52-rise-video/src/novel.tsx create mode 100644 artifacts/glm52-rise-video/src/sheep.tsx create mode 100644 artifacts/glm52-rise-video/src/video.tsx create mode 100644 packages/app/e2e/performance/timeline-stability/README.md create mode 100644 packages/app/e2e/performance/timeline-stability/adverse.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/context-matrix.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/environment-matrix.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/file-matrix.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/file-mutation.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/fixture.test.ts create mode 100644 packages/app/e2e/performance/timeline-stability/fixture.ts create mode 100644 packages/app/e2e/performance/timeline-stability/interaction.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/lifecycle.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/oracle-browser.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/playwright.config.ts create mode 100644 packages/app/e2e/performance/timeline-stability/scroll-interaction.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/shell-matrix.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/tool-mutation.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/tools.spec.ts create mode 100644 packages/app/e2e/performance/timeline-stability/transition-matrix.spec.ts create mode 100644 packages/app/e2e/performance/timeline/review-pane-scaling-benchmark.spec.ts create mode 100644 packages/app/e2e/performance/timeline/session-parent-hydration-benchmark.spec.ts create mode 100644 packages/app/e2e/performance/unit/mock-server.test.ts create mode 100644 packages/app/e2e/performance/unit/session-tab-switch-probe.test.ts create mode 100644 packages/app/e2e/performance/unit/visual-stability.test.ts create mode 100644 packages/app/e2e/regression/new-session-panel-corner.spec.ts create mode 100644 packages/app/e2e/regression/remote-tab-busy.spec.ts create mode 100644 packages/app/e2e/regression/review-image-flash.spec.ts create mode 100644 packages/app/e2e/regression/review-tab-switch.spec.ts create mode 100644 packages/app/e2e/regression/review-terminal-stacked.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-accessibility.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-context-state.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-file-projection.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-file-state.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-history-root.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-lifecycle-state.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-locale-projection.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-projection.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-reasoning-projection.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-reducer-projection.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-tool-projection.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-tool-state.spec.ts create mode 100644 packages/app/e2e/regression/session-timeline-transport.spec.ts create mode 100644 packages/app/e2e/regression/subagent-child-navigation.spec.ts create mode 100644 packages/app/e2e/regression/tab-navigate-mousedown.spec.ts create mode 100644 packages/app/e2e/regression/terminal-composer-focus.spec.ts create mode 100644 packages/app/e2e/regression/terminal-tab-switch.spec.ts create mode 100644 packages/app/e2e/utils/sse-transport.ts create mode 100644 packages/app/e2e/utils/visual-stability.ts create mode 100644 packages/app/e2e/utils/visual-stability/analyzer.ts create mode 100644 packages/app/e2e/utils/visual-stability/capture.ts create mode 100644 packages/app/e2e/utils/visual-stability/index.ts create mode 100644 packages/app/e2e/utils/visual-stability/invariant.ts create mode 100644 packages/app/e2e/utils/visual-stability/model.ts create mode 100644 packages/app/e2e/utils/visual-stability/probe.ts create mode 100644 packages/app/e2e/utils/visual-stability/regions.ts create mode 100644 packages/app/e2e/utils/visual-stability/reporter.ts create mode 100644 packages/app/e2e/utils/visual-stability/scenario.ts create mode 100644 packages/app/src/components/dialog-select-model-search.test.ts create mode 100644 packages/app/src/components/dialog-select-model-search.ts delete mode 100644 packages/app/src/components/dialog-select-provider.tsx create mode 100644 packages/app/src/components/file-tree-v2-model.test.ts create mode 100644 packages/app/src/components/file-tree-v2-model.ts create mode 100644 packages/app/src/components/file-tree-v2.tsx create mode 100644 packages/app/src/components/session/session-sortable-terminal-tab-v2.tsx create mode 100644 packages/app/src/components/virtual-scroll-element.test.ts create mode 100644 packages/app/src/components/virtual-scroll-element.ts create mode 100644 packages/app/src/context/closed-tabs.ts create mode 100644 packages/app/src/pages/home-session-open.test.ts create mode 100644 packages/app/src/pages/home-session-open.ts create mode 100644 packages/app/src/pages/session/session-lineage.ts create mode 100644 packages/app/src/pages/session/session-panel-layout.test.ts create mode 100644 packages/app/src/pages/session/session-panel-layout.ts create mode 100644 packages/app/src/pages/session/terminal-panel-v2.tsx create mode 100644 packages/app/src/pages/session/timeline/projection.test.ts create mode 100644 packages/app/src/pages/session/timeline/row-reconciliation.ts create mode 100644 packages/app/src/pages/session/timeline/timeline-row.ts create mode 100644 packages/app/src/pages/session/v2/review-diff-kinds.test.ts create mode 100644 packages/app/src/pages/session/v2/review-diff-kinds.ts create mode 100644 packages/app/src/pages/session/v2/review-panel-v2-state.ts create mode 100644 packages/app/src/pages/session/v2/review-panel-v2.tsx create mode 100644 packages/app/src/pages/session/v2/session-file-list-v2.tsx create mode 100644 packages/app/src/utils/search-keydown.ts create mode 100644 packages/app/test-browser/session-lineage.test.ts create mode 100644 packages/app/test-browser/toast-owner.test.ts create mode 100644 packages/desktop/src/main/onboarding.ts create mode 100644 packages/desktop/src/main/window-registry.test.ts create mode 100644 packages/desktop/src/main/window-registry.ts create mode 100644 packages/desktop/src/renderer/onboarding.tsx create mode 100644 packages/opencode/src/mcp/browser.ts create mode 100644 packages/opencode/src/tool/code-mode.ts create mode 100644 packages/opencode/test/fixture/mcp-lifecycle-stdio.ts create mode 100644 packages/opencode/test/tool/code-mode-integration.test.ts create mode 100644 packages/opencode/test/tool/code-mode.test.ts create mode 100644 packages/session-ui/src/v2/components/line-comment-annotations-v2.tsx create mode 100644 packages/session-ui/src/v2/components/session-review-empty-changes-v2.tsx create mode 100644 packages/session-ui/src/v2/components/session-review-empty-no-git-v2.tsx create mode 100644 packages/session-ui/src/v2/components/session-review-file-preview-v2-virtualize.test.ts create mode 100644 packages/session-ui/src/v2/components/session-review-file-preview-v2-virtualize.ts create mode 100644 packages/session-ui/src/v2/components/session-review-file-preview-v2.tsx create mode 100644 packages/session-ui/src/v2/components/session-review-v2.css create mode 100644 packages/session-ui/src/v2/components/session-review-v2.tsx create mode 100644 packages/tui/src/component/dialog-debug.tsx create mode 100644 packages/tui/src/component/register-spinner.ts create mode 100644 packages/tui/src/util/system.ts create mode 100644 packages/ui/src/v2/components/file-tree-v2.css diff --git a/README.zh.md b/README.zh.md index 93f81e83cd0..352e13ccaa1 100644 --- a/README.zh.md +++ b/README.zh.md @@ -125,4 +125,4 @@ OpenCode 内置两种 Agent,可用 `Tab` 键快速切换: --- -**加入我们的社区** [飞书](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=738j8655-cd59-4633-a30a-1124e0096789&qr_code=true) | [X.com](https://x.com/opencode) +**加入我们的社区** [飞书](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=52ao9352-5623-4fa0-b7dd-3407c392c1af&qr_code=true) | [X.com](https://x.com/opencode) diff --git a/README.zht.md b/README.zht.md index 59d9709bd39..f09358b1330 100644 --- a/README.zht.md +++ b/README.zht.md @@ -125,4 +125,4 @@ OpenCode 內建了兩種 Agent,您可以使用 `Tab` 鍵快速切換。 --- -**加入我們的社群** [飞书](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=738j8655-cd59-4633-a30a-1124e0096789&qr_code=true) | [X.com](https://x.com/opencode) +**加入我們的社群** [飞书](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=52ao9352-5623-4fa0-b7dd-3407c392c1af&qr_code=true) | [X.com](https://x.com/opencode) diff --git a/artifacts/glm52-rise-video/.gitignore b/artifacts/glm52-rise-video/.gitignore new file mode 100644 index 00000000000..9d38bb25911 --- /dev/null +++ b/artifacts/glm52-rise-video/.gitignore @@ -0,0 +1,3 @@ +node_modules +.remotion +out/frame-*.png diff --git a/artifacts/glm52-rise-video/bun.lock b/artifacts/glm52-rise-video/bun.lock new file mode 100644 index 00000000000..cac009ae812 --- /dev/null +++ b/artifacts/glm52-rise-video/bun.lock @@ -0,0 +1,483 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "glm52-rise-video", + "dependencies": { + "@remotion/cli": "^4.0.384", + "react": "^19.2.3", + "react-dom": "^19.2.3", + "remotion": "^4.0.384", + }, + "devDependencies": { + "@types/react": "^19.2.8", + "@types/react-dom": "^19.2.3", + "typescript": "^5.8.2", + }, + }, + }, + "packages": { + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], + + "@babel/parser": ["@babel/parser@7.24.1", "", { "bin": "./bin/babel-parser.js" }, "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg=="], + + "@babel/types": ["@babel/types@7.24.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w=="], + + "@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], + + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.28.1", "", { "os": "android", "cpu": "arm" }, "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.28.1", "", { "os": "android", "cpu": "arm64" }, "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.28.1", "", { "os": "android", "cpu": "x64" }, "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.28.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.28.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.28.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.28.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.28.1", "", { "os": "linux", "cpu": "arm" }, "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.28.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.28.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.28.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.28.1", "", { "os": "linux", "cpu": "none" }, "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.28.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.28.1", "", { "os": "linux", "cpu": "x64" }, "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.28.1", "", { "os": "none", "cpu": "x64" }, "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.28.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.28.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.28.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.28.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.28.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.28.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + + "@mediabunny/aac-encoder": ["@mediabunny/aac-encoder@1.47.0", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-JNzgdJoHMFFnv5imi1+dmjZMudsJ1zNCUCEkKjBh90cqGhAFg8xu4V2gsyxE2i6oq/YpWx23P+OvoANLSMcDzA=="], + + "@mediabunny/flac-encoder": ["@mediabunny/flac-encoder@1.47.0", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-VpKmJO0xlYcFCRD6JvJlMbNQ6d/6YMHdO1gFIqWlZABHjSSL6BquNNEgWSCv5vdF8ELDBwIYBVZEslakIB/7GA=="], + + "@mediabunny/mp3-encoder": ["@mediabunny/mp3-encoder@1.47.0", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-JyzZyGeGRm2HVUQaGJ/VZT9OG+kG00mA8SLP/f3CO7+qWAmBncKc16WYXWHbZEo8Jn/ZGA6De32S5R2bTQbDqA=="], + + "@module-federation/error-codes": ["@module-federation/error-codes@0.22.0", "", {}, "sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug=="], + + "@module-federation/runtime": ["@module-federation/runtime@0.22.0", "", { "dependencies": { "@module-federation/error-codes": "0.22.0", "@module-federation/runtime-core": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA=="], + + "@module-federation/runtime-core": ["@module-federation/runtime-core@0.22.0", "", { "dependencies": { "@module-federation/error-codes": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA=="], + + "@module-federation/runtime-tools": ["@module-federation/runtime-tools@0.22.0", "", { "dependencies": { "@module-federation/runtime": "0.22.0", "@module-federation/webpack-bundler-runtime": "0.22.0" } }, "sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA=="], + + "@module-federation/sdk": ["@module-federation/sdk@0.22.0", "", {}, "sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g=="], + + "@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.22.0", "", { "dependencies": { "@module-federation/runtime": "0.22.0", "@module-federation/sdk": "0.22.0" } }, "sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA=="], + + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="], + + "@remotion/bundler": ["@remotion/bundler@4.0.483", "", { "dependencies": { "@remotion/media-parser": "4.0.483", "@remotion/studio": "4.0.483", "@remotion/studio-shared": "4.0.483", "@remotion/timeline-utils": "4.0.483", "@rspack/core": "1.7.11", "@rspack/plugin-react-refresh": "1.6.1", "css-loader": "7.1.4", "esbuild": "0.28.1", "react-refresh": "0.18.0", "remotion": "4.0.483", "style-loader": "4.0.0", "webpack": "5.105.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-5fQRMYgr2sxZPBOThnIVuFwHBq/FhusJ+Ke6xopga8io8ecK/mj9GaRXC3tgfMa+YWuu8ZSXZ0U9EsMZjjP5YQ=="], + + "@remotion/canvas-capture": ["@remotion/canvas-capture@4.0.483", "", { "dependencies": { "mediabunny": "1.47.0", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-JABgbfvXwjFp1E61tlDN9gVAH8OoeF4kUUELNwG9kcNOE4ex8+vCYEO6VKIaXZ4l8A1PEAQ5EK//NheTJ80gfw=="], + + "@remotion/cli": ["@remotion/cli@4.0.483", "", { "dependencies": { "@remotion/bundler": "4.0.483", "@remotion/media-utils": "4.0.483", "@remotion/player": "4.0.483", "@remotion/renderer": "4.0.483", "@remotion/studio": "4.0.483", "@remotion/studio-server": "4.0.483", "@remotion/studio-shared": "4.0.483", "dotenv": "17.3.1", "minimist": "1.2.6", "prompts": "2.4.2", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" }, "bin": { "remotion": "remotion-cli.js", "remotionb": "remotionb-cli.js", "remotiond": "remotiond-cli.js" } }, "sha512-z4TQcgTfQbSIV4GQpCvIihDL77M+leQelbxv962PmfSKTT7z3XnNN732PcZ4sei2+Xg+d2SD95K4tI5XBYs5Gw=="], + + "@remotion/compositor-darwin-arm64": ["@remotion/compositor-darwin-arm64@4.0.483", "", { "os": "darwin", "cpu": "arm64" }, "sha512-CkEJXouGEoCs5PX3KOufkXrlT/Kgn0ZF7SEQ4meCYGYMZD+QPVtsmS1MXH8pQ4RHlFO6Tk7g0CIHMT3Y4yzpuA=="], + + "@remotion/compositor-darwin-x64": ["@remotion/compositor-darwin-x64@4.0.483", "", { "os": "darwin", "cpu": "x64" }, "sha512-vDZK5U8FYbHGMjFC2lUgJRBz8KXwbwFSvEQi8FATD0roNg75SoaEJWrqAOIVv8v5eBjPvo18znDc36NLRYn1Eg=="], + + "@remotion/compositor-linux-arm64-gnu": ["@remotion/compositor-linux-arm64-gnu@4.0.483", "", { "os": "linux", "cpu": "arm64" }, "sha512-1LzfYDY/DQxy3MIc9pCbTn1ObcBDcyI6MzODOwe1bTZl8TZxdUUt1M3hDrQ60AB6iHwruBAnzT9dnogiMIdSew=="], + + "@remotion/compositor-linux-arm64-musl": ["@remotion/compositor-linux-arm64-musl@4.0.483", "", { "os": "linux", "cpu": "arm64" }, "sha512-nG1btxg0HXuLzulIqAg9NnxWyewZNrA0iLe82HdniaJjeWLORreGo4cEEJz1SjbDpQuPEY562XGkTO2DLKK5mA=="], + + "@remotion/compositor-linux-x64-gnu": ["@remotion/compositor-linux-x64-gnu@4.0.483", "", { "os": "linux", "cpu": "x64" }, "sha512-CV4h6r2rNYh4P8utUzP6RM2vW2vq43nA3IvVOwRSuh9LwJh/7rwG53Oco4HanY/sstaNuymGpT57wdXwONU5CQ=="], + + "@remotion/compositor-linux-x64-musl": ["@remotion/compositor-linux-x64-musl@4.0.483", "", { "os": "linux", "cpu": "x64" }, "sha512-moKvavbkoz5nteJZA4K6LMgTTlewhwIbtO7DYARZ3LK3ClGUKnYfFcmaPS15hMun02JPTOMIWbrlaszdR75mxA=="], + + "@remotion/compositor-win32-x64-msvc": ["@remotion/compositor-win32-x64-msvc@4.0.483", "", { "os": "win32", "cpu": "x64" }, "sha512-eDpWe6Vy7ySHugwxlgaeohqdBwR1etxiymXzT13cgbPw2+p6d55z1tJ7VPTXyfu0o+UdyRTauWqD4msoxN0wow=="], + + "@remotion/licensing": ["@remotion/licensing@4.0.483", "", {}, "sha512-GRtjykrxMmB5Cjpq1oVqeYIRXI95vid6afX0LTLfp1shD6MR4lTZRoRuopxrrZp1E4XFGXoY64b6dlIudgTyBQ=="], + + "@remotion/media-parser": ["@remotion/media-parser@4.0.483", "", {}, "sha512-iva9Eof7QQX+3hGxH/N8pGi80wgdGuzOr825Zn7IuEe7IWdtRYWlFpCEghmyfhrwgaWa7RY51wg77ycR3c3nRg=="], + + "@remotion/media-utils": ["@remotion/media-utils@4.0.483", "", { "dependencies": { "mediabunny": "1.47.0", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4T4WQh/U95kCBzgmz/EL/HL8Zeox/AKAL5ufsehrZFgwlcvH1EsKNJH/RWaAtNPRLF+pskEOgFzPYaczHeI8hg=="], + + "@remotion/player": ["@remotion/player@4.0.483", "", { "dependencies": { "remotion": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-yyIQ9vinUqqS0fQeL52bPCWQIr8qDXCqQ4iys8P7dSZncdu8V29p4W2a0/4eKV8bv5+mjnJQ/U6nl9NxBF1hdA=="], + + "@remotion/renderer": ["@remotion/renderer@4.0.483", "", { "dependencies": { "@remotion/licensing": "4.0.483", "@remotion/streaming": "4.0.483", "execa": "5.1.1", "remotion": "4.0.483", "source-map": "0.8.0-beta.0", "ws": "8.21.0" }, "optionalDependencies": { "@remotion/compositor-darwin-arm64": "4.0.483", "@remotion/compositor-darwin-x64": "4.0.483", "@remotion/compositor-linux-arm64-gnu": "4.0.483", "@remotion/compositor-linux-arm64-musl": "4.0.483", "@remotion/compositor-linux-x64-gnu": "4.0.483", "@remotion/compositor-linux-x64-musl": "4.0.483", "@remotion/compositor-win32-x64-msvc": "4.0.483" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-eSKdQqm8rcl+GNyOhFsBgcPYWMcxTJWHL5xaNrd037piCaL3sdJ57OEO/AbfEvvOO14zwUvlsONKjlkLlEVyKg=="], + + "@remotion/streaming": ["@remotion/streaming@4.0.483", "", {}, "sha512-96rqrk+l5AfriHOqmqxMn8rI6UJfFY7r5UMDZoSKqXWzTOwj+0VWHTRl9ilZQMXhYACaMSA/5yrL9jgQEK8Yuw=="], + + "@remotion/studio": ["@remotion/studio@4.0.483", "", { "dependencies": { "@jridgewell/trace-mapping": "0.3.31", "@remotion/canvas-capture": "4.0.483", "@remotion/media-utils": "4.0.483", "@remotion/player": "4.0.483", "@remotion/renderer": "4.0.483", "@remotion/studio-shared": "4.0.483", "@remotion/timeline-utils": "4.0.483", "@remotion/web-renderer": "4.0.483", "@remotion/zod-types": "4.0.483", "mediabunny": "1.47.0", "memfs": "3.4.3", "open": "8.4.2", "remotion": "4.0.483", "semver": "7.5.3", "zod": "4.3.6" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-gNa1Lw8NmHl0jwFb5fk7rzA+WFTJQpGDT/49A38t9jpEwoF+h1mKTgY8gA202apzjBHrEECdFE450npnBOUpUw=="], + + "@remotion/studio-server": ["@remotion/studio-server@4.0.483", "", { "dependencies": { "@babel/parser": "7.24.1", "@babel/types": "7.24.0", "@remotion/bundler": "4.0.483", "@remotion/renderer": "4.0.483", "@remotion/studio-shared": "4.0.483", "memfs": "3.4.3", "open": "8.4.2", "prettier": "3.8.1", "recast": "0.23.11", "remotion": "4.0.483", "semver": "7.5.3" } }, "sha512-2FSLbVN5N8bgtQPX+RQRbis557tJJnVTOZuEBZndfC9NOoPdARlSgEnwVer9tBNczUlc6B3KrPxyPSlS3UjL+Q=="], + + "@remotion/studio-shared": ["@remotion/studio-shared@4.0.483", "", { "dependencies": { "remotion": "4.0.483" } }, "sha512-aXxBYUgsWgphHVq7T7bz+ICMGzfii7pcX1IxS5hbLMLJHqlDtk9g+qcxm4kJ2Fjj/Gb5gERKiNzYym8WZTIM2Q=="], + + "@remotion/timeline-utils": ["@remotion/timeline-utils@4.0.483", "", { "dependencies": { "mediabunny": "1.47.0" } }, "sha512-KTTMdpNA5uRLX+iisAITO+V9cJBk17F8EWvuUnAEVmAFOQTbGIyPI9HNw5pZmL7SlzOJdFjAtksTjipeYGkEug=="], + + "@remotion/web-renderer": ["@remotion/web-renderer@4.0.483", "", { "dependencies": { "@mediabunny/aac-encoder": "1.47.0", "@mediabunny/flac-encoder": "1.47.0", "@mediabunny/mp3-encoder": "1.47.0", "@remotion/licensing": "4.0.483", "mediabunny": "1.47.0", "remotion": "4.0.483" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-14iURfVWA/hcF/rJvkid1ZR5nmnVhkTIf071FabCFi6kdViOSVBugSglJ8tUPvWVbWmxlXGDGQD9CSU18IATww=="], + + "@remotion/zod-types": ["@remotion/zod-types@4.0.483", "", { "dependencies": { "remotion": "4.0.483" }, "peerDependencies": { "zod": "4.3.6" } }, "sha512-KIVYIzFpZBDB0wxGGQu5tDBr4XOYRzvrPXjmo6O/FI5Xx7O8hgvJmBs9VDkEwonAOft86sg79hI19F1DTX1p4w=="], + + "@rspack/binding": ["@rspack/binding@1.7.11", "", { "optionalDependencies": { "@rspack/binding-darwin-arm64": "1.7.11", "@rspack/binding-darwin-x64": "1.7.11", "@rspack/binding-linux-arm64-gnu": "1.7.11", "@rspack/binding-linux-arm64-musl": "1.7.11", "@rspack/binding-linux-x64-gnu": "1.7.11", "@rspack/binding-linux-x64-musl": "1.7.11", "@rspack/binding-wasm32-wasi": "1.7.11", "@rspack/binding-win32-arm64-msvc": "1.7.11", "@rspack/binding-win32-ia32-msvc": "1.7.11", "@rspack/binding-win32-x64-msvc": "1.7.11" } }, "sha512-2MGdy2s2HimsDT444Bp5XnALzNRxuBNc7y0JzyuqKbHBywd4x2NeXyhWXXoxufaCFu5PBc9Qq9jyfjW2Aeh06Q=="], + + "@rspack/binding-darwin-arm64": ["@rspack/binding-darwin-arm64@1.7.11", "", { "os": "darwin", "cpu": "arm64" }, "sha512-oduECiZVqbO5zlVw+q7Vy65sJFth99fWPTyucwvLJJtJkPL5n17Uiql2cYP6Ijn0pkqtf1SXgK8WjiKLG5bIig=="], + + "@rspack/binding-darwin-x64": ["@rspack/binding-darwin-x64@1.7.11", "", { "os": "darwin", "cpu": "x64" }, "sha512-a1+TtTE9ap6RalgFi7FGIgkJP6O4Vy6ctv+9WGJy53E4kuqHR0RygzaiVxCI/GMc/vBT9vY23hyrpWb3d1vtXA=="], + + "@rspack/binding-linux-arm64-gnu": ["@rspack/binding-linux-arm64-gnu@1.7.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-P0QrGRPbTWu6RKWfN0bDtbnEps3rXH0MWIMreZABoUrVmNQKtXR6e73J3ub6a+di5s2+K0M2LJ9Bh2/H4UsDUA=="], + + "@rspack/binding-linux-arm64-musl": ["@rspack/binding-linux-arm64-musl@1.7.11", "", { "os": "linux", "cpu": "arm64" }, "sha512-6ky7R43VMjWwmx3Yx7Jl7faLBBMAgMDt+/bN35RgwjiPgsIByz65EwytUVuW9rikB43BGHvA/eqlnjLrUzNBqw=="], + + "@rspack/binding-linux-x64-gnu": ["@rspack/binding-linux-x64-gnu@1.7.11", "", { "os": "linux", "cpu": "x64" }, "sha512-cuOJMfCOvb2Wgsry5enXJ3iT1FGUjdPqtGUBVupQlEG4ntSYsQ2PtF4wIDVasR3wdxC5nQbipOrDiN/u6fYsdQ=="], + + "@rspack/binding-linux-x64-musl": ["@rspack/binding-linux-x64-musl@1.7.11", "", { "os": "linux", "cpu": "x64" }, "sha512-CoK37hva4AmHGh3VCsQXmGr40L36m1/AdnN5LEjUX6kx5rEH7/1nEBN6Ii72pejqDVvk9anEROmPDiPw10tpFg=="], + + "@rspack/binding-wasm32-wasi": ["@rspack/binding-wasm32-wasi@1.7.11", "", { "dependencies": { "@napi-rs/wasm-runtime": "1.0.7" }, "cpu": "none" }, "sha512-OtrmnPUVJMxjNa3eDMfHyPdtlLRmmp/aIm0fQHlAOATbZvlGm12q7rhPW5BXTu1yh+1rQ1/uqvz+SzKEZXuJaQ=="], + + "@rspack/binding-win32-arm64-msvc": ["@rspack/binding-win32-arm64-msvc@1.7.11", "", { "os": "win32", "cpu": "arm64" }, "sha512-lObFW6e5lCWNgTBNwT//yiEDbsxm9QG4BYUojqeXxothuzJ/L6ibXz6+gLMvbOvLGV3nKgkXmx8GvT9WDKR0mA=="], + + "@rspack/binding-win32-ia32-msvc": ["@rspack/binding-win32-ia32-msvc@1.7.11", "", { "os": "win32", "cpu": "ia32" }, "sha512-0pYGnZd8PPqNR68zQ8skamqNAXEA1sUfXuAdYcknIIRq2wsbiwFzIc0Pov1cIfHYab37G7sSIPBiOUdOWF5Ivw=="], + + "@rspack/binding-win32-x64-msvc": ["@rspack/binding-win32-x64-msvc@1.7.11", "", { "os": "win32", "cpu": "x64" }, "sha512-EeQXayoQk/uBkI3pdoXfQBXNIUrADq56L3s/DFyM2pJeUDrWmhfIw2UFIGkYPTMSCo8F2JcdcGM32FGJrSnU0Q=="], + + "@rspack/core": ["@rspack/core@1.7.11", "", { "dependencies": { "@module-federation/runtime-tools": "0.22.0", "@rspack/binding": "1.7.11", "@rspack/lite-tapable": "1.1.0" }, "peerDependencies": { "@swc/helpers": ">=0.5.1" }, "optionalPeers": ["@swc/helpers"] }, "sha512-rsD9b+Khmot5DwCMiB3cqTQo53ioPG3M/A7BySu8+0+RS7GCxKm+Z+mtsjtG/vsu4Tn2tcqCdZtA3pgLoJB+ew=="], + + "@rspack/lite-tapable": ["@rspack/lite-tapable@1.1.0", "", {}, "sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw=="], + + "@rspack/plugin-react-refresh": ["@rspack/plugin-react-refresh@1.6.1", "", { "dependencies": { "error-stack-parser": "^2.1.4", "html-entities": "^2.6.0" }, "peerDependencies": { "react-refresh": ">=0.10.0 <1.0.0", "webpack-hot-middleware": "2.x" }, "optionalPeers": ["webpack-hot-middleware"] }, "sha512-eqqW5645VG3CzGzFgNg5HqNdHVXY+567PGjtDhhrM8t67caxmsSzRmT5qfoEIfBcGgFkH9vEg7kzXwmCYQdQDw=="], + + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], + + "@types/dom-mediacapture-transform": ["@types/dom-mediacapture-transform@0.1.11", "", { "dependencies": { "@types/dom-webcodecs": "*" } }, "sha512-Y2p+nGf1bF2XMttBnsVPHUWzRRZzqUoJAKmiP10b5umnO6DDrWI0BrGDJy1pOHoOULVmGSfFNkQrAlC5dcj6nQ=="], + + "@types/dom-webcodecs": ["@types/dom-webcodecs@0.1.13", "", {}, "sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ=="], + + "@types/eslint": ["@types/eslint@9.6.1", "", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], + + "@types/eslint-scope": ["@types/eslint-scope@3.7.7", "", { "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg=="], + + "@types/estree": ["@types/estree@1.0.9", "", {}, "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/node": ["@types/node@26.0.1", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-fc3KiUoBt6kie0N9bIW3E47vZsuaMf0PM2AaUpLCLT0s/LvX1nxAim6Fc049cNxODPpGm6qRAuUOB86SkRuPQw=="], + + "@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="], + + "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], + + "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="], + + "@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="], + + "@webassemblyjs/helper-api-error": ["@webassemblyjs/helper-api-error@1.13.2", "", {}, "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="], + + "@webassemblyjs/helper-buffer": ["@webassemblyjs/helper-buffer@1.14.1", "", {}, "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="], + + "@webassemblyjs/helper-numbers": ["@webassemblyjs/helper-numbers@1.13.2", "", { "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA=="], + + "@webassemblyjs/helper-wasm-bytecode": ["@webassemblyjs/helper-wasm-bytecode@1.13.2", "", {}, "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="], + + "@webassemblyjs/helper-wasm-section": ["@webassemblyjs/helper-wasm-section@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/wasm-gen": "1.14.1" } }, "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw=="], + + "@webassemblyjs/ieee754": ["@webassemblyjs/ieee754@1.13.2", "", { "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw=="], + + "@webassemblyjs/leb128": ["@webassemblyjs/leb128@1.13.2", "", { "dependencies": { "@xtuc/long": "4.2.2" } }, "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw=="], + + "@webassemblyjs/utf8": ["@webassemblyjs/utf8@1.13.2", "", {}, "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="], + + "@webassemblyjs/wasm-edit": ["@webassemblyjs/wasm-edit@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/helper-wasm-section": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-opt": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1", "@webassemblyjs/wast-printer": "1.14.1" } }, "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ=="], + + "@webassemblyjs/wasm-gen": ["@webassemblyjs/wasm-gen@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg=="], + + "@webassemblyjs/wasm-opt": ["@webassemblyjs/wasm-opt@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1" } }, "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw=="], + + "@webassemblyjs/wasm-parser": ["@webassemblyjs/wasm-parser@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ=="], + + "@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="], + + "@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="], + + "@xtuc/long": ["@xtuc/long@4.2.2", "", {}, "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="], + + "acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="], + + "acorn-import-phases": ["acorn-import-phases@1.0.4", "", { "peerDependencies": { "acorn": "^8.14.0" } }, "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ=="], + + "ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="], + + "ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="], + + "ajv-keywords": ["ajv-keywords@5.1.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" } }, "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw=="], + + "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], + + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.40", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-BSSLZ9/Cjjv7Gtj5B68ZzXcXUg8iOf3fme+FCuh8rC/Go+Kmh8cox7M3A8dolou16s64QjLPOSdngh7GxXvkSw=="], + + "browserslist": ["browserslist@4.28.4", "", { "dependencies": { "baseline-browser-mapping": "^2.10.38", "caniuse-lite": "^1.0.30001799", "electron-to-chromium": "^1.5.376", "node-releases": "^2.0.48", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-MTc8i/x9jBQd1iMw2CFGS+rwMa07eYjLR0CCTLDACl9xhxy+nIs3KeML/biicXtk9JrZ6dnnTatmc7ErPXIxqw=="], + + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001799", "", {}, "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw=="], + + "chrome-trace-event": ["chrome-trace-event@1.0.4", "", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="], + + "commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "css-loader": ["css-loader@7.1.4", "", { "dependencies": { "icss-utils": "^5.1.0", "postcss": "^8.4.40", "postcss-modules-extract-imports": "^3.1.0", "postcss-modules-local-by-default": "^4.0.5", "postcss-modules-scope": "^3.2.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", "semver": "^7.6.3" }, "peerDependencies": { "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0", "webpack": "^5.27.0" }, "optionalPeers": ["@rspack/core", "webpack"] }, "sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw=="], + + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="], + + "dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.379", "", {}, "sha512-v/qV5aV5EUA2pGilzUCq5/eyOloZAqDZBu9UMBIzgPpLlprjSR6zswsWBTv0KpqxLGUAZEwhO95ZCt7srymNVA=="], + + "enhanced-resolve": ["enhanced-resolve@5.24.1", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw=="], + + "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="], + + "es-module-lexer": ["es-module-lexer@2.1.0", "", {}, "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ=="], + + "esbuild": ["esbuild@0.28.1", "", { "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" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "eslint-scope": ["eslint-scope@5.1.1", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], + + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@4.3.0", "", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], + + "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + + "execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-uri": ["fast-uri@3.1.2", "", {}, "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ=="], + + "fs-monkey": ["fs-monkey@1.0.3", "", {}, "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q=="], + + "get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], + + "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "html-entities": ["html-entities@2.6.0", "", {}, "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ=="], + + "human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], + + "icss-utils": ["icss-utils@5.1.0", "", { "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA=="], + + "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + + "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + + "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jest-worker": ["jest-worker@27.5.1", "", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="], + + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + + "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + + "loader-runner": ["loader-runner@4.3.2", "", {}, "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w=="], + + "lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="], + + "lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="], + + "mediabunny": ["mediabunny@1.47.0", "", { "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-webcodecs": "0.1.13" } }, "sha512-XQMZAcaKPkJ7hQ/Q2fvBdl3ZazQl2WVxDysUbJWh4PuAnLoerdsQBdPTDWdUdK6hh26LQ8Ue94MLLnmpWvlUYg=="], + + "memfs": ["memfs@3.4.3", "", { "dependencies": { "fs-monkey": "1.0.3" } }, "sha512-eivjfi7Ahr6eQTn44nvTnR60e4a1Fs1Via2kCR5lHo/kyNoiMWaXCNJ/GpSd0ilXas2JSOl9B5FTIhflXu0hlg=="], + + "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], + + "minimist": ["minimist@1.2.6", "", {}, "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q=="], + + "nanoid": ["nanoid@3.3.15", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA=="], + + "neo-async": ["neo-async@2.6.2", "", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], + + "node-releases": ["node-releases@2.0.50", "", {}, "sha512-J6l92tKHX6w8Jy5nO1Vuc01NoIiRGi/d6qBKVxh+IQ8Cr3b6HbVNfKiF8ZpFKufTwpwxMmce2W3iQZ861ZRyTg=="], + + "npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="], + + "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], + + "open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "postcss": ["postcss@8.5.15", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A=="], + + "postcss-modules-extract-imports": ["postcss-modules-extract-imports@3.1.0", "", { "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q=="], + + "postcss-modules-local-by-default": ["postcss-modules-local-by-default@4.2.0", "", { "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.1.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw=="], + + "postcss-modules-scope": ["postcss-modules-scope@3.2.1", "", { "dependencies": { "postcss-selector-parser": "^7.0.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA=="], + + "postcss-modules-values": ["postcss-modules-values@4.0.0", "", { "dependencies": { "icss-utils": "^5.0.0" }, "peerDependencies": { "postcss": "^8.1.0" } }, "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ=="], + + "postcss-selector-parser": ["postcss-selector-parser@7.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg=="], + + "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], + + "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], + + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "react": ["react@19.2.7", "", {}, "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ=="], + + "react-dom": ["react-dom@19.2.7", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.7" } }, "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ=="], + + "react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="], + + "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="], + + "remotion": ["remotion@4.0.483", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-lf4xq4Twn75TQeTavFLrTE4zdck7EKBSx07ZrPv4om40Sist+3G0kq7NNzSjMeJ6G2Wx6vI+0oICD/vv4sGWtg=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + + "schema-utils": ["schema-utils@4.3.3", "", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA=="], + + "semver": ["semver@7.5.3", "", { "dependencies": { "lru-cache": "^6.0.0" }, "bin": { "semver": "bin/semver.js" } }, "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + + "source-map": ["source-map@0.8.0-beta.0", "", { "dependencies": { "whatwg-url": "^7.0.0" } }, "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], + + "stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="], + + "strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="], + + "style-loader": ["style-loader@4.0.0", "", { "peerDependencies": { "webpack": "^5.27.0" } }, "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA=="], + + "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], + + "terser": ["terser@5.48.0", "", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" } }, "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q=="], + + "terser-webpack-plugin": ["terser-webpack-plugin@5.6.1", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ=="], + + "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="], + + "to-fast-properties": ["to-fast-properties@2.0.0", "", {}, "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog=="], + + "tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], + + "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "watchpack": ["watchpack@2.5.2", "", { "dependencies": { "graceful-fs": "^4.1.2" } }, "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg=="], + + "webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], + + "webpack": ["webpack@5.105.0", "", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.15.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.19.0", "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", "terser-webpack-plugin": "^5.3.16", "watchpack": "^2.5.1", "webpack-sources": "^3.3.3" }, "bin": { "webpack": "bin/webpack.js" } }, "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw=="], + + "webpack-sources": ["webpack-sources@3.5.0", "", {}, "sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ=="], + + "whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], + + "yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], + + "css-loader/semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + + "esrecurse/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + } +} diff --git a/artifacts/glm52-rise-video/out/flash-share.mp4 b/artifacts/glm52-rise-video/out/flash-share.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..3e182b4c11267e50fb7af069bd917b81872e6e46 GIT binary patch literal 333945 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%0AkFW=SE6`*D!pyucFxLs~_jLlz0O3k}W(7i_ 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

0esriXHN2LQ0babOUHb_@gH3+vN~LI13w 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

vR{e8<{ge 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

Yvp}}>RWA$tnosdj6+A8@v@Z=H=#==O4AMb_zJ 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%0ArsUT!)Xrow8M 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

6%3DBcE%WMG7s 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�i^>^KuBqxIe#t*)dmXyg!l$=wd;@kLJu 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 M={}4@8H`S+0m_o>t`IW&EbtmE7`rQ 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�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�c`(_9`*wO|2BsX*!P&` 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

8OU?5Q4Vn*kCH(ep~~;fny^P-4`92OO0JSu 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 qOX|?%Wfwt?KIT~pvOUl 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 literal 0 HcmV?d00001 diff --git a/artifacts/glm52-rise-video/out/june-totals.png b/artifacts/glm52-rise-video/out/june-totals.png new file mode 100644 index 0000000000000000000000000000000000000000..678376dbed6998f063dde5ef26de9fb918119792 GIT binary patch literal 65609 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 literal 0 HcmV?d00001 diff --git a/artifacts/glm52-rise-video/out/novel-1984.mp4 b/artifacts/glm52-rise-video/out/novel-1984.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..b94a8992578e1c50e382c06cb2f3b026412eef89 GIT binary patch literal 2569837 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%0A9Y2N4_^p<}JAyzl4`ro{LpGna9x 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