@agentproto/adapter-gemini 0.2.26 → 0.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +8 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -29,6 +29,14 @@ var gemini = defineAgentCli({
|
|
|
29
29
|
range: ">=0.1.0",
|
|
30
30
|
timeout_ms: 15e3
|
|
31
31
|
},
|
|
32
|
+
// `install[]` is the global npm package, so the npm shape is the whole
|
|
33
|
+
// upgrade story: latest from the registry, in-place reinstall, and an
|
|
34
|
+
// exact-version rollback for a failed post-upgrade ACP smoke probe.
|
|
35
|
+
upgrade: {
|
|
36
|
+
latest: { npm: "@google/gemini-cli" },
|
|
37
|
+
cmd: ["npm", "i", "-g", "@google/gemini-cli@latest"],
|
|
38
|
+
rollback: ["npm", "i", "-g", "@google/gemini-cli@{version}"]
|
|
39
|
+
},
|
|
32
40
|
auth: {
|
|
33
41
|
ref: "./SECRETS.md",
|
|
34
42
|
// Every api-key rail the Gemini CLI honors — all three are scrubbed under a
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * @agentproto/adapter-gemini — AIP-45 adapter for Google's Gemini CLI in ACP\n * mode (`gemini --experimental-acp`).\n *\n * The Gemini CLI is an open-source terminal agent that speaks the Agent Client\n * Protocol when launched with `--experimental-acp` (aliased to `--acp` on\n * current builds; the experimental spelling still works and matches the wider\n * ACP catalog). Install it with `npm i -g @google/gemini-cli`, then:\n *\n * import { gemini, geminiRuntime } from \"@agentproto/adapter-gemini\"\n * const session = await geminiRuntime().start({\n * env: { GEMINI_API_KEY: \"...\" },\n * })\n * for await (const evt of session.send({ role: \"user\", content: \"...\" })) {\n * console.log(evt)\n * }\n * await session.close()\n *\n * The headline feature over the generic `gemini-cli` ACP catalog entry is\n * billing-auth: a native `provider` + a FILE-BASED (external) subscription so\n * \"use my existing Gemini login\" is a verified, observable, money-safe opt-in.\n */\n\nimport { join } from \"node:path\"\nimport {\n createAgentCliRuntime,\n defineAgentCli,\n type AgentCliHandle,\n type AgentCliRuntime,\n} from \"@agentproto/driver-agent-cli\"\nimport type { AuthStore, CapabilityStrategy, CredSource } from \"@agentproto/provider-kit\"\n\nexport const gemini: AgentCliHandle = defineAgentCli({\n name: \"gemini\",\n id: \"gemini\",\n description:\n \"Google's Gemini CLI in ACP mode (`gemini --experimental-acp`) — an open-source terminal agent driving Gemini models over the Agent Client Protocol via stdio JSON-RPC. Native adapter (over the generic `gemini-cli` catalog entry) so subscription billing-auth — \\\"use my existing Gemini login\\\" — is a verified, money-safe opt-in.\",\n version: \"0.1.0\",\n bin: \"gemini\",\n // `--experimental-acp` starts ACP mode. Current Gemini CLI (0.45.x) prefers\n // the shorter `--acp`, but keeps `--experimental-acp` as a working alias, and\n // it's the spelling the rest of the ACP catalog uses — so keep it for parity.\n bin_args: [\"--experimental-acp\"],\n install: [\n {\n method: \"npm\",\n package: \"@google/gemini-cli\",\n global: true,\n },\n ],\n version_check: {\n cmd: \"gemini --version\",\n parse: \"(\\\\d+\\\\.\\\\d+\\\\.\\\\d+)\",\n range: \">=0.1.0\",\n timeout_ms: 15_000,\n },\n auth: {\n ref: \"./SECRETS.md\",\n // Every api-key rail the Gemini CLI honors — all three are scrubbed under a\n // file-based subscription so a stray key can't flip billing (see below).\n state: {\n env: [\"GEMINI_API_KEY\", \"GOOGLE_API_KEY\", \"GOOGLE_GENERATIVE_AI_API_KEY\"],\n },\n },\n // Billing-auth (opt-in — no authEnforce, so unconfigured spawns stay\n // ambient). Single-provider adapter: api-key mode SETS providerEnvVar\n // (\"google\") = GOOGLE_GENERATIVE_AI_API_KEY, derived from the catalog.\n provider: \"google\",\n // \"Use my existing Gemini login\" — a FILE-BASED (external) subscription. The\n // Gemini CLI's OAuth login lives in `~/.gemini/oauth_creds.json`\n // (`access_token`), which the CLI reads ITSELF; it has no env-bearer channel\n // like claude-code's CLAUDE_CODE_OAUTH_TOKEN. So `external: true`: subscription\n // mode injects NOTHING (no setEnv) — the host verifies the login is present\n // (fail-loud, via the `gemini` provision recipe) and the driver only SCRUBS\n // the api-key vars so a leftover key can't silently flip the spawn to per-token\n // API billing under a \"subscription\" label.\n //\n // GOOGLE_GENERATIVE_AI_API_KEY is scrubbed automatically (it's the provider's\n // api-key var). GEMINI_API_KEY and GOOGLE_API_KEY are the two SIBLING keys the\n // Gemini CLI also honors — and, critically, an env API key OVERRIDES the OAuth\n // login in Google's auth precedence, so BOTH must be scrubbed for the login to\n // win (they're listed as conflictEnv). Money-safe by construction: no OAuth\n // bearer is ever written into an api-key env var, because no bearer is injected\n // at all. An unconfigured gemini spawn stays ambient — the CLI uses its own\n // oauth_creds.json precedence — so this only ADDS an explicit, verified,\n // billing-guaranteed, observable opt-in on top of that.\n authSubscription: {\n external: true,\n conflictEnv: [\"GEMINI_API_KEY\", \"GOOGLE_API_KEY\"],\n },\n sandbox: \"./SANDBOX.md\",\n protocol: \"acp\",\n acp: \"./gemini-acp.ACP.md\",\n session: {\n mode: \"persistent\",\n idle_timeout_ms: 1_800_000,\n context_carryover: true,\n },\n models: {\n default: \"gemini-2.5-pro\",\n // Sourced from the model catalog's curated Google (vendor \"google\") text\n // models — NOT hand-invented ids (see packages/model-catalog/src/llm/\n // catalog.ts). Kept to the stable + current preview lines the CLI serves.\n allowed: [\n \"gemini-2.5-pro\",\n \"gemini-2.5-flash\",\n \"gemini-2.5-flash-lite\",\n \"gemini-3.5-flash\",\n \"gemini-3.1-pro-preview\",\n \"gemini-3-flash-preview\",\n \"gemini-3.1-flash-lite\",\n ],\n env: {\n google: \"GOOGLE_GENERATIVE_AI_API_KEY\",\n gemini: \"GEMINI_API_KEY\",\n },\n // The Gemini CLI takes its model as the documented global `-m/--model`\n // flag, composed into argv at spawn time (confirmed present on 0.45.2 via\n // `gemini --help`). It's a global flag, so it applies alongside\n // `--experimental-acp`; worst case a future ACP build ignores it and the\n // session falls back to the CLI's default model — never a mis-bill.\n apply: \"arg\",\n bin_args_template: [\"-m\", \"{model}\"],\n },\n capabilities: {\n streaming: true,\n tool_calls: true,\n sub_agents: false,\n file_io: true,\n // Gemini models are natively multimodal; the CLI forwards ACP image content\n // blocks into the Gemini vision pipeline.\n multimodal: true,\n // The Gemini CLI implements ACP session lifecycle (newSession / loadSession).\n resumable: true,\n bidirectional: true,\n },\n options: [\n {\n id: \"model\",\n type: \"enum\",\n enum: [\n \"gemini-2.5-pro\",\n \"gemini-2.5-flash\",\n \"gemini-2.5-flash-lite\",\n \"gemini-3.5-flash\",\n \"gemini-3.1-pro-preview\",\n \"gemini-3-flash-preview\",\n \"gemini-3.1-flash-lite\",\n ],\n description: \"Override the default model for this operator binding.\",\n // Real composition happens via `models.apply: \"arg\"` above; this option\n // exists so `config.options.model` validates.\n },\n ],\n continuation: {\n default: \"native-resume\",\n supported: [\"native-resume\", \"pinned-session\", \"transcript\", \"none\"],\n pinned_session: {\n idle_timeout_ms: 1_800_000,\n key_scope: [\"conversation\", \"operator\"],\n },\n },\n tags: [\"gemini\", \"google\", \"acp\", \"agent-runtime\", \"coding\"],\n})\n\nexport function geminiRuntime(): AgentCliRuntime {\n return createAgentCliRuntime(gemini)\n}\n\ninterface GeminiSettingsFile {\n security?: { auth?: { selectedType?: unknown } }\n}\n\n/**\n * Best-effort capability discovery for gemini: parses the Gemini CLI's own\n * `~/.gemini/settings.json` (`security.auth.selectedType`) plus the\n * presence of `~/.gemini/oauth_creds.json` to report whether the \"use my\n * existing Gemini login\" file-based subscription is actually live on this\n * host, alongside the api-key fallback path. Never throws — a malformed\n * settings.json just leaves `selectedType` undetermined rather than\n * blanking the whole result.\n */\nexport const geminiCapabilities: CapabilityStrategy = async (def, ctx) => {\n const settingsPath = join(ctx.homeDir, \".gemini\", \"settings.json\")\n const oauthPath = join(ctx.homeDir, \".gemini\", \"oauth_creds.json\")\n\n let selectedType: string | undefined\n const settingsRaw = await ctx.readFile(settingsPath)\n if (settingsRaw !== null) {\n try {\n const parsed = JSON.parse(settingsRaw) as GeminiSettingsFile\n if (typeof parsed.security?.auth?.selectedType === \"string\") {\n selectedType = parsed.security.auth.selectedType\n }\n } catch (err) {\n ctx.warn(\n `gemini capability discovery: could not parse ~/.gemini/settings.json: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n\n const oauthLoginPresent = (await ctx.readFile(oauthPath)) !== null\n const oauthSelected = selectedType !== undefined && selectedType.toLowerCase().includes(\"oauth\")\n\n // Same var the manifest itself declares for google (models.env.google) —\n // never a hardcoded/guessed name.\n const apiKeyEnvVar = def.models?.env?.google ?? \"GOOGLE_GENERATIVE_AI_API_KEY\"\n const apiKeyPresent = !!ctx.env[apiKeyEnvVar]\n\n const oauthPresent = oauthSelected && oauthLoginPresent\n const source: CredSource = oauthPresent\n ? { kind: \"oauth-file\", path: \"~/.gemini/oauth_creds.json\" }\n : { kind: \"env\", var: apiKeyEnvVar }\n\n const authStores: AuthStore[] = [\n { kind: \"oauth-file\", path: \"~/.gemini/oauth_creds.json\", format: \"json\", providerKeyed: false },\n { kind: \"env\", providerKeyed: false },\n ]\n\n const modelApply = def.models?.apply\n return {\n adapter: def.id,\n source: \"discovered\",\n discoverable: \"parse\",\n authStores,\n providers: [\n {\n id: \"google\",\n billingEndpoint: \"google\",\n cred: { present: oauthPresent || apiKeyPresent, source },\n },\n ],\n models: { mechanism: \"catalog\" },\n endpointCompat: {},\n application: {\n modelApply: modelApply === \"command\" || modelApply === \"arg\" ? modelApply : \"config\",\n postureApply: \"none\",\n coupled: false,\n },\n }\n}\n\nexport type { AgentCliHandle, AgentCliRuntime }\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;AAgCO,IAAM,SAAyB,cAAA,CAAe;AAAA,EACnD,IAAA,EAAM,QAAA;AAAA,EACN,EAAA,EAAI,QAAA;AAAA,EACJ,WAAA,EACE,uVAAA;AAAA,EACF,OAAA,EAAS,OAAA;AAAA,EACT,GAAA,EAAK,QAAA;AAAA;AAAA;AAAA;AAAA,EAIL,QAAA,EAAU,CAAC,oBAAoB,CAAA;AAAA,EAC/B,OAAA,EAAS;AAAA,IACP;AAAA,MACE,MAAA,EAAQ,KAAA;AAAA,MACR,OAAA,EAAS,oBAAA;AAAA,MACT,MAAA,EAAQ;AAAA;AACV,GACF;AAAA,EACA,aAAA,EAAe;AAAA,IACb,GAAA,EAAK,kBAAA;AAAA,IACL,KAAA,EAAO,sBAAA;AAAA,IACP,KAAA,EAAO,SAAA;AAAA,IACP,UAAA,EAAY;AAAA,GACd;AAAA;AAAA;AAAA;AAAA,EAIA,OAAA,EAAS;AAAA,IACP,MAAA,EAAQ,EAAE,GAAA,EAAK,oBAAA,EAAqB;AAAA,IACpC,GAAA,EAAK,CAAC,KAAA,EAAO,GAAA,EAAK,MAAM,2BAA2B,CAAA;AAAA,IACnD,QAAA,EAAU,CAAC,KAAA,EAAO,GAAA,EAAK,MAAM,8BAA8B;AAAA,GAC7D;AAAA,EACA,IAAA,EAAM;AAAA,IACJ,GAAA,EAAK,cAAA;AAAA;AAAA;AAAA,IAGL,KAAA,EAAO;AAAA,MACL,GAAA,EAAK,CAAC,gBAAA,EAAkB,gBAAA,EAAkB,8BAA8B;AAAA;AAC1E,GACF;AAAA;AAAA;AAAA;AAAA,EAIA,QAAA,EAAU,QAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBV,gBAAA,EAAkB;AAAA,IAChB,QAAA,EAAU,IAAA;AAAA,IACV,WAAA,EAAa,CAAC,gBAAA,EAAkB,gBAAgB;AAAA,GAClD;AAAA,EACA,OAAA,EAAS,cAAA;AAAA,EACT,QAAA,EAAU,KAAA;AAAA,EACV,GAAA,EAAK,qBAAA;AAAA,EACL,OAAA,EAAS;AAAA,IACP,IAAA,EAAM,YAAA;AAAA,IACN,eAAA,EAAiB,IAAA;AAAA,IACjB,iBAAA,EAAmB;AAAA,GACrB;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,OAAA,EAAS,gBAAA;AAAA;AAAA;AAAA;AAAA,IAIT,OAAA,EAAS;AAAA,MACP,gBAAA;AAAA,MACA,kBAAA;AAAA,MACA,uBAAA;AAAA,MACA,kBAAA;AAAA,MACA,wBAAA;AAAA,MACA,wBAAA;AAAA,MACA;AAAA,KACF;AAAA,IACA,GAAA,EAAK;AAAA,MACH,MAAA,EAAQ,8BAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,KAAA,EAAO,KAAA;AAAA,IACP,iBAAA,EAAmB,CAAC,IAAA,EAAM,SAAS;AAAA,GACrC;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,SAAA,EAAW,IAAA;AAAA,IACX,UAAA,EAAY,IAAA;AAAA,IACZ,UAAA,EAAY,KAAA;AAAA,IACZ,OAAA,EAAS,IAAA;AAAA;AAAA;AAAA,IAGT,UAAA,EAAY,IAAA;AAAA;AAAA,IAEZ,SAAA,EAAW,IAAA;AAAA,IACX,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,OAAA,EAAS;AAAA,IACP;AAAA,MACE,EAAA,EAAI,OAAA;AAAA,MACJ,IAAA,EAAM,MAAA;AAAA,MACN,IAAA,EAAM;AAAA,QACJ,gBAAA;AAAA,QACA,kBAAA;AAAA,QACA,uBAAA;AAAA,QACA,kBAAA;AAAA,QACA,wBAAA;AAAA,QACA,wBAAA;AAAA,QACA;AAAA,OACF;AAAA,MACA,WAAA,EAAa;AAAA;AAAA;AAAA;AAGf,GACF;AAAA,EACA,YAAA,EAAc;AAAA,IACZ,OAAA,EAAS,eAAA;AAAA,IACT,SAAA,EAAW,CAAC,eAAA,EAAiB,gBAAA,EAAkB,cAAc,MAAM,CAAA;AAAA,IACnE,cAAA,EAAgB;AAAA,MACd,eAAA,EAAiB,IAAA;AAAA,MACjB,SAAA,EAAW,CAAC,cAAA,EAAgB,UAAU;AAAA;AACxC,GACF;AAAA,EACA,MAAM,CAAC,QAAA,EAAU,QAAA,EAAU,KAAA,EAAO,iBAAiB,QAAQ;AAC7D,CAAC;AAEM,SAAS,aAAA,GAAiC;AAC/C,EAAA,OAAO,sBAAsB,MAAM,CAAA;AACrC;AAeO,IAAM,kBAAA,GAAyC,OAAO,GAAA,EAAK,GAAA,KAAQ;AACxE,EAAA,MAAM,YAAA,GAAe,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,WAAW,eAAe,CAAA;AACjE,EAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,WAAW,kBAAkB,CAAA;AAEjE,EAAA,IAAI,YAAA;AACJ,EAAA,MAAM,WAAA,GAAc,MAAM,GAAA,CAAI,QAAA,CAAS,YAAY,CAAA;AACnD,EAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,WAAW,CAAA;AACrC,MAAA,IAAI,OAAO,MAAA,CAAO,QAAA,EAAU,IAAA,EAAM,iBAAiB,QAAA,EAAU;AAC3D,QAAA,YAAA,GAAe,MAAA,CAAO,SAAS,IAAA,CAAK,YAAA;AAAA,MACtC;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,GAAA,CAAI,IAAA;AAAA,QACF,yEACK,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,OACvD;AAAA,IACF;AAAA,EACF;AAEA,EAAA,MAAM,iBAAA,GAAqB,MAAM,GAAA,CAAI,QAAA,CAAS,SAAS,CAAA,KAAO,IAAA;AAC9D,EAAA,MAAM,gBAAgB,YAAA,KAAiB,MAAA,IAAa,aAAa,WAAA,EAAY,CAAE,SAAS,OAAO,CAAA;AAI/F,EAAA,MAAM,YAAA,GAAe,GAAA,CAAI,MAAA,EAAQ,GAAA,EAAK,MAAA,IAAU,8BAAA;AAChD,EAAA,MAAM,aAAA,GAAgB,CAAC,CAAC,GAAA,CAAI,IAAI,YAAY,CAAA;AAE5C,EAAA,MAAM,eAAe,aAAA,IAAiB,iBAAA;AACtC,EAAA,MAAM,MAAA,GAAqB,YAAA,GACvB,EAAE,IAAA,EAAM,YAAA,EAAc,IAAA,EAAM,4BAAA,EAA6B,GACzD,EAAE,IAAA,EAAM,KAAA,EAAO,GAAA,EAAK,YAAA,EAAa;AAErC,EAAA,MAAM,UAAA,GAA0B;AAAA,IAC9B,EAAE,MAAM,YAAA,EAAc,IAAA,EAAM,8BAA8B,MAAA,EAAQ,MAAA,EAAQ,eAAe,KAAA,EAAM;AAAA,IAC/F,EAAE,IAAA,EAAM,KAAA,EAAO,aAAA,EAAe,KAAA;AAAM,GACtC;AAEA,EAAA,MAAM,UAAA,GAAa,IAAI,MAAA,EAAQ,KAAA;AAC/B,EAAA,OAAO;AAAA,IACL,SAAS,GAAA,CAAI,EAAA;AAAA,IACb,MAAA,EAAQ,YAAA;AAAA,IACR,YAAA,EAAc,OAAA;AAAA,IACd,UAAA;AAAA,IACA,SAAA,EAAW;AAAA,MACT;AAAA,QACE,EAAA,EAAI,QAAA;AAAA,QACJ,eAAA,EAAiB,QAAA;AAAA,QACjB,IAAA,EAAM,EAAE,OAAA,EAAS,YAAA,IAAgB,eAAe,MAAA;AAAO;AACzD,KACF;AAAA,IACA,MAAA,EAAQ,EAAE,SAAA,EAAW,SAAA,EAAU;AAAA,IAC/B,gBAAgB,EAAC;AAAA,IACjB,WAAA,EAAa;AAAA,MACX,UAAA,EAAY,UAAA,KAAe,SAAA,IAAa,UAAA,KAAe,QAAQ,UAAA,GAAa,QAAA;AAAA,MAC5E,YAAA,EAAc,MAAA;AAAA,MACd,OAAA,EAAS;AAAA;AACX,GACF;AACF","file":"index.mjs","sourcesContent":["/**\n * @agentproto/adapter-gemini — AIP-45 adapter for Google's Gemini CLI in ACP\n * mode (`gemini --experimental-acp`).\n *\n * The Gemini CLI is an open-source terminal agent that speaks the Agent Client\n * Protocol when launched with `--experimental-acp` (aliased to `--acp` on\n * current builds; the experimental spelling still works and matches the wider\n * ACP catalog). Install it with `npm i -g @google/gemini-cli`, then:\n *\n * import { gemini, geminiRuntime } from \"@agentproto/adapter-gemini\"\n * const session = await geminiRuntime().start({\n * env: { GEMINI_API_KEY: \"...\" },\n * })\n * for await (const evt of session.send({ role: \"user\", content: \"...\" })) {\n * console.log(evt)\n * }\n * await session.close()\n *\n * The headline feature over the generic `gemini-cli` ACP catalog entry is\n * billing-auth: a native `provider` + a FILE-BASED (external) subscription so\n * \"use my existing Gemini login\" is a verified, observable, money-safe opt-in.\n */\n\nimport { join } from \"node:path\"\nimport {\n createAgentCliRuntime,\n defineAgentCli,\n type AgentCliHandle,\n type AgentCliRuntime,\n} from \"@agentproto/driver-agent-cli\"\nimport type { AuthStore, CapabilityStrategy, CredSource } from \"@agentproto/provider-kit\"\n\nexport const gemini: AgentCliHandle = defineAgentCli({\n name: \"gemini\",\n id: \"gemini\",\n description:\n \"Google's Gemini CLI in ACP mode (`gemini --experimental-acp`) — an open-source terminal agent driving Gemini models over the Agent Client Protocol via stdio JSON-RPC. Native adapter (over the generic `gemini-cli` catalog entry) so subscription billing-auth — \\\"use my existing Gemini login\\\" — is a verified, money-safe opt-in.\",\n version: \"0.1.0\",\n bin: \"gemini\",\n // `--experimental-acp` starts ACP mode. Current Gemini CLI (0.45.x) prefers\n // the shorter `--acp`, but keeps `--experimental-acp` as a working alias, and\n // it's the spelling the rest of the ACP catalog uses — so keep it for parity.\n bin_args: [\"--experimental-acp\"],\n install: [\n {\n method: \"npm\",\n package: \"@google/gemini-cli\",\n global: true,\n },\n ],\n version_check: {\n cmd: \"gemini --version\",\n parse: \"(\\\\d+\\\\.\\\\d+\\\\.\\\\d+)\",\n range: \">=0.1.0\",\n timeout_ms: 15_000,\n },\n // `install[]` is the global npm package, so the npm shape is the whole\n // upgrade story: latest from the registry, in-place reinstall, and an\n // exact-version rollback for a failed post-upgrade ACP smoke probe.\n upgrade: {\n latest: { npm: \"@google/gemini-cli\" },\n cmd: [\"npm\", \"i\", \"-g\", \"@google/gemini-cli@latest\"],\n rollback: [\"npm\", \"i\", \"-g\", \"@google/gemini-cli@{version}\"],\n },\n auth: {\n ref: \"./SECRETS.md\",\n // Every api-key rail the Gemini CLI honors — all three are scrubbed under a\n // file-based subscription so a stray key can't flip billing (see below).\n state: {\n env: [\"GEMINI_API_KEY\", \"GOOGLE_API_KEY\", \"GOOGLE_GENERATIVE_AI_API_KEY\"],\n },\n },\n // Billing-auth (opt-in — no authEnforce, so unconfigured spawns stay\n // ambient). Single-provider adapter: api-key mode SETS providerEnvVar\n // (\"google\") = GOOGLE_GENERATIVE_AI_API_KEY, derived from the catalog.\n provider: \"google\",\n // \"Use my existing Gemini login\" — a FILE-BASED (external) subscription. The\n // Gemini CLI's OAuth login lives in `~/.gemini/oauth_creds.json`\n // (`access_token`), which the CLI reads ITSELF; it has no env-bearer channel\n // like claude-code's CLAUDE_CODE_OAUTH_TOKEN. So `external: true`: subscription\n // mode injects NOTHING (no setEnv) — the host verifies the login is present\n // (fail-loud, via the `gemini` provision recipe) and the driver only SCRUBS\n // the api-key vars so a leftover key can't silently flip the spawn to per-token\n // API billing under a \"subscription\" label.\n //\n // GOOGLE_GENERATIVE_AI_API_KEY is scrubbed automatically (it's the provider's\n // api-key var). GEMINI_API_KEY and GOOGLE_API_KEY are the two SIBLING keys the\n // Gemini CLI also honors — and, critically, an env API key OVERRIDES the OAuth\n // login in Google's auth precedence, so BOTH must be scrubbed for the login to\n // win (they're listed as conflictEnv). Money-safe by construction: no OAuth\n // bearer is ever written into an api-key env var, because no bearer is injected\n // at all. An unconfigured gemini spawn stays ambient — the CLI uses its own\n // oauth_creds.json precedence — so this only ADDS an explicit, verified,\n // billing-guaranteed, observable opt-in on top of that.\n authSubscription: {\n external: true,\n conflictEnv: [\"GEMINI_API_KEY\", \"GOOGLE_API_KEY\"],\n },\n sandbox: \"./SANDBOX.md\",\n protocol: \"acp\",\n acp: \"./gemini-acp.ACP.md\",\n session: {\n mode: \"persistent\",\n idle_timeout_ms: 1_800_000,\n context_carryover: true,\n },\n models: {\n default: \"gemini-2.5-pro\",\n // Sourced from the model catalog's curated Google (vendor \"google\") text\n // models — NOT hand-invented ids (see packages/model-catalog/src/llm/\n // catalog.ts). Kept to the stable + current preview lines the CLI serves.\n allowed: [\n \"gemini-2.5-pro\",\n \"gemini-2.5-flash\",\n \"gemini-2.5-flash-lite\",\n \"gemini-3.5-flash\",\n \"gemini-3.1-pro-preview\",\n \"gemini-3-flash-preview\",\n \"gemini-3.1-flash-lite\",\n ],\n env: {\n google: \"GOOGLE_GENERATIVE_AI_API_KEY\",\n gemini: \"GEMINI_API_KEY\",\n },\n // The Gemini CLI takes its model as the documented global `-m/--model`\n // flag, composed into argv at spawn time (confirmed present on 0.45.2 via\n // `gemini --help`). It's a global flag, so it applies alongside\n // `--experimental-acp`; worst case a future ACP build ignores it and the\n // session falls back to the CLI's default model — never a mis-bill.\n apply: \"arg\",\n bin_args_template: [\"-m\", \"{model}\"],\n },\n capabilities: {\n streaming: true,\n tool_calls: true,\n sub_agents: false,\n file_io: true,\n // Gemini models are natively multimodal; the CLI forwards ACP image content\n // blocks into the Gemini vision pipeline.\n multimodal: true,\n // The Gemini CLI implements ACP session lifecycle (newSession / loadSession).\n resumable: true,\n bidirectional: true,\n },\n options: [\n {\n id: \"model\",\n type: \"enum\",\n enum: [\n \"gemini-2.5-pro\",\n \"gemini-2.5-flash\",\n \"gemini-2.5-flash-lite\",\n \"gemini-3.5-flash\",\n \"gemini-3.1-pro-preview\",\n \"gemini-3-flash-preview\",\n \"gemini-3.1-flash-lite\",\n ],\n description: \"Override the default model for this operator binding.\",\n // Real composition happens via `models.apply: \"arg\"` above; this option\n // exists so `config.options.model` validates.\n },\n ],\n continuation: {\n default: \"native-resume\",\n supported: [\"native-resume\", \"pinned-session\", \"transcript\", \"none\"],\n pinned_session: {\n idle_timeout_ms: 1_800_000,\n key_scope: [\"conversation\", \"operator\"],\n },\n },\n tags: [\"gemini\", \"google\", \"acp\", \"agent-runtime\", \"coding\"],\n})\n\nexport function geminiRuntime(): AgentCliRuntime {\n return createAgentCliRuntime(gemini)\n}\n\ninterface GeminiSettingsFile {\n security?: { auth?: { selectedType?: unknown } }\n}\n\n/**\n * Best-effort capability discovery for gemini: parses the Gemini CLI's own\n * `~/.gemini/settings.json` (`security.auth.selectedType`) plus the\n * presence of `~/.gemini/oauth_creds.json` to report whether the \"use my\n * existing Gemini login\" file-based subscription is actually live on this\n * host, alongside the api-key fallback path. Never throws — a malformed\n * settings.json just leaves `selectedType` undetermined rather than\n * blanking the whole result.\n */\nexport const geminiCapabilities: CapabilityStrategy = async (def, ctx) => {\n const settingsPath = join(ctx.homeDir, \".gemini\", \"settings.json\")\n const oauthPath = join(ctx.homeDir, \".gemini\", \"oauth_creds.json\")\n\n let selectedType: string | undefined\n const settingsRaw = await ctx.readFile(settingsPath)\n if (settingsRaw !== null) {\n try {\n const parsed = JSON.parse(settingsRaw) as GeminiSettingsFile\n if (typeof parsed.security?.auth?.selectedType === \"string\") {\n selectedType = parsed.security.auth.selectedType\n }\n } catch (err) {\n ctx.warn(\n `gemini capability discovery: could not parse ~/.gemini/settings.json: ` +\n `${err instanceof Error ? err.message : String(err)}`,\n )\n }\n }\n\n const oauthLoginPresent = (await ctx.readFile(oauthPath)) !== null\n const oauthSelected = selectedType !== undefined && selectedType.toLowerCase().includes(\"oauth\")\n\n // Same var the manifest itself declares for google (models.env.google) —\n // never a hardcoded/guessed name.\n const apiKeyEnvVar = def.models?.env?.google ?? \"GOOGLE_GENERATIVE_AI_API_KEY\"\n const apiKeyPresent = !!ctx.env[apiKeyEnvVar]\n\n const oauthPresent = oauthSelected && oauthLoginPresent\n const source: CredSource = oauthPresent\n ? { kind: \"oauth-file\", path: \"~/.gemini/oauth_creds.json\" }\n : { kind: \"env\", var: apiKeyEnvVar }\n\n const authStores: AuthStore[] = [\n { kind: \"oauth-file\", path: \"~/.gemini/oauth_creds.json\", format: \"json\", providerKeyed: false },\n { kind: \"env\", providerKeyed: false },\n ]\n\n const modelApply = def.models?.apply\n return {\n adapter: def.id,\n source: \"discovered\",\n discoverable: \"parse\",\n authStores,\n providers: [\n {\n id: \"google\",\n billingEndpoint: \"google\",\n cred: { present: oauthPresent || apiKeyPresent, source },\n },\n ],\n models: { mechanism: \"catalog\" },\n endpointCompat: {},\n application: {\n modelApply: modelApply === \"command\" || modelApply === \"arg\" ? modelApply : \"config\",\n postureApply: \"none\",\n coupled: false,\n },\n }\n}\n\nexport type { AgentCliHandle, AgentCliRuntime }\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentproto/adapter-gemini",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.28",
|
|
4
4
|
"description": "@agentproto/adapter-gemini — AIP-45 AGENT-CLI adapter for Google's Gemini CLI in ACP mode (`gemini --experimental-acp`). Native billing-auth: \"use my existing Gemini login\".",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentproto",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@agentproto/driver-agent-cli": "2.
|
|
44
|
+
"@agentproto/driver-agent-cli": "2.13.1",
|
|
45
45
|
"@agentproto/provider-kit": "0.4.6"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|