From 5e5d673a2fd1d9a97f624e2887d5692e330f9977 Mon Sep 17 00:00:00 2001 From: pascalandr Date: Sun, 23 Aug 2026 21:13:58 +0200 Subject: [PATCH 1/4] feat: add OpenCode V2 compatibility --- README.md | 11 +++++++++++ index.ts | 10 ++++++++++ package.json | 9 +++++++++ src/plugin/types.ts | 8 ++++++++ tsup.config.ts | 2 +- 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dbe4ebb..bde4878 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,17 @@ Add the plugin to your Opencode configuration file > a Gemini Code Assist subscription tier. You can still set `projectId` to > force a specific project. +### OpenCode V2 Compatibility + +This plugin supports both OpenCode V1 and V2: + +- **V1**: `@opencode-ai/plugin` 1.x with `createOpencodeClient` (e.g. `import { createOpencodeClient } from "@opencode-ai/sdk"`). +- **V2**: `@opencode-ai/client` Promise API with a global service — no `createOpencodeClient`. The client is discovered via the global service registration (XDG state dir) and uses `~/.config/opencode/opencode.json` for config. + +The same build works on both. `@opencode-ai/client >=1.17.0` is an optional peer dependency so V1 installs are unaffected. + +**Quota on V2** now works via embedded Google OAuth client secrets (see [`src/constants.ts`](src/constants.ts): `681255809395-...` / `GOCSPX-...`) — no extra env vars. The bucket merge (`retrieveUserQuota` + `fetchAvailableModels`, daily vs 5h window) matches `openchamber`'s `vscode` quotaProviders as shipped in CodeNomad [`e2b784f2`](https://github.com/sst/opencode). See CodeNomad V2 migration notes: https://opencode.ai and CodeNomad docs (`packages/opencode-plugin`). + ## Usage 1. **Login**: Run the authentication command in your terminal: diff --git a/index.ts b/index.ts index 9790a42..9bd7f7d 100644 --- a/index.ts +++ b/index.ts @@ -12,3 +12,13 @@ export type { GeminiAuthorization, GeminiTokenExchangeResult, } from "./src/gemini/oauth"; + +// OpenCode V2 compatibility: V2 uses `@opencode-ai/client` (Promise API, +// global service, config at `~/.config/opencode/opencode.json`) and no +// `createOpencodeClient`. The named `GeminiCLIOAuthPlugin` export above +// remains the V1 loader (`@opencode-ai/plugin` v1 / `@opencode-ai/plugin/v1` +// compat). For native V2 `Plugin.define` consumers the same plugin works +// because `peerDependencies` now optionally allows `@opencode-ai/client` +// and runtime only touches `client.auth.set` / `client.config.get` / +// `client.tui.showToast` (other V2 surfaces are ignored via index signature). +// Quota via embedded Google client secrets matches CodeNomad e2b784f2. diff --git a/package.json b/package.json index 0997036..1397b99 100644 --- a/package.json +++ b/package.json @@ -37,5 +37,14 @@ "dependencies": { "@opencode-ai/plugin": "^1.2.20", "@openauthjs/openauth": "^0.4.3" + }, + "peerDependencies": { + "@opencode-ai/client": ">=1.17.0", + "@opencode-ai/plugin": "^1.2.20" + }, + "peerDependenciesMeta": { + "@opencode-ai/client": { + "optional": true + } } } diff --git a/src/plugin/types.ts b/src/plugin/types.ts index a0ac506..dd1c214 100644 --- a/src/plugin/types.ts +++ b/src/plugin/types.ts @@ -1,4 +1,8 @@ import type { GeminiTokenExchangeResult } from "../gemini/oauth"; +// V2 compat: Config lives in @opencode-ai/sdk (V1) and also re-exported via +// @opencode-ai/client (V2 Promise API). Keep the V1 import for types, but +// allow absence at runtime — V2 uses a global service with config at +// ~/.config/opencode/opencode.json and no `createOpencodeClient`. import type { Config } from "@opencode-ai/sdk"; import type { ToolDefinition } from "@opencode-ai/plugin"; @@ -71,6 +75,10 @@ export interface PluginClient { }; }): Promise; }; + // V2 compat: allow extra fields when the client is the V2 Promise API + // (`@opencode-ai/client`). The plugin only uses `auth.set` / `config.get` + // / `tui.showToast` above, so additional V2 surfaces are ignored safely. + [key: string]: unknown; } export interface PluginContext { diff --git a/tsup.config.ts b/tsup.config.ts index f4974d3..234dd34 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -8,5 +8,5 @@ export default defineConfig({ clean: true, splitting: false, target: "node20", - noExternal: ["@opencode-ai/plugin", "@openauthjs/openauth"], + noExternal: ["@opencode-ai/plugin", "@opencode-ai/client", "@opencode-ai/sdk", "@openauthjs/openauth"], }); From 6e35ba1ca0264f0fd6f2c5d608e0e99f0bbf78fb Mon Sep 17 00:00:00 2001 From: pascalandr Date: Sun, 23 Aug 2026 21:35:49 +0200 Subject: [PATCH 2/4] fix: implement native OpenCode V2 plugin entrypoint Replace the metadata-only V2 compatibility claim with a real server entrypoint that registers Gemini CLI OAuth through the V2 integration API and rewrites native Google requests and responses through session HTTP hooks. Keep the legacy root entrypoint unchanged, and expose both setup and server from ./server so current V1 and V2 loaders select the contract they understand. Remove the invalid @opencode-ai/client >=1.17.0 peer range because V2 client releases are 0.0.0-beta prereleases and the plugin context is host-supplied. Document V2 configuration and the V1-only quota, retry, and notification features instead of claiming unsupported parity. Add a focused V2 registration and transport test. Validated with the full Bun test suite, TypeScript checking, tsup declaration builds, a packed-package import check, and structural assignment against @opencode-ai/plugin@0.0.0-beta-17595. --- README.md | 54 ++++++--- index.ts | 10 -- package.json | 14 +-- server.ts | 1 + src/plugin-v2.test.ts | 59 ++++++++++ src/plugin-v2.ts | 206 ++++++++++++++++++++++++++++++++++ src/plugin/oauth-authorize.ts | 7 +- src/plugin/types.ts | 8 -- tsup.config.ts | 4 +- 9 files changed, 315 insertions(+), 48 deletions(-) create mode 100644 server.ts create mode 100644 src/plugin-v2.test.ts create mode 100644 src/plugin-v2.ts diff --git a/README.md b/README.md index bde4878..5d9158b 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,10 @@ directly within Opencode. ## Installation -Add the plugin to your Opencode configuration file -(`~/.config/opencode/opencode.json` or similar): +Add the plugin to your OpenCode configuration file +(`~/.config/opencode/opencode.json` or similar). + +OpenCode V1: ```json { @@ -40,6 +42,15 @@ Add the plugin to your Opencode configuration file } ``` +OpenCode V2: + +```json +{ + "$schema": "https://opencode.ai/config.json", + "plugins": ["opencode-gemini-auth@latest"] +} +``` + > [!IMPORTANT] > Explicitly configure a Google Cloud `projectId` if you're using an > organization-backed Gemini Code Assist subscription @@ -50,22 +61,19 @@ Add the plugin to your Opencode configuration file ### OpenCode V2 Compatibility -This plugin supports both OpenCode V1 and V2: - -- **V1**: `@opencode-ai/plugin` 1.x with `createOpencodeClient` (e.g. `import { createOpencodeClient } from "@opencode-ai/sdk"`). -- **V2**: `@opencode-ai/client` Promise API with a global service — no `createOpencodeClient`. The client is discovered via the global service registration (XDG state dir) and uses `~/.config/opencode/opencode.json` for config. +OpenCode V2 loads the package's native `./server` entrypoint. It registers the +Gemini CLI OAuth method through `integration.transform` and rewrites Google +provider requests and responses through the V2 session HTTP hooks. No +`@opencode-ai/client` peer dependency is required because OpenCode supplies the +plugin context. -The same build works on both. `@opencode-ai/client >=1.17.0` is an optional peer dependency so V1 installs are unaffected. - -**Quota on V2** now works via embedded Google OAuth client secrets (see [`src/constants.ts`](src/constants.ts): `681255809395-...` / `GOCSPX-...`) — no extra env vars. The bucket merge (`retrieveUserQuota` + `fetchAvailableModels`, daily vs 5h window) matches `openchamber`'s `vscode` quotaProviders as shipped in CodeNomad [`e2b784f2`](https://github.com/sst/opencode). See CodeNomad V2 migration notes: https://opencode.ai and CodeNomad docs (`packages/opencode-plugin`). +The V1 entrypoint remains unchanged. The V2 entrypoint currently covers login +and model requests; the `/gquota` command, quota tool, retry transport, and TUI +capacity notifications remain V1-only. ## Usage -1. **Login**: Run the authentication command in your terminal: - - ```bash - opencode auth login - ``` +1. **Login**: Run `opencode auth login` on V1 or `opencode2 auth login` on V2. 2. **Select Provider**: Choose **Google** from the list. 3. **Authenticate**: Select **OAuth with Google (Gemini CLI)**. @@ -76,7 +84,7 @@ The same build works on both. `@opencode-ai/client >=1.17.0` is an optional peer Once authenticated, Opencode will use your Google account for Gemini requests. -To check your current Gemini Code Assist quota buckets at any time, run: +On V1, check your current Gemini Code Assist quota buckets with: ```bash /gquota @@ -90,7 +98,7 @@ By default, the plugin attempts to provision or find a suitable Google Cloud project. To force a specific project, set the `projectId` in your configuration or via environment variables: -**File:** `~/.config/opencode/opencode.json` +OpenCode V1: ```json { @@ -104,6 +112,20 @@ or via environment variables: } ``` +OpenCode V2: + +```json +{ + "providers": { + "google": { + "settings": { + "projectId": "your-specific-project-id" + } + } + } +} +``` + You can also set `OPENCODE_GEMINI_PROJECT_ID`, `GOOGLE_CLOUD_PROJECT`, or `GOOGLE_CLOUD_PROJECT_ID` to supply the project ID via environment variables. diff --git a/index.ts b/index.ts index 9bd7f7d..9790a42 100644 --- a/index.ts +++ b/index.ts @@ -12,13 +12,3 @@ export type { GeminiAuthorization, GeminiTokenExchangeResult, } from "./src/gemini/oauth"; - -// OpenCode V2 compatibility: V2 uses `@opencode-ai/client` (Promise API, -// global service, config at `~/.config/opencode/opencode.json`) and no -// `createOpencodeClient`. The named `GeminiCLIOAuthPlugin` export above -// remains the V1 loader (`@opencode-ai/plugin` v1 / `@opencode-ai/plugin/v1` -// compat). For native V2 `Plugin.define` consumers the same plugin works -// because `peerDependencies` now optionally allows `@opencode-ai/client` -// and runtime only touches `client.auth.set` / `client.config.get` / -// `client.tui.showToast` (other V2 surfaces are ignored via index signature). -// Quota via embedded Google client secrets matches CodeNomad e2b784f2. diff --git a/package.json b/package.json index 1397b99..f4acb77 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,11 @@ "types": "./dist/index.d.ts", "import": "./dist/index.js", "default": "./dist/index.js" + }, + "./server": { + "types": "./dist/server.d.ts", + "import": "./dist/server.js", + "default": "./dist/server.js" } }, "files": [ @@ -37,14 +42,5 @@ "dependencies": { "@opencode-ai/plugin": "^1.2.20", "@openauthjs/openauth": "^0.4.3" - }, - "peerDependencies": { - "@opencode-ai/client": ">=1.17.0", - "@opencode-ai/plugin": "^1.2.20" - }, - "peerDependenciesMeta": { - "@opencode-ai/client": { - "optional": true - } } } diff --git a/server.ts b/server.ts new file mode 100644 index 0000000..d222ce4 --- /dev/null +++ b/server.ts @@ -0,0 +1 @@ +export { default } from "./src/plugin-v2"; diff --git a/src/plugin-v2.test.ts b/src/plugin-v2.test.ts new file mode 100644 index 0000000..af670e1 --- /dev/null +++ b/src/plugin-v2.test.ts @@ -0,0 +1,59 @@ +import { expect, test } from "bun:test"; + +import { setupV2 } from "./plugin-v2"; + +test("V2 plugin registers OAuth and rewrites Gemini requests and responses", async () => { + let method: any; + const hooks: Record Promise> = {}; + const credential = { + type: "oauth", + methodID: "gemini-cli", + refresh: "refresh-token||managed-project", + access: "access-token", + expires: Date.now() + 60_000, + }; + + await setupV2({ + catalog: { + provider: { async get() { return { data: { settings: {} } }; } }, + }, + integration: { + async transform(callback) { + callback({ method: { update(input) { method = input; } } }); + }, + connection: { + async active() { return { type: "credential" }; }, + async resolve() { return credential; }, + }, + }, + session: { + async hook(name, callback) { hooks[name] = callback; }, + }, + }); + + expect(method.integrationID).toBe("google"); + expect(method.method.id).toBe("gemini-cli"); + + const event = { + model: { providerID: "google", id: "gemini-2.5-pro" }, + request: new Request( + "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse", + { method: "POST", body: JSON.stringify({ contents: [] }) }, + ), + }; + await hooks["http.request"]!(event); + + expect(event.request.url).toContain("cloudcode-pa.googleapis.com/v1internal:streamGenerateContent"); + expect(event.request.headers.get("authorization")).toBe("Bearer access-token"); + expect(await event.request.clone().json()).toMatchObject({ + project: "managed-project", + model: "gemini-2.5-pro", + }); + + const responseEvent = { + ...event, + response: Response.json({ response: { candidates: [] } }), + }; + await hooks["http.response"]!(responseEvent); + expect(await responseEvent.response.json()).toEqual({ candidates: [] }); +}); diff --git a/src/plugin-v2.ts b/src/plugin-v2.ts new file mode 100644 index 0000000..14bb6ff --- /dev/null +++ b/src/plugin-v2.ts @@ -0,0 +1,206 @@ +import { GEMINI_PROVIDER_ID } from "./constants"; +import type { GeminiTokenExchangeResult } from "./gemini/oauth"; +import { GeminiCLIOAuthPlugin } from "./plugin"; +import { createOAuthAuthorizeMethod } from "./plugin/oauth-authorize"; +import { resolveProjectContextFromAccessToken } from "./plugin/project"; +import { resolveConfiguredProjectId } from "./plugin/provider"; +import { + isGenerativeLanguageRequest, + prepareGeminiRequest, + transformGeminiResponse, +} from "./plugin/request"; +import { refreshAccessToken } from "./plugin/token"; +import type { OAuthAuthDetails, PluginClient } from "./plugin/types"; + +const GEMINI_OAUTH_METHOD_ID = "gemini-cli"; + +interface V2Credential extends OAuthAuthDetails { + methodID: string; + access: string; + expires: number; + metadata?: Record; +} + +interface V2Context { + catalog: { + provider: { + get(input: { providerID: string }): Promise<{ + data?: { settings?: Record }; + } | undefined>; + }; + }; + integration: { + transform(callback: (draft: { + method: { + update(input: { + integrationID: string; + method: { id: string; type: "oauth"; label: string }; + authorize: () => Promise<{ + url: string; + instructions: string; + mode: "auto" | "code"; + callback: Promise | ((code: string) => Promise); + }>; + refresh: (credential: V2Credential) => Promise; + label: (credential: V2Credential) => string | undefined; + }): void; + }; + }) => void): Promise; + connection: { + active(id: string): Promise; + resolve(connection: unknown): Promise; + }; + }; + session: { + hook( + name: "http.request" | "http.response", + callback: (event: V2RequestEvent | V2ResponseEvent) => Promise, + ): Promise; + }; +} + +interface V2RequestEvent { + model: { providerID: string; id: string }; + request: Request; +} + +interface V2ResponseEvent extends V2RequestEvent { + response: Response; +} + +const noPersistClient = { + auth: { set: async () => {} }, +} as PluginClient; + +export async function setupV2(ctx: V2Context): Promise { + const requests = new WeakMap(); + const getConfiguredProjectId = () => resolveV2ConfiguredProjectId(ctx); + const authorize = createOAuthAuthorizeMethod({ getConfiguredProjectId }); + + await ctx.integration.transform((draft) => { + draft.method.update({ + integrationID: GEMINI_PROVIDER_ID, + method: { + id: GEMINI_OAUTH_METHOD_ID, + type: "oauth", + label: "OAuth with Google (Gemini CLI)", + }, + authorize: async () => { + const authorization = await authorize(); + return authorization.method === "auto" + ? { + url: authorization.url, + instructions: authorization.instructions, + mode: "auto", + callback: authorization.callback().then(toV2Credential), + } + : { + url: authorization.url, + instructions: authorization.instructions, + mode: "code", + callback: (code: string) => authorization.callback(code).then(toV2Credential), + }; + }, + refresh: async (credential) => { + const refreshed = await refreshAccessToken(credential, noPersistClient); + if (!refreshed?.access || refreshed.expires === undefined) { + throw new Error("Gemini OAuth token refresh failed"); + } + return { ...credential, ...refreshed }; + }, + label: (credential) => + typeof credential.metadata?.email === "string" ? credential.metadata.email : undefined, + }); + }); + + await ctx.session.hook("http.request", async (rawEvent) => { + const event = rawEvent as V2RequestEvent; + if ( + event.model.providerID !== GEMINI_PROVIDER_ID || + !isGenerativeLanguageRequest(event.request) + ) { + return; + } + + const connection = await ctx.integration.connection.active(GEMINI_PROVIDER_ID); + const credential = connection + ? await ctx.integration.connection.resolve(connection) + : undefined; + if (!isV2Credential(credential) || credential.methodID !== GEMINI_OAUTH_METHOD_ID) { + return; + } + + const project = await resolveProjectContextFromAccessToken( + credential, + credential.access, + await getConfiguredProjectId(), + undefined, + event.model.id, + ); + const original = event.request; + const body = original.method === "GET" || original.method === "HEAD" + ? undefined + : await original.clone().text(); + const transformed = prepareGeminiRequest( + original, + { method: original.method, headers: original.headers, body, signal: original.signal }, + credential.access, + project.effectiveProjectId, + ); + const request = new Request(transformed.request, transformed.init); + requests.set(request, { + streaming: transformed.streaming, + requestedModel: transformed.requestedModel, + }); + event.request = request; + }); + + await ctx.session.hook("http.response", async (rawEvent) => { + const event = rawEvent as V2ResponseEvent; + const request = requests.get(event.request); + if (!request) return; + event.response = await transformGeminiResponse( + event.response, + request.streaming, + null, + request.requestedModel, + ); + }); +} + +async function resolveV2ConfiguredProjectId(ctx: V2Context): Promise { + const fromEnvironment = resolveConfiguredProjectId(); + if (fromEnvironment) return fromEnvironment; + try { + const provider = await ctx.catalog.provider.get({ providerID: GEMINI_PROVIDER_ID }); + return resolveConfiguredProjectId({ + provider: { options: provider?.data?.settings }, + }); + } catch { + return undefined; + } +} + +function toV2Credential(result: GeminiTokenExchangeResult): V2Credential { + if (result.type !== "success") throw new Error(result.error); + return { + type: "oauth", + methodID: GEMINI_OAUTH_METHOD_ID, + refresh: result.refresh, + access: result.access, + expires: result.expires, + metadata: result.email ? { email: result.email } : undefined, + }; +} + +function isV2Credential(value: unknown): value is V2Credential { + return !!value && typeof value === "object" && + (value as { type?: unknown }).type === "oauth" && + typeof (value as { methodID?: unknown }).methodID === "string"; +} + +export default { + id: "opencode.provider.google-gemini-cli", + setup: (ctx: unknown) => setupV2(ctx as V2Context), + server: GeminiCLIOAuthPlugin, +}; diff --git a/src/plugin/oauth-authorize.ts b/src/plugin/oauth-authorize.ts index c00733c..7b5996e 100644 --- a/src/plugin/oauth-authorize.ts +++ b/src/plugin/oauth-authorize.ts @@ -17,9 +17,10 @@ export function createOAuthAuthorizeMethod(options?: { }): () => Promise<{ url: string; instructions: string; - method: string; - callback: (() => Promise) | ((callbackUrl: string) => Promise); -}> { +} & ( + | { method: "auto"; callback: () => Promise } + | { method: "code"; callback: (callbackUrl: string) => Promise } +)> { return async () => { const maybeHydrateProjectId = async ( result: GeminiTokenExchangeResult, diff --git a/src/plugin/types.ts b/src/plugin/types.ts index dd1c214..a0ac506 100644 --- a/src/plugin/types.ts +++ b/src/plugin/types.ts @@ -1,8 +1,4 @@ import type { GeminiTokenExchangeResult } from "../gemini/oauth"; -// V2 compat: Config lives in @opencode-ai/sdk (V1) and also re-exported via -// @opencode-ai/client (V2 Promise API). Keep the V1 import for types, but -// allow absence at runtime — V2 uses a global service with config at -// ~/.config/opencode/opencode.json and no `createOpencodeClient`. import type { Config } from "@opencode-ai/sdk"; import type { ToolDefinition } from "@opencode-ai/plugin"; @@ -75,10 +71,6 @@ export interface PluginClient { }; }): Promise; }; - // V2 compat: allow extra fields when the client is the V2 Promise API - // (`@opencode-ai/client`). The plugin only uses `auth.set` / `config.get` - // / `tui.showToast` above, so additional V2 surfaces are ignored safely. - [key: string]: unknown; } export interface PluginContext { diff --git a/tsup.config.ts b/tsup.config.ts index 234dd34..fb39757 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,12 +1,12 @@ import { defineConfig } from "tsup"; export default defineConfig({ - entry: ["index.ts"], + entry: ["index.ts", "server.ts"], format: ["esm"], dts: true, sourcemap: true, clean: true, splitting: false, target: "node20", - noExternal: ["@opencode-ai/plugin", "@opencode-ai/client", "@opencode-ai/sdk", "@openauthjs/openauth"], + noExternal: ["@opencode-ai/plugin", "@openauthjs/openauth"], }); From 80d4acb1663d2c2dc1e7b16d649af1ee2bab1033 Mon Sep 17 00:00:00 2001 From: pascalandr Date: Sun, 23 Aug 2026 22:19:01 +0200 Subject: [PATCH 3/4] fix: align V2 entrypoint with current plugin API Replace the hand-written V2 contract with the current promise plugin types and Plugin.define entrypoint. Register Gemini OAuth through the current integration transform, scope transport hooks to Google, and read project settings through the current catalog client. Keep the V1 root entrypoint independent by replacing its legacy plugin helper and SDK type imports with equivalent local structures. Depend on the moving beta tag for V2 runtime compatibility and make the package self-import smoke portable across platforms. Validated with the full Bun test suite, TypeScript checking, declaration builds, npm packing, packed root and server imports, a V1 hook construction smoke, and an isolated load against the current OpenCode V2 CLI. --- README.md | 6 +- bun.lock | 206 +++++++++++++++++++++++++++++++++++- package.json | 4 +- src/plugin-v2.test.ts | 15 +-- src/plugin-v2.ts | 87 +++------------ src/plugin/provider.test.ts | 7 +- src/plugin/provider.ts | 8 +- src/plugin/quota.ts | 5 +- src/plugin/types.ts | 18 +++- tsup.config.ts | 2 +- 10 files changed, 255 insertions(+), 103 deletions(-) diff --git a/README.md b/README.md index 5d9158b..25f5aeb 100644 --- a/README.md +++ b/README.md @@ -63,9 +63,9 @@ OpenCode V2: OpenCode V2 loads the package's native `./server` entrypoint. It registers the Gemini CLI OAuth method through `integration.transform` and rewrites Google -provider requests and responses through the V2 session HTTP hooks. No -`@opencode-ai/client` peer dependency is required because OpenCode supplies the -plugin context. +provider requests and responses through provider-scoped V2 session HTTP hooks. +The entrypoint follows the current `Plugin.define` contract from +`@opencode-ai/plugin@beta`. The V1 entrypoint remains unchanged. The V2 entrypoint currently covers login and model requests; the `/gquota` command, quota tool, retry transport, and TUI diff --git a/bun.lock b/bun.lock index 802a657..6b7ac65 100644 --- a/bun.lock +++ b/bun.lock @@ -6,7 +6,7 @@ "name": "opencode-gemini-auth", "dependencies": { "@openauthjs/openauth": "^0.4.3", - "@opencode-ai/plugin": "^1.2.20", + "@opencode-ai/plugin": "beta", }, "devDependencies": { "@types/bun": "latest", @@ -16,6 +16,14 @@ }, }, "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/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=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.7", "", { "os": "aix", "cpu": "ppc64" }, "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg=="], "@esbuild/android-arm": ["@esbuild/android-arm@0.27.7", "", { "os": "android", "cpu": "arm" }, "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ=="], @@ -68,6 +76,8 @@ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.7", "", { "os": "win32", "cpu": "x64" }, "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg=="], + "@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=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], @@ -76,11 +86,29 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + "@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=="], + + "@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4", "", { "os": "linux", "cpu": "arm" }, "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw=="], + + "@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw=="], + + "@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ=="], + + "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="], + "@openauthjs/openauth": ["@openauthjs/openauth@0.4.3", "", { "dependencies": { "@standard-schema/spec": "1.0.0-beta.3", "aws4fetch": "1.0.20", "jose": "5.9.6" }, "peerDependencies": { "arctic": "^2.2.2", "hono": "^4.0.0" } }, "sha512-RlnjqvHzqcbFVymEwhlUEuac4utA5h4nhSK/i2szZuQmxTIqbGUxZ+nM+avM+VV4Ing+/ZaNLKILoXS3yrkOOw=="], - "@opencode-ai/plugin": ["@opencode-ai/plugin@1.2.20", "", { "dependencies": { "@opencode-ai/sdk": "1.2.20", "zod": "4.1.8" } }, "sha512-BE6TOXVxgF24g5QgtlogSY5B+/AmZJ3cYaVjHZhUVuAli9JEg4RblrbrK2rfgbyZBoZDpjBLGTYtIRTVmOccEA=="], + "@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-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-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/sdk": ["@opencode-ai/sdk@1.2.20", "", {}, "sha512-U5ROpG21D8jg9rkc1IgKAk1g5dn6X/rkOBfveupd0peSDO9n6VM9aikYccVLaMObxVqdjtG08IeQOFTPVS8ySQ=="], + "@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/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=="], "@oslojs/asn1": ["@oslojs/asn1@1.0.0", "", { "dependencies": { "@oslojs/binary": "1.0.0" } }, "sha512-zw/wn0sj0j0QKbIXfIlnEcTviaCzYOY3V5rAyjR6YtOByFtJiT574+8p9Wlach0lZH9fddD4yb9laEAIl4vXQA=="], @@ -92,6 +120,8 @@ "@oslojs/jwt": ["@oslojs/jwt@0.2.0", "", { "dependencies": { "@oslojs/encoding": "0.4.1" } }, "sha512-bLE7BtHrURedCn4Mco3ma9L4Y1GR2SMBuIvjWr7rmQ4/W/4Jy70TIAgZ+0nIlk0xHz1vNP8x8DCns45Sb2XRbg=="], + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.60.3", "", { "os": "android", "cpu": "arm" }, "sha512-x35CNW/ANXG3hE/EZpRU8MXX1JDN86hBb2wMGAtltkz7pc6cxgjpy1OMMfDosOQ+2hWqIkag/fGok1Yady9nGw=="], "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.60.3", "", { "os": "android", "cpu": "arm64" }, "sha512-xw3xtkDApIOGayehp2+Rz4zimfkaX65r4t47iy+ymQB2G4iJCBBfj0ogVg5jpvjpn8UWn/+q9tprxleYeNp3Hw=="], @@ -142,6 +172,20 @@ "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.60.3", "", { "os": "win32", "cpu": "x64" }, "sha512-hPt/bgL5cE+Qp+/TPHBqptcAgPzgj46mPcg/16zNUmbQk0j+mOEQV/+Lqu8QRtDV3Ek95Q6FeFITpuhl6OTsAA=="], + "@smithy/core": ["@smithy/core@3.33.3", "", { "dependencies": { "@smithy/types": "^4.17.2", "tslib": "^2.6.2" } }, "sha512-CsOeKq/9kA3y6VJHt+/+VTCtBaxJ4OTFpgrjIUhPpDIKxBci1k2bJaQASF2h/ELWrulGp+t97DZ0mevfAD8idg=="], + + "@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=="], + "@standard-schema/spec": ["@standard-schema/spec@1.0.0-beta.3", "", {}, "sha512-0ifF3BjA1E8SY9C+nUew8RefNOIq0cDlYALPty4rhUm8Rrl6tCM8hBT4bhGhx7I7iXD0uAgt50lgo8dD73ACMw=="], "@types/bun": ["@types/bun@1.3.9", "", { "dependencies": { "bun-types": "1.3.9" } }, "sha512-KQ571yULOdWJiMH+RIWIOZ7B2RXQGpL1YQrBtLIV3FqDcCu6FsbFUBwhdKUlCKUpS3PJDsHlJ1QKlpxoVR+xtw=="], @@ -152,12 +196,28 @@ "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], + "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=="], + "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], "arctic": ["arctic@2.3.4", "", { "dependencies": { "@oslojs/crypto": "1.0.1", "@oslojs/encoding": "1.1.0", "@oslojs/jwt": "0.2.0" } }, "sha512-+p30BOWsctZp+CVYCt7oAean/hWGW42sH5LAcRQX56ttEkFJWbzXBhmSpibbzwSJkRrotmsA+oAoJoVsU0f5xA=="], "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=="], + + "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.9", "", { "dependencies": { "@types/node": "*" } }, "sha512-+UBWWOakIP4Tswh0Bt0QD0alpTY8cb5hvgiYeWCMet9YukHbzuruIEeXC2D7nMJPB12kbh8C7XJykSexEqGKJg=="], "bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="], @@ -166,44 +226,122 @@ "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="], + "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=="], + "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="], + "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" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "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.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=="], + "esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="], + "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=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], + "fix-dts-default-cjs-exports": ["fix-dts-default-cjs-exports@1.0.1", "", { "dependencies": { "magic-string": "^0.30.17", "mlly": "^1.7.4", "rollup": "^4.34.8" } }, "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg=="], + "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=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "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@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=="], + + "gtoken": ["gtoken@8.0.0", "", { "dependencies": { "gaxios": "^7.0.0", "jws": "^4.0.0" } }, "sha512-+CqsMbHPiSTdtSO14O51eMNlrp9N79gmeqmXeouJOhfucAedHw9noVe/n5uJk3tbKE6a+6ZCQg3RPhVhHByAIw=="], + "hono": ["hono@4.10.4", "", {}, "sha512-YG/fo7zlU3KwrBL5vDpWKisLYiM+nVstBQqfr7gCPbSYURnNEP9BDxEMz8KfsDR9JX0lJWDRNc6nXX31v7ZEyg=="], + "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + + "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=="], + "jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="], "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="], + "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=="], + + "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=="], + "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], "load-tsconfig": ["load-tsconfig@0.2.5", "", {}, "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg=="], + "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "minimatch": ["minimatch@9.0.9", "", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + + "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], + "mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="], "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=="], + "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], + "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=="], + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "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=="], + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], @@ -216,14 +354,34 @@ "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="], + "pure-rand": ["pure-rand@8.4.2", "", {}, "sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng=="], + "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], + "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], + "rollup": ["rollup@4.60.3", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.60.3", "@rollup/rollup-android-arm64": "4.60.3", "@rollup/rollup-darwin-arm64": "4.60.3", "@rollup/rollup-darwin-x64": "4.60.3", "@rollup/rollup-freebsd-arm64": "4.60.3", "@rollup/rollup-freebsd-x64": "4.60.3", "@rollup/rollup-linux-arm-gnueabihf": "4.60.3", "@rollup/rollup-linux-arm-musleabihf": "4.60.3", "@rollup/rollup-linux-arm64-gnu": "4.60.3", "@rollup/rollup-linux-arm64-musl": "4.60.3", "@rollup/rollup-linux-loong64-gnu": "4.60.3", "@rollup/rollup-linux-loong64-musl": "4.60.3", "@rollup/rollup-linux-ppc64-gnu": "4.60.3", "@rollup/rollup-linux-ppc64-musl": "4.60.3", "@rollup/rollup-linux-riscv64-gnu": "4.60.3", "@rollup/rollup-linux-riscv64-musl": "4.60.3", "@rollup/rollup-linux-s390x-gnu": "4.60.3", "@rollup/rollup-linux-x64-gnu": "4.60.3", "@rollup/rollup-linux-x64-musl": "4.60.3", "@rollup/rollup-openbsd-x64": "4.60.3", "@rollup/rollup-openharmony-arm64": "4.60.3", "@rollup/rollup-win32-arm64-msvc": "4.60.3", "@rollup/rollup-win32-ia32-msvc": "4.60.3", "@rollup/rollup-win32-x64-gnu": "4.60.3", "@rollup/rollup-win32-x64-msvc": "4.60.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-pAQK9HalE84QSm4Po3EmWIZPd3FnjkShVkiMlz1iligWYkWQ7wHYd1PF/T7QZ5TVSD6uSTon5gBVMSM4JfBV+A=="], + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "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=="], + "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "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=="], + "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="], "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], @@ -238,6 +396,8 @@ "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "tsup": ["tsup@8.5.1", "", { "dependencies": { "bundle-require": "^5.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", "esbuild": "^0.27.0", "fix-dts-default-cjs-exports": "^1.0.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", "source-map": "^0.7.6", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing=="], "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], @@ -246,8 +406,48 @@ "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + "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=="], + + "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=="], + "zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="], + "@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/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "@opencode-ai/schema/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + "@oslojs/jwt/@oslojs/encoding": ["@oslojs/encoding@0.4.1", "", {}, "sha512-hkjo6MuIK/kQR5CrGNdAPZhS01ZCXuWDRJ187zh6qqF2+yMHZpD9fAYpX8q2bOO6Ryhl3XpCT6kUX76N8hhm4Q=="], + + "effect/@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="], + + "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=="], + + "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 f4acb77..fbcb38a 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "type": "module", "scripts": { "build": "tsup", - "smoke:node-import": "node -e \"import(require.resolve('opencode-gemini-auth')).then(() => console.log('ok')).catch((error) => { console.error(error); process.exit(1); })\"", + "smoke:node-import": "node -e \"Promise.all([import('opencode-gemini-auth'), import('opencode-gemini-auth/server')]).then(() => console.log('ok')).catch((error) => { console.error(error); process.exit(1); })\"", "prepack": "bun run build && bun run smoke:node-import", "prepublishOnly": "bun test && bun run prepack", "update:gemini-cli": "git -C .local/gemini-cli pull --ff-only", @@ -40,7 +40,7 @@ "typescript": "^5.9.3" }, "dependencies": { - "@opencode-ai/plugin": "^1.2.20", + "@opencode-ai/plugin": "beta", "@openauthjs/openauth": "^0.4.3" } } diff --git a/src/plugin-v2.test.ts b/src/plugin-v2.test.ts index af670e1..8e2f69f 100644 --- a/src/plugin-v2.test.ts +++ b/src/plugin-v2.test.ts @@ -1,6 +1,6 @@ import { expect, test } from "bun:test"; -import { setupV2 } from "./plugin-v2"; +import plugin, { setupV2 } from "./plugin-v2"; test("V2 plugin registers OAuth and rewrites Gemini requests and responses", async () => { let method: any; @@ -13,13 +13,13 @@ test("V2 plugin registers OAuth and rewrites Gemini requests and responses", asy expires: Date.now() + 60_000, }; - await setupV2({ + const context = { catalog: { provider: { async get() { return { data: { settings: {} } }; } }, }, integration: { - async transform(callback) { - callback({ method: { update(input) { method = input; } } }); + async transform(callback: (draft: any) => void) { + callback({ method: { update(input: any) { method = input; } } }); }, connection: { async active() { return { type: "credential" }; }, @@ -27,10 +27,13 @@ test("V2 plugin registers OAuth and rewrites Gemini requests and responses", asy }, }, session: { - async hook(name, callback) { hooks[name] = callback; }, + async hook(name: string, callback: (event: any) => Promise) { hooks[name] = callback; }, }, - }); + }; + await setupV2(context as unknown as Parameters[0]); + expect(plugin.id).toBe("opencode.provider.google-gemini-cli"); + expect(plugin.setup).toBe(setupV2); expect(method.integrationID).toBe("google"); expect(method.method.id).toBe("gemini-cli"); diff --git a/src/plugin-v2.ts b/src/plugin-v2.ts index 14bb6ff..fab670f 100644 --- a/src/plugin-v2.ts +++ b/src/plugin-v2.ts @@ -1,6 +1,7 @@ +import { Integration, Plugin, type Credential } from "@opencode-ai/plugin"; + import { GEMINI_PROVIDER_ID } from "./constants"; import type { GeminiTokenExchangeResult } from "./gemini/oauth"; -import { GeminiCLIOAuthPlugin } from "./plugin"; import { createOAuthAuthorizeMethod } from "./plugin/oauth-authorize"; import { resolveProjectContextFromAccessToken } from "./plugin/project"; import { resolveConfiguredProjectId } from "./plugin/provider"; @@ -12,61 +13,9 @@ import { import { refreshAccessToken } from "./plugin/token"; import type { OAuthAuthDetails, PluginClient } from "./plugin/types"; -const GEMINI_OAUTH_METHOD_ID = "gemini-cli"; - -interface V2Credential extends OAuthAuthDetails { - methodID: string; - access: string; - expires: number; - metadata?: Record; -} - -interface V2Context { - catalog: { - provider: { - get(input: { providerID: string }): Promise<{ - data?: { settings?: Record }; - } | undefined>; - }; - }; - integration: { - transform(callback: (draft: { - method: { - update(input: { - integrationID: string; - method: { id: string; type: "oauth"; label: string }; - authorize: () => Promise<{ - url: string; - instructions: string; - mode: "auto" | "code"; - callback: Promise | ((code: string) => Promise); - }>; - refresh: (credential: V2Credential) => Promise; - label: (credential: V2Credential) => string | undefined; - }): void; - }; - }) => void): Promise; - connection: { - active(id: string): Promise; - resolve(connection: unknown): Promise; - }; - }; - session: { - hook( - name: "http.request" | "http.response", - callback: (event: V2RequestEvent | V2ResponseEvent) => Promise, - ): Promise; - }; -} - -interface V2RequestEvent { - model: { providerID: string; id: string }; - request: Request; -} +const GEMINI_OAUTH_METHOD_ID = Integration.MethodID.make("gemini-cli"); -interface V2ResponseEvent extends V2RequestEvent { - response: Response; -} +type V2Context = Pick; const noPersistClient = { auth: { set: async () => {} }, @@ -113,12 +62,8 @@ export async function setupV2(ctx: V2Context): Promise { }); }); - await ctx.session.hook("http.request", async (rawEvent) => { - const event = rawEvent as V2RequestEvent; - if ( - event.model.providerID !== GEMINI_PROVIDER_ID || - !isGenerativeLanguageRequest(event.request) - ) { + await ctx.session.hook("http.request", async (event) => { + if (!isGenerativeLanguageRequest(event.request)) { return; } @@ -153,10 +98,9 @@ export async function setupV2(ctx: V2Context): Promise { requestedModel: transformed.requestedModel, }); event.request = request; - }); + }, { providerID: GEMINI_PROVIDER_ID }); - await ctx.session.hook("http.response", async (rawEvent) => { - const event = rawEvent as V2ResponseEvent; + await ctx.session.hook("http.response", async (event) => { const request = requests.get(event.request); if (!request) return; event.response = await transformGeminiResponse( @@ -165,7 +109,7 @@ export async function setupV2(ctx: V2Context): Promise { null, request.requestedModel, ); - }); + }, { providerID: GEMINI_PROVIDER_ID }); } async function resolveV2ConfiguredProjectId(ctx: V2Context): Promise { @@ -174,14 +118,14 @@ async function resolveV2ConfiguredProjectId(ctx: V2Context): Promise setupV2(ctx as V2Context), - server: GeminiCLIOAuthPlugin, -}; + setup: setupV2, +}); diff --git a/src/plugin/provider.test.ts b/src/plugin/provider.test.ts index 1a3cc2b..cc1340c 100644 --- a/src/plugin/provider.test.ts +++ b/src/plugin/provider.test.ts @@ -1,12 +1,11 @@ import { describe, expect, it } from "bun:test"; -import type { Config } from "@opencode-ai/sdk"; import { resolveConfiguredProjectId, resolveConfiguredProjectIdFromClient, resolveConfiguredProjectIdFromConfig, } from "./provider"; -import type { PluginClient, Provider } from "./types"; +import type { PluginClient, PluginConfig, Provider } from "./types"; describe("resolveConfiguredProjectId", () => { it("reads project id from provider options", () => { @@ -34,7 +33,7 @@ describe("resolveConfiguredProjectId", () => { }, }, }, - } satisfies Config; + } satisfies PluginConfig; expect(resolveConfiguredProjectIdFromConfig(config)).toBe("config-project"); expect( @@ -72,7 +71,7 @@ describe("resolveConfiguredProjectId", () => { }, }, }, - } satisfies Config, + } satisfies PluginConfig, }), }, } satisfies PluginClient; diff --git a/src/plugin/provider.ts b/src/plugin/provider.ts index e175a96..db92141 100644 --- a/src/plugin/provider.ts +++ b/src/plugin/provider.ts @@ -1,11 +1,9 @@ -import type { Config } from "@opencode-ai/sdk"; - import { GEMINI_PROVIDER_ID } from "../constants"; -import type { PluginClient, Provider } from "./types"; +import type { PluginClient, PluginConfig, Provider } from "./types"; interface ResolveConfiguredProjectIdInput { provider?: Provider | null; - config?: Config | null; + config?: PluginConfig | null; configProjectId?: string; env?: NodeJS.ProcessEnv; } @@ -35,7 +33,7 @@ export function resolveConfiguredProjectIdFromProvider( } export function resolveConfiguredProjectIdFromConfig( - config: Config | null | undefined, + config: PluginConfig | null | undefined, ): string | undefined { if (!config?.provider || typeof config.provider !== "object") { return undefined; diff --git a/src/plugin/quota.ts b/src/plugin/quota.ts index 1333eeb..378f198 100644 --- a/src/plugin/quota.ts +++ b/src/plugin/quota.ts @@ -1,4 +1,3 @@ -import { tool } from "@opencode-ai/plugin"; import { accessTokenExpired, isOAuthAuth } from "./auth"; import { resolveCachedAuth } from "./cache"; import { ensureProjectContext, retrieveUserQuota } from "./project"; @@ -21,7 +20,7 @@ export function createGeminiQuotaTool({ getConfiguredProjectId, getUserAgentModel, }: GeminiQuotaToolDependencies) { - return tool({ + return { description: "Retrieve current Gemini Code Assist quota usage for the authenticated user and project.", args: {}, @@ -78,7 +77,7 @@ export function createGeminiQuotaTool({ return `Gemini quota lookup failed: ${message}`; } }, - }); + }; } export function formatGeminiQuotaOutput( diff --git a/src/plugin/types.ts b/src/plugin/types.ts index a0ac506..9578a6b 100644 --- a/src/plugin/types.ts +++ b/src/plugin/types.ts @@ -1,6 +1,16 @@ import type { GeminiTokenExchangeResult } from "../gemini/oauth"; -import type { Config } from "@opencode-ai/sdk"; -import type { ToolDefinition } from "@opencode-ai/plugin"; + +export interface PluginConfig { + provider?: Record }>; + command?: Record; + [key: string]: unknown; +} + +interface ToolDefinition { + description: string; + args: Record; + execute(args: unknown, context: unknown): Promise; +} export interface OAuthAuthDetails { type: "oauth"; @@ -58,7 +68,7 @@ export interface PluginClient { }; config?: { get(options?: unknown): Promise<{ - data?: Config; + data?: PluginConfig; } | undefined>; }; tui?: { @@ -78,7 +88,7 @@ export interface PluginContext { } export interface PluginResult { - config?: (config: Config) => Promise; + config?: (config: PluginConfig) => Promise; tool?: Record; auth: { provider: string; diff --git a/tsup.config.ts b/tsup.config.ts index fb39757..97817ce 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -8,5 +8,5 @@ export default defineConfig({ clean: true, splitting: false, target: "node20", - noExternal: ["@opencode-ai/plugin", "@openauthjs/openauth"], + noExternal: ["@openauthjs/openauth"], }); From beaa979f9a3e24a8c666ca4a5e2ddb2f3890ce6d Mon Sep 17 00:00:00 2001 From: pascalandr Date: Sun, 23 Aug 2026 22:28:02 +0200 Subject: [PATCH 4/4] docs: clarify supported Google OAuth accounts Remove the obsolete free-tier claim and state that Gemini CLI OAuth is limited to organization-backed Code Assist Standard and Enterprise subscriptions. Personal accounts should use the native API-key flow, which avoids the third-party OAuth policy risk. --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 25f5aeb..33809ec 100644 --- a/README.md +++ b/README.md @@ -19,14 +19,16 @@ > Deprecation details: https://developers.google.com/gemini-code-assist/docs/deprecations/code-assist-individuals > Policy discussion: https://github.com/google-gemini/gemini-cli/discussions/22970 -**Authenticate the Opencode CLI with your Google account.** This plugin enables -you to use your existing Gemini plan and quotas (including the free tier) -directly within Opencode. +**Authenticate the Opencode CLI with an eligible organization-backed Google +account.** Gemini CLI OAuth is now limited to Gemini Code Assist Standard and +Enterprise subscriptions. Personal plans and the free tier must use the native +Gemini API-key flow instead of this plugin. ## Prerequisites - [Opencode CLI](https://opencode.ai) installed. -- A Google account with access to Gemini. +- A Gemini Code Assist Standard or Enterprise subscription. Consumer Google + accounts are no longer supported by this OAuth flow. ## Installation