@@ -0,0 +1,57 @@
|
||||
# stanp-opencode
|
||||
|
||||
OpenCode V2 plugin providing a `coordinate` agent and fast/good/deep worker pairs, with GPT routing or explicit custom model assignments. Your default agent and the built-in `build` agent remain unchanged.
|
||||
|
||||
## Install the latest release
|
||||
|
||||
Requires **OpenCode V2** (`opencode2`), **Bun 1.3.14+**, Bash, curl, jq, and `sha256sum` (Linux/WSL). The native plugin API is pinned to `@opencode/plugin@0.0.0-beta-19378`; use the matching OpenCode beta.
|
||||
|
||||
Download and inspect [install.sh](install.sh), then run it without sudo:
|
||||
|
||||
```sh
|
||||
curl --fail --show-error --location \
|
||||
https://git.krtss.de/StanPonomarev/stanp-opencode/raw/branch/main/install.sh \
|
||||
--output install.sh
|
||||
bash install.sh
|
||||
```
|
||||
|
||||
From a checkout, run `bash install.sh` directly. Rerun the same script to upgrade to the latest published, non-prerelease Gitea release.
|
||||
|
||||
The installer downloads `stanp-opencode.tgz` and its SHA-256 checksum, verifies the archive, and installs its dependencies with lifecycle scripts disabled. It activates the plugin only after importing and checking the native V2 export. Downloads, dependency installation, and validation failures leave the previous active plugin untouched. The checksum detects corruption; it is not a signature independent of the release server.
|
||||
|
||||
Installation defaults to `~/.config/opencode` and respects `XDG_CONFIG_HOME`. Override it explicitly when needed:
|
||||
|
||||
```sh
|
||||
OPENCODE_CONFIG_DIR=/path/to/opencode-config bash install.sh
|
||||
```
|
||||
|
||||
The installer atomically updates the `plugins/stanp-opencode` symlink for [V2 automatic plugin discovery](https://opencode.ai/v2/docs/plugins), with dependencies in a private `stanp-opencode/install.*` directory beneath the same config directory. It does not edit `opencode.json` or `opencode.jsonc`, install OpenCode itself, or configure provider credentials. Older private installation directories are retained so running sessions can finish; remove unused ones after restarting OpenCode.
|
||||
|
||||
Restart `opencode2` after installation (or `opencode2 service restart` for an existing service). Connect your provider, then select `coordinate` in the agent picker. The default configuration uses OpenAI GPT models; agents are only enabled when the required models are available.
|
||||
|
||||
## Configure
|
||||
|
||||
See [GPT configuration](examples/gpt.opencode.jsonc) and [custom model assignments](examples/custom.opencode.jsonc). When using the installer, point the example's plugin package entry at the installed package directory rather than the unpublished npm package name:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"plugins": [
|
||||
{
|
||||
"package": "./plugins/stanp-opencode",
|
||||
"options": {
|
||||
"mode": "gpt",
|
||||
"provider": "openai",
|
||||
"lunaPriority": true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
This relative path assumes the configuration file is in the selected global config directory. Use an absolute path in project configuration. Remove any old V1 `plugin` entry when migrating; V2 uses `plugins`. `lunaPriority` requests priority service where supported and can increase cost; set it to `false` to use the provider default.
|
||||
|
||||
The plugin supplies session-local `todoread` and `todowrite` tools when no other plugin provides them. In this pinned V2 beta, custom tools cannot open permission prompts: an `ask` or `deny` rule blocks these todo tools rather than bypassing the rule. Explicitly allow them if you want to use them.
|
||||
|
||||
## Uninstall
|
||||
|
||||
Remove the `plugins/stanp-opencode` symlink from the selected config directory and remove any explicit configuration entry for it, then restart OpenCode. Once no running session uses it, the private `stanp-opencode` installation directory can also be removed.
|
||||
@@ -8,7 +8,8 @@
|
||||
"zod": "4.1.8",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opencode-ai/plugin": "1.18.30",
|
||||
"@opencode/client": "0.0.0-beta-19378",
|
||||
"@opencode/plugin": "0.0.0-beta-19378",
|
||||
"@oxlint/plugins": "1.82.0",
|
||||
"@types/bun": "1.3.14",
|
||||
"oxfmt": "0.67.0",
|
||||
@@ -16,13 +17,75 @@
|
||||
"typescript": "7.0.2",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opencode-ai/plugin": "^1.18.30",
|
||||
"@opencode/plugin": "0.0.0-beta-19378",
|
||||
},
|
||||
},
|
||||
},
|
||||
"packages": {
|
||||
"@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="],
|
||||
|
||||
"@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/sha256-browser": ["@aws-crypto/sha256-browser@5.2.0", "", { "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-crypto/supports-web-crypto": "^5.2.0", "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-locate-window": "^3.0.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw=="],
|
||||
|
||||
"@aws-crypto/sha256-js": ["@aws-crypto/sha256-js@5.2.0", "", { "dependencies": { "@aws-crypto/util": "^5.2.0", "@aws-sdk/types": "^3.222.0", "tslib": "^2.6.2" } }, "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA=="],
|
||||
|
||||
"@aws-crypto/supports-web-crypto": ["@aws-crypto/supports-web-crypto@5.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg=="],
|
||||
|
||||
"@aws-crypto/util": ["@aws-crypto/util@5.2.0", "", { "dependencies": { "@aws-sdk/types": "^3.222.0", "@smithy/util-utf8": "^2.0.0", "tslib": "^2.6.2" } }, "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ=="],
|
||||
|
||||
"@aws-sdk/client-cognito-identity": ["@aws-sdk/client-cognito-identity@3.1057.0", "", { "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", "@aws-sdk/core": "^3.974.15", "@aws-sdk/credential-provider-node": "^3.972.47", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/fetch-http-handler": "^5.4.5", "@smithy/node-http-handler": "^4.7.5", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-5MliYkp2u0+2arTp5fZIaxl+xmm90LEKv/VeSxhfNQW4t0fvWJrNO429/jchWQenNoDRrOGE59VfbuZUfwFujg=="],
|
||||
|
||||
"@aws-sdk/core": ["@aws-sdk/core@3.977.9", "", { "dependencies": { "@aws-sdk/types": "^3.974.5", "@aws-sdk/xml-builder": "^3.972.40", "@aws/lambda-invoke-store": "^0.3.0", "@smithy/core": "^3.33.3", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.17.2", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "sha512-reqPFEQrZxDZpeGj4PFMepBeR5LGYHRqq/L0motTzgFkCRBA4rFdaVXDSLYyGHhxVz7sT2PDnPN9CluGSfgyJA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-cognito-identity": ["@aws-sdk/credential-provider-cognito-identity@3.972.69", "", { "dependencies": { "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-vpsh9VWmQVC/nsdzf72F2yUMBOFT1aq+hoLseYV03zjVXVHkjqSNJskFRKPFxc3MRFrHNbSSmOwsbYE15u9ecw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-env": ["@aws-sdk/credential-provider-env@3.972.70", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-H404B7dJl2mCrBqahDEYsanB0xhdDp6tXnXcTUnXmmpy2Q3J0Ho0bUajZ2jr/RdwzCyS59Gi8xXIFwPLGBl6Uw=="],
|
||||
|
||||
"@aws-sdk/credential-provider-http": ["@aws-sdk/credential-provider-http@3.972.72", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/fetch-http-handler": "^5.7.2", "@smithy/node-http-handler": "^4.11.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-X98zYOrVOeuosCX+6ktf29FC2N2GHPLia7qv6mzPzTc+RPAuHWCDS++Z6JK7eGYqb/v6uaW7bAXaOvDBfol+0w=="],
|
||||
|
||||
"@aws-sdk/credential-provider-ini": ["@aws-sdk/credential-provider-ini@3.973.15", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/credential-provider-env": "^3.972.70", "@aws-sdk/credential-provider-http": "^3.972.72", "@aws-sdk/credential-provider-login": "^3.972.77", "@aws-sdk/credential-provider-process": "^3.972.70", "@aws-sdk/credential-provider-sso": "^3.973.14", "@aws-sdk/credential-provider-web-identity": "^3.972.76", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-Rykg6s5ceBuynMOGWgoowO4N+27JfnqXAnVaSunZl0hOO1XodSrxGNz6sCEbnmS0lAfQZDKyb3fbr46gSuv6Sg=="],
|
||||
|
||||
"@aws-sdk/credential-provider-login": ["@aws-sdk/credential-provider-login@3.972.77", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-Jb59xfEISoN5mmbnA+HYqdtrSX3CgCtJoof+V5D8/TgUI56W63GEEd5Y58WijU3Ou6+WEgaLD1feVzaRXV5IDQ=="],
|
||||
|
||||
"@aws-sdk/credential-provider-node": ["@aws-sdk/credential-provider-node@3.972.82", "", { "dependencies": { "@aws-sdk/credential-provider-env": "^3.972.70", "@aws-sdk/credential-provider-http": "^3.972.72", "@aws-sdk/credential-provider-ini": "^3.973.15", "@aws-sdk/credential-provider-process": "^3.972.70", "@aws-sdk/credential-provider-sso": "^3.973.14", "@aws-sdk/credential-provider-web-identity": "^3.972.76", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/credential-provider-imds": "^4.4.16", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-znDkEOGXB8W3kG1LJUKP3foBZY/9qLM0eil/DxWXSp37XsdsRLQHE/d/OaCGGVgKpA6znR38h/+INk8do1FjiA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-process": ["@aws-sdk/credential-provider-process@3.972.70", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-2ry03fGRJr4sV3jI+ocjj5JqALnFD6ymM5KiNCDZMvq8bX2GSbE0vji4aM43TVCl2nXqqLRZaUxdq/KeWRAY4Q=="],
|
||||
|
||||
"@aws-sdk/credential-provider-sso": ["@aws-sdk/credential-provider-sso@3.973.14", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/token-providers": "3.1116.0", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-jkhg/8ocAAoc0RFyLMhCw+/zZh7gystQgd4F4hznNa8P4Cc501PQmxd+jGLiMHodPJ+7Zv/3znM62gZojyasmA=="],
|
||||
|
||||
"@aws-sdk/credential-provider-web-identity": ["@aws-sdk/credential-provider-web-identity@3.972.76", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-d3AGyVu759PGr35mEB2s22xxlNEA5rpdxtSPJthfPFJvoQ8dt357iVPECqWfUxXp1toJAvKmbtcIYVGigaGsCA=="],
|
||||
|
||||
"@aws-sdk/credential-providers": ["@aws-sdk/credential-providers@3.1057.0", "", { "dependencies": { "@aws-sdk/client-cognito-identity": "3.1057.0", "@aws-sdk/core": "^3.974.15", "@aws-sdk/credential-provider-cognito-identity": "^3.972.38", "@aws-sdk/credential-provider-env": "^3.972.41", "@aws-sdk/credential-provider-http": "^3.972.43", "@aws-sdk/credential-provider-ini": "^3.972.46", "@aws-sdk/credential-provider-login": "^3.972.45", "@aws-sdk/credential-provider-node": "^3.972.47", "@aws-sdk/credential-provider-process": "^3.972.41", "@aws-sdk/credential-provider-sso": "^3.972.45", "@aws-sdk/credential-provider-web-identity": "^3.972.45", "@aws-sdk/nested-clients": "^3.997.13", "@aws-sdk/types": "^3.973.9", "@smithy/core": "^3.24.5", "@smithy/credential-provider-imds": "^4.3.6", "@smithy/types": "^4.14.2", "tslib": "^2.6.2" } }, "sha512-rbrEHtz11g0kxsSkYr3fx2HABNNblp4AhB2MgPvJHgYOWfJ2eBviU7Mvoaef0PW8QH6lbZDfJcnM7eKvtvz3sw=="],
|
||||
|
||||
"@aws-sdk/nested-clients": ["@aws-sdk/nested-clients@3.997.44", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/signature-v4-multi-region": "^3.996.46", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/fetch-http-handler": "^5.7.2", "@smithy/node-http-handler": "^4.11.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-NhEgryjlBF9w38ZXqGymQV28IhkYa1mKhlbYnqIis57AYwWGVYfUPgg/qC2rLRqOUfblxx++irvju10kVTa8Vw=="],
|
||||
|
||||
"@aws-sdk/signature-v4-multi-region": ["@aws-sdk/signature-v4-multi-region@3.996.46", "", { "dependencies": { "@aws-sdk/types": "^3.974.5", "@smithy/signature-v4": "^5.6.12", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-L+2xZTye/2T96f3lwCws0Zw6GG2JHZW9e8FpVgGBeeExSKyeoZ6CWRpBml/7DNiK/O26jrgPM9F+Ay8VkgzUWQ=="],
|
||||
|
||||
"@aws-sdk/token-providers": ["@aws-sdk/token-providers@3.1116.0", "", { "dependencies": { "@aws-sdk/core": "^3.977.9", "@aws-sdk/nested-clients": "^3.997.44", "@aws-sdk/types": "^3.974.5", "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-ygIivKqh8aHzNkucOCXHyIBgBpLPfrSI0mCqXF+vLBsPTUKqj0VSqAY0GFPe7lQl4HntjOcQ+KSyS7oUV2C54Q=="],
|
||||
|
||||
"@aws-sdk/types": ["@aws-sdk/types@3.974.5", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ=="],
|
||||
|
||||
"@aws-sdk/util-locate-window": ["@aws-sdk/util-locate-window@3.965.10", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-ycwH6Zd2GhuSqdXX9ihbCjeGTB6xOJs+O3+Jb8/zDG9978XU80qs75dfkPJRMNKe5MvBZPuNeFpd4JZKPoUF4g=="],
|
||||
|
||||
"@aws-sdk/xml-builder": ["@aws-sdk/xml-builder@3.972.40", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-wlFmCIGUlwF4zx/kncw+bmxTQh1HeSJq4mYV/V5cZUSJadDP3kXvGW8Rn21cimj/7y9ju+47oYWXi97vF7czaA=="],
|
||||
|
||||
"@aws/lambda-invoke-store": ["@aws/lambda-invoke-store@0.3.0", "", {}, "sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ=="],
|
||||
|
||||
"@effect/opentelemetry": ["@effect/opentelemetry@4.0.0-rc.112", "", { "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <2.0.0", "@opentelemetry/api-logs": ">=0.203.0 <0.300.0", "@opentelemetry/resources": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-logs": ">=0.203.0 <0.300.0", "@opentelemetry/sdk-metrics": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-base": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-node": ">=2.0.0 <3.0.0", "@opentelemetry/sdk-trace-web": ">=2.0.0 <3.0.0", "@opentelemetry/semantic-conventions": ">=1.33.0 <2.0.0", "effect": "^4.0.0-rc.112" }, "optionalPeers": ["@opentelemetry/api", "@opentelemetry/api-logs", "@opentelemetry/resources", "@opentelemetry/sdk-logs", "@opentelemetry/sdk-metrics", "@opentelemetry/sdk-trace-base", "@opentelemetry/sdk-trace-node", "@opentelemetry/sdk-trace-web"] }, "sha512-OTRv1DxTHUmnakgJ6XVM8wVgF1KgZH4UXnOemwSLUwUjXO+RCikzF8oR/rlVmOGq81KtQzj1URM4M4nchlQOuQ=="],
|
||||
|
||||
"@effect/platform-node": ["@effect/platform-node@4.0.0-rc.112", "", { "dependencies": { "@effect/platform-node-shared": "^4.0.0-rc.112", "mime": "^4.1.0", "undici": "^8.10.0" }, "peerDependencies": { "effect": "^4.0.0-rc.112", "redis": ">=5.0.0 <7.0.0" } }, "sha512-/BMAcdNGQQskLmI0Zoa95KfTZkr9HV9N4NSxaSrusG6GeW6Ulp9KvZ+Rlaiw8lnOt43CXjFLdfll5/k5rxL4hQ=="],
|
||||
|
||||
"@effect/platform-node-shared": ["@effect/platform-node-shared@4.0.0-rc.112", "", { "dependencies": { "@types/ws": "^8.18.1", "ws": "^8.21.3" }, "peerDependencies": { "effect": "^4.0.0-rc.112" } }, "sha512-ttjz0xKamFN7vL8pNDYVwddJLjZvqKePc05djlz2VcdaKbLsnYbtMnL1rbOfHgEnIUSHGh7FkjaN4DM1Ov81sQ=="],
|
||||
|
||||
"@gar/promise-retry": ["@gar/promise-retry@1.0.3", "", {}, "sha512-GmzA9ckNokPypTg10pgpeHNQe7ph+iIKKmhKu3Ob9ANkswreCx7R3cKmY781K8QK3AqVL3xVh9A42JvIAbkkSA=="],
|
||||
|
||||
"@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="],
|
||||
|
||||
"@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="],
|
||||
|
||||
"@isaacs/string-locale-compare": ["@isaacs/string-locale-compare@1.1.0", "", {}, "sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ=="],
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w=="],
|
||||
@@ -35,9 +98,73 @@
|
||||
|
||||
"@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="],
|
||||
|
||||
"@opencode-ai/plugin": ["@opencode-ai/plugin@1.18.30", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode-ai/sdk": "1.18.30", "effect": "4.0.0-beta.83", "zod": "4.1.8" }, "peerDependencies": { "@opentui/core": ">=0.4.5", "@opentui/keymap": ">=0.4.5", "@opentui/solid": ">=0.4.5" }, "optionalPeers": ["@opentui/core", "@opentui/keymap", "@opentui/solid"] }, "sha512-bXWcA2VD478PXXke1qAYANTq58fCcbgY0GAUqZIFZqPpo48FoG8RH37nNZ78eHtz+ddiKIhFTBZJRaHF3IgFqw=="],
|
||||
"@npmcli/agent": ["@npmcli/agent@4.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.1", "lru-cache": "^11.2.1", "socks-proxy-agent": "^8.0.3" } }, "sha512-EUEuWAxnL07Sp5/iC/1X6Xj+XThUvnbei9zfRWZdEXa7lss9RTHMhAHBeg+MZ5To9s/gGaSI+UwZTPdYMvKSeg=="],
|
||||
|
||||
"@opencode-ai/sdk": ["@opencode-ai/sdk@1.18.30", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-uviJ+PZLc/D1szt33WGzzt/rqJ+IaNmRGBb+UcOXrcQANl8XXKJrp4CNQQ2UAnUJ3Ek+VqcamIwjtKHUW/OjOQ=="],
|
||||
"@npmcli/arborist": ["@npmcli/arborist@9.4.0", "", { "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/fs": "^5.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/map-workspaces": "^5.0.0", "@npmcli/metavuln-calculator": "^9.0.2", "@npmcli/name-from-folder": "^4.0.0", "@npmcli/node-gyp": "^5.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/query": "^5.0.0", "@npmcli/redact": "^4.0.0", "@npmcli/run-script": "^10.0.0", "bin-links": "^6.0.0", "cacache": "^20.0.1", "common-ancestor-path": "^2.0.0", "hosted-git-info": "^9.0.0", "json-stringify-nice": "^1.1.4", "lru-cache": "^11.2.1", "minimatch": "^10.0.3", "nopt": "^9.0.0", "npm-install-checks": "^8.0.0", "npm-package-arg": "^13.0.0", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "pacote": "^21.0.2", "parse-conflict-json": "^5.0.1", "proc-log": "^6.0.0", "proggy": "^4.0.0", "promise-all-reject-late": "^1.0.0", "promise-call-limit": "^3.0.1", "semver": "^7.3.7", "ssri": "^13.0.0", "treeverse": "^3.0.0", "walk-up-path": "^4.0.0" }, "bin": { "arborist": "bin/index.js" } }, "sha512-4Bm8hNixJG/sii1PMnag0V9i/sGOX9VRzFrUiZMSBJpGlLR38f+Btl85d07G9GL56xO0l0OZjvrGNYsDYp0xKA=="],
|
||||
|
||||
"@npmcli/config": ["@npmcli/config@10.8.1", "", { "dependencies": { "@npmcli/map-workspaces": "^5.0.0", "@npmcli/package-json": "^7.0.0", "ci-info": "^4.0.0", "ini": "^6.0.0", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "walk-up-path": "^4.0.0" } }, "sha512-MAYk9IlIGiyC0c9fnjdBSQfIFPZT0g1MfeSiD1UXTq2zJOLX55jS9/sETJHqw/7LN18JjITrhYfgCfapbmZHiQ=="],
|
||||
|
||||
"@npmcli/fs": ["@npmcli/fs@5.0.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-7OsC1gNORBEawOa5+j2pXN9vsicaIOH5cPXxoR6fJOmH6/EXpJB2CajXOu1fPRFun2m1lktEFX11+P89hqO/og=="],
|
||||
|
||||
"@npmcli/git": ["@npmcli/git@7.0.2", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/promise-spawn": "^9.0.0", "ini": "^6.0.0", "lru-cache": "^11.2.1", "npm-pick-manifest": "^11.0.1", "proc-log": "^6.0.0", "semver": "^7.3.5", "which": "^6.0.0" } }, "sha512-oeolHDjExNAJAnlYP2qzNjMX/Xi9bmu78C9dIGr4xjobrSKbuMYCph8lTzn4vnW3NjIqVmw/f8BCfouqyJXlRg=="],
|
||||
|
||||
"@npmcli/installed-package-contents": ["@npmcli/installed-package-contents@4.0.0", "", { "dependencies": { "npm-bundled": "^5.0.0", "npm-normalize-package-bin": "^5.0.0" }, "bin": { "installed-package-contents": "bin/index.js" } }, "sha512-yNyAdkBxB72gtZ4GrwXCM0ZUedo9nIbOMKfGjt6Cu6DXf0p8y1PViZAKDC8q8kv/fufx0WTjRBdSlyrvnP7hmA=="],
|
||||
|
||||
"@npmcli/map-workspaces": ["@npmcli/map-workspaces@5.0.3", "", { "dependencies": { "@npmcli/name-from-folder": "^4.0.0", "@npmcli/package-json": "^7.0.0", "glob": "^13.0.0", "minimatch": "^10.0.3" } }, "sha512-o2grssXo1e774E5OtEwwrgoszYRh0lqkJH+Pb9r78UcqdGJRDRfhpM8DvZPjzNLLNYeD/rNbjOKM3Ss5UABROw=="],
|
||||
|
||||
"@npmcli/metavuln-calculator": ["@npmcli/metavuln-calculator@9.0.3", "", { "dependencies": { "cacache": "^20.0.0", "json-parse-even-better-errors": "^5.0.0", "pacote": "^21.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5" } }, "sha512-94GLSYhLXF2t2LAC7pDwLaM4uCARzxShyAQKsirmlNcpidH89VA4/+K1LbJmRMgz5gy65E/QBBWQdUvGLe2Frg=="],
|
||||
|
||||
"@npmcli/name-from-folder": ["@npmcli/name-from-folder@4.0.0", "", {}, "sha512-qfrhVlOSqmKM8i6rkNdZzABj8MKEITGFAY+4teqBziksCQAOLutiAxM1wY2BKEd8KjUSpWmWCYxvXr0y4VTlPg=="],
|
||||
|
||||
"@npmcli/node-gyp": ["@npmcli/node-gyp@5.0.0", "", {}, "sha512-uuG5HZFXLfyFKqg8QypsmgLQW7smiRjVc45bqD/ofZZcR/uxEjgQU8qDPv0s9TEeMUiAAU/GC5bR6++UdTirIQ=="],
|
||||
|
||||
"@npmcli/package-json": ["@npmcli/package-json@7.0.5", "", { "dependencies": { "@npmcli/git": "^7.0.0", "glob": "^13.0.0", "hosted-git-info": "^9.0.0", "json-parse-even-better-errors": "^5.0.0", "proc-log": "^6.0.0", "semver": "^7.5.3", "spdx-expression-parse": "^4.0.0" } }, "sha512-iVuTlG3ORq2iaVa1IWUxAO/jIp77tUKBhoMjuzYW2kL4MLN1bi/ofqkZ7D7OOwh8coAx1/S2ge0rMdGv8sLSOQ=="],
|
||||
|
||||
"@npmcli/promise-spawn": ["@npmcli/promise-spawn@9.0.1", "", { "dependencies": { "which": "^6.0.0" } }, "sha512-OLUaoqBuyxeTqUvjA3FZFiXUfYC1alp3Sa99gW3EUDz3tZ3CbXDdcZ7qWKBzicrJleIgucoWamWH1saAmH/l2Q=="],
|
||||
|
||||
"@npmcli/query": ["@npmcli/query@5.0.0", "", { "dependencies": { "postcss-selector-parser": "^7.0.0" } }, "sha512-8TZWfTQOsODpLqo9SVhVjHovmKXNpevHU0gO9e+y4V4fRIOneiXy0u0sMP9LmS71XivrEWfZWg50ReH4WRT4aQ=="],
|
||||
|
||||
"@npmcli/redact": ["@npmcli/redact@4.0.0", "", {}, "sha512-gOBg5YHMfZy+TfHArfVogwgfBeQnKbbGo3pSUyK/gSI0AVu+pEiDVcKlQb0D8Mg1LNRZILZ6XG8I5dJ4KuAd9Q=="],
|
||||
|
||||
"@npmcli/run-script": ["@npmcli/run-script@10.0.4", "", { "dependencies": { "@npmcli/node-gyp": "^5.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "node-gyp": "^12.1.0", "proc-log": "^6.0.0" } }, "sha512-mGUWr1uMnf0le2TwfOZY4SFxZGXGfm4Jtay/nwAa2FLNAKXUoUwaGwBMNH36UHPtinWfTSJ3nqFQr0091CxVGg=="],
|
||||
|
||||
"@opencode/ai": ["@opencode/ai@0.0.0-beta-19378", "", { "dependencies": { "@aws-sdk/credential-providers": "3.1057.0", "@opencode/schema": "0.0.0-beta-19378", "@smithy/eventstream-codec": "4.2.14", "@smithy/util-utf8": "4.2.2", "aws4fetch": "1.0.20", "effect": "4.0.0-rc.112", "google-auth-library": "10.5.0" } }, "sha512-mk20W9+HH82jT8VLowhu9weV6Qkch+ydbfPRp2FJFh53RP9up1YaHLDu1o913biSJQNa36Q/9shln7YIOJ2PNA=="],
|
||||
|
||||
"@opencode/client": ["@opencode/client@0.0.0-beta-19378", "", { "dependencies": { "@opencode/protocol": "0.0.0-beta-19378", "@opencode/schema": "0.0.0-beta-19378" }, "peerDependencies": { "effect": "4.0.0-rc.112", "solid-js": ">=1.9.0" }, "optionalPeers": ["effect", "solid-js"] }, "sha512-tYhOVbCt4RFIxw3DYvX9NREomExR4QCE/K/mFoUxkU8dlhQNCDDT8ztztDkLyLycYwwvAJ+wKt4La6vH0/s8Pg=="],
|
||||
|
||||
"@opencode/plugin": ["@opencode/plugin@0.0.0-beta-19378", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode/ai": "0.0.0-beta-19378", "@opencode/client": "0.0.0-beta-19378", "@opencode/protocol": "0.0.0-beta-19378", "@opencode/schema": "0.0.0-beta-19378", "@opencode/util": "0.0.0-beta-19378", "@standard-schema/spec": "1.1.0", "effect": "4.0.0-rc.112", "zod": "4.1.8" }, "peerDependencies": { "@opencode/theme": "0.0.0-beta-19378", "@opentui/core": ">=0.5.10", "@opentui/solid": ">=0.5.10", "solid-js": ">=1.9.0" }, "optionalPeers": ["@opencode/theme", "@opentui/core", "@opentui/solid", "solid-js"] }, "sha512-Kzlp3gpem5QSzmEkrUOZPABnFy6a+m5wRGskXqt1KrJbXMIjrW9xnluFn81iHpiHEWRkQZOVZssw6VKPgyXQtA=="],
|
||||
|
||||
"@opencode/protocol": ["@opencode/protocol@0.0.0-beta-19378", "", { "dependencies": { "@opencode/schema": "0.0.0-beta-19378", "effect": "4.0.0-rc.112" } }, "sha512-BXh+ygV/xah3LYD12i0eVH69JW6m+7vVK7MiSUnKm+T88G8DT0ytJmqFcLYtoa1EcDNnujcmHMrLtHheTn4b4g=="],
|
||||
|
||||
"@opencode/schema": ["@opencode/schema@0.0.0-beta-19378", "", { "dependencies": { "@standard-schema/spec": "1.1.0", "effect": "4.0.0-rc.112" } }, "sha512-aBilB58tyzWEE44gNmZXZpu5Xw2W3mNV3vrdKCX19z2VRoaZGY8BRhjDwFNGGBoZ9U5KXp9e0C0GKydUuKxT/w=="],
|
||||
|
||||
"@opencode/util": ["@opencode/util@0.0.0-beta-19378", "", { "dependencies": { "@effect/opentelemetry": "4.0.0-rc.112", "@effect/platform-node": "4.0.0-rc.112", "@effect/platform-node-shared": "4.0.0-rc.112", "@npmcli/arborist": "9.4.0", "@npmcli/config": "10.8.1", "@opentelemetry/api": "1.9.0", "@opentelemetry/context-async-hooks": "2.6.1", "@opentelemetry/exporter-trace-otlp-http": "0.214.0", "@opentelemetry/sdk-trace-base": "2.6.1", "@opentelemetry/sdk-trace-node": "2.6.1", "cross-spawn": "7.0.6", "effect": "4.0.0-rc.112", "glob": "13.0.5", "mime-types": "3.0.2", "minimatch": "10.2.5", "npm-package-arg": "13.0.2", "pacote": "21.5.1" } }, "sha512-YNAWKFt348p9UZWQJ5wyazTq8TOPrStaLnd7bA8m5E17CaULtKnxeiKBIcG095cpeqIZ+/JCQBurcqOZ7UbDrA=="],
|
||||
|
||||
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
||||
|
||||
"@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.214.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-40lSJeqYO8Uz2Yj7u94/SJWE/wONa7rmMKjI1ZcIjgf3MHNHv1OZUCrCETGuaRF62d5pQD1wKIW+L4lmSMTzZA=="],
|
||||
|
||||
"@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.6.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-XHzhwRNkBpeP8Fs/qjGrAf9r9PRv67wkJQ/7ZPaBQQ68DYlTBBx5MF9LvPx7mhuXcDessKK2b+DcxqwpgkcivQ=="],
|
||||
|
||||
"@opentelemetry/core": ["@opentelemetry/core@2.6.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-8xHSGWpJP9wBxgBpnqGL0R3PbdWQndL1Qp50qrg71+B28zK5OQmUgcDKLJgzyAAV38t4tOyLMGDD60LneR5W8g=="],
|
||||
|
||||
"@opentelemetry/exporter-trace-otlp-http": ["@opentelemetry/exporter-trace-otlp-http@0.214.0", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/otlp-exporter-base": "0.214.0", "@opentelemetry/otlp-transformer": "0.214.0", "@opentelemetry/resources": "2.6.1", "@opentelemetry/sdk-trace-base": "2.6.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-kIN8nTBMgV2hXzV/a20BCFilPZdAIMYYJGSgfMMRm/Xa+07y5hRDS2Vm12A/z8Cdu3Sq++ZvJfElokX2rkgGgw=="],
|
||||
|
||||
"@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.214.0", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/otlp-transformer": "0.214.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-u1Gdv0/E9wP+apqWf7Wv2npXmgJtxsW2XL0TEv9FZloTZRuMBKmu8cYVXwS4Hm3q/f/3FuCnPTgiwYvIqRSpRg=="],
|
||||
|
||||
"@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/sdk-logs": "0.214.0", "@opentelemetry/sdk-metrics": "2.6.1", "@opentelemetry/sdk-trace-base": "2.6.1", "protobufjs": "^7.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-DSaYcuBRh6uozfsWN3R8HsN0yDhCuWP7tOFdkUOVaWD1KVJg8m4qiLUsg/tNhTLS9HUYUcwNpwL2eroLtsZZ/w=="],
|
||||
|
||||
"@opentelemetry/resources": ["@opentelemetry/resources@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-lID/vxSuKWXM55XhAKNoYXu9Cutoq5hFdkbTdI/zDKQktXzcWBVhNsOkiZFTMU9UtEWuGRNe0HUgmsFldIdxVA=="],
|
||||
|
||||
"@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.214.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.214.0", "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-zf6acnScjhsaBUU22zXZ/sLWim1dfhUAbGXdMmHmNG3LfBnQ3DKsOCITb2IZwoUsNNMTogqFKBnlIPPftUgGwA=="],
|
||||
|
||||
"@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-9t9hJHX15meBy2NmTJxL+NJfXmnausR2xUDvE19XQce0Qi/GBtDGamU8nS1RMbdgDmhgpm3VaOu2+fiS/SfTpQ=="],
|
||||
|
||||
"@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.6.1", "", { "dependencies": { "@opentelemetry/core": "2.6.1", "@opentelemetry/resources": "2.6.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-r86ut4T1e8vNwB35CqCcKd45yzqH6/6Wzvpk2/cZB8PsPLlZFTvrh8yfOS3CYZYcUmAx4hHTZJ8AO8Dj8nrdhw=="],
|
||||
|
||||
"@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.6.1", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.6.1", "@opentelemetry/core": "2.6.1", "@opentelemetry/sdk-trace-base": "2.6.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-Hh2i4FwHWRFhnO2Q/p6svMxy8MPsNCG0uuzUY3glqm0rwM0nQvbTO1dXSp9OqQoTKXcQzaz9q1f65fsurmOhNw=="],
|
||||
|
||||
"@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.43.0", "", {}, "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg=="],
|
||||
|
||||
"@oxfmt/binding-android-arm-eabi": ["@oxfmt/binding-android-arm-eabi@0.67.0", "", { "os": "android", "cpu": "arm" }, "sha512-2olh3ioEmc4gRzQm7jxyB1b/PFBoFvTq8KdgYySeNpysDtA6DEg2Mvya4/I6flhL7G0eOrE8RD7JCNCIMhE16Q=="],
|
||||
|
||||
@@ -117,12 +244,82 @@
|
||||
|
||||
"@oxlint/plugins": ["@oxlint/plugins@1.82.0", "", {}, "sha512-IDF4UXBNOaCeLoEpVxf5Bg85KOWdeuBEkbo1rGzS2vXcbD+GT1asBSeeTC+5BgW6NFTHVByd6N5giHsFPGtwAA=="],
|
||||
|
||||
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
|
||||
|
||||
"@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="],
|
||||
|
||||
"@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="],
|
||||
|
||||
"@protobufjs/codegen": ["@protobufjs/codegen@2.0.5", "", {}, "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g=="],
|
||||
|
||||
"@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.1", "", {}, "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg=="],
|
||||
|
||||
"@protobufjs/fetch": ["@protobufjs/fetch@1.1.1", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1" } }, "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw=="],
|
||||
|
||||
"@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="],
|
||||
|
||||
"@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="],
|
||||
|
||||
"@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="],
|
||||
|
||||
"@protobufjs/utf8": ["@protobufjs/utf8@1.1.2", "", {}, "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug=="],
|
||||
|
||||
"@redis/bloom": ["@redis/bloom@6.2.1", "", { "peerDependencies": { "@redis/client": "^6.2.1" } }, "sha512-huQgNLaCIZfQ9SeLn4q9124uOUd8HbZDYHwwUzNcRgHqCHiHKl2dDxMqJCeWh8cMqZAoWuHR8XnWbDMIf+o7ag=="],
|
||||
|
||||
"@redis/client": ["@redis/client@6.2.1", "", { "dependencies": { "cluster-key-slot": "1.1.2" }, "peerDependencies": { "@node-rs/xxhash": "^1.1.0", "@opentelemetry/api": ">=1 <2" }, "optionalPeers": ["@node-rs/xxhash", "@opentelemetry/api"] }, "sha512-LzxBY7SIBvvJiyCgcaJZZakE3fJrZZ++i24+EDW9fKpCl68D35uJcKFpZZwCfOoG9WZTbyZlMzMeM0gtOAMU9Q=="],
|
||||
|
||||
"@redis/json": ["@redis/json@6.2.1", "", { "peerDependencies": { "@redis/client": "^6.2.1" } }, "sha512-AFIUJ8Gj0DaaSBHYuSt8+O0oYWM+50OK1c0OmodB7XERIA8+BbyV3O4v76f9iccWasd1/7qjfZTpuzexUaZtrQ=="],
|
||||
|
||||
"@redis/search": ["@redis/search@6.2.1", "", { "peerDependencies": { "@redis/client": "^6.2.1" } }, "sha512-2vfOAOyYFE7UUw3sBBlkqqruBtOUS4HRY5MtW4hp83llrwvtrTE4r22CEqXddlV+54zkLxBE4nmsIJ/dpezQrQ=="],
|
||||
|
||||
"@redis/time-series": ["@redis/time-series@6.2.1", "", { "peerDependencies": { "@redis/client": "^6.2.1" } }, "sha512-kiYniph04dJOole+L359B6C9E+jYS2uDP7hca6Onj0xF38ZIpyxARO0Iq0W4ZRn1e8Q6vqW00QFZVSMRA/2Ijw=="],
|
||||
|
||||
"@sigstore/bundle": ["@sigstore/bundle@4.0.0", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.5.0" } }, "sha512-NwCl5Y0V6Di0NexvkTqdoVfmjTaQwoLM236r89KEojGmq/jMls8S+zb7yOwAPdXvbwfKDlP+lmXgAL4vKSQT+A=="],
|
||||
|
||||
"@sigstore/core": ["@sigstore/core@3.2.1", "", {}, "sha512-qRsxPnCrbC/puegGxKuynfnxgLiHqWStrSjxkoB4YKqq3Z3s4cyZyj42ZdWFAEblNP65C+rBH8EuREHIXoi83g=="],
|
||||
|
||||
"@sigstore/protobuf-specs": ["@sigstore/protobuf-specs@0.5.2", "", {}, "sha512-SQqvFMt4V78fdjcDdYX6HbiVSOR4QK3ZgwCa2KOsopAgPIHy1rU5UDUmzLl02r5oyyaYcYHR1hpwDRk/yUe+Mw=="],
|
||||
|
||||
"@sigstore/sign": ["@sigstore/sign@4.1.1", "", { "dependencies": { "@gar/promise-retry": "^1.0.2", "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.2.0", "@sigstore/protobuf-specs": "^0.5.0", "make-fetch-happen": "^15.0.4", "proc-log": "^6.1.0" } }, "sha512-Hf4xglukg0XXQ2RiD5vSoLjdPe8OBUPA8XeVjUObheuDcWdYWrnH/BNmxZCzkAy68MzmNCxXLeurJvs6hcP2OQ=="],
|
||||
|
||||
"@sigstore/tuf": ["@sigstore/tuf@4.0.2", "", { "dependencies": { "@sigstore/protobuf-specs": "^0.5.0", "tuf-js": "^4.1.0" } }, "sha512-TCAzTy0xzdP79EnxSjq9KQ3eaR7+FmudLC6eRKknVKZbV7ZNlGLClAAQb/HMNJ5n2OBNk2GT1tEmU0xuPr+SLQ=="],
|
||||
|
||||
"@sigstore/verify": ["@sigstore/verify@3.1.1", "", { "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.2.1", "@sigstore/protobuf-specs": "^0.5.0" } }, "sha512-qv7+G3J2cc6wwFj3yKvXOamzqhMwSk1ogPGmhpS8iXllcPrJaIIBA+4HbttlHVu1pqWTdmaCH/WE7UOC51kdoA=="],
|
||||
|
||||
"@smithy/core": ["@smithy/core@3.33.3", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-CsOeKq/9kA3y6VJHt+/+VTCtBaxJ4OTFpgrjIUhPpDIKxBci1k2bJaQASF2h/ELWrulGp+t97DZ0mevfAD8idg=="],
|
||||
|
||||
"@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.5.2", "", { "dependencies": { "@smithy/core": "^3.33.2", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg=="],
|
||||
|
||||
"@smithy/eventstream-codec": ["@smithy/eventstream-codec@4.2.14", "", { "dependencies": { "@aws-crypto/crc32": "5.2.0", "@smithy/types": "^4.14.1", "@smithy/util-hex-encoding": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-erZq0nOIpzfeZdCyzZjdJb4nVSKLUmSkaQUVkRGQTXs30gyUGeKnrYEg+Xe1W5gE3aReS7IgsvANwVPxSzY6Pw=="],
|
||||
|
||||
"@smithy/fetch-http-handler": ["@smithy/fetch-http-handler@5.8.0", "", { "dependencies": { "@smithy/core": "^3.33.3", "@smithy/types": "^4.18.0", "tslib": "^2.6.2" } }, "sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA=="],
|
||||
|
||||
"@smithy/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="],
|
||||
|
||||
"@smithy/node-http-handler": ["@smithy/node-http-handler@4.12.1", "", { "dependencies": { "@smithy/core": "^3.33.3", "@smithy/types": "^4.18.0", "tslib": "^2.6.2" } }, "sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw=="],
|
||||
|
||||
"@smithy/signature-v4": ["@smithy/signature-v4@5.7.3", "", { "dependencies": { "@smithy/core": "^3.33.3", "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-7ImGm+FkHRLcBaRttIAMZ6bzJZWb2cJGoYjq46F2UjycujWzrL9GEN9h4w7eQyXJYnltrUhxbbieBAIRrdqpow=="],
|
||||
|
||||
"@smithy/types": ["@smithy/types@4.18.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-CgB6HHWer/vrKps24ulRIbpcpb7K4xAU7SkZ7YHzBPlwHsvsrCJFEXK421s+cJzX+ZrqtA/TuU5w1HzI7k9N8A=="],
|
||||
|
||||
"@smithy/util-buffer-from": ["@smithy/util-buffer-from@4.5.2", "", { "dependencies": { "@smithy/core": "^3.33.2", "tslib": "^2.6.2" } }, "sha512-nxu3SgmAw9JXT2CtkU0m/XNLWpP9MsaBx1zAGAypCbYj15tIFlmcYwpF+Oh18le83d+IM9PT7ENdXnE4C+d5mA=="],
|
||||
|
||||
"@smithy/util-hex-encoding": ["@smithy/util-hex-encoding@4.5.2", "", { "dependencies": { "@smithy/core": "^3.33.2", "tslib": "^2.6.2" } }, "sha512-iq+cW3mAb7vfcxEEpYi3zXKpDtbrIFyanWjQl4zBq4seWD4OSxXDWSfespZxenX6aEaighn+NR3u1nU1DSvs3w=="],
|
||||
|
||||
"@smithy/util-utf8": ["@smithy/util-utf8@4.2.2", "", { "dependencies": { "@smithy/util-buffer-from": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw=="],
|
||||
|
||||
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
||||
|
||||
"@tufjs/canonical-json": ["@tufjs/canonical-json@2.0.0", "", {}, "sha512-yVtV8zsdo8qFHe+/3kw81dSLyF7D576A5cCFCi4X7B39tWT7SekaEFUnvnWJHz+9qO7qJTah1JbrDjWKqFtdWA=="],
|
||||
|
||||
"@tufjs/models": ["@tufjs/models@4.1.0", "", { "dependencies": { "@tufjs/canonical-json": "2.0.0", "minimatch": "^10.1.1" } }, "sha512-Y8cK9aggNRsqJVaKUlEYs4s7CvQ1b1ta2DVPyAimb0I2qhzjNk+A+mxvll/klL0RlfuIUei8BF7YWiua4kQqww=="],
|
||||
|
||||
"@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
|
||||
|
||||
"@types/node": ["@types/node@26.5.0", "", { "dependencies": { "undici-types": "~8.9.0" } }, "sha512-dVSGpriSoCgz8WnDNTuSSuSv1PC/ALXihO4ulRZt7Md8k9mlbdin3lGOcDE8SnWOgf513ByWlXd7BK4azmyg/A=="],
|
||||
|
||||
"@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="],
|
||||
|
||||
"@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="],
|
||||
|
||||
"@typescript/typescript-darwin-arm64": ["@typescript/typescript-darwin-arm64@7.0.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA=="],
|
||||
@@ -163,60 +360,376 @@
|
||||
|
||||
"@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="],
|
||||
|
||||
"abbrev": ["abbrev@4.0.0", "", {}, "sha512-a1wflyaL0tHtJSmLSOVybYhy22vRih4eduhhrkcjgrWGnRfrZtovJ2FRjxuTtkkj47O/baf0R86QU5OuYpz8fA=="],
|
||||
|
||||
"agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="],
|
||||
|
||||
"ansi-regex": ["ansi-regex@6.3.0", "", {}, "sha512-WpDfL7NO6j7tH88IDBNVdUJxDh9nmCteAVW9dsep846XdwF4naCBK+/tGLX3KJgcpgMRXCFlTM2hKGoK9FsdrQ=="],
|
||||
|
||||
"ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
|
||||
|
||||
"aws4fetch": ["aws4fetch@1.0.20", "", {}, "sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g=="],
|
||||
|
||||
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
||||
|
||||
"base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
|
||||
|
||||
"bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="],
|
||||
|
||||
"bin-links": ["bin-links@6.0.2", "", { "dependencies": { "cmd-shim": "^8.0.0", "npm-normalize-package-bin": "^5.0.0", "proc-log": "^6.0.0", "read-cmd-shim": "^6.0.0", "write-file-atomic": "^7.0.0" } }, "sha512-frE1t78WOwJ45PKV2cF2tNPjTcs9L1J9s6VkrV59wanRP4GlaomuxYPVma7BwthMg8WnfSory4w5PTE6FZZ81w=="],
|
||||
|
||||
"bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="],
|
||||
|
||||
"brace-expansion": ["brace-expansion@5.0.9", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg=="],
|
||||
|
||||
"buffer-equal-constant-time": ["buffer-equal-constant-time@1.0.1", "", {}, "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA=="],
|
||||
|
||||
"bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
|
||||
|
||||
"cacache": ["cacache@20.0.4", "", { "dependencies": { "@npmcli/fs": "^5.0.0", "fs-minipass": "^3.0.0", "glob": "^13.0.0", "lru-cache": "^11.1.0", "minipass": "^7.0.3", "minipass-collect": "^2.0.1", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "p-map": "^7.0.2", "ssri": "^13.0.0" } }, "sha512-M3Lab8NPYlZU2exsL3bMVvMrMqgwCnMWfdZbK28bn3pK6APT/Te/I8hjRPNu1uwORY9a1eEQoifXbKPQMfMTOA=="],
|
||||
|
||||
"chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="],
|
||||
|
||||
"ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="],
|
||||
|
||||
"cluster-key-slot": ["cluster-key-slot@1.1.2", "", {}, "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="],
|
||||
|
||||
"cmd-shim": ["cmd-shim@8.0.0", "", {}, "sha512-Jk/BK6NCapZ58BKUxlSI+ouKRbjH1NLZCgJkYoab+vEHUY3f6OzpNBN9u7HFSv9J6TRDGs4PLOHezoKGaFRSCA=="],
|
||||
|
||||
"color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
|
||||
|
||||
"color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
|
||||
|
||||
"common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="],
|
||||
|
||||
"content-type": ["content-type@2.1.0", "", {}, "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag=="],
|
||||
|
||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||
|
||||
"cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="],
|
||||
|
||||
"data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"effect": ["effect@4.0.0-beta.83", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.8.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.1", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^14.0.0", "yaml": "^2.9.0" } }, "sha512-0wsak8RtgGAr9UWSbVDgJHZcUqMSvicHcvaZv1MbMM7MCGgW4Rn/137J1MHQbwYPcwYGxT/IqehFd+UbYuj78w=="],
|
||||
"eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="],
|
||||
|
||||
"ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="],
|
||||
|
||||
"effect": ["effect@4.0.0-rc.112", "", { "dependencies": { "fast-check": "^4.9.0", "msgpackr": "^2.0.5" } }, "sha512-wXxwuh1Ywnv4cPRM3Wfa0vDwuOHnZ1TsTgHJkG9XgzND6inhBH9n1vBxhg3iIXOia/OrpmvVmd3lrD4vq6bF3A=="],
|
||||
|
||||
"emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
|
||||
|
||||
"env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="],
|
||||
|
||||
"exponential-backoff": ["exponential-backoff@3.1.3", "", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="],
|
||||
|
||||
"extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
|
||||
|
||||
"fast-check": ["fast-check@4.9.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg=="],
|
||||
|
||||
"find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="],
|
||||
"fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
|
||||
|
||||
"ini": ["ini@7.0.0", "", {}, "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w=="],
|
||||
"fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="],
|
||||
|
||||
"foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
|
||||
|
||||
"formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="],
|
||||
|
||||
"fs-minipass": ["fs-minipass@3.0.3", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw=="],
|
||||
|
||||
"gaxios": ["gaxios@7.3.1", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-kB3rzJV7d9juLZh8/56QTXCwQfxyhdOMdyYk1HdQKFtF8TJTDTZQJtixWIwXdE9Jji91mC41DUNpjleo4L4eAQ=="],
|
||||
|
||||
"gcp-metadata": ["gcp-metadata@8.1.4", "", { "dependencies": { "gaxios": "7.1.3", "google-logging-utils": "1.1.3", "json-bigint": "^1.0.0" } }, "sha512-iJ9KMsiu+xKtNRX0PmGLSaIU3bUBAyzWTyqKemKPzNPsmmsBCQYmlNg+brEbES7IHSXtdVwzBPzx1vz3FAaipw=="],
|
||||
|
||||
"glob": ["glob@13.0.5", "", { "dependencies": { "minimatch": "^10.2.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-BzXxZg24Ibra1pbQ/zE7Kys4Ua1ks7Bn6pKLkVPZ9FZe4JQS6/Q7ef3LG1H+k7lUf5l4T3PLSyYyYJVYUvfgTw=="],
|
||||
|
||||
"google-auth-library": ["google-auth-library@10.5.0", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.0.0", "gcp-metadata": "^8.0.0", "google-logging-utils": "^1.0.0", "gtoken": "^8.0.0", "jws": "^4.0.0" } }, "sha512-7ABviyMOlX5hIVD60YOfHw4/CxOfBhyduaYB+wbFWCWoni4N7SLcV46hrVRktuBbZjFC9ONyqamZITN7q3n32w=="],
|
||||
|
||||
"google-logging-utils": ["google-logging-utils@1.2.0", "", {}, "sha512-WE9av4wKDZgRjBwgVUabocx8T6/7o3Ca1Fat46FXDhXVAFibzNadedcOXrdgd1Kzmk8tsk/9ZH89Wyf/SqeZ3A=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="],
|
||||
|
||||
"hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="],
|
||||
|
||||
"http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="],
|
||||
|
||||
"http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
|
||||
|
||||
"https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="],
|
||||
|
||||
"iconv-lite": ["iconv-lite@0.7.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ=="],
|
||||
|
||||
"ignore-walk": ["ignore-walk@8.0.0", "", { "dependencies": { "minimatch": "^10.0.3" } }, "sha512-FCeMZT4NiRQGh+YkeKMtWrOmBgWjHjMJ26WQWrRQyoyzqevdaGSakUaJW5xQYmjLlUVk2qUnCjYVBax9EKKg8A=="],
|
||||
|
||||
"ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="],
|
||||
|
||||
"ip-address": ["ip-address@10.7.0", "", {}, "sha512-BGFsyJd5mpXp3rK6jIdADLNgpJUK1jnjzvYF8lK+VyDab9JAmqN0YOKDdP17HlgKb2+ehPgDc8EtnRLbGCAMhA=="],
|
||||
|
||||
"is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
|
||||
|
||||
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
||||
|
||||
"jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="],
|
||||
|
||||
"json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="],
|
||||
|
||||
"json-parse-even-better-errors": ["json-parse-even-better-errors@5.0.0", "", {}, "sha512-ZF1nxZ28VhQouRWhUcVlUIN3qwSgPuswK05s/HIaoetAoE/9tngVmCHjSxmSQPav1nd+lPtTL0YZ/2AFdR/iYQ=="],
|
||||
|
||||
"json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
|
||||
|
||||
"kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="],
|
||||
"json-stringify-nice": ["json-stringify-nice@1.1.4", "", {}, "sha512-5Z5RFW63yxReJ7vANgW6eZFGWaQvnPE3WNmZoOJrSkGju2etKA2L5rrOa1sm877TVTFt57A80BH1bArcmlLfPw=="],
|
||||
|
||||
"jsonparse": ["jsonparse@1.3.1", "", {}, "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg=="],
|
||||
|
||||
"just-diff": ["just-diff@6.0.2", "", {}, "sha512-S59eriX5u3/QhMNq3v/gm8Kd0w8OS6Tz2FS1NG4blv+z0MuQcBRJyFWjdovM0Rad4/P4aUPFtnkNjMjyMlMSYA=="],
|
||||
|
||||
"just-diff-apply": ["just-diff-apply@5.5.0", "", {}, "sha512-OYTthRfSh55WOItVqwpefPtNt2VdKsq5AnAK6apdtR6yCH8pr0CmSr710J0Mf+WdQy7K/OzMy7K2MgAfdQURDw=="],
|
||||
|
||||
"jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="],
|
||||
|
||||
"jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="],
|
||||
|
||||
"long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="],
|
||||
|
||||
"lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="],
|
||||
|
||||
"make-fetch-happen": ["make-fetch-happen@15.0.6", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/agent": "^4.0.0", "@npmcli/redact": "^4.0.0", "cacache": "^20.0.1", "http-cache-semantics": "^4.1.1", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^1.0.0", "proc-log": "^6.0.0", "ssri": "^13.0.0" } }, "sha512-Je0fLJ0F5atA7F+eIlLzk+Wkcl57JDf4kf+EW8xiP5E31xOQxkIxTbgf1Oi1Lw9tRI9UEMRdI5Vz2xTzoNU1Jw=="],
|
||||
|
||||
"mime": ["mime@4.1.0", "", { "bin": { "mime": "bin/cli.js" } }, "sha512-X5ju04+cAzsojXKes0B/S4tcYtFAJ6tTMuSPBEn9CPGlrWr8Fiw7qYeLT0XyH80HSoAoqWCaz+MWKh22P7G1cw=="],
|
||||
|
||||
"mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
|
||||
|
||||
"mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
|
||||
|
||||
"minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="],
|
||||
|
||||
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
||||
|
||||
"minipass-collect": ["minipass-collect@2.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw=="],
|
||||
|
||||
"minipass-fetch": ["minipass-fetch@5.0.2", "", { "dependencies": { "minipass": "^7.0.3", "minipass-sized": "^2.0.0", "minizlib": "^3.0.1" }, "optionalDependencies": { "iconv-lite": "^0.7.2" } }, "sha512-2d0q2a8eCi2IRg/IGubCNRJoYbA1+YPXAzQVRFmB45gdGZafyivnZ5YSEfo3JikbjGxOdntGFvBQGqaSMXlAFQ=="],
|
||||
|
||||
"minipass-flush": ["minipass-flush@1.0.7", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-TbqTz9cUwWyHS2Dy89P3ocAGUGxKjjLuR9z8w4WUTGAVgEj17/4nhgo2Du56i0Fm3Pm30g4iA8Lcqctc76jCzA=="],
|
||||
|
||||
"minipass-pipeline": ["minipass-pipeline@1.2.4", "", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="],
|
||||
|
||||
"minipass-sized": ["minipass-sized@2.0.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-zSsHhto5BcUVM2m1LurnXY6M//cGhVaegT71OfOXoprxT6o780GZd792ea6FfrQkuU4usHZIUczAQMRUE2plzA=="],
|
||||
|
||||
"minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="],
|
||||
|
||||
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
||||
|
||||
"msgpackr": ["msgpackr@2.1.0", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-p/pBCVO63CsvvpkomUnNNag6+n38rULuDA6HHe70o2gtC8ODI52foF/4ko2qQcp6OiErJXTmrZeXmsGGHsIQNQ=="],
|
||||
|
||||
"msgpackr-extract": ["msgpackr-extract@3.0.4", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw=="],
|
||||
|
||||
"multipasta": ["multipasta@0.2.8", "", {}, "sha512-ZPWuMKyv0cSO29f7hozp+k6+crZbQijV8ipMvxNxRf2SwtYGTX1ZX89Kd20VV4H9Znonx+EQn+iy1wGQsJ+b+Q=="],
|
||||
"negotiator": ["negotiator@1.1.0", "", { "dependencies": { "content-type": "^2.1.0" } }, "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg=="],
|
||||
|
||||
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
|
||||
|
||||
"node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="],
|
||||
|
||||
"node-gyp": ["node-gyp@12.4.0", "", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "graceful-fs": "^4.2.6", "nopt": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "tar": "^7.5.4", "tinyglobby": "^0.2.12", "undici": "^6.25.0", "which": "^6.0.0" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "sha512-OMcPNvqTCFUnNaBlmdgq+lfNqY7gTiSmNRDjY3uAXRyudeKZEZxu3CLtjMQrx4zZxCX2b/mpNqTtwuCJgXhHkw=="],
|
||||
|
||||
"node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],
|
||||
|
||||
"nopt": ["nopt@9.0.0", "", { "dependencies": { "abbrev": "^4.0.0" }, "bin": { "nopt": "bin/nopt.js" } }, "sha512-Zhq3a+yFKrYwSBluL4H9XP3m3y5uvQkB/09CwDruCiRmR/UJYnn9W4R48ry0uGC70aeTPKLynBtscP9efFFcPw=="],
|
||||
|
||||
"npm-bundled": ["npm-bundled@5.0.0", "", { "dependencies": { "npm-normalize-package-bin": "^5.0.0" } }, "sha512-JLSpbzh6UUXIEoqPsYBvVNVmyrjVZ1fzEFbqxKkTJQkWBO3xFzFT+KDnSKQWwOQNbuWRwt5LSD6HOTLGIWzfrw=="],
|
||||
|
||||
"npm-install-checks": ["npm-install-checks@8.0.0", "", { "dependencies": { "semver": "^7.1.1" } }, "sha512-ScAUdMpyzkbpxoNekQ3tNRdFI8SJ86wgKZSQZdUxT+bj0wVFpsEMWnkXP0twVe1gJyNF5apBWDJhhIbgrIViRA=="],
|
||||
|
||||
"npm-normalize-package-bin": ["npm-normalize-package-bin@5.0.0", "", {}, "sha512-CJi3OS4JLsNMmr2u07OJlhcrPxCeOeP/4xq67aWNai6TNWWbTrlNDgl8NcFKVlcBKp18GPj+EzbNIgrBfZhsag=="],
|
||||
|
||||
"npm-package-arg": ["npm-package-arg@13.0.2", "", { "dependencies": { "hosted-git-info": "^9.0.0", "proc-log": "^6.0.0", "semver": "^7.3.5", "validate-npm-package-name": "^7.0.0" } }, "sha512-IciCE3SY3uE84Ld8WZU23gAPPV9rIYod4F+rc+vJ7h7cwAJt9Vk6TVsK60ry7Uj3SRS3bqRRIGuTp9YVlk6WNA=="],
|
||||
|
||||
"npm-packlist": ["npm-packlist@10.0.4", "", { "dependencies": { "ignore-walk": "^8.0.0", "proc-log": "^6.0.0" } }, "sha512-uMW73iajD8hiH4ZBxEV3HC+eTnppIqwakjOYuvgddnalIw2lJguKviK1pcUJDlIWm1wSJkchpDZDSVVsZEYRng=="],
|
||||
|
||||
"npm-pick-manifest": ["npm-pick-manifest@11.0.3", "", { "dependencies": { "npm-install-checks": "^8.0.0", "npm-normalize-package-bin": "^5.0.0", "npm-package-arg": "^13.0.0", "semver": "^7.3.5" } }, "sha512-buzyCfeoGY/PxKqmBqn1IUJrZnUi1VVJTdSSRPGI60tJdUhUoSQFhs0zycJokDdOznQentgrpf8LayEHyyYlqQ=="],
|
||||
|
||||
"npm-registry-fetch": ["npm-registry-fetch@19.1.1", "", { "dependencies": { "@npmcli/redact": "^4.0.0", "jsonparse": "^1.3.1", "make-fetch-happen": "^15.0.0", "minipass": "^7.0.2", "minipass-fetch": "^5.0.0", "minizlib": "^3.0.1", "npm-package-arg": "^13.0.0", "proc-log": "^6.0.0" } }, "sha512-TakBap6OM1w0H73VZVDf44iFXsOS3h+L4wVMXmbWOQroZgFhMch0juN6XSzBNlD965yIKvWg2dfu7NSiaYLxtw=="],
|
||||
|
||||
"oxfmt": ["oxfmt@0.67.0", "", { "dependencies": { "tinypool": "2.1.2" }, "optionalDependencies": { "@oxfmt/binding-android-arm-eabi": "0.67.0", "@oxfmt/binding-android-arm64": "0.67.0", "@oxfmt/binding-darwin-arm64": "0.67.0", "@oxfmt/binding-darwin-x64": "0.67.0", "@oxfmt/binding-freebsd-x64": "0.67.0", "@oxfmt/binding-linux-arm-gnueabihf": "0.67.0", "@oxfmt/binding-linux-arm-musleabihf": "0.67.0", "@oxfmt/binding-linux-arm64-gnu": "0.67.0", "@oxfmt/binding-linux-arm64-musl": "0.67.0", "@oxfmt/binding-linux-ppc64-gnu": "0.67.0", "@oxfmt/binding-linux-riscv64-gnu": "0.67.0", "@oxfmt/binding-linux-riscv64-musl": "0.67.0", "@oxfmt/binding-linux-s390x-gnu": "0.67.0", "@oxfmt/binding-linux-x64-gnu": "0.67.0", "@oxfmt/binding-linux-x64-musl": "0.67.0", "@oxfmt/binding-openharmony-arm64": "0.67.0", "@oxfmt/binding-win32-arm64-msvc": "0.67.0", "@oxfmt/binding-win32-ia32-msvc": "0.67.0", "@oxfmt/binding-win32-x64-msvc": "0.67.0" }, "peerDependencies": { "svelte": "^5.0.0", "vite-plus": "*" }, "optionalPeers": ["svelte", "vite-plus"], "bin": { "oxfmt": "bin/oxfmt" } }, "sha512-vV7sSiPsaO0mSxdoUdayipVDFPzW/UQ+hrezEHa20+Tx1dnMdZLSRHMT0PdS67FFbhd74M1n08asW21aLGeCrA=="],
|
||||
|
||||
"oxlint": ["oxlint@1.82.0", "", { "optionalDependencies": { "@oxlint/binding-android-arm-eabi": "1.82.0", "@oxlint/binding-android-arm64": "1.82.0", "@oxlint/binding-darwin-arm64": "1.82.0", "@oxlint/binding-darwin-x64": "1.82.0", "@oxlint/binding-freebsd-x64": "1.82.0", "@oxlint/binding-linux-arm-gnueabihf": "1.82.0", "@oxlint/binding-linux-arm-musleabihf": "1.82.0", "@oxlint/binding-linux-arm64-gnu": "1.82.0", "@oxlint/binding-linux-arm64-musl": "1.82.0", "@oxlint/binding-linux-ppc64-gnu": "1.82.0", "@oxlint/binding-linux-riscv64-gnu": "1.82.0", "@oxlint/binding-linux-riscv64-musl": "1.82.0", "@oxlint/binding-linux-s390x-gnu": "1.82.0", "@oxlint/binding-linux-x64-gnu": "1.82.0", "@oxlint/binding-linux-x64-musl": "1.82.0", "@oxlint/binding-openharmony-arm64": "1.82.0", "@oxlint/binding-win32-arm64-msvc": "1.82.0", "@oxlint/binding-win32-ia32-msvc": "1.82.0", "@oxlint/binding-win32-x64-msvc": "1.82.0" }, "peerDependencies": { "oxlint-tsgolint": ">=7.0.2001", "vite-plus": "*" }, "optionalPeers": ["oxlint-tsgolint", "vite-plus"], "bin": { "oxlint": "bin/oxlint" } }, "sha512-+iFM1BGw1ntYJt3QngbJmjbrGxPaKMUADOXOijpWGnYcBPq8YZnQftSS1C+pVcDYy9YxqDVJKQqQkTazTQMboQ=="],
|
||||
|
||||
"p-map": ["p-map@7.0.7", "", {}, "sha512-VaWRu2i4FJNRtiRWCuuQRgfQ1B7a6+gMSrO+3j0EQi/k0ULfS9kosRxGoiqwzIjZTDI02tGfk5mXXltLg6QtfQ=="],
|
||||
|
||||
"package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
|
||||
|
||||
"pacote": ["pacote@21.5.1", "", { "dependencies": { "@gar/promise-retry": "^1.0.0", "@npmcli/git": "^7.0.0", "@npmcli/installed-package-contents": "^4.0.0", "@npmcli/package-json": "^7.0.0", "@npmcli/promise-spawn": "^9.0.0", "@npmcli/run-script": "^10.0.0", "cacache": "^20.0.0", "fs-minipass": "^3.0.0", "minipass": "^7.0.2", "npm-package-arg": "^13.0.0", "npm-packlist": "^10.0.1", "npm-pick-manifest": "^11.0.1", "npm-registry-fetch": "^19.0.0", "proc-log": "^6.0.0", "sigstore": "^4.0.0", "ssri": "^13.0.0", "tar": "^7.4.3" }, "bin": { "pacote": "bin/index.js" } }, "sha512-KvcJ9iy3crysCsgqc4+PknH/w6jkrp8JN36mpZBPwNaDRwTfMZD37YzRazNstiZUOhuF5pno9f78n9mEJBavwg=="],
|
||||
|
||||
"parse-conflict-json": ["parse-conflict-json@5.0.1", "", { "dependencies": { "json-parse-even-better-errors": "^5.0.0", "just-diff": "^6.0.0", "just-diff-apply": "^5.2.0" } }, "sha512-ZHEmNKMq1wyJXNwLxyHnluPfRAFSIliBvbK/UiOceROt4Xh9Pz0fq49NytIaeaCUf5VR86hwQ/34FCcNU5/LKQ=="],
|
||||
|
||||
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
|
||||
|
||||
"path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
|
||||
|
||||
"picomatch": ["picomatch@4.0.7", "", {}, "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA=="],
|
||||
|
||||
"postcss-selector-parser": ["postcss-selector-parser@7.1.6", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-7qASPzhKF2l2KLboRZux8CCTRMdGiV08vWmyKzPz22qZ7ZjQBOeY7rNzNoCLSUiftJ7HUq0GERHmxw/t0dCdMw=="],
|
||||
|
||||
"proc-log": ["proc-log@6.1.0", "", {}, "sha512-iG+GYldRf2BQ0UDUAd6JQ/RwzaQy6mXmsk/IzlYyal4A4SNFw54MeH4/tLkF4I5WoWG9SQwuqWzS99jaFQHBuQ=="],
|
||||
|
||||
"proggy": ["proggy@4.0.0", "", {}, "sha512-MbA4R+WQT76ZBm/5JUpV9yqcJt92175+Y0Bodg3HgiXzrmKu7Ggq+bpn6y6wHH+gN9NcyKn3yg1+d47VaKwNAQ=="],
|
||||
|
||||
"promise-all-reject-late": ["promise-all-reject-late@1.0.1", "", {}, "sha512-vuf0Lf0lOxyQREH7GDIOUMLS7kz+gs8i6B+Yi8dC68a2sychGrHTJYghMBD6k7eUcH0H5P73EckCA48xijWqXw=="],
|
||||
|
||||
"promise-call-limit": ["promise-call-limit@3.0.2", "", {}, "sha512-mRPQO2T1QQVw11E7+UdCJu7S61eJVWknzml9sC1heAdj1jxl0fWMBypIt9ZOcLFf8FkG995ZD7RnVk7HH72fZw=="],
|
||||
|
||||
"protobufjs": ["protobufjs@7.6.6", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg=="],
|
||||
|
||||
"pure-rand": ["pure-rand@8.4.2", "", {}, "sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng=="],
|
||||
|
||||
"read-cmd-shim": ["read-cmd-shim@6.0.0", "", {}, "sha512-1zM5HuOfagXCBWMN83fuFI/x+T/UhZ7k+KIzhrHXcQoeX5+7gmaDYjELQHmmzIodumBHeByBJT4QYS7ufAgs7A=="],
|
||||
|
||||
"redis": ["redis@6.2.1", "", { "dependencies": { "@redis/bloom": "6.2.1", "@redis/client": "6.2.1", "@redis/json": "6.2.1", "@redis/search": "6.2.1", "@redis/time-series": "6.2.1" } }, "sha512-Z9VHtgYs48PiQC77X9O2Er8Hj4T+5BtFjT91/vi5Is1D04N72cA946ZslM1ImJw8ZctFBZWAVjM7S5wJNeHMpg=="],
|
||||
|
||||
"rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="],
|
||||
|
||||
"safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
||||
|
||||
"safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
|
||||
|
||||
"semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="],
|
||||
|
||||
"shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
|
||||
|
||||
"shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
|
||||
|
||||
"signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
|
||||
|
||||
"sigstore": ["sigstore@4.1.1", "", { "dependencies": { "@sigstore/bundle": "^4.0.0", "@sigstore/core": "^3.2.1", "@sigstore/protobuf-specs": "^0.5.0", "@sigstore/sign": "^4.1.1", "@sigstore/tuf": "^4.0.2", "@sigstore/verify": "^3.1.1" } }, "sha512-endqECJkfhozrXMK5ngu/UAA0xVcVEFdnHJCElGaExypjW+HK5i6zu3NteLoaX/iFbRUbC3+DjttQs0GARr+5w=="],
|
||||
|
||||
"smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
|
||||
|
||||
"socks": ["socks@2.8.10", "", { "dependencies": { "ip-address": "^10.1.1", "smart-buffer": "^4.2.0" } }, "sha512-e0VyvkVTwVYViNovRkZ9aodhxVlyoMn7eJhVUPxZ+eK9P/7CBkxvvsBOHqFPEH416726W8tLXXXjKwqgTErrCQ=="],
|
||||
|
||||
"socks-proxy-agent": ["socks-proxy-agent@8.0.5", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "^4.3.4", "socks": "^2.8.3" } }, "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw=="],
|
||||
|
||||
"spdx-exceptions": ["spdx-exceptions@2.5.0", "", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="],
|
||||
|
||||
"spdx-expression-parse": ["spdx-expression-parse@4.0.0", "", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ=="],
|
||||
|
||||
"spdx-license-ids": ["spdx-license-ids@3.0.23", "", {}, "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw=="],
|
||||
|
||||
"ssri": ["ssri@13.0.1", "", { "dependencies": { "minipass": "^7.0.3" } }, "sha512-QUiRf1+u9wPTL/76GTYlKttDEBWV1ga9ZXW8BG6kfdeyyM8LGPix9gROyg9V2+P0xNyF3X2Go526xKFdMZrHSQ=="],
|
||||
|
||||
"string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="],
|
||||
|
||||
"string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="],
|
||||
|
||||
"strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"tar": ["tar@7.5.22", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="],
|
||||
|
||||
"tinypool": ["tinypool@2.1.2", "", {}, "sha512-9YodfrxS9g9IbFr/KOjE5bAeJ0p61n3bW6mqvy0jtoeKd1kTW1Cxm0oulm6KX2lyM9Gl6WIe8nEbY7LWv5ZJww=="],
|
||||
|
||||
"toml": ["toml@4.3.0", "", {}, "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A=="],
|
||||
"treeverse": ["treeverse@3.0.0", "", {}, "sha512-gcANaAnd2QDZFmHFEOF4k7uc1J/6a6z3DJMd/QwEyxLoKGiptJRwid582r7QIsFlFMIZ3SnxfS52S4hm2DHkuQ=="],
|
||||
|
||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"tuf-js": ["tuf-js@4.1.0", "", { "dependencies": { "@tufjs/models": "4.1.0", "debug": "^4.4.3", "make-fetch-happen": "^15.0.1" } }, "sha512-50QV99kCKH5P/Vs4E2Gzp7BopNV+KzTXqWeaxrfu5IQJBOULRsTIS9seSsOVT8ZnGXzCyx55nYWAi4qJzpZKEQ=="],
|
||||
|
||||
"typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="],
|
||||
|
||||
"undici": ["undici@8.10.2", "", {}, "sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ=="],
|
||||
|
||||
"undici-types": ["undici-types@8.9.0", "", {}, "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg=="],
|
||||
|
||||
"uuid": ["uuid@14.0.2", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ=="],
|
||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||
|
||||
"validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="],
|
||||
|
||||
"walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="],
|
||||
|
||||
"web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="],
|
||||
|
||||
"which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
|
||||
|
||||
"yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="],
|
||||
"wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="],
|
||||
|
||||
"wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
|
||||
|
||||
"write-file-atomic": ["write-file-atomic@7.0.1", "", { "dependencies": { "signal-exit": "^4.0.1" } }, "sha512-OTIk8iR8/aCRWBqvxrzxR0hgxWpnYBblY1S5hDWBQfk/VFmJwzmJgQFN3WsoUKHISv2eAwe+PpbUzyL1CKTLXg=="],
|
||||
|
||||
"ws": ["ws@8.21.3", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw=="],
|
||||
|
||||
"yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="],
|
||||
|
||||
"zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="],
|
||||
|
||||
"@aws-crypto/sha256-browser/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8": ["@smithy/util-utf8@2.3.0", "", { "dependencies": { "@smithy/util-buffer-from": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A=="],
|
||||
|
||||
"@npmcli/git/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
|
||||
|
||||
"@npmcli/promise-spawn/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
|
||||
|
||||
"gcp-metadata/gaxios": ["gaxios@7.1.3", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2", "rimraf": "^5.0.1" } }, "sha512-YGGyuEdVIjqxkxVH1pUTMY/XtmmsApXrCVv5EU25iX6inEPbV+VakJfLealkBtJN69AQmh1eGOdCl9Sm1UP6XQ=="],
|
||||
|
||||
"gcp-metadata/google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="],
|
||||
|
||||
"minipass-flush/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"minipass-pipeline/minipass": ["minipass@3.3.6", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="],
|
||||
|
||||
"node-gyp/undici": ["undici@6.28.1", "", {}, "sha512-zWpdTVD54H48CIybL0rWQ3ukpb9d23wM7eH5RtfdmeP70cWHNjtfo7P4vZX+5CoDcO53J4Pu5uXp7lNfjc6DRA=="],
|
||||
|
||||
"node-gyp/which": ["which@6.0.1", "", { "dependencies": { "isexe": "^4.0.0" }, "bin": { "node-which": "bin/which.js" } }, "sha512-oGLe46MIrCRqX7ytPUf66EAYvdeMIZYn3WaocqqKZAxrBpkqHfL/qvTyJ/bTk5+AqHCjXmrv3CEWgy368zhRUg=="],
|
||||
|
||||
"rimraf/glob": ["glob@10.5.0", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg=="],
|
||||
|
||||
"string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"strip-ansi-cjs/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"wrap-ansi-cjs/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
||||
|
||||
"wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
|
||||
|
||||
"wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
|
||||
|
||||
"@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=="],
|
||||
|
||||
"@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="],
|
||||
|
||||
"@npmcli/git/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
|
||||
|
||||
"@npmcli/promise-spawn/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
|
||||
|
||||
"minipass-flush/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="],
|
||||
|
||||
"node-gyp/which/isexe": ["isexe@4.0.0", "", {}, "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw=="],
|
||||
|
||||
"rimraf/glob/minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="],
|
||||
|
||||
"rimraf/glob/path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
|
||||
|
||||
"string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
|
||||
|
||||
"wrap-ansi-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
|
||||
|
||||
"rimraf/glob/minimatch/brace-expansion": ["brace-expansion@2.1.4", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg=="],
|
||||
|
||||
"rimraf/glob/path-scurry/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
|
||||
|
||||
"rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
// All seven assignments are required in custom mode. Model IDs are local to
|
||||
// the chosen provider, not provider/model strings. Missing models disable
|
||||
// the whole registration. Only GPT mode applies the optional-Astra fallback.
|
||||
"plugin": [
|
||||
[
|
||||
"stanp-opencode",
|
||||
{
|
||||
// All seven assignments are required. Model IDs are local to the provider.
|
||||
// Missing models disable registration; only GPT mode has an Astra fallback.
|
||||
"plugins": [
|
||||
{
|
||||
"package": "stanp-opencode",
|
||||
"options": {
|
||||
"mode": "custom",
|
||||
"provider": "openai",
|
||||
"lunaPriority": false,
|
||||
@@ -20,6 +19,6 @@
|
||||
"coordinate": { "model": "gpt-6-astra", "effort": "medium" },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
+10
-16
@@ -1,24 +1,18 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
// Working server plugin API: v2 does not yet provide task delegation.
|
||||
// Replace the package string with an installed package, release tarball URL,
|
||||
// or an absolute file:///.../stanp-opencode/dist/index.js URL for local use.
|
||||
// Availability is checked at startup against OpenCode's cached catalog and
|
||||
// provider.models, with configured/env/stored authentication. Models added
|
||||
// later by other plugins are not visible; no paid model-entitlement probe runs.
|
||||
"plugin": [
|
||||
[
|
||||
"stanp-opencode",
|
||||
{
|
||||
// Use OpenCode V2 (opencode2), not the V1 opencode CLI.
|
||||
// Availability uses the native catalog, including integrations and earlier plugins.
|
||||
"plugins": [
|
||||
{
|
||||
"package": "stanp-opencode",
|
||||
"options": {
|
||||
"mode": "gpt",
|
||||
"provider": "openai",
|
||||
// Requests priority for Luna when supported by provider metadata.
|
||||
// Official OpenAI supports it, charges more, and may downgrade requests.
|
||||
// Set false to use the provider's default service tier.
|
||||
// Priority may cost more. Only advertised tiers or official OpenAI
|
||||
// Luna endpoints enable it; false retains the provider's default.
|
||||
"lunaPriority": true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
// Select coordinate in the agent picker. This plugin does not replace build.
|
||||
// Do not set default_agent to coordinate if this provider may be disconnected.
|
||||
// Select coordinate in the agent picker. Build and the default stay unchanged.
|
||||
}
|
||||
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
for command in bun curl jq sha256sum; do
|
||||
command -v "$command" >/dev/null || { printf 'Required command not found: %s\n' "$command" >&2; exit 1; }
|
||||
done
|
||||
|
||||
config="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}"
|
||||
mkdir -p "$config"
|
||||
config=$(cd "$config" && pwd -P)
|
||||
mkdir -p "$config/stanp-opencode" "$config/plugins"
|
||||
install=$(mktemp -d "$config/stanp-opencode/install.XXXXXXXX")
|
||||
cleanup() {
|
||||
if [[ -n "$install" ]]; then rm -rf "$install"; fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
api='https://git.krtss.de/api/v1/repos/StanPonomarev/stanp-opencode/releases/latest'
|
||||
curl --fail-with-body --silent --show-error --location --proto '=https' --proto-redir '=https' "$api" -o "$install/release.json"
|
||||
for asset in stanp-opencode.tgz stanp-opencode.tgz.sha256; do
|
||||
url=$(jq -er --arg name "$asset" '[.assets[] | select(.name == $name) | .browser_download_url] | if length == 1 then .[0] | select(type == "string" and startswith("https://")) else error("Missing or duplicate release asset: " + $name) end' "$install/release.json")
|
||||
curl --fail-with-body --silent --show-error --location --proto '=https' --proto-redir '=https' "$url" -o "$install/$asset"
|
||||
done
|
||||
read -r checksum _ < "$install/stanp-opencode.tgz.sha256"
|
||||
if [[ ! "$checksum" =~ ^[a-fA-F0-9]{64}$ ]]; then
|
||||
printf 'Invalid release checksum\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! (cd "$install" && printf '%s stanp-opencode.tgz\n' "$checksum" | sha256sum --check --status); then
|
||||
printf 'Release checksum mismatch; installation unchanged\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
printf '{"private":true,"type":"module"}\n' > "$install/package.json"
|
||||
(cd "$install" && bun add --production --ignore-scripts --no-cache ./stanp-opencode.tgz)
|
||||
bun -e '
|
||||
if (!await Bun.file(process.argv[1]).exists()) {
|
||||
throw new Error("Latest release lacks the OpenCode V2 directory entrypoint. Publish a V2-compatible release first.");
|
||||
}
|
||||
const { default: plugin } = await import(process.argv[1]);
|
||||
if (!plugin || plugin.id !== "stanp-opencode" || typeof plugin.setup !== "function") {
|
||||
throw new Error("Latest release is not a native OpenCode V2 plugin. Publish a V2-compatible release first.");
|
||||
}
|
||||
' "$install/node_modules/stanp-opencode/index.js"
|
||||
|
||||
tag=$(jq -r '.tag_name' "$install/release.json")
|
||||
ln -s "../stanp-opencode/$(basename "$install")/node_modules/stanp-opencode" "$install/plugin"
|
||||
mv -Tf "$install/plugin" "$config/plugins/stanp-opencode"
|
||||
install=""
|
||||
printf 'Installed stanp-opencode %s into %s/plugins/stanp-opencode\nRestart opencode2 to load it.\n' "$tag" "$config"
|
||||
+6
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "stanp-opencode",
|
||||
"version": "0.1.0",
|
||||
"version": "1.0.0",
|
||||
"description": "Stanp agents for OpenCode",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
@@ -12,13 +12,13 @@
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"dist",
|
||||
"examples"
|
||||
],
|
||||
"packageManager": "bun@1.3.14",
|
||||
"engines": {
|
||||
"bun": ">=1.3.14",
|
||||
"opencode": "^1.18.30"
|
||||
"bun": ">=1.3.14"
|
||||
},
|
||||
"scripts": {
|
||||
"check": "tsc --noEmit",
|
||||
@@ -29,7 +29,8 @@
|
||||
"build": "bun build src/index.ts --outdir dist --target bun --format esm --packages external && tsc --project tsconfig.build.json --emitDeclarationOnly"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opencode-ai/plugin": "1.18.30",
|
||||
"@opencode/client": "0.0.0-beta-19378",
|
||||
"@opencode/plugin": "0.0.0-beta-19378",
|
||||
"@oxlint/plugins": "1.82.0",
|
||||
"@types/bun": "1.3.14",
|
||||
"oxfmt": "0.67.0",
|
||||
@@ -37,7 +38,7 @@
|
||||
"typescript": "7.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opencode-ai/plugin": "^1.18.30"
|
||||
"@opencode/plugin": "0.0.0-beta-19378"
|
||||
},
|
||||
"dependencies": {
|
||||
"zod": "4.1.8"
|
||||
|
||||
+228
-173
@@ -1,192 +1,247 @@
|
||||
import type { PluginModule } from "@opencode-ai/plugin";
|
||||
import type {
|
||||
AgentConfig,
|
||||
Config,
|
||||
PermissionConfig,
|
||||
PermissionObjectConfig,
|
||||
} from "@opencode-ai/sdk/v2";
|
||||
import { Agent, Model, Plugin, Provider } from "@opencode/plugin";
|
||||
import type { ModelInfo } from "@opencode/client";
|
||||
import { z } from "zod";
|
||||
import { gptAgents, settings, workerNames } from "./config.js";
|
||||
import { discover } from "./provider.js";
|
||||
import { descriptions, routingGuide } from "./routing.js";
|
||||
|
||||
// OpenCode permission patterns are wildcards, not filesystem globs.
|
||||
// Permission actions use wildcards, not filesystem globs.
|
||||
function matches(value: string, pattern: string) {
|
||||
const escaped = pattern
|
||||
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
||||
.replace(/\*/g, ".*")
|
||||
.replace(/\?/g, ".");
|
||||
return new RegExp(`^${escaped}$`, process.platform === "win32" ? "si" : "s").test(value);
|
||||
return new RegExp(`^${escaped}$`, "s").test(value);
|
||||
}
|
||||
|
||||
function rulesFor(action: string, defaults: PermissionObjectConfig, ...layers: PermissionConfig[]) {
|
||||
const result = { ...defaults };
|
||||
for (const layer of layers) {
|
||||
for (const [key, rule] of Object.entries(
|
||||
layer instanceof Object ? layer : { "*": layer },
|
||||
)) {
|
||||
if (!rule || !matches(action, key)) continue;
|
||||
for (const [pattern, effect] of Object.entries(
|
||||
rule instanceof Object ? rule : { "*": rule },
|
||||
)) {
|
||||
// Last matching rule wins. A new wildcard supersedes every earlier rule.
|
||||
if (pattern === "*") {
|
||||
for (const previous of Object.keys(result)) delete result[previous];
|
||||
}
|
||||
delete result[pattern];
|
||||
result[pattern] = effect;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
const reading = [
|
||||
"read",
|
||||
"glob",
|
||||
"grep",
|
||||
"list",
|
||||
"todoread",
|
||||
"todowrite",
|
||||
"webfetch",
|
||||
"websearch",
|
||||
"question",
|
||||
"external_directory",
|
||||
"doom_loop",
|
||||
];
|
||||
const delegation = z.object({ agent: z.string() });
|
||||
const todos = z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
content: z.string(),
|
||||
status: z.enum(["pending", "in_progress", "completed", "cancelled"]),
|
||||
priority: z.enum(["high", "medium", "low"]),
|
||||
}),
|
||||
);
|
||||
|
||||
function flatPermission(action: string, ...layers: PermissionConfig[]) {
|
||||
return (
|
||||
Object.entries(rulesFor(action, { "*": "allow" }, ...layers)).findLast(([pattern]) =>
|
||||
matches("*", pattern),
|
||||
)?.[1] ?? "allow"
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
export default Plugin.define({
|
||||
id: "stanp-opencode",
|
||||
async server(context, options) {
|
||||
const selected = settings.parse({ mode: "gpt", ...options });
|
||||
const activeWorkers = new Set<string>();
|
||||
return {
|
||||
async config(input) {
|
||||
// SAFETY: OpenCode 1.18.30 passes its validated live Config here. The plugin's
|
||||
// legacy SDK type is stale; SDK/v2 describes the actual permission schema.
|
||||
const config = input as Config;
|
||||
const provider = await discover(config, selected.provider);
|
||||
if (!provider) return;
|
||||
const assignments = selected.mode === "gpt" ? gptAgents : selected.agents;
|
||||
const deep = selected.mode === "custom" || provider.models.has("gpt-6-astra");
|
||||
const workers = workerNames.filter((name) => deep || !name.startsWith("deep-"));
|
||||
const coordinate =
|
||||
selected.mode === "gpt" && !deep
|
||||
? { model: "gpt-5.6-sol", effort: "medium" }
|
||||
: assignments.coordinate;
|
||||
if (
|
||||
![coordinate, ...workers.map((name) => assignments[name])].every(({ model }) =>
|
||||
provider.models.has(model),
|
||||
)
|
||||
)
|
||||
return;
|
||||
async setup(context) {
|
||||
const selected = settings.parse({ mode: "gpt", ...context.options });
|
||||
let models = new Map<string, { model: ModelInfo; serviceTier: string | undefined }>();
|
||||
let inherited: Agent.Info["permissions"] = Agent.Info.default(
|
||||
Agent.ID.make("build"),
|
||||
).permissions;
|
||||
let permissionKey = JSON.stringify(inherited);
|
||||
const controller = new AbortController();
|
||||
// Subscribe before the first read: configuration can publish its catalog while
|
||||
// asynchronous setup is running.
|
||||
const updates = (async () => {
|
||||
for await (const event of context.event.subscribe({ signal: controller.signal })) {
|
||||
if (event.type === "catalog.updated") {
|
||||
models = await discover(context, selected.provider);
|
||||
await context.agent.reload();
|
||||
} else if (event.type === "agent.updated") {
|
||||
// The configured build transform may run after ours. Read the final
|
||||
// registry, then replay only when its effective permissions change.
|
||||
const { data } = await context.agent.list();
|
||||
const permissions =
|
||||
data.find((agent) => agent.id === "build")?.permissions ??
|
||||
Agent.Info.default(Agent.ID.make("build")).permissions;
|
||||
const key = JSON.stringify(permissions);
|
||||
if (key === permissionKey) continue;
|
||||
inherited = permissions;
|
||||
permissionKey = key;
|
||||
await context.agent.reload();
|
||||
}
|
||||
}
|
||||
})().catch((error) => {
|
||||
if (!controller.signal.aborted)
|
||||
console.error("stanp-opencode catalog update failed", error);
|
||||
});
|
||||
models = await discover(context, selected.provider);
|
||||
const { data: initialAgents } = await context.agent.list();
|
||||
inherited = initialAgents.find((agent) => agent.id === "build")?.permissions ?? inherited;
|
||||
permissionKey = JSON.stringify(inherited);
|
||||
const assignments = selected.mode === "gpt" ? gptAgents : selected.agents;
|
||||
let workers: (typeof workerNames)[number][] = [];
|
||||
const active = new Set<string>();
|
||||
|
||||
const agents = (config.agent ??= {});
|
||||
const global = config.permission ?? {};
|
||||
const build = agents.build?.permission ?? {};
|
||||
// Custom agents already inherit OpenCode's defaults and global permissions.
|
||||
// Supply only build's differing defaults, explicit todo access (task otherwise
|
||||
// disables it), and build's original overrides. Do not flatten global rules.
|
||||
const inherited: Exclude<PermissionConfig, string> = {
|
||||
question: flatPermission("question", global),
|
||||
plan_enter: flatPermission("plan_enter", global),
|
||||
todowrite: flatPermission("todowrite", global),
|
||||
};
|
||||
for (const [key, rule] of Object.entries(
|
||||
build instanceof Object ? build : { "*": build },
|
||||
)) {
|
||||
delete inherited[key];
|
||||
inherited[key] = rule;
|
||||
}
|
||||
delete inherited.task;
|
||||
inherited.task = "deny";
|
||||
for (const name of workers) {
|
||||
const assignment = assignments[name];
|
||||
const options: AgentConfig["options"] = {
|
||||
reasoningEffort: assignment.effort,
|
||||
await context.agent.transform((editor) => {
|
||||
const deep = selected.mode === "custom" || models.has("gpt-6-astra");
|
||||
const candidates = workerNames.filter((name) => deep || !name.startsWith("deep-"));
|
||||
const coordinate =
|
||||
selected.mode === "gpt" && !deep
|
||||
? { model: "gpt-5.6-sol", effort: "medium" }
|
||||
: assignments.coordinate;
|
||||
workers = [coordinate, ...candidates.map((name) => assignments[name])].every(
|
||||
({ model }) => models.has(model),
|
||||
)
|
||||
? candidates
|
||||
: [];
|
||||
active.clear();
|
||||
for (const name of workers) active.add(name);
|
||||
if (workers.length === 0) return;
|
||||
for (const name of workers) {
|
||||
const assignment = assignments[name];
|
||||
const available = models.get(assignment.model)!;
|
||||
editor.update(name, (agent) => {
|
||||
agent.name = Agent.Name.make(name);
|
||||
agent.mode = "subagent";
|
||||
agent.hidden = false;
|
||||
agent.description = descriptions[name];
|
||||
agent.model = {
|
||||
providerID: Provider.ID.make(available.model.providerID),
|
||||
id: Model.ID.make(available.model.id),
|
||||
};
|
||||
const tier = provider.models.get(assignment.model)?.serviceTier;
|
||||
if (selected.lunaPriority && tier) {
|
||||
options.serviceTier = tier;
|
||||
}
|
||||
agents[name] = {
|
||||
mode: "subagent",
|
||||
description: descriptions[name],
|
||||
model: `${selected.provider}/${assignment.model}`,
|
||||
options,
|
||||
permission: structuredClone(inherited),
|
||||
};
|
||||
activeWorkers.add(name);
|
||||
}
|
||||
const reading: Exclude<PermissionConfig, string> = {};
|
||||
for (const name of ["glob", "grep", "list", "todoread"]) {
|
||||
reading[name] = rulesFor(name, { "*": "allow" }, global, build);
|
||||
}
|
||||
agents.coordinate = {
|
||||
mode: "primary",
|
||||
description:
|
||||
"Read, plan, and coordinate specialist workers; never implement directly.",
|
||||
model: `${selected.provider}/${coordinate.model}`,
|
||||
options: { reasoningEffort: coordinate.effort },
|
||||
prompt: routingGuide(deep),
|
||||
permission: {
|
||||
"*": "deny",
|
||||
...reading,
|
||||
read: rulesFor(
|
||||
"read",
|
||||
{
|
||||
"*": "allow",
|
||||
"*.env": "ask",
|
||||
"*.env.*": "ask",
|
||||
"*.env.example": "allow",
|
||||
},
|
||||
global,
|
||||
build,
|
||||
),
|
||||
external_directory: rulesFor(
|
||||
"external_directory",
|
||||
{ "*": "ask" },
|
||||
global,
|
||||
build,
|
||||
),
|
||||
doom_loop: "ask",
|
||||
webfetch: flatPermission("webfetch", global, build),
|
||||
websearch: flatPermission("websearch", global, build),
|
||||
todowrite: flatPermission("todowrite", global, build),
|
||||
question: flatPermission("question", global, build),
|
||||
task: {
|
||||
"*": "deny",
|
||||
...Object.fromEntries(workers.map((name) => [name, "allow" as const])),
|
||||
agent.request = {
|
||||
settings: {
|
||||
reasoningEffort: assignment.effort,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
async "tool.execute.before"(input, output) {
|
||||
if (activeWorkers.size === 0 || input.tool !== "task") return;
|
||||
const target = output.args?.subagent_type;
|
||||
// Primary mode only hides coordinate from suggestions; @mentions and subtask
|
||||
// commands can bypass task permissions, so enforce the policy here as well.
|
||||
if (target === "coordinate") {
|
||||
throw new Error("coordinate is a primary agent and cannot be delegated to");
|
||||
}
|
||||
const recent = await context.client.session.messages({
|
||||
path: { id: input.sessionID },
|
||||
query: { limit: 1 },
|
||||
throwOnError: true,
|
||||
headers: {},
|
||||
body: {},
|
||||
};
|
||||
if (selected.lunaPriority && available.serviceTier)
|
||||
agent.request.settings.serviceTier = available.serviceTier;
|
||||
agent.permissions = [
|
||||
...structuredClone(inherited),
|
||||
{ action: "subagent", resource: "*", effect: "deny" },
|
||||
];
|
||||
});
|
||||
const message = recent.data?.at(-1)?.info;
|
||||
const parent =
|
||||
message?.role === "assistant"
|
||||
? (
|
||||
await context.client.session.message({
|
||||
path: { id: input.sessionID, messageID: message.parentID },
|
||||
throwOnError: true,
|
||||
})
|
||||
).data?.info
|
||||
: message;
|
||||
// Subtask commands label their synthetic assistant with the TARGET agent;
|
||||
// its parent user message identifies the caller, including resumed sessions.
|
||||
if (parent?.role !== "user")
|
||||
throw new Error("Cannot determine task caller; refusing delegation");
|
||||
if (activeWorkers.has(parent.agent))
|
||||
throw new Error("Workers cannot delegate tasks");
|
||||
if (parent.agent === "coordinate" && !activeWorkers.has(target)) {
|
||||
throw new Error("coordinate may delegate only to its available workers");
|
||||
}
|
||||
},
|
||||
}
|
||||
editor.update("coordinate", (agent) => {
|
||||
const available = models.get(coordinate.model)!;
|
||||
agent.name = Agent.Name.make("coordinate");
|
||||
agent.mode = "primary";
|
||||
agent.hidden = false;
|
||||
agent.description =
|
||||
"Read, plan, and coordinate specialist workers; never implement directly.";
|
||||
agent.model = {
|
||||
providerID: Provider.ID.make(available.model.providerID),
|
||||
id: Model.ID.make(available.model.id),
|
||||
};
|
||||
agent.request = {
|
||||
settings: { reasoningEffort: coordinate.effort },
|
||||
headers: {},
|
||||
body: {},
|
||||
};
|
||||
agent.system = routingGuide(deep);
|
||||
agent.permissions = [
|
||||
{ action: "*", resource: "*", effect: "deny" },
|
||||
...reading.flatMap((action) =>
|
||||
inherited
|
||||
.filter((rule) => matches(action, rule.action))
|
||||
.map((rule) => ({ ...rule, action })),
|
||||
),
|
||||
...workers.map((resource) => ({
|
||||
action: "subagent",
|
||||
resource,
|
||||
effect: "allow" as const,
|
||||
})),
|
||||
];
|
||||
});
|
||||
});
|
||||
async function assertTodo(agentID: Agent.ID, action: string) {
|
||||
const { data: agent } = await context.agent.get({ agentID });
|
||||
const effect =
|
||||
agent.permissions.findLast(
|
||||
(rule) => matches(action, rule.action) && matches("*", rule.resource),
|
||||
)?.effect ?? "ask";
|
||||
if (effect !== "allow")
|
||||
throw new Error(
|
||||
`${action} requires an allow permission: OpenCode beta's public plugin API cannot request custom-tool permission approval (${effect}).`,
|
||||
);
|
||||
}
|
||||
await context.tool.transform((editor) => {
|
||||
if (!editor.get("todowrite"))
|
||||
editor.add({
|
||||
name: "todowrite",
|
||||
description:
|
||||
"Replace this session's todo list to track the work and its progress.",
|
||||
input: z.object({ todos }),
|
||||
options: { codemode: false },
|
||||
async execute(input, tool) {
|
||||
await assertTodo(tool.agent, "todowrite");
|
||||
await context.storage.set(`todos:${tool.sessionID}`, input.todos);
|
||||
return { content: JSON.stringify(input.todos) };
|
||||
},
|
||||
});
|
||||
if (!editor.get("todoread"))
|
||||
editor.add({
|
||||
name: "todoread",
|
||||
description: "Read this session's todo list.",
|
||||
input: z.object({}),
|
||||
options: { codemode: false },
|
||||
async execute(_input, tool) {
|
||||
await assertTodo(tool.agent, "todoread");
|
||||
const stored = await context.storage.get(`todos:${tool.sessionID}`);
|
||||
return {
|
||||
content: JSON.stringify(
|
||||
stored === undefined ? [] : todos.parse(stored),
|
||||
),
|
||||
};
|
||||
},
|
||||
});
|
||||
});
|
||||
await context.session.hook("context", (event) => {
|
||||
if (workerNames.some((name) => name === event.agent)) {
|
||||
delete event.tools.subagent;
|
||||
return;
|
||||
}
|
||||
const tool = event.tools.subagent;
|
||||
if (event.agent === "coordinate" && workers.length === 0) {
|
||||
delete event.tools.subagent;
|
||||
return;
|
||||
}
|
||||
if (event.agent !== "coordinate" || !tool) return;
|
||||
tool.description = `Delegate a self-contained assignment to one of these workers:\n${workers.map((name) => `- ${name}: ${descriptions[name]}`).join("\n")}`;
|
||||
// The executable definition remains native; constrain only this request's schema.
|
||||
const properties = z.record(z.string(), z.unknown()).parse(tool.input.properties ?? {});
|
||||
tool.input = {
|
||||
...tool.input,
|
||||
properties: { ...properties, agent: { type: "string", enum: workers } },
|
||||
};
|
||||
});
|
||||
await context.tool.hook("execute.before", (event) => {
|
||||
if (event.tool !== "subagent") return;
|
||||
const { agent } = delegation.parse(event.input);
|
||||
if (agent === "coordinate") throw new Error("coordinate cannot run as a subagent");
|
||||
if (workerNames.some((name) => name === event.agent))
|
||||
throw new Error("Workers cannot delegate tasks");
|
||||
if (event.agent === "coordinate" && !active.has(agent))
|
||||
throw new Error("coordinate may delegate only to its available workers");
|
||||
});
|
||||
// Commands can create child sessions without going through the subagent tool.
|
||||
await context.session.hook("prompt", async (event) => {
|
||||
const child = await context.session.get({ sessionID: event.sessionID });
|
||||
if (!child.parentID) return;
|
||||
if (child.agent === "coordinate")
|
||||
throw new Error("coordinate cannot run as a subagent");
|
||||
const parent = await context.session.get({ sessionID: child.parentID });
|
||||
if (workerNames.some((name) => name === parent.agent))
|
||||
throw new Error("Workers cannot delegate tasks");
|
||||
if (
|
||||
parent.agent === "coordinate" &&
|
||||
(child.agent === undefined || !active.has(child.agent))
|
||||
)
|
||||
throw new Error("coordinate may delegate only to its available workers");
|
||||
});
|
||||
return async () => {
|
||||
controller.abort();
|
||||
await updates;
|
||||
};
|
||||
},
|
||||
} satisfies PluginModule;
|
||||
});
|
||||
|
||||
+25
-193
@@ -1,200 +1,32 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { homedir } from "node:os";
|
||||
import { isAbsolute, join } from "node:path";
|
||||
import type { Config } from "@opencode-ai/sdk/v2";
|
||||
import type { Plugin } from "@opencode/plugin";
|
||||
import type { ModelInfo } from "@opencode/client";
|
||||
import { z } from "zod";
|
||||
|
||||
const endpoint = z.object({ npm: z.string().optional(), api: z.string().optional() });
|
||||
const catalogProvider = endpoint.extend({
|
||||
id: z.string(),
|
||||
env: z.array(z.string()),
|
||||
models: z.record(
|
||||
z.string(),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
status: z.enum(["active", "alpha", "beta", "deprecated"]).optional(),
|
||||
provider: endpoint.optional(),
|
||||
}),
|
||||
),
|
||||
});
|
||||
const record = z.record(z.string(), z.unknown());
|
||||
const auth = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
type: z.literal("api"),
|
||||
key: z.string(),
|
||||
metadata: z.record(z.string(), z.string()).optional(),
|
||||
}),
|
||||
z.object({
|
||||
type: z.literal("oauth"),
|
||||
refresh: z.string(),
|
||||
access: z.string(),
|
||||
expires: z.number().int().nonnegative(),
|
||||
accountId: z.string().optional(),
|
||||
enterpriseUrl: z.string().optional(),
|
||||
}),
|
||||
z.object({ type: z.literal("wellknown"), key: z.string(), token: z.string() }),
|
||||
]);
|
||||
const priorityOptions = z.object({ serviceTier: z.enum(["priority", "fast"]) });
|
||||
const missingFile = z.object({ code: z.literal("ENOENT") });
|
||||
|
||||
type Model = {
|
||||
id: string;
|
||||
npm: string;
|
||||
baseURL: string | undefined;
|
||||
serviceTier: z.infer<typeof priorityOptions>["serviceTier"] | undefined;
|
||||
status: string | undefined;
|
||||
};
|
||||
|
||||
async function local(path: string) {
|
||||
try {
|
||||
return await readFile(path, "utf8");
|
||||
} catch (error) {
|
||||
if (missingFile.safeParse(error).success) return undefined;
|
||||
throw error;
|
||||
function priority(model: ModelInfo) {
|
||||
if (model.modelID !== "gpt-5.6-luna") return undefined;
|
||||
for (const settings of [model.settings, ...model.variants.map((variant) => variant.settings)]) {
|
||||
if (settings?.serviceTier === "priority" || settings?.serviceTier === "fast")
|
||||
return settings.serviceTier;
|
||||
}
|
||||
}
|
||||
|
||||
async function catalog() {
|
||||
const source = process.env.OPENCODE_MODELS_URL || "https://models.opencode.ai";
|
||||
const filename =
|
||||
source === "https://models.opencode.ai"
|
||||
? "models.json"
|
||||
: `models-${createHash("sha1").update(source).digest("hex")}.json`;
|
||||
const cache = process.env.XDG_CACHE_HOME;
|
||||
const path =
|
||||
process.env.OPENCODE_MODELS_PATH ??
|
||||
join(cache && isAbsolute(cache) ? cache : join(homedir(), ".cache"), "opencode", filename);
|
||||
const text = await local(path);
|
||||
if (text !== undefined) return record.parse(JSON.parse(text));
|
||||
const disabled = process.env.OPENCODE_DISABLE_MODELS_FETCH?.toLowerCase();
|
||||
if (disabled === "true" || disabled === "1") return {};
|
||||
const response = await fetch(`${source}/api.json`, { signal: AbortSignal.timeout(10_000) });
|
||||
if (!response.ok) throw new Error(`Model catalog request failed (${response.status})`);
|
||||
return record.parse(await response.json());
|
||||
}
|
||||
|
||||
async function authenticated(providerID: string) {
|
||||
const data = process.env.XDG_DATA_HOME;
|
||||
const text =
|
||||
process.env.OPENCODE_AUTH_CONTENT ||
|
||||
(await local(
|
||||
join(
|
||||
data && isAbsolute(data) ? data : join(homedir(), ".local/share"),
|
||||
"opencode",
|
||||
"auth.json",
|
||||
),
|
||||
));
|
||||
if (text === undefined) return false;
|
||||
// Neither JSON nor schema diagnostics may include credential contents.
|
||||
try {
|
||||
const entries = record.parse(JSON.parse(text));
|
||||
if (!Object.hasOwn(entries, providerID)) return false;
|
||||
const credential = auth.parse(entries[providerID]);
|
||||
return credential.type === "api" || credential.type === "oauth";
|
||||
} catch {
|
||||
throw new Error("Invalid OpenCode authentication data");
|
||||
}
|
||||
}
|
||||
|
||||
// OpenAI lists Luna Fast/Priority support; account limits can still downgrade requests.
|
||||
// https://developers.openai.com/api/docs/guides/fast-mode
|
||||
function official(npm: string | undefined, baseURL: string | undefined) {
|
||||
if (npm !== "@ai-sdk/openai") return false;
|
||||
if (!baseURL) return true;
|
||||
if (!URL.canParse(baseURL)) return false;
|
||||
const url = new URL(baseURL);
|
||||
return url.origin === "https://api.openai.com" && /^\/v1\/?$/.test(url.pathname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap snapshot only: provider.list would wait for this config hook itself.
|
||||
* ponytail: catalog/config/env/stored auth only; bundled snapshots, experimental
|
||||
* catalog modes, runtime discovery, and later plugin/auth-loader rewrites are not
|
||||
* observable here. A post-bootstrap provider hook is needed to include those.
|
||||
* Credentials establish connectivity, not model entitlement or OAuth validity.
|
||||
*/
|
||||
export async function discover(config: Config, providerID: string) {
|
||||
if (config.disabled_providers?.includes(providerID)) return undefined;
|
||||
if (config.enabled_providers && !config.enabled_providers.includes(providerID))
|
||||
const baseURL = model.settings?.baseURL;
|
||||
if (model.package !== "@opencode/ai/providers/openai" && model.package !== "@ai-sdk/openai")
|
||||
return undefined;
|
||||
const configured =
|
||||
config.provider && Object.hasOwn(config.provider, providerID)
|
||||
? config.provider[providerID]
|
||||
: undefined;
|
||||
const entries = await catalog();
|
||||
const provider = Object.hasOwn(entries, providerID)
|
||||
? catalogProvider.parse(entries[providerID])
|
||||
if (baseURL === undefined) return "priority";
|
||||
const endpoint = z.url().safeParse(baseURL);
|
||||
if (!endpoint.success) return undefined;
|
||||
const url = new URL(endpoint.data);
|
||||
return url.origin === "https://api.openai.com" && /^\/v1\/?$/.test(url.pathname)
|
||||
? "priority"
|
||||
: undefined;
|
||||
if (!provider && !configured) return undefined;
|
||||
if (
|
||||
!configured &&
|
||||
!provider?.env.some((key) => Boolean(process.env[key])) &&
|
||||
!(await authenticated(providerID))
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const effective = new Map<string, Model>();
|
||||
for (const [key, model] of Object.entries(provider?.models ?? {})) {
|
||||
const npm = model.provider?.npm ?? provider?.npm ?? "@ai-sdk/openai-compatible";
|
||||
const baseURL = configured?.options?.baseURL || (model.provider?.api ?? provider?.api);
|
||||
effective.set(key, {
|
||||
id: model.id,
|
||||
npm,
|
||||
baseURL,
|
||||
status: model.status,
|
||||
serviceTier: priorityOptions.safeParse(configured?.options).data?.serviceTier,
|
||||
});
|
||||
}
|
||||
for (const [key, model] of Object.entries(configured?.models ?? {})) {
|
||||
const existing = effective.get(model.id ?? key);
|
||||
const npm =
|
||||
model.provider?.npm ??
|
||||
configured?.npm ??
|
||||
existing?.npm ??
|
||||
provider?.npm ??
|
||||
"@ai-sdk/openai-compatible";
|
||||
const baseURL =
|
||||
configured?.options?.baseURL ||
|
||||
(model.provider?.api ?? configured?.api ?? existing?.baseURL ?? provider?.api);
|
||||
let serviceTier = priorityOptions.safeParse({
|
||||
serviceTier: model.options?.serviceTier ?? configured?.options?.serviceTier,
|
||||
}).data?.serviceTier;
|
||||
if (!serviceTier) {
|
||||
for (const variant of Object.values(model.variants ?? {})) {
|
||||
if (variant.disabled) continue;
|
||||
serviceTier = priorityOptions.safeParse(variant).data?.serviceTier;
|
||||
if (serviceTier) break;
|
||||
}
|
||||
}
|
||||
effective.set(key, {
|
||||
id: model.id ?? existing?.id ?? key,
|
||||
npm,
|
||||
baseURL,
|
||||
status: model.status ?? existing?.status,
|
||||
serviceTier,
|
||||
});
|
||||
}
|
||||
const experimental = process.env.OPENCODE_ENABLE_EXPERIMENTAL_MODELS?.toLowerCase();
|
||||
for (const [key, model] of effective) {
|
||||
if (
|
||||
model.status === "deprecated" ||
|
||||
(model.status === "alpha" && experimental !== "true" && experimental !== "1") ||
|
||||
configured?.blacklist?.includes(key) ||
|
||||
(configured?.whitelist && !configured.whitelist.includes(key)) ||
|
||||
(key === "gpt-5-chat-latest" &&
|
||||
["openai", "github-copilot", "openrouter"].includes(providerID)) ||
|
||||
(providerID === "openrouter" && key === "openai/gpt-5-chat")
|
||||
) {
|
||||
effective.delete(key);
|
||||
continue;
|
||||
}
|
||||
model.serviceTier =
|
||||
model.id === "gpt-5.6-luna"
|
||||
? (model.serviceTier ??
|
||||
(official(model.npm, model.baseURL) ? "priority" : undefined))
|
||||
: undefined;
|
||||
}
|
||||
return { models: effective };
|
||||
export async function discover(context: Plugin.Context, providerID: string) {
|
||||
// Native lists already apply activation, integrations, configuration, and catalog transforms.
|
||||
const { data } = await context.catalog.model.list();
|
||||
const models = new Map<string, { model: ModelInfo; serviceTier: string | undefined }>();
|
||||
for (const model of data) {
|
||||
if (model.providerID === providerID && model.enabled)
|
||||
models.set(model.id, { model, serviceTier: priority(model) });
|
||||
}
|
||||
return models;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,206 @@
|
||||
import { afterEach, expect, test } from "bun:test";
|
||||
import { createHash } from "node:crypto";
|
||||
import {
|
||||
chmod,
|
||||
mkdir,
|
||||
mkdtemp,
|
||||
readFile,
|
||||
readdir,
|
||||
readlink,
|
||||
rm,
|
||||
symlink,
|
||||
writeFile,
|
||||
} from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const installer = fileURLToPath(new URL("../install.sh", import.meta.url));
|
||||
const directories: string[] = [];
|
||||
const configContents = '{\n // Keep user settings and comments.\n "theme": "dark"\n}\n';
|
||||
const previousPlugin = 'export default { id: "previous", setup() { return "preserved"; } };\n';
|
||||
const previousTarget = "../stanp-opencode/install.previous";
|
||||
|
||||
afterEach(async () => {
|
||||
await Promise.all(
|
||||
directories.splice(0).map((path) => rm(path, { recursive: true, force: true })),
|
||||
);
|
||||
});
|
||||
|
||||
async function run(command: string[], cwd: string, env: NodeJS.ProcessEnv) {
|
||||
const child = Bun.spawn(command, {
|
||||
cwd,
|
||||
env,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
timeout: 20_000,
|
||||
});
|
||||
const [exitCode, stdout, stderr] = await Promise.all([
|
||||
child.exited,
|
||||
new Response(child.stdout).text(),
|
||||
new Response(child.stderr).text(),
|
||||
]);
|
||||
return { exitCode, stdout, stderr };
|
||||
}
|
||||
|
||||
async function install(mode: "native" | "checksum" | "legacy") {
|
||||
const directory = await mkdtemp(join(tmpdir(), "stanp-install-"));
|
||||
directories.push(directory);
|
||||
const config =
|
||||
mode === "native"
|
||||
? join(directory, "xdg", "opencode")
|
||||
: join(directory, "custom config with spaces");
|
||||
const bin = join(directory, "bin");
|
||||
const fixture = join(directory, "package");
|
||||
await Promise.all([
|
||||
mkdir(bin),
|
||||
mkdir(join(fixture, "dist"), { recursive: true }),
|
||||
mkdir(join(config, "plugins"), { recursive: true }),
|
||||
mkdir(join(config, "stanp-opencode", "install.previous"), { recursive: true }),
|
||||
]);
|
||||
await Promise.all([
|
||||
writeFile(join(config, "opencode.jsonc"), configContents),
|
||||
symlink(previousTarget, join(config, "plugins", "stanp-opencode")),
|
||||
writeFile(join(config, "stanp-opencode", "install.previous", "index.js"), previousPlugin),
|
||||
writeFile(
|
||||
join(config, "stanp-opencode", "install.previous", "package.json"),
|
||||
'{"name":"stanp-opencode","type":"module","main":"./index.js"}\n',
|
||||
),
|
||||
writeFile(join(fixture, "index.js"), 'export { default } from "./dist/index.js";\n'),
|
||||
writeFile(
|
||||
join(fixture, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "stanp-opencode",
|
||||
version: "1.0.0",
|
||||
type: "module",
|
||||
main: "./dist/index.js",
|
||||
exports: "./dist/index.js",
|
||||
scripts: { postinstall: "bun ./postinstall.js" },
|
||||
}),
|
||||
),
|
||||
writeFile(
|
||||
join(fixture, "postinstall.js"),
|
||||
'await Bun.write(process.env.POSTINSTALL_MARKER, "executed");\n',
|
||||
),
|
||||
writeFile(
|
||||
join(fixture, "dist", "index.js"),
|
||||
'await Bun.write(process.env.IMPORT_MARKER, "imported");\n' +
|
||||
(mode === "legacy"
|
||||
? 'export default { id: "stanp-opencode", async server() { return {}; } };\n'
|
||||
: 'export default { id: "stanp-opencode", setup() { return "native-ready"; } };\n'),
|
||||
),
|
||||
]);
|
||||
const env = {
|
||||
...Bun.env,
|
||||
PATH: `${bin}:${dirname(process.execPath)}:${Bun.env.PATH ?? "/usr/bin:/bin"}`,
|
||||
HOME: directory,
|
||||
XDG_CONFIG_HOME: join(directory, "xdg"),
|
||||
OPENCODE_CONFIG_DIR: mode === "native" ? "" : config,
|
||||
FIXTURE_DIR: directory,
|
||||
POSTINSTALL_MARKER: join(directory, "postinstall-ran"),
|
||||
IMPORT_MARKER: join(directory, "import-ran"),
|
||||
};
|
||||
const packed = await run(["tar", "-czf", "stanp-opencode.tgz", "package"], directory, env);
|
||||
expect(packed, packed.stderr).toMatchObject({ exitCode: 0 });
|
||||
const digest =
|
||||
mode === "checksum"
|
||||
? "0".repeat(64)
|
||||
: createHash("sha256")
|
||||
.update(await readFile(join(directory, "stanp-opencode.tgz")))
|
||||
.digest("hex");
|
||||
await Promise.all([
|
||||
writeFile(join(directory, "stanp-opencode.tgz.sha256"), `${digest} stanp-opencode.tgz\n`),
|
||||
writeFile(
|
||||
join(directory, "release.json"),
|
||||
JSON.stringify({
|
||||
tag_name: "v1.0.0",
|
||||
assets: ["stanp-opencode.tgz", "stanp-opencode.tgz.sha256"].map((name) => ({
|
||||
name,
|
||||
browser_download_url: `https://fixtures.invalid/${name}`,
|
||||
})),
|
||||
}),
|
||||
),
|
||||
writeFile(
|
||||
join(bin, "curl"),
|
||||
`#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
url=""
|
||||
output=""
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
-o|--output) output="$2"; shift 2 ;;
|
||||
https://*) url="$1"; shift ;;
|
||||
*) shift ;;
|
||||
esac
|
||||
done
|
||||
case "$url" in
|
||||
https://git.krtss.de/api/v1/repos/StanPonomarev/stanp-opencode/releases/latest) source=release.json ;;
|
||||
https://fixtures.invalid/stanp-opencode.tgz) source=stanp-opencode.tgz ;;
|
||||
https://fixtures.invalid/stanp-opencode.tgz.sha256) source=stanp-opencode.tgz.sha256 ;;
|
||||
*) printf 'Unexpected fixture URL: %s\\n' "$url" >&2; exit 1 ;;
|
||||
esac
|
||||
if [[ -n "$output" ]]; then
|
||||
cp "$FIXTURE_DIR/$source" "$output"
|
||||
else
|
||||
cat "$FIXTURE_DIR/$source"
|
||||
fi
|
||||
`,
|
||||
),
|
||||
]);
|
||||
await chmod(join(bin, "curl"), 0o755);
|
||||
const result = await run(["bash", installer], directory, env);
|
||||
return { directory, config, env, result };
|
||||
}
|
||||
|
||||
test("installs an importable native plugin under XDG without changing user configuration or running scripts", async () => {
|
||||
const { directory, config, env, result } = await install("native");
|
||||
expect(result, result.stderr).toMatchObject({ exitCode: 0 });
|
||||
// The generated package path is only known at runtime; exercise its module-loading boundary.
|
||||
const imported = await run(
|
||||
[
|
||||
process.execPath,
|
||||
"-e",
|
||||
"const { default: plugin } = await import(process.argv[1]); console.log(JSON.stringify([plugin.id, plugin.setup()]));",
|
||||
join(config, "plugins", "stanp-opencode"),
|
||||
],
|
||||
directory,
|
||||
env,
|
||||
);
|
||||
expect(imported, imported.stderr).toMatchObject({
|
||||
exitCode: 0,
|
||||
stdout: '["stanp-opencode","native-ready"]\n',
|
||||
});
|
||||
expect(await readFile(join(config, "opencode.jsonc"), "utf8")).toBe(configContents);
|
||||
expect(
|
||||
await readFile(join(config, "stanp-opencode", "install.previous", "index.js"), "utf8"),
|
||||
).toBe(previousPlugin);
|
||||
expect(await Bun.file(env.POSTINSTALL_MARKER).exists()).toBe(false);
|
||||
}, 60_000);
|
||||
|
||||
for (const mode of ["checksum", "legacy"] as const) {
|
||||
test(`${mode} failure preserves the installed plugin in a custom path containing spaces`, async () => {
|
||||
const { directory, config, env, result } = await install(mode);
|
||||
expect(result.exitCode, result.stderr).not.toBe(0);
|
||||
expect(await readlink(join(config, "plugins", "stanp-opencode"))).toBe(previousTarget);
|
||||
expect(await readFile(join(config, "opencode.jsonc"), "utf8")).toBe(configContents);
|
||||
expect(
|
||||
await readFile(join(config, "stanp-opencode", "install.previous", "index.js"), "utf8"),
|
||||
).toBe(previousPlugin);
|
||||
expect(await readdir(join(config, "stanp-opencode"))).toEqual(["install.previous"]);
|
||||
expect(await readdir(join(config, "plugins"))).toEqual(["stanp-opencode"]);
|
||||
// Load the preserved package from this test's runtime-selected configuration directory.
|
||||
const imported = await run(
|
||||
[
|
||||
process.execPath,
|
||||
"-e",
|
||||
"const { default: plugin } = await import(process.argv[1]); console.log(plugin.setup());",
|
||||
join(config, "plugins", "stanp-opencode"),
|
||||
],
|
||||
directory,
|
||||
env,
|
||||
);
|
||||
expect(imported, imported.stderr).toMatchObject({ exitCode: 0, stdout: "preserved\n" });
|
||||
expect(await Bun.file(env.POSTINSTALL_MARKER).exists()).toBe(false);
|
||||
expect(await Bun.file(env.IMPORT_MARKER).exists()).toBe(mode === "legacy");
|
||||
}, 60_000);
|
||||
}
|
||||
+335
-170
@@ -1,186 +1,351 @@
|
||||
import { afterAll, beforeAll, expect, test } from "bun:test";
|
||||
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { createOpencodeClient } from "@opencode-ai/sdk";
|
||||
import type { Config, PluginOptions } from "@opencode-ai/plugin";
|
||||
import plugin from "../src/index.js";
|
||||
import { z } from "zod";
|
||||
import { afterEach, expect, test } from "bun:test";
|
||||
import { Agent, Model, Plugin, Provider } from "@opencode/plugin";
|
||||
import type { AgentEditor } from "@opencode/plugin/promise/agent";
|
||||
import type { DeepMutable } from "@opencode/plugin/promise/types";
|
||||
import type { Info, ToolContext, ToolEditor } from "@opencode/plugin/promise/tool";
|
||||
import type { JsonValue, ModelInfo, SessionGetInput } from "@opencode/client";
|
||||
import type { SessionContext } from "@opencode/plugin/promise/session";
|
||||
import { gptAgents } from "../src/config.js";
|
||||
import plugin from "../src/index.js";
|
||||
|
||||
let directory: string;
|
||||
const originalModels = process.env.OPENCODE_MODELS_PATH;
|
||||
const originalAuth = process.env.OPENCODE_AUTH_CONTENT;
|
||||
|
||||
beforeAll(async () => {
|
||||
directory = await mkdtemp(join(tmpdir(), "stanp-tests-"));
|
||||
const path = join(directory, "models.json");
|
||||
await writeFile(
|
||||
path,
|
||||
JSON.stringify({
|
||||
test: {
|
||||
id: "test",
|
||||
env: [],
|
||||
npm: "@ai-sdk/openai-compatible",
|
||||
models: Object.fromEntries(
|
||||
["gpt-5.6-luna", "gpt-5.6-sol", "gpt-6-astra"].map((id) => [id, { id }]),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
process.env.OPENCODE_MODELS_PATH = path;
|
||||
process.env.OPENCODE_AUTH_CONTENT = "{}";
|
||||
const providerID = Provider.ID.make("test");
|
||||
function model(id: string): ModelInfo {
|
||||
return Model.Info.default(providerID, Model.ID.make(id));
|
||||
}
|
||||
const allModels = ["gpt-5.6-luna", "gpt-5.6-sol", "gpt-6-astra"].map(model);
|
||||
const cleanups: Plugin.Cleanup[] = [];
|
||||
afterEach(async () => {
|
||||
for (const cleanup of cleanups.splice(0)) await cleanup();
|
||||
});
|
||||
type ModelContext = Pick<SessionContext, "agent" | "tools">;
|
||||
type HookEvent = ModelContext | Pick<SessionGetInput, "sessionID">;
|
||||
type FixtureSetup = (
|
||||
context: Pick<Plugin.Context, "options">,
|
||||
) => Plugin.Cleanup | void | Promise<Plugin.Cleanup | void>;
|
||||
|
||||
afterAll(async () => {
|
||||
if (originalModels === undefined) delete process.env.OPENCODE_MODELS_PATH;
|
||||
else process.env.OPENCODE_MODELS_PATH = originalModels;
|
||||
if (originalAuth === undefined) delete process.env.OPENCODE_AUTH_CONTENT;
|
||||
else process.env.OPENCODE_AUTH_CONTENT = originalAuth;
|
||||
await rm(directory, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
async function hooks(caller = "build", options: PluginOptions = { provider: "test" }) {
|
||||
return plugin.server(
|
||||
{
|
||||
client: createOpencodeClient({
|
||||
baseUrl: "http://localhost:1",
|
||||
fetch: async (request) =>
|
||||
Response.json(
|
||||
request.url.endsWith("/user")
|
||||
? { info: { role: "user", agent: caller }, parts: [] }
|
||||
: [
|
||||
{
|
||||
info: {
|
||||
role: "assistant",
|
||||
mode: "general",
|
||||
parentID: "user",
|
||||
},
|
||||
parts: [],
|
||||
},
|
||||
],
|
||||
),
|
||||
}),
|
||||
project: { id: "test", worktree: directory, time: { created: 0 } },
|
||||
directory,
|
||||
worktree: directory,
|
||||
serverUrl: new URL("http://localhost:1"),
|
||||
experimental_workspace: { register() {} },
|
||||
$: Bun.$,
|
||||
async function host(
|
||||
models: ModelInfo[] = allModels,
|
||||
options: Plugin.Context["options"] = { provider: "test" },
|
||||
) {
|
||||
const agents = new Map<string, DeepMutable<Agent.Info>>();
|
||||
const build: DeepMutable<Agent.Info> = Agent.Info.default(Agent.ID.make("build"));
|
||||
build.permissions.push({ action: "shell", resource: "git push *", effect: "ask" });
|
||||
agents.set("build", build);
|
||||
const originalBuild = structuredClone(build);
|
||||
const sessionHooks: Record<string, (event: HookEvent) => Promise<void> | void> = {};
|
||||
let before!: (event: { tool: string; agent: string; input: unknown }) => Promise<void> | void;
|
||||
let parent = "build";
|
||||
let child = "fast-lo";
|
||||
let defaultAgent = "build";
|
||||
const registration = { async dispose() {} };
|
||||
let transform!: (editor: AgentEditor) => void;
|
||||
let reloaded = Promise.withResolvers<void>();
|
||||
let events!: ReadableStreamDefaultController<{ type: string }>;
|
||||
const stream = new ReadableStream<{ type: string }>({
|
||||
start(controller) {
|
||||
events = controller;
|
||||
},
|
||||
});
|
||||
const storage = new Map<string, JsonValue>();
|
||||
const tools = new Map<string, Info>();
|
||||
// SAFETY: This test host implements the native APIs used by setup; unrelated context
|
||||
// services are deliberately absent so unexpected new dependencies fail the test.
|
||||
const context = {
|
||||
options,
|
||||
);
|
||||
catalog: {
|
||||
model: {
|
||||
async list() {
|
||||
return { data: models };
|
||||
},
|
||||
},
|
||||
},
|
||||
event: {
|
||||
subscribe({ signal }: { signal: AbortSignal }) {
|
||||
signal.addEventListener("abort", () => events.close(), { once: true });
|
||||
return stream;
|
||||
},
|
||||
},
|
||||
storage: {
|
||||
async get(key: string) {
|
||||
return storage.get(key);
|
||||
},
|
||||
async set(key: string, value: JsonValue) {
|
||||
storage.set(key, value);
|
||||
},
|
||||
},
|
||||
agent: {
|
||||
async list() {
|
||||
return { data: [...agents.values()] };
|
||||
},
|
||||
async get({ agentID }: { agentID: string }) {
|
||||
return { data: agents.get(agentID) };
|
||||
},
|
||||
async transform(callback: (editor: AgentEditor) => void) {
|
||||
transform = callback;
|
||||
callback({
|
||||
get: (id) => agents.get(id),
|
||||
list: () => [...agents.values()],
|
||||
default(id) {
|
||||
defaultAgent = id ?? "build";
|
||||
},
|
||||
remove(id) {
|
||||
agents.delete(id);
|
||||
},
|
||||
update(id, update) {
|
||||
const agent = agents.get(id) ?? Agent.Info.default(Agent.ID.make(id));
|
||||
update(agent);
|
||||
agents.set(id, agent);
|
||||
},
|
||||
});
|
||||
return registration;
|
||||
},
|
||||
async reload() {
|
||||
agents.clear();
|
||||
agents.set("build", build);
|
||||
await this.transform(transform);
|
||||
reloaded.resolve();
|
||||
},
|
||||
},
|
||||
session: {
|
||||
async hook(name: string, callback: (event: HookEvent) => Promise<void> | void) {
|
||||
sessionHooks[name] = callback;
|
||||
return registration;
|
||||
},
|
||||
async get({ sessionID }: { sessionID: string }) {
|
||||
return sessionID === "child"
|
||||
? { agent: child, parentID: "parent" }
|
||||
: { agent: parent };
|
||||
},
|
||||
},
|
||||
tool: {
|
||||
async transform(callback: (editor: ToolEditor) => void) {
|
||||
callback({
|
||||
get(id) {
|
||||
const tool = tools.get(id);
|
||||
return tool ? { ...tool, id } : undefined;
|
||||
},
|
||||
list: () => [...tools].map(([id, tool]) => ({ ...tool, id })),
|
||||
namespace() {},
|
||||
add(tool) {
|
||||
tools.set(tool.name, tool);
|
||||
},
|
||||
update(id, update) {
|
||||
const tool = tools.get(id);
|
||||
if (tool) update(tool);
|
||||
},
|
||||
remove(id) {
|
||||
tools.delete(id);
|
||||
},
|
||||
});
|
||||
return registration;
|
||||
},
|
||||
async hook(_name: string, callback: typeof before) {
|
||||
before = callback;
|
||||
return registration;
|
||||
},
|
||||
},
|
||||
};
|
||||
// SAFETY: Exercise the real setup with the native operations implemented by this
|
||||
// partial host; absent services intentionally fail instead of becoming inert mocks.
|
||||
const setup = plugin.setup as FixtureSetup;
|
||||
const cleanup = await setup(context);
|
||||
if (cleanup) cleanups.push(cleanup);
|
||||
return {
|
||||
agents,
|
||||
build,
|
||||
defaultAgent,
|
||||
originalBuild,
|
||||
async refresh(next: ModelInfo[]) {
|
||||
models = next;
|
||||
reloaded = Promise.withResolvers<void>();
|
||||
events.enqueue({ type: "catalog.updated" });
|
||||
await reloaded.promise;
|
||||
},
|
||||
async changeBuildPermissions(permissions: Agent.Info["permissions"]) {
|
||||
build.permissions = [...permissions];
|
||||
reloaded = Promise.withResolvers<void>();
|
||||
events.enqueue({ type: "agent.updated" });
|
||||
await reloaded.promise;
|
||||
},
|
||||
async todo(name: string, sessionID: string, input: JsonValue = {}) {
|
||||
// SAFETY: Todo executors use only sessionID and agent from the native context.
|
||||
return tools
|
||||
.get(name)!
|
||||
.execute(input, { sessionID, agent: Agent.ID.make("build") } as ToolContext);
|
||||
},
|
||||
async delegate(caller: string, target: string) {
|
||||
await before({ tool: "subagent", agent: caller, input: { agent: target } });
|
||||
},
|
||||
async command(caller: string, target: string) {
|
||||
parent = caller;
|
||||
child = target;
|
||||
await sessionHooks.prompt!({ sessionID: "child" });
|
||||
},
|
||||
async tools(caller: string) {
|
||||
const event: ModelContext = {
|
||||
agent: Agent.ID.make(caller),
|
||||
tools: {
|
||||
subagent: {
|
||||
description: "Native subagents",
|
||||
input: {
|
||||
type: "object",
|
||||
properties: { agent: { type: "string" }, prompt: { type: "string" } },
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
await sessionHooks.context!(event);
|
||||
return event.tools;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test("registration is atomic; only missing Astra degrades to four workers", async () => {
|
||||
const full: Config = { provider: { test: {} } };
|
||||
await (await hooks()).config(full);
|
||||
// The host's /agent endpoint rejects undefined options rather than JSON-stringifying them.
|
||||
z.json().parse(full.agent);
|
||||
expect(Object.keys(full.agent ?? {})).toEqual([
|
||||
"fast-lo",
|
||||
"fast-hi",
|
||||
"good-lo",
|
||||
"good-hi",
|
||||
"deep-lo",
|
||||
"deep-hi",
|
||||
"coordinate",
|
||||
]);
|
||||
|
||||
const reduced: Config = { provider: { test: { blacklist: ["gpt-6-astra"] } } };
|
||||
await (await hooks()).config(reduced);
|
||||
expect(Object.keys(reduced.agent ?? {})).toEqual([
|
||||
"fast-lo",
|
||||
"fast-hi",
|
||||
"good-lo",
|
||||
"good-hi",
|
||||
"coordinate",
|
||||
]);
|
||||
expect(reduced.agent?.coordinate?.model).toBe("test/gpt-5.6-sol");
|
||||
|
||||
for (const missing of ["gpt-5.6-luna", "gpt-5.6-sol"]) {
|
||||
const config: Config = { provider: { test: { blacklist: [missing] } } };
|
||||
await (await hooks()).config(config);
|
||||
expect(config.agent).toBeUndefined();
|
||||
}
|
||||
});
|
||||
|
||||
test("disconnected and explicitly disabled providers register nothing", async () => {
|
||||
const disconnected: Config = {};
|
||||
await (await hooks()).config(disconnected);
|
||||
expect(disconnected.agent).toBeUndefined();
|
||||
|
||||
const disabled: Config = { provider: { test: {} }, disabled_providers: ["test"] };
|
||||
await (await hooks()).config(disabled);
|
||||
expect(disabled.agent).toBeUndefined();
|
||||
});
|
||||
|
||||
test("manual task targets cannot bypass coordinate's primary-only restriction", async () => {
|
||||
const active = await hooks();
|
||||
await active.config({ provider: { test: {} } });
|
||||
await expect(
|
||||
active["tool.execute.before"](
|
||||
{ tool: "task", sessionID: "test", callID: "test" },
|
||||
{ args: { subagent_type: "coordinate", prompt: "implement" } },
|
||||
),
|
||||
).rejects.toThrow("cannot be delegated to");
|
||||
});
|
||||
|
||||
test("subtask bypass uses the parent user agent, not the synthetic assistant target", async () => {
|
||||
const coordinate = await hooks("coordinate");
|
||||
await coordinate.config({ provider: { test: { blacklist: ["gpt-6-astra"] } } });
|
||||
for (const target of ["general", "deep-lo"]) {
|
||||
await expect(
|
||||
coordinate["tool.execute.before"](
|
||||
{ tool: "task", sessionID: "test", callID: "test" },
|
||||
{ args: { subagent_type: target } },
|
||||
),
|
||||
).rejects.toThrow("only to its available workers");
|
||||
}
|
||||
const worker = await hooks("fast-hi");
|
||||
await worker.config({ provider: { test: {} } });
|
||||
await expect(
|
||||
worker["tool.execute.before"](
|
||||
{ tool: "task", sessionID: "test", callID: "test" },
|
||||
{ args: { subagent_type: "good-lo" } },
|
||||
),
|
||||
).rejects.toThrow("Workers cannot delegate");
|
||||
});
|
||||
|
||||
test("custom assignments do not silently take the GPT fallback", async () => {
|
||||
const custom = await hooks("build", {
|
||||
test("missing required models disables registration; only GPT mode degrades without Astra", async () => {
|
||||
const full = await host();
|
||||
expect(full.agents.has("deep-hi")).toBe(true);
|
||||
expect(String(full.agents.get("coordinate")?.model?.id)).toBe("gpt-6-astra");
|
||||
const reduced = await host(allModels.slice(0, 2));
|
||||
expect(reduced.agents.has("deep-hi")).toBe(false);
|
||||
expect(String(reduced.agents.get("coordinate")?.model?.id)).toBe("gpt-5.6-sol");
|
||||
expect(reduced.agents.get("coordinate")?.system).toContain("Deep agents are unavailable");
|
||||
expect((await host([])).agents.has("coordinate")).toBe(false);
|
||||
expect((await host(allModels.slice(1))).agents.has("coordinate")).toBe(false);
|
||||
const custom = await host([...allModels, model("local")], {
|
||||
mode: "custom",
|
||||
provider: "test",
|
||||
agents: { ...gptAgents, coordinate: { model: "local", effort: "low" } },
|
||||
});
|
||||
const config: Config = { provider: { test: { models: { local: { name: "Local" } } } } };
|
||||
await custom.config(config);
|
||||
expect(config.agent?.coordinate?.model).toBe("test/local");
|
||||
expect(config.agent?.coordinate?.options).toEqual({ reasoningEffort: "low" });
|
||||
|
||||
const missing: Config = {
|
||||
provider: { test: { blacklist: ["gpt-6-astra"], models: { local: {} } } },
|
||||
};
|
||||
await custom.config(missing);
|
||||
expect(missing.agent).toBeUndefined();
|
||||
expect(String(custom.agents.get("coordinate")?.model?.id)).toBe("local");
|
||||
expect(
|
||||
(
|
||||
await host(allModels.slice(0, 2), {
|
||||
mode: "custom",
|
||||
provider: "test",
|
||||
agents: gptAgents,
|
||||
})
|
||||
).agents.has("coordinate"),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
test("tier selection requires evidence and preserves the advertised fast tier", async () => {
|
||||
const namedFast = { name: "Luna", variants: { fast: { reasoningEffort: "low" } } };
|
||||
const ordinary: Config = { provider: { test: { models: { "gpt-5.6-luna": namedFast } } } };
|
||||
await (await hooks()).config(ordinary);
|
||||
expect(ordinary.agent?.["fast-lo"]?.options).toEqual({ reasoningEffort: "low" });
|
||||
|
||||
const advertised: Config = {
|
||||
provider: {
|
||||
test: {
|
||||
models: { "gpt-5.6-luna": { options: { serviceTier: "fast" } } },
|
||||
},
|
||||
},
|
||||
};
|
||||
await (await hooks()).config(advertised);
|
||||
expect(advertised.agent?.["fast-lo"]?.options).toEqual({
|
||||
reasoningEffort: "low",
|
||||
serviceTier: "fast",
|
||||
test("worker inheritance and coordinator isolation preserve build and default", async () => {
|
||||
const result = await host();
|
||||
expect(result.defaultAgent).toBe("build");
|
||||
expect(result.agents.get("build")).toEqual(result.originalBuild);
|
||||
const worker = result.agents.get("fast-lo")!;
|
||||
expect(worker.permissions).toContainEqual({
|
||||
action: "shell",
|
||||
resource: "git push *",
|
||||
effect: "ask",
|
||||
});
|
||||
expect(worker.permissions.at(-1)).toEqual({
|
||||
action: "subagent",
|
||||
resource: "*",
|
||||
effect: "deny",
|
||||
});
|
||||
const coordinate = result.agents.get("coordinate")!;
|
||||
expect(coordinate.permissions[0]).toEqual({ action: "*", resource: "*", effect: "deny" });
|
||||
expect(coordinate.permissions.some((rule) => rule.action === "shell")).toBe(false);
|
||||
expect(coordinate.permissions).toContainEqual({
|
||||
action: "read",
|
||||
resource: "*.env",
|
||||
effect: "ask",
|
||||
});
|
||||
expect(coordinate.permissions).toContainEqual({
|
||||
action: "subagent",
|
||||
resource: "fast-lo",
|
||||
effect: "allow",
|
||||
});
|
||||
});
|
||||
|
||||
test("manual calls and command-created child sessions cannot bypass delegation restrictions", async () => {
|
||||
const result = await host(allModels.slice(0, 2));
|
||||
for (const invoke of [result.delegate, result.command]) {
|
||||
await expect(invoke("build", "coordinate")).rejects.toThrow("cannot run as a subagent");
|
||||
await expect(invoke("fast-hi", "good-lo")).rejects.toThrow("Workers cannot delegate");
|
||||
await expect(invoke("coordinate", "deep-lo")).rejects.toThrow(
|
||||
"only to its available workers",
|
||||
);
|
||||
await invoke("coordinate", "good-hi");
|
||||
}
|
||||
const tools = await result.tools("coordinate");
|
||||
expect(tools.subagent?.input.properties).toEqual({
|
||||
agent: { type: "string", enum: ["fast-lo", "fast-hi", "good-lo", "good-hi"] },
|
||||
prompt: { type: "string" },
|
||||
});
|
||||
expect(await result.tools("fast-lo")).toEqual({});
|
||||
expect((await result.tools("build")).subagent?.description).toBe("Native subagents");
|
||||
});
|
||||
|
||||
test("reasoning settings and Luna priority use native advertised or official support", async () => {
|
||||
const luna = {
|
||||
...model("gpt-5.6-luna"),
|
||||
package: "@opencode/ai/providers/openai",
|
||||
settings: { baseURL: "https://api.openai.com/v1" },
|
||||
};
|
||||
const ordinary = await host();
|
||||
expect(ordinary.agents.get("fast-lo")?.request.settings).toEqual({ reasoningEffort: "low" });
|
||||
const official = await host([luna, ...allModels.slice(1)]);
|
||||
expect(official.agents.get("fast-hi")?.request.settings).toEqual({
|
||||
reasoningEffort: "high",
|
||||
serviceTier: "priority",
|
||||
});
|
||||
const proxy = await host([
|
||||
{ ...luna, settings: { baseURL: "https://proxy.example/v1" } },
|
||||
...allModels.slice(1),
|
||||
]);
|
||||
expect(proxy.agents.get("fast-lo")?.request.settings).toEqual({ reasoningEffort: "low" });
|
||||
const advertised = await host([
|
||||
{ ...luna, package: "custom", settings: { serviceTier: "fast" } },
|
||||
...allModels.slice(1),
|
||||
]);
|
||||
expect(advertised.agents.get("fast-lo")?.request.settings.serviceTier).toBe("fast");
|
||||
const disabled = await host([luna, ...allModels.slice(1)], {
|
||||
provider: "test",
|
||||
lunaPriority: false,
|
||||
});
|
||||
expect(disabled.agents.get("fast-lo")?.request.settings).toEqual({ reasoningEffort: "low" });
|
||||
});
|
||||
|
||||
test("catalog updates activate late models and remove unavailable agents", async () => {
|
||||
const result = await host([]);
|
||||
await result.refresh(allModels);
|
||||
expect(String(result.agents.get("coordinate")?.model?.id)).toBe("gpt-6-astra");
|
||||
await result.refresh(allModels.slice(0, 2));
|
||||
expect(result.agents.has("deep-lo")).toBe(false);
|
||||
expect(String(result.agents.get("coordinate")?.model?.id)).toBe("gpt-5.6-sol");
|
||||
await result.refresh([]);
|
||||
expect(result.agents.has("coordinate")).toBe(false);
|
||||
});
|
||||
|
||||
test("late build permission overrides remain effective for workers and coordinator", async () => {
|
||||
const result = await host();
|
||||
await result.changeBuildPermissions([
|
||||
...result.build.permissions,
|
||||
{ action: "read", resource: "*.env", effect: "deny" },
|
||||
{ action: "shell", resource: "git push *", effect: "deny" },
|
||||
]);
|
||||
expect(result.agents.get("fast-lo")?.permissions).toContainEqual({
|
||||
action: "shell",
|
||||
resource: "git push *",
|
||||
effect: "deny",
|
||||
});
|
||||
expect(
|
||||
result.agents
|
||||
.get("coordinate")
|
||||
?.permissions.filter((rule) => rule.action === "read" && rule.resource === "*.env")
|
||||
.at(-1)?.effect,
|
||||
).toBe("deny");
|
||||
});
|
||||
|
||||
test("todo lists persist within one session without leaking to another", async () => {
|
||||
const result = await host();
|
||||
const todos = [{ id: "1", content: "Implement", status: "in_progress", priority: "high" }];
|
||||
await result.todo("todowrite", "one", { todos });
|
||||
expect((await result.todo("todoread", "one")).content).toBe(JSON.stringify(todos));
|
||||
expect((await result.todo("todoread", "two")).content).toBe("[]");
|
||||
result.build.permissions.push({ action: "todowrite", resource: "*", effect: "ask" });
|
||||
await expect(result.todo("todowrite", "one", { todos: [] })).rejects.toThrow("cannot request");
|
||||
expect((await result.todo("todoread", "one")).content).toBe(JSON.stringify(todos));
|
||||
result.build.permissions.push({ action: "todoread", resource: "*", effect: "deny" });
|
||||
await expect(result.todo("todoread", "one")).rejects.toThrow("(deny)");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user