zidane 8.2.1 → 8.2.3
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/acp-cli.js +8 -8
- package/dist/{acp-D7Pr8NGt.js → acp-oYRjlh71.js} +6 -6
- package/dist/{acp-D7Pr8NGt.js.map → acp-oYRjlh71.js.map} +1 -1
- package/dist/acp.d.ts +2 -2
- package/dist/acp.js +1 -1
- package/dist/{agent-DecDtKA_.js → agent-CBQglXtH.js} +9 -379
- package/dist/agent-CBQglXtH.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +1 -1
- package/dist/{builtin-artifact-kinds-B_OEgf8b.js → builtin-artifact-kinds-BmorPkgz.js} +36 -9
- package/dist/builtin-artifact-kinds-BmorPkgz.js.map +1 -0
- package/dist/chat/pure.d.ts +4 -4
- package/dist/chat/pure.js +6 -6
- package/dist/chat.d.ts +4 -4
- package/dist/chat.js +15 -15
- package/dist/{cli-shared-Dx4vmif6.js → cli-shared-E5m_pI8A.js} +2 -2
- package/dist/{cli-shared-Dx4vmif6.js.map → cli-shared-E5m_pI8A.js.map} +1 -1
- package/dist/{client-core-imHuBWV3.d.ts → client-core-EEEX_u6D.d.ts} +24 -5
- package/dist/{client-core-imHuBWV3.d.ts.map → client-core-EEEX_u6D.d.ts.map} +1 -1
- package/dist/{connection-loop-CdHt3iQi.d.ts → connection-loop-CpgfUmuw.d.ts} +3 -3
- package/dist/{connection-loop-CdHt3iQi.d.ts.map → connection-loop-CpgfUmuw.d.ts.map} +1 -1
- package/dist/contexts/daytona.d.ts +1 -1
- package/dist/contexts/e2b.d.ts +1 -1
- package/dist/{credentials-Dti61yoi.js → credentials-B9DfBJP9.js} +11 -7
- package/dist/credentials-B9DfBJP9.js.map +1 -0
- package/dist/daemon-cli.js +2 -2
- package/dist/{dispatcher-vy3J6JMA.js → dispatcher-Bv9-c6I2.js} +28 -14
- package/dist/dispatcher-Bv9-c6I2.js.map +1 -0
- package/dist/{engine-BN6PjWAW.js → engine-XmoPPB6U.js} +5 -5
- package/dist/{engine-BN6PjWAW.js.map → engine-XmoPPB6U.js.map} +1 -1
- package/dist/{eval-BaJtxLCW.js → eval-CfQlBR81.js} +2 -2
- package/dist/{eval-BaJtxLCW.js.map → eval-CfQlBR81.js.map} +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +1 -1
- package/dist/{executor-CT4oUkg6.js → executor-BhthPE1q.js} +3 -3
- package/dist/{executor-CT4oUkg6.js.map → executor-BhthPE1q.js.map} +1 -1
- package/dist/{extensions-BKt7lxxv.js → extensions-BgBwogRW.js} +114 -113
- package/dist/extensions-BgBwogRW.js.map +1 -0
- package/dist/extensions.d.ts +1 -1
- package/dist/extensions.js +2 -2
- package/dist/{fold-rules-BYedvsH7.d.ts → fold-rules-DSypi36k.d.ts} +2 -2
- package/dist/{fold-rules-BYedvsH7.d.ts.map → fold-rules-DSypi36k.d.ts.map} +1 -1
- package/dist/google-O6pRnddf.js +881 -0
- package/dist/google-O6pRnddf.js.map +1 -0
- package/dist/{headless-Ebd1ZEzC.js → headless-R4pbpTkm.js} +3 -3
- package/dist/{headless-Ebd1ZEzC.js.map → headless-R4pbpTkm.js.map} +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/{host-scoped-settings-Cy_zbmB_.js → host-scoped-settings-C-Nmb6vr.js} +2 -2
- package/dist/{host-scoped-settings-Cy_zbmB_.js.map → host-scoped-settings-C-Nmb6vr.js.map} +1 -1
- package/dist/{host-signals-Cx2IAbHh.js → host-signals-BFudPyCT.js} +5 -5
- package/dist/{host-signals-Cx2IAbHh.js.map → host-signals-BFudPyCT.js.map} +1 -1
- package/dist/{index-pc71ADi6.d.ts → index-AqRZ3gEz.d.ts} +71 -4
- package/dist/index-AqRZ3gEz.d.ts.map +1 -0
- package/dist/{index-Bt_G2Z_2.d.ts → index-CDS7YdUC.d.ts} +5 -5
- package/dist/{index-Bt_G2Z_2.d.ts.map → index-CDS7YdUC.d.ts.map} +1 -1
- package/dist/{index-CidMTcxS.d.ts → index-DyQyDLX1.d.ts} +167 -10
- package/dist/index-DyQyDLX1.d.ts.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +15 -15
- package/dist/ipc/remote.d.ts +5 -5
- package/dist/ipc/remote.js +3 -3
- package/dist/ipc.d.ts +5 -5
- package/dist/ipc.js +7 -7
- package/dist/{links-DSZ4uQ5w.js → links-rFaWqS2Y.js} +10 -10
- package/dist/{links-DSZ4uQ5w.js.map → links-rFaWqS2Y.js.map} +1 -1
- package/dist/{mcp-allowlist-BQ5MvhHi.js → mcp-allowlist-CLXweyxk.js} +14 -3
- package/dist/mcp-allowlist-CLXweyxk.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/{oauth-BSqXgads.js → oauth-7_48zR7n.js} +226 -40
- package/dist/oauth-7_48zR7n.js.map +1 -0
- package/dist/{openai-dTmPxM6T.js → openai-Rh6u5NXF.js} +121 -2
- package/dist/openai-Rh6u5NXF.js.map +1 -0
- package/dist/{openrouter-CtZbQDa0.js → openrouter-Dg0yaI-o.js} +91 -2
- package/dist/openrouter-Dg0yaI-o.js.map +1 -0
- package/dist/output/stream-json.d.ts +1 -1
- package/dist/output/terminal.d.ts +1 -1
- package/dist/plugins.d.ts +1 -1
- package/dist/{presets-EzlHyFSi.js → presets-DXeHsd24.js} +3 -3
- package/dist/{presets-EzlHyFSi.js.map → presets-DXeHsd24.js.map} +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/{prompts-D2lPHLOV.d.ts → prompts-DmY13jvF.d.ts} +2 -1
- package/dist/prompts-DmY13jvF.d.ts.map +1 -0
- package/dist/protocol-BIv1Yuvl.js.map +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/google.d.ts +1 -1
- package/dist/providers/google.js +1 -784
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/neuralwatt.d.ts +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/openrouter.js +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +1 -101
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +6 -5
- package/dist/{registry-BBaEgTsX.js → registry-eourRLY2.js} +3 -3
- package/dist/{registry-BBaEgTsX.js.map → registry-eourRLY2.js.map} +1 -1
- package/dist/{remote-hosts-bO7wOt44.js → remote-hosts-DY2J07ut.js} +4 -4
- package/dist/{remote-hosts-bO7wOt44.js.map → remote-hosts-DY2J07ut.js.map} +1 -1
- package/dist/restate.d.ts +1 -1
- package/dist/{secret-shapes-Cda65uDH.js → secret-shapes-BjW4l6U0.js} +17 -3
- package/dist/secret-shapes-BjW4l6U0.js.map +1 -0
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/{session-factory-BazyVdzj.js → session-factory-CMwIXE-7.js} +5 -5
- package/dist/{session-factory-BazyVdzj.js.map → session-factory-CMwIXE-7.js.map} +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/{settings-keys-zYaer8DY.js → settings-keys-CPdmkTz7.js} +3 -3
- package/dist/{settings-keys-zYaer8DY.js.map → settings-keys-CPdmkTz7.js.map} +1 -1
- package/dist/{shell-path-od9XHRPt.js → shell-path-B8b3EOtK.js} +3 -3
- package/dist/{shell-path-od9XHRPt.js.map → shell-path-B8b3EOtK.js.map} +1 -1
- package/dist/{skills-use-D68a1gyZ.js → skills-use-CssTEaIj.js} +375 -2
- package/dist/skills-use-CssTEaIj.js.map +1 -0
- package/dist/skills.d.ts +1 -1
- package/dist/store-L01W0gGI.js.map +1 -1
- package/dist/{system-freeze-DXvJpveP.js → system-freeze-Um9ZJiPo.js} +24 -9
- package/dist/system-freeze-Um9ZJiPo.js.map +1 -0
- package/dist/{todo-edits-CmqNFvLJ.js → todo-edits-BERpCRPj.js} +3 -3
- package/dist/{todo-edits-CmqNFvLJ.js.map → todo-edits-BERpCRPj.js.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/prompts.d.ts +1 -1
- package/dist/tools/prompts.js +7 -0
- package/dist/tools/prompts.js.map +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/{tools-9Dpm8F-f.js → tools-pZVFIJ_K.js} +273 -2
- package/dist/tools-pZVFIJ_K.js.map +1 -0
- package/dist/tools.d.ts +3 -3
- package/dist/tools.js +4 -4
- package/dist/{transcript-anchors-B3TFJqr_.js → transcript-anchors-jHrg-r-H.js} +10 -10
- package/dist/{transcript-anchors-B3TFJqr_.js.map → transcript-anchors-jHrg-r-H.js.map} +1 -1
- package/dist/{transcript-reconcile-BC2DbTmp.js → transcript-reconcile-CPdrNbbR.js} +19 -2
- package/dist/{transcript-reconcile-BC2DbTmp.js.map → transcript-reconcile-CPdrNbbR.js.map} +1 -1
- package/dist/tui.d.ts +7 -7
- package/dist/tui.js +25 -23
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-CIFoOebZ.d.ts → turn-operations-DuGtKuc_.d.ts} +10 -3
- package/dist/turn-operations-DuGtKuc_.d.ts.map +1 -0
- package/dist/{types-iFLlZKd0.d.ts → types-C0PJmBaO.d.ts} +2 -2
- package/dist/{types-iFLlZKd0.d.ts.map → types-C0PJmBaO.d.ts.map} +1 -1
- package/dist/types-JzccL5GE.js +24 -0
- package/dist/types-JzccL5GE.js.map +1 -0
- package/dist/types.d.ts +2 -2
- package/dist/{url-BTH-HE9Y.js → url-D8KZ7Edw.js} +2 -2
- package/dist/{url-BTH-HE9Y.js.map → url-D8KZ7Edw.js.map} +1 -1
- package/dist/{version-4T82xRxQ.js → version-bd3DQJkc.js} +2 -2
- package/dist/{version-4T82xRxQ.js.map → version-bd3DQJkc.js.map} +1 -1
- package/dist/wire-DH77Z-rr.js +80 -0
- package/dist/wire-DH77Z-rr.js.map +1 -0
- package/dist/{workspace-exec-stream-By8na6vz.js → workspace-exec-stream-CyfYgqAh.js} +4 -4
- package/dist/{workspace-exec-stream-By8na6vz.js.map → workspace-exec-stream-CyfYgqAh.js.map} +1 -1
- package/dist/{write-file-B4vi3SvQ.js → write-file-QYrcDdl3.js} +3 -3
- package/dist/{write-file-B4vi3SvQ.js.map → write-file-QYrcDdl3.js.map} +1 -1
- package/dist/{ws-CS312Jpx.js → ws-CURQ2igk.js} +5 -5
- package/dist/{ws-CS312Jpx.js.map → ws-CURQ2igk.js.map} +1 -1
- package/dist/{ws-client-wWka-Jku.js → ws-client-BVljYbdb.js} +3 -3
- package/dist/{ws-client-wWka-Jku.js.map → ws-client-BVljYbdb.js.map} +1 -1
- package/dist/xai-CStTwCV2.js +182 -0
- package/dist/xai-CStTwCV2.js.map +1 -0
- package/docs/ARCHITECTURE.md +1 -0
- package/docs/ARTIFACTS.md +1 -1
- package/docs/EXTENSIONS.md +9 -5
- package/package.json +2 -2
- package/dist/agent-DecDtKA_.js.map +0 -1
- package/dist/builtin-artifact-kinds-B_OEgf8b.js.map +0 -1
- package/dist/credentials-Dti61yoi.js.map +0 -1
- package/dist/dispatcher-vy3J6JMA.js.map +0 -1
- package/dist/extensions-BKt7lxxv.js.map +0 -1
- package/dist/index-CidMTcxS.d.ts.map +0 -1
- package/dist/index-pc71ADi6.d.ts.map +0 -1
- package/dist/mcp-allowlist-BQ5MvhHi.js.map +0 -1
- package/dist/oauth-BSqXgads.js.map +0 -1
- package/dist/openai-dTmPxM6T.js.map +0 -1
- package/dist/openrouter-CtZbQDa0.js.map +0 -1
- package/dist/prompts-D2lPHLOV.d.ts.map +0 -1
- package/dist/providers/google.js.map +0 -1
- package/dist/providers/xai.js.map +0 -1
- package/dist/secret-shapes-Cda65uDH.js.map +0 -1
- package/dist/skills-use-D68a1gyZ.js.map +0 -1
- package/dist/system-freeze-DXvJpveP.js.map +0 -1
- package/dist/tools-9Dpm8F-f.js.map +0 -1
- package/dist/turn-operations-CIFoOebZ.d.ts.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials-B9DfBJP9.js","names":["CLIENT_ID","AUTHORIZE_URL","TOKEN_URL","CALLBACK_PORT","CALLBACK_PATH","SCOPES","PROVIDER_NAME","parseAuthorizationInput","exchangeAuthorizationCode","AUTHORIZE_URL","CALLBACK_PORT","CALLBACK_PATH","getModels","getModel"],"sources":["../src/chat/oauth-page/anthropic.ts","../src/chat/oauth-page/google.ts","../src/chat/oauth-page/openai-codex.ts","../src/chat/oauth-page/index.ts","../src/chat/providers.ts","../src/chat/credentials.ts"],"sourcesContent":["/**\n * Anthropic OAuth flow with a customisable callback page.\n *\n * Mirrors `loginAnthropic` from `@earendil-works/pi-ai/oauth` 1:1 except:\n *\n * 1. The HTTP callback server's response HTML routes through\n * {@link OAuthCallbackPageRenderer} instead of pi-ai's baked-in page.\n * 2. The lifecycle is delegated to {@link startCallbackServer} so the\n * Codex sibling and any future loopback provider share one HTTP impl.\n *\n * Refresh + `getApiKey` delegate to `src/providers/oauth-registry` — which\n * wraps pi-ai's canonical `auth.oauth.refresh` flow — those don't touch\n * HTML and there's no upside to forking them.\n *\n * Endpoints, client id, port and scopes match pi-ai `1.3.0`\n * (`dist/auth/oauth/anthropic.js`). Compare them again on each\n * `@earendil-works/pi-ai` upgrade. One flow difference since 1.3.0: when\n * port 53692 can't be bound, pi-ai retries on a free loopback port before\n * falling back to the pasted redirect URL; this flow rejects instead.\n */\n\nimport type {\n OAuthCredentials,\n OAuthLoginCallbacks,\n} from '@earendil-works/pi-ai/oauth'\nimport type { OAuthProviderInterface } from '../../providers/oauth-registry'\nimport type { OAuthCallbackPageRenderer } from './render'\nimport { refreshAnthropicToken } from '../../providers/oauth-registry'\nimport { generatePkce } from './pkce'\nimport { honorsRemoteCallback, listensForCallback, startCallbackServer } from './server'\n\n// Copied verbatim from pi-ai (compared at 1.3.0) — `dist/auth/oauth/anthropic.js`.\nconst CLIENT_ID = atob('OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl')\nconst AUTHORIZE_URL = 'https://claude.ai/oauth/authorize'\nconst TOKEN_URL = 'https://platform.claude.com/v1/oauth/token'\nconst CALLBACK_PORT = 53692\nconst CALLBACK_PATH = '/callback'\nconst SCOPES = 'org:create_api_key user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload'\nconst PROVIDER_NAME = 'Anthropic'\n\n/**\n * Parse what the user pasted into the manual-code prompt. Accepts:\n * - the bare authorization code\n * - the full `redirect_uri?code=...&state=...` URL\n * - the `code#state` shorthand Anthropic surfaces on the page\n * - a raw query string with `code=...&state=...`\n *\n * Matches pi-ai's parse table so an existing user's muscle memory still works.\n */\nfunction parseAuthorizationInput(input: string): { code?: string, state?: string } {\n const value = input.trim()\n if (!value)\n return {}\n\n try {\n const url = new URL(value)\n return {\n code: url.searchParams.get('code') ?? undefined,\n state: url.searchParams.get('state') ?? undefined,\n }\n }\n catch {\n // fall through to non-URL parsing below\n }\n\n if (value.includes('#')) {\n const [code, state] = value.split('#', 2)\n return { code, state }\n }\n if (value.includes('code=')) {\n const params = new URLSearchParams(value)\n return {\n code: params.get('code') ?? undefined,\n state: params.get('state') ?? undefined,\n }\n }\n return { code: value }\n}\n\nasync function postJson(url: string, body: Record<string, unknown>): Promise<string> {\n const response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Accept': 'application/json',\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(30_000),\n })\n const responseBody = await response.text()\n if (!response.ok)\n throw new Error(`HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`)\n return responseBody\n}\n\nasync function exchangeAuthorizationCode(\n code: string,\n state: string,\n verifier: string,\n redirectUri: string,\n): Promise<OAuthCredentials> {\n const responseBody = await postJson(TOKEN_URL, {\n grant_type: 'authorization_code',\n client_id: CLIENT_ID,\n code,\n state,\n redirect_uri: redirectUri,\n code_verifier: verifier,\n })\n\n const tokenData = JSON.parse(responseBody) as {\n refresh_token: string\n access_token: string\n expires_in: number\n }\n\n return {\n refresh: tokenData.refresh_token,\n access: tokenData.access_token,\n // -5min so a refresh fires before the upstream expiry; matches pi-ai.\n expires: Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000,\n }\n}\n\nexport interface LoginAnthropicWithPageOptions extends Pick<\n OAuthLoginCallbacks,\n 'onAuth' | 'onPrompt' | 'onProgress' | 'onManualCodeInput'\n> {\n renderPage: OAuthCallbackPageRenderer\n /** `false`: no loopback listener here; the redirect URL comes back through `onManualCodeInput` (a remote sign-in). */\n listen?: boolean\n}\n\nexport async function loginAnthropicWithCustomPage(\n options: LoginAnthropicWithPageOptions,\n): Promise<OAuthCredentials> {\n const { verifier, challenge } = await generatePkce()\n const server = await startCallbackServer({\n port: CALLBACK_PORT,\n path: CALLBACK_PATH,\n expectedState: verifier,\n providerName: PROVIDER_NAME,\n renderPage: options.renderPage,\n successMessage: 'You can close this tab.',\n onListenError: 'reject',\n ...(options.listen === false ? { listen: false } : {}),\n })\n\n let code: string | undefined\n let state: string | undefined\n\n try {\n const authParams = new URLSearchParams({\n code: 'true',\n client_id: CLIENT_ID,\n response_type: 'code',\n redirect_uri: server.redirectUri,\n scope: SCOPES,\n code_challenge: challenge,\n code_challenge_method: 'S256',\n state: verifier,\n })\n\n options.onAuth({\n url: `${AUTHORIZE_URL}?${authParams.toString()}`,\n instructions: 'Complete login in your browser. If the browser is on another machine, paste the final redirect URL here.',\n })\n\n if (options.onManualCodeInput) {\n let manualInput: string | undefined\n let manualError: Error | undefined\n const manualPromise = options\n .onManualCodeInput()\n .then((input) => {\n manualInput = input\n server.cancelWait()\n })\n .catch((err) => {\n manualError = err instanceof Error ? err : new Error(String(err))\n server.cancelWait()\n })\n\n const result = await server.waitForCode()\n if (manualError)\n throw manualError\n\n if (result?.code) {\n code = result.code\n state = result.state\n }\n else if (manualInput) {\n const parsed = parseAuthorizationInput(manualInput)\n if (parsed.state && parsed.state !== verifier)\n throw new Error('OAuth state mismatch')\n code = parsed.code\n state = parsed.state ?? verifier\n }\n\n if (!code) {\n await manualPromise\n if (manualError)\n throw manualError\n if (manualInput) {\n const parsed = parseAuthorizationInput(manualInput)\n if (parsed.state && parsed.state !== verifier)\n throw new Error('OAuth state mismatch')\n code = parsed.code\n state = parsed.state ?? verifier\n }\n }\n }\n else {\n const result = await server.waitForCode()\n if (result?.code) {\n code = result.code\n state = result.state\n }\n }\n\n if (!code) {\n const input = await options.onPrompt({\n message: 'Paste the authorization code or full redirect URL:',\n placeholder: server.redirectUri,\n })\n const parsed = parseAuthorizationInput(input)\n if (parsed.state && parsed.state !== verifier)\n throw new Error('OAuth state mismatch')\n code = parsed.code\n state = parsed.state ?? verifier\n }\n\n if (!code)\n throw new Error('Missing authorization code')\n if (!state)\n throw new Error('Missing OAuth state')\n\n options.onProgress?.('Exchanging authorization code for tokens...')\n return await exchangeAuthorizationCode(code, state, verifier, server.redirectUri)\n }\n finally {\n server.close()\n }\n}\n\n/**\n * Build an `OAuthProviderInterface` that behaves identically to pi-ai's\n * `anthropicOAuthProvider` except for the callback page HTML. Drop this\n * onto `ProviderDescriptor.oauthProvider` to override.\n */\nexport function createAnthropicOAuthProviderWithCustomPage(\n renderPage: OAuthCallbackPageRenderer,\n): OAuthProviderInterface {\n // Honors `callbackServer: false`: a remote sign-in binds nothing on this machine.\n return honorsRemoteCallback({\n id: 'anthropic',\n name: 'Anthropic (Claude Pro/Max)',\n usesCallbackServer: true,\n async login(callbacks: OAuthLoginCallbacks) {\n return loginAnthropicWithCustomPage({\n renderPage,\n onAuth: callbacks.onAuth,\n onPrompt: callbacks.onPrompt,\n onProgress: callbacks.onProgress,\n onManualCodeInput: callbacks.onManualCodeInput,\n listen: listensForCallback(callbacks),\n })\n },\n async refreshToken(credentials: OAuthCredentials) {\n return refreshAnthropicToken(credentials.refresh)\n },\n getApiKey(credentials: OAuthCredentials) {\n return credentials.access\n },\n })\n}\n","/**\n * \"Sign in with Google\" for Vertex AI.\n *\n * Loopback-redirect PKCE against Google's OAuth 2.0 endpoints, for a\n * Desktop-app OAuth client (Google accepts any loopback port for those).\n * Scope `cloud-platform` for Vertex AI, plus `openid email` for the account\n * label. After the token exchange the user picks the Google Cloud project the\n * grant bills: listed through Cloud Resource Manager, typed in when listing\n * isn't possible.\n *\n * The OAuth client comes from the host's environment until zidane ships a\n * verified client of its own:\n *\n * ZIDANE_GOOGLE_CLIENT_ID / ZIDANE_GOOGLE_CLIENT_SECRET\n *\n * Without both, the sign-in stays hidden; gcloud's Application Default\n * Credentials keep working through the Vertex AI project field. Google\n * documents a Desktop client's secret as not confidential. The grant stores\n * the client it was minted with anyway, because refreshing a Google refresh\n * token needs that same client id and secret. The grant's shape and its\n * refresh live in `providers/google-oauth`, which the OAuth registry seeds.\n *\n * This is Google Cloud's own OAuth (billed to the user's project, which a\n * Google AI plan's monthly Cloud credits cover), not the Antigravity or\n * Gemini CLI sign-in: Google bans those from third-party tools.\n */\n\nimport type { OAuthLoginCallbacks } from '@earendil-works/pi-ai/oauth'\nimport type { GoogleOAuthCredentials } from '../../providers/google-oauth'\nimport type { OAuthProviderInterface } from '../../providers/oauth-registry'\nimport type { OAuthCallbackPageRenderer } from './render'\nimport { Buffer } from 'node:buffer'\nimport { randomBytes } from 'node:crypto'\nimport { GOOGLE_VERTEX_OAUTH_ID, googleTokenExpiry, googleTokenRequest, refreshGoogleToken } from '../../providers/google-oauth'\nimport { generatePkce } from './pkce'\nimport { awaitAuthorizationCode, honorsRemoteCallback, listensForCallback, startCallbackServer } from './server'\n\nconst AUTHORIZE_URL = 'https://accounts.google.com/o/oauth2/v2/auth'\nconst PROJECTS_URL = 'https://cloudresourcemanager.googleapis.com/v1/projects?filter=lifecycleState%3AACTIVE&pageSize=200'\nconst SCOPES = 'https://www.googleapis.com/auth/cloud-platform openid email'\nconst CALLBACK_PORT = 56123\nconst CALLBACK_PATH = '/oauth2callback'\n\n/** The Desktop OAuth client to sign in with, from the environment. */\nexport interface GoogleOAuthClient {\n id: string\n secret: string\n}\n\n/**\n * The configured OAuth client, or `undefined` when either half is missing.\n *\n * @param env - Environment to read.\n */\nexport function googleOAuthClient(env: Record<string, string | undefined> = process.env): GoogleOAuthClient | undefined {\n const id = env.ZIDANE_GOOGLE_CLIENT_ID?.trim()\n const secret = env.ZIDANE_GOOGLE_CLIENT_SECRET?.trim()\n return id && secret ? { id, secret } : undefined\n}\n\n/** `email` claim of an OpenID id token; no verification needed, it only labels the account. */\nfunction emailOf(idToken: string | undefined): string | undefined {\n const payload = idToken?.split('.')[1]\n if (!payload)\n return undefined\n try {\n const claims = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8')) as { email?: unknown }\n return typeof claims.email === 'string' ? claims.email : undefined\n }\n catch {\n return undefined\n }\n}\n\nasync function listProjects(accessToken: string): Promise<{ id: string, name?: string }[]> {\n const response = await fetch(PROJECTS_URL, { headers: { Authorization: `Bearer ${accessToken}` } })\n if (!response.ok)\n return []\n const body = await response.json() as { projects?: { projectId?: unknown, name?: unknown }[] }\n return (body.projects ?? []).flatMap(p => typeof p.projectId === 'string'\n ? [{ id: p.projectId, ...(typeof p.name === 'string' ? { name: p.name } : {}) }]\n : [])\n}\n\n/** The project the grant bills: the only one, a pick from the list, or typed in. */\nasync function pickProject(accessToken: string, callbacks: OAuthLoginCallbacks): Promise<string> {\n const projects = await listProjects(accessToken).catch(() => [])\n if (projects.length === 1) {\n callbacks.onProgress?.(`Using Google Cloud project ${projects[0]!.id}.`)\n return projects[0]!.id\n }\n if (projects.length > 1) {\n const picked = await callbacks.onSelect({\n message: 'Google Cloud project to use for Vertex AI',\n options: projects.map(p => ({ id: p.id, label: p.name && p.name !== p.id ? `${p.name} (${p.id})` : p.id })),\n })\n if (picked)\n return picked\n }\n const typed = (await callbacks.onPrompt({\n message: 'Google Cloud project ID for Vertex AI (Vertex AI API enabled, billing on):',\n placeholder: projects[0]?.id ?? 'my-project-id',\n })).trim()\n if (!typed)\n throw new Error('Vertex AI needs a Google Cloud project.')\n return typed\n}\n\n/**\n * Run the browser sign-in and return the grant to persist.\n *\n * @param callbacks - Login callbacks: browser hand-off, prompts, project pick.\n * @param renderPage - Renderer for the page the browser lands on.\n * @param client - OAuth client to sign in with. Defaults to the environment's.\n */\nexport async function loginGoogle(\n callbacks: OAuthLoginCallbacks,\n renderPage: OAuthCallbackPageRenderer,\n client = googleOAuthClient(),\n): Promise<GoogleOAuthCredentials> {\n if (!client)\n throw new Error('Sign in with Google needs an OAuth client: set ZIDANE_GOOGLE_CLIENT_ID and ZIDANE_GOOGLE_CLIENT_SECRET (a Desktop app client from the Google Cloud console), or use gcloud Application Default Credentials with a project instead.')\n const { verifier, challenge } = await generatePkce()\n const state = randomBytes(16).toString('hex')\n const server = await startCallbackServer({\n port: CALLBACK_PORT,\n path: CALLBACK_PATH,\n expectedState: state,\n providerName: 'Google',\n renderPage,\n successMessage: 'You can close this tab.',\n onListenError: 'reject',\n ...(listensForCallback(callbacks) ? {} : { listen: false }),\n })\n try {\n const url = new URL(AUTHORIZE_URL)\n url.searchParams.set('client_id', client.id)\n url.searchParams.set('redirect_uri', server.redirectUri)\n url.searchParams.set('response_type', 'code')\n url.searchParams.set('scope', SCOPES)\n url.searchParams.set('code_challenge', challenge)\n url.searchParams.set('code_challenge_method', 'S256')\n url.searchParams.set('state', state)\n // A refresh token is only issued for offline access, and only again on consent.\n url.searchParams.set('access_type', 'offline')\n url.searchParams.set('prompt', 'consent')\n callbacks.onAuth({\n url: url.toString(),\n instructions: 'Complete Google sign-in in your browser. If the browser is on another machine, paste the final redirect URL here.',\n })\n\n const code = await awaitAuthorizationCode(server, state, callbacks)\n callbacks.onProgress?.('Exchanging authorization code for tokens...')\n const tokens = await googleTokenRequest({\n client_id: client.id,\n client_secret: client.secret,\n code,\n code_verifier: verifier,\n grant_type: 'authorization_code',\n redirect_uri: server.redirectUri,\n }, callbacks.signal)\n if (!tokens.refresh_token)\n throw new Error('Google returned no refresh token. Sign in again and grant offline access.')\n const projectId = await pickProject(tokens.access_token, callbacks)\n const email = emailOf(tokens.id_token)\n return {\n access: tokens.access_token,\n refresh: tokens.refresh_token,\n expires: googleTokenExpiry(tokens.expires_in),\n projectId,\n clientId: client.id,\n clientSecret: client.secret,\n ...(email ? { email } : {}),\n }\n }\n finally {\n server.close()\n }\n}\n\n/**\n * Build the \"Sign in with Google\" `OAuthProviderInterface` for Vertex AI,\n * themed through `renderPage`. Honors `callbackServer: false` (a remote\n * sign-in binds nothing on this machine).\n *\n * @param renderPage - Renderer for the page the browser lands on.\n */\nexport function createGoogleOAuthProvider(renderPage: OAuthCallbackPageRenderer): OAuthProviderInterface {\n return honorsRemoteCallback({\n id: GOOGLE_VERTEX_OAUTH_ID,\n name: 'Google (Vertex AI)',\n usesCallbackServer: true,\n login: (callbacks: OAuthLoginCallbacks) => loginGoogle(callbacks, renderPage),\n refreshToken: refreshGoogleToken,\n getApiKey: credentials => credentials.access,\n })\n}\n","/**\n * OpenAI Codex (ChatGPT Plus/Pro) OAuth flow with a customisable callback\n * page. 1:1 mirror of pi-ai's `loginOpenAICodex` (endpoints compared at\n * `1.3.0`, `dist/auth/oauth/openai-codex.js`) except the HTTP callback\n * server routes through {@link OAuthCallbackPageRenderer}.\n *\n * Refresh delegates to `refreshOpenAICodexToken` in\n * `src/providers/oauth-registry`, which wraps pi-ai's canonical\n * `auth.oauth.refresh` flow — Codex's refresh path involves JWT decoding for\n * `accountId`, and we don't want to duplicate it. The HTML override is\n * purely about the landing page.\n */\n\nimport type {\n OAuthCredentials,\n OAuthLoginCallbacks,\n} from '@earendil-works/pi-ai/oauth'\nimport type { OAuthProviderInterface } from '../../providers/oauth-registry'\nimport type { OAuthCallbackPageRenderer } from './render'\nimport { Buffer } from 'node:buffer'\nimport { randomBytes } from 'node:crypto'\nimport { refreshOpenAICodexToken } from '../../providers/oauth-registry'\nimport { generatePkce } from './pkce'\nimport { honorsRemoteCallback, listensForCallback, startCallbackServer } from './server'\n\n// Copied verbatim from pi-ai (compared at 1.3.0) — `dist/auth/oauth/openai-codex.js`.\nconst CLIENT_ID = 'app_EMoamEEZ73f0CkXaXp7hrann'\nconst AUTHORIZE_URL = 'https://auth.openai.com/oauth/authorize'\nconst TOKEN_URL = 'https://auth.openai.com/oauth/token'\nconst CALLBACK_PORT = 1455\nconst CALLBACK_PATH = '/auth/callback'\nconst SCOPE = 'openid profile email offline_access'\nconst JWT_CLAIM_PATH = 'https://api.openai.com/auth'\nconst PROVIDER_NAME = 'OpenAI'\n\nfunction createState(): string {\n return randomBytes(16).toString('hex')\n}\n\nfunction parseAuthorizationInput(input: string): { code?: string, state?: string } {\n const value = input.trim()\n if (!value)\n return {}\n\n try {\n const url = new URL(value)\n return {\n code: url.searchParams.get('code') ?? undefined,\n state: url.searchParams.get('state') ?? undefined,\n }\n }\n catch {\n // fall through\n }\n\n if (value.includes('#')) {\n const [code, state] = value.split('#', 2)\n return { code, state }\n }\n if (value.includes('code=')) {\n const params = new URLSearchParams(value)\n return {\n code: params.get('code') ?? undefined,\n state: params.get('state') ?? undefined,\n }\n }\n return { code: value }\n}\n\ninterface JwtPayload {\n [key: string]: unknown\n [JWT_CLAIM_PATH]?: { chatgpt_account_id?: string }\n}\n\nfunction decodeJwt(token: string): JwtPayload | null {\n try {\n const parts = token.split('.')\n if (parts.length !== 3)\n return null\n const payload = parts[1] ?? ''\n // JWT segments are base64url (RFC 7515) — `-`/`_` alphabet, no padding.\n // `atob` expects standard base64 and throws on those chars, which made\n // extraction fail for perfectly valid tokens whose payload happened to\n // contain them. `Buffer` handles both alphabets and missing padding.\n const decoded = Buffer.from(payload, 'base64url').toString('utf8')\n return JSON.parse(decoded) as JwtPayload\n }\n catch {\n return null\n }\n}\n\nfunction getAccountId(accessToken: string): string | null {\n const payload = decodeJwt(accessToken)\n const claim = payload?.[JWT_CLAIM_PATH] as { chatgpt_account_id?: string } | undefined\n const accountId = claim?.chatgpt_account_id\n return typeof accountId === 'string' && accountId.length > 0 ? accountId : null\n}\n\ninterface TokenExchangeSuccess {\n type: 'success'\n access: string\n refresh: string\n expires: number\n}\n\ninterface TokenExchangeFailure {\n type: 'failed'\n message: string\n}\n\nasync function exchangeAuthorizationCode(\n code: string,\n verifier: string,\n redirectUri: string,\n): Promise<TokenExchangeSuccess | TokenExchangeFailure> {\n const response = await fetch(TOKEN_URL, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'authorization_code',\n client_id: CLIENT_ID,\n code,\n code_verifier: verifier,\n redirect_uri: redirectUri,\n }),\n })\n\n if (!response.ok) {\n const text = await response.text().catch(() => '')\n return {\n type: 'failed',\n message: `OpenAI Codex token exchange failed (${response.status}): ${text || response.statusText}`,\n }\n }\n\n const json = await response.json() as {\n access_token?: string\n refresh_token?: string\n expires_in?: number\n }\n if (!json.access_token || !json.refresh_token || typeof json.expires_in !== 'number') {\n return {\n type: 'failed',\n message: `OpenAI Codex token exchange response missing fields: ${JSON.stringify(json)}`,\n }\n }\n return {\n type: 'success',\n access: json.access_token,\n refresh: json.refresh_token,\n expires: Date.now() + json.expires_in * 1000,\n }\n}\n\nexport interface LoginOpenAICodexWithPageOptions extends Pick<\n OAuthLoginCallbacks,\n 'onAuth' | 'onPrompt' | 'onProgress' | 'onManualCodeInput'\n> {\n renderPage: OAuthCallbackPageRenderer\n /** OAuth `originator` parameter. Defaults to `\"pi\"` to stay observable upstream. */\n originator?: string\n /** `false`: no loopback listener here; the redirect URL comes back through `onManualCodeInput` (a remote sign-in). */\n listen?: boolean\n}\n\nexport async function loginOpenAICodexWithCustomPage(\n options: LoginOpenAICodexWithPageOptions,\n): Promise<OAuthCredentials> {\n const { verifier, challenge } = await generatePkce()\n const state = createState()\n const originator = options.originator ?? 'pi'\n\n const server = await startCallbackServer({\n port: CALLBACK_PORT,\n path: CALLBACK_PATH,\n expectedState: state,\n providerName: PROVIDER_NAME,\n renderPage: options.renderPage,\n successMessage: 'You can close this tab.',\n // Matches pi-ai: Codex falls back to manual paste on port collision.\n onListenError: 'resolveWithStub',\n ...(options.listen === false ? { listen: false } : {}),\n })\n\n const authUrl = new URL(AUTHORIZE_URL)\n authUrl.searchParams.set('response_type', 'code')\n authUrl.searchParams.set('client_id', CLIENT_ID)\n authUrl.searchParams.set('redirect_uri', server.redirectUri)\n authUrl.searchParams.set('scope', SCOPE)\n authUrl.searchParams.set('code_challenge', challenge)\n authUrl.searchParams.set('code_challenge_method', 'S256')\n authUrl.searchParams.set('state', state)\n authUrl.searchParams.set('id_token_add_organizations', 'true')\n authUrl.searchParams.set('codex_cli_simplified_flow', 'true')\n authUrl.searchParams.set('originator', originator)\n\n options.onAuth({\n url: authUrl.toString(),\n instructions: 'A browser window should open. Complete login to finish.',\n })\n\n let code: string | undefined\n\n try {\n if (options.onManualCodeInput) {\n let manualCode: string | undefined\n let manualError: Error | undefined\n const manualPromise = options\n .onManualCodeInput()\n .then((input) => {\n manualCode = input\n server.cancelWait()\n })\n .catch((err) => {\n manualError = err instanceof Error ? err : new Error(String(err))\n server.cancelWait()\n })\n\n const result = await server.waitForCode()\n if (manualError)\n throw manualError\n\n if (result?.code) {\n code = result.code\n }\n else if (manualCode) {\n const parsed = parseAuthorizationInput(manualCode)\n if (parsed.state && parsed.state !== state)\n throw new Error('State mismatch')\n code = parsed.code\n }\n\n if (!code) {\n await manualPromise\n if (manualError)\n throw manualError\n if (manualCode) {\n const parsed = parseAuthorizationInput(manualCode)\n if (parsed.state && parsed.state !== state)\n throw new Error('State mismatch')\n code = parsed.code\n }\n }\n }\n else {\n const result = await server.waitForCode()\n if (result?.code)\n code = result.code\n }\n\n if (!code) {\n const input = await options.onPrompt({\n message: 'Paste the authorization code (or full redirect URL):',\n })\n const parsed = parseAuthorizationInput(input)\n if (parsed.state && parsed.state !== state)\n throw new Error('State mismatch')\n code = parsed.code\n }\n\n if (!code)\n throw new Error('Missing authorization code')\n\n const tokenResult = await exchangeAuthorizationCode(code, verifier, server.redirectUri)\n if (tokenResult.type !== 'success')\n throw new Error(tokenResult.message)\n\n const accountId = getAccountId(tokenResult.access)\n if (!accountId)\n throw new Error('Failed to extract accountId from token')\n\n return {\n access: tokenResult.access,\n refresh: tokenResult.refresh,\n expires: tokenResult.expires,\n accountId,\n }\n }\n finally {\n server.close()\n }\n}\n\n/**\n * Build an `OAuthProviderInterface` that behaves identically to pi-ai's\n * `openaiCodexOAuthProvider` except for the callback page HTML.\n */\nexport function createOpenAICodexOAuthProviderWithCustomPage(\n renderPage: OAuthCallbackPageRenderer,\n): OAuthProviderInterface {\n // Honors `callbackServer: false`: a remote sign-in binds nothing on this machine.\n return honorsRemoteCallback({\n id: 'openai-codex',\n name: 'ChatGPT Plus/Pro (Codex Subscription)',\n usesCallbackServer: true,\n async login(callbacks: OAuthLoginCallbacks) {\n return loginOpenAICodexWithCustomPage({\n renderPage,\n onAuth: callbacks.onAuth,\n onPrompt: callbacks.onPrompt,\n onProgress: callbacks.onProgress,\n onManualCodeInput: callbacks.onManualCodeInput,\n listen: listensForCallback(callbacks),\n })\n },\n async refreshToken(credentials: OAuthCredentials) {\n return refreshOpenAICodexToken(credentials.refresh)\n },\n getApiKey(credentials: OAuthCredentials) {\n return credentials.access\n },\n })\n}\n","/**\n * Custom OAuth callback page — drop-in replacements for pi-ai's built-in\n * Anthropic + OpenAI Codex providers that route the post-redirect HTML\n * through your own renderer.\n *\n * Why this module exists\n * ----------------------\n * `@earendil-works/pi-ai` (checked at `1.3.0`) bakes its callback page\n * into its Anthropic / OpenAI Codex login flows with no override, so this\n * module forks the two flows in one self-contained place — everything else\n * (token refresh, `getApiKey`, env handling) delegates back to pi-ai's\n * canonical flows via `src/providers/oauth-registry` unchanged. The pi-ai\n * OAuth architecture is `Provider.auth.oauth` + `AuthInteraction`. pi-ai\n * removed its `OAuthLoginCallbacks` registry surface in `0.80.8`, so\n * `src/providers/oauth-registry.ts` reproduces it locally.\n *\n * How to use\n * ----------\n *\n * ```ts\n * import { createCustomCallbackOAuthProviders, renderDefaultCallbackPage } from './chat/oauth-page'\n * import { BUILTIN_PROVIDERS } from './chat/providers'\n *\n * const { anthropic, openaiCodex } = createCustomCallbackOAuthProviders(renderDefaultCallbackPage)\n *\n * const providers = {\n * ...BUILTIN_PROVIDERS,\n * anthropic: { ...BUILTIN_PROVIDERS.anthropic, oauthProvider: anthropic },\n * openai: { ...BUILTIN_PROVIDERS.openai, oauthProvider: openaiCodex },\n * }\n * ```\n *\n * Or override per provider with `createAnthropicOAuthProviderWithCustomPage`\n * / `createOpenAICodexOAuthProviderWithCustomPage` directly.\n *\n * Deleting this module\n * --------------------\n * Deleting it means adopting pi-ai's canonical `Provider.auth.oauth` +\n * `CredentialStore` architecture in place of `src/providers/oauth.ts`'s\n * credential handling — see `src/providers/oauth-registry.ts` for the seam.\n *\n * Endpoints match pi-ai `1.3.0`. Compare endpoints + ports on every pi-ai\n * bump (auth URLs, client IDs, callback ports are duplicated verbatim here;\n * see `anthropic.ts` and `openai-codex.ts` for the source-of-truth\n * pointers).\n */\n\nimport type { OAuthProviderInterface } from '../../providers/oauth-registry'\nimport type { OAuthCallbackPageRenderer } from './render'\nimport { registerOAuthProvider } from '../../providers/oauth-registry'\nimport { createAnthropicOAuthProviderWithCustomPage } from './anthropic'\nimport { createCursorOAuthProvider } from './cursor'\nimport { createGoogleOAuthProvider } from './google'\nimport { createOpenAICodexOAuthProviderWithCustomPage } from './openai-codex'\nimport { createXaiOAuthProvider } from './xai'\n\nexport type {\n LoginAnthropicWithPageOptions,\n} from './anthropic'\nexport {\n createAnthropicOAuthProviderWithCustomPage,\n loginAnthropicWithCustomPage,\n} from './anthropic'\nexport {\n createCursorOAuthProvider,\n CURSOR_OAUTH_PROVIDER_ID,\n loginCursor,\n refreshCursorToken,\n} from './cursor'\nexport {\n createGoogleOAuthProvider,\n googleOAuthClient,\n loginGoogle,\n} from './google'\nexport type { GoogleOAuthClient } from './google'\nexport type {\n LoginOpenAICodexWithPageOptions,\n} from './openai-codex'\nexport {\n createOpenAICodexOAuthProviderWithCustomPage,\n loginOpenAICodexWithCustomPage,\n} from './openai-codex'\nexport type { PkcePair } from './pkce'\nexport { generatePkce } from './pkce'\nexport type {\n OAuthCallbackPage,\n OAuthCallbackPageRenderer,\n} from './render'\nexport {\n escapeHtmlForCallbackPage,\n renderDefaultCallbackPage,\n} from './render'\n// The loopback/paste building blocks, for flows outside the core (`zidane/oauth`).\nexport type { CallbackServerHandle, CallbackServerOptions, ZidaneOAuthLoginCallbacks } from './server'\nexport { awaitAuthorizationCode, canSignInRemotely, listensForCallback, parseRedirectInput, startCallbackServer } from './server'\nexport {\n createXaiOAuthProvider,\n loginXai,\n refreshXaiToken,\n XAI_OAUTH_PROVIDER_ID,\n xaiBaseUrl,\n} from './xai'\nexport type { XaiOAuthCredentials } from './xai'\n\nexport interface CustomCallbackOAuthProviders {\n anthropic: OAuthProviderInterface\n openaiCodex: OAuthProviderInterface\n}\n\n/**\n * Bundle helper — returns both Anthropic + OpenAI Codex providers wired\n * with the same renderer. Hosts that want different renderers per provider\n * should call the individual `create…WithCustomPage` factories instead.\n */\nexport function createCustomCallbackOAuthProviders(\n renderPage: OAuthCallbackPageRenderer,\n): CustomCallbackOAuthProviders {\n return {\n anthropic: createAnthropicOAuthProviderWithCustomPage(renderPage),\n openaiCodex: createOpenAICodexOAuthProviderWithCustomPage(renderPage),\n }\n}\n\nlet cursorRegistered = false\n\n/**\n * Register Cursor with pi-ai's OAuth registry.\n *\n * Unlike Anthropic / Codex, Cursor is **not** built into pi-ai, so\n * `getOAuthApiKey('cursor', …)` (used by `resolveOAuthApiKey` for lazy\n * token refresh) would throw \"Unknown OAuth provider\" until we register it.\n * Call once at startup from both the CLI auth path and the TUI. Idempotent.\n */\nexport function registerCursorOAuthProvider(): OAuthProviderInterface {\n const provider = createCursorOAuthProvider()\n if (!cursorRegistered) {\n registerOAuthProvider(provider)\n cursorRegistered = true\n }\n return provider\n}\n\nlet googleRegistered = false\n\n/**\n * Register \"Sign in with Google\" (Vertex AI) with the OAuth registry,\n * replacing the refresh-only seed with the interactive flow themed through\n * `renderPage`. Call once at startup; idempotent.\n */\nexport function registerGoogleOAuthProvider(\n renderPage: OAuthCallbackPageRenderer,\n): OAuthProviderInterface {\n const provider = createGoogleOAuthProvider(renderPage)\n if (!googleRegistered) {\n registerOAuthProvider(provider)\n googleRegistered = true\n }\n return provider\n}\n\nlet xaiRegistered = false\n\n/**\n * Register xAI Grok with pi-ai's OAuth registry.\n *\n * pi-ai ships an xAI *API-key* provider, but no OAuth one — so\n * `getOAuthApiKey('xai-oauth', …)` (lazy refresh in `resolveOAuthApiKey`)\n * would throw \"Unknown OAuth provider\" until we register our flow. The\n * callback page routes through the supplied renderer so the post-redirect\n * HTML matches zidane's theme. Call once at startup; idempotent.\n */\nexport function registerXaiOAuthProvider(\n renderPage: OAuthCallbackPageRenderer,\n): OAuthProviderInterface {\n const provider = createXaiOAuthProvider(renderPage)\n if (!xaiRegistered) {\n registerOAuthProvider(provider)\n xaiRegistered = true\n }\n return provider\n}\n","/**\n * Provider registry — the customization seam for the TUI.\n *\n * A {@link ProviderDescriptor} carries everything the TUI needs to know about\n * a provider in one place: how to instantiate it, what to show in the UI,\n * how to detect credentials, how to OAuth (if applicable), and where to look\n * up its models. Hosts can ship their own descriptors instead of the built-in\n * ones — see {@link BUILTIN_PROVIDERS}.\n */\n\nimport type { ImageModelInfo, Provider } from '../providers'\nimport type { ModelCatalogEntry, ModelTier } from '../providers/model-catalog'\nimport type { OAuthProviderInterface } from '../providers/oauth-registry'\nimport type { ProviderCredential } from './credentials'\nimport type { ProviderUsageCredits, ProviderUsageWindow } from './provider-usage-format'\nimport { getBuiltinModel as getModel, getBuiltinModels as getModels } from '@earendil-works/pi-ai/providers/all'\nimport { anthropic, arcee, baseten, cerebras, cursor, google, googleVertex, local, mistral, openai, openrouter, xai, zai } from '../providers'\nimport { ANTHROPIC_DECISION_MODELS } from '../providers/anthropic-decisions'\nimport { GOOGLE_DEFAULT_MODEL, GOOGLE_EXTRA_MODELS } from '../providers/google'\nimport { GOOGLE_IMAGE_MODELS, OPENAI_IMAGE_MODELS, openrouterImageModels, XAI_IMAGE_MODELS } from '../providers/images'\nimport { listModelOverlay, listModels, lookupModel, mergeCatalogEntry } from '../providers/model-catalog'\nimport { neuralwatt, NEURALWATT_DEFAULT_MODEL } from '../providers/neuralwatt'\nimport { OPENAI_DECISION_MODELS } from '../providers/openai-decisions'\nimport { OPENROUTER_DEFAULT_MODEL } from '../providers/openrouter'\nimport { OPENROUTER_DECISION_MODELS } from '../providers/openrouter-decisions'\nimport { ANTHROPIC_EXTRA_MODELS, DEFAULT_MODEL_PICK, FAST_MODE_OPTIONS } from './anthropic-models'\nimport { modelDisplayName } from './model-name'\nimport { createCustomCallbackOAuthProviders, googleOAuthClient, registerCursorOAuthProvider, registerGoogleOAuthProvider, registerXaiOAuthProvider, renderDefaultCallbackPage } from './oauth-page'\n\n/**\n * pi-ai's stock Anthropic + Codex OAuth providers bake their own callback\n * HTML; we route both through `renderDefaultCallbackPage` so the post-redirect\n * page matches zidane's theme. The override lives in `src/chat/oauth-page/`\n * — see that folder's `index.ts` for the deletion path once pi-ai exposes\n * a `renderCallbackPage` hook upstream.\n */\nconst { anthropic: anthropicOAuthProvider, openaiCodex: openaiCodexOAuthProvider }\n = createCustomCallbackOAuthProviders(renderDefaultCallbackPage)\n\n/**\n * Cursor isn't built into pi-ai, so registering it makes lazy token refresh\n * (`getOAuthApiKey('cursor', …)` inside `resolveOAuthApiKey`) resolve to our\n * Cursor flow. The poll-based login has no callback server, so no themed page.\n */\nconst cursorOAuthProvider = registerCursorOAuthProvider()\n\n/**\n * xAI Grok isn't built into pi-ai's OAuth registry (only its API-key provider\n * is), so register our loopback-PKCE flow — themed via `renderDefaultCallbackPage`\n * — so lazy token refresh resolves through it.\n */\nconst xaiOAuthProvider = registerXaiOAuthProvider(renderDefaultCallbackPage)\n\n/** \"Sign in with Google\" for Vertex AI, themed like the others. */\nconst googleOAuthProvider = registerGoogleOAuthProvider(renderDefaultCallbackPage)\n\n/**\n * Structural model metadata — compatible with pi-ai's `Model` interface but\n * not coupled to it, so hosts can pass either pi-ai-shaped objects or a\n * custom registry of their own.\n *\n * Deliberately a structural duplicate of pi-ai's `Model` rather than a\n * re-export: keeps the public API stable when pi-ai bumps shape, and lets\n * hosts implement their own registry without depending on pi-ai's types.\n *\n * Lives here (rather than `./config`) because `ProviderDescriptor.models`\n * needs it — defining it in `./config` would create an import cycle.\n */\nexport interface ModelInfo {\n /** Model id as the provider's API names it. */\n id: string\n /** Display name. */\n name?: string\n /** Maximum context window in tokens. */\n contextWindow: number\n /** Maximum output tokens. */\n maxTokens?: number\n /** Whether the model exposes a reasoning knob. */\n reasoning?: boolean\n /** Input modalities the model accepts. */\n input?: readonly ('text' | 'image')[]\n /** Rates in USD per million tokens. */\n cost?: { input: number, output: number, cacheRead?: number, cacheWrite?: number }\n /** Catalog provider id the model belongs to. */\n provider?: string\n /** Size class within the provider's lineup; unset = derived from the id (`modelTier`). */\n tier?: ModelTier\n /**\n * Model-specific toggleable knobs surfaced in the UI (e.g. Anthropic's\n * \"fast mode\"). Each option is an independent boolean the user flips on the\n * active model; enabled options are collected into `StreamOptions.modelOptions`\n * keyed by {@link ModelOption.id} and applied to the wire by the provider.\n * Omitted / empty → the model has no custom options and the picker is hidden.\n */\n options?: readonly ModelOption[]\n}\n\n/**\n * A single toggleable model option. Declarative metadata only — the provider\n * owns the actual request-body translation (keyed on {@link id}). Kept generic\n * (not \"fast mode\"-specific) so new per-model knobs land without a type change.\n */\nexport interface ModelOption {\n /** Stable identifier; the key under which the toggle persists + reaches the provider. */\n id: string\n /** Short label shown in the picker (e.g. \"Fast mode\"). */\n label: string\n /** One-line description of the trade-off (shown in the picker row). */\n description?: string\n /**\n * Optional cost multipliers applied to the model's base rates while the\n * option is enabled. `{ input: 2, output: 2 }` doubles both. Used by the\n * cost estimator so the footer reflects premium-priced modes (fast mode).\n */\n costMultiplier?: { input?: number, output?: number, cacheRead?: number, cacheWrite?: number }\n}\n\n/**\n * Free-form configuration field that a provider needs the user to supply\n * alongside (or instead of) an API key — e.g. a self-hosted base URL, an\n * Azure deployment name, a default model id.\n *\n * The wizard prompts for each field in order. Submitted values are persisted\n * into the apikey credential (as `customFields[key]`) and mirrored into\n * `process.env[envVar]` so the provider's factory can read them via the same\n * env-var convention as `envKey`.\n *\n * Descriptors without an `envKey` use `customFields` as the sole credential\n * mechanism — the wizard skips its API-key step in that case.\n */\nexport interface CustomField {\n /** Storage key inside the credential's `customFields` record. */\n key: string\n /** Human-readable label shown in the wizard step's title. */\n label: string\n /** Env var name to mirror this field into at TUI launch + on submit. */\n envVar: string\n /** Optional placeholder shown in the wizard input. */\n placeholder?: string\n /** Optional helper copy rendered above the input. */\n hint?: string\n /** When true, an empty submission is rejected by the wizard. Default: false. */\n required?: boolean\n}\n\n/**\n * What a provider instance is built FOR beyond its defaults: one stored\n * account of the provider instead of the active one. Built by the host from a\n * session's pinned account (`credentials.providerFactoryOptions`): an OAuth\n * account rides as `account` (resolved to its slot on every token read), an\n * API-key account as its `apiKey`.\n */\nexport interface ProviderFactoryOptions {\n /** Stable id of the OAuth account to run on (`ProviderCredential.id`). */\n account?: string\n /** The API key to run on, for an API-key account. */\n apiKey?: string\n}\n\n/** What a {@link ProviderUsageProbe} reports; the host stamps identity and time. */\nexport interface ProviderUsageReport {\n /** Outcome. Default `'ok'`. */\n status?: 'ok' | 'unauthorized' | 'unavailable'\n /** Plan name, when the provider reports one. */\n plan?: string | null\n /** Rate-limit or quota windows. `usedPercent` is clamped to 0..100. */\n windows?: readonly ProviderUsageWindow[]\n /** Credit balance, for pay-as-you-go plans. */\n credits?: ProviderUsageCredits | null\n /** Short failure reason when `status` isn't `ok`. */\n error?: string | null\n /** A short hint shown under the windows. */\n note?: string\n}\n\n/** A provider's own subscription-usage probe (see {@link ProviderDescriptor.usage}). */\nexport interface ProviderUsageProbe {\n /** Kind of stored credential the probe authenticates with. @default 'oauth' */\n credentialKind?: ProviderCredential['kind']\n /**\n * Report usage for one stored credential: an OAuth grant as stored (access\n * token unexpired, extra fields included) or an API key. A throw, or no\n * answer within 15s, reads as `unavailable` with the error's message.\n *\n * @param credential - The credential to probe with.\n * @param signal - Aborts at the deadline.\n */\n fetch: (credential: ProviderCredential, signal: AbortSignal) => Promise<ProviderUsageReport>\n}\n\n/** Describes one provider: how to build it, how it authenticates and which models it offers. */\nexport interface ProviderDescriptor {\n /**\n * Unique identifier. Used as the registry key, persisted in `state.json`\n * as the resumed provider, and (by default) as the credential-file key.\n */\n key: string\n /** Display name shown in the TUI's provider picker and labels. */\n label: string\n /**\n * One line on what the provider serves and how it signs in, shown under\n * its name in provider pickers (the setup wizard, Settings › Accounts).\n * Example: `'Claude models. Your Claude plan, or an API key.'`.\n */\n description?: string\n /**\n * The account a browser sign-in uses, as a button names it: `Sign in with\n * <signInLabel>` (`'Claude'`, `'ChatGPT'`). Defaults to {@link label}.\n */\n signInLabel?: string\n /**\n * Factory that builds a fresh `Provider` instance. Called on every session\n * activation. Some factories (e.g. zidane's built-in `anthropic`) eagerly\n * resolve credentials at construction time and throw when none are\n * configured — set {@link defaultModel} on the descriptor to avoid the TUI\n * calling the factory before the user has picked + authed a provider.\n */\n factory: (options?: ProviderFactoryOptions) => Provider\n /**\n * The factory honors {@link ProviderFactoryOptions}: an instance can run on\n * any of the provider's stored accounts. Pickers only offer an account\n * choice for these providers, and the host only pins one for them — a\n * factory that ignored the options would bill the active account instead.\n */\n accounts?: boolean\n /**\n * Default model id to seed the picker with. When omitted, the TUI falls\n * back to `descriptor.factory().meta.defaultModel`, which constructs the\n * provider — fine for lazy-credential factories, but breaks for factories\n * that throw on missing credentials before the wizard runs. Setting this\n * eagerly lets the TUI render the auth wizard without ever instantiating\n * the provider.\n */\n defaultModel?: string\n /**\n * Env var checked when detecting whether the user has an API key\n * configured for this provider. Optional — set to `undefined` when the\n * provider only supports OAuth (or only credentials via a custom path).\n */\n envKey?: string\n /**\n * Key under which credentials live in `credentials.json`. Defaults to\n * `key`. Built-ins that override it: OpenAI (`openai-codex`, the key the\n * harness provider looks up) and xAI (`xai-oauth`).\n */\n credentialFileKey?: string\n /** Placeholder shown in the wizard's API-key input. */\n apiKeyPlaceholder?: string\n /**\n * pi-ai (or compat) OAuth provider. When present, the wizard offers an\n * OAuth option in addition to API key.\n */\n oauthProvider?: OAuthProviderInterface\n /**\n * Optional copy appended to the wizard's \"OAuth\" method description.\n * Use to communicate why a user might pick OAuth (e.g. subscription tier,\n * org-wide SSO). Shown after `browser-based sign-in`. Skip the leading\n * space — the wizard adds it. Example: `'Claude Pro/Max subscription'`.\n */\n oauthHint?: string\n /**\n * pi-ai provider id used to look up models in pi-ai's built-in registry.\n * Defaults to `key`. Only Codex differs (`openai` → `openai-codex`).\n */\n piProviderId?: string\n /**\n * Back-compat aliases for persisted model ids whose upstream slug changed.\n * Used for metadata lookups only; aliases are not surfaced as picker rows.\n */\n modelAliases?: Readonly<Record<string, string>>\n /**\n * Override the model list returned for this provider's picker. When set,\n * skips pi-ai's registry entirely. Useful for hosts maintaining their\n * own model catalogue or for custom providers pi-ai doesn't know about.\n */\n models?: readonly ModelInfo[]\n /**\n * Additional free-form fields the wizard should collect from the user\n * (e.g. base URL for a self-hosted endpoint, default model slug for a\n * provider with no fixed catalogue). Each field is persisted in the\n * apikey credential's `customFields` map and mirrored into the matching\n * `envVar` at TUI launch.\n *\n * When `envKey` is also set, the wizard collects custom fields **before**\n * the API key. When `envKey` is omitted, the wizard skips the API-key\n * step entirely — `customFields` becomes the sole credential mechanism\n * (used by the `local` provider, which authenticates via baseURL only).\n */\n customFields?: readonly CustomField[]\n /**\n * Extra models merged AHEAD of pi-ai's registry list (de-duped by id, pi-ai\n * wins on collision). Unlike {@link models} this augments rather than\n * replaces — used to surface freshly-shipped models pi-ai hasn't bundled\n * yet without losing the rest of the registry. Ignored when {@link models}\n * is set.\n */\n extraModels?: readonly ModelInfo[]\n /**\n * Resolve the custom {@link ModelOption}s a given model id supports. Used to\n * attach options (e.g. fast mode) to models that come from pi-ai's registry —\n * which {@link extraModels} can't reach because pi-ai wins the id collision.\n * Returns `undefined` / `[]` for models with no options. Models that already\n * carry `options` (e.g. via {@link extraModels}) keep theirs.\n */\n optionsFor?: (modelId: string) => readonly ModelOption[] | undefined\n /**\n * Env var holding a user-supplied context window (in tokens) for providers\n * that have no model registry to advertise one — chiefly the `local`\n * provider, whose runtime (Ollama, vLLM, …) doesn't expose its loaded\n * model's window over the OpenAI-compat API. When set, {@link getContextWindow}\n * falls back to resolving this env var (via {@link resolveContextWindow})\n * after the registry lookup comes up empty. The value is either a single\n * window (`\"32768\"`, applied to every model) or a per-model map\n * (`\"llama3.1:8b=32768, qwen=128k, 64k\"`, with an optional bare fallback).\n * Pair it with a {@link CustomField} that mirrors the user's value into the\n * same `envVar` so the footer's context indicator and auto-compaction work\n * for local models.\n */\n contextWindowEnvVar?: string\n /**\n * Decision models the provider's native Decisions endpoint serves\n * (`Provider.decisions`), listed by the settings' decision-model picker.\n * Omit for providers without one.\n */\n decisionModels?: readonly string[]\n /**\n * Image models the provider's image endpoint serves (`Provider.images`),\n * listed by the model picker and the `generate_image` tool. Omit for\n * providers without one.\n */\n imageModels?: readonly ImageModelInfo[]\n /**\n * Subscription-usage probe, for a provider without a built-in one (an\n * extension's). Runs through the built-ins' pipeline: the user's\n * subscription-usage setting and `ZIDANE_NO_USAGE_CHECK`, one probe per\n * stored credential of `credentialKind` (every account), expired OAuth\n * tokens renewed in their own slot first, a one-minute cache, and the last\n * good snapshot kept through a transient failure. Ignored when the\n * credential key has a built-in probe.\n */\n usage?: ProviderUsageProbe\n}\n\n/**\n * Convenience accessor — returns `credentialFileKey ?? key`.\n *\n * @param desc - The provider descriptor.\n */\nexport function credKeyOf(desc: ProviderDescriptor): string {\n return desc.credentialFileKey ?? desc.key\n}\n\n/**\n * Convenience accessor — returns `piProviderId ?? key`.\n *\n * @param desc - The provider descriptor.\n */\nexport function piIdOf(desc: ProviderDescriptor): string {\n return desc.piProviderId ?? desc.key\n}\n\n/**\n * The model a session with no pick runs on: the descriptor's default, else\n * {@link DEFAULT_MODEL_PICK}.\n *\n * @param desc - The provider descriptor.\n */\nexport function defaultModelOf(desc: ProviderDescriptor): string {\n return desc.defaultModel ?? DEFAULT_MODEL_PICK.modelId\n}\n\n/**\n * Catalog keys a descriptor answers to, most specific first.\n *\n * Usually one: for every provider except Codex the descriptor `key`, the pi-ai\n * registry id, and the `Provider.name` used on the wire are the same string.\n * Codex is the exception — metadata lives under `openai-codex` while its cost\n * accounting runs under `openai` — so a consumer's single entry has to work\n * under either. The wire side does the same via `aliasCatalogProviders`; if\n * these two disagreed, an override would half-apply (right invoice, wrong\n * context gauge), which is harder to notice than failing outright.\n */\nfunction catalogProvidersOf(desc: ProviderDescriptor): readonly string[] {\n const piId = piIdOf(desc)\n return piId === desc.key ? [piId] : [piId, desc.key]\n}\n\n// ---------------------------------------------------------------------------\n// Built-in descriptors\n// ---------------------------------------------------------------------------\n\n/** Descriptor for Anthropic, with OAuth and API-key accounts. */\nexport const anthropicDescriptor: ProviderDescriptor = {\n key: 'anthropic',\n label: 'Anthropic',\n description: 'Claude models. Sign in with your Claude plan, or use an API key.',\n signInLabel: 'Claude',\n factory: anthropic,\n accounts: true,\n defaultModel: DEFAULT_MODEL_PICK.modelId,\n envKey: 'ANTHROPIC_API_KEY',\n apiKeyPlaceholder: 'sk-ant-…',\n oauthProvider: anthropicOAuthProvider,\n oauthHint: 'Claude Pro or Max plan',\n extraModels: ANTHROPIC_EXTRA_MODELS,\n optionsFor: id => FAST_MODE_OPTIONS[id] ? [FAST_MODE_OPTIONS[id]] : undefined,\n // Approximate: a forced tool call on the small model (`anthropic-decisions.ts`).\n decisionModels: ANTHROPIC_DECISION_MODELS,\n}\n\n/**\n * Models we have CONFIRMED accept OpenAI's priority service tier\n * (`serviceTier: 'priority'`, wired in `src/providers/openai.ts`) at the\n * published 2.5× multiplier. Deliberately a set rather than \"the current\n * flagship\": priority availability and its multiplier are per-model, so a new\n * default (gpt-6-astra, the 5.6 family) does not inherit the toggle — add the\n * id here once https://platform.openai.com/docs/guides/priority-processing\n * lists it, together with the multiplier its pricing page states. Missing =\n * the picker hides the fast toggle, which is the safe direction: offering it\n * would send a tier the model may reject and would misreport cost.\n */\nconst OPENAI_PRIORITY_TIER_MODELS: ReadonlySet<string> = new Set(['gpt-5.5'])\n\n/** Descriptor for OpenAI through the Codex credentials, with accounts. */\nexport const openaiDescriptor: ProviderDescriptor = {\n key: 'openai',\n label: 'OpenAI',\n description: 'GPT models. Sign in with your ChatGPT plan, or use an API key.',\n signInLabel: 'ChatGPT',\n factory: openai,\n accounts: true,\n defaultModel: 'gpt-6-astra',\n envKey: 'OPENAI_CODEX_API_KEY',\n credentialFileKey: 'openai-codex',\n piProviderId: 'openai-codex',\n // Both credential shapes stream: the provider auto-detects the backend —\n // an `sk-…` platform key routes to the standard Responses API\n // (api.openai.com, platform billing), a Codex OAuth JWT (`eyJ…`, via the\n // login flow) to the ChatGPT Codex backend (subscription billing).\n apiKeyPlaceholder: 'sk-… (platform) or eyJ… (Codex)',\n oauthProvider: openaiCodexOAuthProvider,\n // Platform API keys only: `Provider.decisions` reports Codex OAuth as unavailable.\n decisionModels: OPENAI_DECISION_MODELS,\n // Platform API keys only, like decisions.\n imageModels: OPENAI_IMAGE_MODELS,\n // OpenAI publishes `gpt-5.6` as an alias for the Sol flagship; pi-ai's\n // registry only carries the concrete ids, so resolve the shorthand for\n // metadata lookups (context window, reasoning, cost). Wire-side mirror\n // lives in `MODEL_ALIASES` in `src/providers/openai.ts`.\n modelAliases: {\n 'gpt-5.6': 'gpt-5.6-sol',\n },\n optionsFor: id => OPENAI_PRIORITY_TIER_MODELS.has(id)\n ? [{\n id: 'fast',\n label: 'Fast mode',\n description: 'Priority tier at 2.5× pricing',\n costMultiplier: { input: 2.5, output: 2.5, cacheRead: 2.5, cacheWrite: 2.5 },\n }]\n : undefined,\n}\n\n/** Descriptor for OpenRouter, with a metadata alias for retired Claude slugs. */\nexport const openrouterDescriptor: ProviderDescriptor = {\n key: 'openrouter',\n label: 'OpenRouter',\n description: 'Models from many labs through one API key.',\n factory: openrouter,\n defaultModel: OPENROUTER_DEFAULT_MODEL,\n envKey: 'OPENROUTER_API_KEY',\n apiKeyPlaceholder: 'sk-or-…',\n decisionModels: OPENROUTER_DECISION_MODELS,\n imageModels: openrouterImageModels(),\n // Metadata-side mirror of the OpenRouter provider's wire alias (see\n // `MODEL_ALIASES` in `src/providers/openrouter.ts`). Keeps context-window /\n // reasoning lookups resolving for sessions persisted with the old slug.\n modelAliases: {\n 'anthropic/claude-sonnet-4-6': 'anthropic/claude-sonnet-4.6',\n 'anthropic/claude-fable-5-1': 'anthropic/claude-fable-5.1',\n },\n}\n\n/** Descriptor for Cerebras, defaulting to `gpt-oss-120b`. */\nexport const cerebrasDescriptor: ProviderDescriptor = {\n key: 'cerebras',\n label: 'Cerebras',\n description: 'Open models hosted by Cerebras. Uses an API key.',\n factory: cerebras,\n // `zai-glm-4.7` is gone from Cerebras' catalog; `gpt-oss-120b` is in pi-ai's registry.\n defaultModel: 'gpt-oss-120b',\n envKey: 'CEREBRAS_API_KEY',\n apiKeyPlaceholder: 'csk-…',\n}\n\n/**\n * xAI Grok. Supports BOTH a static API key (`XAI_API_KEY`) and the\n * SuperGrok / X Premium+ OAuth subscription, so the wizard offers both methods.\n * Models come from pi-ai's `xai` registry (OpenAI-compatible endpoint), shared\n * by both auth modes.\n */\nexport const xaiDescriptor: ProviderDescriptor = {\n key: 'xai',\n label: 'xAI Grok',\n description: 'Grok models. Sign in with SuperGrok or X Premium+, or use an API key.',\n signInLabel: 'xAI',\n factory: xai,\n accounts: true,\n defaultModel: 'grok-4.6',\n envKey: 'XAI_API_KEY',\n apiKeyPlaceholder: 'xai-…',\n oauthProvider: xaiOAuthProvider,\n oauthHint: 'SuperGrok or X Premium+ plan',\n // pi-ai stores the OAuth credential under the provider id, distinct from the\n // `xai` descriptor key so the API-key and OAuth credentials never collide.\n credentialFileKey: 'xai-oauth',\n piProviderId: 'xai',\n imageModels: XAI_IMAGE_MODELS,\n}\n\n/** Picker rows for the Google models pi-ai hasn't bundled yet (`GOOGLE_EXTRA_MODELS`). */\nfunction googleExtraModels(route: 'google' | 'google-vertex'): readonly ModelInfo[] {\n return GOOGLE_EXTRA_MODELS.map(model => ({\n id: model.id,\n name: model.name,\n contextWindow: model.contextWindow,\n maxTokens: model.maxTokens,\n reasoning: true,\n input: ['text', 'image'] as const,\n cost: model.rates(),\n provider: route,\n }))\n}\n\n/**\n * Google Gemini on the Gemini API (Google AI Studio), with an API key. A\n * Google AI Pro / Ultra plan's monthly Google Cloud credits pay for it on a\n * billing-enabled project. Models come from pi-ai's `google` registry plus\n * the ones it hasn't bundled yet.\n */\nexport const googleDescriptor: ProviderDescriptor = {\n key: 'google',\n label: 'Google Gemini',\n description: 'Gemini models. Uses an API key from Google AI Studio.',\n factory: google,\n defaultModel: GOOGLE_DEFAULT_MODEL,\n envKey: 'GEMINI_API_KEY',\n apiKeyPlaceholder: 'AIza…',\n piProviderId: 'google',\n extraModels: googleExtraModels('google'),\n imageModels: GOOGLE_IMAGE_MODELS,\n}\n\n/**\n * Google Vertex AI, with Google Cloud credentials for the configured project:\n * gcloud's Application Default Credentials (`gcloud auth application-default\n * login`) or `GOOGLE_APPLICATION_CREDENTIALS`. No `envKey`, so the wizard\n * collects the project and location as the credential (like `local`); a\n * Vertex API key in `GOOGLE_CLOUD_API_KEY` takes over when set.\n *\n * \"Sign in with Google\" is offered once an OAuth client is configured\n * (`ZIDANE_GOOGLE_CLIENT_ID` / `_SECRET`, see `oauth-page/google`). A getter,\n * because the TUI fills the environment after this module loads.\n */\nexport const googleVertexDescriptor: ProviderDescriptor = {\n key: 'google-vertex',\n label: 'Google Vertex AI',\n description: 'Gemini models on Vertex AI, with your Google Cloud project.',\n signInLabel: 'Google',\n factory: googleVertex,\n accounts: true,\n get oauthProvider() {\n return googleOAuthClient() ? googleOAuthProvider : undefined\n },\n oauthHint: 'Google account with a Google Cloud project',\n defaultModel: GOOGLE_DEFAULT_MODEL,\n envKey: undefined,\n piProviderId: 'google-vertex',\n extraModels: googleExtraModels('google-vertex'),\n customFields: [\n {\n key: 'project',\n label: 'Google Cloud project',\n envVar: 'GOOGLE_CLOUD_PROJECT',\n placeholder: 'my-project-id',\n hint: 'Run `gcloud auth application-default login` first. The project needs the Vertex AI API and billing turned on. Google AI Pro and Ultra credits apply.',\n required: true,\n },\n {\n key: 'location',\n label: 'Location',\n envVar: 'GOOGLE_CLOUD_LOCATION',\n placeholder: 'global',\n hint: 'Vertex AI region. Leave blank for global.',\n },\n ],\n}\n\n/**\n * Arcee Trinity models (Platform API slugs). pi-ai has no Arcee registry, so we\n * ship a curated list. `reasoning: true` surfaces the effort/thinking UI — the\n * `arcee()` factory round-trips Trinity's `reasoning_content` across turns so the\n * model resumes its chain-of-thought through tool calls.\n *\n * Costs/context per Arcee's published Trinity catalogue.\n */\nconst ARCEE_MODELS: readonly ModelInfo[] = [\n { id: 'trinity-large-thinking', name: 'Trinity Large (Thinking)', contextWindow: 256_000, reasoning: true, input: ['text'], cost: { input: 0.25, output: 0.8 } },\n { id: 'trinity-large-preview', name: 'Trinity Large (Preview)', contextWindow: 128_000, input: ['text'], cost: { input: 0.45, output: 0.15 } },\n { id: 'trinity-mini', name: 'Trinity Mini', contextWindow: 128_000, input: ['text'], cost: { input: 0.045, output: 0.15 } },\n]\n\nexport const arceeDescriptor: ProviderDescriptor = {\n key: 'arcee',\n label: 'Arcee',\n description: 'Arcee models. Uses an API key.',\n factory: arcee,\n defaultModel: 'trinity-large-thinking',\n envKey: 'ARCEE_API_KEY',\n apiKeyPlaceholder: 'arcee-…',\n models: ARCEE_MODELS,\n}\n\n/**\n * Baseten Model APIs — a curated list merged BEHIND pi-ai's `baseten`\n * registry as `extraModels` (pi-ai wins on shared ids).\n * Mirrors https://docs.baseten.co/inference/model-apis/overview (context\n * windows) and Baseten's published per-MTok rates. Models without a\n * `cost` (GLM 5.1, Nemotron Ultra) have no published rate yet — the footer\n * cost indicator hides for those. `/v1/models` is the live source of truth.\n * Keep the rates here in sync with `EXTRA_COST_RATES` in `../providers/cost.ts`:\n * this table is picker metadata only (`ModelInfo.cost`); turn pricing — and\n * therefore every cost surface — comes from `fillEstimatedCost`, which reads\n * the registry and that table, never this one.\n *\n * All listed models support reasoning (`reasoning_content`); the `baseten()`\n * factory maps the thinking level to `reasoning_effort` / `chat_template_args`\n * per model.\n */\nconst BASETEN_MODELS: readonly ModelInfo[] = [\n { id: 'zai-org/GLM-5.2', name: 'GLM 5.2', contextWindow: 1_000_000, reasoning: true, input: ['text'], cost: { input: 1.4, output: 4.4, cacheRead: 0.14 } },\n { id: 'zai-org/GLM-5.1', name: 'GLM 5.1', contextWindow: 200_000, reasoning: true, input: ['text'] },\n { id: 'zai-org/GLM-5', name: 'GLM 5', contextWindow: 200_000, reasoning: true, input: ['text'], cost: { input: 0.95, output: 3.15, cacheRead: 0.2 } },\n { id: 'zai-org/GLM-4.7', name: 'GLM 4.7', contextWindow: 200_000, reasoning: true, input: ['text'], cost: { input: 0.6, output: 2.2, cacheRead: 0.12 } },\n { id: 'moonshotai/Kimi-K2.6', name: 'Kimi K2.6', contextWindow: 256_000, reasoning: true, input: ['text', 'image'], cost: { input: 1, output: 3.9, cacheRead: 0.2 } },\n { id: 'moonshotai/Kimi-K2.5', name: 'Kimi K2.5', contextWindow: 256_000, reasoning: true, input: ['text', 'image'], cost: { input: 0.6, output: 3, cacheRead: 0.12 } },\n { id: 'deepseek-ai/DeepSeek-V4-Pro', name: 'DeepSeek V4 Pro', contextWindow: 131_000, reasoning: true, input: ['text'], cost: { input: 1.74, output: 3.48, cacheRead: 0.145 } },\n { id: 'nvidia/Nemotron-120B-A12B', name: 'Nemotron Super', contextWindow: 200_000, reasoning: true, input: ['text'], cost: { input: 0.3, output: 0.75, cacheRead: 0.06 } },\n { id: 'nvidia/NVIDIA-Nemotron-3-Ultra-550B-A55B', name: 'Nemotron Ultra', contextWindow: 200_000, reasoning: true, input: ['text'] },\n { id: 'openai/gpt-oss-120b', name: 'GPT-OSS 120B', contextWindow: 128_000, reasoning: true, input: ['text'], cost: { input: 0.1, output: 0.5 } },\n]\n\nexport const basetenDescriptor: ProviderDescriptor = {\n key: 'baseten',\n label: 'Baseten',\n description: 'Models hosted by Baseten. Uses an API key.',\n factory: baseten,\n defaultModel: 'zai-org/GLM-5.3',\n envKey: 'BASETEN_API_KEY',\n apiKeyPlaceholder: 'baseten-api-key…',\n // pi-ai bundles a `baseten` registry (GLM 5.x, Kimi K2.x/K3, DeepSeek\n // V4, Nemotron, gpt-oss); the curated list above is kept as `extraModels`\n // so ids it carries that pi-ai does not remain selectable. Bundled wins on\n // overlap, so pi-ai's rates and windows supersede ours as they land.\n piProviderId: 'baseten',\n extraModels: BASETEN_MODELS,\n}\n\n/**\n * Z.ai (Zhipu) GLM Open Platform — the GLM 4.x list, merged BEHIND pi-ai's\n * `zai` registry as `extraModels` (pi-ai wins on shared ids). Mirrors https://docs.z.ai/guides/overview/pricing and per-model\n * context windows from the GLM-4.7 overview page. `reasoning: true`\n * surfaces the effort/thinking UI — the `zai()` factory maps the thinking\n * level to Z.ai's `extra_body.thinking` toggle and round-trips\n * `reasoning_content` across turns. GLM-4.7-Flash and GLM-4.5-Flash are\n * Z.ai's zero-cost tiers (`cost` omitted).\n */\nconst ZAI_MODELS: readonly ModelInfo[] = [\n { id: 'glm-4.7-flash', name: 'GLM-4.7-Flash', contextWindow: 200_000, maxTokens: 128_000, reasoning: true, input: ['text'] },\n { id: 'glm-4.7', name: 'GLM-4.7', contextWindow: 200_000, maxTokens: 128_000, reasoning: true, input: ['text'], cost: { input: 0.6, output: 2.2, cacheRead: 0.11 } },\n { id: 'glm-4.6', name: 'GLM-4.6', contextWindow: 200_000, maxTokens: 128_000, reasoning: true, input: ['text'], cost: { input: 0.6, output: 2.2, cacheRead: 0.11 } },\n { id: 'glm-4.5-flash', name: 'GLM-4.5-Flash', contextWindow: 128_000, reasoning: true, input: ['text'] },\n { id: 'glm-4.5-air', name: 'GLM-4.5-Air', contextWindow: 128_000, reasoning: true, input: ['text'], cost: { input: 0.2, output: 1.1, cacheRead: 0.03 } },\n]\n\n/**\n * Neuralwatt's standard-tier chat models (pi-ai bundles no registry for it).\n * Mirrors `GET https://api.neuralwatt.com/v1/models`: context windows, image\n * input and per-MTok rates as published there. The `nw-*` tracking aliases,\n * `-flex` and `-fast` variants are left out of the picker; any id still\n * works when typed. Picker metadata only: turn pricing comes from\n * `fillEstimatedCost`, which does not know these rates.\n */\nconst NEURALWATT_MODELS: readonly ModelInfo[] = [\n { id: 'kimi-k3', name: 'Kimi K3', contextWindow: 1_048_560, reasoning: true, input: ['text', 'image'], cost: { input: 3, output: 15, cacheRead: 0.3 } },\n { id: 'glm-5.3', name: 'GLM 5.3', contextWindow: 1_048_560, reasoning: true, input: ['text'], cost: { input: 1.45, output: 4.5, cacheRead: 0.145 } },\n { id: 'glm-5.3-flash', name: 'GLM-5.3 Flash', contextWindow: 1_048_560, reasoning: true, input: ['text', 'image'], cost: { input: 0.15, output: 0.5, cacheRead: 0.03 } },\n { id: 'deepseek-v4.1-flash', name: 'DeepSeek V4.1 Flash', contextWindow: 1_048_560, maxTokens: 393_216, reasoning: true, input: ['text', 'image'], cost: { input: 0.15, output: 0.6, cacheRead: 0.015 } },\n { id: 'deepseek-v4-flash', name: 'DeepSeek V4 Flash', contextWindow: 1_048_560, maxTokens: 393_216, reasoning: true, input: ['text'], cost: { input: 0.14, output: 0.28, cacheRead: 0.028 } },\n { id: 'mimo-v2.6-pro', name: 'MiMo-V2.6-Pro', contextWindow: 1_048_560, maxTokens: 393_216, reasoning: true, input: ['text', 'image'], cost: { input: 0.87, output: 1.74, cacheRead: 0.036 } },\n { id: 'qwen-3.8-27b', name: 'Qwen 3.8 27B', contextWindow: 262_128, maxTokens: 131_072, reasoning: true, input: ['text', 'image'], cost: { input: 0.45, output: 3.2, cacheRead: 0.25 } },\n { id: 'qwen3.6-35b', name: 'Qwen3.6 35B', contextWindow: 262_128, reasoning: true, input: ['text', 'image'], cost: { input: 0.29, output: 1.15, cacheRead: 0.029 } },\n { id: 'gemma-4-31b', name: 'Gemma 4 31B', contextWindow: 262_128, maxTokens: 16_384, reasoning: true, input: ['text', 'image'], cost: { input: 0.144, output: 0.42, cacheRead: 0.0144 } },\n]\n\n/** Neuralwatt: API key from `NEURALWATT_API_KEY`, the curated model list above. */\nexport const neuralwattDescriptor: ProviderDescriptor = {\n key: 'neuralwatt',\n label: 'Neuralwatt',\n description: 'Models hosted by Neuralwatt, with measured energy per request. Uses an API key.',\n factory: neuralwatt,\n defaultModel: NEURALWATT_DEFAULT_MODEL,\n envKey: 'NEURALWATT_API_KEY',\n apiKeyPlaceholder: 'sk-…',\n models: NEURALWATT_MODELS,\n}\n\n/**\n * Mistral La Plateforme. Models come from pi-ai's `mistral` registry (plain\n * slugs, same ids the OpenAI-compatible `/v1/chat/completions` route accepts).\n * The `mistral()` factory maps the thinking level to `reasoning_effort` for the\n * families that document it and parses Mistral's `thinking` content chunks.\n */\nexport const mistralDescriptor: ProviderDescriptor = {\n key: 'mistral',\n label: 'Mistral',\n description: 'Mistral models. Uses an API key.',\n factory: mistral,\n defaultModel: 'mistral-medium-latest',\n envKey: 'MISTRAL_API_KEY',\n apiKeyPlaceholder: 'mistral-api-key…',\n piProviderId: 'mistral',\n}\n\nexport const zaiDescriptor: ProviderDescriptor = {\n key: 'zai',\n label: 'Z.ai',\n description: 'GLM models from Z.ai. Uses an API key.',\n factory: zai,\n defaultModel: 'glm-5.3-flash',\n envKey: 'ZAI_API_KEY',\n apiKeyPlaceholder: 'zai-api-key…',\n // Same shape as Baseten: pi-ai's `zai` registry (GLM 5.x) owns the list,\n // the GLM 4.x entries below ride as extras for sessions pinned to them.\n piProviderId: 'zai',\n extraModels: ZAI_MODELS,\n}\n\n/**\n * Conservative context-window assumption for a user-configured local model.\n * Local runtimes expose no reliable per-model metadata over the OpenAI-compat\n * `/v1/models` endpoint (it returns ids, not context sizes), so we pick a\n * floor that fits the smallest mainstream OSS models (Llama 3.x 8B, Qwen2.5)\n * without over-promising. The footer's context indicator and auto-compaction\n * lean on this — under-estimating is the safe direction (compact early rather\n * than overflow the server's real window).\n *\n * Users running larger-context models (e.g. a 128K Qwen) can raise it via the\n * `LOCAL_LLM_CONTEXT_WINDOW` env var / customField, which supports a single\n * value or a per-model map (resolved by {@link resolveContextWindow}).\n */\nconst LOCAL_DEFAULT_CONTEXT_WINDOW = 8_192\n\n/**\n * Local OpenAI-compatible LLM (Ollama, vLLM, LM Studio, Lemonade, llama.cpp).\n *\n * No fixed base URL or model catalogue — both come from the user via\n * `customFields`. No `envKey`, so the wizard skips the API-key prompt and\n * treats the customFields-only credential as the auth signal (see\n * `applyApiKeyEnv` + `detectAuth`).\n *\n * Vision / cache / reasoning are off by default in the factory — flip them\n * by passing a custom descriptor that calls `local({ capabilities })`.\n *\n * `models` is a getter, not a static list: there's no fixed catalogue to ship,\n * but once the user has configured a default model (mirrored into\n * `LOCAL_LLM_DEFAULT_MODEL` by `applyApiKeyEnv`), we surface it as a\n * single-entry list so the model picker + footer aren't empty. Resolved at\n * access time because the env var is populated at TUI launch, after this\n * module loads. Empty list when unconfigured — the picker hides, the user\n * types a slug at the prompt as before.\n */\nexport const localDescriptor: ProviderDescriptor = {\n key: 'local',\n label: 'Local LLM',\n description: 'A model server that speaks the OpenAI API, such as Ollama, vLLM, LM Studio or llama.cpp.',\n factory: local,\n get models(): readonly ModelInfo[] {\n const configured = process.env.LOCAL_LLM_DEFAULT_MODEL?.trim()\n if (!configured)\n return []\n // Resolve the window from the user's `LOCAL_LLM_CONTEXT_WINDOW` (single\n // value or per-model map), falling back to the conservative default. Uses\n // the same parser as `getContextWindow`'s `contextWindowEnvVar` path so\n // both surfaces agree on the number.\n const resolved = resolveContextWindow(process.env.LOCAL_LLM_CONTEXT_WINDOW, configured)\n return [{\n id: configured,\n name: configured,\n contextWindow: resolved ?? LOCAL_DEFAULT_CONTEXT_WINDOW,\n input: ['text'],\n }]\n },\n customFields: [\n {\n key: 'baseURL',\n label: 'Base URL',\n envVar: 'LOCAL_LLM_BASE_URL',\n placeholder: 'http://localhost:11434/v1',\n hint: 'The URL of your local LLM server. Ollama: http://localhost:11434/v1, vLLM: http://localhost:8000/v1, LM Studio: http://localhost:1234/v1.',\n required: true,\n },\n {\n key: 'apiKey',\n label: 'API key',\n envVar: 'LOCAL_LLM_API_KEY',\n placeholder: 'leave blank if your server has no auth',\n },\n {\n key: 'model',\n label: 'Default model',\n envVar: 'LOCAL_LLM_DEFAULT_MODEL',\n placeholder: 'llama3.1:8b, qwen2.5-coder, mistral-small',\n hint: 'The model id your server serves. If blank, pick one later in the model picker.',\n },\n {\n key: 'contextWindow',\n label: 'Context window (tokens)',\n envVar: 'LOCAL_LLM_CONTEXT_WINDOW',\n placeholder: '32768, or per model: llama3.1:8b=32768, qwen2.5-coder=128k, 64k',\n hint: 'Local runtimes do not report a context length. Set it to turn on the context indicator and auto-compaction. Use one value (32768, 128k) for all models, or a comma-separated `model=window` list with an optional bare value as the fallback.',\n },\n ],\n contextWindowEnvVar: 'LOCAL_LLM_CONTEXT_WINDOW',\n}\n\n/**\n * Cursor models. pi-ai has no Cursor registry, so we ship a small curated\n * list (Cursor proxies these). Context windows are nominal — Cursor inference\n * isn't wired yet (the provider's `stream()` throws), so these only drive the\n * picker once the protobuf transport lands.\n */\nconst CURSOR_MODELS: readonly ModelInfo[] = [\n { id: 'claude-4.6-sonnet', name: 'Claude Sonnet 4.6', contextWindow: 200_000, reasoning: true, input: ['text', 'image'] },\n { id: 'claude-4.8-opus', name: 'Claude Opus 4.8', contextWindow: 200_000, reasoning: true, input: ['text', 'image'] },\n { id: 'gpt-5.5', name: 'GPT-5.5', contextWindow: 272_000, reasoning: true, input: ['text', 'image'] },\n { id: 'composer-2', name: 'Composer 2', contextWindow: 200_000, input: ['text'] },\n { id: 'composer-2.5', name: 'Composer 2.5', contextWindow: 200_000, input: ['text'] },\n]\n\nexport const cursorDescriptor: ProviderDescriptor = {\n key: 'cursor',\n label: 'Cursor',\n description: 'Cursor models. Sign in with your Cursor plan.',\n signInLabel: 'Cursor',\n factory: cursor,\n accounts: true,\n defaultModel: 'claude-4.6-sonnet',\n // OAuth-only: no API-key env var.\n envKey: undefined,\n oauthProvider: cursorOAuthProvider,\n oauthHint: 'Cursor plan',\n models: CURSOR_MODELS,\n}\n\n/**\n * Default provider registry. Passed verbatim when `runTui` is invoked without\n * an explicit `providers` option. Hosts that want to override per-provider\n * metadata can spread this and replace specific entries:\n *\n * ```ts\n * runTui({ providers: { ...BUILTIN_PROVIDERS, anthropic: myOwnAnthropicDescriptor } })\n * ```\n *\n * `cursor` is intentionally NOT registered here: OAuth works, but inference\n * isn't wired (`cursor.stream()` throws — Cursor speaks a protobuf/HTTP-2\n * agent protocol, not OpenAI-compat). Shipping it in the picker only lets users\n * select a model that errors every turn. The descriptor stays exported so a\n * host can opt in (`{ ...BUILTIN_PROVIDERS, cursor: cursorDescriptor }`) once\n * the transport lands — re-add it here at that point.\n */\nexport const BUILTIN_PROVIDERS: Readonly<Record<string, ProviderDescriptor>> = {\n 'anthropic': anthropicDescriptor,\n 'openai': openaiDescriptor,\n 'openrouter': openrouterDescriptor,\n 'cerebras': cerebrasDescriptor,\n 'xai': xaiDescriptor,\n 'google': googleDescriptor,\n 'google-vertex': googleVertexDescriptor,\n 'arcee': arceeDescriptor,\n 'baseten': basetenDescriptor,\n 'zai': zaiDescriptor,\n 'mistral': mistralDescriptor,\n 'neuralwatt': neuralwattDescriptor,\n 'local': localDescriptor,\n}\n\n// ---------------------------------------------------------------------------\n// Model registry helper\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the model list for a given provider. Honors `descriptor.models`\n * when set; otherwise queries pi-ai via `descriptor.piProviderId`. Returns\n * `[]` for descriptors with no known mapping (custom providers without a\n * model list) — callers should hide the model picker in that case.\n *\n * @param descriptor - The provider descriptor.\n */\nexport function modelsForDescriptor(descriptor: ProviderDescriptor): readonly ModelInfo[] {\n if (descriptor.models)\n return descriptor.models\n const piId = piIdOf(descriptor)\n const catalogKeys = catalogProvidersOf(descriptor)\n // A catalog whose `list` answers OWNS this provider's models — bundled\n // entries are not consulted, so it can hide as well as add. The picker\n // resolves metadata before any agent exists, so only the process-wide\n // catalog is visible here; `behavior.modelCatalog` governs the wire path.\n const owned = firstDefined(catalogKeys, key => listModels(key))\n let bundled: readonly ModelInfo[]\n if (owned) {\n // An id-less list entry is unusable downstream (the picker selects by id,\n // every lookup keys on it), so drop it with one warning rather than\n // rendering a blank selectable row. `ModelCatalogEntry.id` is optional for\n // the patch/table form, which is exactly how this mistake happens.\n const usable = owned.filter(entry => entry.id !== undefined && entry.id !== '')\n if (usable.length !== owned.length)\n warnOnce(`model catalog: dropped ${owned.length - usable.length} \"${piId}\" list entr${owned.length - usable.length === 1 ? 'y' : 'ies'} with no id`)\n bundled = usable.map(entry => toModelInfo(entry, piId))\n }\n else {\n try {\n bundled = getModels(piId as never) as readonly ModelInfo[]\n }\n catch {\n bundled = []\n }\n // Table-form entries OVERLAY: patch matching ids, append unknown ones,\n // leave everything they don't name intact.\n const overlay = dedupeById(catalogKeys.flatMap(key => listModelOverlay(key)))\n if (overlay.length > 0) {\n const known = new Set(bundled.map(m => m.id))\n bundled = [\n ...bundled.map((m) => {\n const entry = overlay.find(e => e.id === m.id)\n return entry ? mergeCatalogEntry(m, entry) : m\n }),\n ...overlay.filter(e => e.id !== undefined && !known.has(e.id)).map(entry => toModelInfo(entry, piId)),\n ]\n }\n }\n // `extraModels` is OUR stopgap for models pi-ai hasn't bundled yet — the\n // same role the catalog fills properly. An owning catalog therefore\n // suppresses them too, otherwise a consumer couldn't hide a model we\n // hardcoded and \"owns the list\" would be a half-truth.\n if (!owned && descriptor.extraModels?.length) {\n // Merge extras ahead of the bundled list, de-duped by id (bundled wins, so a\n // model that lands in pi-ai later transparently supersedes the local entry).\n const bundledIds = new Set(bundled.map(m => m.id))\n const extras = descriptor.extraModels.filter(m => !bundledIds.has(m.id))\n bundled = [...extras, ...bundled]\n }\n return descriptor.optionsFor ? bundled.map(m => decorateOptions(m, descriptor)) : bundled\n}\n\n/** First non-`undefined` result of `resolve` across `keys`. */\nfunction firstDefined<T>(keys: readonly string[], resolve: (key: string) => T | undefined): T | undefined {\n for (const key of keys) {\n const value = resolve(key)\n if (value !== undefined)\n return value\n }\n return undefined\n}\n\n/** De-dupe catalog entries by id, first occurrence winning. */\nfunction dedupeById(entries: readonly ModelCatalogEntry[]): readonly ModelCatalogEntry[] {\n if (entries.length < 2)\n return entries\n const seen = new Set<string>()\n return entries.filter((entry) => {\n const id = entry.id ?? ''\n if (seen.has(id))\n return false\n seen.add(id)\n return true\n })\n}\n\n/**\n * Attach descriptor-resolved {@link ModelOption}s to a model that doesn't\n * already declare its own. Pure / non-mutating — returns the input untouched\n * when the model has options already or the descriptor resolves none.\n */\nfunction decorateOptions(model: ModelInfo, descriptor: ProviderDescriptor): ModelInfo {\n if (model.options?.length || !descriptor.optionsFor)\n return model\n const options = descriptor.optionsFor(model.id)\n return options?.length ? { ...model, options } : model\n}\n\n/**\n * Resolve a single model's metadata via the descriptor's model source.\n * Mirrors {@link modelsForDescriptor} routing: descriptor's own list wins,\n * pi-ai's registry is the fallback. Returns `null` when the model isn't\n * known.\n *\n * @param descriptor - The provider descriptor.\n * @param modelId - Model id, resolved through `modelAliases`.\n */\nexport function getModelInfo(descriptor: ProviderDescriptor, modelId: string): ModelInfo | null {\n const lookupId = descriptor.modelAliases?.[modelId] ?? modelId\n if (descriptor.models)\n return descriptor.models.find(m => m.id === lookupId) ?? null\n const piId = piIdOf(descriptor)\n const entry = firstDefined(catalogProvidersOf(descriptor), key => lookupModel(key, lookupId))\n try {\n const bundled = getModel(piId as never, lookupId as never) as ModelInfo | undefined\n if (bundled)\n return decorateOptions(mergeCatalogEntry(bundled, entry), descriptor)\n }\n catch {\n // fall through to the catalog entry, then extras\n }\n // Registry miss: a catalog entry stands on its own — that's the point, these\n // are models the bundled snapshot has never heard of.\n if (entry)\n return decorateOptions(toModelInfo({ ...entry, id: entry.id ?? lookupId }, piId), descriptor)\n const extra = descriptor.extraModels?.find(m => m.id === lookupId)\n return extra ? decorateOptions(extra, descriptor) : null\n}\n\nconst modelLabels = new WeakMap<object, Map<string, string>>()\n\n/**\n * The name the model picker shows for a model (`Opus 4.5`): the provider's\n * catalog name when `registry` knows the model, else the id made readable.\n * Without a provider key, or with one `registry` doesn't hold, the first\n * provider that knows the id names it. Memoized per registry: surfaces call\n * it on every render.\n *\n * @param registry - Descriptors keyed by provider key.\n * @param modelId - Model id to label.\n * @param providerKey - Optional provider key to look the model up under first.\n */\nexport function modelLabel(registry: Readonly<Record<string, ProviderDescriptor>>, modelId: string, providerKey?: string | null): string {\n let cache = modelLabels.get(registry)\n if (!cache) {\n cache = new Map()\n modelLabels.set(registry, cache)\n }\n const cacheKey = `${providerKey ?? ''}\\u0000${modelId}`\n const hit = cache.get(cacheKey)\n if (hit !== undefined)\n return hit\n let key = providerKey && registry[providerKey] ? providerKey : undefined\n let info = key ? getModelInfo(registry[key]!, modelId) : null\n if (!key) {\n for (const [k, descriptor] of Object.entries(registry)) {\n info = getModelInfo(descriptor, modelId)\n if (info) {\n key = k\n break\n }\n }\n }\n const name = modelDisplayName({ providerKey: key ?? providerKey, modelId, modelName: info?.name }).name\n cache.set(cacheKey, name)\n return name\n}\n\n/**\n * De-duped warning sink. `modelsForDescriptor` runs on every picker render, so\n * a malformed catalog entry must not spam the terminal. Mirrors the\n * `[zidane:schema]` seen-set convention in `providers/schema-sanitize.ts`.\n */\nconst warnedCatalogLines = new Set<string>()\nfunction warnOnce(line: string): void {\n if (warnedCatalogLines.has(line))\n return\n warnedCatalogLines.add(line)\n console.warn(`[zidane:model-catalog] ${line}`)\n}\n\n/**\n * Catalog entry → `ModelInfo`. `contextWindow` is required on `ModelInfo` but\n * optional on an entry (most overrides only correct a ceiling or a rate), so a\n * missing one becomes `0`. That placeholder is NOT a window: `getContextWindow`\n * treats non-positive values as unknown and falls through to\n * `contextWindowEnvVar` / `null`, which is what keeps the context panel from\n * rendering percentages against a 1-token window.\n */\nfunction toModelInfo(entry: ModelCatalogEntry, provider: string): ModelInfo {\n return {\n id: entry.id ?? '',\n ...(entry.name !== undefined ? { name: entry.name } : {}),\n contextWindow: entry.contextWindow ?? 0,\n ...(entry.maxTokens !== undefined ? { maxTokens: entry.maxTokens } : {}),\n ...(entry.reasoning !== undefined ? { reasoning: entry.reasoning } : {}),\n ...(entry.input !== undefined ? { input: entry.input } : {}),\n ...(entry.cost !== undefined\n ? {\n cost: {\n input: entry.cost.input ?? 0,\n output: entry.cost.output ?? 0,\n ...(entry.cost.cacheRead !== undefined ? { cacheRead: entry.cost.cacheRead } : {}),\n ...(entry.cost.cacheWrite !== undefined ? { cacheWrite: entry.cost.cacheWrite } : {}),\n },\n }\n : {}),\n ...(entry.tier !== undefined ? { tier: entry.tier } : {}),\n provider,\n }\n}\n\n/**\n * Parse a user-supplied context-window string into a token count.\n *\n * Accepts a plain integer (`\"32768\"`), or a number with a `k`/`m` suffix\n * (×1_000 / ×1_000_000, case-insensitive, optional space) — so `\"128k\"`\n * yields `128_000`, matching how the footer renders windows (`fmtTokens`).\n * Fractional values are floored (`\"1.5k\"` → `1500`). Returns `null` for\n * empty, malformed, zero, or negative input so callers fall through to\n * \"window unknown\" rather than a bogus ceiling.\n */\nexport function parseContextWindow(raw: string | undefined | null): number | null {\n if (raw == null)\n return null\n const trimmed = raw.trim()\n if (trimmed.length === 0)\n return null\n const match = /^(\\d+(?:\\.\\d+)?)\\s*([km])?$/i.exec(trimmed)\n if (!match)\n return null\n const suffix = match[2]?.toLowerCase()\n const mult = suffix === 'k' ? 1_000 : suffix === 'm' ? 1_000_000 : 1\n const value = Math.floor(Number.parseFloat(match[1]) * mult)\n return value >= 1 ? value : null\n}\n\n/**\n * Resolve a per-model context window from a user-supplied spec string.\n *\n * A spec is a comma-separated list of entries. An entry is either:\n * - `model=window` — a per-model override (split on the **first** `=`, so\n * model ids containing `:` or `/` survive), or\n * - a bare `window` — the fallback applied to any model not named above.\n *\n * Windows are parsed by {@link parseContextWindow} (plain int or k/m suffix).\n * Whitespace around entries and the `=` is ignored; malformed entries are\n * skipped rather than poisoning the whole spec; a later duplicate key wins.\n *\n * Lookup order for `modelId`: exact map entry → bare fallback → `null`. A\n * lone bare value (`\"32768\"`) therefore behaves as a single global window,\n * keeping the simple single-model config working.\n *\n * @example resolveContextWindow('llama3.1:8b=32768, qwen=128k, 64k', 'qwen') // 128000\n */\nexport function resolveContextWindow(spec: string | undefined | null, modelId: string): number | null {\n if (spec == null)\n return null\n const overrides = new Map<string, number>()\n let fallback: number | null = null\n for (const entry of spec.split(',')) {\n const eq = entry.indexOf('=')\n if (eq === -1) {\n const bare = parseContextWindow(entry)\n if (bare != null)\n fallback = bare\n continue\n }\n const key = entry.slice(0, eq).trim()\n const window = parseContextWindow(entry.slice(eq + 1))\n if (key.length > 0 && window != null)\n overrides.set(key, window)\n }\n return overrides.get(modelId) ?? fallback\n}\n\n/**\n * Look up the model's max context window via the descriptor's model source.\n * Falls back to {@link ProviderDescriptor.contextWindowEnvVar} (parsed via\n * {@link resolveContextWindow}, which supports a per-model map) when the\n * registry has nothing — this is how local LLMs, whose runtimes don't\n * advertise a window, get one. Returns `null` when neither source resolves a\n * value (custom slugs, providers without a registry or a configured window);\n * callers should hide the context indicator and skip auto-compaction then.\n *\n * @param descriptor - The provider descriptor.\n * @param modelId - Model id, resolved through `modelAliases`.\n */\nexport function getContextWindow(descriptor: ProviderDescriptor, modelId: string): number | null {\n // `> 0`, not just non-null: a model record can carry a placeholder `0` (a\n // catalog entry that only corrects a ceiling or a rate, a descriptor entry\n // with no advertised window). Returning it would make the caller treat 0 as\n // a REAL window — `effectiveContextWindow(0)` clamps to 1 token, and the\n // context panel then renders absurd percentages instead of hiding.\n const fromRegistry = getModelInfo(descriptor, modelId)?.contextWindow\n if (fromRegistry != null && fromRegistry > 0)\n return fromRegistry\n if (descriptor.contextWindowEnvVar)\n return resolveContextWindow(process.env[descriptor.contextWindowEnvVar], modelId)\n return null\n}\n\n// `OUTPUT_RESERVE_TOKENS` + `effectiveContextWindow` live in the core\n// `src/compact/policy.ts` so the agent loop (which can't import `src/chat/`)\n// shares the same window math as the chat footer + auto-compact trigger.\n// Re-exported here for `chat/providers` importers.\nexport { effectiveContextWindow, OUTPUT_RESERVE_TOKENS } from '../compact/policy'\n\n/**\n * Whether the given model exposes a reasoning / extended-thinking knob.\n * Drives the TUI's effort picker visibility — the footer's effort segment\n * (`effortLabel`) and its shortcut only surface when this is `true`.\n * Returns `false` for unknown models (no registry entry → no advertised\n * capability).\n *\n * @param descriptor - The provider descriptor.\n * @param modelId - Model id, resolved through `modelAliases`.\n */\nexport function modelSupportsReasoning(descriptor: ProviderDescriptor, modelId: string): boolean {\n return getModelInfo(descriptor, modelId)?.reasoning === true\n}\n\n/**\n * Custom {@link ModelOption}s the given model supports (e.g. fast mode), or `[]`\n * when none. Drives the TUI/GUI options picker visibility — surfaces only when\n * non-empty.\n *\n * @param descriptor - The provider descriptor.\n * @param modelId - Model id, resolved through `modelAliases`.\n */\nexport function modelOptionsFor(descriptor: ProviderDescriptor, modelId: string): readonly ModelOption[] {\n return getModelInfo(descriptor, modelId)?.options ?? []\n}\n\n/**\n * Normalize a model-options blob to an enabled-only `{ id: true }` map.\n *\n * Single source of truth shared by every surface that reads or persists model\n * options — the TUI run path, the GUI engine reader, and the GUI IPC handlers.\n * Tolerant of arbitrary input (persisted JSON metadata may be anything): a\n * non-object → `{}`, and only entries strictly equal to `true` survive. This\n * keeps the persisted shape minimal (no `{ fast: false }` noise) and means\n * callers never forward a disabled option to `agent.run`.\n *\n * @param raw - Persisted or untrusted options blob.\n */\nexport function enabledModelOptions(raw: unknown): Record<string, boolean> {\n if (!raw || typeof raw !== 'object')\n return {}\n const out: Record<string, boolean> = {}\n for (const [id, on] of Object.entries(raw as Record<string, unknown>)) {\n if (on === true)\n out[id] = true\n }\n return out\n}\n\n/**\n * Resolve a model's remembered options for a (re)pick: keep only options the\n * model still declares AND that are enabled, dropping any that no longer apply\n * (e.g. switching away from a model that supported `fast`). Returns `undefined`\n * when nothing applies so callers can omit the field entirely.\n *\n * Shared by the TUI pick path and the launch-time resume path so \"which options\n * survive a model switch / relaunch\" is decided in exactly one place.\n *\n * @param descriptor - The provider descriptor.\n * @param modelId - The model being picked.\n * @param remembered - Remembered enabled options keyed by model id.\n */\nexport function restoreModelOptions(\n descriptor: ProviderDescriptor,\n modelId: string,\n remembered: Record<string, Record<string, boolean>> | undefined,\n): Record<string, boolean> | undefined {\n const validIds = new Set(modelOptionsFor(descriptor, modelId).map(o => o.id))\n if (validIds.size === 0)\n return undefined\n const enabled = enabledModelOptions(remembered?.[modelId])\n const filtered: Record<string, boolean> = {}\n for (const id of Object.keys(enabled)) {\n if (validIds.has(id))\n filtered[id] = true\n }\n return Object.keys(filtered).length > 0 ? filtered : undefined\n}\n","/**\n * Credential storage for the TUI.\n *\n * Lives at `<dataDir>/credentials.json` (default `~/.zidane/credentials.json`,\n * overridable via `ZIDANE_STORAGE_DIR`). Owner-only (0o600) so refresh tokens\n * and API keys don't leak on shared boxes.\n *\n * Two credential kinds:\n * - `apikey` — a plain API key entered by the user (e.g. via the setup wizard).\n * - `oauth` — tokens obtained via a provider's OAuth flow (refresh-aware).\n *\n * **Slots.** A provider may hold several credentials at once: at most one API\n * key and any number of OAuth accounts (optionally named via `label`). The\n * ACTIVE one — what every reader resolves — sits at the canonical file key;\n * the others sit at `#`-qualified siblings (`foo#alt` for the API key,\n * `foo#account:N` for OAuth accounts). See `./cred-keys` for the arithmetic.\n *\n * **Schema note.** File keys come from {@link ProviderDescriptor.credentialFileKey}\n * (falling back to `descriptor.key`). They must match what the harness providers\n * look up at runtime — for built-ins this is `anthropic`, `openai-codex`,\n * `openrouter`, `cerebras`. Hosts that ship custom providers control the file\n * key via the descriptor.\n *\n * A legacy `.credentials.json` (written by `bun run auth` in older versions)\n * is migrated on first read if the new file doesn't exist yet. It is only\n * trusted when it sits in the user's home dir or next to the new file. The\n * legacy file is left in place — we don't delete user data behind their back.\n */\n\nimport type { ProviderDescriptor, ProviderFactoryOptions } from './providers'\nimport { randomUUID } from 'node:crypto'\nimport { existsSync, readFileSync, realpathSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, resolve } from 'node:path'\nimport { writeFileAtomic } from '../atomic-write'\nimport { pinnedAccountMissingError, withCredentialsLock } from '../providers/oauth'\nimport {\n ACCOUNT_CRED_KEY_INFIX,\n ALTERNATE_CRED_KEY_SUFFIX,\n alternateCredKey,\n CRED_KEY_SLOT_SEPARATOR,\n credentialSlotKeys,\n credentialSlotOf,\n isAccountCredKey,\n isReservedCredKey,\n nextAccountCredKey,\n} from './cred-keys'\nimport { credKeyOf } from './providers'\n\nexport {\n ACCOUNT_CRED_KEY_INFIX,\n accountCredKey,\n ALTERNATE_CRED_KEY_SUFFIX,\n alternateCredKey,\n CRED_KEY_SLOT_SEPARATOR,\n credentialSlotKeys,\n credentialSlotOf,\n DEFAULT_OAUTH_ACCOUNT_LABEL,\n isAccountCredKey,\n isReservedCredKey,\n oauthAccountLabel,\n} from './cred-keys'\n\n/** POSIX mode for the credentials file. Ignored on Windows. */\nconst FILE_MODE = 0o600\n\n/**\n * Stable identity of one stored credential (an \"account\"): set when it is\n * stored and carried wherever the entry moves — promotion swaps entries\n * between slot keys, refresh spreads the stored entry into the rotated one.\n * What a session pinned to an account stores (`metadata.account`); resolve it\n * to the current slot with {@link credentialSlotOf}. Older files get one on\n * their next write ({@link ensureCredentialIds}).\n */\ninterface CredentialIdentity {\n id?: string\n}\n\n/** A stored API key credential. */\nexport interface ApiKeyCredential extends CredentialIdentity {\n /** Discriminant that marks an API key credential. */\n kind: 'apikey'\n /**\n * Bearer API key. May be empty when the descriptor has no `envKey` and\n * authenticates entirely via {@link customFields} (e.g. the `local`\n * provider, where the auth signal is the configured base URL).\n */\n value: string\n /**\n * Free-form fields collected by the wizard from the descriptor's\n * `customFields` definitions. Keys match the descriptor field's `key`.\n * Mirrored into `process.env[field.envVar]` by `applyApiKeyEnv` so the\n * provider's factory can read them via the existing env-var convention.\n */\n customFields?: Record<string, string>\n}\n/** A stored OAuth credential. */\nexport interface OAuthCredential extends CredentialIdentity {\n /** Discriminant that marks an OAuth credential. */\n kind: 'oauth'\n /** OAuth access token. */\n access: string\n /** Refresh token used to renew the access token. */\n refresh?: string\n /** Expiry time of the access token, as recorded by the OAuth flow. */\n expires?: number\n /**\n * User-given account name (\"work\", \"personal\"). Optional — absent reads as\n * `DEFAULT_OAUTH_ACCOUNT_LABEL` (see `oauthAccountLabel`). Survives token\n * refresh because the refresh path spreads the stored entry into the rotated\n * one (see `resolveOAuthApiKey`).\n */\n label?: string\n /** Provider-specific extras (e.g. OpenAI Codex `accountId`). */\n [extra: string]: unknown\n}\n/** Either an API key or an OAuth credential stored for a provider. */\nexport type ProviderCredential = ApiKeyCredential | OAuthCredential\n\n/** One stored credential of a provider, addressed by the file key it lives at. */\nexport interface StoredCredential {\n /** File key — the selection identity for promote / remove / relabel. */\n key: string\n /** The stored credential. */\n credential: ProviderCredential\n /** True for the canonical slot, i.e. the credential readers resolve. */\n active: boolean\n}\n\n/** Top-level shape of `credentials.json` — keys are credential-file keys. */\nexport type CredentialsFile = Record<string, ProviderCredential>\n\n/**\n * Resolve the credentials file path given the resolved TUI data directory\n * (typically `~/.zidane`, i.e. `config.paths.dir`).\n *\n * Matches the convention used elsewhere in the TUI (sessions.db, state.json)\n * so a single `ZIDANE_STORAGE_DIR` override moves the entire data root.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n */\nexport function credentialsPath(dataDir: string): string {\n return resolve(dataDir, 'credentials.json')\n}\n\n/**\n * Read credentials from disk.\n *\n * Returns `{}` when the file is missing or corrupt (last-ditch tolerance —\n * a hand-edit gone wrong shouldn't lock the user out of re-authing). On first\n * call with no file present, attempts a migration from a legacy\n * `.credentials.json` in the current directory (the location older `bun run auth`\n * versions used), when that directory is the home dir or the data dir.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n */\nexport function readCredentials(dataDir: string): CredentialsFile {\n const path = credentialsPath(dataDir)\n\n if (!existsSync(path)) {\n const migrated = migrateLegacyFile(path)\n if (migrated)\n return migrated\n return {}\n }\n\n return readStoredCredentials(path)\n}\n\nfunction readStoredCredentials(path: string): CredentialsFile {\n try {\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw)\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))\n return {}\n return normalizeCredentials(parsed as Record<string, unknown>)\n }\n catch {\n return {}\n }\n}\n\n/**\n * Re-tag legacy / refresh-stripped entries so the discriminated union holds.\n *\n * An untagged object with a string `access` is an OAuth credential — either the\n * pre-TUI `bun run auth` shape, or one whose `kind` was dropped when a token\n * refresh was persisted (a provider refresh returns no `kind`). Without\n * re-tagging, {@link detectAuth} and {@link applyApiKeyEnv} stop recognizing it\n * and force a spurious re-login. Mirrors the provider-side tolerance in\n * `readOAuthCredentials`. Entries with an explicit `kind` and anything we can't\n * classify pass through untouched.\n */\nfunction normalizeCredentials(parsed: Record<string, unknown>): CredentialsFile {\n const result: CredentialsFile = {}\n for (const [key, value] of Object.entries(parsed)) {\n // Only re-tag entries with no explicit `kind`; `isOAuthLegacy` (shared with\n // the legacy-file migration) is the \"object carrying an access token\" guard.\n const untagged = !!value && typeof value === 'object' && (value as Record<string, unknown>).kind === undefined\n if (untagged && isOAuthLegacy(value))\n result[key] = { ...value, kind: 'oauth' }\n else\n result[key] = value as ProviderCredential\n }\n return result\n}\n\n/**\n * Canonical file key for a descriptor, rejecting the reserved slot separator.\n *\n * Loud on a misconfigured provider instead of quietly mixing its credentials\n * into another provider's slot (extension registration refuses the separator\n * upfront; this covers descriptors passed in directly). Read paths stay\n * tolerant — only the functions that WRITE slots go through here.\n */\nfunction assertableCredKey(descriptor: ProviderDescriptor): string {\n const fileKey = credKeyOf(descriptor)\n if (isReservedCredKey(fileKey)) {\n throw new Error(\n `Provider \"${descriptor.key}\" uses credential key \"${fileKey}\", but `\n + `\"${CRED_KEY_SLOT_SEPARATOR}\" is reserved for a provider's extra credential slots `\n + `(\\`${ALTERNATE_CRED_KEY_SUFFIX}\\`, \\`${ACCOUNT_CRED_KEY_INFIX}N\\`).`,\n )\n }\n return fileKey\n}\n\n/**\n * Read a single provider's credential (translating via the descriptor).\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param descriptor - The provider descriptor that selects the credential file key.\n */\nexport function readProviderCredential(dataDir: string, descriptor: ProviderDescriptor): ProviderCredential | undefined {\n return readCredentials(dataDir)[credKeyOf(descriptor)]\n}\n\n/**\n * Both stored credentials for a provider: `active` is the one every reader\n * resolves, `alternate` is the stored-but-not-preferred one (if any).\n *\n * Predates multi-account and only sees the `#alt` slot; use\n * {@link readProviderCredentials} to list every stored account.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param descriptor - The provider descriptor that selects the credential file key.\n */\nexport function readProviderCredentialPair(\n dataDir: string,\n descriptor: ProviderDescriptor,\n): { active?: ProviderCredential, alternate?: ProviderCredential } {\n const all = readCredentials(dataDir)\n const fileKey = credKeyOf(descriptor)\n return { active: all[fileKey], alternate: all[alternateCredKey(fileKey)] }\n}\n\n/** Every file key holding one of `fileKey`'s credentials, in display order (`credentialSlotKeys`). */\nconst slotKeysOf = credentialSlotKeys\n\nfunction isSlotOf(fileKey: string, key: string): boolean {\n return key === fileKey || key === alternateCredKey(fileKey) || isAccountCredKey(fileKey, key)\n}\n\n/**\n * Every stored credential of a provider, active first.\n *\n * Tolerant of any kind in any slot: `#alt` is meant for the API key and\n * `#account:N` for OAuth accounts, but a file written by an older build (which\n * parked the OAuth alternate in `#alt`) must still list everything it holds.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param descriptor - The provider descriptor that selects the credential file key.\n */\nexport function readProviderCredentials(dataDir: string, descriptor: ProviderDescriptor): StoredCredential[] {\n return storedCredentialsOf(readCredentials(dataDir), credKeyOf(descriptor))\n}\n\n/**\n * One stored credential of a provider by its stable id (see\n * {@link CredentialIdentity}), wherever it sits now; `undefined` when it is\n * no longer stored.\n *\n * @param all - The parsed credentials file.\n * @param fileKey - The provider's canonical credential file key.\n * @param id - Stable credential id.\n */\nexport function storedCredentialById(all: CredentialsFile, fileKey: string, id: string): StoredCredential | undefined {\n const key = credentialSlotOf(all, fileKey, id)\n return key ? { key, credential: all[key]!, active: key === fileKey } : undefined\n}\n\n/**\n * Pure form of {@link readProviderCredentials} over an already-read file.\n *\n * @param all - The parsed credentials file.\n * @param fileKey - The provider's canonical credential file key.\n */\nexport function storedCredentialsOf(all: CredentialsFile, fileKey: string): StoredCredential[] {\n return slotKeysOf(all, fileKey).map(key => ({ key, credential: all[key], active: key === fileKey }))\n}\n\n/**\n * Write credentials atomically (write-then-rename) with mode 0o600.\n *\n * Atomic on the same filesystem — readers either see the previous file or the\n * new one, never a half-written intermediate. Creates the parent dir if needed\n * (first launch on a fresh machine: `~/.zidane/` may not exist yet).\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param creds - The full credentials file contents to write.\n */\nexport function writeCredentials(dataDir: string, creds: CredentialsFile): void {\n withCredentialsLock(credentialsPath(dataDir), () => writeCredentialsUnlocked(dataDir, creds))\n}\n\nfunction writeCredentialsUnlocked(dataDir: string, creds: CredentialsFile): void {\n writeFileAtomic(\n credentialsPath(dataDir),\n `${JSON.stringify(creds, null, 2)}\\n`,\n { ensureDir: true, mode: FILE_MODE },\n )\n}\n\n/**\n * Run `fn` against the on-disk file under the mutation lock and persist what it\n * returns. Migrates the legacy file first (migration takes the same lock).\n */\nfunction mutateCredentials<T>(\n dataDir: string,\n fn: (all: CredentialsFile) => { result: T, write: boolean },\n /**\n * File key of the provider this write is about: its credentials leave with\n * their stable ids. Only ITS slots — touching another provider's entries\n * (or a host token) would race that provider's in-flight refresh, which\n * refuses to persist over an entry that changed under it.\n */\n idsFor?: string,\n): T {\n readCredentials(dataDir)\n return withCredentialsLock(credentialsPath(dataDir), () => {\n const all = readStoredCredentials(credentialsPath(dataDir))\n const { result, write } = fn(all)\n if (write) {\n if (idsFor !== undefined)\n assignCredentialIds(all, credentialSlotKeys(all, idsFor))\n writeCredentialsUnlocked(dataDir, all)\n }\n return result\n })\n}\n\nfunction newCredentialId(): string {\n return randomUUID().replace(/-/g, '').slice(0, 12)\n}\n\nfunction isProviderCredential(value: unknown): value is ProviderCredential {\n return !!value && typeof value === 'object' && ((value as { kind?: unknown }).kind === 'apikey' || (value as { kind?: unknown }).kind === 'oauth')\n}\n\n/** Give each credential at `keys` that lacks one a stable id. True when any changed. */\nfunction assignCredentialIds(all: CredentialsFile, keys: readonly string[]): boolean {\n let changed = false\n for (const key of keys) {\n const value = all[key]\n if (isProviderCredential(value) && (typeof value.id !== 'string' || value.id === '')) {\n all[key] = { ...value, id: newCredentialId() }\n changed = true\n }\n }\n return changed\n}\n\n/**\n * Give every stored credential its stable id, once. Files from before ids\n * (and entries written by tools that replace them wholesale) are otherwise\n * only id-less until their next write; run at config resolve so pickers can\n * pin any listed account. No-op (no write) when every entry has one, or no\n * file exists.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param providers - Registered provider descriptors. Only their credential slots are given ids.\n */\nexport function ensureCredentialIds(dataDir: string, providers: Readonly<Record<string, ProviderDescriptor>>): void {\n const path = credentialsPath(dataDir)\n if (!existsSync(path))\n return\n // The registered providers' slots only: other entries (host tokens) are not accounts.\n const slotsOf = (all: CredentialsFile) => [...new Set(Object.values(providers).map(credKeyOf))].flatMap(fileKey => credentialSlotKeys(all, fileKey))\n const stored = readStoredCredentials(path)\n if (!slotsOf(stored).some(key => isProviderCredential(stored[key]) && typeof stored[key]?.id !== 'string'))\n return\n try {\n withCredentialsLock(path, () => {\n const all = readStoredCredentials(path)\n if (assignCredentialIds(all, slotsOf(all)))\n writeCredentialsUnlocked(dataDir, all)\n })\n }\n catch {\n // Best-effort: a held lock means another writer — which assigns ids too.\n }\n}\n\n/**\n * Read one entry by its file key, whatever owns it. For stores that keep a\n * secret beside the provider slots under their own namespace (the host\n * registry: `hosts:<id>`).\n */\nexport function readCredentialEntry(dataDir: string, key: string): ProviderCredential | undefined {\n return readCredentials(dataDir)[key]\n}\n\n/**\n * Write (or, `undefined`, delete) one entry by its file key, under the same\n * lock, mode and atomic write as every credential write. Refuses provider\n * slot keys (`#`): those go through the provider writers above.\n */\nexport function writeCredentialEntry(dataDir: string, key: string, cred: ProviderCredential | undefined): void {\n if (isReservedCredKey(key))\n throw new Error(`\"${key}\" is a provider credential slot.`)\n mutateCredentials(dataDir, (all) => {\n if (cred === undefined) {\n if (!(key in all))\n return { result: undefined, write: false }\n delete all[key]\n }\n else {\n all[key] = cred\n }\n return { result: undefined, write: true }\n })\n}\n\n/**\n * Move an OAuth grant out of `#alt` into an account slot.\n *\n * Before multi-account, `#alt` held whichever kind was not active — so a file\n * from that era can have an OAuth grant there. `#alt` is now the API key's\n * slot, and every writer below relies on that; relocating first means the\n * grant is preserved instead of overwritten when an API key gets demoted.\n */\nfunction relocateLegacyOAuthAlternate(all: CredentialsFile, fileKey: string): void {\n const altKey = alternateCredKey(fileKey)\n const alt = all[altKey]\n if (alt?.kind !== 'oauth')\n return\n delete all[altKey]\n all[nextAccountCredKey(fileKey, Object.keys(all))] = alt\n}\n\n/**\n * Park a credential that just lost the canonical slot.\n *\n * API keys go to `#alt` (there is at most one, so the slot is free once\n * `relocateLegacyOAuthAlternate` has run). OAuth grants reuse the slot the\n * promoted credential vacated when that was an account slot — a swap, no new\n * numbering — and otherwise take the next free `#account:N`.\n */\nfunction parkDemoted(all: CredentialsFile, fileKey: string, cred: ProviderCredential, vacated?: string): void {\n if (cred.kind === 'apikey') {\n all[alternateCredKey(fileKey)] = cred\n return\n }\n if (vacated && isAccountCredKey(fileKey, vacated)) {\n all[vacated] = cred\n return\n }\n all[nextAccountCredKey(fileKey, Object.keys(all))] = cred\n}\n\n/** `next` carrying `previous`'s stable id (when it had one). */\nfunction withIdOf<T extends ProviderCredential>(previous: ProviderCredential | undefined, next: T): T {\n return typeof previous?.id === 'string' ? { ...next, id: previous.id } : next\n}\n\n/** Options for {@link setProviderCredential}. */\nexport interface SetProviderCredentialOptions {\n /**\n * File key of the stored credential this one REPLACES (a re-auth of a known\n * account). The slot keeps its position — replacing the active one keeps it\n * active. When the key is no longer stored (removed from another window\n * mid-login), the credential is added as a new active account instead.\n */\n replaceKey?: string\n}\n\n/**\n * Store a credential as the provider's preferred one.\n *\n * The previous active credential is demoted, not destroyed: otherwise\n * authenticating with OAuth would silently delete a working API key (and vice\n * versa), and a second OAuth login would overwrite the first account. An API key moves to\n * {@link alternateCredKey}; an OAuth grant moves to the next free account slot.\n * Replacing an API key with an API key is a plain overwrite — there is only\n * ever one — and so is an OAuth login that names its predecessor via\n * `replaceKey`.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param descriptor - The provider descriptor that selects the credential file key.\n * @param cred - The credential to store as the preferred one.\n * @param opts - Options. `replaceKey` names the stored credential this one replaces.\n */\nexport function setProviderCredential(\n dataDir: string,\n descriptor: ProviderDescriptor,\n cred: ProviderCredential,\n opts: SetProviderCredentialOptions = {},\n): void {\n mutateCredentials(dataDir, (all) => {\n const fileKey = assertableCredKey(descriptor)\n relocateLegacyOAuthAlternate(all, fileKey)\n\n if (opts.replaceKey !== undefined) {\n if (!isSlotOf(fileKey, opts.replaceKey))\n throw new Error(`\"${opts.replaceKey}\" is not a credential slot of provider \"${descriptor.key}\"`)\n if (opts.replaceKey in all) {\n // A re-auth of a known account: still that account, so sessions pinned to it stay on it.\n all[opts.replaceKey] = withIdOf(all[opts.replaceKey], cred)\n return { result: undefined, write: true }\n }\n }\n\n const previous = all[fileKey]\n if (previous && !(previous.kind === 'apikey' && cred.kind === 'apikey'))\n parkDemoted(all, fileKey, previous)\n // A stale second API key in `#alt` (older builds could leave one) would\n // surface as a duplicate row that \"switches\" to itself.\n else if (cred.kind === 'apikey')\n delete all[alternateCredKey(fileKey)]\n // There is one API key per provider: a new one replaces it in place, same account.\n all[fileKey] = previous?.kind === 'apikey' && cred.kind === 'apikey' ? withIdOf(previous, cred) : cred\n return { result: undefined, write: true }\n }, credKeyOf(descriptor))\n}\n\n/**\n * Outcome of {@link setPreferredCredential}.\n *\n * Three states rather than a boolean because the two non-promoting cases need\n * opposite handling: `already-active` is a harmless idempotent call (the UI\n * repaints and moves on), while `not-stored` means the caller asked for a\n * credential that does not exist and should say so.\n */\nexport type PreferCredentialResult = 'promoted' | 'already-active' | 'not-stored'\n\n/**\n * What {@link setPreferredCredential} promotes: a stored credential by file\n * key (from {@link readProviderCredentials} / `AuthMethod.key`), or the first\n * stored credential of a kind — the right form when the caller only knows\n * \"switch to the API key\".\n */\nexport type PreferredCredentialTarget = ProviderCredential['kind'] | { key: string }\n\n/**\n * Make one of the provider's stored credentials the preferred one.\n *\n * Swaps the target into the canonical slot and parks the previous active one\n * (see {@link parkDemoted}). Returns which of the three outcomes happened so a\n * caller cannot report a swap that provably did not occur — the write is\n * silent either way, and a `void` return would look like success to a caller\n * that trusted it instead of refetching.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param descriptor - The provider descriptor that selects the credential file key.\n * @param target - A credential kind or a stored credential's file key.\n */\nexport function setPreferredCredential(\n dataDir: string,\n descriptor: ProviderDescriptor,\n target: PreferredCredentialTarget,\n): PreferCredentialResult {\n return mutateCredentials(dataDir, (all) => {\n const fileKey = assertableCredKey(descriptor)\n relocateLegacyOAuthAlternate(all, fileKey)\n const active = all[fileKey]\n\n let key: string | undefined\n if (typeof target === 'string') {\n if (active?.kind === target)\n return { result: 'already-active', write: false }\n key = slotKeysOf(all, fileKey).find(k => k !== fileKey && all[k]?.kind === target)\n }\n else {\n if (target.key === fileKey && active)\n return { result: 'already-active', write: false }\n key = isSlotOf(fileKey, target.key) && target.key in all ? target.key : undefined\n }\n if (key === undefined)\n return { result: 'not-stored', write: false }\n\n const promoted = all[key]\n delete all[key]\n all[fileKey] = promoted\n if (active)\n parkDemoted(all, fileKey, active, key)\n return { result: 'promoted', write: true }\n }, credKeyOf(descriptor))\n}\n\n/**\n * Drop ONE stored credential. Removing the active one promotes a survivor —\n * another credential of the same kind when there is one (a second OAuth\n * account), else whatever is left — so the provider does not go dark while it\n * still holds a working credential. Returns false when `key` was not stored.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param descriptor - The provider descriptor that selects the credential file key.\n * @param key - File key of the credential to remove.\n */\nexport function removeStoredCredential(dataDir: string, descriptor: ProviderDescriptor, key: string): boolean {\n return mutateCredentials(dataDir, (all) => {\n const fileKey = credKeyOf(descriptor)\n if (!isSlotOf(fileKey, key) || !(key in all))\n return { result: false, write: false }\n const removed = all[key]\n delete all[key]\n if (key === fileKey) {\n const rest = slotKeysOf(all, fileKey)\n const successor = rest.find(k => all[k]?.kind === removed.kind) ?? rest[0]\n if (successor !== undefined) {\n all[fileKey] = all[successor]\n delete all[successor]\n }\n }\n return { result: true, write: true }\n }, credKeyOf(descriptor))\n}\n\n/**\n * Name a stored OAuth account. An empty label drops the field, which reads\n * back as {@link DEFAULT_OAUTH_ACCOUNT_LABEL}. Returns false when `key` holds\n * no OAuth credential.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param descriptor - The provider descriptor that selects the credential file key.\n * @param key - File key of the OAuth credential to name.\n * @param label - New account name. An empty or whitespace-only value clears it.\n */\nexport function setCredentialLabel(dataDir: string, descriptor: ProviderDescriptor, key: string, label: string): boolean {\n return mutateCredentials(dataDir, (all) => {\n const fileKey = credKeyOf(descriptor)\n const entry = isSlotOf(fileKey, key) ? all[key] : undefined\n if (entry?.kind !== 'oauth')\n return { result: false, write: false }\n const trimmed = label.trim()\n if (trimmed)\n entry.label = trimmed\n else\n delete entry.label\n return { result: true, write: true }\n }, credKeyOf(descriptor))\n}\n\n/**\n * Sign a provider out — drops EVERY stored credential.\n *\n * \"Signed out\" has to mean the provider resolves nothing afterwards, which is\n * what this guarantees; promoting a survivor instead would silently leave the\n * provider authenticated through another source. Callers that want that behavior use\n * {@link removeStoredCredential} on the one slot they mean.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param descriptor - The provider descriptor that selects the credential file key.\n */\nexport function removeProviderCredential(dataDir: string, descriptor: ProviderDescriptor): void {\n mutateCredentials(dataDir, (all) => {\n const keys = slotKeysOf(all, credKeyOf(descriptor))\n for (const key of keys)\n delete all[key]\n return { result: undefined, write: keys.length > 0 }\n })\n}\n\n/**\n * Reconcile `process.env` with the stored credentials so the harness providers\n * pick up the wizard's output via their existing env-var resolution. Each\n * host (TUI, daemon, desktop app) calls it at launch after the credentials file\n * has been resolved, and again after a credential change.\n *\n * **Precedence: stored credential > ambient env.** When the user has run the\n * auth wizard, that's an explicit, recent action — it MUST win over whatever\n * ambient value is already in `process.env`. Otherwise an upgrade reliably\n * breaks for anyone whose cwd happens to contain a stale `.env`: Bun\n * auto-loads `.env` from cwd into `process.env` before our code runs, older\n * versions of `bun run auth` upserted tokens into `cwd/.env`, and even a\n * one-off `export ANTHROPIC_API_KEY=…` from months ago in the user's shell rc\n * can outlive its usefulness. None of those should override a key the user\n * just typed into the wizard.\n *\n * Three cases per registered provider with an `envKey`:\n *\n * 1. Stored `kind: 'apikey'` → overwrite env with the stored value. Wizard\n * wins. A debug log fires when this clobbers a different ambient value.\n * 2. Stored `kind: 'oauth'` → DELETE env, so {@link resolveOAuthApiKey}\n * falls through to the file-read + refresh path. A stale OAuth token\n * in env would otherwise short-circuit refresh and get rejected.\n * 3. No stored entry → leave env alone. Env-only setups (no wizard run yet,\n * hosts driving zidane purely from secrets management) keep working.\n *\n * To opt out and force ambient env to win again, the user signs the provider\n * out via the wizard (which deletes the stored entry → case 3 above).\n *\n * Descriptors without an `envKey` (OAuth-only providers, custom providers\n * that bypass env-var resolution) are skipped silently.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param registry - Provider descriptors keyed by id.\n * @param opts - Options. `log` receives diagnostics and defaults to a write to stderr.\n */\nexport function applyApiKeyEnv(\n dataDir: string,\n registry: Readonly<Record<string, ProviderDescriptor>>,\n opts: { log?: (message: string) => void } = {},\n): void {\n // Diagnostics default to stderr, which is correct for the ONE launch-time\n // call this was written for — it runs before the renderer owns the terminal.\n // Callers that run while a full-screen TUI is up (a credential swap from the\n // settings modal) must pass a sink instead: a raw stderr write mid-render\n // paints straight over the frame.\n const log = opts.log ?? (message => void process.stderr.write(message))\n const creds = readCredentials(dataDir)\n for (const descriptor of Object.values(registry)) {\n const cred = creds[credKeyOf(descriptor)]\n\n // Mirror customFields → env regardless of whether the descriptor has an\n // envKey. Same \"stored beats ambient\" semantics as the API-key path.\n if (cred?.kind === 'apikey' && descriptor.customFields) {\n const stored = cred.customFields ?? {}\n for (const field of descriptor.customFields) {\n const value = stored[field.key]\n if (typeof value === 'string' && value.length > 0) {\n const ambient = process.env[field.envVar]\n if (ambient && ambient !== value && process.env.ZIDANE_DEBUG) {\n log(\n `[zidane/chat] applyApiKeyEnv: overriding ambient \\`${field.envVar}\\` `\n + `with stored value from credentials.json (provider=${descriptor.key}, field=${field.key}).\\n`,\n )\n }\n process.env[field.envVar] = value\n }\n }\n }\n\n if (!descriptor.envKey)\n continue\n const envKey = descriptor.envKey\n const ambient = process.env[envKey]\n\n if (cred?.kind === 'apikey' && cred.value) {\n if (ambient && ambient !== cred.value && process.env.ZIDANE_DEBUG) {\n log(\n `[zidane/chat] applyApiKeyEnv: overriding ambient \\`${envKey}\\` `\n + `with stored API key from credentials.json (provider=${descriptor.key}). `\n + `Sign out via the auth wizard if the ambient value was intended to win.\\n`,\n )\n }\n process.env[envKey] = cred.value\n continue\n }\n\n if (cred?.kind === 'oauth' && cred.access) {\n if (ambient !== undefined && process.env.ZIDANE_DEBUG) {\n log(\n `[zidane/chat] applyApiKeyEnv: clearing ambient \\`${envKey}\\` because `\n + `credentials.json has stored OAuth for ${descriptor.key} and needs the file to refresh it.\\n`,\n )\n }\n delete process.env[envKey]\n continue\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Legacy migration\n// ---------------------------------------------------------------------------\n\n/**\n * `bun run auth` (pre-TUI) wrote `.credentials.json` in the current directory\n * with an entry per provider mapping directly to an OAuthCredentials payload, e.g.:\n *\n * {\n * \"anthropic\": { \"access\": \"...\", \"refresh\": \"...\", \"expires\": 123 },\n * \"openai-codex\": { \"access\": \"...\", \"refresh\": \"...\", \"expires\": 123, \"accountId\": \"...\" }\n * }\n *\n * We don't delete the legacy file — it might still be used by a host that\n * imports the harness directly. We just copy its contents into the new\n * location under the kind-tagged shape so the TUI picks them up.\n *\n * The file is only read when it sits in the home dir or in the data dir (see the\n * check below). Migration is provider-agnostic: any top-level entry with an `access` field\n * is preserved verbatim (extras included), under the same key. The TUI's\n * detection then looks them up via the matching descriptor's `credentialFileKey`.\n *\n * Returns the migrated credentials when the migration ran, or `null` when\n * there's no legacy file to migrate.\n */\nfunction migrateLegacyFile(targetPath: string): CredentialsFile | null {\n const legacyPath = resolve(process.cwd(), '.credentials.json')\n // Only trust a legacy file that sits directly in the user's home dir (where\n // `bun run auth` was typically run) or next to the migration target. A\n // cwd-relative read from an arbitrary checkout would let an untrusted repo\n // plant a `.credentials.json` that gets persisted as the USER-LEVEL\n // credential file. Compared via realpath so symlinked dirs (e.g. macOS\n // `/var` → `/private/var`) don't defeat the check.\n const real = (p: string): string => {\n try {\n return realpathSync(p)\n }\n catch {\n return p\n }\n }\n const legacyDir = real(dirname(legacyPath))\n if (legacyDir !== real(homedir()) && legacyDir !== real(dirname(resolve(targetPath))))\n return null\n if (!existsSync(legacyPath))\n return null\n\n let legacy: Record<string, unknown>\n try {\n legacy = JSON.parse(readFileSync(legacyPath, 'utf-8'))\n }\n catch {\n return null\n }\n if (!legacy || typeof legacy !== 'object' || Array.isArray(legacy))\n return null\n\n const migrated: CredentialsFile = {}\n for (const [fileKey, value] of Object.entries(legacy)) {\n if (!isOAuthLegacy(value))\n continue\n const { access, refresh, expires, ...extras } = value\n migrated[fileKey] = {\n kind: 'oauth',\n access,\n ...(typeof refresh === 'string' ? { refresh } : {}),\n ...(typeof expires === 'number' ? { expires } : {}),\n ...extras,\n }\n }\n\n if (Object.keys(migrated).length === 0)\n return null\n\n return withCredentialsLock(targetPath, () => {\n if (existsSync(targetPath))\n return readStoredCredentials(targetPath)\n writeFileAtomic(targetPath, `${JSON.stringify(migrated, null, 2)}\\n`, { ensureDir: true, mode: FILE_MODE })\n return migrated\n })\n}\n\nfunction isOAuthLegacy(value: unknown): value is { access: string, refresh?: string, expires?: number, [extra: string]: unknown } {\n return (\n typeof value === 'object'\n && value !== null\n && 'access' in value\n && typeof (value as { access: unknown }).access === 'string'\n )\n}\n\n/**\n * Factory options that build `descriptor` on its stored account `account`\n * (a credential id), or `undefined` for the provider's active account: no\n * account asked for, or a provider whose factory cannot take one\n * (`descriptor.accounts`). An OAuth account rides as `account` and is resolved\n * to its slot on every token read; an API-key account as its key. An account\n * no longer stored still rides as `account`, so the call fails with the\n * pinned-account error instead of quietly running on the active account.\n *\n * @param dataDir - Directory holding `credentials.json`, usually `config.paths.dir`.\n * @param descriptor - The provider descriptor that selects the credential file key.\n * @param account - Id of the stored account to pin, or `undefined` for the active account.\n */\nexport function providerFactoryOptions(\n dataDir: string,\n descriptor: ProviderDescriptor,\n account: string | undefined,\n): ProviderFactoryOptions | undefined {\n if (!account || descriptor.accounts !== true)\n return undefined\n const stored = storedCredentialById(readCredentials(dataDir), credKeyOf(descriptor), account)\n if (stored?.credential.kind === 'apikey') {\n if (!stored.credential.value)\n throw new Error(pinnedAccountMissingError(descriptor.label))\n return { apiKey: stored.credential.value }\n }\n return { account }\n}\n"],"mappings":"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"}
|
package/dist/daemon-cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { l as defaultSocketPath } from "./settings-keys-
|
|
3
|
-
import { a as startIpcDaemon, t as fixPath } from "./shell-path-
|
|
2
|
+
import { l as defaultSocketPath } from "./settings-keys-CPdmkTz7.js";
|
|
3
|
+
import { a as startIpcDaemon, t as fixPath } from "./shell-path-B8b3EOtK.js";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { spawnSync } from "node:child_process";
|
|
6
6
|
import { parseArgs } from "node:util";
|
|
@@ -6,24 +6,24 @@ import { i as writeJsonFileAtomic, n as writeFileAtomic, t as OWNER_ONLY } from
|
|
|
6
6
|
import { a as loginMcpServer, l as createPathAutocompleteProvider, u as resolveInlineSuggestion } from "./src-B8dW-xgG.js";
|
|
7
7
|
import { t as projectUserPaths } from "./project-user-paths-DWqZyUgb.js";
|
|
8
8
|
import { f as abortableInstallIo, s as installSkillFromSpec } from "./skills-DxT9Cnkt.js";
|
|
9
|
-
import { c as removeInstalledExtension, i as installExtensionFromSpec, l as updateInstalledExtension, m as filterRegistryPlugins, n as ExtensionInstallError, nt as createExtensionBus, rt as serializedPayloadBytes, u as discoverAndBuildExtensionRegistry, x as createExtensionHostRuntimeBridge, y as createExtensionHud } from "./extensions-
|
|
10
|
-
import { n as compareVersions, t as ZIDANE_VERSION } from "./version-
|
|
9
|
+
import { c as removeInstalledExtension, i as installExtensionFromSpec, l as updateInstalledExtension, m as filterRegistryPlugins, n as ExtensionInstallError, nt as createExtensionBus, rt as serializedPayloadBytes, u as discoverAndBuildExtensionRegistry, x as createExtensionHostRuntimeBridge, y as createExtensionHud } from "./extensions-BgBwogRW.js";
|
|
10
|
+
import { n as compareVersions, t as ZIDANE_VERSION } from "./version-bd3DQJkc.js";
|
|
11
11
|
import { n as canSignInRemotely } from "./server-uWgMffBf.js";
|
|
12
12
|
import { i as sqliteStoreFile } from "./sqlite-store-DITTl5as.js";
|
|
13
13
|
import { a as errorResponse, r as createJsonRpcConnection } from "./json-rpc-G0rBfEar.js";
|
|
14
|
-
import { R as selectActiveTodos, i as describeForkFailure, z as setTodosForRun } from "./session-factory-
|
|
14
|
+
import { R as selectActiveTodos, i as describeForkFailure, z as setTodosForRun } from "./session-factory-CMwIXE-7.js";
|
|
15
15
|
import { d as sessionModelFallbacks, u as readSessionAccount } from "./turn-operations-CWoCTC_L.js";
|
|
16
16
|
import { M as isMainSession, N as isSideSession, f as readSessionSpaceId, r as SPACE_METADATA_KEY, t as DEFAULT_SPACE_ID } from "./spaces-CyjMh5Zf.js";
|
|
17
|
-
import { F as sparseSettingsUpdate, O as DEFAULT_SETTINGS, P as settingsFromStored, f as enforceSettingsInvariants, i as looksLikeSecret, n as isSecretName, r as isSecretPathSegment, t as KNOWN_TOKEN, u as SETTINGS_TOGGLES } from "./secret-shapes-
|
|
18
|
-
import { I as writeProjects, N as readProjects, P as safelistProjectKey, _ as parseMcpsFile, a as settingsFromWire, d as userSystemMdPath, h as discoverProjectMcps, o as settingsToWire, r as isWindowOnlySetting } from "./host-scoped-settings-
|
|
19
|
-
import { G as readPinnedSkills, H as normalizeLaunchOverrides, I as TITLE_SOURCE_KEY, K as isStaleRunMarker, Lt as scopeCwd, N as isInside, Rt as buildPluginContributions, S as applyEnvironmentSettingsChange, U as PINNED_SKILLS_META_KEY, W as pinnedSkillsValue, Xt as
|
|
17
|
+
import { F as sparseSettingsUpdate, O as DEFAULT_SETTINGS, P as settingsFromStored, f as enforceSettingsInvariants, i as looksLikeSecret, n as isSecretName, r as isSecretPathSegment, t as KNOWN_TOKEN, u as SETTINGS_TOGGLES } from "./secret-shapes-BjW4l6U0.js";
|
|
18
|
+
import { I as writeProjects, N as readProjects, P as safelistProjectKey, _ as parseMcpsFile, a as settingsFromWire, d as userSystemMdPath, h as discoverProjectMcps, o as settingsToWire, r as isWindowOnlySetting } from "./host-scoped-settings-C-Nmb6vr.js";
|
|
19
|
+
import { $t as testDecisionModel, G as readPinnedSkills, H as normalizeLaunchOverrides, I as TITLE_SOURCE_KEY, K as isStaleRunMarker, Lt as scopeCwd, N as isInside, Rt as buildPluginContributions, S as applyEnvironmentSettingsChange, U as PINNED_SKILLS_META_KEY, W as pinnedSkillsValue, Xt as listDecisionModels, Yt as listImageModels, bt as machineDiscoveryCwd, c as mcpsWritePath, d as createExtensionMcpHost, f as resolveConfig, l as removeMcpServer, lt as discoverProjectSkills, m as createChatHost, q as toTodosSnapshot, r as runOAuthLogin, rn as createMemoryApprovalsStore, s as testModel, u as upsertMcpServer, v as createFileMcpCredentialStore, xt as insideDeclaredRoots, yt as createProviderBuilder, zt as discoverProjectPlugins } from "./oauth-7_48zR7n.js";
|
|
20
20
|
import { E as toolResultText, S as sumRunCosts, _ as runProgress, a as eventsFromTurns, b as sessionEnvironmentSummary, c as headerFromData, g as runInProgress, i as deriveSessionTitle, l as lastContextSizeFromTurns, o as getSessionHeader, s as getSessionMeta, u as listSessionMeta } from "./store-L01W0gGI.js";
|
|
21
21
|
import { c as searchSessionHistoryIndexAsync, n as buildSessionSearchIndexAsync, u as searchSessionIndexAsync } from "./history-search-CbDaXIfU.js";
|
|
22
|
-
import { et as remoteHostsGate, it as MachineErrorCode, lt as toMachineName, n as enabledMcpsWithout, t as enabledMcpsWith } from "./mcp-allowlist-
|
|
23
|
-
import { d as removeStoredCredential, l as readProviderCredentials, m as setProviderCredential, n as credentialsPath, t as applyApiKeyEnv, u as removeProviderCredential, y as BUILTIN_PROVIDERS } from "./credentials-
|
|
24
|
-
import { r as detectAuth } from "./cli-shared-
|
|
22
|
+
import { et as remoteHostsGate, it as MachineErrorCode, lt as toMachineName, n as enabledMcpsWithout, t as enabledMcpsWith } from "./mcp-allowlist-CLXweyxk.js";
|
|
23
|
+
import { d as removeStoredCredential, l as readProviderCredentials, m as setProviderCredential, n as credentialsPath, t as applyApiKeyEnv, u as removeProviderCredential, y as BUILTIN_PROVIDERS } from "./credentials-B9DfBJP9.js";
|
|
24
|
+
import { r as detectAuth } from "./cli-shared-E5m_pI8A.js";
|
|
25
25
|
import { i as METHOD_NOT_FOUND } from "./connection-BaHd3T-D.js";
|
|
26
|
-
import { a as createSignalListeners, f as probeSocket, i as IpcVersionMismatchError, n as hashValue, o as openIpcClient, r as isRecord, s as IPC_BUILD_ID, t as isSyncableSetting, u as ensureDaemonRunning } from "./settings-keys-
|
|
26
|
+
import { a as createSignalListeners, f as probeSocket, i as IpcVersionMismatchError, n as hashValue, o as openIpcClient, r as isRecord, s as IPC_BUILD_ID, t as isSyncableSetting, u as ensureDaemonRunning } from "./settings-keys-CPdmkTz7.js";
|
|
27
27
|
import { n as IpcErrorCode, o as REDACTED, s as SESSION_TURNS_MAX_PAGE } from "./protocol-BIv1Yuvl.js";
|
|
28
28
|
import { a as isPagedLoad, c as loadOrThrow, d as nonNegativeInt, f as optionalString, l as InvalidParamsError, n as createTranscriptReplayCache, p as sessionIdOf, t as changedSessionOf, u as checkParams } from "./transcript-cache-DXdgVuoy.js";
|
|
29
29
|
import { c as settingField, n as SYNC_CATEGORIES, o as SYSTEM_MD_FIELD } from "./types-B4oqzENY.js";
|
|
@@ -562,7 +562,7 @@ function createMachineLinkHandlers(options) {
|
|
|
562
562
|
});
|
|
563
563
|
};
|
|
564
564
|
const load = () => {
|
|
565
|
-
links ??= import("./links-
|
|
565
|
+
links ??= import("./links-rFaWqS2Y.js").then(({ startMachineLinks }) => startMachineLinks({
|
|
566
566
|
dataDir: env.userDataDir(),
|
|
567
567
|
machines: host.machines,
|
|
568
568
|
hostId: options.hostId,
|
|
@@ -1796,12 +1796,25 @@ function createCatalogHandlers({ env, host }) {
|
|
|
1796
1796
|
providers: config.providers,
|
|
1797
1797
|
authed
|
|
1798
1798
|
});
|
|
1799
|
+
const imageModels = listImageModels({
|
|
1800
|
+
providers: config.providers,
|
|
1801
|
+
authed
|
|
1802
|
+
});
|
|
1799
1803
|
return { providers: authed.map((auth) => {
|
|
1800
1804
|
const decisions = decisionModels.filter((entry) => entry.providerKey === auth.key).map((entry) => ({
|
|
1801
1805
|
id: entry.modelId,
|
|
1802
1806
|
available: entry.available,
|
|
1803
1807
|
...entry.reason ? { reason: entry.reason } : {}
|
|
1804
1808
|
}));
|
|
1809
|
+
const images = imageModels.filter((entry) => entry.providerKey === auth.key).map((entry) => ({
|
|
1810
|
+
id: entry.modelId,
|
|
1811
|
+
name: entry.modelName,
|
|
1812
|
+
references: entry.references,
|
|
1813
|
+
transparency: entry.transparency,
|
|
1814
|
+
available: entry.available,
|
|
1815
|
+
...entry.reason ? { reason: entry.reason } : {},
|
|
1816
|
+
...entry.isDefault ? { isDefault: true } : {}
|
|
1817
|
+
}));
|
|
1805
1818
|
return {
|
|
1806
1819
|
key: auth.key,
|
|
1807
1820
|
label: config.providers[auth.key]?.label ?? auth.label,
|
|
@@ -1811,7 +1824,8 @@ function createCatalogHandlers({ env, host }) {
|
|
|
1811
1824
|
label,
|
|
1812
1825
|
active
|
|
1813
1826
|
})) } : {},
|
|
1814
|
-
...decisions.length > 0 ? { decisionModels: decisions } : {}
|
|
1827
|
+
...decisions.length > 0 ? { decisionModels: decisions } : {},
|
|
1828
|
+
...images.length > 0 ? { imageModels: images } : {}
|
|
1815
1829
|
};
|
|
1816
1830
|
}) };
|
|
1817
1831
|
},
|
|
@@ -2265,7 +2279,7 @@ function createMachineServeHandlers(input) {
|
|
|
2265
2279
|
return existing.executor;
|
|
2266
2280
|
}
|
|
2267
2281
|
makeRoom(principal);
|
|
2268
|
-
const { createMachineExecutor } = await import("./executor-
|
|
2282
|
+
const { createMachineExecutor } = await import("./executor-BhthPE1q.js");
|
|
2269
2283
|
const entry = {
|
|
2270
2284
|
peer,
|
|
2271
2285
|
principal,
|
|
@@ -5460,4 +5474,4 @@ async function createHostDispatcher(options) {
|
|
|
5460
5474
|
//#endregion
|
|
5461
5475
|
export { historyWorkerUrl as a, createWorkerRpcClient as c, createDaemonEnvironment as d, createFileApprovalsStore as f, createPacedWriter as g, connectOrSpawnDaemon as h, createTranscriptHistoryWorker as i, createMachineHandlers as l, connectIpcClient as m, HISTORY_WORKER_KILL_SWITCH as n, WorkerRequestError as o, createHostEnvironment as p, createHostTranscriptPager as r, WorkerUnavailableError as s, createHostDispatcher as t, createMachineLinkHandlers as u };
|
|
5462
5476
|
|
|
5463
|
-
//# sourceMappingURL=dispatcher-
|
|
5477
|
+
//# sourceMappingURL=dispatcher-Bv9-c6I2.js.map
|