From a1971209d42ffdeb49b32b9aea882b1bfea53b10 Mon Sep 17 00:00:00 2001 From: pascalandr Date: Sun, 23 Aug 2026 21:11:09 +0200 Subject: [PATCH 1/5] feat: add OpenCode V2 compatibility V2 host uses @opencode-ai/client Promise API (0.0.0-beta-17595+) and a single global daemon instead of per-workspace runtimes. This plugin requires no runtime change: the Bun.serve proxy already binds an ephemeral port and reuses a healthy sibling on OPENCODE_CLAUDE_PROXY_PORT, so it coexists with the global service. Registration stays plugin field in opencode.json. Add optional peer @opencode-ai/client >=0.0.0-beta-17595, document no packages/opencode-plugin (deleted in CodeNomad MIGRATION_V2.md), and note CodeNomad V2 quota now surfaces Claude OAuth usage via api.anthropic.com/api/oauth/usage (e2b784f2). --- README.md | 12 +++++++++++- package.json | 8 ++++++++ src/index.ts | 5 +++++ src/proxy.ts | 5 +++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d664e42..78c8f61 100644 --- a/README.md +++ b/README.md @@ -147,11 +147,21 @@ The proxy records Agent SDK `rate_limit_event` telemetry and hard session-limit ## Requirements -- [OpenCode](https://opencode.ai) +- [OpenCode](https://opencode.ai) — V1 (`@opencode-ai/plugin` 1.18.x) and V2 (`@opencode-ai/client` ≥ 0.0.0-beta-17595) both supported - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) — on `PATH` or installed via the provider's install action (npm is used, or the official install script); the plugin also checks `~/.local/bin` and the npm global bin for a CLI the server PATH cannot see - Claude plan supported by Claude Code - Bun (plugin runtime) · Node.js ≥ 18 +## OpenCode V2 compatibility + +Verified with CodeNomad's V2 foundation (`MIGRATION_V2.md`, `0.0.0-beta-17595`): + +- **Host client:** V2 replaces `@opencode-ai/sdk` with the native `@opencode-ai/client` Promise API (`@opencode-ai/client/solid` + `createData`). This plugin does **not** depend on `@opencode-ai/client` at runtime (optional peer `>=0.0.0-beta-17595`), only the host does — no code change required in the plugin. +- **Global service:** V2 runs one shared OpenCode daemon for all workspaces/clients (see [opencode#43898](https://github.com/anomalyco/opencode/issues/43898#issuecomment-5372607267)). The plugin's `Bun.serve` proxy binds an ephemeral port by default and reuses an existing healthy listener on `OPENCODE_CLAUDE_PROXY_PORT` if pinned, so it coexists with the single global daemon — no per-workspace Bun runtime. +- **No `packages/opencode-plugin`:** CodeNomad V2 deletes its own `packages/opencode-plugin`, custom plugin channels, and per-workspace runtimes; external plugins like this one are unaffected. +- **Registration unchanged:** still `plugin: ["@openchamber/opencode-claude"]` in `~/.config/opencode/opencode.json` (global) or `.opencode/opencode.json` (project). The provider remains `claude-code`. +- **Quota:** CodeNomad V2 (`e2b784f2`) now surfaces Claude subscription quota via its auth-file plugin — `api.anthropic.com/api/oauth/usage` with `retry-after` cooldown (5 m–1 h) — alongside the existing `claude-code` proxy rate-limit gate (`GET /v1/rate-limit`). No model guessing required. + ## Development ```bash diff --git a/package.json b/package.json index 382e607..86e9297 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,14 @@ "@opencode-ai/plugin": "^1.18.15", "zod": "^4.4.3" }, + "peerDependencies": { + "@opencode-ai/client": ">=0.0.0-beta-17595" + }, + "peerDependenciesMeta": { + "@opencode-ai/client": { + "optional": true + } + }, "devDependencies": { "@types/bun": "^1.3.11", "@types/node": "^22.15.0", diff --git a/src/index.ts b/src/index.ts index 9e9936e..ce962b3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,6 +8,11 @@ * * Register in opencode.json: * { "plugin": ["@openchamber/opencode-claude"] } + * + * OpenCode V2: compatible with the native @opencode-ai/client Promise API + * (0.0.0-beta-17595+) and the single global daemon model. The proxy binds an + * ephemeral Bun.serve port and publishes the live URL via the config hook so + * the global service always hits the owning listener — no per-workspace runtime. */ import type { Hooks, Plugin, PluginInput } from "@opencode-ai/plugin"; import { diff --git a/src/proxy.ts b/src/proxy.ts index 8aae174..309d937 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -7,6 +7,11 @@ * Tool calls from OpenCode are exposed as an in-process MCP server. When Claude * invokes one, the stream parks (Cursor bridge-pool pattern) and returns * tool_calls; the follow-up request with tool results resumes the turn. + * + * OpenCode V2: the proxy is a single global listener (Bun.serve, ephemeral port + * by default) that coexists with V2's one shared daemon — no per-workspace + * runtime. A pinned OPENCODE_CLAUDE_PROXY_PORT reuses a healthy sibling + * listener via /v1/models health check. */ import { createHash, randomUUID } from "node:crypto"; import { From e6ff4ce3a8610c47847b3a9fbe25370d99ae0eab Mon Sep 17 00:00:00 2001 From: pascalandr Date: Sun, 23 Aug 2026 21:23:26 +0200 Subject: [PATCH 2/5] fix: retract unsupported OpenCode V2 compatibility OpenCode V2 requires the new Plugin.define entrypoint and registration APIs, while this package still implements the V1 hook contract. Remove the unrelated optional client peer and the claims that daemon and proxy behavior make the existing plugin compatible. Document the current V1-only requirement so users are not directed to install a package that V2 cannot load. The existing V1 runtime remains unchanged. Validated with bun run build. The smoke script still fails on Windows at its Unix executable fixture in test/smoke.ts:236, which is unrelated to this documentation and manifest correction. --- README.md | 12 +----------- package.json | 8 -------- src/index.ts | 5 ----- src/proxy.ts | 5 ----- 4 files changed, 1 insertion(+), 29 deletions(-) diff --git a/README.md b/README.md index 78c8f61..d89f246 100644 --- a/README.md +++ b/README.md @@ -147,21 +147,11 @@ The proxy records Agent SDK `rate_limit_event` telemetry and hard session-limit ## Requirements -- [OpenCode](https://opencode.ai) — V1 (`@opencode-ai/plugin` 1.18.x) and V2 (`@opencode-ai/client` ≥ 0.0.0-beta-17595) both supported +- [OpenCode V1](https://opencode.ai) (`@opencode-ai/plugin` 1.18.x). OpenCode V2 is not yet supported because it uses a different plugin API. - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) — on `PATH` or installed via the provider's install action (npm is used, or the official install script); the plugin also checks `~/.local/bin` and the npm global bin for a CLI the server PATH cannot see - Claude plan supported by Claude Code - Bun (plugin runtime) · Node.js ≥ 18 -## OpenCode V2 compatibility - -Verified with CodeNomad's V2 foundation (`MIGRATION_V2.md`, `0.0.0-beta-17595`): - -- **Host client:** V2 replaces `@opencode-ai/sdk` with the native `@opencode-ai/client` Promise API (`@opencode-ai/client/solid` + `createData`). This plugin does **not** depend on `@opencode-ai/client` at runtime (optional peer `>=0.0.0-beta-17595`), only the host does — no code change required in the plugin. -- **Global service:** V2 runs one shared OpenCode daemon for all workspaces/clients (see [opencode#43898](https://github.com/anomalyco/opencode/issues/43898#issuecomment-5372607267)). The plugin's `Bun.serve` proxy binds an ephemeral port by default and reuses an existing healthy listener on `OPENCODE_CLAUDE_PROXY_PORT` if pinned, so it coexists with the single global daemon — no per-workspace Bun runtime. -- **No `packages/opencode-plugin`:** CodeNomad V2 deletes its own `packages/opencode-plugin`, custom plugin channels, and per-workspace runtimes; external plugins like this one are unaffected. -- **Registration unchanged:** still `plugin: ["@openchamber/opencode-claude"]` in `~/.config/opencode/opencode.json` (global) or `.opencode/opencode.json` (project). The provider remains `claude-code`. -- **Quota:** CodeNomad V2 (`e2b784f2`) now surfaces Claude subscription quota via its auth-file plugin — `api.anthropic.com/api/oauth/usage` with `retry-after` cooldown (5 m–1 h) — alongside the existing `claude-code` proxy rate-limit gate (`GET /v1/rate-limit`). No model guessing required. - ## Development ```bash diff --git a/package.json b/package.json index 86e9297..382e607 100644 --- a/package.json +++ b/package.json @@ -58,14 +58,6 @@ "@opencode-ai/plugin": "^1.18.15", "zod": "^4.4.3" }, - "peerDependencies": { - "@opencode-ai/client": ">=0.0.0-beta-17595" - }, - "peerDependenciesMeta": { - "@opencode-ai/client": { - "optional": true - } - }, "devDependencies": { "@types/bun": "^1.3.11", "@types/node": "^22.15.0", diff --git a/src/index.ts b/src/index.ts index ce962b3..9e9936e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,11 +8,6 @@ * * Register in opencode.json: * { "plugin": ["@openchamber/opencode-claude"] } - * - * OpenCode V2: compatible with the native @opencode-ai/client Promise API - * (0.0.0-beta-17595+) and the single global daemon model. The proxy binds an - * ephemeral Bun.serve port and publishes the live URL via the config hook so - * the global service always hits the owning listener — no per-workspace runtime. */ import type { Hooks, Plugin, PluginInput } from "@opencode-ai/plugin"; import { diff --git a/src/proxy.ts b/src/proxy.ts index 309d937..8aae174 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -7,11 +7,6 @@ * Tool calls from OpenCode are exposed as an in-process MCP server. When Claude * invokes one, the stream parks (Cursor bridge-pool pattern) and returns * tool_calls; the follow-up request with tool results resumes the turn. - * - * OpenCode V2: the proxy is a single global listener (Bun.serve, ephemeral port - * by default) that coexists with V2's one shared daemon — no per-workspace - * runtime. A pinned OPENCODE_CLAUDE_PROXY_PORT reuses a healthy sibling - * listener via /v1/models health check. */ import { createHash, randomUUID } from "node:crypto"; import { From ecaae3d6c70bdbd942a41fc56e7ba1a3958bfa2f Mon Sep 17 00:00:00 2001 From: pascalandr Date: Sun, 23 Aug 2026 21:48:16 +0200 Subject: [PATCH 3/5] feat: add native OpenCode V2 compatibility Add a real V2 server plugin entrypoint while preserving the existing V1 root export. The V2 plugin starts the Claude proxy, contributes the claude-code provider and model catalog through native transforms, registers the official Claude CLI sign-in relay, and rewrites native model requests with live proxy, effort, session, model, and project-directory context. Pin @opencode-ai/plugin to the target 0.0.0-beta-17595 release and use its versioned V1 type export for the legacy entrypoint. V2 stores only a non-secret connection marker because its integration contract requires a credential record; Claude Code continues to own and refresh the actual subscription credentials. Add a mocked V2 context test covering catalog, integration, hook registration, routing, and cleanup. Validate TypeScript build and no-emit checking plus fresh packed-package imports for both root and ./server; the legacy smoke script retains its pre-existing Windows fake executable failure at test/smoke.ts:236. --- README.md | 42 ++++++---- bun.lock | 172 +++++++++++++++++++++++++++++++++++++---- package.json | 9 ++- src/index.ts | 2 +- src/server.ts | 155 +++++++++++++++++++++++++++++++++++++ test/plugin-v2.test.ts | 128 ++++++++++++++++++++++++++++++ 6 files changed, 476 insertions(+), 32 deletions(-) create mode 100644 src/server.ts create mode 100644 test/plugin-v2.test.ts diff --git a/README.md b/README.md index d89f246..5bf2c57 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ Subscription limit state is tracked with its reset time. `GET /v1/rate-limit` an ## Quick start -`claude-code` is **not** a built-in OpenCode provider. Install the plugin first, or `opencode auth login --provider claude-code` fails with `Unknown provider "claude-code"`. +`claude-code` is **not** a built-in OpenCode provider. Install the plugin before trying to sign in. ### 1. Install the plugin @@ -54,19 +54,27 @@ Subscription limit state is tracked with its reset time. `GET /v1/rate-limit` an npm install -g @openchamber/opencode-claude ``` -Or with OpenCode: +Or with OpenCode V2: ```bash -# global (recommended) -opencode plugin @openchamber/opencode-claude -g - -# or project-local (writes .opencode/opencode.json) -opencode plugin @openchamber/opencode-claude +opencode2 plugin add @openchamber/opencode-claude ``` ### 2. Register it in OpenCode -Add (or merge) this into `~/.config/opencode/opencode.json`: +OpenCode V2 uses the package's native `./server` entrypoint. Add (or merge) this into `~/.config/opencode/opencode.json`: + +```jsonc +{ + "$schema": "https://opencode.ai/config.json", + "plugins": ["@openchamber/opencode-claude"], + "providers": { + "claude-code": { "name": "Claude Code" } + } +} +``` + +OpenCode V1 continues to use the root entrypoint and legacy field names: ```jsonc { @@ -81,15 +89,17 @@ Add (or merge) this into `~/.config/opencode/opencode.json`: ### 3. Authenticate ```bash -claude auth login -opencode auth login --provider claude-code +claude auth login --claudeai +opencode2 auth login # pick "Sign in with Claude Code CLI" ``` +On OpenCode V1, use `opencode auth login --provider claude-code` instead. + ### 4. Run a Claude model ```bash -opencode run "Summarise this repository in five bullets." --model claude-code/sonnet +opencode2 run "Summarise this repository in five bullets." --model claude-code/sonnet ``` In the TUI, pick provider **claude-code**, choose a model, and set the **effort** variant (`low` / `medium` / `high` / `xhigh` / `max`) when you want deeper thinking. @@ -111,12 +121,12 @@ opencode plugin file://$PWD | **Install Claude Code CLI and sign in** | Shown only when the CLI is missing: runs the official installer (`npm i -g @anthropic-ai/claude-code`, official install script as fallback), then continues with the sign-in relay | | Paste the code from the Claude page | Goes straight to the CLI's stdin; the CLI does the token exchange and owns the result | | `claude auth login --claudeai` | Terminal alternative, always called out in the instructions — also the offered fallback when the CLI is missing (with the install command alongside) | -| Successful verification | Completes without writing to OpenCode's auth store | +| Successful verification | V1 stores nothing; V2 stores only a non-secret connection marker because its integration API requires a credential record | | Access expires | Claude Code refreshes its own credentials | Signing in is either the link and its code or the terminal command — the sign-in page the CLI asks for is the only URL the plugin ever hands to the host. -The plugin does not implement OAuth, inspect Claude credential files, inject tokens, or call Anthropic inference endpoints directly. +The plugin does not implement OAuth, inspect Claude credential files, inject tokens, or call Anthropic inference endpoints directly. In V2, the stored marker contains no Claude credential and is never used to authenticate with Anthropic. ## Architecture @@ -147,7 +157,7 @@ The proxy records Agent SDK `rate_limit_event` telemetry and hard session-limit ## Requirements -- [OpenCode V1](https://opencode.ai) (`@opencode-ai/plugin` 1.18.x). OpenCode V2 is not yet supported because it uses a different plugin API. +- [OpenCode V1](https://opencode.ai) or OpenCode V2 beta `0.0.0-beta-17595` - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) — on `PATH` or installed via the provider's install action (npm is used, or the official install script); the plugin also checks `~/.local/bin` and the npm global bin for a CLI the server PATH cannot see - Claude plan supported by Claude Code - Bun (plugin runtime) · Node.js ≥ 18 @@ -175,8 +185,8 @@ Optional knobs: | Symptom | Fix | | --- | --- | | Unknown provider `claude-code` | Install `@openchamber/opencode-claude` and restart OpenCode | -| Claude Code missing from provider list | Confirm `plugin` includes `@openchamber/opencode-claude` and restart OpenCode | -| Authentication error | Run `claude auth login`, verify `claude auth status --json`, then restart OpenCode | +| Claude Code missing from provider list | Confirm V2 `plugins` (or V1 `plugin`) includes `@openchamber/opencode-claude` and restart OpenCode | +| Authentication error | Run `claude auth login --claudeai`, verify `claude auth status --json`, then restart OpenCode | | 429 / rate-limit | Poll `GET /v1/rate-limit` or wait until `resetsAt`; the next turn resumes the same session | | Tools hang or invent output | Update to the latest plugin — park/resume MCP bridging is required | | Attachments ignored | Use a current build; image/PDF parts are converted to Claude blocks | diff --git a/bun.lock b/bun.lock index 3681484..c7907f8 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,7 @@ "name": "@openchamber/opencode-claude", "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.3.224", - "@opencode-ai/plugin": "^1.18.15", + "@opencode-ai/plugin": "0.0.0-beta-17595", "zod": "^4.4.3", }, "devDependencies": { @@ -39,10 +39,18 @@ "@anthropic-ai/sdk": ["@anthropic-ai/sdk@0.115.0", "", { "dependencies": { "json-schema-to-ts": "^3.1.1", "standardwebhooks": "^1.0.0" }, "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" }, "optionalPeers": ["zod"], "bin": { "anthropic-ai-sdk": "bin/cli" } }, "sha512-BJrFIVyjNuU8lfDyIJTvlRYzgQg+zEl78BxE7fq8esULsGz9IRQvGtW5spq3tydmtjQb/GFdooKGdGsetpx+lQ=="], + "@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/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/types": ["@aws-sdk/types@3.974.5", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-LkwLL2BLbC6wNNm4JaH9mbEqBMdOZCct6VAYqhdN4U1xrWM+fUJQEfbHwQgDypapOWTRtlk25akb5afM0P8CIQ=="], + "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], "@hono/node-server": ["@hono/node-server@2.1.0", "", { "peerDependencies": { "hono": "^4" } }, "sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg=="], + "@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=="], + "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.30.0", "", { "dependencies": { "@hono/node-server": "^1.19.9 || ^2.0.5", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA=="], "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ=="], @@ -57,9 +65,33 @@ "@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.15", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode-ai/sdk": "1.18.15", "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-AY10RtFbzLkf951dbLkSGJdBeddeS6ojbjvqCpWnINedqlj2cK/GF91xWjWnlHpqQZ4GABLPCuoSJx8mGmKvCw=="], + "@opencode-ai/ai": ["@opencode-ai/ai@0.0.0-beta-17595", "", { "dependencies": { "@opencode-ai/schema": "0.0.0-beta-17595", "@smithy/eventstream-codec": "4.2.14", "@smithy/util-utf8": "4.2.2", "aws4fetch": "1.0.20", "effect": "4.0.0-beta.107", "google-auth-library": "10.5.0" } }, "sha512-Dwxmw9tv5tw2t8p9Bmjo8XQqkdlNOc8SM8av8jRZYr2/c3NX38+rvOsLl5q85oAVqEKAHEqgXlMITwm60QhAEw=="], + + "@opencode-ai/client": ["@opencode-ai/client@0.0.0-beta-17595", "", { "dependencies": { "@opencode-ai/protocol": "0.0.0-beta-17595", "@opencode-ai/schema": "0.0.0-beta-17595" }, "peerDependencies": { "effect": "4.0.0-beta.107", "solid-js": ">=1.9.0" }, "optionalPeers": ["effect", "solid-js"] }, "sha512-uDM6jztQiyXulYQL9G7kx283cv+0WhgQ98AzfClKQnV5mOB5wVBTGIjD1FGRwyxhUNGJBrfaP+NqOwWFjZhoeg=="], + + "@opencode-ai/plugin": ["@opencode-ai/plugin@0.0.0-beta-17595", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode-ai/ai": "0.0.0-beta-17595", "@opencode-ai/client": "0.0.0-beta-17595", "@opencode-ai/protocol": "0.0.0-beta-17595", "@opencode-ai/schema": "0.0.0-beta-17595", "@opencode-ai/sdk": "1.18.5", "@standard-schema/spec": "1.1.0", "effect": "4.0.0-beta.107", "zod": "4.1.8" }, "peerDependencies": { "@opencode-ai/theme": "0.0.0-beta-17595", "@opentui/core": ">=0.5.3", "@opentui/keymap": ">=0.5.3", "@opentui/solid": ">=0.5.3", "solid-js": ">=1.9.0" }, "optionalPeers": ["@opencode-ai/theme", "@opentui/core", "@opentui/keymap", "@opentui/solid", "solid-js"] }, "sha512-AeK5lPPpy/3IO7zgmLvn9uaQD4OzN8EYQlxFk8P5WxOb1THLAzNs3c8eQJ8ZY2k6SFgdZJ/Vr+0Czo06yEI0RA=="], + + "@opencode-ai/protocol": ["@opencode-ai/protocol@0.0.0-beta-17595", "", { "dependencies": { "@opencode-ai/schema": "0.0.0-beta-17595", "effect": "4.0.0-beta.107" } }, "sha512-du77bQXIvOvqzyqS/I5gJMY3FZhXH2Oi3gs3ywAOnHCGRkwmVE9ofvFwR4G/Rzx/oVUOuGkyN28si29AluXGWw=="], + + "@opencode-ai/schema": ["@opencode-ai/schema@0.0.0-beta-17595", "", { "dependencies": { "@standard-schema/spec": "1.1.0", "effect": "4.0.0-beta.107" } }, "sha512-448/fW6HIHd2JT+TSgm4izcAWl51f17GR6WcfGbS9SyWmXFNnX1Fi03xNRgf7dnul9yyceXEsMbreUvteKxAYg=="], + + "@opencode-ai/sdk": ["@opencode-ai/sdk@1.18.5", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-7KgMvP5/1oxbhHj6kYBtPSTEdFKYpUeEYOzBTKdzSaRpapUpFFdn6Hkus3rr0rljO0kukWZIgRd3DrVBwTULGA=="], + + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + + "@smithy/core": ["@smithy/core@3.33.3", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-CsOeKq/9kA3y6VJHt+/+VTCtBaxJ4OTFpgrjIUhPpDIKxBci1k2bJaQASF2h/ELWrulGp+t97DZ0mevfAD8idg=="], - "@opencode-ai/sdk": ["@opencode-ai/sdk@1.18.15", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-8sfo9nGiVwesAZW9Wqkvynyn7w4wYaHx1O9qOHpYL65+Bs2XUpHP3kBbZe58gjQydFgk6I74kUF7sqCiPu2arQ=="], + "@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/is-array-buffer": ["@smithy/is-array-buffer@2.2.0", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA=="], + + "@smithy/types": ["@smithy/types@4.17.2", "", { "dependencies": { "tslib": "^2.6.2" } }, "sha512-FOKpVZob9MPTn2znRzGrnsMHv7BOsKVw3XiP/cOyYLDVZ9qKp4nifIiSCuUU/fIj5Vu0UOAxCFr+qRAtG0NUkA=="], + + "@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=="], "@stablelib/base64": ["@stablelib/base64@1.0.1", "", {}, "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="], @@ -71,12 +103,30 @@ "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], + "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], + "ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="], "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], + "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@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "bignumber.js": ["bignumber.js@9.3.1", "", {}, "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ=="], + "body-parser": ["body-parser@2.3.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^2.0.0", "debug": "^4.4.3", "http-errors": "^2.0.1", "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", "qs": "^6.15.2", "raw-body": "^3.0.2", "type-is": "^2.1.0" } }, "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw=="], + "brace-expansion": ["brace-expansion@2.1.4", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg=="], + + "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=="], "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], @@ -85,6 +135,10 @@ "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + "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=="], + "content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="], "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], @@ -97,6 +151,8 @@ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + "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=="], "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], @@ -105,9 +161,15 @@ "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + "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=="], + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - "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=="], + "effect": ["effect@4.0.0-beta.107", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.4", "uuid": "^14.0.1" } }, "sha512-OoBAv8eF+yanc+C6xhgEUnWeXUSHA6ynnscYqpkAY9GSnzZWystsIjBowVqCkLpHGlnRtdIqYT3wHwpOY6JDnQ=="], + + "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], @@ -129,6 +191,8 @@ "express-rate-limit": ["express-rate-limit@8.6.2", "", { "dependencies": { "debug": "^4.4.3", "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A=="], + "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=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], @@ -137,9 +201,13 @@ "fast-uri": ["fast-uri@3.1.5", "", {}, "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw=="], + "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], + "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], - "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="], + "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=="], "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], @@ -147,12 +215,24 @@ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + "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=="], + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + "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=="], + + "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=="], + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + "gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], @@ -161,22 +241,28 @@ "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], + "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=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], - "ini": ["ini@7.0.0", "", {}, "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w=="], - "ip-address": ["ip-address@10.4.0", "", {}, "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ=="], "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="], "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=="], + "jose": ["jose@6.2.8", "", {}, "sha512-Bsdjwm3Qsd/P0jR+BHDe3LytDfY7WBq2HmCCLIwuVRHMuEC9ae7/R474GIUdF1NgCyZjzVo/A9DOiOBtXq8ZoQ=="], + "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], @@ -185,8 +271,14 @@ "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="], + "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=="], + "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="], + "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], "media-typer": ["media-typer@1.1.1", "", {}, "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ=="], @@ -197,16 +289,22 @@ "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], + "minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + + "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], "msgpackr": ["msgpackr@2.0.5", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-cef05H/dSYpLpqp3sj/qyZh5vhUYCalnaLO7j1yOmpsR0y/XwLVtK7r5gn+U/F7CTEfMowcGhlUQJDLcLf7jcA=="], "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.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + "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-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=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], @@ -217,10 +315,14 @@ "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + "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=="], + "path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="], @@ -237,8 +339,12 @@ "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], + "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], @@ -259,16 +365,26 @@ "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + "standardwebhooks": ["standardwebhooks@1.0.0", "", { "dependencies": { "@stablelib/base64": "^1.0.0", "fast-sha256": "^1.3.0" } }, "sha512-BbHGOQK9olHPMvQNHWul6MYlrRTAOKn03rOe4A8O3CLWhNf4YHBqq2HJKKC+sfqpxiBY52pNeesD6jIiLDz8jg=="], "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], - "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + "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=="], - "toml": ["toml@4.3.0", "", {}, "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A=="], + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "type-is": ["type-is@2.1.0", "", { "dependencies": { "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], @@ -281,20 +397,50 @@ "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + "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=="], - "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + "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=="], - "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], + "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=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], + "@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=="], + "@opencode-ai/plugin/zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="], "body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], + "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=="], + + "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=="], + "type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], + + "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/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=="], + + "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=="], } } diff --git a/package.json b/package.json index 382e607..2df5ab1 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,11 @@ "types": "./dist/index.d.ts", "import": "./opencode-claude.js", "default": "./opencode-claude.js" + }, + "./server": { + "types": "./dist/server.d.ts", + "import": "./dist/server.js", + "default": "./dist/server.js" } }, "files": [ @@ -21,7 +26,7 @@ "scripts": { "prebuild": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"", "build": "tsc -p tsconfig.json", - "test": "bun test/smoke.ts", + "test": "bun test test/plugin-v2.test.ts && bun test/smoke.ts", "test:haiku": "bun test/haiku-live.ts", "prepublishOnly": "npm run build" }, @@ -55,7 +60,7 @@ }, "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.3.224", - "@opencode-ai/plugin": "^1.18.15", + "@opencode-ai/plugin": "0.0.0-beta-17595", "zod": "^4.4.3" }, "devDependencies": { diff --git a/src/index.ts b/src/index.ts index 9e9936e..f003f94 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ * Register in opencode.json: * { "plugin": ["@openchamber/opencode-claude"] } */ -import type { Hooks, Plugin, PluginInput } from "@opencode-ai/plugin"; +import type { Hooks, Plugin, PluginInput } from "@opencode-ai/plugin/v1"; import { DEFAULT_MODEL_ID, DIRECTORY_HEADER, diff --git a/src/server.ts b/src/server.ts new file mode 100644 index 0000000..a7477a6 --- /dev/null +++ b/src/server.ts @@ -0,0 +1,155 @@ +import { Credential, Integration, Model, Plugin } from "@opencode-ai/plugin"; +import { + DIRECTORY_HEADER, + EFFORT_HEADER, + EFFORT_LEVELS, + PROVIDER_ID, + SESSION_HEADER, +} from "./constants.js"; +import { detectClaudeCode } from "./detect.js"; +import { buildAuthMethods } from "./index.js"; +import { + encodeClaudeModelSelection, + resolveClaudeModelSelection, +} from "./model-selection.js"; +import { getClaudeModels } from "./models.js"; +import { + getClaudeProxyBaseUrl, + startProxy, + stopProxy, +} from "./proxy.js"; + +const AUTH_METHOD_ID = "claude-cli"; +const PROVIDER_PACKAGE = "@opencode-ai/ai/providers/openai-compatible"; +const CONNECTION_MARKER = "managed-by-claude-code-cli"; +const CONNECTION_TTL_MS = 365 * 24 * 60 * 60 * 1_000; + +function connectionMarker() { + return Credential.OAuth.make({ + type: "oauth", + methodID: Integration.MethodID.make(AUTH_METHOD_ID), + access: CONNECTION_MARKER, + refresh: CONNECTION_MARKER, + expires: Date.now() + CONNECTION_TTL_MS, + }); +} + +async function requireLoginSuccess(result: { type: string }) { + if (result.type !== "success") { + throw new Error("Claude Code CLI sign-in failed"); + } + return connectionMarker(); +} + +async function authorizeWithClaudeCli() { + const detection = await detectClaudeCode(); + const authorization = await buildAuthMethods( + detection.status !== "missing-cli", + process.cwd(), + )[0]!.authorize(); + if (authorization.method === "code") { + return { + url: authorization.url, + instructions: authorization.instructions, + mode: "code" as const, + callback: async (code: string) => + requireLoginSuccess(await authorization.callback(code)), + }; + } + return { + url: authorization.url, + instructions: authorization.instructions, + mode: "auto" as const, + callback: authorization.callback().then(requireLoginSuccess), + }; +} + +export async function setupV2(ctx: Plugin.Context) { + await startProxy(); + + try { + await ctx.catalog.transform((catalog) => { + catalog.provider.update(PROVIDER_ID, (provider) => { + if (provider.name === PROVIDER_ID) provider.name = "Claude Code"; + provider.package = PROVIDER_PACKAGE; + provider.settings = { + ...provider.settings, + apiKey: CONNECTION_MARKER, + baseURL: getClaudeProxyBaseUrl(), + }; + }); + + for (const definition of getClaudeModels()) { + catalog.model.update(PROVIDER_ID, definition.id, (model) => { + model.modelID = Model.ID.make(definition.id); + model.name = definition.name; + model.capabilities = { + tools: true, + input: ["text", "image", "pdf"], + output: ["text"], + }; + model.variants = EFFORT_LEVELS.map((id) => ({ + id: Model.VariantID.make(id), + })); + model.limit = { + context: definition.contextWindow, + output: definition.maxTokens, + }; + }); + } + }); + + await ctx.integration.transform((integration) => { + integration.update(PROVIDER_ID, (draft) => { + draft.name = "Claude Code"; + }); + integration.method.update({ + integrationID: PROVIDER_ID, + method: { + id: AUTH_METHOD_ID, + type: "oauth", + label: "Sign in with Claude Code CLI", + }, + authorize: authorizeWithClaudeCli, + refresh: async (credential) => { + if (!(await detectClaudeCode()).loggedIn) { + throw new Error( + "Claude Code CLI is not signed in. Run `claude auth login --claudeai`.", + ); + } + return { ...credential, expires: Date.now() + CONNECTION_TTL_MS }; + }, + label: () => "Claude Code CLI", + }); + }); + + await ctx.session.hook("http.request", async (event) => { + if (event.model.providerID !== PROVIDER_ID) return; + + const session = await ctx.session.get({ sessionID: event.sessionID }); + const request = new Request( + `${getClaudeProxyBaseUrl()}/chat/completions`, + event.request, + ); + request.headers.set( + EFFORT_HEADER, + encodeClaudeModelSelection( + resolveClaudeModelSelection(event.model.id, event.model.variant), + ), + ); + request.headers.set(SESSION_HEADER, event.sessionID); + request.headers.set(DIRECTORY_HEADER, session.location.directory); + event.request = request; + }); + } catch (error) { + await stopProxy(); + throw error; + } + + return stopProxy; +} + +export default Plugin.define({ + id: "opencode.provider.claude-code", + setup: setupV2, +}); diff --git a/test/plugin-v2.test.ts b/test/plugin-v2.test.ts new file mode 100644 index 0000000..91c92df --- /dev/null +++ b/test/plugin-v2.test.ts @@ -0,0 +1,128 @@ +import { afterEach, expect, test } from "bun:test"; +import type { Plugin } from "@opencode-ai/plugin"; +import { DIRECTORY_HEADER, EFFORT_HEADER, SESSION_HEADER } from "../src/constants.ts"; +import { decodeClaudeModelSelection } from "../src/model-selection.ts"; +import { getClaudeModels } from "../src/models.ts"; +import { getProxyPort, stopProxy } from "../src/proxy.ts"; +import { setupV2 } from "../src/server.ts"; + +afterEach(stopProxy); + +test("V2 registers Claude catalog, CLI login, and request routing", async () => { + const provider: any = { + id: "claude-code", + name: "claude-code", + activation: "auto", + package: "", + }; + const models = new Map(); + let integration: any; + let method: any; + let requestHook: ((event: any) => Promise | void) | undefined; + + const ctx = { + catalog: { + async transform(callback: (draft: any) => void) { + callback({ + provider: { + update(id: string, update: (draft: any) => void) { + expect(id).toBe("claude-code"); + update(provider); + }, + }, + model: { + update(_providerID: string, id: string, update: (draft: any) => void) { + const model = { + id, + modelID: id, + providerID: "claude-code", + name: id, + capabilities: { tools: true, input: [], output: [] }, + variants: [], + time: { released: 0 }, + cost: [], + status: "active", + enabled: true, + limit: { context: 0, output: 0 }, + }; + update(model); + models.set(id, model); + }, + }, + }); + return { async dispose() {} }; + }, + }, + integration: { + async transform(callback: (draft: any) => void) { + callback({ + update(id: string, update: (draft: any) => void) { + integration = { id, name: id }; + update(integration); + }, + method: { update(input: any) { method = input; } }, + }); + return { async dispose() {} }; + }, + }, + session: { + async get() { + return { location: { directory: "C:\\work\\project" } }; + }, + async hook(name: string, callback: (event: any) => Promise | void) { + expect(name).toBe("http.request"); + requestHook = callback; + return { async dispose() {} }; + }, + }, + } as unknown as Plugin.Context; + + const cleanup = await setupV2(ctx); + + expect(getProxyPort()).toBeNumber(); + expect(provider).toMatchObject({ + name: "Claude Code", + package: "@opencode-ai/ai/providers/openai-compatible", + settings: { apiKey: "managed-by-claude-code-cli" }, + }); + expect(models.size).toBe(getClaudeModels().length); + expect(models.get("sonnet")).toMatchObject({ + capabilities: { tools: true, input: ["text", "image", "pdf"] }, + variants: [ + { id: "low" }, + { id: "medium" }, + { id: "high" }, + { id: "xhigh" }, + { id: "max" }, + ], + }); + expect(integration).toEqual({ id: "claude-code", name: "Claude Code" }); + expect(method).toMatchObject({ + integrationID: "claude-code", + method: { id: "claude-cli", type: "oauth" }, + }); + expect(method.authorize).toBeFunction(); + expect(method.refresh).toBeFunction(); + + const event = { + sessionID: "session-123", + agent: "build", + model: { providerID: "claude-code", id: "sonnet", variant: "high" }, + request: new Request("https://unused.example/v1/chat/completions", { + method: "POST", + body: JSON.stringify({ model: "sonnet", messages: [] }), + headers: { "content-type": "application/json" }, + }), + }; + await requestHook!(event); + + expect(event.request.url).toMatch(/^http:\/\/127\.0\.0\.1:\d+\/v1\/chat\/completions$/); + expect(event.request.headers.get(SESSION_HEADER)).toBe("session-123"); + expect(event.request.headers.get(DIRECTORY_HEADER)).toBe("C:\\work\\project"); + expect( + decodeClaudeModelSelection(event.request.headers.get(EFFORT_HEADER)), + ).toEqual({ modelId: "sonnet", effort: "high" }); + + await cleanup?.(); + expect(getProxyPort()).toBeNull(); +}); From 70e6bb28b76c2d934d6fef1d5c4faf834f685d59 Mon Sep 17 00:00:00 2001 From: pascalandr Date: Sun, 23 Aug 2026 22:20:14 +0200 Subject: [PATCH 4/5] fix: track the current OpenCode V2 plugin beta Depend on the beta dist-tag instead of a numbered prerelease and regenerate the Bun lockfile. Keep the OpenCode V1 type contract through a stable-major npm alias because the current beta no longer exports its V1 compatibility path. Expose the V1 handler from the server entrypoint for loaders that prefer package server exports, while retaining the native V2 id/setup plugin and its catalog, integration, request-hook, and proxy behavior. Document the explicit V2 server-file configuration required while the package root remains V1-compatible. Validated with build, no-emit typecheck, focused V2 tests, packed root/server imports, an isolated current opencode2 loader smoke covering plugin/catalog/integration/provider/proxy state, and a current V1 model-catalog smoke. The full suite still reaches the existing Windows extensionless fixture failure in test/smoke.ts. --- README.md | 14 +++++++++----- bun.lock | 35 ++++++++++++++++++++++++++--------- package.json | 3 ++- src/index.ts | 2 +- src/server.ts | 14 +++++++++----- test/plugin-v2.test.ts | 8 +++++++- 6 files changed, 54 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 5bf2c57..b600949 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,14 @@ Subscription limit state is tracked with its reset time. `GET /v1/rate-limit` an npm install -g @openchamber/opencode-claude ``` -Or with OpenCode V2: +For OpenCode V2, install it beside the global configuration so the explicit +server entrypoint can resolve its dependencies while the package root remains +compatible with OpenCode V1: ```bash -opencode2 plugin add @openchamber/opencode-claude +mkdir -p ~/.config/opencode +cd ~/.config/opencode +bun add @openchamber/opencode-claude ``` ### 2. Register it in OpenCode @@ -67,7 +71,7 @@ OpenCode V2 uses the package's native `./server` entrypoint. Add (or merge) this ```jsonc { "$schema": "https://opencode.ai/config.json", - "plugins": ["@openchamber/opencode-claude"], + "plugins": ["./node_modules/@openchamber/opencode-claude/dist/server.js"], "providers": { "claude-code": { "name": "Claude Code" } } @@ -157,7 +161,7 @@ The proxy records Agent SDK `rate_limit_event` telemetry and hard session-limit ## Requirements -- [OpenCode V1](https://opencode.ai) or OpenCode V2 beta `0.0.0-beta-17595` +- [OpenCode V1](https://opencode.ai) or the latest OpenCode V2 beta - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) — on `PATH` or installed via the provider's install action (npm is used, or the official install script); the plugin also checks `~/.local/bin` and the npm global bin for a CLI the server PATH cannot see - Claude plan supported by Claude Code - Bun (plugin runtime) · Node.js ≥ 18 @@ -185,7 +189,7 @@ Optional knobs: | Symptom | Fix | | --- | --- | | Unknown provider `claude-code` | Install `@openchamber/opencode-claude` and restart OpenCode | -| Claude Code missing from provider list | Confirm V2 `plugins` (or V1 `plugin`) includes `@openchamber/opencode-claude` and restart OpenCode | +| Claude Code missing from provider list | Confirm V2 `plugins` points to the installed `dist/server.js` (or V1 `plugin` includes `@openchamber/opencode-claude`) and restart OpenCode | | Authentication error | Run `claude auth login --claudeai`, verify `claude auth status --json`, then restart OpenCode | | 429 / rate-limit | Poll `GET /v1/rate-limit` or wait until `resetsAt`; the next turn resumes the same session | | Tools hang or invent output | Update to the latest plugin — park/resume MCP bridging is required | diff --git a/bun.lock b/bun.lock index c7907f8..555b9fb 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,8 @@ "name": "@openchamber/opencode-claude", "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.3.224", - "@opencode-ai/plugin": "0.0.0-beta-17595", + "@opencode-ai/plugin": "beta", + "@opencode-ai/plugin-v1": "npm:@opencode-ai/plugin@^1.18.0", "zod": "^4.4.3", }, "devDependencies": { @@ -65,17 +66,19 @@ "@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/ai": ["@opencode-ai/ai@0.0.0-beta-17595", "", { "dependencies": { "@opencode-ai/schema": "0.0.0-beta-17595", "@smithy/eventstream-codec": "4.2.14", "@smithy/util-utf8": "4.2.2", "aws4fetch": "1.0.20", "effect": "4.0.0-beta.107", "google-auth-library": "10.5.0" } }, "sha512-Dwxmw9tv5tw2t8p9Bmjo8XQqkdlNOc8SM8av8jRZYr2/c3NX38+rvOsLl5q85oAVqEKAHEqgXlMITwm60QhAEw=="], + "@opencode-ai/ai": ["@opencode-ai/ai@0.0.0-beta-17963", "", { "dependencies": { "@opencode-ai/schema": "0.0.0-beta-17963", "@smithy/eventstream-codec": "4.2.14", "@smithy/util-utf8": "4.2.2", "aws4fetch": "1.0.20", "effect": "4.0.0-rc.110", "google-auth-library": "10.5.0" } }, "sha512-LF7b7efdIYyDpJ93E5du7t6dDnlEN+JissHVUcXnJofLGBcZXvb8O575zz/G3J9hkbXlromdyaokMA5Rk2qDWQ=="], - "@opencode-ai/client": ["@opencode-ai/client@0.0.0-beta-17595", "", { "dependencies": { "@opencode-ai/protocol": "0.0.0-beta-17595", "@opencode-ai/schema": "0.0.0-beta-17595" }, "peerDependencies": { "effect": "4.0.0-beta.107", "solid-js": ">=1.9.0" }, "optionalPeers": ["effect", "solid-js"] }, "sha512-uDM6jztQiyXulYQL9G7kx283cv+0WhgQ98AzfClKQnV5mOB5wVBTGIjD1FGRwyxhUNGJBrfaP+NqOwWFjZhoeg=="], + "@opencode-ai/client": ["@opencode-ai/client@0.0.0-beta-17963", "", { "dependencies": { "@opencode-ai/protocol": "0.0.0-beta-17963", "@opencode-ai/schema": "0.0.0-beta-17963" }, "peerDependencies": { "effect": "4.0.0-rc.110", "solid-js": ">=1.9.0" }, "optionalPeers": ["effect", "solid-js"] }, "sha512-Rq+XXxmIOZ5LbiUj89byxN2FWxmmoZqq1BHGdS6734QN2/K1GD/mcWTfIKJlMToEZ03EGCvxJKjvGrixYCEFUA=="], - "@opencode-ai/plugin": ["@opencode-ai/plugin@0.0.0-beta-17595", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode-ai/ai": "0.0.0-beta-17595", "@opencode-ai/client": "0.0.0-beta-17595", "@opencode-ai/protocol": "0.0.0-beta-17595", "@opencode-ai/schema": "0.0.0-beta-17595", "@opencode-ai/sdk": "1.18.5", "@standard-schema/spec": "1.1.0", "effect": "4.0.0-beta.107", "zod": "4.1.8" }, "peerDependencies": { "@opencode-ai/theme": "0.0.0-beta-17595", "@opentui/core": ">=0.5.3", "@opentui/keymap": ">=0.5.3", "@opentui/solid": ">=0.5.3", "solid-js": ">=1.9.0" }, "optionalPeers": ["@opencode-ai/theme", "@opentui/core", "@opentui/keymap", "@opentui/solid", "solid-js"] }, "sha512-AeK5lPPpy/3IO7zgmLvn9uaQD4OzN8EYQlxFk8P5WxOb1THLAzNs3c8eQJ8ZY2k6SFgdZJ/Vr+0Czo06yEI0RA=="], + "@opencode-ai/plugin": ["@opencode-ai/plugin@0.0.0-beta-17963", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode-ai/ai": "0.0.0-beta-17963", "@opencode-ai/client": "0.0.0-beta-17963", "@opencode-ai/protocol": "0.0.0-beta-17963", "@opencode-ai/schema": "0.0.0-beta-17963", "@standard-schema/spec": "1.1.0", "effect": "4.0.0-rc.110", "zod": "4.1.8" }, "peerDependencies": { "@opencode-ai/theme": "0.0.0-beta-17963", "@opentui/core": ">=0.5.6", "@opentui/solid": ">=0.5.6", "solid-js": ">=1.9.0" }, "optionalPeers": ["@opencode-ai/theme", "@opentui/core", "@opentui/solid", "solid-js"] }, "sha512-hXt5Sebz5Ug+1QOR2JuFhQufZH9ZCCW0Rjpwc3IeALNLy9hfV2CytajZJmwnvXjrBQaY4AoOWOHsnMgnJGRvcw=="], - "@opencode-ai/protocol": ["@opencode-ai/protocol@0.0.0-beta-17595", "", { "dependencies": { "@opencode-ai/schema": "0.0.0-beta-17595", "effect": "4.0.0-beta.107" } }, "sha512-du77bQXIvOvqzyqS/I5gJMY3FZhXH2Oi3gs3ywAOnHCGRkwmVE9ofvFwR4G/Rzx/oVUOuGkyN28si29AluXGWw=="], + "@opencode-ai/plugin-v1": ["@opencode-ai/plugin@1.18.21", "", { "dependencies": { "@ai-sdk/provider": "3.0.8", "@opencode-ai/sdk": "1.18.21", "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-wQXMbSvg3pG75F8fYAiJxYuyr6Cl9Hd74lSCY2yznZnejpwa+ksd2kMphmgSo+/UgLhb2AId9KAI6dsRhprzTg=="], - "@opencode-ai/schema": ["@opencode-ai/schema@0.0.0-beta-17595", "", { "dependencies": { "@standard-schema/spec": "1.1.0", "effect": "4.0.0-beta.107" } }, "sha512-448/fW6HIHd2JT+TSgm4izcAWl51f17GR6WcfGbS9SyWmXFNnX1Fi03xNRgf7dnul9yyceXEsMbreUvteKxAYg=="], + "@opencode-ai/protocol": ["@opencode-ai/protocol@0.0.0-beta-17963", "", { "dependencies": { "@opencode-ai/schema": "0.0.0-beta-17963", "effect": "4.0.0-rc.110" } }, "sha512-KuOm/aYa2fgdp+mlNscxWXgTVIgtpPAJI1Wh4bdmutKs1EvWF4eJYZEY/m+Vcdbw2vsvz8JRp/AjWj2TxY1J8Q=="], - "@opencode-ai/sdk": ["@opencode-ai/sdk@1.18.5", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-7KgMvP5/1oxbhHj6kYBtPSTEdFKYpUeEYOzBTKdzSaRpapUpFFdn6Hkus3rr0rljO0kukWZIgRd3DrVBwTULGA=="], + "@opencode-ai/schema": ["@opencode-ai/schema@0.0.0-beta-17963", "", { "dependencies": { "@standard-schema/spec": "1.1.0", "effect": "4.0.0-rc.110" } }, "sha512-qPAzn/4RwTN0QA2BcURVpXRK15uRB0NTvg9E80FvAVjE2Bf6BCpc4XivyqgdjU2Ds3r+Dk9mri3gbwZTug1yIA=="], + + "@opencode-ai/sdk": ["@opencode-ai/sdk@1.18.21", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-k6iHQ5C8wOPglk+LgFyYnst168cGMQYumgpbVoeXJ+iC1AtvwD5zmjuF8CxMze/y9G1K2bOeO6p9yRvA7eHZLA=="], "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], @@ -167,7 +170,7 @@ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - "effect": ["effect@4.0.0-beta.107", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.4", "uuid": "^14.0.1" } }, "sha512-OoBAv8eF+yanc+C6xhgEUnWeXUSHA6ynnscYqpkAY9GSnzZWystsIjBowVqCkLpHGlnRtdIqYT3wHwpOY6JDnQ=="], + "effect": ["effect@4.0.0-rc.110", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "msgpackr": "^2.0.4" } }, "sha512-ega6FTJ8CS2of7tHZiADvgyJyV999Q6tZ9juE56V81O0jw6flRwydaPNtyfvP2a5LL9PZrse8A1jnNUD5sWVHg=="], "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], @@ -205,6 +208,8 @@ "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], + "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="], + "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=="], @@ -247,6 +252,8 @@ "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + "ini": ["ini@7.0.0", "", {}, "sha512-ifK0CgjALofS5bkrcTy4RaQ9Vx2Knf/eLeIO+NaswQEpH1UblrtTSCIvN71qQDMq0PeQ/SSPojvEJp9vvvfr+w=="], + "ip-address": ["ip-address@10.4.0", "", {}, "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ=="], "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], @@ -299,6 +306,8 @@ "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.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], @@ -381,6 +390,8 @@ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + "toml": ["toml@4.3.0", "", {}, "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A=="], + "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -393,7 +404,7 @@ "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], - "uuid": ["uuid@14.0.1", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew=="], + "uuid": ["uuid@14.0.2", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-xZe/16rV4aa+HGSOCiY2YeLT1OybRLrrkL/Rqaq7p7GMVXjFh+6wN4oMYgjFmnSnhY8t6Xpdl2l9qmnHYuMHwQ=="], "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], @@ -407,6 +418,8 @@ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], + "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], "zod-to-json-schema": ["zod-to-json-schema@3.25.2", "", { "peerDependencies": { "zod": "^3.25.28 || ^4" } }, "sha512-O/PgfnpT1xKSDeQYSCfRI5Gy3hPf91mKVDuYLUHZJMiDFptvP41MSnWofm8dnCm0256ZNfZIM7DSzuSMAFnjHA=="], @@ -415,6 +428,10 @@ "@opencode-ai/plugin/zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="], + "@opencode-ai/plugin-v1/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=="], + + "@opencode-ai/plugin-v1/zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="], + "body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], "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=="], diff --git a/package.json b/package.json index 2df5ab1..9f3b6e6 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,8 @@ }, "dependencies": { "@anthropic-ai/claude-agent-sdk": "^0.3.224", - "@opencode-ai/plugin": "0.0.0-beta-17595", + "@opencode-ai/plugin": "beta", + "@opencode-ai/plugin-v1": "npm:@opencode-ai/plugin@^1.18.0", "zod": "^4.4.3" }, "devDependencies": { diff --git a/src/index.ts b/src/index.ts index f003f94..bf2d2e9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ * Register in opencode.json: * { "plugin": ["@openchamber/opencode-claude"] } */ -import type { Hooks, Plugin, PluginInput } from "@opencode-ai/plugin/v1"; +import type { Hooks, Plugin, PluginInput } from "@opencode-ai/plugin-v1"; import { DEFAULT_MODEL_ID, DIRECTORY_HEADER, diff --git a/src/server.ts b/src/server.ts index a7477a6..10ffb92 100644 --- a/src/server.ts +++ b/src/server.ts @@ -7,7 +7,7 @@ import { SESSION_HEADER, } from "./constants.js"; import { detectClaudeCode } from "./detect.js"; -import { buildAuthMethods } from "./index.js"; +import { buildAuthMethods, ClaudeCodePlugin } from "./index.js"; import { encodeClaudeModelSelection, resolveClaudeModelSelection, @@ -149,7 +149,11 @@ export async function setupV2(ctx: Plugin.Context) { return stopProxy; } -export default Plugin.define({ - id: "opencode.provider.claude-code", - setup: setupV2, -}); +// V1 package loaders also prefer ./server, so expose their handler here. +export default Object.assign( + Plugin.define({ + id: "opencode.provider.claude-code", + setup: setupV2, + }), + { server: ClaudeCodePlugin }, +); diff --git a/test/plugin-v2.test.ts b/test/plugin-v2.test.ts index 91c92df..5144dd9 100644 --- a/test/plugin-v2.test.ts +++ b/test/plugin-v2.test.ts @@ -4,11 +4,17 @@ import { DIRECTORY_HEADER, EFFORT_HEADER, SESSION_HEADER } from "../src/constant import { decodeClaudeModelSelection } from "../src/model-selection.ts"; import { getClaudeModels } from "../src/models.ts"; import { getProxyPort, stopProxy } from "../src/proxy.ts"; -import { setupV2 } from "../src/server.ts"; +import serverPlugin, { setupV2 } from "../src/server.ts"; afterEach(stopProxy); test("V2 registers Claude catalog, CLI login, and request routing", async () => { + expect(serverPlugin).toMatchObject({ + id: "opencode.provider.claude-code", + setup: setupV2, + server: expect.any(Function), + }); + const provider: any = { id: "claude-code", name: "claude-code", From 21093544832ba2ec7e0928d850e9756dd77e166b Mon Sep 17 00:00:00 2001 From: pascalandr Date: Sun, 23 Aug 2026 22:24:21 +0200 Subject: [PATCH 5/5] fix: load Claude through native V2 entrypoint Keep the V2 server export limited to the Plugin.define contract so OpenCode does not classify it as a legacy server plugin. Register the provider with its authentication integration and document normal package installation instead of requiring a dist/server.js path. The focused V2 test now prevents the legacy server property from returning. --- README.md | 14 ++++---------- src/server.ts | 15 ++++++--------- test/plugin-v2.test.ts | 3 ++- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index b600949..83f0af3 100644 --- a/README.md +++ b/README.md @@ -54,24 +54,18 @@ Subscription limit state is tracked with its reset time. `GET /v1/rate-limit` an npm install -g @openchamber/opencode-claude ``` -For OpenCode V2, install it beside the global configuration so the explicit -server entrypoint can resolve its dependencies while the package root remains -compatible with OpenCode V1: - ```bash -mkdir -p ~/.config/opencode -cd ~/.config/opencode -bun add @openchamber/opencode-claude +opencode2 plugin add @openchamber/opencode-claude ``` ### 2. Register it in OpenCode -OpenCode V2 uses the package's native `./server` entrypoint. Add (or merge) this into `~/.config/opencode/opencode.json`: +OpenCode V2 uses the package's native `./server` entrypoint. The command above adds it to `~/.config/opencode/opencode.json`; the resulting configuration is: ```jsonc { "$schema": "https://opencode.ai/config.json", - "plugins": ["./node_modules/@openchamber/opencode-claude/dist/server.js"], + "plugins": ["@openchamber/opencode-claude"], "providers": { "claude-code": { "name": "Claude Code" } } @@ -189,7 +183,7 @@ Optional knobs: | Symptom | Fix | | --- | --- | | Unknown provider `claude-code` | Install `@openchamber/opencode-claude` and restart OpenCode | -| Claude Code missing from provider list | Confirm V2 `plugins` points to the installed `dist/server.js` (or V1 `plugin` includes `@openchamber/opencode-claude`) and restart OpenCode | +| Claude Code missing from provider list | Confirm V2 `plugins` (or V1 `plugin`) includes `@openchamber/opencode-claude` and restart OpenCode | | Authentication error | Run `claude auth login --claudeai`, verify `claude auth status --json`, then restart OpenCode | | 429 / rate-limit | Poll `GET /v1/rate-limit` or wait until `resetsAt`; the next turn resumes the same session | | Tools hang or invent output | Update to the latest plugin — park/resume MCP bridging is required | diff --git a/src/server.ts b/src/server.ts index 10ffb92..7625bbd 100644 --- a/src/server.ts +++ b/src/server.ts @@ -7,7 +7,7 @@ import { SESSION_HEADER, } from "./constants.js"; import { detectClaudeCode } from "./detect.js"; -import { buildAuthMethods, ClaudeCodePlugin } from "./index.js"; +import { buildAuthMethods } from "./index.js"; import { encodeClaudeModelSelection, resolveClaudeModelSelection, @@ -71,6 +71,7 @@ export async function setupV2(ctx: Plugin.Context) { await ctx.catalog.transform((catalog) => { catalog.provider.update(PROVIDER_ID, (provider) => { if (provider.name === PROVIDER_ID) provider.name = "Claude Code"; + provider.integrationID = Integration.ID.make(PROVIDER_ID); provider.package = PROVIDER_PACKAGE; provider.settings = { ...provider.settings, @@ -149,11 +150,7 @@ export async function setupV2(ctx: Plugin.Context) { return stopProxy; } -// V1 package loaders also prefer ./server, so expose their handler here. -export default Object.assign( - Plugin.define({ - id: "opencode.provider.claude-code", - setup: setupV2, - }), - { server: ClaudeCodePlugin }, -); +export default Plugin.define({ + id: "opencode.provider.claude-code", + setup: setupV2, +}); diff --git a/test/plugin-v2.test.ts b/test/plugin-v2.test.ts index 5144dd9..377a717 100644 --- a/test/plugin-v2.test.ts +++ b/test/plugin-v2.test.ts @@ -12,8 +12,8 @@ test("V2 registers Claude catalog, CLI login, and request routing", async () => expect(serverPlugin).toMatchObject({ id: "opencode.provider.claude-code", setup: setupV2, - server: expect.any(Function), }); + expect("server" in serverPlugin).toBeFalse(); const provider: any = { id: "claude-code", @@ -88,6 +88,7 @@ test("V2 registers Claude catalog, CLI login, and request routing", async () => expect(getProxyPort()).toBeNumber(); expect(provider).toMatchObject({ name: "Claude Code", + integrationID: "claude-code", package: "@opencode-ai/ai/providers/openai-compatible", settings: { apiKey: "managed-by-claude-code-cli" }, });