mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-17 12:58:34 -04:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 945e73c9b7 | |||
| c400746dd5 | |||
| e3ce37899d | |||
| c5e58b38a8 | |||
| 1f86a6d3f0 | |||
| be8f975a99 | |||
| c7abb340f1 | |||
| 45771a7e39 | |||
| 39810da936 | |||
| 01c8bf20f9 | |||
| 9241a79dc9 | |||
| e73fa8f4b7 |
@@ -1028,7 +1028,7 @@
|
||||
"packages/www": {
|
||||
"name": "@opencode-ai/www",
|
||||
"dependencies": {
|
||||
"blume": "1.1.4",
|
||||
"blume": "1.5.1",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/cloudflare": "14.1.4",
|
||||
@@ -1289,6 +1289,12 @@
|
||||
|
||||
"@astrojs/yaml2ts": ["@astrojs/yaml2ts@0.2.4", "", { "dependencies": { "yaml": "^2.8.3" } }, "sha512-8oddpOae35pJsXPQXhTkM0ypfKPskVsh2bCxRtbf7e+/Epw2nReakFYpLKjZMEr75CsoF203PMnCocpfz0s69A=="],
|
||||
|
||||
"@asyncapi/converter": ["@asyncapi/converter@2.0.2", "", { "dependencies": { "@asyncapi/parser": "^3.6.2", "js-yaml": "^3.14.1", "path": "^0.12.7" } }, "sha512-tFvT2ijEriTe9CPCMP32fh2VPzdQiUupK63MyW7UBDCtENANPZJ0aboZuVPhgBhmqo2TxcHWbZANpmXc5sEFiw=="],
|
||||
|
||||
"@asyncapi/parser": ["@asyncapi/parser@3.6.3", "", { "dependencies": { "@asyncapi/specs": "^6.11.1", "@openapi-contrib/openapi-schema-to-json-schema": "~3.2.0", "@stoplight/json": "3.21.0", "@stoplight/json-ref-readers": "^1.2.2", "@stoplight/json-ref-resolver": "^3.1.5", "@stoplight/spectral-core": "^1.18.3", "@stoplight/spectral-functions": "^1.7.2", "@stoplight/spectral-parsers": "^1.0.2", "@stoplight/spectral-ref-resolver": "^1.0.3", "@stoplight/types": "^13.12.0", "@types/json-schema": "^7.0.11", "@types/urijs": "^1.19.19", "ajv": "^8.18.0", "ajv-errors": "^3.0.0", "ajv-formats": "^2.1.1", "avsc": "^5.7.5", "js-yaml": "^4.3.1", "jsonpath-plus": "^10.0.7", "node-fetch": "2.6.7" } }, "sha512-MUC8xIUMcS2qNvqrqyx/ie0txu3d/OdIsrXs7UCzawdyR6P07gh35DpOqPz/z57s1UA3vERVpcheZYl3h8cVtw=="],
|
||||
|
||||
"@asyncapi/specs": ["@asyncapi/specs@6.11.1", "", { "dependencies": { "@types/json-schema": "^7.0.11" } }, "sha512-A3WBLqAKGoJ2+6FWFtpjBlCQ1oFCcs4GxF7zsIGvNqp/klGUHjlA3aAcZ9XMMpLGE8zPeYDz2x9FmO6DSuKraQ=="],
|
||||
|
||||
"@aws-crypto/crc32": ["@aws-crypto/crc32@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg=="],
|
||||
|
||||
"@aws-crypto/crc32c": ["@aws-crypto/crc32c@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag=="],
|
||||
@@ -1799,6 +1805,12 @@
|
||||
|
||||
"@js-temporal/polyfill": ["@js-temporal/polyfill@0.5.1", "", { "dependencies": { "jsbi": "^4.3.0" } }, "sha512-hloP58zRVCRSpgDxmqCWJNlizAlUgJFqG2ypq79DCvyv9tHjRYMDOcPFjzfl/A1/YxDvRCZz8wvZvmapQnKwFQ=="],
|
||||
|
||||
"@jsep-plugin/assignment": ["@jsep-plugin/assignment@1.3.0", "", { "peerDependencies": { "jsep": "^0.4.0||^1.0.0" } }, "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ=="],
|
||||
|
||||
"@jsep-plugin/regex": ["@jsep-plugin/regex@1.0.4", "", { "peerDependencies": { "jsep": "^0.4.0||^1.0.0" } }, "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg=="],
|
||||
|
||||
"@jsep-plugin/ternary": ["@jsep-plugin/ternary@1.1.4", "", { "peerDependencies": { "jsep": "^0.4.0||^1.0.0" } }, "sha512-ck5wiqIbqdMX6WRQztBL7ASDty9YLgJ3sSAK5ZpBzXeySvFGCzIvM6UiAI4hTZ22fEcYQVV/zhUbNscggW+Ukg=="],
|
||||
|
||||
"@jsx-email/all": ["@jsx-email/all@2.2.3", "", { "dependencies": { "@jsx-email/body": "1.0.2", "@jsx-email/button": "1.0.4", "@jsx-email/column": "1.0.3", "@jsx-email/container": "1.0.2", "@jsx-email/font": "1.0.3", "@jsx-email/head": "1.0.2", "@jsx-email/heading": "1.0.2", "@jsx-email/hr": "1.0.2", "@jsx-email/html": "1.0.2", "@jsx-email/img": "1.0.2", "@jsx-email/link": "1.0.2", "@jsx-email/markdown": "2.0.4", "@jsx-email/preview": "1.0.2", "@jsx-email/render": "1.1.1", "@jsx-email/row": "1.0.2", "@jsx-email/section": "1.0.2", "@jsx-email/tailwind": "2.4.4", "@jsx-email/text": "1.0.2" }, "peerDependencies": { "react": "^18.2.0" } }, "sha512-OBvLe/hVSQc0LlMSTJnkjFoqs3bmxcC4zpy/5pT5agPCSKMvAKQjzmsc2xJ2wO73jSpRV1K/g38GmvdCfrhSoQ=="],
|
||||
|
||||
"@jsx-email/body": ["@jsx-email/body@1.0.2", "", { "peerDependencies": { "react": "^18.2.0" } }, "sha512-NjR2tgLH4XGfGkm+O8kcVwi9MBqZsXZCLlmk3HlMux3/n/+a5zB+yhJqXWZBJl2i+6cSF+E2O6hK11ekyK9WWQ=="],
|
||||
@@ -1985,6 +1997,8 @@
|
||||
|
||||
"@one-ini/wasm": ["@one-ini/wasm@0.1.1", "", {}, "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw=="],
|
||||
|
||||
"@openapi-contrib/openapi-schema-to-json-schema": ["@openapi-contrib/openapi-schema-to-json-schema@3.2.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3" } }, "sha512-Gj6C0JwCr8arj0sYuslWXUBSP/KnUlEGnPW4qxlXvAl543oaNQgMgIgkQUA6vs5BCCvwTEiL8m/wdWzfl4UvSw=="],
|
||||
|
||||
"@openauthjs/openauth": ["@openauthjs/openauth@0.0.0-20250322224806", "", { "dependencies": { "@standard-schema/spec": "1.0.0-beta.3", "aws4fetch": "1.0.20", "jose": "5.9.6" }, "peerDependencies": { "arctic": "^2.2.2", "hono": "^4.0.0" } }, "sha512-p5IWSRXvABcwocH2dNI0w8c1QJelIOFulwhKk+aLLFfUbs8u1pr7kQbYe8yCSM2+bcLHiwbogpUQc2ovrGwCuw=="],
|
||||
|
||||
"@opencode-ai/ai": ["@opencode-ai/ai@workspace:packages/ai"],
|
||||
@@ -2585,6 +2599,8 @@
|
||||
|
||||
"@scalar/validation": ["@scalar/validation@0.6.2", "", {}, "sha512-Sc1TkcwGV6aVCO51AyKeaGiP8gpwAHxEtO5d3tZzPV+KsnlC/YokQxFxwBrbIXw73k9hmcExnJyGu3k5i6n6VA=="],
|
||||
|
||||
"@scarf/scarf": ["@scarf/scarf@1.4.0", "", {}, "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ=="],
|
||||
|
||||
"@selderee/plugin-htmlparser2": ["@selderee/plugin-htmlparser2@0.11.0", "", { "dependencies": { "domhandler": "^5.0.3", "selderee": "^0.11.0" } }, "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ=="],
|
||||
|
||||
"@sentry-internal/browser-utils": ["@sentry-internal/browser-utils@10.36.0", "", { "dependencies": { "@sentry/core": "10.36.0" } }, "sha512-WILVR8HQBWOxbqLRuTxjzRCMIACGsDTo6jXvzA8rz6ezElElLmIrn3CFAswrESLqEEUa4CQHl5bLgSVJCRNweA=="],
|
||||
@@ -2807,6 +2823,36 @@
|
||||
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
"@stoplight/better-ajv-errors": ["@stoplight/better-ajv-errors@1.0.3", "", { "dependencies": { "jsonpointer": "^5.0.0", "leven": "^3.1.0" }, "peerDependencies": { "ajv": ">=8" } }, "sha512-0p9uXkuB22qGdNfy3VeEhxkU5uwvp/KrBTAbrLBURv6ilxIVwanKwjMc41lQfIVgPGcOkmLbTolfFrSsueu7zA=="],
|
||||
|
||||
"@stoplight/json": ["@stoplight/json@3.21.0", "", { "dependencies": { "@stoplight/ordered-object-literal": "^1.0.3", "@stoplight/path": "^1.3.2", "@stoplight/types": "^13.6.0", "jsonc-parser": "~2.2.1", "lodash": "^4.17.21", "safe-stable-stringify": "^1.1" } }, "sha512-5O0apqJ/t4sIevXCO3SBN9AHCEKKR/Zb4gaj7wYe5863jme9g02Q0n/GhM7ZCALkL+vGPTe4ZzTETP8TFtsw3g=="],
|
||||
|
||||
"@stoplight/json-ref-readers": ["@stoplight/json-ref-readers@1.2.2", "", { "dependencies": { "node-fetch": "^2.6.0", "tslib": "^1.14.1" } }, "sha512-nty0tHUq2f1IKuFYsLM4CXLZGHdMn+X/IwEUIpeSOXt0QjMUbL0Em57iJUDzz+2MkWG83smIigNZ3fauGjqgdQ=="],
|
||||
|
||||
"@stoplight/json-ref-resolver": ["@stoplight/json-ref-resolver@3.1.6", "", { "dependencies": { "@stoplight/json": "^3.21.0", "@stoplight/path": "^1.3.2", "@stoplight/types": "^12.3.0 || ^13.0.0", "@types/urijs": "^1.19.19", "dependency-graph": "~0.11.0", "fast-memoize": "^2.5.2", "immer": "^9.0.6", "lodash": "^4.17.21", "tslib": "^2.6.0", "urijs": "^1.19.11" } }, "sha512-YNcWv3R3n3U6iQYBsFOiWSuRGE5su1tJSiX6pAPRVk7dP0L7lqCteXGzuVRQ0gMZqUl8v1P0+fAKxF6PLo9B5A=="],
|
||||
|
||||
"@stoplight/ordered-object-literal": ["@stoplight/ordered-object-literal@1.0.5", "", {}, "sha512-COTiuCU5bgMUtbIFBuyyh2/yVVzlr5Om0v5utQDgBCuQUOPgU1DwoffkTfg4UBQOvByi5foF4w4T+H9CoRe5wg=="],
|
||||
|
||||
"@stoplight/path": ["@stoplight/path@1.3.2", "", {}, "sha512-lyIc6JUlUA8Ve5ELywPC8I2Sdnh1zc1zmbYgVarhXIp9YeAB0ReeqmGEOWNtlHkbP2DAA1AL65Wfn2ncjK/jtQ=="],
|
||||
|
||||
"@stoplight/spectral-core": ["@stoplight/spectral-core@1.23.1", "", { "dependencies": { "@scarf/scarf": "^1.4.0", "@stoplight/better-ajv-errors": "1.0.3", "@stoplight/json": "~3.21.0", "@stoplight/path": "1.3.2", "@stoplight/spectral-parsers": "^1.0.0", "@stoplight/spectral-ref-resolver": "^1.0.4", "@stoplight/spectral-runtime": "^1.1.2", "@stoplight/types": "~13.6.0", "@types/es-aggregate-error": "^1.0.2", "@types/json-schema": "^7.0.11", "ajv": "^8.18.0", "ajv-errors": "~3.0.0", "ajv-formats": "~2.1.1", "es-aggregate-error": "^1.0.7", "expr-eval-fork": "^3.0.1", "jsonpath-plus": "^10.3.0", "lodash": "^4.18.1", "lodash.topath": "^4.5.2", "minimatch": "^3.1.4", "nimma": "0.2.3", "pony-cause": "^1.1.1", "tslib": "^2.8.1" } }, "sha512-VLC8OhpO/pMJKb6IHhurxJjXO1qB56Ng1unIb8b+hNxdw0+SEcASvmR+RpjfHYX/jv/DfSaA1x8QhFBJBmqBOQ=="],
|
||||
|
||||
"@stoplight/spectral-formats": ["@stoplight/spectral-formats@1.8.5", "", { "dependencies": { "@scarf/scarf": "^1.4.0", "@stoplight/json": "^3.17.0", "@stoplight/spectral-core": "^1.23.0", "@types/json-schema": "^7.0.7", "tslib": "^2.8.1" } }, "sha512-xaC0rCH0p7/bzNJsz+JgLSj+Cp6uwYGWpePQxdLkF2G6a8Zyp3OyS7umkGYNiimEwKrOjvCNNTFJpeuiENZSBA=="],
|
||||
|
||||
"@stoplight/spectral-functions": ["@stoplight/spectral-functions@1.10.5", "", { "dependencies": { "@scarf/scarf": "^1.4.0", "@stoplight/better-ajv-errors": "1.0.3", "@stoplight/json": "^3.17.1", "@stoplight/spectral-core": "^1.23.0", "@stoplight/spectral-formats": "^1.8.1", "@stoplight/spectral-runtime": "^1.1.2", "ajv": "^8.18.0", "ajv-draft-04": "~1.0.0", "ajv-errors": "~3.0.0", "ajv-formats": "~2.1.1", "lodash": "^4.18.1", "tslib": "^2.8.1" } }, "sha512-vDCd0NJ93715bcUpZZ5vNHiyxd4cgHF6tuXsDiXOXKAByg+I1fR5/dMijEo6Ce1Lz95a+RZ22JKYhF1YuzVvuA=="],
|
||||
|
||||
"@stoplight/spectral-parsers": ["@stoplight/spectral-parsers@1.0.5", "", { "dependencies": { "@stoplight/json": "~3.21.0", "@stoplight/types": "^14.1.1", "@stoplight/yaml": "~4.3.0", "tslib": "^2.8.1" } }, "sha512-ANDTp2IHWGvsQDAY85/jQi9ZrF4mRrA5bciNHX+PUxPr4DwS6iv4h+FVWJMVwcEYdpyoIdyL+SRmHdJfQEPmwQ=="],
|
||||
|
||||
"@stoplight/spectral-ref-resolver": ["@stoplight/spectral-ref-resolver@1.0.5", "", { "dependencies": { "@stoplight/json-ref-readers": "1.2.2", "@stoplight/json-ref-resolver": "~3.1.6", "@stoplight/spectral-runtime": "^1.1.2", "dependency-graph": "0.11.0", "tslib": "^2.8.1" } }, "sha512-gj3TieX5a9zMW29z3mBlAtDOCgN3GEc1VgZnCVlr5irmR4Qi5LuECuFItAq4pTn5Zu+sW5bqutsCH7D4PkpyAA=="],
|
||||
|
||||
"@stoplight/spectral-runtime": ["@stoplight/spectral-runtime@1.1.6", "", { "dependencies": { "@stoplight/json": "^3.20.1", "@stoplight/path": "^1.3.2", "@stoplight/types": "^13.6.0", "lodash": "^4.18.1", "node-fetch": "^2.7.0", "tslib": "^2.8.1" } }, "sha512-Y8rEDyMN4bSMJCrDs2shdcVHYyCnH3FvXRP4dBhha4Z8iJv+JPp7KqOV/hwVB/hWFC209upiwj2oDmLfR0qCDg=="],
|
||||
|
||||
"@stoplight/types": ["@stoplight/types@13.20.0", "", { "dependencies": { "@types/json-schema": "^7.0.4", "utility-types": "^3.10.0" } }, "sha512-2FNTv05If7ib79VPDA/r9eUet76jewXFH2y2K5vuge6SXbRHtWBhcaRmu+6QpF4/WRNoJj5XYRSwLGXDxysBGA=="],
|
||||
|
||||
"@stoplight/yaml": ["@stoplight/yaml@4.3.0", "", { "dependencies": { "@stoplight/ordered-object-literal": "^1.0.5", "@stoplight/types": "^14.1.1", "@stoplight/yaml-ast-parser": "0.0.50", "tslib": "^2.2.0" } }, "sha512-JZlVFE6/dYpP9tQmV0/ADfn32L9uFarHWxfcRhReKUnljz1ZiUM5zpX+PH8h5CJs6lao3TuFqnPm9IJJCEkE2w=="],
|
||||
|
||||
"@stoplight/yaml-ast-parser": ["@stoplight/yaml-ast-parser@0.0.50", "", {}, "sha512-Pb6M8TDO9DtSVla9yXSTAxmo9GVEouq5P40DWXdOie69bXogZTkgvopCq+yEvTMA0F6PEvdJmbtTV3ccIp11VQ=="],
|
||||
|
||||
"@storybook/addon-a11y": ["@storybook/addon-a11y@10.5.7", "", { "dependencies": { "@storybook/global": "^5.0.0", "axe-core": "^4.2.0" }, "peerDependencies": { "storybook": "^10.5.7" } }, "sha512-I30rsNz6aA3xg3811MEry40uJDHP3l5SOkfqtmNkp7y4NdqTDdKhmbhhDAZQX1WWEk6GeMBGr3AJ3TCz7r7JmQ=="],
|
||||
|
||||
"@storybook/addon-docs": ["@storybook/addon-docs@10.5.7", "", { "dependencies": { "@mdx-js/react": "^3.0.0", "@storybook/csf-plugin": "10.5.7", "@storybook/icons": "^2.0.2", "@storybook/react-dom-shim": "10.5.7", "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.5.7" }, "optionalPeers": ["@types/react"] }, "sha512-KNARJfjICaizinsR3INMEiipZm1ObYo+xw+E26gteu50Bcy2dIZUtk5uHY5XdtardU3AXX6yRXoBZ2HCY3lbHA=="],
|
||||
@@ -3023,6 +3069,8 @@
|
||||
|
||||
"@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
|
||||
|
||||
"@types/es-aggregate-error": ["@types/es-aggregate-error@1.0.6", "", { "dependencies": { "@types/node": "*" } }, "sha512-qJ7LIFp06h1QE1aVxbVd+zJP2wdaugYXYfd6JxsyRMrYHaxb6itXPogW2tz+ylUJ1n1b+JF1PHyYCfYHm0dvUg=="],
|
||||
|
||||
"@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=="],
|
||||
@@ -3127,6 +3175,8 @@
|
||||
|
||||
"@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
|
||||
|
||||
"@types/urijs": ["@types/urijs@1.19.26", "", {}, "sha512-wkXrVzX5yoqLnndOwFsieJA7oKM8cNkOKJtf/3vVGSUFkWDKZvFHpIl9Pvqb/T9UsawBBFMTTD8xu7sK5MWuvg=="],
|
||||
|
||||
"@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="],
|
||||
|
||||
"@types/which": ["@types/which@3.0.4", "", {}, "sha512-liyfuo/106JdlgSchJzXEQCVArk0CvevqPote8F8HgWgJ3dRCcTHgJIsLDuee0kxk/mhbInzIZk3QWSZJ8R+2w=="],
|
||||
@@ -3213,6 +3263,8 @@
|
||||
|
||||
"@webgpu/types": ["@webgpu/types@0.1.54", "", {}, "sha512-81oaalC8LFrXjhsczomEQ0u3jG+TqE6V9QHLA8GNZq/Rnot0KDugu3LhSYSlie8tSdooAN1Hov05asrUUp9qgg=="],
|
||||
|
||||
"@workflow/serde": ["@workflow/serde@4.1.0", "", {}, "sha512-pav4F2BoirECWR7Nf1TKt+2eETcBj7jj4cBefQ8VXQCA6NPkaKeLfj/zMgi+3zYV5ZIBT4GuUiphsj0/b9hPQQ=="],
|
||||
|
||||
"@xmldom/xmldom": ["@xmldom/xmldom@0.8.13", "", {}, "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw=="],
|
||||
|
||||
"@yuuang/ffi-rs-android-arm64": ["@yuuang/ffi-rs-android-arm64@1.3.7", "", { "os": "android", "cpu": "arm64" }, "sha512-t6Wx3Xll6c07Nuk0k3xnZsxKFxlshm92i0U/BiTHc6kQbvu+fMJF+gKsj4yEj886jH51CM3EqZT9Xdhq9CdUVw=="],
|
||||
@@ -3265,6 +3317,8 @@
|
||||
|
||||
"ajv-draft-04": ["ajv-draft-04@1.0.0", "", { "peerDependencies": { "ajv": "^8.5.0" }, "optionalPeers": ["ajv"] }, "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw=="],
|
||||
|
||||
"ajv-errors": ["ajv-errors@3.0.0", "", { "peerDependencies": { "ajv": "^8.0.1" } }, "sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ=="],
|
||||
|
||||
"ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
|
||||
|
||||
"ajv-i18n": ["ajv-i18n@4.2.0", "", { "peerDependencies": { "ajv": "^8.0.0-beta.0" } }, "sha512-v/ei2UkCEeuKNXh8RToiFsUclmU+G57LO1Oo22OagNMENIw+Yb8eMwvHu7Vn9fmkjJyv6XclhJ8TbuigSglPkg=="],
|
||||
@@ -3343,6 +3397,8 @@
|
||||
|
||||
"available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
|
||||
|
||||
"avsc": ["avsc@5.7.9", "", {}, "sha512-yOA4wFeI7ET3v32Di/sUybQ+ttP20JHSW3mxLuNGeO0uD6PPcvLrIQXSvy/rhJOWU5JrYh7U4OHplWMmtAtjMg=="],
|
||||
|
||||
"aws-ssl-profiles": ["aws-ssl-profiles@1.1.2", "", {}, "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g=="],
|
||||
|
||||
"aws4": ["aws4@1.13.2", "", {}, "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw=="],
|
||||
@@ -3409,7 +3465,7 @@
|
||||
|
||||
"bluebird": ["bluebird@3.7.2", "", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="],
|
||||
|
||||
"blume": ["blume@1.1.4", "", { "dependencies": { "@astrojs/check": "^0.9.0", "@astrojs/markdown-satteri": "^0.3.2", "@astrojs/mdx": "^7.0.0", "@astrojs/node": "^11.0.0", "@astrojs/react": "^6.0.0", "@astrojs/vercel": "^11.0.0", "@clack/prompts": "^1.7.0", "@iconify-json/lucide": "^1.2.115", "@iconify/types": "^2.0.0", "@iconify/utils": "^3.1.3", "@modelcontextprotocol/sdk": "^1.29.0", "@orama/orama": "^3.1.18", "@pierre/diffs": "^1.2.11", "@scalar/astro": "^0.4.5", "@scalar/openapi-parser": "^0.28.8", "@scalar/openapi-types": "^0.9.1", "@shikijs/transformers": "^4.2.0", "@shikijs/twoslash": "^4.2.0", "@tailwindcss/typography": "^0.5.20", "@tailwindcss/vite": "^4", "@vercel/analytics": "^2.0.1", "ai": "^5.0.0", "astro": "^7.0.2", "babel-plugin-react-compiler": "^1.0.0", "citty": "^0.1.6", "consola": "^3.4.0", "dompurify": "^3.4.11", "epub-gen-memory": "^1.1.2", "github-slugger": "^2.0.0", "gray-matter": "^4.0.3", "jiti": "^2.4.0", "js-yaml": "^4.1.0", "katex": "^0.17.0", "marked": "^18.0.5", "mermaid": "^11.15.0", "node-html-parser": "^9.0.0", "pagefind": "^1.3.0", "pathe": "^2.0.0", "react": "^19.0.0", "react-dom": "^19.0.0", "satteri": "^0.9.5", "shiki": "^4.2.0", "simple-icons": "^13.0.0", "tailwindcss": "^4", "takumi-js": "^2.2.1", "tinyglobby": "^0.2.10", "twoslash": "^0.3.9", "typescript": "^6.0.3", "undici": "^8.6.0", "zod": "^3.24.0" }, "peerDependencies": { "@ai-sdk/openai-compatible": "^1.0.41", "@astrojs/cloudflare": "^14.0.0", "@astrojs/netlify": "^8.0.0", "@astrojs/svelte": "^9.0.0", "@astrojs/vue": "^7.0.0", "@mixedbread/sdk": "^0.76.0", "@notionhq/client": "^2.2.15", "@openrouter/ai-sdk-provider": "^1.5.4", "@oramacloud/client": "^2.1.0", "@sanity/client": "^6.21.0", "algoliasearch": "^5.55.0", "flexsearch": "^0.8.0", "typesense": "^3.0.0" }, "optionalPeers": ["@ai-sdk/openai-compatible", "@astrojs/cloudflare", "@astrojs/netlify", "@astrojs/svelte", "@astrojs/vue", "@mixedbread/sdk", "@notionhq/client", "@openrouter/ai-sdk-provider", "@oramacloud/client", "@sanity/client", "algoliasearch", "flexsearch", "typesense"], "bin": { "blume": "bin/blume.mjs" } }, "sha512-boCWAMfuyc2788hjGJPrmxu4mNUojG+XkkPypjq+z8KErq1yV4XrHgET8bzVJtmOdpWVGLIjfzmbLniTePBU8Q=="],
|
||||
"blume": ["blume@1.5.1", "", { "dependencies": { "@astrojs/check": "^0.9.0", "@astrojs/markdown-satteri": "^0.3.2", "@astrojs/mdx": "^7.0.0", "@astrojs/node": "^11.0.0", "@astrojs/react": "^6.0.0", "@astrojs/vercel": "^11.0.3", "@asyncapi/converter": "^2.0.2", "@clack/prompts": "^1.7.0", "@iconify-json/lucide": "^1.2.115", "@iconify/types": "^2.0.0", "@iconify/utils": "^3.1.3", "@modelcontextprotocol/sdk": "^1.29.0", "@orama/orama": "^3.1.18", "@pierre/diffs": "^1.2.11", "@scalar/astro": "^0.4.5", "@scalar/openapi-parser": "^0.28.8", "@scalar/openapi-types": "^0.9.1", "@shikijs/transformers": "^4.2.0", "@shikijs/twoslash": "^4.2.0", "@tailwindcss/typography": "^0.5.20", "@tailwindcss/vite": "^4", "@types/mdast": "^4.0.4", "@vercel/analytics": "^2.0.1", "ai": "^7.0.42", "astro": "^7.1.0", "babel-plugin-react-compiler": "^1.0.0", "chokidar": "^5.0.0", "citty": "^0.1.6", "consola": "^3.4.0", "cross-spawn": "^7.0.6", "dompurify": "^3.4.13", "dotenv": "^17.4.2", "epub-gen-memory": "^1.1.2", "fast-xml-parser": "^5.10.1", "get-tsconfig": "^4.14.1", "github-slugger": "^2.0.0", "gray-matter": "^4.0.3", "html-escaper": "^3.0.3", "image-size": "^2.0.2", "jiti": "^2.4.0", "js-yaml": "^4.3.1", "katex": "^0.18.1", "markdown-table": "^3.0.4", "marked": "^18.0.5", "mdast-util-from-markdown": "^2.0.3", "mdast-util-gfm": "^3.1.0", "mdast-util-to-string": "^4.0.0", "medium-zoom": "^1.1.0", "mermaid": "^11.16.1", "micromark-extension-gfm": "^3.0.0", "nanotar": "^0.3.0", "node-html-parser": "^9.0.0", "openapi-sampler": "^1.7.4", "p-limit": "^7.3.1", "p-map": "^7.0.6", "p-retry": "^8.0.0", "package-manager-detector": "^1.8.0", "pagefind": "^1.3.0", "pathe": "^2.0.0", "perfect-debounce": "^2.1.0", "picomatch": "^4.0.5", "react": "^19.0.0", "react-dom": "^19.0.0", "robots-parser": "^3.0.1", "satteri": "^0.9.5", "semver": "^7.8.5", "sharp": "^0.35.3", "shiki": "^4.2.0", "simple-icons": "^13.0.0", "string-width": "^8.1.0", "tailwindcss": "^4.3.3", "takumi-js": "^2.2.1", "tinyglobby": "^0.2.10", "twoslash": "^0.3.9", "typescript": "^6.0.3", "ufo": "^1.6.4", "undici": "^8.9.0", "write-file-atomic": "^8.0.0", "zod": "^4.3.6" }, "peerDependencies": { "@ai-sdk/openai-compatible": "^3.0.0", "@astrojs/cloudflare": "^14.0.0", "@astrojs/netlify": "^8.0.0", "@astrojs/svelte": "^9.0.0", "@astrojs/vue": "^7.0.0", "@mixedbread/sdk": "^0.76.0", "@notionhq/client": "^2.2.15", "@openrouter/ai-sdk-provider": "^3.0.0", "@oramacloud/client": "^2.1.0", "@sanity/client": "^6.21.0 || ^7.0.0", "algoliasearch": "^5.55.0", "flexsearch": "^0.8.0", "typesense": "^3.0.0" }, "optionalPeers": ["@ai-sdk/openai-compatible", "@astrojs/cloudflare", "@astrojs/netlify", "@astrojs/svelte", "@astrojs/vue", "@mixedbread/sdk", "@notionhq/client", "@openrouter/ai-sdk-provider", "@oramacloud/client", "@sanity/client", "algoliasearch", "flexsearch", "typesense"], "bin": { "blume": "bin/blume.mjs" } }, "sha512-RnzoY+OHvchUJkXjF7s45SUW5rhuL81URWATEZoEl3psWeajsUu6JRyqDuy8bpYZjoth7P6gpS4IijZspv8Yrw=="],
|
||||
|
||||
"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=="],
|
||||
|
||||
@@ -3737,6 +3793,8 @@
|
||||
|
||||
"depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
|
||||
|
||||
"dependency-graph": ["dependency-graph@0.11.0", "", {}, "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg=="],
|
||||
|
||||
"deprecation": ["deprecation@2.3.1", "", {}, "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ=="],
|
||||
|
||||
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
||||
@@ -3791,7 +3849,7 @@
|
||||
|
||||
"dot-prop": ["dot-prop@8.0.2", "", { "dependencies": { "type-fest": "^3.8.0" } }, "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ=="],
|
||||
|
||||
"dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
|
||||
"dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="],
|
||||
|
||||
"dotenv-expand": ["dotenv-expand@11.0.7", "", { "dependencies": { "dotenv": "^16.4.5" } }, "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA=="],
|
||||
|
||||
@@ -3877,6 +3935,8 @@
|
||||
|
||||
"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-aggregate-error": ["es-aggregate-error@1.0.14", "", { "dependencies": { "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "globalthis": "^1.0.4", "has-property-descriptors": "^1.0.2", "set-function-name": "^2.0.2" } }, "sha512-3YxX6rVb07B5TV11AV5wsL7nQCHXNwoHPsQC8S4AmBiqYhyNCJ5BRKXkXyDJvs8QzXN20NgRtxe3dEEQD9NLHA=="],
|
||||
|
||||
"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=="],
|
||||
@@ -3951,6 +4011,8 @@
|
||||
|
||||
"exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="],
|
||||
|
||||
"expr-eval-fork": ["expr-eval-fork@3.0.3", "", {}, "sha512-BhC+hbc5lIVjygr840n5DEkW3MQq7H9o+mc1/N7Z5uIiCFVyESLL5DIE7LNq4CYUNxy+XjA+3jRrL/h0Kt2xcg=="],
|
||||
|
||||
"express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
|
||||
|
||||
"express-rate-limit": ["express-rate-limit@8.6.2", "", { "dependencies": { "debug": "^4.4.3", "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A=="],
|
||||
@@ -3977,6 +4039,8 @@
|
||||
|
||||
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
|
||||
|
||||
"fast-memoize": ["fast-memoize@2.5.2", "", {}, "sha512-Ue0LwpDYErFbmNnZSF0UH6eImUwDmogUO1jyE+JbN2gsQz/jICm1Ve7t9QT0rNSsfJt+Hs4/S3GnsDVjL4HVrw=="],
|
||||
|
||||
"fast-string-truncated-width": ["fast-string-truncated-width@3.0.3", "", {}, "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g=="],
|
||||
|
||||
"fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="],
|
||||
@@ -3987,7 +4051,7 @@
|
||||
|
||||
"fast-xml-builder": ["fast-xml-builder@1.3.0", "", { "dependencies": { "path-expression-matcher": "^1.6.2", "xml-naming": "^0.3.0" } }, "sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ=="],
|
||||
|
||||
"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=="],
|
||||
"fast-xml-parser": ["fast-xml-parser@5.10.1", "", { "dependencies": { "@nodable/entities": "^3.0.0", "fast-xml-builder": "^1.2.0", "is-unsafe": "^2.0.0", "path-expression-matcher": "^1.6.2", "strnum": "^2.4.1", "xml-naming": "^0.3.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw=="],
|
||||
|
||||
"fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
|
||||
|
||||
@@ -4027,6 +4091,8 @@
|
||||
|
||||
"for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
|
||||
|
||||
"foreach": ["foreach@2.0.6", "", {}, "sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg=="],
|
||||
|
||||
"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.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=="],
|
||||
@@ -4243,6 +4309,8 @@
|
||||
|
||||
"ignore-walk": ["ignore-walk@8.0.0", "", { "dependencies": { "minimatch": "^10.0.3" } }, "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A=="],
|
||||
|
||||
"image-size": ["image-size@2.0.2", "", { "bin": { "image-size": "bin/image-size.js" } }, "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w=="],
|
||||
|
||||
"immediate": ["immediate@3.0.6", "", {}, "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="],
|
||||
|
||||
"immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="],
|
||||
@@ -4329,6 +4397,8 @@
|
||||
|
||||
"is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
|
||||
|
||||
"is-network-error": ["is-network-error@1.3.2", "", {}, "sha512-PhBY86zaxNZUuWP6h13Vu5oFe0XY6/UlKzQnYFELzGVHygP3MxmvTfYSG7GN3aIab/iWudSMgjSnG9Dq+nHrgA=="],
|
||||
|
||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||
|
||||
"is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
|
||||
@@ -4401,6 +4471,8 @@
|
||||
|
||||
"jsbi": ["jsbi@4.3.2", "", {}, "sha512-9fqMSQbhJykSeii05nxKl4m6Eqn2P6rOlYiS+C5Dr/HPIU/7yZxu5qzbs40tgaFORiw2Amd0mirjxatXYMkIew=="],
|
||||
|
||||
"jsep": ["jsep@1.4.0", "", {}, "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw=="],
|
||||
|
||||
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
||||
|
||||
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
|
||||
@@ -4409,6 +4481,8 @@
|
||||
|
||||
"json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="],
|
||||
|
||||
"json-pointer": ["json-pointer@0.6.2", "", { "dependencies": { "foreach": "^2.0.4" } }, "sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw=="],
|
||||
|
||||
"json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
|
||||
|
||||
"json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="],
|
||||
@@ -4431,6 +4505,8 @@
|
||||
|
||||
"jsonparse": ["jsonparse@1.3.1", "", {}, "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg=="],
|
||||
|
||||
"jsonpath-plus": ["jsonpath-plus@10.4.0", "", { "dependencies": { "@jsep-plugin/assignment": "^1.3.0", "@jsep-plugin/regex": "^1.0.4", "jsep": "^1.4.0" }, "bin": { "jsonpath": "bin/jsonpath-cli.js", "jsonpath-plus": "bin/jsonpath-cli.js" } }, "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA=="],
|
||||
|
||||
"jsonpointer": ["jsonpointer@5.0.1", "", {}, "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ=="],
|
||||
|
||||
"jsonwebtoken": ["jsonwebtoken@9.0.3", "", { "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", "lodash.isboolean": "^3.0.3", "lodash.isinteger": "^4.0.4", "lodash.isnumber": "^3.0.3", "lodash.isplainobject": "^4.0.6", "lodash.isstring": "^4.0.1", "lodash.once": "^4.0.0", "ms": "^2.1.1", "semver": "^7.5.4" } }, "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g=="],
|
||||
@@ -4529,6 +4605,8 @@
|
||||
|
||||
"lodash.once": ["lodash.once@4.1.1", "", {}, "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg=="],
|
||||
|
||||
"lodash.topath": ["lodash.topath@4.5.2", "", {}, "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg=="],
|
||||
|
||||
"loglevelnext": ["loglevelnext@6.0.0", "", {}, "sha512-FDl1AI2sJGjHHG3XKJd6sG3/6ncgiGCQ0YkW46nxe7SfqQq6hujd9CvFXIXtkGBUN83KPZ2KSOJK8q5P0bSSRQ=="],
|
||||
|
||||
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
||||
@@ -4613,6 +4691,8 @@
|
||||
|
||||
"media-typer": ["media-typer@1.1.1", "", {}, "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ=="],
|
||||
|
||||
"medium-zoom": ["medium-zoom@1.1.0", "", {}, "sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ=="],
|
||||
|
||||
"merge-anything": ["merge-anything@5.1.7", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ=="],
|
||||
|
||||
"merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
|
||||
@@ -4767,12 +4847,16 @@
|
||||
|
||||
"nanoid": ["nanoid@3.3.18", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w=="],
|
||||
|
||||
"nanotar": ["nanotar@0.3.0", "", {}, "sha512-Kv2JYYiCzt16Kt5QwAc9BFG89xfPNBx+oQL4GQXD9nLqPkZBiNaqaCWtwnbk/q7UVsTYevvM1b0UF8zmEI4pCg=="],
|
||||
|
||||
"negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
|
||||
|
||||
"neotraverse": ["neotraverse@0.6.18", "", {}, "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA=="],
|
||||
|
||||
"nf3": ["nf3@0.1.12", "", {}, "sha512-qbMXT7RTGh74MYWPeqTIED8nDW70NXOULVHpdWcdZ7IVHVnAsMV9fNugSNnvooipDc1FMOzpis7T9nXJEbJhvQ=="],
|
||||
|
||||
"nimma": ["nimma@0.2.3", "", { "dependencies": { "@jsep-plugin/regex": "^1.0.1", "@jsep-plugin/ternary": "^1.0.2", "astring": "^1.8.1", "jsep": "^1.2.0" }, "optionalDependencies": { "jsonpath-plus": "^6.0.1 || ^10.1.0", "lodash.topath": "^4.5.2" } }, "sha512-1ZOI8J+1PKKGceo/5CT5GfQOG6H8I2BencSK06YarZ2wXwH37BSSUWldqJmMJYA5JfqDqffxDXynt6f11AyKcA=="],
|
||||
|
||||
"nitro": ["nitro@3.0.1-alpha.1", "", { "dependencies": { "consola": "^3.4.2", "crossws": "^0.4.1", "db0": "^0.3.4", "h3": "2.0.1-rc.5", "jiti": "^2.6.1", "nf3": "^0.1.10", "ofetch": "^2.0.0-alpha.3", "ohash": "^2.0.11", "oxc-minify": "^0.96.0", "oxc-transform": "^0.96.0", "srvx": "^0.9.5", "undici": "^7.16.0", "unenv": "^2.0.0-rc.24", "unstorage": "^2.0.0-alpha.4" }, "peerDependencies": { "rolldown": "*", "rollup": "^4", "vite": "^7", "xml2js": "^0.6.2" }, "optionalPeers": ["rolldown", "rollup", "vite", "xml2js"], "bin": { "nitro": "dist/cli/index.mjs" } }, "sha512-U4AxIsXxdkxzkFrK0XAw0e5Qbojk8jQ50MjjRBtBakC4HurTtQoiZvF+lSe382jhuQZCfAyywGWOFa9QzXLFaw=="],
|
||||
|
||||
"nlcst-to-string": ["nlcst-to-string@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="],
|
||||
@@ -4861,6 +4945,8 @@
|
||||
|
||||
"openai": ["openai@6.49.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-aYCc0C6L864eR6WSYIwQGyXriw/nIyZx0ObvhzOEVuk0zoBDpynjSbrionWI7q65B5H8jJX0DXR9snEzM6bfPg=="],
|
||||
|
||||
"openapi-sampler": ["openapi-sampler@1.7.4", "", { "dependencies": { "@types/json-schema": "^7.0.7", "fast-xml-parser": "^5.5.1", "json-pointer": "0.6.2" } }, "sha512-CKS/rd5ucPCuEDbJnjGDXZTsuGWcmv53aCmQx7soZlPEONUGN4af0/dY5+THRFZraSEjeA78nlfzdFswC/N5SA=="],
|
||||
|
||||
"openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="],
|
||||
|
||||
"openid-client": ["openid-client@5.6.4", "", { "dependencies": { "jose": "^4.15.4", "lru-cache": "^6.0.0", "object-hash": "^2.2.0", "oidc-token-hash": "^5.0.3" } }, "sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA=="],
|
||||
@@ -4899,7 +4985,7 @@
|
||||
|
||||
"p-queue": ["p-queue@8.1.1", "", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^6.1.2" } }, "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ=="],
|
||||
|
||||
"p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="],
|
||||
"p-retry": ["p-retry@8.0.0", "", { "dependencies": { "is-network-error": "^1.3.0" } }, "sha512-kFVqH1HxOHp8LupNsOys7bSV09VYTRLxarH/mokO4Rqhk6wGi70E0jh4VzvVGXfEVNggHoHLAMWsQqHyU1Ey9A=="],
|
||||
|
||||
"p-timeout": ["p-timeout@6.1.4", "", {}, "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg=="],
|
||||
|
||||
@@ -4933,6 +5019,8 @@
|
||||
|
||||
"pascal-case": ["pascal-case@3.1.2", "", { "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g=="],
|
||||
|
||||
"path": ["path@0.12.7", "", { "dependencies": { "process": "^0.11.1", "util": "^0.10.3" } }, "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q=="],
|
||||
|
||||
"path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="],
|
||||
|
||||
"path-data-parser": ["path-data-parser@0.1.0", "", {}, "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="],
|
||||
@@ -4965,6 +5053,8 @@
|
||||
|
||||
"pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="],
|
||||
|
||||
"perfect-debounce": ["perfect-debounce@2.1.0", "", {}, "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g=="],
|
||||
|
||||
"piccolore": ["piccolore@0.1.3", "", {}, "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw=="],
|
||||
|
||||
"picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
|
||||
@@ -4993,6 +5083,8 @@
|
||||
|
||||
"points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="],
|
||||
|
||||
"pony-cause": ["pony-cause@1.1.1", "", {}, "sha512-PxkIc/2ZpLiEzQXu5YRDOUgBlfGYBY8156HY5ZcRAwwonMk5W/MrJP2LLkG/hF7GEQzaHo2aS7ho6ZLCOvf+6g=="],
|
||||
|
||||
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
|
||||
|
||||
"postcss": ["postcss@8.5.26", "", { "dependencies": { "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ=="],
|
||||
@@ -5221,6 +5313,8 @@
|
||||
|
||||
"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=="],
|
||||
|
||||
"robots-parser": ["robots-parser@3.0.1", "", {}, "sha512-s+pyvQeIKIZ0dx5iJiQk1tPLJAWln39+MI5jtM8wnyws+G5azk+dMnMX0qfbqNetKKNgcWWOdi0sfm+FbQbgdQ=="],
|
||||
|
||||
"robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="],
|
||||
|
||||
"rolldown": ["rolldown@1.2.3", "", { "dependencies": { "@oxc-project/types": "=0.143.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.2.3", "@rolldown/binding-darwin-arm64": "1.2.3", "@rolldown/binding-darwin-x64": "1.2.3", "@rolldown/binding-freebsd-x64": "1.2.3", "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", "@rolldown/binding-linux-arm64-gnu": "1.2.3", "@rolldown/binding-linux-arm64-musl": "1.2.3", "@rolldown/binding-linux-ppc64-gnu": "1.2.3", "@rolldown/binding-linux-s390x-gnu": "1.2.3", "@rolldown/binding-linux-x64-gnu": "1.2.3", "@rolldown/binding-linux-x64-musl": "1.2.3", "@rolldown/binding-openharmony-arm64": "1.2.3", "@rolldown/binding-win32-arm64-msvc": "1.2.3", "@rolldown/binding-win32-x64-msvc": "1.2.3" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A=="],
|
||||
@@ -5249,6 +5343,8 @@
|
||||
|
||||
"safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
|
||||
|
||||
"safe-stable-stringify": ["safe-stable-stringify@1.1.1", "", {}, "sha512-ERq4hUjKDbJfE4+XtZLFPCDi8Vb1JqaxAPTxWFLBx8XcAlf9Bda/ZJdVezs/NAfsMQScyIlUMx+Yeu7P7rx5jw=="],
|
||||
|
||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||
|
||||
"sanitize-filename": ["sanitize-filename@1.6.4", "", { "dependencies": { "truncate-utf8-bytes": "^1.0.0" } }, "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg=="],
|
||||
@@ -5459,7 +5555,7 @@
|
||||
|
||||
"stripe": ["stripe@18.0.0", "", { "dependencies": { "@types/node": ">=8.1.0", "qs": "^6.11.0" } }, "sha512-3Fs33IzKUby//9kCkCa1uRpinAoTvj6rJgQ2jrBEysoxEvfsclvXdna1amyEYbA2EKkjynuB4+L/kleCCaWTpA=="],
|
||||
|
||||
"strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="],
|
||||
"strnum": ["strnum@2.4.1", "", { "dependencies": { "anynum": "^1.0.1" } }, "sha512-M9eUSMT2dCB2cTNPG7UYj6KuK7RJR2SN2+yCV/fTW3xzTCS6EaGZ5pSMgDIjB7r8zSfTGk+dvvn9rTjpVS9Mwg=="],
|
||||
|
||||
"stubborn-fs": ["stubborn-fs@2.0.0", "", { "dependencies": { "stubborn-utils": "^1.0.1" } }, "sha512-Y0AvSwDw8y+nlSNFXMm2g6L51rBGdAQT20J3YSOqxC53Lo3bjWRtr2BKcfYoAf352WYpsZSTURrA0tqhfgudPA=="],
|
||||
|
||||
@@ -5681,6 +5777,8 @@
|
||||
|
||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||
|
||||
"urijs": ["urijs@1.19.11", "", {}, "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ=="],
|
||||
|
||||
"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=="],
|
||||
@@ -5689,8 +5787,12 @@
|
||||
|
||||
"utf8-byte-length": ["utf8-byte-length@1.0.5", "", {}, "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA=="],
|
||||
|
||||
"util": ["util@0.10.4", "", { "dependencies": { "inherits": "2.0.3" } }, "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A=="],
|
||||
|
||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"utility-types": ["utility-types@3.11.0", "", {}, "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw=="],
|
||||
|
||||
"utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="],
|
||||
|
||||
"uuid": ["uuid@14.0.1", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew=="],
|
||||
@@ -5807,7 +5909,7 @@
|
||||
|
||||
"wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
|
||||
|
||||
"write-file-atomic": ["write-file-atomic@7.0.1", "", { "dependencies": { "signal-exit": "^4.0.1" } }, "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg=="],
|
||||
"write-file-atomic": ["write-file-atomic@8.0.0", "", { "dependencies": { "signal-exit": "^4.0.1" } }, "sha512-dYwyZredl67GyLLIHJnRM3h2PcOmN5SkcgC7eM5DPDEOEl6dLFqVrMg3F1Ea32usj4VSVZtd2H4MtKTNOf6nPg=="],
|
||||
|
||||
"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=="],
|
||||
|
||||
@@ -5999,6 +6101,12 @@
|
||||
|
||||
"@astrojs/vercel/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=="],
|
||||
|
||||
"@asyncapi/parser/ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
|
||||
|
||||
"@asyncapi/parser/js-yaml": ["js-yaml@4.3.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ=="],
|
||||
|
||||
"@asyncapi/parser/node-fetch": ["node-fetch@2.6.7", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ=="],
|
||||
|
||||
"@aws-crypto/crc32/@aws-sdk/types": ["@aws-sdk/types@3.974.2", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA=="],
|
||||
|
||||
"@aws-crypto/crc32c/@aws-sdk/types": ["@aws-sdk/types@3.974.2", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-3W6IUtSxFbH6X7Wb7DzGCV5QiFQsd0g8bOfntpmDxQlzBoKWUMBu/JPQR0DwkE+Hpnxd6db1tXbOwdeHddG6cA=="],
|
||||
@@ -6117,8 +6225,6 @@
|
||||
|
||||
"@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.10.1", "", { "dependencies": { "@nodable/entities": "^3.0.0", "fast-xml-builder": "^1.2.0", "is-unsafe": "^2.0.0", "path-expression-matcher": "^1.6.2", "strnum": "^2.4.1", "xml-naming": "^0.3.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw=="],
|
||||
|
||||
"@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
|
||||
"@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
|
||||
@@ -6325,6 +6431,8 @@
|
||||
|
||||
"@scalar/types/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
||||
|
||||
"@sentry/bundler-plugin-core/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
|
||||
|
||||
"@sentry/bundler-plugin-core/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=="],
|
||||
|
||||
"@sentry/bundler-plugin-core/magic-string": ["magic-string@0.30.8", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" } }, "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ=="],
|
||||
@@ -6365,6 +6473,8 @@
|
||||
|
||||
"@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=="],
|
||||
|
||||
"@slack/web-api/p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="],
|
||||
|
||||
"@solidjs/start/es-module-lexer": ["es-module-lexer@1.7.0", "", {}, "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA=="],
|
||||
|
||||
"@solidjs/start/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
|
||||
@@ -6373,6 +6483,26 @@
|
||||
|
||||
"@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=="],
|
||||
|
||||
"@stoplight/better-ajv-errors/leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
|
||||
|
||||
"@stoplight/json/jsonc-parser": ["jsonc-parser@2.2.1", "", {}, "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w=="],
|
||||
|
||||
"@stoplight/json-ref-readers/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="],
|
||||
|
||||
"@stoplight/json-ref-resolver/immer": ["immer@9.0.21", "", {}, "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA=="],
|
||||
|
||||
"@stoplight/spectral-core/@stoplight/types": ["@stoplight/types@13.6.0", "", { "dependencies": { "@types/json-schema": "^7.0.4", "utility-types": "^3.10.0" } }, "sha512-dzyuzvUjv3m1wmhPfq82lCVYGcXG0xUYgqnWfCq3PCVR4BKFhjdkHrnJ+jIDoMKvXb05AZP/ObQF6+NpDo29IQ=="],
|
||||
|
||||
"@stoplight/spectral-core/ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
|
||||
|
||||
"@stoplight/spectral-core/minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
|
||||
|
||||
"@stoplight/spectral-functions/ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="],
|
||||
|
||||
"@stoplight/spectral-parsers/@stoplight/types": ["@stoplight/types@14.1.1", "", { "dependencies": { "@types/json-schema": "^7.0.4", "utility-types": "^3.10.0" } }, "sha512-/kjtr+0t0tjKr+heVfviO9FrU/uGLc+QNX3fHJc19xsCNYqU7lVhaXxDmEID9BZTjG+/r9pK9xP/xU02XGg65g=="],
|
||||
|
||||
"@stoplight/yaml/@stoplight/types": ["@stoplight/types@14.1.1", "", { "dependencies": { "@types/json-schema": "^7.0.4", "utility-types": "^3.10.0" } }, "sha512-/kjtr+0t0tjKr+heVfviO9FrU/uGLc+QNX3fHJc19xsCNYqU7lVhaXxDmEID9BZTjG+/r9pK9xP/xU02XGg65g=="],
|
||||
|
||||
"@storybook/addon-docs/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="],
|
||||
|
||||
"@storybook/addon-docs/react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="],
|
||||
@@ -6435,6 +6565,8 @@
|
||||
|
||||
"app-builder-lib/ci-info": ["ci-info@4.3.1", "", {}, "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA=="],
|
||||
|
||||
"app-builder-lib/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
|
||||
|
||||
"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.3.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ=="],
|
||||
@@ -6473,6 +6605,8 @@
|
||||
|
||||
"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=="],
|
||||
|
||||
"bin-links/write-file-atomic": ["write-file-atomic@7.0.1", "", { "dependencies": { "signal-exit": "^4.0.1" } }, "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg=="],
|
||||
|
||||
"blume/@astrojs/mdx": ["@astrojs/mdx@7.0.5", "", { "dependencies": { "@astrojs/internal-helpers": "0.10.2", "@astrojs/markdown-remark": "7.2.2", "@mdx-js/mdx": "^3.1.1", "acorn": "^8.16.0", "es-module-lexer": "^2.0.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", "piccolore": "^0.1.3", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", "source-map": "^0.7.6", "unist-util-visit": "^5.1.0", "vfile": "^6.0.3" }, "peerDependencies": { "@astrojs/markdown-satteri": "^0.3.1", "astro": "^7.0.0" }, "optionalPeers": ["@astrojs/markdown-satteri"] }, "sha512-wEM/HH1RiEntyPVagdiF+yArzfcYLKBB0C1RZspVidKZ97rRMbaqP1Nbl/GR0sJs8zwaceqxRymw8aOKKJRdYw=="],
|
||||
|
||||
"blume/@clack/prompts": ["@clack/prompts@1.7.0", "", { "dependencies": { "@clack/core": "1.4.3", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A=="],
|
||||
@@ -6481,23 +6615,35 @@
|
||||
|
||||
"blume/@shikijs/transformers": ["@shikijs/transformers@4.4.2", "", { "dependencies": { "@shikijs/core": "4.4.2", "@shikijs/types": "4.4.2" } }, "sha512-d81PJ9KkR1tVP95FH/9296HTtDo0mh76wv10u9T1YmsZq/UcXgt0OLdBszfUQ1i+umkRMCjDnFbFZU7/tCODTQ=="],
|
||||
|
||||
"blume/ai": ["ai@7.0.64", "", { "dependencies": { "@ai-sdk/gateway": "4.0.51", "@ai-sdk/provider": "4.0.7", "@ai-sdk/provider-utils": "5.0.27" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-29Ufm56e53pRzIPueWzZiwJsgxmZStaBFpwEkVM89sqyIIax/pzDm+ez/ksJ/CcY9UCuYzvCQpE2zkFHICvS3w=="],
|
||||
|
||||
"blume/astro": ["astro@7.1.3", "", { "dependencies": { "@astrojs/compiler-rs": "^0.3.1", "@astrojs/internal-helpers": "0.10.1", "@astrojs/markdown-satteri": "0.3.4", "@astrojs/telemetry": "3.3.3", "@capsizecss/unpack": "^4.0.0", "@clack/prompts": "^1.1.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.3.0", "am-i-vibing": "^0.4.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "ci-info": "^4.4.0", "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^2.0.1", "devalue": "^5.8.1", "diff": "^8.0.3", "dset": "^3.1.4", "es-module-lexer": "^2.0.0", "esbuild": "^0.28.0", "flattie": "^1.1.1", "fontace": "~0.4.1", "get-tsconfig": "5.0.0-beta.4", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", "js-yaml": "^4.1.1", "jsonc-parser": "^3.3.1", "magic-string": "^0.30.21", "magicast": "^0.5.2", "mrmime": "^2.0.1", "neotraverse": "^1.0.1", "obug": "^2.1.1", "p-limit": "^7.3.0", "p-queue": "^9.1.0", "package-manager-detector": "^1.6.0", "piccolore": "^0.1.3", "picomatch": "^4.0.4", "semver": "^7.7.4", "shiki": "^4.0.2", "smol-toml": "^1.6.0", "svgo": "^4.0.1", "tinyclip": "^0.1.12", "tinyexec": "^1.0.4", "tinyglobby": "^0.2.15", "ultrahtml": "^1.6.0", "unifont": "~0.7.4", "unstorage": "^1.17.5", "vite": "^8.0.13", "vitefu": "^1.1.2", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", "zod": "^4.3.6" }, "optionalDependencies": { "sharp": "^0.34.0 || ^0.35.0" }, "peerDependencies": { "@astrojs/markdown-remark": "7.2.1" }, "optionalPeers": ["@astrojs/markdown-remark"], "bin": { "astro": "./bin/astro.mjs" } }, "sha512-4dhPyAAXthf3xLEYnG8SeL7yr/nTPPABfY7e9YF0yuO+vK9Xp+8Q5j4xzsmL3GueukQv4oNwGNTBepLOiDGeJA=="],
|
||||
|
||||
"blume/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="],
|
||||
|
||||
"blume/dompurify": ["dompurify@3.4.13", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ=="],
|
||||
|
||||
"blume/js-yaml": ["js-yaml@4.3.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ=="],
|
||||
|
||||
"blume/katex": ["katex@0.17.0", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-Vdw0ATsQ9V+LuegM/BTwQqV/6cTl5lbGcIrU+BCgLxyf6bo38ybOr372tuSIxir3CN720flu1meYR6XzNMwQnw=="],
|
||||
"blume/katex": ["katex@0.18.4", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-IMPntbRLOU+eu88XDiFKqQ8Akhr9Tv7jDMXqPhjG9SI1JMA4DIgXk4x9k4skJz2NZJXBRbC+2pYBLj9olqcZow=="],
|
||||
|
||||
"blume/node-html-parser": ["node-html-parser@9.0.1", "", { "dependencies": { "css-select": "^5.1.0", "entities": "^8.0.0" } }, "sha512-QrdiYYm1NnLRXsMXThUgVcF/syWfWIgHFmy8hylWMGFbHFtnRuXLBxxGQvIm3xaIJMUDJ0ayOmT/FGJYT3pZIw=="],
|
||||
|
||||
"blume/p-limit": ["p-limit@7.3.1", "", { "dependencies": { "yocto-queue": "^1.2.1" } }, "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q=="],
|
||||
|
||||
"blume/react": ["react@19.2.8", "", {}, "sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw=="],
|
||||
|
||||
"blume/react-dom": ["react-dom@19.2.8", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.8" } }, "sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ=="],
|
||||
|
||||
"blume/sharp": ["sharp@0.35.3", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.5" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.3", "@img/sharp-darwin-x64": "0.35.3", "@img/sharp-freebsd-wasm32": "0.35.3", "@img/sharp-libvips-darwin-arm64": "1.3.2", "@img/sharp-libvips-darwin-x64": "1.3.2", "@img/sharp-libvips-linux-arm": "1.3.2", "@img/sharp-libvips-linux-arm64": "1.3.2", "@img/sharp-libvips-linux-ppc64": "1.3.2", "@img/sharp-libvips-linux-riscv64": "1.3.2", "@img/sharp-libvips-linux-s390x": "1.3.2", "@img/sharp-libvips-linux-x64": "1.3.2", "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", "@img/sharp-libvips-linuxmusl-x64": "1.3.2", "@img/sharp-linux-arm": "0.35.3", "@img/sharp-linux-arm64": "0.35.3", "@img/sharp-linux-ppc64": "0.35.3", "@img/sharp-linux-riscv64": "0.35.3", "@img/sharp-linux-s390x": "0.35.3", "@img/sharp-linux-x64": "0.35.3", "@img/sharp-linuxmusl-arm64": "0.35.3", "@img/sharp-linuxmusl-x64": "0.35.3", "@img/sharp-webcontainers-wasm32": "0.35.3", "@img/sharp-win32-arm64": "0.35.3", "@img/sharp-win32-ia32": "0.35.3", "@img/sharp-win32-x64": "0.35.3" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q=="],
|
||||
|
||||
"blume/string-width": ["string-width@8.2.2", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-GaPUh5gfdrYzqeVNZvUfT23vYYxXzKYidUcnMtJg/3rxRV63EFZy3k6xfKlmfeJD0176lnUV/Usr3XcwSvFzpg=="],
|
||||
|
||||
"blume/tailwindcss": ["tailwindcss@4.3.3", "", {}, "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ=="],
|
||||
|
||||
"blume/typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
|
||||
|
||||
"blume/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
||||
"blume/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
||||
|
||||
"body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="],
|
||||
|
||||
@@ -6545,6 +6691,8 @@
|
||||
|
||||
"dot-prop/type-fest": ["type-fest@3.13.1", "", {}, "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g=="],
|
||||
|
||||
"dotenv-expand/dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="],
|
||||
|
||||
"duplexer2/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="],
|
||||
|
||||
"editorconfig/commander": ["commander@10.0.1", "", {}, "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug=="],
|
||||
@@ -6685,8 +6833,6 @@
|
||||
|
||||
"p-locate/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
|
||||
|
||||
"p-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="],
|
||||
|
||||
"parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
|
||||
|
||||
"parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
|
||||
@@ -6785,6 +6931,8 @@
|
||||
|
||||
"unzipper/fs-extra": ["fs-extra@11.3.1", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g=="],
|
||||
|
||||
"util/inherits": ["inherits@2.0.3", "", {}, "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/openai-compatible": ["@ai-sdk/openai-compatible@2.0.64", "", { "dependencies": { "@ai-sdk/provider": "3.0.14", "@ai-sdk/provider-utils": "4.0.42" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-oMh5/bhu2ibsXqzHeLbJ+9Y7UQdOSrfOLPI+UA1vEcqXGYVBQfWxLe5jBUpsaL8GBBj/nmSeYGX6QPan8RfHiQ=="],
|
||||
|
||||
"venice-ai-sdk-provider/@ai-sdk/provider": ["@ai-sdk/provider@3.0.14", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-5X1k57JBJ4H7H1QjX7CnJYAB1I19r/trVZTMcSms7/kLNZ8RaU4Nt2agcwZzv82Hfx6Q7/TOLU7agAKeFfc8cA=="],
|
||||
@@ -7019,6 +7167,8 @@
|
||||
|
||||
"@astrojs/vercel/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.28.1", "", { "os": "win32", "cpu": "x64" }, "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A=="],
|
||||
|
||||
"@asyncapi/parser/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"@aws-crypto/sha1-browser/@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-crypto/sha256-browser/@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=="],
|
||||
@@ -7033,6 +7183,8 @@
|
||||
|
||||
"@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/core/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=="],
|
||||
|
||||
"@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=="],
|
||||
|
||||
"@aws-sdk/client-sts/@aws-sdk/credential-provider-node/@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.775.0", "", { "dependencies": { "@aws-sdk/core": "3.775.0", "@aws-sdk/types": "3.775.0", "@smithy/fetch-http-handler": "^5.0.2", "@smithy/node-http-handler": "^4.0.4", "@smithy/property-provider": "^4.0.2", "@smithy/protocol-http": "^5.1.0", "@smithy/smithy-client": "^4.2.0", "@smithy/types": "^4.2.0", "@smithy/util-stream": "^4.2.0", "tslib": "^2.6.2" } }, "sha512-PjDQeDH/J1S0yWV32wCj2k5liRo0ssXMseCBEkCsD3SqsU8o5cU82b0hMX4sAib/RkglCSZqGO0xMiN0/7ndww=="],
|
||||
@@ -7091,10 +7243,6 @@
|
||||
|
||||
"@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=="],
|
||||
|
||||
"@bruits/satteri-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
|
||||
@@ -7413,6 +7561,8 @@
|
||||
|
||||
"@slack/web-api/p-queue/p-timeout": ["p-timeout@3.2.0", "", { "dependencies": { "p-finally": "^1.0.0" } }, "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg=="],
|
||||
|
||||
"@slack/web-api/p-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="],
|
||||
|
||||
"@solidjs/start/shiki/@shikijs/core": ["@shikijs/core@1.29.2", "", { "dependencies": { "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ=="],
|
||||
|
||||
"@solidjs/start/shiki/@shikijs/engine-javascript": ["@shikijs/engine-javascript@1.29.2", "", { "dependencies": { "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "oniguruma-to-es": "^2.2.0" } }, "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A=="],
|
||||
@@ -7425,6 +7575,8 @@
|
||||
|
||||
"@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=="],
|
||||
|
||||
"@stoplight/spectral-core/minimatch/brace-expansion": ["brace-expansion@1.1.18", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw=="],
|
||||
|
||||
"@storybook/addon-docs/react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||
|
||||
"@storybook/csf-plugin/unplugin/acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="],
|
||||
@@ -7515,6 +7667,12 @@
|
||||
|
||||
"blume/@shikijs/transformers/@shikijs/types": ["@shikijs/types@4.4.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" } }, "sha512-PFYitV4vpDr/iPCIhnHp+Q4ftic5N5VeNJ3KQ1O8gn3h2ar8qgwMAXF7tq4m1CWaMS60fV4VqF6vfnWH4F7vqQ=="],
|
||||
|
||||
"blume/ai/@ai-sdk/gateway": ["@ai-sdk/gateway@4.0.51", "", { "dependencies": { "@ai-sdk/provider": "4.0.7", "@ai-sdk/provider-utils": "5.0.27", "@vercel/oidc": "3.2.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-tQxWGUbg/O3A5EgekJo/C2byLVQ1r+vL6QdEVWmxUSnPhdCupcOeDbQO1tv9Um40VrdwYuSWlYzcbWvtlG5bOA=="],
|
||||
|
||||
"blume/ai/@ai-sdk/provider": ["@ai-sdk/provider@4.0.7", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6or44XprPzKbr8zkmzosowSE0pxkvJcoojBL+mCZvPUt3kvXp3XSNqeVun9golb1acEfSo6yaEBRT18h2VU+1Q=="],
|
||||
|
||||
"blume/ai/@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@5.0.27", "", { "dependencies": { "@ai-sdk/provider": "4.0.7", "@standard-schema/spec": "^1.1.0", "@workflow/serde": "4.1.0", "eventsource-parser": "^3.0.8", "undici": "^7.28.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-EzAn4pdgG5g0xXtH6lE2zyNmfjDQIDjATkfqzuidEI35g++hh4+07vnjzkT/RmGmIClPZiRj/Q2GMPV2V7mkHw=="],
|
||||
|
||||
"blume/astro/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.10.1", "", { "dependencies": { "@types/hast": "^3.0.4", "@types/mdast": "^4.0.4", "js-yaml": "^4.1.1", "picomatch": "^4.0.4", "retext-smartypants": "^6.2.0", "shiki": "^4.0.2", "smol-toml": "^1.6.0", "unified": "^11.0.5" } }, "sha512-5phcroT/vmOOrYuuAxtkbPixy5hePtlz9i8K4OeDv3dNK6/UQRuXPOSRTxIOBbUY5Sonw2UaxjbuVc43Mcir6Q=="],
|
||||
|
||||
"blume/astro/@astrojs/telemetry": ["@astrojs/telemetry@3.3.3", "", { "dependencies": { "ci-info": "^4.4.0", "dset": "^3.1.4", "is-docker": "^4.0.0", "package-manager-detector": "^1.6.0" } }, "sha512-C1TLn5sPJr0x4vk56piHWKbnqlEB8BKyte5Y45V02U+D7BGO5eMqZDH5aPjnkXQWJggvmsTXxH03QMZ9NgWLzQ=="],
|
||||
@@ -7535,12 +7693,8 @@
|
||||
|
||||
"blume/astro/neotraverse": ["neotraverse@1.0.1", "", {}, "sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w=="],
|
||||
|
||||
"blume/astro/p-limit": ["p-limit@7.3.1", "", { "dependencies": { "yocto-queue": "^1.2.1" } }, "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q=="],
|
||||
|
||||
"blume/astro/p-queue": ["p-queue@9.3.3", "", { "dependencies": { "eventemitter3": "^5.0.4", "p-timeout": "^7.0.0" } }, "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA=="],
|
||||
|
||||
"blume/astro/sharp": ["sharp@0.35.3", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.5" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.3", "@img/sharp-darwin-x64": "0.35.3", "@img/sharp-freebsd-wasm32": "0.35.3", "@img/sharp-libvips-darwin-arm64": "1.3.2", "@img/sharp-libvips-darwin-x64": "1.3.2", "@img/sharp-libvips-linux-arm": "1.3.2", "@img/sharp-libvips-linux-arm64": "1.3.2", "@img/sharp-libvips-linux-ppc64": "1.3.2", "@img/sharp-libvips-linux-riscv64": "1.3.2", "@img/sharp-libvips-linux-s390x": "1.3.2", "@img/sharp-libvips-linux-x64": "1.3.2", "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", "@img/sharp-libvips-linuxmusl-x64": "1.3.2", "@img/sharp-linux-arm": "0.35.3", "@img/sharp-linux-arm64": "0.35.3", "@img/sharp-linux-ppc64": "0.35.3", "@img/sharp-linux-riscv64": "0.35.3", "@img/sharp-linux-s390x": "0.35.3", "@img/sharp-linux-x64": "0.35.3", "@img/sharp-linuxmusl-arm64": "0.35.3", "@img/sharp-linuxmusl-x64": "0.35.3", "@img/sharp-webcontainers-wasm32": "0.35.3", "@img/sharp-win32-arm64": "0.35.3", "@img/sharp-win32-ia32": "0.35.3", "@img/sharp-win32-x64": "0.35.3" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q=="],
|
||||
|
||||
"blume/astro/unifont": ["unifont@0.7.4", "", { "dependencies": { "css-tree": "^3.1.0", "ofetch": "^1.5.1", "ohash": "^2.0.11" } }, "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg=="],
|
||||
|
||||
"blume/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=="],
|
||||
@@ -7549,7 +7703,7 @@
|
||||
|
||||
"blume/astro/yargs-parser": ["yargs-parser@22.0.0", "", {}, "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw=="],
|
||||
|
||||
"blume/astro/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
||||
"blume/chokidar/readdirp": ["readdirp@5.1.1", "", {}, "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA=="],
|
||||
|
||||
"blume/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
@@ -7559,6 +7713,42 @@
|
||||
|
||||
"blume/react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
|
||||
|
||||
"blume/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.2" }, "os": "darwin", "cpu": "arm64" }, "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg=="],
|
||||
|
||||
"blume/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.3.2" }, "os": "darwin", "cpu": "x64" }, "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w=="],
|
||||
|
||||
"blume/sharp/@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg=="],
|
||||
|
||||
"blume/sharp/@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw=="],
|
||||
|
||||
"blume/sharp/@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.3.2", "", { "os": "linux", "cpu": "arm" }, "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ=="],
|
||||
|
||||
"blume/sharp/@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA=="],
|
||||
|
||||
"blume/sharp/@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.3.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ=="],
|
||||
|
||||
"blume/sharp/@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w=="],
|
||||
|
||||
"blume/sharp/@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw=="],
|
||||
|
||||
"blume/sharp/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ=="],
|
||||
|
||||
"blume/sharp/@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.3.2" }, "os": "linux", "cpu": "arm" }, "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA=="],
|
||||
|
||||
"blume/sharp/@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ=="],
|
||||
|
||||
"blume/sharp/@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.3.2" }, "os": "linux", "cpu": "s390x" }, "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw=="],
|
||||
|
||||
"blume/sharp/@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA=="],
|
||||
|
||||
"blume/sharp/@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w=="],
|
||||
|
||||
"blume/sharp/@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg=="],
|
||||
|
||||
"blume/sharp/@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.35.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw=="],
|
||||
|
||||
"blume/sharp/@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.35.3", "", { "os": "win32", "cpu": "x64" }, "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA=="],
|
||||
|
||||
"builder-util/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
|
||||
|
||||
"cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
@@ -8115,6 +8305,8 @@
|
||||
|
||||
"@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-sts/@aws-sdk/core/fast-xml-parser/strnum": ["strnum@1.1.2", "", {}, "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA=="],
|
||||
|
||||
"@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=="],
|
||||
@@ -8479,6 +8671,8 @@
|
||||
|
||||
"@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=="],
|
||||
|
||||
"@stoplight/spectral-core/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"ansi-align/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"app-builder-lib/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="],
|
||||
@@ -8505,6 +8699,8 @@
|
||||
|
||||
"blume/@shikijs/transformers/@shikijs/core/@shikijs/primitive": ["@shikijs/primitive@4.4.2", "", { "dependencies": { "@shikijs/types": "4.4.2", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.5" } }, "sha512-l6fQQKsOMlz72n38fztmSgZ76MO6KSWuw8o+GJ+FhmqrpC9pIOJNQNXGgbb5yX2AwpzlEHwsaLPnk/8o4Fm+rA=="],
|
||||
|
||||
"blume/ai/@ai-sdk/provider-utils/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="],
|
||||
|
||||
"blume/astro/@astrojs/telemetry/is-docker": ["is-docker@4.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA=="],
|
||||
|
||||
"blume/astro/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ=="],
|
||||
@@ -8561,46 +8757,8 @@
|
||||
|
||||
"blume/astro/p-queue/p-timeout": ["p-timeout@7.0.1", "", {}, "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.2" }, "os": "darwin", "cpu": "arm64" }, "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.3.2" }, "os": "darwin", "cpu": "x64" }, "sha512-Xo+5uFBtLN0BKqieTxiFzFPQAUlBbbH5iBKyRX/z1JrbnYsHTfKJnUfL8+p2TPXr1pXqao4eeL4Rl144uDpK9w=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.3.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-9J6ypZFpQBj4YnePGoq/S38w6nz+vqg5WZLrLGY4YuSemdMq47GMLBPO42MzwdGwpg/agZ7xzZcFHa48xlywfg=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.3.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-m2pW1n6cns9VaubNwsZ+c3CRYjxNQWgJ5gPlnL1nbBcpkBvFm6SCFN5o0psFHI8w9n11NKhFkeEDns98tiqbEw=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.3.2", "", { "os": "linux", "cpu": "arm" }, "sha512-1eMLzy92I4J6rmi4mAT8yC3HxOtniyGELlzGbNMLLeqe052ahFQ0h6LFq+lh5DsDIdYViIDst08abvSbcEdLXQ=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-dqVSFynCox4C/J8kT16V7SIFAns0IjgLwkvYT7p8LQVmJ5OS5b6tI9IGflxTeuBS//zXeFIUbwt5dwxyZ17cnA=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.3.2", "", { "os": "linux", "cpu": "s390x" }, "sha512-/ABshyj8gCpyIrNXnHn4LorDJ0HHm1VhXPBlxZ8zAtfVPAaSafXPGn+sUSIRiwaSBy0mmFjSjiXI5mkcwdChKQ=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-ITPEtgffGJ0S6G9dRyw/366tJQqFRcHWPHhC+Stpg3Z8AEMrDrTr2lhdz4f/Y/HMbRh//7Z5mBzEpVdi62Oc3w=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.3.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-zE9EdiUzUmg5mDT5a1rk5fYJ6GWPloTwWBYDS14naqHsL+EaMpDj1AWnpLgh3u0YCORv2Tt50wrcrpYqkP97Kw=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.3.2", "", { "os": "linux", "cpu": "x64" }, "sha512-m0lrLiUt+lBYnCFr8qV/65yMR4E/c7/wf78I5eKTdkEakFAlZ9QlzEM3QIhhAwVeUhLAHLcCq7a7Vszq/oFNZQ=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.3.2" }, "os": "linux", "cpu": "arm" }, "sha512-affVWCTLooy8TSxbDx2qkzuDeaWLNVBA+P//FNBirHsXpP2fuBhk5AuboYUnrDnzoXes8GFjpTx0SBFOCRg+FA=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-QgKDspHPnrU+GQ55XPhGwyhC8acLVOOSyAvo1oVfFmrIXLkDNmGWzAfDZ4xK8oSA1qBQrALcHX0G5UZni/SuFQ=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.3.2" }, "os": "linux", "cpu": "s390x" }, "sha512-KgAxQ0DxpNOq1rG2t5cgTgShJFGSuU7XO45cqC+1NVOuZnP6tlgZRuSYOfNupGkHID0o3cJOsw4DVeJpMovcGw=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-8pqvxubL2PGdhlPy6GLqzDYMUjyRmKAwKHYKixpdJYBUK7PJ0C029XdsnpFIdgRZG68fZiGdHVWcKPvtiPB4cA=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.3.2" }, "os": "linux", "cpu": "arm64" }, "sha512-Vz0iQjzzcSX3HCbfwFfCSG/9SCIqyO0mH2sXyiHaAYfBk0cRsCWXRyQYX0ovCK/PAQBbTzQ0dsPQHh5MAFL59w=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.3.2" }, "os": "linux", "cpu": "x64" }, "sha512-6O1NPKcDVj9QEdg7Hx549EX8U0rp6yXQERqru6yRN7fGBn32UvIRJUlWnk+8xDCiG76hXVBbX82NZ/ZKr0euIg=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.35.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-r53mXsBN6lFUDiST764SvgwUdHAqM4rPAiDzAmf4fLoB6X/rkfyTrLCg6+g17wJJiCmB3JYgHuUldCWUIRFSXw=="],
|
||||
|
||||
"blume/astro/sharp/@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.35.3", "", { "os": "win32", "cpu": "x64" }, "sha512-D4y1vNeZrIIJCN+uHaWVtH86B+aCrdMYYjicy9pXHvbGZeGYLLSd3wdVuC37FxVXlU1ARsk84eKWfWMXGYEqvA=="],
|
||||
|
||||
"blume/astro/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=="],
|
||||
|
||||
"blume/astro/unstorage/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="],
|
||||
|
||||
"blume/astro/unstorage/h3": ["h3@1.15.11", "", { "dependencies": { "cookie-es": "^1.2.3", "crossws": "^0.3.5", "defu": "^6.1.6", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg=="],
|
||||
|
||||
"blume/astro/unstorage/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=="],
|
||||
@@ -9059,8 +9217,6 @@
|
||||
|
||||
"babel-plugin-module-resolver/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
|
||||
"blume/astro/unstorage/chokidar/readdirp": ["readdirp@5.1.1", "", {}, "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA=="],
|
||||
|
||||
"blume/astro/unstorage/h3/cookie-es": ["cookie-es@1.2.3", "", {}, "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw=="],
|
||||
|
||||
"blume/astro/unstorage/h3/crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="],
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
exact = true
|
||||
# Only install newly resolved package versions published at least 3 days ago.
|
||||
minimumReleaseAge = 259200
|
||||
minimumReleaseAgeExcludes = ["@ai-sdk/amazon-bedrock", "@ai-sdk/anthropic", "@opencode-ai/sdk", "@opentui/core", "@opentui/core-darwin-arm64", "@opentui/core-darwin-x64", "@opentui/core-linux-arm64", "@opentui/core-linux-arm64-musl", "@opentui/core-linux-x64", "@opentui/core-linux-x64-musl", "@opentui/core-win32-arm64", "@opentui/core-win32-x64", "@opentui/keymap", "@opentui/solid", "opentui-spinner", "gitlab-ai-provider", "opencode-gitlab-auth", "@ff-labs/fff-node", "@ff-labs/fff-bun", "@ff-labs/fff-bin-darwin-arm64", "@ff-labs/fff-bin-darwin-x64", "@ff-labs/fff-bin-linux-arm64-gnu", "@ff-labs/fff-bin-linux-arm64-musl", "@ff-labs/fff-bin-linux-x64-gnu", "@ff-labs/fff-bin-linux-x64-musl", "@ff-labs/fff-bin-win32-arm64", "@ff-labs/fff-bin-win32-x64", "@pierre/diffs", "@pierre/theming", "app-builder-lib", "dmg-builder", "electron-builder", "electron-publish"]
|
||||
minimumReleaseAgeExcludes = ["@ai-sdk/amazon-bedrock", "@ai-sdk/anthropic", "@opencode-ai/sdk", "@opentui/core", "@opentui/core-darwin-arm64", "@opentui/core-darwin-x64", "@opentui/core-linux-arm64", "@opentui/core-linux-arm64-musl", "@opentui/core-linux-x64", "@opentui/core-linux-x64-musl", "@opentui/core-win32-arm64", "@opentui/core-win32-x64", "@opentui/keymap", "@opentui/solid", "opentui-spinner", "gitlab-ai-provider", "opencode-gitlab-auth", "@ff-labs/fff-node", "@ff-labs/fff-bun", "@ff-labs/fff-bin-darwin-arm64", "@ff-labs/fff-bin-darwin-x64", "@ff-labs/fff-bin-linux-arm64-gnu", "@ff-labs/fff-bin-linux-arm64-musl", "@ff-labs/fff-bin-linux-x64-gnu", "@ff-labs/fff-bin-linux-x64-musl", "@ff-labs/fff-bin-win32-arm64", "@ff-labs/fff-bin-win32-x64", "@pierre/diffs", "@pierre/theming", "app-builder-lib", "dmg-builder", "electron-builder", "electron-publish", "blume"]
|
||||
|
||||
[test]
|
||||
root = "./do-not-run-tests-from-root"
|
||||
|
||||
@@ -20,8 +20,8 @@ Options:
|
||||
--no-modify-path Don't modify shell config files (.zshrc, .bashrc, etc.)
|
||||
|
||||
Examples:
|
||||
curl -fsSL https://raw.githubusercontent.com/anomalyco/opencode/v2/install | bash
|
||||
curl -fsSL https://raw.githubusercontent.com/anomalyco/opencode/v2/install | bash -s -- --version 0.0.0-beta-17236
|
||||
curl -fsSL https://opencode.ai/v2/install | bash
|
||||
curl -fsSL https://opencode.ai/v2/install | bash -s -- --version 0.0.0-beta-17236
|
||||
./install --binary /path/to/opencode2
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { expect, test } from "@playwright/test"
|
||||
import type { SessionMessageAssistant, SessionMessageInfo } from "@opencode-ai/client/promise"
|
||||
import { session, sessionID, setupTimeline } from "../performance/timeline-stability/fixture"
|
||||
import { event, session, sessionID, setupTimeline } from "../performance/timeline-stability/fixture"
|
||||
|
||||
const user = { id: "msg_user", type: "user", text: "Run it", time: { created: 1 } } satisfies SessionMessageInfo
|
||||
|
||||
const assistant = (completed: boolean, tool = false, childID?: string): SessionMessageAssistant => ({
|
||||
const assistant = (
|
||||
completed: boolean,
|
||||
tool = false,
|
||||
childID?: string,
|
||||
background = false,
|
||||
): SessionMessageAssistant => ({
|
||||
id: "msg_assistant",
|
||||
type: "assistant",
|
||||
agent: "build",
|
||||
@@ -15,7 +20,11 @@ const assistant = (completed: boolean, tool = false, childID?: string): SessionM
|
||||
type: "tool",
|
||||
id: "call_subagent",
|
||||
name: "subagent",
|
||||
state: { status: "running", input: {}, metadata: childID ? { sessionID: childID } : {} },
|
||||
state: {
|
||||
status: "running",
|
||||
input: { description: "Inspect code", ...(background ? { background: true } : {}) },
|
||||
metadata: { status: "running", ...(childID ? { sessionID: childID } : {}) },
|
||||
},
|
||||
time: { created: 2 },
|
||||
},
|
||||
]
|
||||
@@ -59,12 +68,17 @@ test("renders current protocol notices in CLI order", async ({ page }) => {
|
||||
await expect(notices.nth(1)).toContainText("explore finished · Search code")
|
||||
await expect(notices.nth(2)).toContainText("Continuing after restart")
|
||||
await expect(notices.nth(3)).toContainText("Skill · Review")
|
||||
await expect(notices).toHaveClass([/text-text-weak/, /text-text-weak/, /text-text-weak/, /text-text-weak/])
|
||||
await expect(notices.locator(".text-text-strong")).toHaveCount(0)
|
||||
expect(ownerWarnings).toEqual([])
|
||||
})
|
||||
|
||||
test("moves blocking work to the background with Ctrl+B", async ({ page }) => {
|
||||
await setupTimeline(page, { currentMessages: [user, assistant(false, true)] })
|
||||
await expect(page.locator('[data-component="task-tool-card"]')).toBeVisible()
|
||||
const card = page.locator('[data-component="task-tool-card"]')
|
||||
await expect(card).toBeVisible()
|
||||
await expect(card).toContainText("Inspect code")
|
||||
await expect(card).not.toContainText("(background)")
|
||||
await expect(page.getByText("Called `subagent`", { exact: false })).toHaveCount(0)
|
||||
await expect(page.locator('[data-component="background-tool-control"]')).toHaveCount(0)
|
||||
await expect(page.locator('[data-action="session-background-toggle"]')).toContainText("Move 1 subagent to background")
|
||||
@@ -77,6 +91,11 @@ test("moves blocking work to the background with Ctrl+B", async ({ page }) => {
|
||||
await request
|
||||
})
|
||||
|
||||
test("waits for completion before labeling requested background work", async ({ page }) => {
|
||||
await setupTimeline(page, { currentMessages: [user, assistant(false, true, undefined, true)] })
|
||||
await expect(page.locator('[data-component="task-tool-card"]')).not.toContainText("(background)")
|
||||
})
|
||||
|
||||
test("navigates from a running subagent card and hides background controls in the child", async ({ page }) => {
|
||||
const childID = "ses_running_child"
|
||||
await setupTimeline(page, {
|
||||
@@ -105,7 +124,7 @@ test("shows a badge for active background work", async ({ page }) => {
|
||||
test("separates blocking and already-backgrounded work into two rows", async ({ page }) => {
|
||||
const backgroundID = "ses_background_existing"
|
||||
const blockingID = "ses_background_blocking"
|
||||
await setupTimeline(page, {
|
||||
const timeline = await setupTimeline(page, {
|
||||
currentMessages: [
|
||||
user,
|
||||
{
|
||||
@@ -175,9 +194,16 @@ test("separates blocking and already-backgrounded work into two rows", async ({
|
||||
})
|
||||
|
||||
const dock = page.locator('[data-component="session-background-dock"]')
|
||||
const backgroundCard = page.locator('[data-timeline-part-id="call_backgrounded"]')
|
||||
await expect(dock).toContainText("Move 1 subagent to background")
|
||||
await expect(dock.getByText("Running 1 shell and 1 subagent in background", { exact: true })).toBeVisible()
|
||||
await expect(backgroundCard).toContainText("Background task (background)")
|
||||
await expect(backgroundCard.locator('[data-component="session-progress-indicator-v2"]')).toBeVisible()
|
||||
await expect(
|
||||
page.locator('[data-timeline-part-id="call_shell_backgrounded"] [data-component="text-shimmer"]'),
|
||||
).toHaveAttribute("data-active", "true")
|
||||
|
||||
await timeline.send(event("session.status", { sessionID: backgroundID, status: { type: "idle" } }))
|
||||
await expect(backgroundCard.locator('[data-component="session-progress-indicator-v2"]')).toHaveCount(0)
|
||||
await expect(backgroundCard).toContainText("Background task (background)")
|
||||
})
|
||||
|
||||
@@ -115,6 +115,12 @@ test("labels V2 skill tools from IDs and result metadata", async ({ page }) => {
|
||||
"aria-label",
|
||||
"OpenCode",
|
||||
)
|
||||
for (const id of [pending, completed]) {
|
||||
const skill = page.locator(`[data-timeline-part-id="${id}"]`)
|
||||
await expect(skill.locator('[data-slot="skill-tool-label"]')).toHaveText("Skill")
|
||||
await expect(skill.locator('[data-slot="skill-tool-separator"]')).toHaveText("·")
|
||||
await expect(skill.locator('use[href="#opencode-icon-post-skill"]')).toBeVisible()
|
||||
}
|
||||
})
|
||||
|
||||
function questionInput() {
|
||||
|
||||
@@ -1057,9 +1057,12 @@ function MessageTimelineView(
|
||||
<TimelineRowFrame row={noticeRow()}>
|
||||
<Show when={content()}>
|
||||
{(content) => (
|
||||
<div data-slot="session-timeline-notice" class={`w-full pt-3 pb-1 text-13-regular ${turnPadding()}`}>
|
||||
<span class="text-13-medium text-text-strong">{content().label}</span>
|
||||
<Show when={content().data}>{(data) => <span class="text-text-weak"> · {data()}</span>}</Show>
|
||||
<div
|
||||
data-slot="session-timeline-notice"
|
||||
class={`w-full pt-3 pb-1 text-13-regular text-text-weak ${turnPadding()}`}
|
||||
>
|
||||
<span class="text-13-medium">{content().label}</span>
|
||||
<Show when={content().data}>{(data) => <span> · {data()}</span>}</Show>
|
||||
</div>
|
||||
)}
|
||||
</Show>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { TuiKeybind } from "@opencode-ai/tui/config/v1/keybind"
|
||||
import { Definitions } from "@opencode-ai/tui/config/keybind"
|
||||
import { Effect, FileSystem, Option, Schema } from "effect"
|
||||
import { randomUUID } from "crypto"
|
||||
import { createScanner, parse, parseTree, type Node, type ParseError } from "jsonc-parser"
|
||||
import { applyEdits, createScanner, modify, parse, parseTree, type Node, type ParseError } from "jsonc-parser"
|
||||
import path from "path"
|
||||
import { Info } from "./schema"
|
||||
|
||||
@@ -41,33 +41,55 @@ export const run = Effect.fn("cli.config.migrate")(function* (input: {
|
||||
if (errors.length) return
|
||||
const config = Option.getOrUndefined(decodeRecord(value))
|
||||
if (config === undefined) return
|
||||
const terminal = Option.getOrUndefined(decodeRecord(config.terminal))
|
||||
const legacyCopy = terminal?.copy_on_select
|
||||
const copy =
|
||||
typeof legacyCopy === "boolean" && terminal?.copy === undefined ? (legacyCopy ? "select" : "manual") : undefined
|
||||
const renamed =
|
||||
typeof legacyCopy !== "boolean"
|
||||
? text
|
||||
: [
|
||||
...(copy === undefined ? [] : [{ path: ["terminal", "copy"], value: copy }]),
|
||||
{ path: ["terminal", "copy_on_select"], value: undefined },
|
||||
].reduce(
|
||||
(text, edit) =>
|
||||
applyEdits(
|
||||
text,
|
||||
modify(text, edit.path, edit.value, { formattingOptions: { tabSize: 2, insertSpaces: true } }),
|
||||
),
|
||||
text,
|
||||
)
|
||||
const keybinds = Option.getOrUndefined(decodeRecord(config.keybinds))
|
||||
if (keybinds === undefined) return
|
||||
const deduped = findKeybindObjects(text)
|
||||
.slice(0, -1)
|
||||
.reduce((text) => {
|
||||
const property = findKeybindObjects(text)[0]
|
||||
return property === undefined ? text : removeProperty(text, property)
|
||||
}, text)
|
||||
const updated = Object.keys(keybinds).reduce((text, name) => {
|
||||
const target =
|
||||
TuiKeybind.CommandMap[name as keyof typeof TuiKeybind.CommandMap] ??
|
||||
(name in Definitions || LegacyKeybindTargets.has(name) ? name : undefined)
|
||||
if (target === undefined) return text
|
||||
const properties = findKeybindProperties(text, name)
|
||||
if (!properties.length) return text
|
||||
const remove = !(target in Definitions) || (target !== name && target in keybinds)
|
||||
// The parser gives the final duplicate precedence, so remove earlier properties before renaming it.
|
||||
const updated = properties.slice(0, remove ? properties.length : -1).reduce((text) => {
|
||||
const property = findKeybindProperties(text, name)[0]
|
||||
return property === undefined ? text : removeProperty(text, property)
|
||||
}, text)
|
||||
if (remove) return updated
|
||||
if (target === name) return updated
|
||||
const key = findKeybindProperties(updated, name)[0]?.children?.[0]
|
||||
if (key === undefined) return text
|
||||
return updated.slice(0, key.offset) + JSON.stringify(target) + updated.slice(key.offset + key.length)
|
||||
}, deduped)
|
||||
const updated =
|
||||
keybinds === undefined
|
||||
? renamed
|
||||
: Object.keys(keybinds).reduce(
|
||||
(text, name) => {
|
||||
const target =
|
||||
TuiKeybind.CommandMap[name as keyof typeof TuiKeybind.CommandMap] ??
|
||||
(name in Definitions || LegacyKeybindTargets.has(name) ? name : undefined)
|
||||
if (target === undefined) return text
|
||||
const properties = findKeybindProperties(text, name)
|
||||
if (!properties.length) return text
|
||||
const remove = !(target in Definitions) || (target !== name && target in keybinds)
|
||||
// The parser gives the final duplicate precedence, so remove earlier properties before renaming it.
|
||||
const cleaned = properties.slice(0, remove ? properties.length : -1).reduce((text) => {
|
||||
const property = findKeybindProperties(text, name)[0]
|
||||
return property === undefined ? text : removeProperty(text, property)
|
||||
}, text)
|
||||
if (remove) return cleaned
|
||||
if (target === name) return cleaned
|
||||
const key = findKeybindProperties(cleaned, name)[0]?.children?.[0]
|
||||
if (key === undefined) return text
|
||||
return cleaned.slice(0, key.offset) + JSON.stringify(target) + cleaned.slice(key.offset + key.length)
|
||||
},
|
||||
findKeybindObjects(renamed)
|
||||
.slice(0, -1)
|
||||
.reduce((text) => {
|
||||
const property = findKeybindObjects(text)[0]
|
||||
return property === undefined ? text : removeProperty(text, property)
|
||||
}, renamed),
|
||||
)
|
||||
if (updated === text) return
|
||||
const updatedErrors: ParseError[] = []
|
||||
const info = Option.getOrUndefined(decodeInfo(parse(updated, updatedErrors, { allowTrailingComma: true })))
|
||||
|
||||
@@ -210,6 +210,46 @@ test("migrates legacy keybind names in an existing cli.json", async () => {
|
||||
}
|
||||
})
|
||||
|
||||
test("migrates copy_on_select in an existing cli.json", async () => {
|
||||
for (const item of [
|
||||
{ legacy: true, expected: "select" },
|
||||
{ legacy: false, expected: "manual" },
|
||||
{ legacy: true, copy: "manual", expected: "manual" },
|
||||
] as const) {
|
||||
const directory = await Bun.$`mktemp -d`.text().then((value) => value.trim())
|
||||
const file = path.join(directory, "cli.json")
|
||||
await Bun.write(
|
||||
file,
|
||||
`{
|
||||
// Preserve this comment
|
||||
"terminal": {
|
||||
${item.copy === undefined ? "" : `"copy": ${JSON.stringify(item.copy)},`}
|
||||
"copy_on_select": ${item.legacy}
|
||||
}
|
||||
}
|
||||
`,
|
||||
)
|
||||
|
||||
try {
|
||||
const config = await run(
|
||||
directory,
|
||||
Effect.gen(function* () {
|
||||
const service = yield* Config.Service
|
||||
return yield* service.get()
|
||||
}),
|
||||
)
|
||||
|
||||
expect(config.terminal).toEqual({ copy: item.expected })
|
||||
const text = await Bun.file(file).text()
|
||||
expect(text).toContain("// Preserve this comment")
|
||||
expect(text).not.toContain("copy_on_select")
|
||||
expect(parse(text).terminal).toEqual({ copy: item.expected })
|
||||
} finally {
|
||||
await Bun.$`rm -rf ${directory}`
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
test("uses migrated keybinds when persistence fails", async () => {
|
||||
const directory = await Bun.$`mktemp -d`.text().then((value) => value.trim())
|
||||
const file = path.join(directory, "cli.json")
|
||||
|
||||
@@ -63,6 +63,7 @@ import { AgentPlugin } from "./agent.js"
|
||||
import { CommandPlugin } from "./command.js"
|
||||
import { PlanPlugin } from "./plan.js"
|
||||
import { ModelsDevPlugin } from "./models-dev.js"
|
||||
import { McpCodeModePlugin } from "./mcp-codemode.js"
|
||||
import { ProviderPlugins } from "./provider.js"
|
||||
import { WebSearchPlugins } from "./websearch/index.js"
|
||||
import { PluginRuntime } from "./runtime.js"
|
||||
@@ -94,6 +95,7 @@ const services = Effect.fn("PluginInternal.services")(function* () {
|
||||
const location = yield* Location.Service
|
||||
const locationMutation = yield* LocationMutation.Service
|
||||
const models = yield* ModelsDev.Service
|
||||
const mcpCodeMode = yield* McpCodeModePlugin.Service
|
||||
const npm = yield* Npm.Service
|
||||
const permission = yield* Permission.Service
|
||||
const runtime = yield* PluginRuntime.Service
|
||||
@@ -131,6 +133,7 @@ const services = Effect.fn("PluginInternal.services")(function* () {
|
||||
Context.make(Location.Service, location),
|
||||
Context.make(LocationMutation.Service, locationMutation),
|
||||
Context.make(ModelsDev.Service, models),
|
||||
Context.make(McpCodeModePlugin.Service, mcpCodeMode),
|
||||
Context.make(Npm.Service, npm),
|
||||
Context.make(Permission.Service, permission),
|
||||
Context.make(PluginRuntime.Service, runtime),
|
||||
@@ -175,6 +178,7 @@ export const requirements = LayerNode.group([
|
||||
Location.node,
|
||||
LocationMutation.node,
|
||||
ModelsDev.node,
|
||||
McpCodeModePlugin.node,
|
||||
Npm.node,
|
||||
Permission.node,
|
||||
PluginRuntime.node,
|
||||
@@ -202,6 +206,7 @@ const pre = [
|
||||
SkillPlugin.Plugin,
|
||||
...SystemPromptPlugin.Plugins,
|
||||
ModelsDevPlugin,
|
||||
McpCodeModePlugin.Plugin,
|
||||
...ProviderPlugins,
|
||||
...WebSearchPlugins,
|
||||
PatchTool.Plugin,
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
export * as McpCodeModePlugin from "./mcp-codemode.js"
|
||||
|
||||
import { define } from "@opencode-ai/plugin/effect/plugin"
|
||||
import { ConfigMCP } from "@opencode-ai/schema/config/mcp"
|
||||
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
|
||||
import { Context, Effect, Layer, Scope } from "effect"
|
||||
|
||||
const directToolHosts = new Set(["mcp.cloudflare.com"])
|
||||
type Resolver = (config: typeof ConfigMCP.Server.Type) => boolean | undefined
|
||||
|
||||
export interface Interface {
|
||||
register: (resolver: Resolver) => Effect.Effect<void, never, Scope.Scope>
|
||||
resolve: (config: typeof ConfigMCP.Server.Type) => boolean | undefined
|
||||
}
|
||||
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/McpCodeModePlugin") {}
|
||||
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.sync(() => {
|
||||
let resolvers: Resolver[] = []
|
||||
return Service.of({
|
||||
register: Effect.fn("McpCodeModePlugin.register")(function* (resolver) {
|
||||
resolvers = [...resolvers, resolver]
|
||||
yield* Effect.addFinalizer(() => Effect.sync(() => (resolvers = resolvers.filter((item) => item !== resolver))))
|
||||
}),
|
||||
resolve: (config) =>
|
||||
resolvers
|
||||
.toReversed()
|
||||
.map((resolver) => resolver(config))
|
||||
.find((value) => value !== undefined),
|
||||
})
|
||||
}),
|
||||
)
|
||||
|
||||
export const node = makeLocationNode({ service: Service, layer, deps: [] })
|
||||
|
||||
export const Plugin = define({
|
||||
id: "opencode.mcp.codemode-compatibility",
|
||||
effect: Effect.fn(function* () {
|
||||
const defaults = yield* Service
|
||||
yield* defaults.register(codeModeCompatibilityDefault)
|
||||
}),
|
||||
})
|
||||
|
||||
export function codeModeCompatibilityDefault(config: typeof ConfigMCP.Server.Type) {
|
||||
if (config.type !== "remote") return
|
||||
const url = URL.parse(config.url)
|
||||
if (!url || !directToolHosts.has(url.hostname.toLowerCase())) return
|
||||
return false
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import { App } from "../../app.js"
|
||||
import { Credential } from "../../credential.js"
|
||||
import { Bus } from "../../bus.js"
|
||||
import { Integration } from "../../integration.js"
|
||||
import { Model } from "../../model.js"
|
||||
import { OauthCallbackPage } from "../../oauth/page.js"
|
||||
import { Provider } from "../../provider.js"
|
||||
import type { PluginInternal } from "../internal.js"
|
||||
@@ -229,6 +230,16 @@ export const OpenAIPlugin = define({
|
||||
})
|
||||
}
|
||||
})
|
||||
yield* ctx.session.hook("http.request", (evt) =>
|
||||
Effect.sync(() => {
|
||||
if (!chatgpt || evt.model.providerID !== Provider.ID.openai) return
|
||||
const url = new URL(evt.request.url)
|
||||
evt.request.headers.set("originator", "opencode")
|
||||
evt.request.headers.set("session-id", evt.sessionID)
|
||||
if (url.origin !== "https://api.openai.com") return
|
||||
evt.request = new Request(`${codexBaseURL}${url.pathname.replace(/^\/v1/, "")}${url.search}`, evt.request)
|
||||
}),
|
||||
)
|
||||
const refresh = () => loading.withPermit(load().pipe(Effect.andThen(ctx.catalog.reload())))
|
||||
yield* bus.subscribe(Integration.Event.ConnectionUpdated).pipe(
|
||||
Stream.filter((event) => event.data.integrationID === Integration.ID.make("openai")),
|
||||
|
||||
@@ -11,6 +11,7 @@ import { SessionContext } from "./context.js"
|
||||
import { SessionGenerate } from "./generate.js"
|
||||
import { SessionHistory } from "./history.js"
|
||||
import { SessionModelHeaders } from "./model-headers.js"
|
||||
import { SessionModelHttp } from "./model-http.js"
|
||||
import { SessionPromptCacheKey } from "./prompt-cache-key.js"
|
||||
import { SessionRunnerModel } from "./runner/model.js"
|
||||
import { SessionSystemPrompt } from "./system-prompt.js"
|
||||
@@ -79,6 +80,13 @@ export const layer = Layer.effect(
|
||||
messages: contextEvent.messages,
|
||||
tools: hookedTools,
|
||||
}),
|
||||
{
|
||||
http: SessionModelHttp.middleware(hooks, {
|
||||
sessionID: selection.session.id,
|
||||
agent: selection.agent.id,
|
||||
model: model.ref,
|
||||
}),
|
||||
},
|
||||
)
|
||||
yield* Effect.logInfo("session generation usage diagnostic", { usage: response.usage })
|
||||
return response.text
|
||||
|
||||
@@ -2,12 +2,17 @@ export * as McpTool from "./mcp.js"
|
||||
|
||||
import { ToolFailure } from "@opencode-ai/ai"
|
||||
import { McpEvent } from "@opencode-ai/schema/mcp-event"
|
||||
import { Document } from "@opencode-ai/schema/config"
|
||||
import { Context, Effect, Exit, Fiber, type JsonSchema, Layer, Scope, Semaphore, Stream } from "effect"
|
||||
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
|
||||
import { Bus } from "../bus.js"
|
||||
|
||||
import { MCP } from "../mcp/index.js"
|
||||
import { Config } from "../config.js"
|
||||
import { Permission } from "../permission.js"
|
||||
import { Plugin } from "../plugin.js"
|
||||
import { McpCodeModePlugin } from "../plugin/mcp-codemode.js"
|
||||
import { PluginSupervisor } from "../plugin/supervisor.js"
|
||||
import { Tool } from "../tool.js"
|
||||
|
||||
/**
|
||||
@@ -27,6 +32,8 @@ export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const mcp = yield* MCP.Service
|
||||
const config = yield* Config.Service
|
||||
const codemode = yield* McpCodeModePlugin.Service
|
||||
const tools = yield* Tool.Service
|
||||
const bus = yield* Bus.Service
|
||||
const permission = yield* Permission.Service
|
||||
@@ -39,14 +46,23 @@ export const layer = Layer.effect(
|
||||
const reconcile = lock.withPermit(
|
||||
Effect.gen(function* () {
|
||||
const discovered = yield* mcp.tools()
|
||||
const servers = new Map(
|
||||
(yield* config.entries())
|
||||
.filter((entry): entry is Document => entry.type === "document")
|
||||
.flatMap((entry) => Object.entries(entry.info.mcp?.servers ?? {})),
|
||||
)
|
||||
const next = yield* Scope.fork(scope)
|
||||
yield* tools
|
||||
.transform((draft) => {
|
||||
for (const tool of discovered) {
|
||||
const schema = (tool.inputSchema ?? {}) as JsonSchema.JsonSchema
|
||||
const server = servers.get(tool.server)
|
||||
draft.add({
|
||||
name: tool.name,
|
||||
options: { namespace: namespace(tool.server), codemode: tool.codemode !== false },
|
||||
options: {
|
||||
namespace: namespace(tool.server),
|
||||
codemode: (tool.codemode ?? (server ? codemode.resolve(server) : undefined)) !== false,
|
||||
},
|
||||
description: tool.description ?? "",
|
||||
input: {
|
||||
...schema,
|
||||
@@ -122,7 +138,7 @@ export const layer = Layer.effect(
|
||||
)
|
||||
|
||||
const initial = yield* reconcile.pipe(Effect.forkScoped)
|
||||
yield* bus.subscribe(McpEvent.ToolsChanged).pipe(
|
||||
yield* bus.subscribe([McpEvent.ToolsChanged, Plugin.Event.Updated]).pipe(
|
||||
Stream.runForEach(() => reconcile),
|
||||
Effect.forkScoped({ startImmediately: true }),
|
||||
)
|
||||
@@ -133,5 +149,5 @@ export const layer = Layer.effect(
|
||||
export const node = makeLocationNode({
|
||||
service: Service,
|
||||
layer,
|
||||
deps: [Tool.node, MCP.node, Bus.node, Permission.node],
|
||||
deps: [Tool.node, MCP.node, McpCodeModePlugin.node, Config.node, Bus.node, Permission.node, PluginSupervisor.node],
|
||||
})
|
||||
|
||||
@@ -29,6 +29,8 @@ import { MCP } from "@opencode-ai/core/mcp/index"
|
||||
import { MCPClient } from "@opencode-ai/core/mcp/client"
|
||||
import { MCPStdio } from "@opencode-ai/core/mcp/stdio"
|
||||
import { Permission } from "@opencode-ai/core/permission"
|
||||
import { McpCodeModePlugin } from "@opencode-ai/core/plugin/mcp-codemode"
|
||||
import { PluginSupervisor } from "@opencode-ai/core/plugin/supervisor"
|
||||
import { AbsolutePath } from "@opencode-ai/core/schema"
|
||||
import { Session } from "@opencode-ai/core/session"
|
||||
import { McpTool } from "@opencode-ai/core/tool/mcp"
|
||||
@@ -336,12 +338,16 @@ const permissions = Layer.mock(Permission.Service, {
|
||||
}),
|
||||
})
|
||||
const events = Layer.mock(Bus.Service, { subscribe: () => Stream.never })
|
||||
const plugins = Layer.succeed(PluginSupervisor.Service, PluginSupervisor.Service.of({ flush: Effect.void }))
|
||||
const it = testEffect(
|
||||
AppNodeBuilder.build(LayerNode.group([Tool.node, McpTool.node]), [
|
||||
[MCP.node, mcp],
|
||||
[McpCodeModePlugin.node, McpCodeModePlugin.layer],
|
||||
[Config.node, Config.testLayer()],
|
||||
[Permission.node, permissions],
|
||||
[Bus.node, events],
|
||||
[Image.node, imagePassthrough],
|
||||
[PluginSupervisor.node, plugins],
|
||||
]),
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { ConfigMCP } from "@opencode-ai/schema/config/mcp"
|
||||
import { codeModeCompatibilityDefault, McpCodeModePlugin } from "@opencode-ai/core/plugin/mcp-codemode"
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
|
||||
describe("MCP Code Mode compatibility defaults", () => {
|
||||
it("keeps Cloudflare's Code Mode MCP server direct by default", () => {
|
||||
const config = new ConfigMCP.Remote({ type: "remote", url: "https://mcp.cloudflare.com/mcp" })
|
||||
expect(codeModeCompatibilityDefault(config)).toBe(false)
|
||||
})
|
||||
|
||||
it("does not change Cloudflare's product-specific MCP servers", () => {
|
||||
const config = new ConfigMCP.Remote({ type: "remote", url: "https://docs.mcp.cloudflare.com/mcp" })
|
||||
expect(codeModeCompatibilityDefault(config)).toBeUndefined()
|
||||
})
|
||||
|
||||
it("does not change local or unrelated remote servers", () => {
|
||||
const local = new ConfigMCP.Local({ type: "local", command: ["server"] })
|
||||
const remote = new ConfigMCP.Remote({ type: "remote", url: "https://example.com/mcp" })
|
||||
expect(codeModeCompatibilityDefault(local)).toBeUndefined()
|
||||
expect(codeModeCompatibilityDefault(remote)).toBeUndefined()
|
||||
})
|
||||
|
||||
it("retains a registered direct-tool default", async () => {
|
||||
await Effect.runPromise(
|
||||
Effect.scoped(
|
||||
Effect.gen(function* () {
|
||||
const defaults = yield* McpCodeModePlugin.Service
|
||||
yield* defaults.register(codeModeCompatibilityDefault)
|
||||
const config = new ConfigMCP.Remote({ type: "remote", url: "https://mcp.cloudflare.com/mcp" })
|
||||
expect(defaults.resolve(config)).toBe(false)
|
||||
}).pipe(Effect.provide(McpCodeModePlugin.layer)),
|
||||
),
|
||||
)
|
||||
})
|
||||
})
|
||||
@@ -1,4 +1,6 @@
|
||||
import { Money } from "@opencode-ai/schema/money"
|
||||
import { Agent } from "@opencode-ai/schema/agent"
|
||||
import { Session } from "@opencode-ai/schema/session"
|
||||
import { describe, expect } from "bun:test"
|
||||
import { Effect } from "effect"
|
||||
import { Catalog } from "@opencode-ai/core/catalog"
|
||||
@@ -27,9 +29,14 @@ function required<T>(value: T | undefined): T {
|
||||
return value
|
||||
}
|
||||
|
||||
const httpMiddlewareCount = Effect.fn(function* () {
|
||||
const hooks = yield* PluginHooks.Service
|
||||
return Number(yield* hooks.has("session", "http.request")) + Number(yield* hooks.has("session", "http.response"))
|
||||
const http = Effect.fn(function* (providerID: Provider.ID, url: string) {
|
||||
const event = yield* (yield* PluginHooks.Service).trigger("session", "http.request", {
|
||||
sessionID: Session.ID.make("ses_test"),
|
||||
agent: Agent.ID.make("build"),
|
||||
model: Model.Ref.make({ providerID, id: Model.ID.make("gpt-5.5") }),
|
||||
request: new Request(url, { method: "POST", body: "{}" }),
|
||||
})
|
||||
return { url: event.request.url, headers: Object.fromEntries(event.request.headers.entries()) }
|
||||
})
|
||||
|
||||
describe("OpenAIPlugin", () => {
|
||||
@@ -103,13 +110,22 @@ describe("OpenAIPlugin", () => {
|
||||
})
|
||||
yield* addPlugin()
|
||||
|
||||
const request = yield* http(Provider.ID.openai, "https://api.openai.com/v1/responses")
|
||||
const custom = yield* http(Provider.ID.make("custom-openai"), "https://custom.example/v1/responses")
|
||||
const proxy = yield* http(Provider.ID.openai, "https://proxy.example/v1/responses?region=us")
|
||||
|
||||
const provider = required(yield* catalog.provider.get(Provider.ID.openai))
|
||||
expect(provider.package).toBe("@opencode-ai/ai/providers/openai")
|
||||
expect(provider.settings).toMatchObject({ baseURL: "https://chatgpt.com/backend-api/codex" })
|
||||
expect(provider.headers).toMatchObject({ originator: "opencode", "chatgpt-account-id": "acct_123" })
|
||||
expect(yield* httpMiddlewareCount()).toBe(0)
|
||||
expect(request.url).toBe("https://chatgpt.com/backend-api/codex/responses")
|
||||
expect(request.headers).toMatchObject({ originator: "opencode", "session-id": "ses_test" })
|
||||
expect(custom.headers).not.toHaveProperty("originator")
|
||||
expect(proxy.url).toBe("https://proxy.example/v1/responses?region=us")
|
||||
expect(proxy.headers).toMatchObject({ originator: "opencode", "session-id": "ses_test" })
|
||||
const eligible = required(yield* catalog.model.get(Provider.ID.openai, Model.ID.make("gpt-5.5")))
|
||||
expect(eligible.package).toBe("@opencode-ai/ai/providers/openai")
|
||||
expect(eligible.headers).toMatchObject({ originator: "opencode", "chatgpt-account-id": "acct_123" })
|
||||
expect(eligible.cost).toEqual([])
|
||||
expect(eligible.limit).toEqual({ context: 400_000, input: 272_000, output: 128_000 })
|
||||
expect(eligible.enabled).toBe(true)
|
||||
@@ -151,13 +167,15 @@ describe("OpenAIPlugin", () => {
|
||||
})
|
||||
yield* addPlugin()
|
||||
|
||||
const request = yield* http(Provider.ID.openai, "https://api.openai.com/v1/responses")
|
||||
|
||||
const provider = required(yield* catalog.provider.get(Provider.ID.openai))
|
||||
const model = required(yield* catalog.model.get(Provider.ID.openai, Model.ID.make("gpt-5.5")))
|
||||
expect(model.package).toBe("@opencode-ai/ai/providers/openai")
|
||||
expect(model.enabled).toBe(true)
|
||||
expect(model.limit).toEqual({ context: 1_050_000, input: 922_000, output: 128_000 })
|
||||
expect(request.headers).not.toHaveProperty("originator")
|
||||
expect(provider.headers).not.toHaveProperty("originator")
|
||||
expect(yield* httpMiddlewareCount()).toBe(0)
|
||||
expect(required(yield* catalog.model.get(Provider.ID.openai, Model.ID.make("gpt-4.1"))).enabled).toBe(true)
|
||||
}),
|
||||
)
|
||||
|
||||
@@ -51,15 +51,17 @@ import { Effect, Layer, Schema, Stream } from "effect"
|
||||
import { testEffect } from "./lib/effect"
|
||||
|
||||
const requests: LLMRequest[] = []
|
||||
let hasHttpMiddleware = false
|
||||
let instruction: string | Instructions.Unavailable = "Initial context"
|
||||
const sessionID = SessionSchema.ID.make("ses_generate_test")
|
||||
|
||||
const model = LanguageModel.make({ id: "generate-model", provider: "test", route: OpenAIChat.route })
|
||||
const client = Layer.mock(LLMClient.Service)({
|
||||
stream: () => Stream.die(new Error("unused")),
|
||||
generate: (request) =>
|
||||
generate: (request, options) =>
|
||||
Effect.sync(() => {
|
||||
requests.push(request)
|
||||
hasHttpMiddleware = typeof options?.http === "function"
|
||||
const response = LLMResponse.fromEvents([
|
||||
LLMEvent.stepStart({ index: 0 }),
|
||||
LLMEvent.textStart({ id: "generate" }),
|
||||
@@ -221,6 +223,7 @@ const setup = Effect.gen(function* () {
|
||||
it.effect("generates from fresh settled Session context without durable mutation", () =>
|
||||
Effect.gen(function* () {
|
||||
requests.length = 0
|
||||
hasHttpMiddleware = false
|
||||
instruction = "Initial context"
|
||||
const { db, bus, instructions } = yield* setup
|
||||
yield* InstructionState.prepare(db, bus, instructions, sessionID)
|
||||
@@ -298,6 +301,7 @@ it.effect("generates from fresh settled Session context without durable mutation
|
||||
|
||||
expect(result).toBe("Transient answer")
|
||||
expect(requests).toHaveLength(1)
|
||||
expect(hasHttpMiddleware).toBe(true)
|
||||
expect(requests[0]?.model).toBe(model)
|
||||
expect(requests[0]?.system[0]?.text).toBe("Hooked system")
|
||||
expect(requests[0]?.system.map((part) => part.text)).toContain("Initial context")
|
||||
|
||||
@@ -722,7 +722,7 @@ describe("ShellTool", () => {
|
||||
)
|
||||
const settled = yield* executeTool(registry, call({ command: idleCommand, timeout: 50, background: true }))
|
||||
const shellID = typeof settled.metadata?.shellID === "string" ? settled.metadata.shellID : undefined
|
||||
expect(settled.metadata).toMatchObject({ status: "running", truncated: false })
|
||||
expect(settled.metadata).toMatchObject({ truncated: false })
|
||||
expect(shellID).toStartWith("sh_")
|
||||
|
||||
const shell = yield* Shell.Service
|
||||
@@ -807,7 +807,7 @@ describe("ShellTool", () => {
|
||||
expect(yield* backgroundWhenReady()).toMatchObject([{ id: "call-background-signal", type: "shell" }])
|
||||
const settled = yield* Fiber.join(waiting)
|
||||
const shellID = typeof settled.metadata?.shellID === "string" ? settled.metadata.shellID : undefined
|
||||
expect(settled.metadata).toMatchObject({ status: "running", truncated: false })
|
||||
expect(settled.metadata).toMatchObject({ truncated: false })
|
||||
expect(settled.content?.[0]).toEqual({
|
||||
type: "text",
|
||||
text: "The command was moved to the background.",
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
"./v2/prompt-input/types": "./src/v2/components/prompt-input/types.ts"
|
||||
},
|
||||
"scripts": {
|
||||
"generate:progress-indicator": "bun script/generate-session-progress-indicator.ts",
|
||||
"typecheck": "tsgo -b",
|
||||
"test": "bun test src --only-failures"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
import { deflateSync } from "node:zlib"
|
||||
|
||||
const size = 16
|
||||
const frameRate = 90
|
||||
const duration = 1.2
|
||||
const frameCount = frameRate * duration
|
||||
const opacity = [0.2, 0.5, 0.75, 1]
|
||||
// Each digit selects one dot opacity for one of the eight source key poses.
|
||||
const poses = [
|
||||
"0000000000003000031000321",
|
||||
"0000000000003000320032100",
|
||||
"0000000000333002100010000",
|
||||
"3000023000123000000000000",
|
||||
"1230001300003000000000000",
|
||||
"0012300230003000000000000",
|
||||
"0000100022003330000000000",
|
||||
"0000000000003330002200001",
|
||||
].map((pose) => Array.from(pose, (value) => opacity[Number(value)]))
|
||||
const crcTable = Array.from({ length: 256 }, (_, value) =>
|
||||
Array.from({ length: 8 }).reduce<number>((crc) => ((crc & 1) !== 0 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1), value),
|
||||
)
|
||||
|
||||
await Bun.write(new URL("../src/v2/components/session-progress-indicator-v2-1x.png", import.meta.url), apng(1))
|
||||
|
||||
function apng(scale: number) {
|
||||
const frameSize = size * scale
|
||||
const header = Buffer.alloc(13)
|
||||
header.writeUInt32BE(frameSize, 0)
|
||||
header.writeUInt32BE(frameSize, 4)
|
||||
header[8] = 8
|
||||
header[9] = 6
|
||||
|
||||
const animation = Buffer.alloc(8)
|
||||
animation.writeUInt32BE(frameCount, 0)
|
||||
animation.writeUInt32BE(0, 4)
|
||||
const chunks = [chunk("IHDR", header), chunk("acTL", animation)]
|
||||
const sequence = { value: 0 }
|
||||
|
||||
Array.from({ length: frameCount }, (_, frame) => {
|
||||
const control = Buffer.alloc(26)
|
||||
control.writeUInt32BE(sequence.value++, 0)
|
||||
control.writeUInt32BE(frameSize, 4)
|
||||
control.writeUInt32BE(frameSize, 8)
|
||||
control.writeUInt16BE(frame % 9 === 0 ? 12 : 11, 20)
|
||||
control.writeUInt16BE(1000, 22)
|
||||
chunks.push(chunk("fcTL", control))
|
||||
|
||||
const data = deflateSync(pixels(scale, frame), { level: 9 })
|
||||
if (frame === 0) {
|
||||
chunks.push(chunk("IDAT", data))
|
||||
return
|
||||
}
|
||||
const frameData = Buffer.alloc(data.length + 4)
|
||||
frameData.writeUInt32BE(sequence.value++, 0)
|
||||
data.copy(frameData, 4)
|
||||
chunks.push(chunk("fdAT", frameData))
|
||||
})
|
||||
|
||||
return Buffer.concat([Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]), ...chunks, chunk("IEND", Buffer.alloc(0))])
|
||||
}
|
||||
|
||||
function pixels(scale: number, frame: number) {
|
||||
const frameSize = size * scale
|
||||
const stride = frameSize * 4 + 1
|
||||
const pixels = Buffer.alloc(stride * frameSize)
|
||||
const progress = (frame / frameCount) * poses.length
|
||||
const current = Math.floor(progress)
|
||||
const next = (current + 1) % poses.length
|
||||
const mix = easeOut(progress - current)
|
||||
|
||||
Array.from({ length: frameSize }, (_, y) => (pixels[y * stride] = 0))
|
||||
poses[current].forEach((value, index) => {
|
||||
draw(
|
||||
pixels,
|
||||
stride,
|
||||
(1 + (index % 5) * 3) * scale,
|
||||
(1 + Math.floor(index / 5) * 3) * scale,
|
||||
3 * scale,
|
||||
value + (poses[next][index] - value) * mix,
|
||||
)
|
||||
})
|
||||
return pixels
|
||||
}
|
||||
|
||||
function draw(pixels: Buffer, stride: number, x: number, y: number, size: number, opacity: number) {
|
||||
const left = Math.floor(x)
|
||||
const top = Math.floor(y)
|
||||
const right = Math.ceil(x + size)
|
||||
const bottom = Math.ceil(y + size)
|
||||
|
||||
Array.from({ length: bottom - top }, (_, row) => top + row).forEach((py) =>
|
||||
Array.from({ length: right - left }, (_, column) => left + column).forEach((px) => {
|
||||
const coverageX = Math.max(0, Math.min(px + 1, x + size) - Math.max(px, x))
|
||||
const coverageY = Math.max(0, Math.min(py + 1, y + size) - Math.max(py, y))
|
||||
const offset = py * stride + 1 + px * 4
|
||||
pixels[offset] = 255
|
||||
pixels[offset + 1] = 255
|
||||
pixels[offset + 2] = 255
|
||||
pixels[offset + 3] = Math.round(opacity * coverageX * coverageY * 255)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
function easeOut(progress: number) {
|
||||
const curve = (value: number, first: number, second: number) => {
|
||||
const inverse = 1 - value
|
||||
return 3 * inverse * inverse * value * first + 3 * inverse * value * value * second + value * value * value
|
||||
}
|
||||
const parameter = Array.from({ length: 16 }).reduce<[number, number]>(
|
||||
(range) => {
|
||||
const middle = (range[0] + range[1]) / 2
|
||||
return curve(middle, 0, 0.58) < progress ? [middle, range[1]] : [range[0], middle]
|
||||
},
|
||||
[0, 1],
|
||||
)
|
||||
return curve((parameter[0] + parameter[1]) / 2, 0, 1)
|
||||
}
|
||||
|
||||
function chunk(type: string, data: Buffer) {
|
||||
const name = Buffer.from(type)
|
||||
const result = Buffer.alloc(data.length + 12)
|
||||
result.writeUInt32BE(data.length, 0)
|
||||
name.copy(result, 4)
|
||||
data.copy(result, 8)
|
||||
result.writeUInt32BE(crc32(Buffer.concat([name, data])), data.length + 8)
|
||||
return result
|
||||
}
|
||||
|
||||
function crc32(data: Buffer) {
|
||||
return (
|
||||
(data.reduce<number>((crc, value) => crcTable[(crc ^ value) & 0xff] ^ (crc >>> 8), 0xffffffff) ^ 0xffffffff) >>> 0
|
||||
)
|
||||
}
|
||||
@@ -418,6 +418,10 @@
|
||||
white-space: pre-wrap;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
[data-slot="bash-prompt"] {
|
||||
user-select: none;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="edit-trigger"],
|
||||
|
||||
@@ -547,6 +547,12 @@ export function getToolInfo(
|
||||
title: i18n.t("ui.tool.shell"),
|
||||
subtitle: input.command,
|
||||
}
|
||||
case "execute":
|
||||
return {
|
||||
icon: "console",
|
||||
title: i18n.t("ui.tool.execute"),
|
||||
subtitle: input.code,
|
||||
}
|
||||
case "edit":
|
||||
return {
|
||||
icon: "code-lines",
|
||||
@@ -1574,6 +1580,7 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
|
||||
if (typeof value === "string" && value) return value
|
||||
return taskId()
|
||||
})
|
||||
const toolError = createMemo(() => partError(part(), i18n.t("ui.toolErrorCard.failed")))
|
||||
|
||||
const render = createMemo(() => ToolRegistry.render(part().tool) ?? GenericTool)
|
||||
const controlledOpen = () => (props.onToolOpenChange ? (props.toolOpen ?? props.defaultOpen) : undefined)
|
||||
@@ -1583,7 +1590,7 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
|
||||
<Show when={!hideQuestion()}>
|
||||
<div data-component="tool-part-wrapper" data-timeline-part-id={part().id}>
|
||||
<Switch>
|
||||
<Match when={part().state.status === "error" && (part().state as any).error}>
|
||||
<Match when={toolError()}>
|
||||
{(error) => {
|
||||
const cleaned = error().replace("Error: ", "")
|
||||
if (part().tool === "question" && cleaned.includes("dismissed this question")) {
|
||||
@@ -1644,6 +1651,26 @@ PART_MAPPING["tool"] = function ToolPartDisplay(props) {
|
||||
)
|
||||
}
|
||||
|
||||
function partError(part: ToolPart, fallback: string) {
|
||||
if (part.state.status === "error") return part.state.error
|
||||
if (part.tool !== "execute" || !("metadata" in part.state)) return undefined
|
||||
const calls = part.state.metadata?.toolCalls
|
||||
const failed =
|
||||
part.state.metadata?.error === true ||
|
||||
(Array.isArray(calls) &&
|
||||
calls.some(
|
||||
(call) =>
|
||||
call !== null &&
|
||||
typeof call === "object" &&
|
||||
!Array.isArray(call) &&
|
||||
"status" in call &&
|
||||
call.status === "error",
|
||||
))
|
||||
if (!failed) return undefined
|
||||
if ("output" in part.state && typeof part.state.output === "string" && part.state.output) return part.state.output
|
||||
return fallback
|
||||
}
|
||||
|
||||
export function MessageDivider(props: { label: string }) {
|
||||
return (
|
||||
<div data-component="compaction-part">
|
||||
@@ -2000,17 +2027,25 @@ ToolRegistry.register({
|
||||
const title = createMemo(() => agent().name ?? i18n.t("ui.tool.agent.default"))
|
||||
const tone = createMemo(() => agent().color)
|
||||
const v2Tone = createMemo(() => agent().v2Color)
|
||||
const background = createMemo(() => {
|
||||
if (props.tool === "task") return props.metadata.background === true
|
||||
return props.status === "completed" && props.metadata.status === "running"
|
||||
})
|
||||
const subtitle = createMemo(() => {
|
||||
const value =
|
||||
typeof props.input.description === "string" && props.input.description
|
||||
? props.input.description
|
||||
: childSessionId()
|
||||
if (!value) return value
|
||||
if (props.input.background === true || props.metadata.background === true || props.metadata.status === "running")
|
||||
return `${value} (background)`
|
||||
if (background()) return `${value} (background)`
|
||||
return value
|
||||
})
|
||||
const running = createMemo(() => props.status === "pending" || props.status === "running")
|
||||
const running = createMemo(() => {
|
||||
if (props.status === "pending" || props.status === "running") return true
|
||||
const id = childSessionId()
|
||||
if (!id) return false
|
||||
return (data.store.session_status[id]?.type ?? "idle") !== "idle"
|
||||
})
|
||||
|
||||
const href = createMemo(() => sessionLink(childSessionId(), data.sessionHref))
|
||||
const clickable = createMemo(() => !!(childSessionId() && (data.navigateToSession || href())))
|
||||
@@ -2096,6 +2131,84 @@ ToolRegistry.register({
|
||||
|
||||
ToolRegistry.register({ name: "subagent", render: ToolRegistry.render("task") })
|
||||
|
||||
function ConsoleOutput(props: { copy: string; children: JSX.Element }) {
|
||||
const i18n = useI18n()
|
||||
const [copied, setCopied] = createSignal(false)
|
||||
|
||||
const copy = async () => {
|
||||
if (!props.copy) return
|
||||
if (!(await writeClipboard(props.copy))) return
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
}
|
||||
|
||||
return (
|
||||
<div data-component="bash-output" dir="ltr">
|
||||
<div data-slot="bash-copy">
|
||||
<TooltipV2 value={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.message.copy")} placement="top">
|
||||
<IconButtonV2
|
||||
icon={<IconV2 name={copied() ? "check" : "outline-copy"} size="small" />}
|
||||
size="normal"
|
||||
variant="ghost-muted"
|
||||
onMouseDown={(event) => event.preventDefault()}
|
||||
onClick={copy}
|
||||
aria-label={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.message.copy")}
|
||||
/>
|
||||
</TooltipV2>
|
||||
</div>
|
||||
<div
|
||||
data-slot="bash-scroll"
|
||||
data-scrollable
|
||||
tabIndex={0}
|
||||
role="region"
|
||||
aria-label={i18n.t("ui.scrollView.ariaLabel")}
|
||||
>
|
||||
<pre data-slot="bash-pre">
|
||||
<code>{props.children}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
ToolRegistry.register({
|
||||
name: "execute",
|
||||
render(props) {
|
||||
const i18n = useI18n()
|
||||
const pending = () => props.status === "pending" || props.status === "streaming" || props.status === "running"
|
||||
const code = createMemo(() => (typeof props.input.code === "string" ? props.input.code : ""))
|
||||
const text = createMemo(() => {
|
||||
const output = stripAnsi(props.output ?? "").replace(/\r\n?/g, "\n")
|
||||
return `${code()}${output ? "\n\n" + output : ""}`
|
||||
})
|
||||
const sawPending = pending()
|
||||
return (
|
||||
<BasicTool
|
||||
{...props}
|
||||
icon="console"
|
||||
allowOpenWhilePending
|
||||
trigger={(open) => (
|
||||
<div data-slot="basic-tool-tool-info-structured">
|
||||
<span data-slot="basic-tool-tool-indicator">
|
||||
<Icon name="console" size="small" />
|
||||
</span>
|
||||
<div data-slot="basic-tool-tool-info-main">
|
||||
<span data-slot="basic-tool-tool-title">
|
||||
<TextShimmer text={i18n.t("ui.tool.execute")} active={pending()} />
|
||||
</span>
|
||||
<Show when={!open() && code()}>
|
||||
<ShellSubmessage text={code()} animate={sawPending} />
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<ConsoleOutput copy={text()}>{text()}</ConsoleOutput>
|
||||
</BasicTool>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
ToolRegistry.register({
|
||||
name: "shell",
|
||||
render(props) {
|
||||
@@ -2103,22 +2216,11 @@ ToolRegistry.register({
|
||||
const pending = () =>
|
||||
props.status === "pending" || props.status === "running" || props.metadata.status === "running"
|
||||
const sawPending = pending()
|
||||
const command = () => props.input.command ?? props.metadata.command ?? ""
|
||||
const text = createMemo(() => {
|
||||
const cmd = props.input.command ?? props.metadata.command ?? ""
|
||||
const out = stripAnsi(props.output || props.metadata.output || "").replace(/\r\n?/g, "\n")
|
||||
return `$ ${cmd}${out ? "\n\n" + out : ""}`
|
||||
return `${command()}${out ? "\n\n" + out : ""}`
|
||||
})
|
||||
const [copied, setCopied] = createSignal(false)
|
||||
|
||||
const handleCopy = async () => {
|
||||
const content = text()
|
||||
if (!content) return
|
||||
if (await writeClipboard(content)) {
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<BasicTool
|
||||
{...props}
|
||||
@@ -2137,31 +2239,12 @@ ToolRegistry.register({
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<div data-component="bash-output" dir="ltr">
|
||||
<div data-slot="bash-copy">
|
||||
<TooltipV2 value={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.message.copy")} placement="top">
|
||||
<IconButtonV2
|
||||
icon={<IconV2 name={copied() ? "check" : "outline-copy"} size="small" />}
|
||||
size="normal"
|
||||
variant="ghost-muted"
|
||||
onMouseDown={(e) => e.preventDefault()}
|
||||
onClick={handleCopy}
|
||||
aria-label={copied() ? i18n.t("ui.message.copied") : i18n.t("ui.message.copy")}
|
||||
/>
|
||||
</TooltipV2>
|
||||
</div>
|
||||
<div
|
||||
data-slot="bash-scroll"
|
||||
data-scrollable
|
||||
tabIndex={0}
|
||||
role="region"
|
||||
aria-label={i18n.t("ui.scrollView.ariaLabel")}
|
||||
>
|
||||
<pre data-slot="bash-pre">
|
||||
<code>{text()}</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<ConsoleOutput copy={command()}>
|
||||
<span data-slot="bash-prompt" aria-hidden="true">
|
||||
{"$ "}
|
||||
</span>
|
||||
{text()}
|
||||
</ConsoleOutput>
|
||||
</BasicTool>
|
||||
)
|
||||
},
|
||||
@@ -2637,21 +2720,36 @@ ToolRegistry.register({
|
||||
name: "skill",
|
||||
render(props) {
|
||||
const i18n = useI18n()
|
||||
const title = createMemo(() => skillToolName(props.input, props.metadata) || i18n.t("ui.tool.skill"))
|
||||
const name = createMemo(() => skillToolName(props.input, props.metadata))
|
||||
const running = createMemo(() => props.status === "pending" || props.status === "running")
|
||||
|
||||
const titleContent = () => <TextShimmer text={title()} active={running()} />
|
||||
|
||||
const trigger = () => (
|
||||
<div data-slot="basic-tool-tool-info-structured">
|
||||
<div data-slot="basic-tool-tool-info-main">
|
||||
<span data-slot="basic-tool-tool-title" class="capitalize agent-title">
|
||||
{titleContent()}
|
||||
</span>
|
||||
</div>
|
||||
<div data-slot="skill-tool-trigger" class="flex min-w-0 items-center gap-1.5">
|
||||
<Icon name="post-skill" size="small" class="shrink-0 text-v2-icon-icon-muted" />
|
||||
<span
|
||||
data-slot="skill-tool-label"
|
||||
class="shrink-0 text-[13px] font-[530] leading-5 tracking-[-0.04px] text-v2-text-text-muted"
|
||||
>
|
||||
{i18n.t("ui.tool.skill")}
|
||||
</span>
|
||||
<Show when={name()}>
|
||||
{(name) => (
|
||||
<>
|
||||
<span data-slot="skill-tool-separator" aria-hidden="true" class="shrink-0 text-v2-text-text-muted">
|
||||
·
|
||||
</span>
|
||||
<TextShimmer
|
||||
as="bdi"
|
||||
text={name()}
|
||||
active={running()}
|
||||
class="min-w-0 truncate text-[13px] font-[440] leading-5 tracking-[-0.04px] text-v2-text-text-muted"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</Show>
|
||||
</div>
|
||||
)
|
||||
|
||||
return <BasicTool icon="brain" status={props.status} trigger={trigger()} hideDetails />
|
||||
return <BasicTool icon="post-skill" status={props.status} trigger={trigger()} hideDetails />
|
||||
},
|
||||
})
|
||||
|
||||
@@ -71,8 +71,9 @@ describe("partDefaultOpen", () => {
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
test("preserves shell defaults", () => {
|
||||
test("applies shell defaults to console tools", () => {
|
||||
expect(partDefaultOpen(tool("shell", {}), true, false)).toBe(true)
|
||||
expect(partDefaultOpen(tool("execute", {}), true, false)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ function deletionOnly(part: ToolPart) {
|
||||
|
||||
export function partDefaultOpen(part: PartType, shell = false, edit = false): boolean | undefined {
|
||||
if (part.type !== "tool") return undefined
|
||||
if (part.tool === "bash" || part.tool === "shell") return shell
|
||||
if (part.tool === "bash" || part.tool === "shell" || part.tool === "execute") return shell
|
||||
if (part.tool === "edit" || part.tool === "write" || part.tool === "patch" || part.tool === "apply_patch") {
|
||||
if (!edit) return false
|
||||
return !deletionOnly(part)
|
||||
|
||||
@@ -54,6 +54,7 @@ export function ToolErrorCard(props: ToolErrorCardProps) {
|
||||
websearch: "ui.tool.websearch",
|
||||
bash: "ui.tool.shell",
|
||||
shell: "ui.tool.shell",
|
||||
execute: "ui.tool.execute",
|
||||
patch: "ui.tool.patch",
|
||||
apply_patch: "ui.tool.patch",
|
||||
question: "ui.tool.questions",
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -1,875 +1,25 @@
|
||||
[data-component="session-progress-indicator-v2"] {
|
||||
--_duration: 1200ms;
|
||||
display: block;
|
||||
flex-shrink: 0;
|
||||
color: var(--v2-icon-icon-muted, #808080);
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot] {
|
||||
[data-component="session-progress-indicator-v2"] [data-frame-content] {
|
||||
image-rendering: pixelated;
|
||||
image-rendering: crisp-edges;
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-reduced-motion] {
|
||||
display: none;
|
||||
fill: currentColor;
|
||||
opacity: 0.2;
|
||||
animation-duration: var(--_duration);
|
||||
animation-timing-function: ease-out;
|
||||
animation-iteration-count: infinite;
|
||||
animation-fill-mode: both;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-0 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="0"] {
|
||||
animation-name: session-progress-indicator-v2-dot-0;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-5 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="5"] {
|
||||
animation-name: session-progress-indicator-v2-dot-5;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-10 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 1;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="10"] {
|
||||
animation-name: session-progress-indicator-v2-dot-10;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-15 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="15"] {
|
||||
animation-name: session-progress-indicator-v2-dot-15;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-20 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="20"] {
|
||||
animation-name: session-progress-indicator-v2-dot-20;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-1 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="1"] {
|
||||
animation-name: session-progress-indicator-v2-dot-1;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-6 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="6"] {
|
||||
animation-name: session-progress-indicator-v2-dot-6;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-11 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 1;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="11"] {
|
||||
animation-name: session-progress-indicator-v2-dot-11;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-16 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="16"] {
|
||||
animation-name: session-progress-indicator-v2-dot-16;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-21 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="21"] {
|
||||
animation-name: session-progress-indicator-v2-dot-21;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-2 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="2"] {
|
||||
animation-name: session-progress-indicator-v2-dot-2;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-7 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="7"] {
|
||||
animation-name: session-progress-indicator-v2-dot-7;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-12 {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
25% {
|
||||
opacity: 1;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
75% {
|
||||
opacity: 1;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="12"] {
|
||||
animation-name: session-progress-indicator-v2-dot-12;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-17 {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="17"] {
|
||||
animation-name: session-progress-indicator-v2-dot-17;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-22 {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="22"] {
|
||||
animation-name: session-progress-indicator-v2-dot-22;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-3 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="3"] {
|
||||
animation-name: session-progress-indicator-v2-dot-3;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-8 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="8"] {
|
||||
animation-name: session-progress-indicator-v2-dot-8;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-13 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 1;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="13"] {
|
||||
animation-name: session-progress-indicator-v2-dot-13;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-18 {
|
||||
0% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="18"] {
|
||||
animation-name: session-progress-indicator-v2-dot-18;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-23 {
|
||||
0% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="23"] {
|
||||
animation-name: session-progress-indicator-v2-dot-23;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-4 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="4"] {
|
||||
animation-name: session-progress-indicator-v2-dot-4;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-9 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="9"] {
|
||||
animation-name: session-progress-indicator-v2-dot-9;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-14 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 1;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="14"] {
|
||||
animation-name: session-progress-indicator-v2-dot-14;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-19 {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.75;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="19"] {
|
||||
animation-name: session-progress-indicator-v2-dot-19;
|
||||
}
|
||||
|
||||
@keyframes session-progress-indicator-v2-dot-24 {
|
||||
0% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
12.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
25% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
37.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
50% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
62.5% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
75% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
87.5% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="24"] {
|
||||
animation-name: session-progress-indicator-v2-dot-24;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
[data-component="session-progress-indicator-v2"] [data-dot] {
|
||||
animation: none;
|
||||
[data-component="session-progress-indicator-v2"] [data-frame-content] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-component="session-progress-indicator-v2"] [data-dot="12"] {
|
||||
opacity: 1;
|
||||
[data-component="session-progress-indicator-v2"] [data-reduced-motion] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import { SessionProgressIndicatorV2 } from "./session-progress-indicator-v2"
|
||||
import { createSignal, onCleanup, onMount } from "solid-js"
|
||||
|
||||
const docs = `### Overview
|
||||
Animated 5×5 dot grid loader for in-progress session state.
|
||||
@@ -10,7 +11,7 @@ Derived from Figma \`_sessionProgressIndicator\` with 8-frame rotation.
|
||||
- Accepts standard SVG props.
|
||||
|
||||
### Behavior
|
||||
- CSS keyframes drive per-dot opacity across 8 frames (1.2s loop).
|
||||
- A shared, pre-rendered alpha mask preserves the smooth opacity changes between 8 key poses (1.2s loop).
|
||||
- Center dot stays at full opacity throughout the cycle.
|
||||
|
||||
### Accessibility
|
||||
@@ -48,6 +49,43 @@ export const Sizes = {
|
||||
),
|
||||
}
|
||||
|
||||
export const StressTest = {
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
},
|
||||
render: () => <StressGrid />,
|
||||
}
|
||||
|
||||
function StressGrid() {
|
||||
const measure = () => ({
|
||||
columns: Math.max(1, Math.floor((window.innerWidth + 4) / 20)),
|
||||
rows: Math.max(1, Math.floor((window.innerHeight + 4) / 20)),
|
||||
})
|
||||
const [grid, setGrid] = createSignal(measure())
|
||||
const resize = () => setGrid(measure())
|
||||
onMount(() => window.addEventListener("resize", resize))
|
||||
onCleanup(() => window.removeEventListener("resize", resize))
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
overflow: "hidden",
|
||||
gap: "4px",
|
||||
"grid-template-columns": `repeat(${grid().columns}, 16px)`,
|
||||
"grid-template-rows": `repeat(${grid().rows}, 16px)`,
|
||||
"place-content": "center",
|
||||
}}
|
||||
>
|
||||
{Array.from({ length: grid().columns * grid().rows }, () => (
|
||||
<SessionProgressIndicatorV2 />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export const OnDark = {
|
||||
render: () => (
|
||||
<div
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import { For, splitProps, type ComponentProps } from "solid-js"
|
||||
import { createUniqueId, splitProps, type ComponentProps } from "solid-js"
|
||||
import "./session-progress-indicator-v2.css"
|
||||
|
||||
const grid = 5
|
||||
const dot = 2
|
||||
const gap = 1
|
||||
const origin = 1.5
|
||||
const dots = Array.from({ length: grid * grid }, (_, index) => ({
|
||||
index,
|
||||
x: origin + (index % grid) * (dot + gap),
|
||||
y: origin + Math.floor(index / grid) * (dot + gap),
|
||||
}))
|
||||
const frames = new URL("./session-progress-indicator-v2-1x.png", import.meta.url).href
|
||||
const dots = Array.from({ length: 25 }, (_, index) => {
|
||||
const x = 1.5 + (index % 5) * 3
|
||||
const y = 1.5 + Math.floor(index / 5) * 3
|
||||
return `M${x} ${y}h2v2h-2z`
|
||||
}).join("")
|
||||
|
||||
export function SessionProgressIndicatorV2(props: ComponentProps<"svg">) {
|
||||
const [local, rest] = splitProps(props, ["class", "classList", "width", "height"])
|
||||
const id = createUniqueId()
|
||||
const filter = `session-progress-indicator-filter-${id}`
|
||||
const clip = `session-progress-indicator-clip-${id}`
|
||||
return (
|
||||
<svg
|
||||
{...rest}
|
||||
@@ -26,7 +26,26 @@ export function SessionProgressIndicatorV2(props: ComponentProps<"svg">) {
|
||||
data-component="session-progress-indicator-v2"
|
||||
aria-hidden={rest["aria-hidden"] ?? "true"}
|
||||
>
|
||||
<For each={dots}>{(cell) => <rect data-dot={cell.index} x={cell.x} y={cell.y} width={dot} height={dot} />}</For>
|
||||
<defs>
|
||||
<filter id={filter} filterUnits="userSpaceOnUse" x={0} y={0} width={16} height={16}>
|
||||
<feFlood flood-color="currentColor" result="color" />
|
||||
<feComposite in="color" in2="SourceAlpha" operator="in" />
|
||||
</filter>
|
||||
<clipPath id={clip}>
|
||||
<path d={dots} />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<image
|
||||
data-frame-content
|
||||
href={frames}
|
||||
x={0}
|
||||
y={0}
|
||||
width={16}
|
||||
height={16}
|
||||
filter={`url(#${filter})`}
|
||||
clip-path={`url(#${clip})`}
|
||||
/>
|
||||
<rect data-reduced-motion x={7.5} y={7.5} width={2} height={2} />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -550,7 +550,7 @@ function App(props: { pair?: DialogPairCredentials }) {
|
||||
const offSelectionKeys = keymap.intercept(
|
||||
"key",
|
||||
({ event }) => {
|
||||
if (config.data.terminal?.copy_on_select ?? process.platform !== "win32") return
|
||||
if ((config.data.terminal?.copy ?? (process.platform === "win32" ? "manual" : "select")) === "select") return
|
||||
Selection.handleSelectionKey(renderer, toast, event, clipboard)
|
||||
},
|
||||
{ priority: 1 },
|
||||
@@ -571,7 +571,8 @@ function App(props: { pair?: DialogPairCredentials }) {
|
||||
renderer.clearSelection()
|
||||
}
|
||||
const terminalTitleEnabled = () => config.data.terminal?.title ?? true
|
||||
const copyOnSelectEnabled = () => config.data.terminal?.copy_on_select ?? process.platform !== "win32"
|
||||
const copyOnSelectEnabled = () =>
|
||||
(config.data.terminal?.copy ?? (process.platform === "win32" ? "manual" : "select")) === "select"
|
||||
const pasteSummaryEnabled = () => config.data.prompt?.paste !== "full"
|
||||
const tabsVertical = () =>
|
||||
config.data.tabs.layout === "vertical" && sessionTabsFitVertically(dimensions().width, preferredTabsWidth())
|
||||
|
||||
@@ -274,12 +274,11 @@ export const settings: Setting[] = [
|
||||
keywords: ["terminal title", "tab title"],
|
||||
},
|
||||
{
|
||||
title: "Copy on select",
|
||||
title: "Copy behavior",
|
||||
category: "Terminal",
|
||||
path: ["terminal", "copy_on_select"],
|
||||
default: process.platform !== "win32",
|
||||
values: [false, true],
|
||||
labels: ["off", "on"],
|
||||
path: ["terminal", "copy"],
|
||||
default: process.platform === "win32" ? "manual" : "select",
|
||||
values: ["manual", "select"],
|
||||
keywords: ["selection", "clipboard"],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -103,7 +103,9 @@ export const Info = Schema.Struct({
|
||||
terminal: Schema.optional(
|
||||
Schema.Struct({
|
||||
title: Schema.optional(Schema.Boolean).annotate({ description: "Update the terminal window title" }),
|
||||
copy_on_select: Schema.optional(Schema.Boolean).annotate({ description: "Copy selected terminal text" }),
|
||||
copy: Schema.optional(Schema.Literals(["manual", "select"])).annotate({
|
||||
description: "Copy text manually or immediately after selecting it",
|
||||
}),
|
||||
}),
|
||||
).annotate({ description: "Terminal integration settings" }),
|
||||
prompt: Schema.optional(
|
||||
|
||||
@@ -2930,7 +2930,7 @@ function Shell(props: ToolProps) {
|
||||
const permission = useToolPermission(() => props.part)
|
||||
const color = createMemo(() => (permission() ? theme.text.feedback.warning.default : theme.text.default))
|
||||
const shellID = createMemo(() => stringValue(props.metadata.shellID))
|
||||
const background = createMemo(() => isBackgroundTool(props.metadata, props.part.state.status))
|
||||
const background = createMemo(() => Boolean(shellID()) && props.part.state.status !== "running")
|
||||
const backgroundRunning = createMemo(() => {
|
||||
const id = shellID()
|
||||
return Boolean(id && data.shell.get(id))
|
||||
@@ -3190,7 +3190,7 @@ function Subagent(props: ToolProps) {
|
||||
if (id) navigate({ type: "session", sessionID: id })
|
||||
}}
|
||||
status={
|
||||
isBackgroundTool(props.metadata, props.part.state.status) ? (
|
||||
isBackgroundSubagent(props.metadata, props.part.state.status) ? (
|
||||
<StatusBadge>Background</StatusBadge>
|
||||
) : undefined
|
||||
}
|
||||
@@ -3200,7 +3200,7 @@ function Subagent(props: ToolProps) {
|
||||
)
|
||||
}
|
||||
|
||||
export function isBackgroundTool(
|
||||
export function isBackgroundSubagent(
|
||||
metadata: Record<string, unknown>,
|
||||
status: SessionMessageAssistantTool["state"]["status"],
|
||||
) {
|
||||
|
||||
@@ -207,7 +207,8 @@ export function DialogProvider(props: ParentProps) {
|
||||
const toast = useToast()
|
||||
const clipboard = useClipboard()
|
||||
const config = useConfig()
|
||||
const copyOnSelectEnabled = () => config.data.terminal?.copy_on_select ?? process.platform !== "win32"
|
||||
const copyOnSelectEnabled = () =>
|
||||
(config.data.terminal?.copy ?? (process.platform === "win32" ? "manual" : "select")) === "select"
|
||||
|
||||
function copySelection() {
|
||||
const text = renderer.getSelection()?.getSelectedText()
|
||||
|
||||
@@ -4,7 +4,7 @@ import { testRender, type JSX } from "@opentui/solid"
|
||||
import {
|
||||
InlineToolRow,
|
||||
executeCallSummary,
|
||||
isBackgroundTool,
|
||||
isBackgroundSubagent,
|
||||
parseApplyPatchFiles,
|
||||
parseDiagnostics,
|
||||
parseQuestionAnswers,
|
||||
@@ -214,12 +214,11 @@ describe("TUI inline tool wrapping", () => {
|
||||
).toEqual([{ message: "valid", range: { start: { line: 2, character: 3 } } }])
|
||||
})
|
||||
|
||||
test("labels only detached or async tools as background", () => {
|
||||
expect(isBackgroundTool({ status: "running" }, "running")).toBeFalse()
|
||||
expect(isBackgroundTool({ status: "running" }, "completed")).toBeTrue()
|
||||
expect(isBackgroundTool({ status: "running" }, "error")).toBeFalse()
|
||||
expect(isBackgroundTool({ status: "completed" }, "completed")).toBeFalse()
|
||||
expect(isBackgroundTool({}, "completed")).toBeFalse()
|
||||
test("labels only detached or async subagents as background", () => {
|
||||
expect(isBackgroundSubagent({ status: "running" }, "running")).toBeFalse()
|
||||
expect(isBackgroundSubagent({ status: "running" }, "completed")).toBeTrue()
|
||||
expect(isBackgroundSubagent({ status: "running" }, "error")).toBeFalse()
|
||||
expect(isBackgroundSubagent({ status: "completed" }, "completed")).toBeFalse()
|
||||
})
|
||||
|
||||
test("snapshots consecutive grep, glob, and read rows at a narrow width", async () => {
|
||||
|
||||
@@ -62,6 +62,16 @@ test("shows the new session location default in settings", () => {
|
||||
expect(settings.find((setting) => setting.path.join(".") === "session.new_location")?.default).toBe("launch")
|
||||
})
|
||||
|
||||
test("validates terminal copy behavior", () => {
|
||||
expect(decodeInfo({ terminal: { copy: "manual" } })).toEqual({ terminal: { copy: "manual" } })
|
||||
expect(decodeInfo({ terminal: { copy: "select" } })).toEqual({ terminal: { copy: "select" } })
|
||||
expect(() => decodeInfo({ terminal: { copy: "always" } })).toThrow()
|
||||
|
||||
const setting = settings.find((setting) => setting.path.join(".") === "terminal.copy")
|
||||
expect(setting?.values).toEqual(["manual", "select"])
|
||||
expect(setting?.default).toBe(process.platform === "win32" ? "manual" : "select")
|
||||
})
|
||||
|
||||
test("uses command IDs as keybind keys", () => {
|
||||
const config = resolve({ keybinds: { "session.list": "ctrl+l" } }, { terminalSuspend: true })
|
||||
|
||||
|
||||
@@ -158,6 +158,7 @@ const source = {
|
||||
"ui.tool.websearch": "Web Search",
|
||||
"ui.tool.websearch.provider": "{{provider}} Web Search",
|
||||
"ui.tool.shell": "Shell",
|
||||
"ui.tool.execute": "Execute",
|
||||
"ui.tool.patch": "Patch",
|
||||
"ui.tool.questions": "Questions",
|
||||
"ui.tool.questions.numbered": "Questions {{number}}",
|
||||
|
||||
@@ -258,7 +258,7 @@ const makeCrossSpawnSpawner = Effect.gen(function* () {
|
||||
return { stdout, stderr, all: Stream.merge(stdout, stderr) }
|
||||
}
|
||||
|
||||
const spawn = (command: ChildProcess.StandardCommand, opts: NodeChildProcess.SpawnOptions) =>
|
||||
const launchProcess = (command: ChildProcess.StandardCommand, opts: NodeChildProcess.SpawnOptions) =>
|
||||
Effect.callback<readonly [NodeChildProcess.ChildProcess, ExitSignal], PlatformError.PlatformError>((resume) => {
|
||||
const signal = Deferred.makeUnsafe<readonly [code: number | null, signal: NodeJS.Signals | null]>()
|
||||
const proc = launch(command.command, command.args, opts)
|
||||
@@ -283,6 +283,14 @@ const makeCrossSpawnSpawner = Effect.gen(function* () {
|
||||
})
|
||||
})
|
||||
|
||||
const spawn = Effect.fnUntraced(function* (
|
||||
command: ChildProcess.StandardCommand,
|
||||
opts: NodeChildProcess.SpawnOptions,
|
||||
) {
|
||||
yield* Effect.logInfo("spawning process", { command: command.command, args: command.args, cwd: opts.cwd })
|
||||
return yield* launchProcess(command, opts)
|
||||
})
|
||||
|
||||
const killGroup = (
|
||||
command: ChildProcess.StandardCommand,
|
||||
proc: NodeChildProcess.ChildProcess,
|
||||
|
||||
@@ -23,21 +23,27 @@ export default defineConfig({
|
||||
dir: "packages/www",
|
||||
},
|
||||
theme: {
|
||||
background: { dark: "#131010" },
|
||||
background: { dark: "#000000" },
|
||||
fonts: {
|
||||
body: "ibm-plex-mono",
|
||||
display: "ibm-plex-mono",
|
||||
mono: "ibm-plex-mono",
|
||||
body: { name: "Monaspace Neon", provider: "fontsource", weights: [400, 500, 600, 700], fallback: "mono" },
|
||||
display: { name: "Monaspace Neon", provider: "fontsource", weights: [400, 500, 600, 700], fallback: "mono" },
|
||||
mono: { name: "Monaspace Neon", provider: "fontsource", weights: [400, 500, 600, 700], fallback: "mono" },
|
||||
},
|
||||
mode: "dark",
|
||||
},
|
||||
navigation: {
|
||||
tabs: [
|
||||
{ label: "Docs", path: "/" },
|
||||
{ label: "CLI", path: "/cli" },
|
||||
{ label: "Build", path: "/build" },
|
||||
{ label: "API", path: "/api" },
|
||||
],
|
||||
},
|
||||
markdown: {
|
||||
code: {
|
||||
icons: false,
|
||||
},
|
||||
},
|
||||
openapi: {
|
||||
enabled: true,
|
||||
route: "/api",
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import { defineComponents } from "blume"
|
||||
import Breadcrumbs from "./components/Breadcrumbs.astro"
|
||||
import ThemeTokens from "./snippets/generated/theme-tokens.mdx"
|
||||
|
||||
export default defineComponents({
|
||||
layout: {
|
||||
Breadcrumbs,
|
||||
},
|
||||
mdx: {
|
||||
ThemeTokens,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
---
|
||||
---
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Agents"
|
||||
description: ""
|
||||
---
|
||||
|
||||
Agents combine a system prompt, model preference, tool permissions, and display
|
||||
@@ -18,7 +17,7 @@ Markdown files.
|
||||
| **Explore** (`explore`) | `subagent` | Read-only code and web exploration using `read`, `glob`, `grep`, `webfetch`, and `websearch`. |
|
||||
|
||||
OpenCode also has hidden `compaction`, `title`, and `summary` system agents.
|
||||
They run internal maintenance tasks and are not selectable. There is no built-in
|
||||
They run internal maintenance tasks and are not available for direct use. There is no built-in
|
||||
`scout` agent in V2.
|
||||
|
||||
You can override a built-in agent with an entry of the same ID. Set
|
||||
@@ -50,17 +49,8 @@ An agent's `mode` controls where it can run:
|
||||
| `subagent` | Can run in a child session through the `subagent` tool, but cannot be selected as the main agent. |
|
||||
| `all` | Can be used either way. |
|
||||
|
||||
In the TUI, press <kbd>Tab</kbd> and <kbd>Shift</kbd>+<kbd>Tab</kbd> to cycle
|
||||
through visible primary and `all` agents, or use `/agents` to choose one.
|
||||
|
||||
Subagents run in child sessions with fresh context. A primary agent can invoke
|
||||
one with the `subagent` tool, either in the foreground or in the background.
|
||||
You can also `@` mention a visible subagent to ask the current agent to delegate
|
||||
work to it:
|
||||
|
||||
```text
|
||||
@explore find where authentication errors are handled
|
||||
```
|
||||
|
||||
The parent agent's `subagent` permission controls which agents it may launch.
|
||||
The child currently uses its own configured permissions, not a restricted copy
|
||||
@@ -179,11 +169,11 @@ The equivalent expanded form is:
|
||||
}
|
||||
```
|
||||
|
||||
The TUI uses this as the preferred model when the agent is selected. A child
|
||||
session uses its subagent's configured model, or inherits the parent session's
|
||||
model when none is configured. In the API, the session's selected model is
|
||||
stored separately; creating or switching a primary session with only an agent
|
||||
ID does not itself change that session model.
|
||||
This is the preferred model when the agent is activated. A child session uses
|
||||
its subagent's configured model, or inherits the parent session's model when
|
||||
none is configured. The session's selected model is stored separately;
|
||||
creating or switching a primary session with only an agent ID does not itself
|
||||
change that session model.
|
||||
|
||||
### `system`
|
||||
|
||||
@@ -241,9 +231,9 @@ user input resets the allowance.
|
||||
|
||||
### `hidden`
|
||||
|
||||
When `true`, removes the agent from normal selectors, `@` autocomplete, and the
|
||||
subagent catalog advertised to models. It is a visibility setting, not a
|
||||
security boundary.
|
||||
When `true`, removes the agent from normal agent listings, interactive
|
||||
discovery, and the subagent catalog advertised to models. It is a visibility
|
||||
setting, not a security boundary.
|
||||
|
||||
### `color`
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
---
|
||||
title: "Attachments"
|
||||
description: ""
|
||||
---
|
||||
|
||||
OpenCode can add local context to a prompt as text or image media. Current V2
|
||||
sessions make these attachment types visible to the model:
|
||||
Attachments add local context to a prompt as text or image media. Regardless
|
||||
of how a prompt is submitted, current V2 sessions make these attachment types
|
||||
visible to the model:
|
||||
|
||||
| Input | Model receives |
|
||||
| ----------------------- | -------------------------------------------------------------- |
|
||||
@@ -14,8 +14,8 @@ sessions make these attachment types visible to the model:
|
||||
|
||||
SVG files are treated as text, not image media. PDF, AVIF, BMP, audio, video,
|
||||
and other binary prompt attachments are not currently included in the model
|
||||
request. Some clients may let you select a PDF, but V2 does not yet make that
|
||||
PDF visible to the model.
|
||||
request. A client accepting a file does not mean its contents are visible to
|
||||
the model.
|
||||
|
||||
<Callout type="warning">
|
||||
Use a model that supports image input before attaching an image. OpenCode passes supported image media to the selected
|
||||
@@ -25,81 +25,25 @@ PDF visible to the model.
|
||||
|
||||
## Add attachments
|
||||
|
||||
### TUI
|
||||
Desktop and web clients provide **Attach file**, paste, and drag-and-drop controls for supported text and image files. The
|
||||
desktop file picker limits one selection to 20 MiB in total; the server also applies the per-attachment limit below.
|
||||
|
||||
Type `@` followed by a filename and select the result to attach a project file.
|
||||
This is the preferred way to add source code and other text files:
|
||||
Attachment controls and client-side limits depend on the interface. For programmatic submission, see the generated
|
||||
[API reference](/api).
|
||||
|
||||
```text
|
||||
Explain the error handling in @src/server.ts
|
||||
```
|
||||
|
||||
Paste an image from the clipboard with the configured paste key, `Ctrl+V` by
|
||||
default. You can also drag a supported image into a terminal that exposes the
|
||||
dropped file path to the TUI. The TUI reads PNG, JPEG, GIF, and WebP as image
|
||||
attachments; a dropped SVG is inserted as text.
|
||||
|
||||
### Desktop and web
|
||||
|
||||
Use **Attach file**, paste, or drag and drop. Attach UTF-8 text or a PNG, JPEG,
|
||||
GIF, or WebP image. The desktop file picker limits one selection to 20 MiB in
|
||||
total; the server also applies the per-attachment limit described below.
|
||||
|
||||
### CLI
|
||||
|
||||
Pass `--file` or `-f` to `opencode2 run`. Repeat the flag for multiple files:
|
||||
|
||||
```bash
|
||||
opencode2 run -f src/server.ts -f screenshot.png "Explain the failure"
|
||||
```
|
||||
|
||||
The run command accepts at most 100 file flags and reads at most 10 MiB per
|
||||
file. Use it for text files and the four supported image formats; other binary
|
||||
files do not become model context.
|
||||
|
||||
### API
|
||||
|
||||
The V2 prompt and command payloads accept a `files` array. Each item requires a
|
||||
`uri` and can include `name` and `description`:
|
||||
|
||||
```bash
|
||||
opencode2 api post /api/session/ses_example/prompt --data '{
|
||||
"text": "Review this file",
|
||||
"files": [
|
||||
{
|
||||
"uri": "file:///home/me/project/src/server.ts",
|
||||
"name": "server.ts",
|
||||
"description": "Request handler"
|
||||
}
|
||||
]
|
||||
}'
|
||||
```
|
||||
|
||||
Use an absolute `file:` URL for a file available to the server, or an inline
|
||||
data URL:
|
||||
|
||||
```json
|
||||
{
|
||||
"text": "What is wrong with this layout?",
|
||||
"files": [
|
||||
{
|
||||
"uri": "data:image/png;base64,<base64-data>",
|
||||
"name": "layout.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
HTTP and HTTPS attachment URLs are not supported. OpenCode materializes each
|
||||
attachment before admitting the prompt and rejects invalid URLs, unreadable
|
||||
paths, non-files other than directories, and attachments over 20 MiB decoded.
|
||||
For a text `file:` URL, optional positive `start` and `end` query parameters
|
||||
select one-based lines:
|
||||
V2 prompt and command inputs represent each attachment with a `uri` and
|
||||
optional `name` and `description`. Use an absolute `file:` URL for a file or
|
||||
directory available to the server, or an inline `data:` URL. For a text `file:`
|
||||
URL, optional positive `start` and `end` query parameters select one-based
|
||||
lines:
|
||||
|
||||
```text
|
||||
file:///home/me/project/src/server.ts?start=20&end=60
|
||||
```
|
||||
|
||||
HTTP and HTTPS attachment URLs are not supported. OpenCode materializes each
|
||||
attachment before admitting the prompt and rejects invalid URLs, unreadable
|
||||
paths, non-files other than directories, and attachments over 20 MiB decoded.
|
||||
The server infers the media type from the bytes. A supplied filename or data
|
||||
URL media type does not make an unsupported binary format model-visible.
|
||||
|
||||
@@ -131,9 +75,8 @@ All fields are optional:
|
||||
| `max_base64_bytes` | `5242880` | Maximum byte length of the Base64-encoded image string. Must be a positive integer. |
|
||||
|
||||
<Callout type="note">
|
||||
In the current V2 runtime, these settings apply to image media produced by the built-in `read` tool. Images attached
|
||||
directly through the TUI, desktop, web, CLI, or API bypass this normalization. Resize direct attachments before adding
|
||||
them if the provider requires smaller media.
|
||||
These settings apply to supported image media attached directly to prompts and images produced by the built-in `read`
|
||||
tool. If the image resizer is unavailable, OpenCode passes the original image through unchanged.
|
||||
</Callout>
|
||||
|
||||
The `read` tool recognizes PNG, JPEG, GIF, and WebP by their contents and will
|
||||
@@ -146,10 +89,8 @@ JPEG encodings until the Base64 limit is met. The resulting media type can
|
||||
therefore change to PNG or JPEG. If no encoding fits, the tool call fails.
|
||||
|
||||
When `auto_resize` is `false`, exceeding any limit fails the tool call without
|
||||
modifying the image. An image that cannot be decoded also fails. If the image
|
||||
resizer cannot be loaded, the `read` tool returns the
|
||||
original image instead, so these settings are processing limits rather than an
|
||||
upload or security boundary.
|
||||
modifying the image. An image that cannot be decoded also fails. If the image resizer cannot be loaded, OpenCode uses the
|
||||
original image instead, so these settings are processing limits rather than an upload or security boundary.
|
||||
|
||||
## Limits and provider behavior
|
||||
|
||||
|
||||
@@ -1,14 +1,8 @@
|
||||
---
|
||||
title: "Commands"
|
||||
description: ""
|
||||
---
|
||||
|
||||
Custom commands turn a named prompt template into a slash command. Type the
|
||||
command in the TUI, followed by any arguments:
|
||||
|
||||
```text
|
||||
/review src/auth
|
||||
```
|
||||
Custom commands turn a named prompt template into a reusable command.
|
||||
|
||||
## Configure with Markdown
|
||||
|
||||
@@ -20,7 +14,7 @@ OpenCode discovers `.md` command files in `commands/` directories:
|
||||
```
|
||||
|
||||
Files may be nested; for example, `.opencode/commands/team/review.md` defines
|
||||
`/team/review`. Files with other extensions, including `.mdx`, are not
|
||||
the command `team/review`. Files with other extensions, including `.mdx`, are not
|
||||
discovered.
|
||||
|
||||
```md title=".opencode/commands/review.md"
|
||||
@@ -39,12 +33,6 @@ precedence over global definitions, and a later definition can override a
|
||||
built-in or earlier command with the same name. Changes are reloaded
|
||||
automatically.
|
||||
|
||||
Run it with:
|
||||
|
||||
```text
|
||||
/review src/auth
|
||||
```
|
||||
|
||||
## Configure with JSON
|
||||
|
||||
Add commands under the `commands` key in any OpenCode JSON or JSONC
|
||||
@@ -70,8 +58,8 @@ Add commands under the `commands` key in any OpenCode JSON or JSONC
|
||||
| Field | Required | Behavior |
|
||||
| ------------- | --------- | ---------------------------------------------------------------------- |
|
||||
| `template` | JSON only | Prompt template. In a Markdown command, the file body supplies it. |
|
||||
| `description` | No | Text shown with the command in autocomplete. |
|
||||
| `agent` | No | Agent selected before the prompt runs. |
|
||||
| `description` | No | Text shown with the command in command listings and discovery. |
|
||||
| `agent` | No | Agent activated before the prompt runs. |
|
||||
| `model` | No | Model override in `provider/model` or `provider/model#variant` format. |
|
||||
| `subtask` | No | Accepted as a boolean, but currently has no execution effect in V2. |
|
||||
|
||||
@@ -90,10 +78,6 @@ description: Create a component
|
||||
Create a typed React component named $ARGUMENTS.
|
||||
```
|
||||
|
||||
```text
|
||||
/component Button
|
||||
```
|
||||
|
||||
Use `$1`, `$2`, and higher numbers for parsed positional arguments. Single and
|
||||
double quotes group text containing spaces and are removed during parsing.
|
||||
|
||||
@@ -105,10 +89,6 @@ description: Check one area with a specific focus
|
||||
Check $1. Focus on $2.
|
||||
```
|
||||
|
||||
```text
|
||||
/check src/auth "error handling and missing tests"
|
||||
```
|
||||
|
||||
The highest-numbered positional placeholder present in the template consumes
|
||||
that argument and all remaining arguments. For example, if a template contains
|
||||
only `$1`, then `$1` receives the full parsed argument list. Missing positions
|
||||
@@ -152,10 +132,10 @@ Running a command evaluates its arguments and shell blocks, submits the result
|
||||
as a durable user prompt in the current session, and schedules normal model
|
||||
execution.
|
||||
|
||||
If `agent` is set, it overrides the agent selected when the command was
|
||||
invoked and becomes the session's active agent. If `model` is set, it overrides
|
||||
the model. Otherwise, a model configured on the command's agent takes
|
||||
precedence over the model selected at invocation.
|
||||
If `agent` is set, it overrides the active agent when the command is invoked
|
||||
and becomes the session's active agent. If `model` is set, it overrides the
|
||||
model. Otherwise, a model configured on the command's agent takes precedence
|
||||
over the model active at invocation.
|
||||
|
||||
Although `subtask` is accepted in JSON and frontmatter, V2 currently ignores
|
||||
it: commands run in the current session and do not create a child session.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Compaction"
|
||||
description: ""
|
||||
---
|
||||
|
||||
Compaction replaces the active model context from an older part of a session
|
||||
@@ -34,14 +33,8 @@ second overflow after recovery is returned as an error.
|
||||
|
||||
## Manual compaction
|
||||
|
||||
In the TUI, run:
|
||||
|
||||
```text
|
||||
/compact
|
||||
```
|
||||
|
||||
`/summarize` is an alias. The default keybind is `<leader>c`, configured as
|
||||
`session_compact`.
|
||||
Manual compaction is available through session interfaces. See the generated [API reference](/api) for the server
|
||||
operation.
|
||||
|
||||
A manual request is durably admitted and wakes the session runner. It can
|
||||
compact short histories that would not trigger automatic compaction. If the
|
||||
@@ -50,27 +43,10 @@ steered or queued prompts are promoted. Repeated requests while one is pending
|
||||
coalesce into that pending request. Whether compaction completes or fails, the
|
||||
barrier is then settled so later prompts can proceed.
|
||||
|
||||
The CLI has no separate `compact` subcommand. Use the TUI command or the server
|
||||
API. For example:
|
||||
|
||||
```bash
|
||||
opencode2 api v2.session.compact \
|
||||
--param sessionID=ses_example \
|
||||
--data '{}'
|
||||
```
|
||||
|
||||
The equivalent raw request is:
|
||||
|
||||
```bash
|
||||
opencode2 api post /api/session/ses_example/compact --data '{}'
|
||||
```
|
||||
|
||||
`POST /api/session/:sessionID/compact` returns the admitted compaction input;
|
||||
it does not wait for summary generation. Clients can call
|
||||
`client.session.compact({ sessionID })` and then wait for the session or follow
|
||||
the `session.compaction.*` events. Supplying an optional message `id` makes an
|
||||
exact retry idempotent, but reusing an ID owned by another record returns a
|
||||
conflict.
|
||||
The server operation returns the admitted compaction input; it does not wait
|
||||
for summary generation. Clients can then wait for the session or follow the
|
||||
`session.compaction.*` events. Supplying an optional message `id` makes an exact
|
||||
retry idempotent, but reusing an ID owned by another record returns a conflict.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Formatters"
|
||||
description: ""
|
||||
---
|
||||
|
||||
OpenCode V2 accepts formatter configuration, but it does not yet include a
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Instructions"
|
||||
description: ""
|
||||
---
|
||||
|
||||
Instructions are privileged context that guide an agent throughout a session.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "LSP"
|
||||
description: ""
|
||||
---
|
||||
|
||||
Language Server Protocol (LSP) integrations can provide code diagnostics,
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "MCP servers"
|
||||
description: ""
|
||||
---
|
||||
|
||||
OpenCode can connect to [Model Context Protocol](https://modelcontextprotocol.io/) servers and make their tools, prompts, and instructions available to agents. MCP tools consume model context, so enable only the servers you need.
|
||||
@@ -130,21 +129,8 @@ For a server that supports dynamic client registration, only the remote server i
|
||||
}
|
||||
```
|
||||
|
||||
When the server reports that it needs authentication, run `/connect` in the TUI:
|
||||
|
||||
```text
|
||||
/connect
|
||||
```
|
||||
|
||||
Select the MCP server under **Services**, then complete the browser authorization flow.
|
||||
|
||||
You can also authenticate from the command line:
|
||||
|
||||
```bash
|
||||
opencode2 mcp auth sentry
|
||||
```
|
||||
|
||||
The CLI command prints the authorization URL and waits for the redirect to OpenCode's loopback callback server.
|
||||
When a server reports that it needs authentication, start its OAuth flow using
|
||||
an MCP management interface and complete authorization in the browser.
|
||||
|
||||
If the provider issued client credentials, configure them using V2's snake_case field names:
|
||||
|
||||
@@ -177,12 +163,6 @@ If the provider issued client credentials, configure them using V2's snake_case
|
||||
| `callback_port` | Local callback port, from `1` through `65535`. An available ephemeral port is used by default. |
|
||||
| `redirect_uri` | Pre-registered loopback redirect URI. Its path and port must reach the local callback listener. |
|
||||
|
||||
Remove stored credentials with:
|
||||
|
||||
```bash
|
||||
opencode2 mcp logout sentry
|
||||
```
|
||||
|
||||
## Timeouts
|
||||
|
||||
Timeouts are positive integer milliseconds. Configure defaults under `mcp.timeout`; a server's `timeout` fields override matching defaults.
|
||||
@@ -217,7 +197,7 @@ Timeouts are positive integer milliseconds. Configure defaults under `mcp.timeou
|
||||
|
||||
## Names and permissions
|
||||
|
||||
OpenCode combines the server name and MCP tool name as `<server>_<tool>`. Characters other than letters, numbers, `_`, and `-` are replaced with `_`; for example, server `context 7` and tool `resolve.library/id` become `context_7_resolve_library_id`. MCP prompts appear as slash commands named `<server>:<prompt>` using the same normalization.
|
||||
OpenCode combines the server name and MCP tool name as `<server>_<tool>`. Characters other than letters, numbers, `_`, and `-` are replaced with `_`; for example, server `context 7` and tool `resolve.library/id` become `context_7_resolve_library_id`. MCP prompts become available as commands named `<server>:<prompt>` using the same normalization.
|
||||
|
||||
Choose short server names that remain unique after normalization. Under the default Code Mode, MCP tools are grouped by the normalized server name.
|
||||
|
||||
@@ -251,26 +231,9 @@ Use permission actions to hide or deny a server's tools without stopping its con
|
||||
}
|
||||
```
|
||||
|
||||
## CLI commands
|
||||
## Manage servers
|
||||
|
||||
V2 provides these MCP management commands:
|
||||
|
||||
```bash
|
||||
# Add a local server to the project config
|
||||
opencode2 mcp add everything --env LOG_LEVEL=info -- npx -y @modelcontextprotocol/server-everything
|
||||
|
||||
# Add a remote server to the project config
|
||||
opencode2 mcp add context7 --url https://mcp.context7.com/mcp --header 'CONTEXT7_API_KEY={env:CONTEXT7_API_KEY}'
|
||||
|
||||
# Add to the global config instead
|
||||
opencode2 mcp add context7 --global --url https://mcp.context7.com/mcp
|
||||
|
||||
# List configured servers and connection status
|
||||
opencode2 mcp list
|
||||
|
||||
# Authenticate or remove OAuth credentials
|
||||
opencode2 mcp auth context7
|
||||
opencode2 mcp logout context7
|
||||
```
|
||||
|
||||
`mcp add` accepts either `--url` for a remote server or a command after `--` for a local server, not both. Use `--header NAME=VALUE` only with remote servers and `--env NAME=VALUE` only with local servers. Edit the config directly for OAuth, timeout, working-directory, or enablement settings.
|
||||
OpenCode interfaces can add servers to project or global configuration, list
|
||||
configured servers and their connection status, authenticate remote servers,
|
||||
and remove stored OAuth credentials. Edit configuration directly for OAuth client settings, timeouts, working
|
||||
directories, or enablement.
|
||||
|
||||
@@ -3,22 +3,22 @@ import { defineMeta } from "blume"
|
||||
export default defineMeta({
|
||||
title: "Configure",
|
||||
pages: [
|
||||
"providers",
|
||||
"models",
|
||||
"agents",
|
||||
"permissions",
|
||||
"sharing",
|
||||
"snapshots",
|
||||
"commands",
|
||||
"skills",
|
||||
"instructions",
|
||||
"mcp-servers",
|
||||
"attachments",
|
||||
"compaction",
|
||||
"warming",
|
||||
"themes",
|
||||
"formatters",
|
||||
"lsp",
|
||||
"agents",
|
||||
"models",
|
||||
"skills",
|
||||
"themes",
|
||||
"commands",
|
||||
"providers",
|
||||
"snapshots",
|
||||
"compaction",
|
||||
"formatters",
|
||||
"references",
|
||||
"attachments",
|
||||
"mcp-servers",
|
||||
"permissions",
|
||||
"instructions",
|
||||
"sharing",
|
||||
"warming",
|
||||
],
|
||||
})
|
||||
|
||||
@@ -1,29 +1,21 @@
|
||||
---
|
||||
title: "Models"
|
||||
description: ""
|
||||
---
|
||||
|
||||
OpenCode builds its model catalog from [Models.dev](https://models.dev), provider integrations, and your configuration.
|
||||
Only enabled models whose provider is available for the current project appear in the model picker.
|
||||
OpenCode builds its model catalog from [models.dev](https://models.dev), provider integrations, and your configuration.
|
||||
Only enabled models whose provider is available for the current project are available for selection.
|
||||
|
||||
Connect a provider with `/connect` in the TUI, or configure it in [Providers](/providers).
|
||||
Configure provider availability in [Providers](/providers).
|
||||
|
||||
## Choose a model
|
||||
|
||||
Open the model picker with `/models` or the default `<leader>m` keybind. The picker shows the models available from
|
||||
providers connected to the current project.
|
||||
|
||||
Select a model to use it in the current session. Switching models updates that session without changing your config. Use
|
||||
the catalog entries shown in the picker rather than guessing a provider or model name.
|
||||
Clients can select any model available from providers connected to the current project. Selecting a model updates the
|
||||
current session without changing configuration. Use an available catalog entry rather than guessing a provider or model
|
||||
name.
|
||||
|
||||
## Per-run model
|
||||
|
||||
Select a model for one non-interactive run with `--model` or `-m`:
|
||||
|
||||
```bash
|
||||
opencode2 run --model openai/gpt-5.2 "Explain this repository"
|
||||
opencode2 run -m openai/gpt-5.2#high "Review the current changes"
|
||||
```
|
||||
Command-line runs can select a model without changing the configured default.
|
||||
|
||||
Agents and commands can also select their own model. See [Agents](/agents) and [Commands](/commands).
|
||||
|
||||
@@ -31,9 +23,7 @@ Agents and commands can also select their own model. See [Agents](/agents) and [
|
||||
|
||||
Variants are named request overlays for one model, commonly used for reasoning effort or token budgets. Available names
|
||||
are model-specific and are derived from current catalog metadata. Do not assume that names such as `low`, `high`, or
|
||||
`max` exist for every model; `/variants` shows the valid choices.
|
||||
|
||||
Use `/variants` to choose one for the current model, or press `ctrl+t` to cycle through available variants.
|
||||
`max` exist for every model. Clients should present only the variants available for the selected model.
|
||||
|
||||
## Configure
|
||||
|
||||
@@ -201,7 +191,7 @@ endpoint requires a key, add `apiKey` to provider `settings` using an environmen
|
||||
|
||||
### Model references
|
||||
|
||||
Configuration and CLI options identify a model as `provider/model`, with an optional `#variant`:
|
||||
Configuration fields and model-selection inputs identify a model as `provider/model`, with an optional `#variant`:
|
||||
|
||||
```text
|
||||
openai/gpt-5.2
|
||||
@@ -223,13 +213,13 @@ The expanded config form is equivalent when generated or programmatic configurat
|
||||
}
|
||||
```
|
||||
|
||||
Root, agent, and command `model` fields accept both forms. Use the IDs shown by `/models`, not provider display names.
|
||||
Root, agent, and command `model` fields accept both forms. Use IDs from the available catalog, not provider display names.
|
||||
|
||||
### Caveats
|
||||
|
||||
- The selector object uses `model`, while a provider catalog entry uses `modelID` for the upstream API identifier.
|
||||
- The root `model` currently sets the default provider and model only. Although its selection shape accepts a variant,
|
||||
the V2 catalog default does not retain it; select a variant in the TUI, with `opencode2 run`, or on an agent or command.
|
||||
the V2 catalog default does not retain it; select a variant for the session, run, agent, or command instead.
|
||||
- Model options are provider-specific. A setting accepted by one provider package may be ignored or rejected by another.
|
||||
- Catalog data, credentials, and config are location-scoped. A model available in one project may be unavailable in
|
||||
another.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Permissions"
|
||||
description: ""
|
||||
---
|
||||
|
||||
Permissions control whether an agent may perform an action on a resource. V2
|
||||
@@ -225,6 +224,4 @@ shell proposes the exact command text, and skills and subagents propose their
|
||||
IDs. Review the confirmation carefully and remove saved approvals that are no
|
||||
longer needed.
|
||||
|
||||
For non-interactive runs, `opencode2 run --auto` replies `once` to permission
|
||||
requests. It does not save approvals, and explicit `deny` rules remain enforced.
|
||||
Without `--auto`, a non-interactive run rejects permission requests.
|
||||
Non-interactive clients must decide how to handle requests that require approval; explicit `deny` rules remain enforced.
|
||||
|
||||
@@ -1,64 +1,31 @@
|
||||
---
|
||||
title: "Providers"
|
||||
description: ""
|
||||
---
|
||||
|
||||
OpenCode builds its provider and model catalog from [Models.dev](https://models.dev), then applies the `providers`
|
||||
overlays from your [configuration](/config). A provider needs both a usable runtime package and, when required, an
|
||||
active connection.
|
||||
|
||||
## Connect a provider
|
||||
|
||||
Run `/connect` in the TUI, choose an integration, and complete one of the methods it offers:
|
||||
|
||||
```text
|
||||
/connect
|
||||
```
|
||||
|
||||
An integration may support an API key, OAuth, environment variables, or a combination of them. API keys and OAuth
|
||||
tokens entered through `/connect` are stored by the OpenCode service in its database. Run `/connect` again to replace
|
||||
or remove a stored credential.
|
||||
|
||||
Providers from Models.dev also declare their standard environment variables. A non-empty declared variable is exposed
|
||||
as an environment connection automatically, so common providers usually need no config:
|
||||
|
||||
```bash
|
||||
export ANTHROPIC_API_KEY="your-key"
|
||||
```
|
||||
|
||||
For a custom provider, `env` declares the variables that can supply its key:
|
||||
OpenCode includes a built-in catalog of providers and models from [models.dev](https://models.dev). You can also add a
|
||||
custom provider to your configuration.
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"providers": {
|
||||
"acme": {
|
||||
"name": "Acme",
|
||||
"env": ["ACME_API_KEY"],
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
When several credential sources exist, OpenCode uses the stored credential first, then the first non-empty variable in
|
||||
`env`, then `settings.apiKey`. Use config substitution instead of committing a literal key:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"providers": {
|
||||
"acme": {
|
||||
"package": "@opencode-ai/ai/providers/openai-compatible",
|
||||
"settings": {
|
||||
"apiKey": "{env:ACME_API_KEY}",
|
||||
"baseURL": "https://llm.acme.example/v1",
|
||||
},
|
||||
"models": {
|
||||
"qwen3-coder": {
|
||||
"name": "Qwen 3 Coder",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
<Callout type="warning">Do not commit API keys or authorization headers to your repository.</Callout>
|
||||
|
||||
## Configure
|
||||
|
||||
The `providers` object is keyed by provider ID. Each provider accepts these fields:
|
||||
|
||||
| Field | Purpose |
|
||||
@@ -71,11 +38,7 @@ The `providers` object is keyed by provider ID. Each provider accepts these fiel
|
||||
| `body` | JSON fields merged into request bodies. |
|
||||
| `models` | Models to add or override, keyed by catalog model ID. |
|
||||
|
||||
Configuration files are applied from lowest to highest precedence. `settings` and `body` are deep-merged. Headers are
|
||||
merged case-insensitively. At request time, provider values are inherited by the model, model values override them, and
|
||||
the selected variant is applied last.
|
||||
|
||||
### Endpoint
|
||||
## Endpoint
|
||||
|
||||
Override `settings.baseURL` to send an existing provider through a proxy or compatible endpoint. Its existing package,
|
||||
models, and connection continue to apply:
|
||||
@@ -95,29 +58,10 @@ models, and connection continue to apply:
|
||||
|
||||
`settings` is package-specific. A field only has an effect when the selected package supports it.
|
||||
|
||||
### Experimental OpenAI Responses WebSocket
|
||||
## Headers and body
|
||||
|
||||
OpenAI Responses can reuse one Session-bound WebSocket connection across sequential model calls. This transport is
|
||||
experimental and disabled by default. To test it, set the flag before starting or restarting the OpenCode service:
|
||||
|
||||
```bash
|
||||
export OPENCODE_EXPERIMENTAL_OPENAI_RESPONSES_WEBSOCKET=true
|
||||
opencode2 service restart
|
||||
```
|
||||
|
||||
The flag applies only to the `openai` provider using the native `openai-responses` route. Azure, xAI,
|
||||
OpenAI-compatible providers, and other protocols continue to use HTTP. A Session HTTP plugin hook also forces HTTP so
|
||||
the hook is never bypassed.
|
||||
|
||||
OpenCode reuses a connection only while its endpoint and effective handshake headers remain unchanged. It rotates
|
||||
connections before the provider lifetime limit and never replays a request after ambiguous delivery. HTTP fallback is
|
||||
limited to failures proven to occur before the provider received the request.
|
||||
|
||||
Unset the variable or set it to `false`, then restart the service, to return to HTTP-only execution.
|
||||
|
||||
### Headers and body
|
||||
|
||||
Headers and body fields can be set at provider, model, or variant scope:
|
||||
Use `headers` to add HTTP headers to provider requests. Use `body` to merge additional JSON fields into each request
|
||||
body:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
@@ -132,34 +76,21 @@ Headers and body fields can be set at provider, model, or variant scope:
|
||||
"application": "opencode",
|
||||
},
|
||||
},
|
||||
"models": {
|
||||
"gpt-5.2": {
|
||||
"headers": {
|
||||
"X-Model-Policy": "coding",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
These are request overlays, not a generic authentication scheme. Prefer `/connect`, `env`, or `settings.apiKey` for
|
||||
provider credentials unless the endpoint explicitly requires a custom header.
|
||||
## Package
|
||||
|
||||
### Provider packages
|
||||
|
||||
For an OpenAI-compatible service, use the V2 native compatible package. The model map is explicit because a custom
|
||||
provider has no Models.dev catalog entries:
|
||||
The `package` field selects the runtime used to communicate with a provider. For an OpenAI-compatible API, use the
|
||||
built-in compatible package:
|
||||
|
||||
```jsonc title="opencode.jsonc"
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"model": "acme/qwen3-coder",
|
||||
"providers": {
|
||||
"acme": {
|
||||
"name": "Acme Gateway",
|
||||
"env": ["ACME_API_KEY"],
|
||||
"package": "@opencode-ai/ai/providers/openai-compatible",
|
||||
"settings": {
|
||||
"baseURL": "https://llm.acme.example/v1",
|
||||
@@ -167,15 +98,6 @@ provider has no Models.dev catalog entries:
|
||||
"models": {
|
||||
"qwen3-coder": {
|
||||
"name": "Qwen 3 Coder",
|
||||
"capabilities": {
|
||||
"tools": true,
|
||||
"input": ["text"],
|
||||
"output": ["text"],
|
||||
},
|
||||
"limit": {
|
||||
"context": 131072,
|
||||
"output": 32768,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -183,23 +105,36 @@ provider has no Models.dev catalog entries:
|
||||
}
|
||||
```
|
||||
|
||||
Omit `env` for an endpoint that does not require authentication. The native compatible package requires
|
||||
`settings.baseURL` and uses bearer authentication when a key is available.
|
||||
Native package options:
|
||||
|
||||
The `package` field supports two runtime contracts:
|
||||
- `@opencode-ai/ai/providers/openai`
|
||||
- `@opencode-ai/ai/providers/openai/chat`
|
||||
- `@opencode-ai/ai/providers/openai/responses`
|
||||
- `@opencode-ai/ai/providers/openai-compatible`
|
||||
- `@opencode-ai/ai/providers/openai-compatible/responses`
|
||||
- `@opencode-ai/ai/providers/anthropic`
|
||||
- `@opencode-ai/ai/providers/anthropic-compatible`
|
||||
- `@opencode-ai/ai/providers/google`
|
||||
- `@opencode-ai/ai/providers/google-vertex`
|
||||
- `@opencode-ai/ai/providers/google-vertex/gemini`
|
||||
- `@opencode-ai/ai/providers/google-vertex/chat`
|
||||
- `@opencode-ai/ai/providers/google-vertex/responses`
|
||||
- `@opencode-ai/ai/providers/google-vertex/messages`
|
||||
- `@opencode-ai/ai/providers/azure`
|
||||
- `@opencode-ai/ai/providers/azure/chat`
|
||||
- `@opencode-ai/ai/providers/azure/responses`
|
||||
- `@opencode-ai/ai/providers/amazon-bedrock`
|
||||
- `@opencode-ai/ai/providers/amazon-bedrock/mantle`
|
||||
- `@opencode-ai/ai/providers/amazon-bedrock/mantle/chat`
|
||||
- `@opencode-ai/ai/providers/amazon-bedrock/mantle/responses`
|
||||
- `@opencode-ai/ai/providers/openrouter`
|
||||
- `@opencode-ai/ai/providers/xai`
|
||||
|
||||
| Form | Contract |
|
||||
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `"@opencode-ai/ai/providers/openai-compatible"` | A V2 native package exporting `model(modelID, settings)`. An npm specifier or absolute `file://` URL may use the same contract. |
|
||||
| `"aisdk:@ai-sdk/openai-compatible"` | An AI SDK provider package. The `aisdk:` prefix is required. |
|
||||
You can also use an npm package such as `@acme/opencode-provider` or an absolute `file://` URL for a local package.
|
||||
|
||||
Native packages receive the merged `settings` plus the resolved `apiKey`, `headers`, `body`, and `limits`. AI SDK
|
||||
packages receive their merged provider options. Use a package's own documentation for accepted settings; OpenCode does
|
||||
not validate package-specific keys.
|
||||
Use `settings` for options supported by the selected package.
|
||||
|
||||
`package` may also be set on one model to override the provider package for that model.
|
||||
|
||||
### Models
|
||||
## Models
|
||||
|
||||
Add a model under a provider's `models` map. The object key is the model ID used in OpenCode; `modelID` is the ID sent to
|
||||
the provider:
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "References"
|
||||
description: ""
|
||||
---
|
||||
|
||||
References give OpenCode named access to directories outside the current
|
||||
@@ -122,10 +121,10 @@ are logged and do not stop other references from loading.
|
||||
|
||||
`description` tells agents when a reference is relevant. References with a
|
||||
description are included in agent instructions with their alias and resolved
|
||||
path. References without one remain available in `@` autocomplete but are not
|
||||
advertised automatically.
|
||||
path. References without one remain available to clients but are not advertised
|
||||
automatically.
|
||||
|
||||
Set `hidden` to `true` to remove a reference from TUI `@` autocomplete:
|
||||
Set `hidden` to `true` to remove a reference from interactive client selectors:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
@@ -139,22 +138,15 @@ Set `hidden` to `true` to remove a reference from TUI `@` autocomplete:
|
||||
}
|
||||
```
|
||||
|
||||
`hidden` controls only autocomplete visibility. It does not remove the
|
||||
`hidden` controls only interactive visibility. It does not remove the
|
||||
reference from the reference API or agent instructions when a description is
|
||||
present.
|
||||
|
||||
## Use references
|
||||
|
||||
Type `@` in the TUI and select a reference alias to attach its root directory:
|
||||
|
||||
```text
|
||||
Compare the current implementation with @effect
|
||||
```
|
||||
|
||||
The attachment provides a non-recursive listing of the root's immediate files
|
||||
and directories. V2 currently attaches references by root alias;
|
||||
`@alias/path` is not a reference-specific file browser. Ask the agent to
|
||||
inspect a particular path when more detail is needed.
|
||||
Clients can attach a reference by its root alias. The attachment provides a
|
||||
non-recursive listing of the root's immediate files and directories. Ask the
|
||||
agent to inspect a particular path when more detail is needed.
|
||||
|
||||
References do not grant extra tool permissions. Access outside the active
|
||||
Location remains subject to the agent's normal tool rules and the
|
||||
@@ -169,7 +161,7 @@ applicable edit permission.
|
||||
| `repository` | No | Required | Remote Git repository |
|
||||
| `branch` | No | Optional | Branch to fetch and check out |
|
||||
| `description` | Optional | Optional | Guidance describing when agents should use it |
|
||||
| `hidden` | Optional | Optional | Hide it from TUI `@` autocomplete |
|
||||
| `hidden` | Optional | Optional | Hide it from interactive client selectors |
|
||||
|
||||
An alias cannot be empty or contain `/`, `\`, whitespace, a backtick, or a
|
||||
comma.
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
---
|
||||
title: "Session sharing"
|
||||
description: ""
|
||||
---
|
||||
|
||||
Session sharing is not yet available in OpenCode V2. V2 does not currently
|
||||
publish sessions, upload conversation history to a sharing service, or create
|
||||
public links.
|
||||
|
||||
<Callout type="warning">
|
||||
The V2 TUI registers `/share`, but it currently only reports that sharing is unavailable. There is no functional
|
||||
share/unshare command or server API endpoint.
|
||||
</Callout>
|
||||
There is no functional share or unshare server API endpoint.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Skills"
|
||||
description: ""
|
||||
---
|
||||
|
||||
Skills are Markdown instructions that OpenCode can advertise to an agent and
|
||||
@@ -25,8 +24,6 @@ Create one directory per skill with a `SKILL.md` file:
|
||||
---
|
||||
name: Git Release
|
||||
description: Prepare release notes, version bumps, and GitHub releases
|
||||
metadata:
|
||||
opencode/slash: "true"
|
||||
---
|
||||
|
||||
## Workflow
|
||||
@@ -120,8 +117,8 @@ V2 reads these fields:
|
||||
| Field | Purpose |
|
||||
| ------------------------------ | ------------------------------------------------------------------ |
|
||||
| `name` | Display name; defaults to the path-derived ID |
|
||||
| `description` | Summary shown to the model and command catalog |
|
||||
| `slash` | Set to `false` to hide the skill from the V2 slash-command catalog |
|
||||
| `description` | Summary used for model-facing discovery |
|
||||
| `slash` | Set to `false` to hide the skill from interactive command catalogs |
|
||||
| `metadata.opencode/slash` | Boolean or `"true"`/`"false"`; overrides `slash` |
|
||||
| `metadata.opencode/autoinvoke` | Set to `false` to omit the skill from model-facing discovery |
|
||||
|
||||
@@ -188,10 +185,6 @@ referenced file when the skill instructs it to do so. The supporting-file
|
||||
sample is available for directory-based `SKILL.md` skills; flat Markdown skills
|
||||
receive no neighboring file list.
|
||||
|
||||
In the V2 CLI, skills appear as `/id` commands unless `slash` resolves to
|
||||
`false`. Selecting one appends the skill body as a skill message and resumes
|
||||
the session.
|
||||
|
||||
## Permissions
|
||||
|
||||
Permission rules use the `skill` action and the skill ID as the resource. Rules
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
---
|
||||
title: "Undo"
|
||||
description: ""
|
||||
title: "Snapshots"
|
||||
---
|
||||
|
||||
OpenCode snapshots let the default interactive TUI roll back conversation history and related file changes. They are a
|
||||
convenience for revising recent work, not a replacement for Git commits or backups.
|
||||
OpenCode snapshots let clients roll back conversation history and related file changes. They are a convenience for
|
||||
revising recent work, not a replacement for Git commits or backups.
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -18,9 +17,9 @@ filesystem state:
|
||||
}
|
||||
```
|
||||
|
||||
Filesystem snapshots require a Git repository. With snapshots disabled, unavailable, or missing, undo can still stage a
|
||||
conversation rollback, but it has no captured file state to restore. Disabling snapshots does not delete snapshots that
|
||||
were already stored.
|
||||
Filesystem snapshots require a Git repository. With snapshots disabled, unavailable, or missing, a client can still
|
||||
request a conversation rollback, but there is no captured file state to restore. Disabling snapshots does not delete
|
||||
snapshots that were already stored.
|
||||
|
||||
## What is captured
|
||||
|
||||
@@ -35,54 +34,14 @@ Within that directory, snapshots include tracked files and untracked files that
|
||||
untracked file larger than 2 MiB is excluded. Ignored files, files outside the active directory, and changes to Git
|
||||
metadata are not captured.
|
||||
|
||||
During undo, OpenCode does not check out an entire tree. It restores only paths attributed to cleanly completed assistant
|
||||
steps after the selected conversation boundary. Each path is restored to its state before the first affected step.
|
||||
## Restoration
|
||||
|
||||
## Undo
|
||||
A restoration selects a conversation boundary and restores only paths attributed to cleanly completed assistant steps
|
||||
after it. Each affected path returns to its state before the first restored step, and a file created by those steps is
|
||||
removed when it did not exist in the earlier snapshot.
|
||||
|
||||
Wait for the session to become idle, then run:
|
||||
|
||||
```text
|
||||
/undo
|
||||
```
|
||||
|
||||
The TUI finds the latest non-empty user message and stages a revert at that message:
|
||||
|
||||
- The selected user message and every later message are hidden, but not deleted yet.
|
||||
- The selected message's text, attachments, and agent mentions are placed in the composer for revision.
|
||||
- Captured files changed by the affected assistant steps are restored to their earlier contents. Files created by those
|
||||
steps are removed when they did not exist in the earlier snapshot.
|
||||
- A summary shows the staged message count and restored paths.
|
||||
|
||||
Running `/undo` again moves the staged boundary to an earlier user message. OpenCode keeps the filesystem state from
|
||||
immediately before the first undo as the redo baseline, so repeated undos form one wider staged revert rather than a redo
|
||||
stack.
|
||||
|
||||
<Callout type="warning">
|
||||
Sending a new prompt while an undo is staged commits the revert. The hidden message range is removed from the active
|
||||
session history, the currently reverted files are kept, and redo is no longer available.
|
||||
</Callout>
|
||||
|
||||
## Redo
|
||||
|
||||
While a revert is staged, run:
|
||||
|
||||
```text
|
||||
/redo
|
||||
```
|
||||
|
||||
Redo clears the staged boundary, makes the hidden messages visible again, and restores affected files to their exact state
|
||||
immediately before the first undo. It does not rerun the model. After multiple undos, one redo restores the whole staged
|
||||
range; there is no step-by-step redo stack.
|
||||
|
||||
## Revert a message
|
||||
|
||||
The TUI's **Message Actions** menu also provides **Revert**. It stages the selected message as the conversation boundary
|
||||
and uses the same file restoration and redo behavior, but it does not copy that message into the composer.
|
||||
|
||||
For a conversation-and-files rollback, select a user message. If an assistant message is selected, that message is hidden,
|
||||
but only file changes attributed to later assistant steps are restored; the selected assistant message's own file changes
|
||||
are not included.
|
||||
Clients may stage a restoration before committing it so the previous conversation and filesystem state can still be
|
||||
recovered.
|
||||
|
||||
## Limitations and safety
|
||||
|
||||
@@ -90,19 +49,15 @@ are not included.
|
||||
matching file rollback.
|
||||
- Interrupted or failed steps do not receive a completed end snapshot. File changes made before the failure may remain.
|
||||
- Shell commands can change databases, services, processes, network resources, Git state, ignored build output, or files
|
||||
outside the active directory. Undo and redo do not reverse those side effects.
|
||||
- Undo overwrites the current contents of affected paths with older contents. Redo likewise overwrites those paths with
|
||||
the pre-undo state, including edits made after running undo.
|
||||
outside the active directory. Snapshot restoration does not reverse those side effects.
|
||||
- Restoring a snapshot overwrites the current contents of affected paths. Recovering the pre-restoration state can also
|
||||
overwrite edits made after the restoration was staged.
|
||||
- Other processes can edit the worktree between capture and restore. The server rejects revert operations while the
|
||||
session is actively running, but it cannot protect against external editors or commands.
|
||||
- Snapshot objects can contain complete contents of tracked and non-ignored untracked files. They are stored locally in
|
||||
the OpenCode data directory; do not treat snapshots as secret-free metadata.
|
||||
- Undo is not secure erasure. Committing a revert removes messages from the active projection, not from durable session
|
||||
history or existing snapshot storage.
|
||||
- Snapshot restoration is not secure erasure. Committing a revert removes messages from the active projection, not from
|
||||
durable session history or existing snapshot storage.
|
||||
|
||||
Review the staged file summary and your Git diff before continuing. Commit or back up important work independently before
|
||||
using undo on a dirty worktree.
|
||||
|
||||
<Callout type="note">
|
||||
`/undo` and `/redo` are interactive TUI commands. The non-interactive `run` command does not provide them.
|
||||
</Callout>
|
||||
Review the restored file summary and your Git diff before continuing. Commit or back up important work independently
|
||||
before restoring snapshots on a dirty worktree.
|
||||
|
||||
@@ -1,127 +1,9 @@
|
||||
---
|
||||
title: "Themes"
|
||||
description: "Choose a built-in TUI theme or create a custom color scheme."
|
||||
---
|
||||
|
||||
OpenCode includes built-in light and dark themes and can load custom themes
|
||||
from your global configuration or a project directory. The default theme is
|
||||
`opencode`.
|
||||
Themes are currently a terminal-client capability rather than a shared OpenCode configuration feature. The terminal
|
||||
client includes built-in light and dark themes, supports terminal-aware color modes, and owns theme selection and custom
|
||||
theme loading.
|
||||
|
||||
## Choose a theme
|
||||
|
||||
In the full-screen TUI, run:
|
||||
|
||||
```text
|
||||
/themes
|
||||
```
|
||||
|
||||
You can also open the picker with `ctrl+x`, then `t`, using the
|
||||
default keybindings.
|
||||
|
||||
Use `/settings` to change both the theme and its color mode. OpenCode supports
|
||||
three modes:
|
||||
|
||||
| Mode | Behavior |
|
||||
| -------- | -------------------------------------------------------- |
|
||||
| `system` | Follow the terminal's detected light or dark appearance. |
|
||||
| `dark` | Always use the theme's dark colors. |
|
||||
| `light` | Always use the theme's light colors. |
|
||||
|
||||
Your selection is stored in `~/.config/opencode/cli.json`, or the equivalent
|
||||
path under `$XDG_CONFIG_HOME`:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"theme": {
|
||||
"name": "tokyonight",
|
||||
"mode": "system"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<Callout type="note">
|
||||
Theme selection applies to the full-screen TUI. Direct interactive runs use colors derived from the terminal palette
|
||||
and honor only the color mode.
|
||||
</Callout>
|
||||
|
||||
## Built-in themes
|
||||
|
||||
OpenCode currently includes:
|
||||
|
||||
| | | |
|
||||
| ------------ | ------------------- | ---------------------- |
|
||||
| `aura` | `ayu` | `carbonfox` |
|
||||
| `catppuccin` | `catppuccin-frappe` | `catppuccin-macchiato` |
|
||||
| `cobalt2` | `cursor` | `dracula` |
|
||||
| `everforest` | `flexoki` | `github` |
|
||||
| `gruvbox` | `kanagawa` | `lucent-orng` |
|
||||
| `material` | `matrix` | `mercury` |
|
||||
| `monokai` | `nightowl` | `nord` |
|
||||
| `one-dark` | `opencode` | `orng` |
|
||||
| `osaka-jade` | `palenight` | `rosepine` |
|
||||
| `solarized` | `synthwave84` | `tokyonight` |
|
||||
| `vercel` | `vesper` | `zenburn` |
|
||||
|
||||
When OpenCode can read your terminal palette, the picker also includes
|
||||
`system`. The `system` theme generates its colors from your terminal's
|
||||
foreground, background, and ANSI palette.
|
||||
|
||||
## Custom themes
|
||||
|
||||
Create a JSON file in either of these locations:
|
||||
|
||||
```text
|
||||
~/.config/opencode/themes/my-theme.json
|
||||
.opencode/themes/my-theme.json
|
||||
```
|
||||
|
||||
OpenCode checks the global theme directory first, followed by every
|
||||
`.opencode/themes` directory from the filesystem root down to the current
|
||||
directory. A more local file with the same filename overrides an earlier one.
|
||||
The filename becomes the theme name, so `my-theme.json` appears as `my-theme`.
|
||||
|
||||
Custom theme files must be strict JSON. Comments and trailing commas are not
|
||||
supported.
|
||||
|
||||
### Format
|
||||
|
||||
V2 themes organize colors into hue scales and semantic tokens. Set `version`
|
||||
to `2` and define at least one of `light` or `dark`:
|
||||
|
||||
<Callout type="warning">
|
||||
Native V2 custom theme files are not loaded directly by the current beta. Existing custom files use the V1 format and
|
||||
are migrated to these tokens at runtime. This reference tracks the native V2 schema while direct file loading is
|
||||
completed.
|
||||
</Callout>
|
||||
|
||||
By default, a theme inherits OpenCode's complete theme, so you only need to
|
||||
define overrides. Set `mergeMode` to `true` to inherit one mode from the other
|
||||
before applying that mode's overrides. Set `standalone` to `true` only when you
|
||||
intend to supply a complete independent theme.
|
||||
|
||||
Each token accepts:
|
||||
|
||||
- A hex color such as `"#5c9cf5"`
|
||||
- `"transparent"` to use the terminal default
|
||||
- A hue reference such as `"$hue.blue.500"`
|
||||
- Another semantic token reference such as `"$text.default"`
|
||||
|
||||
Syntax and markdown tokens accept hex colors and hue references. Other
|
||||
semantic tokens can reference any semantic token.
|
||||
|
||||
<ThemeTokens />
|
||||
|
||||
If you add or edit a custom theme while OpenCode is running, restart the TUI to
|
||||
reload it.
|
||||
|
||||
## Terminal colors
|
||||
|
||||
Themes display most accurately in a terminal with truecolor support. Check
|
||||
your terminal with:
|
||||
|
||||
```bash
|
||||
echo $COLORTERM
|
||||
```
|
||||
|
||||
Most modern terminals report `truecolor` or `24bit`. Without truecolor,
|
||||
OpenCode approximates theme colors using the available terminal palette.
|
||||
See [CLI config](/cli/config) for terminal-client theme settings.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Session warming"
|
||||
description: "Keep recently active model sessions warm with periodic transient requests."
|
||||
---
|
||||
|
||||
Session warming sends periodic model requests for recently active sessions.
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Client"
|
||||
description: "Connect an application to the OpenCode HTTP API."
|
||||
---
|
||||
|
||||
`@opencode-ai/client` is the generated TypeScript client for the OpenCode HTTP
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Build"
|
||||
description: "Build on the engine used by millions daily."
|
||||
---
|
||||
|
||||
<CardGroup cols={1}>
|
||||
|
||||
+1
-1
@@ -2,5 +2,5 @@ import { defineMeta } from "blume"
|
||||
|
||||
export default defineMeta({
|
||||
title: "Build",
|
||||
pages: ["index", "plugins", "client", "sdk"],
|
||||
pages: ["sdk", "index", "client", "plugins"],
|
||||
})
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Plugins"
|
||||
description: "Extend OpenCode with plugins."
|
||||
---
|
||||
|
||||
Plugins extend OpenCode in-process. They can transform agents, models, commands,
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "SDK"
|
||||
description: "Embed OpenCode directly in your application."
|
||||
---
|
||||
|
||||
We're working on a general-purpose SDK for embedding OpenCode directly inside
|
||||
|
||||
@@ -0,0 +1,358 @@
|
||||
---
|
||||
title: "Keybinds"
|
||||
---
|
||||
|
||||
Customize bindings in `cli.json`:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"keybinds": {
|
||||
"leader": "ctrl+space",
|
||||
"command.palette.show": "ctrl+k",
|
||||
"app.exit": ["ctrl+c", "ctrl+d"],
|
||||
"app.debug": false
|
||||
},
|
||||
"leader": {
|
||||
"timeout": 1500
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use a string for one key:
|
||||
|
||||
```json
|
||||
{
|
||||
"keybinds": {
|
||||
"command.palette.show": "ctrl+k"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Separate alternatives with commas:
|
||||
|
||||
```json
|
||||
{
|
||||
"keybinds": {
|
||||
"app.exit": "ctrl+c,ctrl+d"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Disable a binding with `"none"` or `false`:
|
||||
|
||||
```json
|
||||
{
|
||||
"keybinds": {
|
||||
"app.debug": "none",
|
||||
"help.show": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use an object for event behavior:
|
||||
|
||||
```json
|
||||
{
|
||||
"keybinds": {
|
||||
"prompt.paste": {
|
||||
"key": "ctrl+v",
|
||||
"preventDefault": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`leader` defaults to `ctrl+x`. `<leader>` in another binding refers to that key.
|
||||
|
||||
```json
|
||||
{
|
||||
"keybinds": {
|
||||
"leader": "ctrl+space",
|
||||
"model.list": "<leader>m"
|
||||
},
|
||||
"leader": {
|
||||
"timeout": 2000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Unknown command IDs are rejected.
|
||||
|
||||
## Application
|
||||
|
||||
| ID | Default | Description |
|
||||
| -------------------------- | ------------------------- | ----------------------------------- |
|
||||
| `leader` | `ctrl+x` | Leader key for keybind combinations |
|
||||
| `app.exit` | `ctrl+c,ctrl+d,<leader>q` | Exit the application |
|
||||
| `app.debug` | `none` | Toggle debug panel |
|
||||
| `app.console` | `none` | Toggle console |
|
||||
| `app.scrap` | `none` | Open scrap screen |
|
||||
| `app.toggle.animations` | `none` | Toggle animations |
|
||||
| `app.toggle.file_context` | `none` | Toggle file context |
|
||||
| `app.toggle.diffwrap` | `none` | Toggle diff wrapping |
|
||||
| `app.toggle.paste_summary` | `none` | Toggle paste summary |
|
||||
| `command.palette.show` | `ctrl+p` | List available commands |
|
||||
| `help.show` | `none` | Open help dialog |
|
||||
| `docs.open` | `none` | Open documentation |
|
||||
| `opencode.settings` | `none` | Open settings |
|
||||
| `server.pair` | `none` | Pair device |
|
||||
| `service.restart` | `none` | Restart service |
|
||||
| `permission.mode` | `none` | Toggle auto-approve permissions |
|
||||
|
||||
## Diff Viewer
|
||||
|
||||
| ID | Default | Description |
|
||||
| ----------------------- | ----------------- | ---------------------------------------- |
|
||||
| `diff.open` | `none` | Open diff viewer |
|
||||
| `diff.close` | `escape,q` | Close diff viewer |
|
||||
| `diff.down` | `j,down` | Move diff viewer down |
|
||||
| `diff.up` | `k,up` | Move diff viewer up |
|
||||
| `diff.page.down` | `pagedown,ctrl+f` | Page diff viewer down |
|
||||
| `diff.page.up` | `pageup,ctrl+b` | Page diff viewer up |
|
||||
| `diff.toggle` | `enter,space` | Toggle diff viewer item |
|
||||
| `diff.expand` | `right` | Expand diff viewer item |
|
||||
| `diff.expand_all` | `E` | Expand all diff viewer folders |
|
||||
| `diff.collapse` | `left` | Collapse diff viewer item |
|
||||
| `diff.switch_focus` | `tab` | Switch diff viewer focus |
|
||||
| `diff.next_hunk` | `]` | Jump to next diff hunk |
|
||||
| `diff.previous_hunk` | `[` | Jump to previous diff hunk |
|
||||
| `diff.next_file` | `n` | Jump to next diff file |
|
||||
| `diff.previous_file` | `p` | Jump to previous diff file |
|
||||
| `diff.toggle_file_tree` | `b` | Toggle diff viewer file tree |
|
||||
| `diff.single_patch` | `s` | Toggle single patch view |
|
||||
| `diff.switch_source` | `d` | Switch diff viewer source |
|
||||
| `diff.toggle_view` | `v` | Toggle diff viewer split or unified view |
|
||||
| `diff.mark_reviewed` | `m` | Toggle selected diff file reviewed |
|
||||
| `diff.help` | `?` | Show more diff viewer shortcuts |
|
||||
|
||||
## Appearance And Navigation
|
||||
|
||||
| ID | Default | Description |
|
||||
| -------------------------- | ----------- | ---------------------------------------- |
|
||||
| `prompt.editor` | `<leader>e` | Open external editor |
|
||||
| `theme.switch` | `<leader>t` | List available themes |
|
||||
| `theme.switch_mode` | `none` | Switch between light and dark theme mode |
|
||||
| `theme.mode.lock` | `none` | Lock or unlock theme mode |
|
||||
| `session.sidebar.toggle` | `<leader>b` | Toggle sidebar |
|
||||
| `session.toggle.scrollbar` | `none` | Toggle session scrollbar |
|
||||
| `opencode.status` | `<leader>s` | View status |
|
||||
| `opencode.debug` | `none` | View debug info |
|
||||
|
||||
## Sessions
|
||||
|
||||
| ID | Default | Description |
|
||||
| ------------------------------------- | ----------------------- | ---------------------------------------- |
|
||||
| `session.export` | `<leader>x` | Export session to editor |
|
||||
| `session.copy` | `none` | Copy session transcript |
|
||||
| `session.move` | `none` | Move session |
|
||||
| `session.new` | `<leader>n` | Create a new session |
|
||||
| `session.list` | `<leader>l` | List all sessions |
|
||||
| `open.menu` | `ctrl+o` | Open recent sessions and projects |
|
||||
| `session.tab.next` | `ctrl+tab,alt+down` | Switch to next open session tab |
|
||||
| `session.tab.previous` | `ctrl+shift+tab,alt+up` | Switch to previous open session tab |
|
||||
| `session.tab.history.back` | `none` | Go back in session tab history |
|
||||
| `session.tab.history.forward` | `ctrl+i` | Go forward in session tab history |
|
||||
| `session.tab.next_unread` | `alt+shift+down` | Switch to next unread session tab |
|
||||
| `session.tab.previous_unread` | `alt+shift+up` | Switch to previous unread session tab |
|
||||
| `session.tab.close` | `<leader>w` | Close current session tab |
|
||||
| `session.tab.reopen` | `ctrl+shift+t` | Reopen last closed session tab |
|
||||
| `session.timeline` | `<leader>g` | Show session timeline |
|
||||
| `session.fork` | `none` | Fork session from message |
|
||||
| `session.rename` | `ctrl+r` | Rename session |
|
||||
| `session.delete` | `ctrl+d` | Delete session |
|
||||
| `session.share` | `none` | Share current session |
|
||||
| `session.unshare` | `none` | Unshare current session |
|
||||
| `session.interrupt` | `escape` | Interrupt current session |
|
||||
| `session.background` | `ctrl+b` | Background blocking session tools |
|
||||
| `session.compact` | `<leader>c` | Compact the session |
|
||||
| `session.cd` | `none` | Change working directory |
|
||||
| `session.queued_prompts` | `<leader>q` | Manage queued prompts |
|
||||
| `queued_prompt.delete` | `ctrl+d` | Delete queued prompt |
|
||||
| `session.toggle.exploration_grouping` | `none` | Toggle related tool call grouping |
|
||||
| `session.child.first` | `down` | Toggle subagent picker |
|
||||
| `session.child.next` | `right` | Go to next child session |
|
||||
| `session.child.previous` | `left` | Go to previous child session |
|
||||
| `session.parent` | `up` | Go to parent session |
|
||||
| `session.pin.toggle` | `ctrl+f` | Pin or unpin session in the session list |
|
||||
| `session.quick_switch.1` | `<leader>1` | Switch to session in quick slot 1 |
|
||||
| `session.quick_switch.2` | `<leader>2` | Switch to session in quick slot 2 |
|
||||
| `session.quick_switch.3` | `<leader>3` | Switch to session in quick slot 3 |
|
||||
| `session.quick_switch.4` | `<leader>4` | Switch to session in quick slot 4 |
|
||||
| `session.quick_switch.5` | `<leader>5` | Switch to session in quick slot 5 |
|
||||
| `session.quick_switch.6` | `<leader>6` | Switch to session in quick slot 6 |
|
||||
| `session.quick_switch.7` | `<leader>7` | Switch to session in quick slot 7 |
|
||||
| `session.quick_switch.8` | `<leader>8` | Switch to session in quick slot 8 |
|
||||
| `session.quick_switch.9` | `<leader>9` | Switch to session in quick slot 9 |
|
||||
| `session.tab.select.1` | `<leader>1,ctrl+1` | Switch to session tab 1 |
|
||||
| `session.tab.select.2` | `<leader>2,ctrl+2` | Switch to session tab 2 |
|
||||
| `session.tab.select.3` | `<leader>3,ctrl+3` | Switch to session tab 3 |
|
||||
| `session.tab.select.4` | `<leader>4,ctrl+4` | Switch to session tab 4 |
|
||||
| `session.tab.select.5` | `<leader>5,ctrl+5` | Switch to session tab 5 |
|
||||
| `session.tab.select.6` | `<leader>6,ctrl+6` | Switch to session tab 6 |
|
||||
| `session.tab.select.7` | `<leader>7,ctrl+7` | Switch to session tab 7 |
|
||||
| `session.tab.select.8` | `<leader>8,ctrl+8` | Switch to session tab 8 |
|
||||
| `session.tab.select.9` | `<leader>9,ctrl+9` | Switch to session tab 9 |
|
||||
| `session.tab.select.10` | `<leader>0,ctrl+0` | Switch to session tab 10 |
|
||||
|
||||
## Models And Agents
|
||||
|
||||
| ID | Default | Description |
|
||||
| ------------------------------ | ----------- | ------------------------------------ |
|
||||
| `stash.delete` | `ctrl+d` | Delete stash entry |
|
||||
| `model.dialog.provider` | `ctrl+a` | Open provider list from model dialog |
|
||||
| `model.dialog.favorite` | `ctrl+f` | Toggle model favorite status |
|
||||
| `model.list` | `<leader>m` | List available models |
|
||||
| `model.cycle_recent` | `f2` | Next recently used model |
|
||||
| `model.cycle_recent_reverse` | `shift+f2` | Previous recently used model |
|
||||
| `model.cycle_favorite` | `none` | Next favorite model |
|
||||
| `model.cycle_favorite_reverse` | `none` | Previous favorite model |
|
||||
| `mcp.list` | `none` | List MCP servers |
|
||||
| `provider.connect` | `none` | Connect integration |
|
||||
| `agent.list` | `<leader>a` | List agents |
|
||||
| `agent.cycle` | `shift+tab` | Next agent |
|
||||
| `agent.cycle.reverse` | `none` | Previous agent |
|
||||
| `variant.cycle` | `ctrl+t` | Cycle model variants |
|
||||
| `variant.list` | `none` | List model variants |
|
||||
|
||||
## Session Navigation
|
||||
|
||||
| ID | Default | Description |
|
||||
| ------------------------------- | ---------------------- | --------------------------------- |
|
||||
| `session.page.up` | `pageup,ctrl+alt+b` | Scroll messages up by one page |
|
||||
| `session.page.down` | `pagedown,ctrl+alt+f` | Scroll messages down by one page |
|
||||
| `session.line.up` | `ctrl+alt+y` | Scroll messages up by one line |
|
||||
| `session.line.down` | `ctrl+alt+e` | Scroll messages down by one line |
|
||||
| `session.half.page.up` | `ctrl+alt+u` | Scroll messages up by half page |
|
||||
| `session.half.page.down` | `ctrl+alt+d` | Scroll messages down by half page |
|
||||
| `session.first` | `ctrl+g,home,alt+home` | Navigate to first message |
|
||||
| `session.last` | `ctrl+alt+g,end` | Navigate to last message |
|
||||
| `session.message.next` | `none` | Navigate to next message |
|
||||
| `session.message.previous` | `none` | Navigate to previous message |
|
||||
| `session.message.user.next` | `none` | Navigate to next user message |
|
||||
| `session.message.user.previous` | `none` | Navigate to previous user message |
|
||||
| `session.messages_last_user` | `alt+end` | Navigate to last user message |
|
||||
| `messages.copy` | `<leader>y` | Copy message |
|
||||
| `session.undo` | `<leader>u` | Undo message |
|
||||
| `session.redo` | `<leader>r` | Redo message |
|
||||
| `session.toggle.thinking` | `none` | Toggle thinking blocks visibility |
|
||||
|
||||
## Prompt Commands
|
||||
|
||||
| ID | Default | Description |
|
||||
| ----------------------------- | ------------ | ---------------------- |
|
||||
| `prompt.submit` | `none` | Submit prompt |
|
||||
| `prompt.queue` | `alt+return` | Queue prompt |
|
||||
| `prompt.editor_context.clear` | `none` | Clear editor context |
|
||||
| `prompt.images.view` | `<leader>i` | View image attachments |
|
||||
| `prompt.skills` | `none` | Open skill selector |
|
||||
| `prompt.stash` | `none` | Stash prompt |
|
||||
| `prompt.stash.pop` | `none` | Pop stashed prompt |
|
||||
| `prompt.stash.list` | `none` | List stashed prompts |
|
||||
|
||||
## Input Editing
|
||||
|
||||
| ID | Default | Description |
|
||||
| ------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------- |
|
||||
| `prompt.clear` | `ctrl+c` | Clear input field |
|
||||
| `prompt.paste` | `{"key":"ctrl+v","preventDefault":false}` (`ctrl+v`; `preventDefault: false`) | Paste from clipboard |
|
||||
| `input.submit` | `return` | Submit input |
|
||||
| `input.newline` | `shift+return,ctrl+return,ctrl+j` | Insert newline in input |
|
||||
| `input.move.left` | `left,ctrl+b` | Move cursor left in input |
|
||||
| `input.move.right` | `right,ctrl+f` | Move cursor right in input |
|
||||
| `input.move.up` | `up` | Move cursor up in input |
|
||||
| `input.move.down` | `down` | Move cursor down in input |
|
||||
| `input.select.left` | `shift+left` | Select left in input |
|
||||
| `input.select.right` | `shift+right` | Select right in input |
|
||||
| `input.select.up` | `shift+up` | Select up in input |
|
||||
| `input.select.down` | `shift+down` | Select down in input |
|
||||
| `input.line.home` | `ctrl+a` | Move to start of line in input |
|
||||
| `input.line.end` | `ctrl+e` | Move to end of line in input |
|
||||
| `input.select.line.home` | `ctrl+shift+a` | Select to start of line in input |
|
||||
| `input.select.line.end` | `ctrl+shift+e` | Select to end of line in input |
|
||||
| `input.visual.line.home` | `alt+a` | Move to start of visual line in input |
|
||||
| `input.visual.line.end` | `alt+e` | Move to end of visual line in input |
|
||||
| `input.select.visual.line.home` | `alt+shift+a` | Select to start of visual line in input |
|
||||
| `input.select.visual.line.end` | `alt+shift+e` | Select to end of visual line in input |
|
||||
| `input.buffer.home` | `none` | Move to start of buffer in input |
|
||||
| `input.buffer.end` | `none` | Move to end of buffer in input |
|
||||
| `input.select.buffer.home` | `shift+home` | Select to start of buffer in input |
|
||||
| `input.select.buffer.end` | `shift+end` | Select to end of buffer in input |
|
||||
| `input.delete.line` | `ctrl+shift+d` | Delete line in input |
|
||||
| `input.delete.to.line.end` | `ctrl+k` | Delete to end of line in input |
|
||||
| `input.delete.to.line.start` | `ctrl+u` | Delete to start of line in input |
|
||||
| `input.backspace` | `backspace,shift+backspace` | Backspace in input |
|
||||
| `input.delete` | `ctrl+d,delete,shift+delete` | Delete character in input |
|
||||
| `input.undo` | `ctrl+-,super+z` | Undo in input |
|
||||
| `input.redo` | `ctrl+.,super+shift+z` | Redo in input |
|
||||
| `input.word.forward` | `alt+f,alt+right,ctrl+right` | Move word forward in input |
|
||||
| `input.word.backward` | `alt+b,alt+left,ctrl+left` | Move word backward in input |
|
||||
| `input.select.word.forward` | `alt+shift+f,alt+shift+right` | Select word forward in input |
|
||||
| `input.select.word.backward` | `alt+shift+b,alt+shift+left` | Select word backward in input |
|
||||
| `input.delete.word.forward` | `alt+d,alt+delete,ctrl+delete` | Delete word forward in input |
|
||||
| `input.delete.word.backward` | `ctrl+w,ctrl+backspace,alt+backspace` | Delete word backward in input |
|
||||
| `input.select.all` | `super+a` | Select all in input |
|
||||
| `prompt.history.previous` | `up` | Previous history item |
|
||||
| `prompt.history.next` | `down` | Next history item |
|
||||
|
||||
## Composer
|
||||
|
||||
| ID | Default | Description |
|
||||
| ----------------------------- | -------- | -------------------- |
|
||||
| `composer.subagent.up` | `up` | Previous subagent |
|
||||
| `composer.subagent.down` | `down` | Next subagent |
|
||||
| `composer.subagent.select` | `return` | Navigate to subagent |
|
||||
| `composer.subagent.interrupt` | `ctrl+d` | Interrupt subagent |
|
||||
| `composer.shell.up` | `up` | Previous shell |
|
||||
| `composer.shell.down` | `down` | Next shell |
|
||||
| `composer.shell.kill` | `ctrl+d` | Kill shell command |
|
||||
|
||||
## Dialogs And Autocomplete
|
||||
|
||||
| ID | Default | Description |
|
||||
| ------------------------------ | ------------- | ----------------------------------- |
|
||||
| `dialog.select.prev` | `up,ctrl+p` | Move to previous dialog item |
|
||||
| `dialog.select.next` | `down,ctrl+n` | Move to next dialog item |
|
||||
| `dialog.select.page_up` | `pageup` | Move up one page in dialog |
|
||||
| `dialog.select.page_down` | `pagedown` | Move down one page in dialog |
|
||||
| `dialog.select.home` | `home` | Move to first dialog item |
|
||||
| `dialog.select.end` | `end` | Move to last dialog item |
|
||||
| `dialog.select.submit` | `return` | Submit selected dialog item |
|
||||
| `dialog.prompt.submit` | `return` | Submit dialog prompt |
|
||||
| `dialog.worktree.generate` | `tab` | Generate worktree name |
|
||||
| `dialog.move_session.new` | `ctrl+m` | New worktree |
|
||||
| `dialog.move_session.delete` | `ctrl+d` | Delete worktree |
|
||||
| `dialog.move_session.refresh` | `ctrl+r` | Refresh worktrees |
|
||||
| `prompt.autocomplete.prev` | `up,ctrl+p` | Move to previous autocomplete item |
|
||||
| `prompt.autocomplete.next` | `down,ctrl+n` | Move to next autocomplete item |
|
||||
| `prompt.autocomplete.hide` | `escape` | Hide autocomplete |
|
||||
| `prompt.autocomplete.select` | `return` | Select autocomplete item |
|
||||
| `prompt.autocomplete.complete` | `tab` | Complete autocomplete item |
|
||||
| `permission.prompt.fullscreen` | `ctrl+f` | Toggle permission prompt fullscreen |
|
||||
| `plugins.toggle` | `space` | Toggle plugin |
|
||||
| `dialog.mcp.toggle` | `space` | Toggle MCP server |
|
||||
| `dialog.plugins.install` | `shift+i` | Install plugin from plugin dialog |
|
||||
|
||||
## Terminal And Plugins
|
||||
|
||||
| ID | Default | Description |
|
||||
| ----------------------- | -------- | -------------------------- |
|
||||
| `terminal.suspend` | `ctrl+z` | Suspend terminal |
|
||||
| `terminal.title.toggle` | `none` | Toggle terminal title |
|
||||
| `plugins.list` | `none` | Open plugin manager dialog |
|
||||
| `plugins.install` | `none` | Install plugin |
|
||||
|
||||
## Which-Key
|
||||
|
||||
| ID | Default | Description |
|
||||
| -------------------------- | --------------------------- | -------------------------------- |
|
||||
| `which-key.toggle` | `ctrl+alt+k` | Toggle which-key panel |
|
||||
| `which-key.layout.toggle` | `ctrl+alt+shift+k` | Switch which-key layout |
|
||||
| `which-key.pending.toggle` | `ctrl+alt+shift+p` | Toggle which-key pending preview |
|
||||
| `which-key.group.previous` | `ctrl+alt+left,ctrl+alt+[` | Previous which-key group |
|
||||
| `which-key.group.next` | `ctrl+alt+right,ctrl+alt+]` | Next which-key group |
|
||||
| `which-key.scroll.up` | `ctrl+alt+up,ctrl+alt+p` | Scroll which-key up |
|
||||
| `which-key.scroll.down` | `ctrl+alt+down,ctrl+alt+n` | Scroll which-key down |
|
||||
| `which-key.page.up` | `ctrl+alt+pageup` | Page which-key up |
|
||||
| `which-key.page.down` | `ctrl+alt+pagedown` | Page which-key down |
|
||||
| `which-key.home` | `ctrl+alt+home` | Jump to first which-key binding |
|
||||
| `which-key.end` | `ctrl+alt+end` | Jump to last which-key binding |
|
||||
@@ -0,0 +1,6 @@
|
||||
import { defineMeta } from "blume"
|
||||
|
||||
export default defineMeta({
|
||||
title: "Configure",
|
||||
pages: ["theme", "plugins", "keybinds"],
|
||||
})
|
||||
@@ -0,0 +1,39 @@
|
||||
---
|
||||
title: "Plugins"
|
||||
---
|
||||
|
||||
Add plugins to `cli.json`:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"plugins": ["opencode.example", "./plugins/status.ts"]
|
||||
}
|
||||
```
|
||||
|
||||
Entries are processed in order. Prefix an ID or wildcard with `-` to disable matching plugins:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"plugins": ["*", "-opencode.notifications", "-team.*"]
|
||||
}
|
||||
```
|
||||
|
||||
Pass plugin options with the object form:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"plugins": [
|
||||
{
|
||||
"package": "@example/opencode-tui",
|
||||
"options": {
|
||||
"compact": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`package` accepts a package name, an absolute path, a `file://` URL, or a path relative to `cli.json`.
|
||||
|
||||
OpenCode also discovers JavaScript and TypeScript plugins from `plugins/tui` under the global config directory and project
|
||||
`.opencode` directories.
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
title: "Theme"
|
||||
---
|
||||
@@ -0,0 +1,165 @@
|
||||
---
|
||||
title: "Config"
|
||||
---
|
||||
|
||||
Most settings can also be changed from the OpenCode TUI. Press `Ctrl+P`, then select **Open settings**.
|
||||
|
||||
<img src={`${import.meta.env.BASE_URL}assets/docs/cli/settings.png`} alt="OpenCode TUI settings dialog" />
|
||||
|
||||
The default CLI config location is:
|
||||
|
||||
```text
|
||||
~/.config/opencode/cli.json
|
||||
```
|
||||
|
||||
Set `$XDG_CONFIG_HOME` to use a different config directory:
|
||||
|
||||
```text
|
||||
$XDG_CONFIG_HOME/opencode/cli.json
|
||||
```
|
||||
|
||||
## Theme
|
||||
|
||||
Set the theme and color mode:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"theme": {
|
||||
"name": "tokyonight",
|
||||
"mode": "system"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Values | Description |
|
||||
| ------ | ---------------------------- | ----------------------------------------------------------------- |
|
||||
| `name` | string | Selects the theme. |
|
||||
| `mode` | `system`, `dark`, or `light` | Selects the color mode. `system` follows the terminal appearance. |
|
||||
|
||||
See [Theme](/cli/theme) for theme configuration.
|
||||
|
||||
## Keybinds
|
||||
|
||||
Override bindings with the top-level `keybinds` object:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"keybinds": {
|
||||
"leader": "ctrl+x",
|
||||
"app.exit": "ctrl+c,ctrl+d,<leader>q",
|
||||
"app.debug": "none",
|
||||
"help.show": false
|
||||
},
|
||||
"leader": {
|
||||
"timeout": 2000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
See [Keybinds](/cli/keybinds) for every available binding.
|
||||
|
||||
## Plugins
|
||||
|
||||
Load terminal plugins in order:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"plugins": [
|
||||
"-opencode.notifications",
|
||||
{
|
||||
"package": "./plugins/status.ts",
|
||||
"options": {
|
||||
"compact": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
See [Plugins](/cli/plugins) for packages, local files, options, and enablement directives.
|
||||
|
||||
## Scroll
|
||||
|
||||
Set scroll speed and acceleration:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"scroll": {
|
||||
"speed": 2,
|
||||
"acceleration": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Values | Description |
|
||||
| -------------- | ------------------------ | --------------------------------- |
|
||||
| `speed` | number, at least `0.001` | Sets the distance per input tick. |
|
||||
| `acceleration` | boolean | Speeds up repeated scrolling. |
|
||||
|
||||
## Attention
|
||||
|
||||
Configure notifications and sounds:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"attention": {
|
||||
"enabled": true,
|
||||
"notifications": true,
|
||||
"sound": true,
|
||||
"volume": 0.4,
|
||||
"sound_pack": "opencode.default",
|
||||
"sounds": {
|
||||
"permission": "/home/me/sounds/permission.wav"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Values | Description |
|
||||
| --------------- | ---------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| `enabled` | boolean | Enables attention alerts. |
|
||||
| `notifications` | boolean | Shows system notifications. |
|
||||
| `sound` | boolean | Plays attention sounds. |
|
||||
| `volume` | number from `0` to `1` | Sets sound volume. |
|
||||
| `sound_pack` | string | Selects the active sound pack. |
|
||||
| `sounds` | object | Overrides files for `default`, `question`, `permission`, `error`, `done`, or `subagent_done` events. |
|
||||
|
||||
## Diffs
|
||||
|
||||
Configure diff presentation:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"diffs": {
|
||||
"wrap": "word",
|
||||
"tree": true,
|
||||
"single": false,
|
||||
"view": "auto"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Values | Description |
|
||||
| -------- | ----------------------------- | ------------------------------------------------------------- |
|
||||
| `wrap` | `word` or `none` | Sets line wrapping. |
|
||||
| `tree` | boolean | Shows the diff file tree. |
|
||||
| `single` | boolean | Shows only the selected file patch. |
|
||||
| `view` | `auto`, `split`, or `unified` | Sets the layout. `auto` chooses based on the available width. |
|
||||
|
||||
## Terminal
|
||||
|
||||
Configure terminal integration:
|
||||
|
||||
```json title="cli.json"
|
||||
{
|
||||
"terminal": {
|
||||
"title": true,
|
||||
"copy": "select"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Values | Description |
|
||||
| ------- | -------------------- | -------------------------------------------------------------------------------------------------------- |
|
||||
| `title` | boolean | Updates the terminal window title. |
|
||||
| `copy` | `manual` or `select` | Sets manual copy or copy on selection. Defaults to `select` on macOS and Linux, and `manual` on Windows. |
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
title: "Intro"
|
||||
---
|
||||
|
||||
Run the CLI in a project to open the full-screen terminal interface:
|
||||
|
||||
```bash
|
||||
opencode2
|
||||
```
|
||||
|
||||
Pass a directory to work in a different project:
|
||||
|
||||
```bash
|
||||
opencode2 ~/code/my-project
|
||||
```
|
||||
|
||||
Suggested terminals:
|
||||
|
||||
- [Ghostty](https://ghostty.org)
|
||||
- [WezTerm](https://wezterm.org)
|
||||
- [Alacritty](https://alacritty.org)
|
||||
- [Kitty](https://sw.kovidgoyal.net/kitty/)
|
||||
|
||||
Truecolor support gives themes their most accurate colors; terminals without it use an approximation of the available
|
||||
palette.
|
||||
|
||||
## Automation
|
||||
|
||||
Use `opencode2 run` to submit a prompt without opening the interactive interface. It is designed for scripts, CI jobs, and
|
||||
other workflows that need model output directly in the terminal.
|
||||
|
||||
```bash
|
||||
opencode2 run "Explain this repository"
|
||||
```
|
||||
|
||||
## Mini
|
||||
|
||||
Use `opencode2 mini` to start OpenCode's minimal interactive interface instead of the full-screen TUI.
|
||||
|
||||
```bash
|
||||
opencode2 mini
|
||||
```
|
||||
|
||||
Run `opencode2 mini --help` to see its session, model, agent, prompt, and replay options.
|
||||
|
||||
## Background service
|
||||
|
||||
By default, OpenCode discovers or starts one shared background server for your user account. Every local OpenCode client
|
||||
connects to that server, which owns sessions, configuration, integrations, permissions, and tool execution.
|
||||
|
||||
Use `--standalone` to run with a private server, or `--server` to connect to a specific server URL:
|
||||
|
||||
```bash
|
||||
opencode2 --standalone
|
||||
opencode2 --server http://localhost:4096
|
||||
```
|
||||
|
||||
See [Troubleshooting](/troubleshooting) for shared service diagnostics and the [API reference](/api) for server endpoints.
|
||||
@@ -0,0 +1,6 @@
|
||||
import { defineMeta } from "blume"
|
||||
|
||||
export default defineMeta({
|
||||
title: "Intro",
|
||||
pages: ["index", "config", "configure", "providers"],
|
||||
})
|
||||
@@ -0,0 +1,3 @@
|
||||
---
|
||||
title: "Providers"
|
||||
---
|
||||
@@ -1,11 +1,8 @@
|
||||
---
|
||||
title: "Config"
|
||||
description: ""
|
||||
---
|
||||
|
||||
<Callout type="tip">
|
||||
You shouldn't have to configure OpenCode manually. Ask OpenCode to update its configuration for you.
|
||||
</Callout>
|
||||
You shouldn't have to configure OpenCode manually. Ask OpenCode to update its configuration for you.
|
||||
|
||||
## Format
|
||||
|
||||
@@ -105,7 +102,7 @@ Set the shell used by the terminal and shell tools.
|
||||
### Model
|
||||
|
||||
Set the default model in `provider/model` format. The root default currently
|
||||
does not retain a `#variant`; select variants in the TUI or on an agent or command.
|
||||
does not retain a `#variant`; agent and command model references can select one.
|
||||
|
||||
```jsonc
|
||||
{
|
||||
@@ -113,8 +110,7 @@ does not retain a `#variant`; select variants in the TUI or on an agent or comma
|
||||
}
|
||||
```
|
||||
|
||||
See the [models guide](/models) for model selection
|
||||
and local models.
|
||||
See the [models guide](/models) for model selection and local models.
|
||||
|
||||
### Default agent
|
||||
|
||||
|
||||
@@ -1,96 +1,38 @@
|
||||
---
|
||||
title: "Get started"
|
||||
description: "Get started with OpenCode."
|
||||
title: "Intro"
|
||||
---
|
||||
|
||||
<Callout type="warning">
|
||||
These docs are for the beta version of OpenCode, which will become OpenCode 2.0. The beta is still changing: things
|
||||
may break, and APIs, configuration, and plugin APIs may change.
|
||||
</Callout>
|
||||
These docs are for the beta version of OpenCode, which will become OpenCode 2.0. The beta is still changing: things may
|
||||
break, and APIs, configuration, and plugin APIs may change.
|
||||
|
||||
<Callout type="note">
|
||||
OpenCode 2 installs and runs as `opencode2`. It does not replace OpenCode 1's `opencode` binary, so you can keep both
|
||||
versions installed and run them side by side.
|
||||
</Callout>
|
||||
OpenCode 2 installs and runs as `opencode2`. It does not replace OpenCode 1's `opencode` binary, so you can keep both
|
||||
versions installed and run them side by side.
|
||||
|
||||
## Install
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash npm
|
||||
npm install -g @opencode-ai/cli@beta
|
||||
```
|
||||
|
||||
```bash bun
|
||||
bun install -g --trust @opencode-ai/cli@beta
|
||||
```
|
||||
|
||||
```bash pnpm
|
||||
pnpm add -g --allow-build=@opencode-ai/cli @opencode-ai/cli@beta
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn global add @opencode-ai/cli@beta
|
||||
```
|
||||
|
||||
```bash curl
|
||||
curl -fsSL https://raw.githubusercontent.com/anomalyco/opencode/v2/install | bash
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
<div data-install-code>
|
||||
<CodeBlock
|
||||
code={`$ npm install -g @opencode-ai/cli@beta
|
||||
$ bun install -g --trust @opencode-ai/cli@beta
|
||||
$ pnpm add -g --allow-build=@opencode-ai/cli @opencode-ai/cli@beta
|
||||
$ yarn global add @opencode-ai/cli@beta
|
||||
$ curl -fsSL https://opencode.ai/v2/install | bash`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
The package uses a trusted postinstall script to select the native `opencode2` binary for your platform. The Bun and pnpm
|
||||
commands above explicitly allow that script to run.
|
||||
|
||||
### Homebrew
|
||||
|
||||
Homebrew installation is not available in beta.
|
||||
|
||||
### Arch Linux
|
||||
|
||||
Arch Linux installation is not available in beta.
|
||||
|
||||
### Windows
|
||||
|
||||
<Callout type="tip">
|
||||
For the best experience on Windows, install [Windows Subsystem for Linux
|
||||
(WSL)](https://learn.microsoft.com/windows/wsl/install), open your Linux distribution, and use one of the beta package
|
||||
manager commands above.
|
||||
</Callout>
|
||||
|
||||
<Tabs>
|
||||
<Tab title="chocolatey">Chocolatey installation is not available in beta.</Tab>
|
||||
<Tab title="scoop">Scoop installation is not available in beta.</Tab>
|
||||
<Tab title="mise">Mise installation is not available in beta.</Tab>
|
||||
<Tab title="docker">Docker installation is not available in beta.</Tab>
|
||||
</Tabs>
|
||||
|
||||
Standalone binaries are not available in beta.
|
||||
|
||||
---
|
||||
|
||||
#### Prerequisites
|
||||
|
||||
To use OpenCode in your terminal, you'll need:
|
||||
|
||||
1. A modern terminal emulator like:
|
||||
- [Ghostty](https://ghostty.org), Linux and macOS
|
||||
- [WezTerm](https://wezterm.org), cross-platform
|
||||
- [Alacritty](https://alacritty.org), cross-platform
|
||||
- [Kitty](https://sw.kovidgoyal.net/kitty/), Linux and macOS
|
||||
2. API keys for the LLM providers you want to use.
|
||||
Homebrew, Arch Linux, Windows package managers, Docker, and standalone binaries are not supported during the beta.
|
||||
|
||||
---
|
||||
|
||||
## Connect
|
||||
|
||||
With OpenCode you can use any LLM provider by configuring its API key.
|
||||
OpenCode has built in support for many LLM providers - you can connect to them
|
||||
directly [in the TUI](/cli/providers) with `/connect`.
|
||||
|
||||
Run `/connect` in the TUI and select your provider.
|
||||
|
||||
```text
|
||||
/connect
|
||||
```
|
||||
See [Providers](/providers) to configure custom providers.
|
||||
|
||||
If you'd like easy access to all the best coding models you can try out
|
||||
[OpenCode Console](https://console.opencode.ai).
|
||||
@@ -98,58 +40,9 @@ If you'd like easy access to all the best coding models you can try out
|
||||
You can also try [OpenCode Go](https://opencode.ai/go) a $10/month subscription
|
||||
plan that grants you access to the best open source models.
|
||||
|
||||
Use `/models` to browse the providers and models available to your project. See [Providers](/providers) for connection and
|
||||
configuration details.
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
You are now ready to use OpenCode in your project. Here are a few common workflows.
|
||||
|
||||
### Ask questions
|
||||
|
||||
Ask OpenCode to explain your codebase.
|
||||
|
||||
<Callout type="tip">Use `@` to fuzzy search for files in the project.</Callout>
|
||||
|
||||
```text
|
||||
How is authentication handled in @packages/functions/src/api/index.ts
|
||||
```
|
||||
|
||||
### Add features
|
||||
|
||||
Ask OpenCode to add a feature by describing the desired behavior and providing relevant context.
|
||||
|
||||
```text
|
||||
When a user deletes a note, flag it as deleted in the database.
|
||||
Create a screen that shows recently deleted notes.
|
||||
From this screen, the user can restore a note or permanently delete it.
|
||||
```
|
||||
|
||||
<Callout type="tip">Give OpenCode plenty of context and examples.</Callout>
|
||||
|
||||
### Undo changes
|
||||
|
||||
Use `/undo` when a change isn't what you wanted.
|
||||
|
||||
```text
|
||||
/undo
|
||||
```
|
||||
|
||||
OpenCode stages a conversation revert and restores your original message so you can revise it. In a Git repository, it
|
||||
also restores file changes when snapshots were captured successfully. Run `/undo` multiple times to move the conversation
|
||||
boundary back, or use `/redo` to restore the staged conversation and files. See [Undo](/snapshots) for
|
||||
limitations and safety details.
|
||||
|
||||
```text
|
||||
/redo
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Customize
|
||||
|
||||
Make OpenCode your own by [picking a theme](/themes), [customizing
|
||||
keybinds](https://opencode.ai/docs/keybinds), [configuring formatters](/formatters), [creating commands](/commands), or
|
||||
editing the [OpenCode config](/config).
|
||||
Make OpenCode your own by editing the [OpenCode config](/config), [connecting MCP servers](/mcp-servers), or [creating
|
||||
commands](/commands). For terminal interface themes and keybindings, see [CLI configuration](/cli/config).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { defineMeta } from "blume"
|
||||
|
||||
export default defineMeta({
|
||||
pages: ["index", "migrate-v1", "config", "troubleshooting", "configure", "build"],
|
||||
pages: ["cli", "build", "index", "config", "configure", "migrate-v1", "troubleshooting"],
|
||||
})
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
---
|
||||
title: "Migrate from V1"
|
||||
description: "Move from OpenCode V1 to the OpenCode 2.0 beta."
|
||||
---
|
||||
|
||||
<Callout type="note">
|
||||
OpenCode 1 and OpenCode 2 can be installed side by side. V1 runs as `opencode`, while V2 installs and runs separately
|
||||
as `opencode2`.
|
||||
</Callout>
|
||||
OpenCode 1 and OpenCode 2 can be installed side by side. V1 runs as `opencode`, while V2 installs and runs separately as
|
||||
`opencode2`.
|
||||
|
||||
## Breaking changes
|
||||
|
||||
@@ -14,7 +11,8 @@ V2 has three intentional breaking changes:
|
||||
|
||||
- [Plugins](#plugins) use a new plugin API.
|
||||
- The [server API and clients](#server-api-and-clients) have new contracts.
|
||||
- [TUI configuration](#tui-configuration) moves from layered `tui.json(c)` files to one global `cli.json` file (auto migrated).
|
||||
- [Terminal client configuration](/cli/config) moves from layered `tui.json(c)` files to one global `cli.json` file (auto
|
||||
migrated).
|
||||
|
||||
Supported V1 functionality outside those areas is intended to remain compatible with V1. Some fields accepted by the V1
|
||||
schema never had a V2 equivalent and are intentionally ignored; these are listed under
|
||||
@@ -25,8 +23,8 @@ should continue to work without changes. If supported behavior described in this
|
||||
beta compatibility bug rather than an expected migration requirement.
|
||||
|
||||
<Callout type="tip">
|
||||
Run `/report` if supported V1 functionality does not work in V2. The report skill collects diagnostics and helps you
|
||||
file a compatibility issue.
|
||||
If supported V1 functionality does not work in V2, follow the issue-reporting guidance in
|
||||
[Troubleshooting](/troubleshooting) and file a compatibility issue.
|
||||
</Callout>
|
||||
|
||||
<Callout type="warning">
|
||||
@@ -35,17 +33,7 @@ beta compatibility bug rather than an expected migration requirement.
|
||||
|
||||
## Install the beta
|
||||
|
||||
Install the beta from the `beta` distribution tag:
|
||||
|
||||
```bash
|
||||
npm install -g @opencode-ai/cli@beta
|
||||
```
|
||||
|
||||
Start it in your project with:
|
||||
|
||||
```bash
|
||||
opencode2
|
||||
```
|
||||
The V2 terminal client is published on the `beta` distribution tag. See the [terminal startup guide](/cli).
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -430,19 +418,17 @@ they are not mistaken for active configuration:
|
||||
|
||||
- `logLevel`: use `OPENCODE_LOG_LEVEL` when starting OpenCode.
|
||||
- `server`: use the V2 service and explicit server options; the server API is an intentional breaking change.
|
||||
- `layout`: remove it; V1 already treated it as deprecated and always used stretch layout.
|
||||
- Top-level `subagent_depth`: use `experimental.subagent_depth` instead.
|
||||
- `compaction.tail_turns` and `compaction.prune`: V2 uses `compaction.keep.tokens` and checkpoint-based compaction instead.
|
||||
- Agent `name` inside V1 JSON configuration.
|
||||
- An enabled-only V1 MCP entry without a `type`.
|
||||
- V1 experimental fields `disable_paste_summary`, `batch_tool`, `openTelemetry`, `primary_tools`, and
|
||||
`continue_loop_on_deny`.
|
||||
- V1 experimental fields `batch_tool`, `openTelemetry`, `primary_tools`, and `continue_loop_on_deny`.
|
||||
- V1 provider fields `id`, `whitelist`, and `blacklist`.
|
||||
- V1 provider-model fields `release_date`, `attachment`, `reasoning`, `temperature`, `experimental`, a non-`deprecated`
|
||||
`status`, and boolean `interleaved`.
|
||||
|
||||
Ignoring these fields is intentional and is not a compatibility regression. If V2 does not preserve behavior identified
|
||||
as supported elsewhere in this guide, run `/report`.
|
||||
as supported elsewhere in this guide, follow the issue-reporting guidance in [Troubleshooting](/troubleshooting).
|
||||
|
||||
### Agent files
|
||||
|
||||
@@ -507,60 +493,21 @@ Existing `AGENTS.md` files stay in place. V2 discovers the global `~/.config/ope
|
||||
files from the current directory up to home. For projects outside home, discovery stops at the project root.
|
||||
|
||||
If a V1 setup relied on a `CLAUDE.md` fallback, move that guidance into the applicable `AGENTS.md`. V2 currently only
|
||||
discovers `AGENTS.md`; because non-API V1 behavior is intended to remain compatible, also run `/report` with the affected
|
||||
project details. See [Instructions](/instructions).
|
||||
discovers `AGENTS.md`; because non-API V1 behavior is intended to remain compatible, also file a compatibility issue with
|
||||
the affected project details. See [Instructions](/instructions).
|
||||
|
||||
## TUI configuration
|
||||
## Terminal client configuration
|
||||
|
||||
V1 loaded `tui.json(c)` from the global config directory and from project directories discovered while walking up from
|
||||
the current directory. V2 instead stores CLI and TUI settings in one global file:
|
||||
V2 replaces layered V1 `tui.json(c)` files with one global terminal client configuration file:
|
||||
|
||||
```text
|
||||
~/.config/opencode/cli.json
|
||||
```
|
||||
|
||||
The CLI owns this file. The background service does not load it, and V2 does not discover or merge project-local
|
||||
`tui.json(c)` or `cli.json` files.
|
||||
|
||||
The native V2 format groups related settings. For example:
|
||||
|
||||
```jsonc
|
||||
// V1: ~/.config/opencode/tui.json
|
||||
{
|
||||
"theme": "tokyonight",
|
||||
"scroll_speed": 2,
|
||||
"scroll_acceleration": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
|
||||
// V2: ~/.config/opencode/cli.json
|
||||
{
|
||||
"theme": {
|
||||
"name": "tokyonight"
|
||||
},
|
||||
"scroll": {
|
||||
"speed": 2,
|
||||
"acceleration": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
V2 migrates the global TUI configuration automatically. On the first CLI or TUI startup, when `cli.json` does not already
|
||||
exist, it:
|
||||
|
||||
- Reads `~/.config/opencode/tui.json`.
|
||||
- Reads persisted TUI preferences from the legacy `kv.json` state file.
|
||||
- Converts supported settings to the native grouped format and writes `~/.config/opencode/cli.json`.
|
||||
- Leaves the V1 files unchanged so V1 can continue using them.
|
||||
|
||||
Migration runs only while `cli.json` is absent. Once that file exists, V2 treats it as the source of truth and does not
|
||||
continually synchronize later changes from `tui.json` or `kv.json`. If you created `cli.json` before starting V2, merge any
|
||||
V1 settings you still need into it manually.
|
||||
|
||||
Project-local V1 TUI configuration is not migrated because V2 has no project-local CLI configuration. Move settings you
|
||||
still want into the global `cli.json`; when multiple projects used different values for the same setting, choose the
|
||||
global behavior you want V2 to use.
|
||||
The terminal client owns this file; the background service does not load it. When `cli.json` is absent, the first V2
|
||||
terminal client startup migrates supported global `tui.json` settings and persisted preferences while leaving V1 files
|
||||
unchanged. Project-local client configuration is not migrated because V2 client configuration is global. See
|
||||
[CLI config](/cli/config) for current client settings.
|
||||
|
||||
## Plugins
|
||||
|
||||
@@ -610,6 +557,6 @@ request types, and responses.
|
||||
|
||||
## Verify your setup
|
||||
|
||||
Start `opencode2` in a project and verify your model, provider credentials, agents, permissions, MCP servers, and plugins
|
||||
before relying on the beta for regular work. Keep your V1 setup until you have confirmed the V2 behavior you need, and do
|
||||
not point V1 at configuration that you have converted to the native V2 shape.
|
||||
Verify your model, provider credentials, agents, permissions, MCP servers, and plugins in a project before relying on the
|
||||
beta for regular work. Keep your V1 setup until you have confirmed the V2 behavior you need, and do not point V1 at
|
||||
configuration that you have converted to the native V2 shape.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
---
|
||||
title: "Troubleshooting"
|
||||
description: "Diagnose OpenCode startup, server, and session issues."
|
||||
---
|
||||
|
||||
<Callout type="tip">
|
||||
@@ -8,8 +7,8 @@ description: "Diagnose OpenCode startup, server, and session issues."
|
||||
the steps below, inspect its service and logs, and help identify the issue.
|
||||
</Callout>
|
||||
|
||||
OpenCode runs as two processes: the TUI is a client, while a background server owns sessions, plugins, permissions, and
|
||||
other application state. Start by determining whether an issue is in the client, the shared server, or a specific project.
|
||||
OpenCode uses a client-server architecture. A background server owns sessions, plugins, permissions, and other application
|
||||
state. Start by determining whether an issue is in a client, the shared server, or a specific project.
|
||||
|
||||
## Check the background service
|
||||
|
||||
@@ -31,12 +30,6 @@ If the service is stuck or unhealthy, restart it:
|
||||
opencode2 service restart
|
||||
```
|
||||
|
||||
From inside the TUI, run `/restart` to restart the managed service and reconnect:
|
||||
|
||||
```text
|
||||
/restart
|
||||
```
|
||||
|
||||
You can also stop and start it explicitly:
|
||||
|
||||
```bash
|
||||
@@ -49,21 +42,10 @@ opencode2 service start
|
||||
needed when diagnosing its lifecycle.
|
||||
</Callout>
|
||||
|
||||
## Run an isolated session
|
||||
|
||||
Use standalone mode to run the TUI with a private server that exits with it:
|
||||
|
||||
```bash
|
||||
opencode2 --standalone
|
||||
```
|
||||
|
||||
If an issue disappears in standalone mode, it is likely related to the shared background service rather than the TUI or
|
||||
project itself.
|
||||
|
||||
## Inspect the API
|
||||
|
||||
The `api` command uses the same discovery and authentication flow as the TUI. It accepts either an HTTP method and path or
|
||||
an OpenAPI operation ID.
|
||||
The `api` command uses the local service discovery and authentication flow. It accepts either an HTTP method and path or an
|
||||
OpenAPI operation ID.
|
||||
|
||||
See the [API reference](/api) for all endpoints and operation IDs.
|
||||
|
||||
@@ -87,21 +69,14 @@ Follow the log while reproducing the problem:
|
||||
tail -f ~/.local/share/opencode/log/opencode.log
|
||||
```
|
||||
|
||||
Each line includes a process `run` ID and a `role` field. Use `role=cli` for TUI and command startup, and `role=server` for
|
||||
session, provider, plugin, permission, and tool activity.
|
||||
Each line includes a process `run` ID and a `role` field. Use `role=server` for session, provider, plugin, permission, and
|
||||
tool activity.
|
||||
|
||||
```bash
|
||||
grep 'role=cli' ~/.local/share/opencode/log/opencode.log
|
||||
grep 'role=server' ~/.local/share/opencode/log/opencode.log
|
||||
grep 'run=8fc3b1d5' ~/.local/share/opencode/log/opencode.log
|
||||
```
|
||||
|
||||
Increase verbosity for one reproduction:
|
||||
|
||||
```bash
|
||||
OPENCODE_LOG_LEVEL=DEBUG opencode2
|
||||
```
|
||||
|
||||
## Service files
|
||||
|
||||
The shared server registers itself at:
|
||||
@@ -129,17 +104,6 @@ The database normally lives at:
|
||||
daemon, and make a backup before inspecting persistent data with external tools.
|
||||
</Callout>
|
||||
|
||||
## Explicit servers
|
||||
|
||||
When connecting with `--server`, set `OPENCODE_PASSWORD` if the server requires authentication:
|
||||
|
||||
```bash
|
||||
OPENCODE_PASSWORD=secret opencode2 --server http://127.0.0.1:4096
|
||||
```
|
||||
|
||||
The CLI checks the server before opening the TUI and reports whether it is unreachable, requires a password, or rejected
|
||||
the supplied password.
|
||||
|
||||
## Report an issue
|
||||
|
||||
Include the following when reporting a reproducible problem:
|
||||
@@ -147,31 +111,9 @@ Include the following when reporting a reproducible problem:
|
||||
- Output from `opencode2 --version`
|
||||
- Output from `opencode2 service status`
|
||||
- The smallest sequence of steps that reproduces the issue
|
||||
- Whether the issue also occurs with `opencode2 --standalone`
|
||||
- Whether the issue affects the shared service, a specific client, or one project
|
||||
- Relevant log lines, including their `run` and `role` fields
|
||||
|
||||
Remove API keys, authorization headers, prompts, file contents, and other sensitive data before sharing logs.
|
||||
|
||||
## Local development
|
||||
|
||||
When working from the OpenCode repository, run V2 commands from the repository root:
|
||||
|
||||
```bash
|
||||
bun dev
|
||||
```
|
||||
|
||||
The local development channel keeps its logs, SQLite database, and service registration separate from installed builds:
|
||||
|
||||
```text
|
||||
~/.local/share/opencode/log/opencode-local.log
|
||||
~/.local/share/opencode/opencode-local.db
|
||||
~/.local/state/opencode/service-local.json
|
||||
```
|
||||
|
||||
Use the same diagnostics through the package development command:
|
||||
|
||||
```bash
|
||||
bun dev service status
|
||||
bun dev service restart
|
||||
bun dev api get /api/health
|
||||
```
|
||||
File reproducible problems in [GitHub Issues](https://github.com/anomalyco/opencode/issues).
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"doctor": "blume doctor"
|
||||
},
|
||||
"dependencies": {
|
||||
"blume": "1.1.4"
|
||||
"blume": "1.5.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/cloudflare": "14.1.4",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
export const prerender = false
|
||||
|
||||
return fetch("https://raw.githubusercontent.com/anomalyco/opencode/v2/install")
|
||||
---
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 58 KiB |
@@ -1,10 +1,22 @@
|
||||
<svg width="234" height="42" viewBox="0 0 234 42" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 30H6V18H18V30Z" fill="#4B4646"/><path d="M18 12H6V30H18V12ZM24 36H0V6H24V36Z" fill="#B7B1B1"/>
|
||||
<path d="M48 30H36V18H48V30Z" fill="#4B4646"/><path d="M36 30H48V12H36V30ZM54 36H36V42H30V6H54V36Z" fill="#B7B1B1"/>
|
||||
<path d="M84 24V30H66V24H84Z" fill="#4B4646"/><path d="M84 24H66V30H84V36H60V6H84V24ZM66 18H78V12H66V18Z" fill="#B7B1B1"/>
|
||||
<path d="M108 36H96V18H108V36Z" fill="#4B4646"/><path d="M108 12H96V36H90V6H108V12ZM114 36H108V12H114V36Z" fill="#B7B1B1"/>
|
||||
<path d="M144 30H126V18H144V30Z" fill="#4B4646"/><path d="M144 12H126V30H144V36H120V6H144V12Z" fill="#F1ECEC"/>
|
||||
<path d="M168 30H156V18H168V30Z" fill="#4B4646"/><path d="M168 12H156V30H168V12ZM174 36H150V6H174V36Z" fill="#F1ECEC"/>
|
||||
<path d="M198 30H186V18H198V30Z" fill="#4B4646"/><path d="M198 12H186V30H198V12ZM204 36H180V6H198V0H204V36Z" fill="#F1ECEC"/>
|
||||
<path d="M234 24V30H216V24H234Z" fill="#4B4646"/><path d="M216 12V18H228V12H216ZM234 24H216V30H234V36H210V6H234V24Z" fill="#F1ECEC"/>
|
||||
<svg width="641" height="115" viewBox="0 0 641 115" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1401_86315)">
|
||||
<mask id="mask0_1401_86315" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="641" height="115">
|
||||
<path d="M640.714 0H0V115H640.714V0Z" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_1401_86315)">
|
||||
<path d="M49.2857 32.8573H16.4286V82.143H49.2857V32.8573ZM65.7143 98.5716H0V16.4287H65.7143V98.5716Z" fill="white"/>
|
||||
<path d="M98.5692 82.143H131.426V32.8573H98.5692V82.143ZM147.855 98.5716H98.5692V115H82.1406V16.4287H147.855V98.5716Z" fill="white"/>
|
||||
<path d="M230.003 65.7144H180.718V82.143H230.003V98.5716H164.289V16.4287H230.003V65.7144ZM180.718 49.2859H213.575V32.8573H180.718V49.2859Z" fill="white"/>
|
||||
<path d="M295.715 32.8573H262.858V98.5716H246.43V16.4287H295.715V32.8573ZM312.144 98.5716H295.715V32.8573H312.144V98.5716Z" fill="white"/>
|
||||
<path d="M394.285 32.8573H344.999V82.143H394.285V98.5716H328.57V16.4287H394.285V32.8573Z" fill="white"/>
|
||||
<path d="M459.997 32.8573H427.14V82.143H459.997V32.8573ZM476.425 98.5716H410.711V16.4287H476.425V98.5716Z" fill="white"/>
|
||||
<path d="M542.145 32.8571H509.288V82.1429H542.145V32.8571ZM558.574 98.5714H492.859V16.4286H542.145V0H558.574V98.5714Z" fill="white"/>
|
||||
<path d="M591.429 32.8573V49.2859H624.286V32.8573H591.429ZM640.714 65.7144H591.429V82.143H640.714V98.5716H575V16.4287H640.714V65.7144Z" fill="white"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1401_86315">
|
||||
<rect width="640.714" height="115" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1,10 +1,22 @@
|
||||
<svg width="234" height="42" viewBox="0 0 234 42" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 30H6V18H18V30Z" fill="#CFCECD"/><path d="M18 12H6V30H18V12ZM24 36H0V6H24V36Z" fill="#656363"/>
|
||||
<path d="M48 30H36V18H48V30Z" fill="#CFCECD"/><path d="M36 30H48V12H36V30ZM54 36H36V42H30V6H54V36Z" fill="#656363"/>
|
||||
<path d="M84 24V30H66V24H84Z" fill="#CFCECD"/><path d="M84 24H66V30H84V36H60V6H84V24ZM66 18H78V12H66V18Z" fill="#656363"/>
|
||||
<path d="M108 36H96V18H108V36Z" fill="#CFCECD"/><path d="M108 12H96V36H90V6H108V12ZM114 36H108V12H114V36Z" fill="#656363"/>
|
||||
<path d="M144 30H126V18H144V30Z" fill="#CFCECD"/><path d="M144 12H126V30H144V36H120V6H144V12Z" fill="#211E1E"/>
|
||||
<path d="M168 30H156V18H168V30Z" fill="#CFCECD"/><path d="M168 12H156V30H168V12ZM174 36H150V6H174V36Z" fill="#211E1E"/>
|
||||
<path d="M198 30H186V18H198V30Z" fill="#CFCECD"/><path d="M198 12H186V30H198V12ZM204 36H180V6H198V0H204V36Z" fill="#211E1E"/>
|
||||
<path d="M234 24V30H216V24H234Z" fill="#CFCECD"/><path d="M216 12V18H228V12H216ZM234 24H216V30H234V36H210V6H234V24Z" fill="#211E1E"/>
|
||||
<svg width="640" height="115" viewBox="0 0 640 115" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1401_86353)">
|
||||
<mask id="mask0_1401_86353" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="640" height="115">
|
||||
<path d="M640 0H0V115H640V0Z" fill="white"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_1401_86353)">
|
||||
<path d="M49.2308 32.8573H16.4103V82.143H49.2308V32.8573ZM65.641 98.5716H0V16.4287H65.641V98.5716Z" fill="black"/>
|
||||
<path d="M98.4649 82.143H131.285V32.8573H98.4649V82.143ZM147.696 98.5716H98.4649V115H82.0547V16.4287H147.696V98.5716Z" fill="black"/>
|
||||
<path d="M229.743 65.7144H180.512V82.143H229.743V98.5716H164.102V16.4287H229.743V65.7144ZM180.512 49.2859H213.332V32.8573H180.512V49.2859Z" fill="black"/>
|
||||
<path d="M295.387 32.8573H262.567V98.5716H246.156V16.4287H295.387V32.8573ZM311.797 98.5716H295.387V32.8573H311.797V98.5716Z" fill="black"/>
|
||||
<path d="M393.844 32.8573H344.613V82.143H393.844V98.5716H328.203V16.4287H393.844V32.8573Z" fill="black"/>
|
||||
<path d="M459.489 32.8573H426.668V82.143H459.489V32.8573ZM475.899 98.5716H410.258V16.4287H475.899V98.5716Z" fill="black"/>
|
||||
<path d="M541.535 32.8571H508.715V82.1428H541.535V32.8571ZM557.946 98.5714H492.305V16.4286H541.535V0H557.946V98.5714Z" fill="black"/>
|
||||
<path d="M590.77 32.8573V49.2859H623.59V32.8573H590.77ZM640 65.7144H590.77V82.143H640V98.5716H574.359V16.4287H640V65.7144Z" fill="black"/>
|
||||
</g>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1401_86353">
|
||||
<rect width="640" height="115" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,105 @@
|
||||
:root {
|
||||
--blume-content-width: 650px;
|
||||
}
|
||||
|
||||
:root[data-theme="dark"] {
|
||||
--blume-foreground: #ffffff;
|
||||
}
|
||||
|
||||
::view-transition-group(*),
|
||||
::view-transition-old(*),
|
||||
::view-transition-new(*) {
|
||||
animation: none !important;
|
||||
}
|
||||
|
||||
[data-blume-doc-grid] {
|
||||
width: 100%;
|
||||
max-width: 1152px;
|
||||
}
|
||||
|
||||
[data-blume-header] {
|
||||
width: 100%;
|
||||
max-width: 1152px;
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
@media (min-width: 64rem) {
|
||||
[data-blume-doc-grid] {
|
||||
grid-template-columns: 15rem minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 80rem) {
|
||||
[data-blume-doc-grid]:has(> aside[aria-label="On this page"]) {
|
||||
grid-template-columns: minmax(0, 1fr) minmax(0, 730px) minmax(0, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
[data-blume-toc] > p:first-child {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-blume-page-actions] > details:has([data-open-in]) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:is([data-blume-nav-drawer], [data-blume-toc]) {
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
:is([data-blume-nav-drawer], [data-blume-toc])::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
[data-install-code] pre code {
|
||||
overflow-wrap: anywhere;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.prose pre {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.prose pre[data-language] {
|
||||
padding-top: 2.75rem;
|
||||
}
|
||||
|
||||
.prose pre[data-language]::before {
|
||||
border-bottom: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.prose pre > code {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.prose {
|
||||
color: var(--blume-foreground);
|
||||
}
|
||||
|
||||
.prose a:not(.blume-heading-anchor, [data-blume-card]) {
|
||||
color: var(--blume-accent);
|
||||
}
|
||||
|
||||
.prose h1 {
|
||||
font-size: 1.875rem;
|
||||
line-height: 1.2;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.prose h2 {
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.prose h3 {
|
||||
font-size: 1rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.prose h4 {
|
||||
font-size: 1rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
Reference in New Issue
Block a user