gsd-pi 2.44.0-dev.0b97ffd → 2.44.0-dev.73f2fd5
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/resources/extensions/gsd/auto/infra-errors.js +3 -0
- package/dist/resources/extensions/gsd/auto/phases.js +36 -36
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
- package/dist/resources/extensions/gsd/auto-timers.js +57 -3
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +9 -6
- package/dist/resources/extensions/gsd/auto.js +30 -3
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +156 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -1
- package/dist/resources/extensions/gsd/commands/handlers/core.js +1 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +5 -0
- package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
- package/dist/resources/extensions/gsd/db-writer.js +34 -16
- package/dist/resources/extensions/gsd/doctor.js +8 -0
- package/dist/resources/extensions/gsd/git-service.js +8 -3
- package/dist/resources/extensions/gsd/gsd-db.js +12 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
- package/dist/resources/extensions/gsd/preferences.js +9 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
- package/dist/resources/extensions/gsd/state.js +19 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +1 -0
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +6 -0
- package/dist/resources/extensions/mcp-client/index.js +14 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +16 -16
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +16 -16
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +20 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/main.js +17 -0
- package/packages/pi-coding-agent/dist/main.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
- package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -1
- package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
- package/packages/pi-coding-agent/src/main.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
- package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
- package/src/resources/extensions/gsd/auto/phases.ts +45 -48
- package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
- package/src/resources/extensions/gsd/auto-timers.ts +64 -3
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +9 -6
- package/src/resources/extensions/gsd/auto.ts +37 -3
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +148 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/core.ts +1 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +5 -0
- package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
- package/src/resources/extensions/gsd/db-writer.ts +39 -17
- package/src/resources/extensions/gsd/doctor.ts +7 -1
- package/src/resources/extensions/gsd/git-service.ts +6 -2
- package/src/resources/extensions/gsd/gsd-db.ts +16 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
- package/src/resources/extensions/gsd/preferences.ts +11 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
- package/src/resources/extensions/gsd/state.ts +19 -1
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -0
- package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +7 -0
- package/src/resources/extensions/mcp-client/index.ts +20 -0
- /package/dist/web/standalone/.next/static/{alS4hoANx0TK4UVZY27da → kxxAA66bah_yhPYqLBHE2}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{alS4hoANx0TK4UVZY27da → kxxAA66bah_yhPYqLBHE2}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-storage.js","sourceRoot":"","sources":["../../src/core/auth-storage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Credential storage for API keys and OAuth tokens.\n * Handles loading, saving, and refreshing credentials from auth.json.\n *\n * Supports multiple credentials per provider with round-robin selection,\n * session-sticky hashing, and automatic rate-limit fallback.\n *\n * Uses file locking to prevent race conditions when multiple pi instances\n * try to refresh tokens simultaneously.\n */\n\nimport {\n\tgetEnvApiKey,\n\ttype OAuthCredentials,\n\ttype OAuthLoginCallbacks,\n\ttype OAuthProviderId,\n} from \"@gsd/pi-ai\";\nimport { getOAuthApiKey, getOAuthProvider, getOAuthProviders } from \"@gsd/pi-ai/oauth\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AUTH_LOCK_STALE_MS } from \"./constants.js\";\nimport { acquireLockAsync, acquireLockSyncWithRetry } from \"./lock-utils.js\";\nimport { resolveConfigValue } from \"./resolve-config-value.js\";\n\nexport type ApiKeyCredential = {\n\ttype: \"api_key\";\n\tkey: string;\n};\n\nexport type OAuthCredential = {\n\ttype: \"oauth\";\n} & OAuthCredentials;\n\nexport type AuthCredential = ApiKeyCredential | OAuthCredential;\n\n/**\n * On-disk format: each provider maps to a single credential or an array of credentials.\n * Single credentials are normalized to arrays at load time for internal use.\n */\nexport type AuthStorageData = Record<string, AuthCredential | AuthCredential[]>;\n\ntype LockResult<T> = {\n\tresult: T;\n\tnext?: string;\n};\n\nexport interface AuthStorageBackend {\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T;\n\twithLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T>;\n}\n\nexport class FileAuthStorageBackend implements AuthStorageBackend {\n\tconstructor(private authPath: string = join(getAgentDir(), \"auth.json\")) {}\n\n\tprivate ensureParentDir(): void {\n\t\tconst dir = dirname(this.authPath);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t\t}\n\t}\n\n\tprivate ensureFileExists(): void {\n\t\tif (!existsSync(this.authPath)) {\n\t\t\twriteFileSync(this.authPath, \"{}\", \"utf-8\");\n\t\t\tchmodSync(this.authPath, 0o600);\n\t\t}\n\t}\n\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T {\n\t\tthis.ensureParentDir();\n\t\tthis.ensureFileExists();\n\n\t\tlet release: (() => void) | undefined;\n\t\ttry {\n\t\t\trelease = acquireLockSyncWithRetry(this.authPath);\n\t\t\tconst current = existsSync(this.authPath) ? readFileSync(this.authPath, \"utf-8\") : undefined;\n\t\t\tconst { result, next } = fn(current);\n\t\t\tif (next !== undefined) {\n\t\t\t\twriteFileSync(this.authPath, next, \"utf-8\");\n\t\t\t\tchmodSync(this.authPath, 0o600);\n\t\t\t}\n\t\t\treturn result;\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\trelease();\n\t\t\t}\n\t\t}\n\t}\n\n\tasync withLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T> {\n\t\tthis.ensureParentDir();\n\t\tthis.ensureFileExists();\n\n\t\tlet release: (() => Promise<void>) | undefined;\n\t\tlet lockCompromised = false;\n\t\tlet lockCompromisedError: Error | undefined;\n\t\tconst throwIfCompromised = () => {\n\t\t\tif (lockCompromised) {\n\t\t\t\tthrow lockCompromisedError ?? new Error(\"Auth storage lock was compromised\");\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\trelease = await acquireLockAsync(this.authPath, {\n\t\t\t\tstaleMs: AUTH_LOCK_STALE_MS,\n\t\t\t\tonCompromised: (err) => {\n\t\t\t\t\tlockCompromised = true;\n\t\t\t\t\tlockCompromisedError = err;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tthrowIfCompromised();\n\t\t\tconst current = existsSync(this.authPath) ? readFileSync(this.authPath, \"utf-8\") : undefined;\n\t\t\tconst { result, next } = await fn(current);\n\t\t\tthrowIfCompromised();\n\t\t\tif (next !== undefined) {\n\t\t\t\twriteFileSync(this.authPath, next, \"utf-8\");\n\t\t\t\tchmodSync(this.authPath, 0o600);\n\t\t\t}\n\t\t\tthrowIfCompromised();\n\t\t\treturn result;\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\ttry {\n\t\t\t\t\tawait release();\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore unlock errors when lock is compromised.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class InMemoryAuthStorageBackend implements AuthStorageBackend {\n\tprivate value: string | undefined;\n\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T {\n\t\tconst { result, next } = fn(this.value);\n\t\tif (next !== undefined) {\n\t\t\tthis.value = next;\n\t\t}\n\t\treturn result;\n\t}\n\n\tasync withLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T> {\n\t\tconst { result, next } = await fn(this.value);\n\t\tif (next !== undefined) {\n\t\t\tthis.value = next;\n\t\t}\n\t\treturn result;\n\t}\n}\n\n// ============================================================================\n// Backoff durations for different error types (milliseconds)\n// ============================================================================\n\nconst BACKOFF_RATE_LIMIT_MS = 30_000; // 30s for rate limit / 429\nconst BACKOFF_QUOTA_EXHAUSTED_MS = 30 * 60_000; // 30min for quota exhausted\nconst BACKOFF_SERVER_ERROR_MS = 20_000; // 20s for 5xx server errors\nconst BACKOFF_DEFAULT_MS = 60_000; // 60s fallback\n\nexport type UsageLimitErrorType = \"rate_limit\" | \"quota_exhausted\" | \"server_error\" | \"unknown\";\n\n/**\n * Get backoff duration for an error type.\n */\nfunction getBackoffDuration(errorType: UsageLimitErrorType): number {\n\tswitch (errorType) {\n\t\tcase \"rate_limit\":\n\t\t\treturn BACKOFF_RATE_LIMIT_MS;\n\t\tcase \"quota_exhausted\":\n\t\t\treturn BACKOFF_QUOTA_EXHAUSTED_MS;\n\t\tcase \"server_error\":\n\t\t\treturn BACKOFF_SERVER_ERROR_MS;\n\t\tdefault:\n\t\t\treturn BACKOFF_DEFAULT_MS;\n\t}\n}\n\n/**\n * Simple string hash for session-sticky credential selection.\n * Returns a positive integer.\n */\nfunction hashString(str: string): number {\n\tlet hash = 0;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i);\n\t\thash = ((hash << 5) - hash + char) | 0;\n\t}\n\treturn Math.abs(hash);\n}\n\n/**\n * Credential storage backed by a JSON file.\n * Supports multiple credentials per provider with round-robin rotation and rate-limit fallback.\n */\nexport class AuthStorage {\n\tprivate data: AuthStorageData = {};\n\tprivate runtimeOverrides: Map<string, string> = new Map();\n\tprivate fallbackResolver?: (provider: string) => string | undefined;\n\tprivate loadError: Error | null = null;\n\tprivate errors: Error[] = [];\n\tprivate credentialChangeListeners: Set<() => void> = new Set();\n\n\t/**\n\t * Round-robin index per provider. Incremented on each call to getApiKey\n\t * when no sessionId is provided.\n\t */\n\tprivate providerRoundRobinIndex: Map<string, number> = new Map();\n\n\t/**\n\t * Backoff tracking per provider per credential index.\n\t * Map<provider, Map<credentialIndex, backoffExpiresAt>>\n\t */\n\tprivate credentialBackoff: Map<string, Map<number, number>> = new Map();\n\n\t/**\n\t * Provider-level backoff tracking.\n\t * Set when all credentials for a provider are backed off.\n\t * Map<provider, backoffExpiresAt>\n\t */\n\tprivate providerBackoff: Map<string, number> = new Map();\n\n\tprivate constructor(private storage: AuthStorageBackend) {\n\t\tthis.reload();\n\t}\n\n\tstatic create(authPath?: string): AuthStorage {\n\t\treturn new AuthStorage(new FileAuthStorageBackend(authPath ?? join(getAgentDir(), \"auth.json\")));\n\t}\n\n\tstatic fromStorage(storage: AuthStorageBackend): AuthStorage {\n\t\treturn new AuthStorage(storage);\n\t}\n\n\tstatic inMemory(data: AuthStorageData = {}): AuthStorage {\n\t\tconst storage = new InMemoryAuthStorageBackend();\n\t\tstorage.withLock(() => ({ result: undefined, next: JSON.stringify(data, null, 2) }));\n\t\treturn AuthStorage.fromStorage(storage);\n\t}\n\n\t/**\n\t * Set a runtime API key override (not persisted to disk).\n\t * Used for CLI --api-key flag.\n\t */\n\tsetRuntimeApiKey(provider: string, apiKey: string): void {\n\t\tthis.runtimeOverrides.set(provider, apiKey);\n\t}\n\n\t/**\n\t * Remove a runtime API key override.\n\t */\n\tremoveRuntimeApiKey(provider: string): void {\n\t\tthis.runtimeOverrides.delete(provider);\n\t}\n\n\t/**\n\t * Set a fallback resolver for API keys not found in auth.json or env vars.\n\t * Used for custom provider keys from models.json.\n\t */\n\tsetFallbackResolver(resolver: (provider: string) => string | undefined): void {\n\t\tthis.fallbackResolver = resolver;\n\t}\n\n\t/**\n\t * Register a callback to be notified when credentials change (e.g., after OAuth token refresh).\n\t * Returns a function to unregister the listener.\n\t */\n\tonCredentialChange(listener: () => void): () => void {\n\t\tthis.credentialChangeListeners.add(listener);\n\t\treturn () => this.credentialChangeListeners.delete(listener);\n\t}\n\n\tprivate notifyCredentialChange(): void {\n\t\tfor (const listener of this.credentialChangeListeners) {\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch {\n\t\t\t\t// Don't let listener errors break the refresh flow\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate recordError(error: unknown): void {\n\t\tconst normalizedError = error instanceof Error ? error : new Error(String(error));\n\t\tthis.errors.push(normalizedError);\n\t}\n\n\tprivate parseStorageData(content: string | undefined): AuthStorageData {\n\t\tif (!content) {\n\t\t\treturn {};\n\t\t}\n\t\treturn JSON.parse(content) as AuthStorageData;\n\t}\n\n\t/**\n\t * Normalize a storage entry to an array of credentials.\n\t * Handles both single credential (backward compat) and array formats.\n\t */\n\tgetCredentialsForProvider(provider: string): AuthCredential[] {\n\t\tconst entry = this.data[provider];\n\t\tif (!entry) return [];\n\t\tif (Array.isArray(entry)) return entry;\n\t\treturn [entry];\n\t}\n\n\t/**\n\t * Reload credentials from storage.\n\t */\n\treload(): void {\n\t\tlet content: string | undefined;\n\t\ttry {\n\t\t\tthis.storage.withLock((current) => {\n\t\t\t\tcontent = current;\n\t\t\t\treturn { result: undefined };\n\t\t\t});\n\t\t\tthis.data = this.parseStorageData(content);\n\t\t\tthis.loadError = null;\n\t\t} catch (error) {\n\t\t\tthis.loadError = error as Error;\n\t\t\tthis.recordError(error);\n\t\t}\n\t}\n\n\tprivate persistProviderChange(provider: string, credential: AuthCredential | AuthCredential[] | undefined): void {\n\t\tif (this.loadError) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.storage.withLock((current) => {\n\t\t\t\tconst currentData = this.parseStorageData(current);\n\t\t\t\tconst merged: AuthStorageData = { ...currentData };\n\t\t\t\tif (credential) {\n\t\t\t\t\tmerged[provider] = credential;\n\t\t\t\t} else {\n\t\t\t\t\tdelete merged[provider];\n\t\t\t\t}\n\t\t\t\treturn { result: undefined, next: JSON.stringify(merged, null, 2) };\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.recordError(error);\n\t\t}\n\t}\n\n\t/**\n\t * Get the first credential for a provider (backward-compatible).\n\t */\n\tget(provider: string): AuthCredential | undefined {\n\t\tconst creds = this.getCredentialsForProvider(provider);\n\t\treturn creds[0] ?? undefined;\n\t}\n\n\t/**\n\t * Set credential for a provider. For API key credentials, appends to\n\t * existing credentials (accumulation on duplicate login). For OAuth,\n\t * replaces (only one OAuth token per provider makes sense).\n\t */\n\tset(provider: string, credential: AuthCredential): void {\n\t\tif (credential.type === \"api_key\") {\n\t\t\tconst existing = this.getCredentialsForProvider(provider);\n\t\t\t// Deduplicate: don't add if same key already exists\n\t\t\tconst isDuplicate = existing.some(\n\t\t\t\t(c) => c.type === \"api_key\" && c.key === credential.key,\n\t\t\t);\n\t\t\tif (isDuplicate) return;\n\n\t\t\tconst updated = [...existing, credential];\n\t\t\tthis.data[provider] = updated.length === 1 ? updated[0] : updated;\n\t\t\tthis.persistProviderChange(provider, updated.length === 1 ? updated[0] : updated);\n\t\t} else {\n\t\t\t// OAuth: replace any existing OAuth credential, keep API keys\n\t\t\tconst existing = this.getCredentialsForProvider(provider);\n\t\t\tconst apiKeys = existing.filter((c) => c.type === \"api_key\");\n\t\t\tif (apiKeys.length === 0) {\n\t\t\t\tthis.data[provider] = credential;\n\t\t\t\tthis.persistProviderChange(provider, credential);\n\t\t\t} else {\n\t\t\t\tconst updated = [...apiKeys, credential];\n\t\t\t\tthis.data[provider] = updated;\n\t\t\t\tthis.persistProviderChange(provider, updated);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove all credentials for a provider.\n\t */\n\tremove(provider: string): void {\n\t\tdelete this.data[provider];\n\t\tthis.providerRoundRobinIndex.delete(provider);\n\t\tthis.credentialBackoff.delete(provider);\n\t\tthis.providerBackoff.delete(provider);\n\t\tthis.persistProviderChange(provider, undefined);\n\t}\n\n\t/**\n\t * List all providers with credentials.\n\t */\n\tlist(): string[] {\n\t\treturn Object.keys(this.data);\n\t}\n\n\t/**\n\t * Check if credentials exist for a provider in auth.json.\n\t */\n\thas(provider: string): boolean {\n\t\treturn provider in this.data;\n\t}\n\n\t/**\n\t * Check if any form of auth is configured for a provider.\n\t * Unlike getApiKey(), this doesn't refresh OAuth tokens.\n\t */\n\thasAuth(provider: string): boolean {\n\t\tif (this.runtimeOverrides.has(provider)) return true;\n\t\tif (this.data[provider]) return true;\n\t\tif (getEnvApiKey(provider)) return true;\n\t\tif (this.fallbackResolver?.(provider)) return true;\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get all credentials (for passing to getOAuthApiKey).\n\t * Returns normalized format where each provider has a single credential\n\t * (the first one) for backward compatibility with OAuth refresh.\n\t *\n\t * NOTE: For providers with multiple API keys, only the first credential is\n\t * returned. This is intentional — callers use this for OAuth refresh only,\n\t * which is always single-credential. Do not use for API key enumeration.\n\t */\n\tgetAll(): Record<string, AuthCredential> {\n\t\tconst result: Record<string, AuthCredential> = {};\n\t\tfor (const [provider, entry] of Object.entries(this.data)) {\n\t\t\tresult[provider] = Array.isArray(entry) ? entry[0] : entry;\n\t\t}\n\t\treturn result;\n\t}\n\n\tdrainErrors(): Error[] {\n\t\tconst drained = [...this.errors];\n\t\tthis.errors = [];\n\t\treturn drained;\n\t}\n\n\t/**\n\t * Login to an OAuth provider.\n\t */\n\tasync login(providerId: OAuthProviderId, callbacks: OAuthLoginCallbacks): Promise<void> {\n\t\tconst provider = getOAuthProvider(providerId);\n\t\tif (!provider) {\n\t\t\tthrow new Error(`Unknown OAuth provider: ${providerId}`);\n\t\t}\n\n\t\tconst credentials = await provider.login(callbacks);\n\t\tthis.set(providerId, { type: \"oauth\", ...credentials });\n\t}\n\n\t/**\n\t * Logout from a provider.\n\t */\n\tlogout(provider: string): void {\n\t\tthis.remove(provider);\n\t}\n\n\t/**\n\t * Returns true when the provider has credentials configured but all of them\n\t * are currently in a backoff window (e.g. rate-limited or quota exhausted).\n\t * Returns false when there are no credentials or at least one is available.\n\t */\n\tareAllCredentialsBackedOff(provider: string): boolean {\n\t\tconst credentials = this.getCredentialsForProvider(provider);\n\t\tif (credentials.length === 0) return false;\n\t\tfor (let i = 0; i < credentials.length; i++) {\n\t\t\tif (!this.isCredentialBackedOff(provider, i)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Mark an entire provider as exhausted.\n\t * Called when all credentials for a provider are backed off.\n\t */\n\tmarkProviderExhausted(provider: string, errorType: UsageLimitErrorType): void {\n\t\tconst backoffMs = getBackoffDuration(errorType);\n\t\tthis.providerBackoff.set(provider, Date.now() + backoffMs);\n\t}\n\n\t/**\n\t * Check if a provider is currently available (not backed off at provider level).\n\t */\n\tisProviderAvailable(provider: string): boolean {\n\t\tconst expiresAt = this.providerBackoff.get(provider);\n\t\tif (expiresAt === undefined) return true;\n\t\tif (Date.now() >= expiresAt) {\n\t\t\tthis.providerBackoff.delete(provider);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get milliseconds remaining until provider backoff expires.\n\t * Returns 0 if provider is available.\n\t */\n\tgetProviderBackoffRemaining(provider: string): number {\n\t\tconst expiresAt = this.providerBackoff.get(provider);\n\t\tif (expiresAt === undefined) return 0;\n\t\tconst remaining = expiresAt - Date.now();\n\t\tif (remaining <= 0) {\n\t\t\tthis.providerBackoff.delete(provider);\n\t\t\treturn 0;\n\t\t}\n\t\treturn remaining;\n\t}\n\n\t/**\n\t * Check if a credential index is currently backed off.\n\t */\n\tprivate isCredentialBackedOff(provider: string, index: number): boolean {\n\t\tconst providerBackoff = this.credentialBackoff.get(provider);\n\t\tif (!providerBackoff) return false;\n\t\tconst expiresAt = providerBackoff.get(index);\n\t\tif (expiresAt === undefined) return false;\n\t\tif (Date.now() >= expiresAt) {\n\t\t\tproviderBackoff.delete(index);\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Select the best credential index for a provider.\n\t * - If sessionId is provided, uses session-sticky hashing as the starting point.\n\t * - Otherwise, uses round-robin as the starting point.\n\t * - Skips credentials that are currently backed off.\n\t * - Returns -1 if all credentials are backed off.\n\t */\n\tprivate selectCredentialIndex(provider: string, credentials: AuthCredential[], sessionId?: string): number {\n\t\tif (credentials.length === 0) return -1;\n\t\tif (credentials.length === 1) {\n\t\t\treturn this.isCredentialBackedOff(provider, 0) ? -1 : 0;\n\t\t}\n\n\t\tlet startIndex: number;\n\t\tif (sessionId) {\n\t\t\tstartIndex = hashString(sessionId) % credentials.length;\n\t\t} else {\n\t\t\tconst current = this.providerRoundRobinIndex.get(provider) ?? 0;\n\t\t\tstartIndex = current % credentials.length;\n\t\t\tthis.providerRoundRobinIndex.set(provider, current + 1);\n\t\t}\n\n\t\t// Try starting from the preferred index, wrapping around\n\t\tfor (let offset = 0; offset < credentials.length; offset++) {\n\t\t\tconst index = (startIndex + offset) % credentials.length;\n\t\t\tif (!this.isCredentialBackedOff(provider, index)) {\n\t\t\t\treturn index;\n\t\t\t}\n\t\t}\n\n\t\t// All credentials are backed off\n\t\treturn -1;\n\t}\n\n\t/**\n\t * Mark a credential as rate-limited. Finds the credential that was most\n\t * recently used for this provider+session and backs it off.\n\t *\n\t * @returns true if another credential is available (caller should retry),\n\t * false if all credentials for this provider are backed off.\n\t */\n\tmarkUsageLimitReached(\n\t\tprovider: string,\n\t\tsessionId?: string,\n\t\toptions?: { errorType?: UsageLimitErrorType },\n\t): boolean {\n\t\tconst credentials = this.getCredentialsForProvider(provider);\n\t\tif (credentials.length === 0) return false;\n\n\t\tconst errorType = options?.errorType ?? \"rate_limit\";\n\n\t\t// For unknown/transport errors (e.g. connection reset, \"terminated\"),\n\t\t// don't back off the only credential — it would make getApiKey() return\n\t\t// undefined and surface a misleading \"Authentication failed\" message.\n\t\tif (errorType === \"unknown\" && credentials.length === 1) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst backoffMs = getBackoffDuration(errorType);\n\n\t\t// Determine which credential was just used (same logic as selectCredentialIndex\n\t\t// but without incrementing round-robin)\n\t\tlet usedIndex: number;\n\t\tif (credentials.length === 1) {\n\t\t\tusedIndex = 0;\n\t\t} else if (sessionId) {\n\t\t\tusedIndex = hashString(sessionId) % credentials.length;\n\t\t} else {\n\t\t\t// Round-robin was already incremented in getApiKey, so the last-used\n\t\t\t// index is (current - 1). Note: in a concurrent scenario where another\n\t\t\t// getApiKey call fires between the original request and this backoff call,\n\t\t\t// we may back off the wrong credential index. This is acceptable because:\n\t\t\t// (a) pi runs single-threaded event loop, (b) backing off the wrong key\n\t\t\t// is safe — it self-heals when the backoff expires.\n\t\t\tconst current = this.providerRoundRobinIndex.get(provider) ?? 0;\n\t\t\tusedIndex = ((current - 1) % credentials.length + credentials.length) % credentials.length;\n\t\t}\n\n\t\t// Set backoff for this credential\n\t\tlet providerBackoff = this.credentialBackoff.get(provider);\n\t\tif (!providerBackoff) {\n\t\t\tproviderBackoff = new Map();\n\t\t\tthis.credentialBackoff.set(provider, providerBackoff);\n\t\t}\n\t\tproviderBackoff.set(usedIndex, Date.now() + backoffMs);\n\n\t\t// Check if any credential is still available\n\t\tfor (let i = 0; i < credentials.length; i++) {\n\t\t\tif (!this.isCredentialBackedOff(provider, i)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Refresh OAuth token with backend locking to prevent race conditions.\n\t * Multiple pi instances may try to refresh simultaneously when tokens expire.\n\t */\n\tprivate async refreshOAuthTokenWithLock(\n\t\tproviderId: OAuthProviderId,\n\t): Promise<{ apiKey: string; newCredentials: OAuthCredentials } | null> {\n\t\tconst provider = getOAuthProvider(providerId);\n\t\tif (!provider) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst result = await this.storage.withLockAsync(async (current) => {\n\t\t\tconst currentData = this.parseStorageData(current);\n\t\t\tthis.data = currentData;\n\t\t\tthis.loadError = null;\n\n\t\t\t// Find the OAuth credential for this provider\n\t\t\tconst creds = this.getCredentialsForProvider(providerId);\n\t\t\tconst cred = creds.find((c) => c.type === \"oauth\");\n\t\t\tif (!cred || cred.type !== \"oauth\") {\n\t\t\t\treturn { result: null };\n\t\t\t}\n\n\t\t\tif (Date.now() < cred.expires) {\n\t\t\t\treturn { result: { apiKey: provider.getApiKey(cred), newCredentials: cred } };\n\t\t\t}\n\n\t\t\tconst oauthCreds: Record<string, OAuthCredentials> = {};\n\t\t\tfor (const [key, value] of Object.entries(currentData)) {\n\t\t\t\tconst first = Array.isArray(value) ? value.find((c) => c.type === \"oauth\") : value;\n\t\t\t\tif (first?.type === \"oauth\") {\n\t\t\t\t\toauthCreds[key] = first;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst refreshed = await getOAuthApiKey(providerId, oauthCreds);\n\t\t\tif (!refreshed) {\n\t\t\t\treturn { result: null };\n\t\t\t}\n\n\t\t\t// Update the OAuth credential in-place within the array\n\t\t\tconst existingEntry = currentData[providerId];\n\t\t\tconst newOAuthCred: OAuthCredential = { type: \"oauth\", ...refreshed.newCredentials };\n\t\t\tlet updatedEntry: AuthCredential | AuthCredential[];\n\n\t\t\tif (Array.isArray(existingEntry)) {\n\t\t\t\tupdatedEntry = existingEntry.map((c) => (c.type === \"oauth\" ? newOAuthCred : c));\n\t\t\t} else {\n\t\t\t\tupdatedEntry = newOAuthCred;\n\t\t\t}\n\n\t\t\tconst merged: AuthStorageData = {\n\t\t\t\t...currentData,\n\t\t\t\t[providerId]: updatedEntry,\n\t\t\t};\n\t\t\tthis.data = merged;\n\t\t\tthis.loadError = null;\n\t\t\treturn { result: refreshed, next: JSON.stringify(merged, null, 2) };\n\t\t});\n\n\t\t// Notify listeners after credential change (e.g., model registry refresh)\n\t\tif (result) {\n\t\t\tqueueMicrotask(() => this.notifyCredentialChange());\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Resolve an API key from a single credential.\n\t */\n\tprivate async resolveCredentialApiKey(\n\t\tproviderId: string,\n\t\tcred: AuthCredential,\n\t): Promise<string | undefined> {\n\t\tif (cred.type === \"api_key\") {\n\t\t\treturn resolveConfigValue(cred.key);\n\t\t}\n\n\t\tif (cred.type === \"oauth\") {\n\t\t\tconst provider = getOAuthProvider(providerId);\n\t\t\tif (!provider) return undefined;\n\n\t\t\tconst needsRefresh = Date.now() >= cred.expires;\n\t\t\tif (needsRefresh) {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.refreshOAuthTokenWithLock(providerId);\n\t\t\t\t\tif (result) return result.apiKey;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.recordError(error);\n\t\t\t\t\tthis.reload();\n\t\t\t\t\tconst updatedCreds = this.getCredentialsForProvider(providerId);\n\t\t\t\t\tconst updatedOAuth = updatedCreds.find((c) => c.type === \"oauth\");\n\t\t\t\t\tif (updatedOAuth?.type === \"oauth\" && Date.now() < updatedOAuth.expires) {\n\t\t\t\t\t\treturn provider.getApiKey(updatedOAuth);\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn provider.getApiKey(cred);\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Get API key for a provider.\n\t * Priority:\n\t * 1. Runtime override (CLI --api-key)\n\t * 2. Credential(s) from auth.json (with round-robin / session-sticky selection)\n\t * 3. Environment variable\n\t * 4. Fallback resolver (models.json custom providers)\n\t *\n\t * @param providerId - The provider to get an API key for\n\t * @param sessionId - Optional session ID for sticky credential selection\n\t */\n\tasync getApiKey(providerId: string, sessionId?: string): Promise<string | undefined> {\n\t\t// Runtime override takes highest priority\n\t\tconst runtimeKey = this.runtimeOverrides.get(providerId);\n\t\tif (runtimeKey) {\n\t\t\treturn runtimeKey;\n\t\t}\n\n\t\tconst credentials = this.getCredentialsForProvider(providerId);\n\n\t\tif (credentials.length > 0) {\n\t\t\tconst index = this.selectCredentialIndex(providerId, credentials, sessionId);\n\t\t\tif (index >= 0) {\n\t\t\t\tconst resolved = await this.resolveCredentialApiKey(providerId, credentials[index]);\n\t\t\t\tif (resolved) return resolved;\n\t\t\t\t// Credential unresolvable (e.g. type:\"oauth\" for a non-OAuth provider) —\n\t\t\t\t// fall through to env / fallback instead of returning undefined (#2083)\n\t\t\t}\n\t\t\t// All credentials backed off or unresolvable - fall through to env/fallback\n\t\t}\n\n\t\t// Fall back to environment variable\n\t\tconst envKey = getEnvApiKey(providerId);\n\t\tif (envKey) return envKey;\n\n\t\t// Fall back to custom resolver (e.g., models.json custom providers)\n\t\treturn this.fallbackResolver?.(providerId) ?? undefined;\n\t}\n\n\t/**\n\t * Get all registered OAuth providers\n\t */\n\tgetOAuthProviders() {\n\t\treturn getOAuthProviders();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"auth-storage.js","sourceRoot":"","sources":["../../src/core/auth-storage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Credential storage for API keys and OAuth tokens.\n * Handles loading, saving, and refreshing credentials from auth.json.\n *\n * Supports multiple credentials per provider with round-robin selection,\n * session-sticky hashing, and automatic rate-limit fallback.\n *\n * Uses file locking to prevent race conditions when multiple pi instances\n * try to refresh tokens simultaneously.\n */\n\nimport {\n\tgetEnvApiKey,\n\ttype OAuthCredentials,\n\ttype OAuthLoginCallbacks,\n\ttype OAuthProviderId,\n} from \"@gsd/pi-ai\";\nimport { getOAuthApiKey, getOAuthProvider, getOAuthProviders } from \"@gsd/pi-ai/oauth\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AUTH_LOCK_STALE_MS } from \"./constants.js\";\nimport { acquireLockAsync, acquireLockSyncWithRetry } from \"./lock-utils.js\";\nimport { resolveConfigValue } from \"./resolve-config-value.js\";\n\nexport type ApiKeyCredential = {\n\ttype: \"api_key\";\n\tkey: string;\n};\n\nexport type OAuthCredential = {\n\ttype: \"oauth\";\n} & OAuthCredentials;\n\nexport type AuthCredential = ApiKeyCredential | OAuthCredential;\n\n/**\n * On-disk format: each provider maps to a single credential or an array of credentials.\n * Single credentials are normalized to arrays at load time for internal use.\n */\nexport type AuthStorageData = Record<string, AuthCredential | AuthCredential[]>;\n\ntype LockResult<T> = {\n\tresult: T;\n\tnext?: string;\n};\n\nexport interface AuthStorageBackend {\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T;\n\twithLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T>;\n}\n\nexport class FileAuthStorageBackend implements AuthStorageBackend {\n\tconstructor(private authPath: string = join(getAgentDir(), \"auth.json\")) {}\n\n\tprivate ensureParentDir(): void {\n\t\tconst dir = dirname(this.authPath);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t\t}\n\t}\n\n\tprivate ensureFileExists(): void {\n\t\tif (!existsSync(this.authPath)) {\n\t\t\twriteFileSync(this.authPath, \"{}\", \"utf-8\");\n\t\t\tchmodSync(this.authPath, 0o600);\n\t\t}\n\t}\n\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T {\n\t\tthis.ensureParentDir();\n\t\tthis.ensureFileExists();\n\n\t\tlet release: (() => void) | undefined;\n\t\ttry {\n\t\t\trelease = acquireLockSyncWithRetry(this.authPath);\n\t\t\tconst current = existsSync(this.authPath) ? readFileSync(this.authPath, \"utf-8\") : undefined;\n\t\t\tconst { result, next } = fn(current);\n\t\t\tif (next !== undefined) {\n\t\t\t\twriteFileSync(this.authPath, next, \"utf-8\");\n\t\t\t\tchmodSync(this.authPath, 0o600);\n\t\t\t}\n\t\t\treturn result;\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\trelease();\n\t\t\t}\n\t\t}\n\t}\n\n\tasync withLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T> {\n\t\tthis.ensureParentDir();\n\t\tthis.ensureFileExists();\n\n\t\tlet release: (() => Promise<void>) | undefined;\n\t\tlet lockCompromised = false;\n\t\tlet lockCompromisedError: Error | undefined;\n\t\tconst throwIfCompromised = () => {\n\t\t\tif (lockCompromised) {\n\t\t\t\tthrow lockCompromisedError ?? new Error(\"Auth storage lock was compromised\");\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\trelease = await acquireLockAsync(this.authPath, {\n\t\t\t\tstaleMs: AUTH_LOCK_STALE_MS,\n\t\t\t\tonCompromised: (err) => {\n\t\t\t\t\tlockCompromised = true;\n\t\t\t\t\tlockCompromisedError = err;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tthrowIfCompromised();\n\t\t\tconst current = existsSync(this.authPath) ? readFileSync(this.authPath, \"utf-8\") : undefined;\n\t\t\tconst { result, next } = await fn(current);\n\t\t\tthrowIfCompromised();\n\t\t\tif (next !== undefined) {\n\t\t\t\twriteFileSync(this.authPath, next, \"utf-8\");\n\t\t\t\tchmodSync(this.authPath, 0o600);\n\t\t\t}\n\t\t\tthrowIfCompromised();\n\t\t\treturn result;\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\ttry {\n\t\t\t\t\tawait release();\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore unlock errors when lock is compromised.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class InMemoryAuthStorageBackend implements AuthStorageBackend {\n\tprivate value: string | undefined;\n\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T {\n\t\tconst { result, next } = fn(this.value);\n\t\tif (next !== undefined) {\n\t\t\tthis.value = next;\n\t\t}\n\t\treturn result;\n\t}\n\n\tasync withLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T> {\n\t\tconst { result, next } = await fn(this.value);\n\t\tif (next !== undefined) {\n\t\t\tthis.value = next;\n\t\t}\n\t\treturn result;\n\t}\n}\n\n// ============================================================================\n// Backoff durations for different error types (milliseconds)\n// ============================================================================\n\nconst BACKOFF_RATE_LIMIT_MS = 30_000; // 30s for rate limit / 429\nconst BACKOFF_QUOTA_EXHAUSTED_MS = 30 * 60_000; // 30min for quota exhausted\nconst BACKOFF_SERVER_ERROR_MS = 20_000; // 20s for 5xx server errors\nconst BACKOFF_DEFAULT_MS = 60_000; // 60s fallback\n\nexport type UsageLimitErrorType = \"rate_limit\" | \"quota_exhausted\" | \"server_error\" | \"unknown\";\n\n/**\n * Get backoff duration for an error type.\n */\nfunction getBackoffDuration(errorType: UsageLimitErrorType): number {\n\tswitch (errorType) {\n\t\tcase \"rate_limit\":\n\t\t\treturn BACKOFF_RATE_LIMIT_MS;\n\t\tcase \"quota_exhausted\":\n\t\t\treturn BACKOFF_QUOTA_EXHAUSTED_MS;\n\t\tcase \"server_error\":\n\t\t\treturn BACKOFF_SERVER_ERROR_MS;\n\t\tdefault:\n\t\t\treturn BACKOFF_DEFAULT_MS;\n\t}\n}\n\n/**\n * Simple string hash for session-sticky credential selection.\n * Returns a positive integer.\n */\nfunction hashString(str: string): number {\n\tlet hash = 0;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i);\n\t\thash = ((hash << 5) - hash + char) | 0;\n\t}\n\treturn Math.abs(hash);\n}\n\n/**\n * Credential storage backed by a JSON file.\n * Supports multiple credentials per provider with round-robin rotation and rate-limit fallback.\n */\nexport class AuthStorage {\n\tprivate data: AuthStorageData = {};\n\tprivate runtimeOverrides: Map<string, string> = new Map();\n\tprivate fallbackResolver?: (provider: string) => string | undefined;\n\tprivate loadError: Error | null = null;\n\tprivate errors: Error[] = [];\n\tprivate credentialChangeListeners: Set<() => void> = new Set();\n\n\t/**\n\t * Round-robin index per provider. Incremented on each call to getApiKey\n\t * when no sessionId is provided.\n\t */\n\tprivate providerRoundRobinIndex: Map<string, number> = new Map();\n\n\t/**\n\t * Backoff tracking per provider per credential index.\n\t * Map<provider, Map<credentialIndex, backoffExpiresAt>>\n\t */\n\tprivate credentialBackoff: Map<string, Map<number, number>> = new Map();\n\n\t/**\n\t * Provider-level backoff tracking.\n\t * Set when all credentials for a provider are backed off.\n\t * Map<provider, backoffExpiresAt>\n\t */\n\tprivate providerBackoff: Map<string, number> = new Map();\n\n\tprivate constructor(private storage: AuthStorageBackend) {\n\t\tthis.reload();\n\t}\n\n\tstatic create(authPath?: string): AuthStorage {\n\t\treturn new AuthStorage(new FileAuthStorageBackend(authPath ?? join(getAgentDir(), \"auth.json\")));\n\t}\n\n\tstatic fromStorage(storage: AuthStorageBackend): AuthStorage {\n\t\treturn new AuthStorage(storage);\n\t}\n\n\tstatic inMemory(data: AuthStorageData = {}): AuthStorage {\n\t\tconst storage = new InMemoryAuthStorageBackend();\n\t\tstorage.withLock(() => ({ result: undefined, next: JSON.stringify(data, null, 2) }));\n\t\treturn AuthStorage.fromStorage(storage);\n\t}\n\n\t/**\n\t * Set a runtime API key override (not persisted to disk).\n\t * Used for CLI --api-key flag.\n\t */\n\tsetRuntimeApiKey(provider: string, apiKey: string): void {\n\t\tthis.runtimeOverrides.set(provider, apiKey);\n\t}\n\n\t/**\n\t * Remove a runtime API key override.\n\t */\n\tremoveRuntimeApiKey(provider: string): void {\n\t\tthis.runtimeOverrides.delete(provider);\n\t}\n\n\t/**\n\t * Set a fallback resolver for API keys not found in auth.json or env vars.\n\t * Used for custom provider keys from models.json.\n\t */\n\tsetFallbackResolver(resolver: (provider: string) => string | undefined): void {\n\t\tthis.fallbackResolver = resolver;\n\t}\n\n\t/**\n\t * Register a callback to be notified when credentials change (e.g., after OAuth token refresh).\n\t * Returns a function to unregister the listener.\n\t */\n\tonCredentialChange(listener: () => void): () => void {\n\t\tthis.credentialChangeListeners.add(listener);\n\t\treturn () => this.credentialChangeListeners.delete(listener);\n\t}\n\n\tprivate notifyCredentialChange(): void {\n\t\tfor (const listener of this.credentialChangeListeners) {\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch {\n\t\t\t\t// Don't let listener errors break the refresh flow\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate recordError(error: unknown): void {\n\t\tconst normalizedError = error instanceof Error ? error : new Error(String(error));\n\t\tthis.errors.push(normalizedError);\n\t}\n\n\tprivate parseStorageData(content: string | undefined): AuthStorageData {\n\t\tif (!content) {\n\t\t\treturn {};\n\t\t}\n\t\treturn JSON.parse(content) as AuthStorageData;\n\t}\n\n\t/**\n\t * Normalize a storage entry to an array of credentials.\n\t * Handles both single credential (backward compat) and array formats.\n\t */\n\tgetCredentialsForProvider(provider: string): AuthCredential[] {\n\t\tconst entry = this.data[provider];\n\t\tif (!entry) return [];\n\t\tif (Array.isArray(entry)) return entry;\n\t\treturn [entry];\n\t}\n\n\t/**\n\t * Reload credentials from storage.\n\t */\n\treload(): void {\n\t\tlet content: string | undefined;\n\t\ttry {\n\t\t\tthis.storage.withLock((current) => {\n\t\t\t\tcontent = current;\n\t\t\t\treturn { result: undefined };\n\t\t\t});\n\t\t\tthis.data = this.parseStorageData(content);\n\t\t\tthis.loadError = null;\n\t\t} catch (error) {\n\t\t\tthis.loadError = error as Error;\n\t\t\tthis.recordError(error);\n\t\t}\n\t}\n\n\tprivate persistProviderChange(provider: string, credential: AuthCredential | AuthCredential[] | undefined): void {\n\t\tif (this.loadError) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.storage.withLock((current) => {\n\t\t\t\tconst currentData = this.parseStorageData(current);\n\t\t\t\tconst merged: AuthStorageData = { ...currentData };\n\t\t\t\tif (credential) {\n\t\t\t\t\tmerged[provider] = credential;\n\t\t\t\t} else {\n\t\t\t\t\tdelete merged[provider];\n\t\t\t\t}\n\t\t\t\treturn { result: undefined, next: JSON.stringify(merged, null, 2) };\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.recordError(error);\n\t\t}\n\t}\n\n\t/**\n\t * Get the first credential for a provider (backward-compatible).\n\t */\n\tget(provider: string): AuthCredential | undefined {\n\t\tconst creds = this.getCredentialsForProvider(provider);\n\t\treturn creds[0] ?? undefined;\n\t}\n\n\t/**\n\t * Set credential for a provider. For API key credentials, appends to\n\t * existing credentials (accumulation on duplicate login). For OAuth,\n\t * replaces (only one OAuth token per provider makes sense).\n\t */\n\tset(provider: string, credential: AuthCredential): void {\n\t\tif (credential.type === \"api_key\") {\n\t\t\tconst existing = this.getCredentialsForProvider(provider);\n\t\t\t// Deduplicate: don't add if same key already exists\n\t\t\tconst isDuplicate = existing.some(\n\t\t\t\t(c) => c.type === \"api_key\" && c.key === credential.key,\n\t\t\t);\n\t\t\tif (isDuplicate) return;\n\n\t\t\tconst updated = [...existing, credential];\n\t\t\tthis.data[provider] = updated.length === 1 ? updated[0] : updated;\n\t\t\tthis.persistProviderChange(provider, updated.length === 1 ? updated[0] : updated);\n\t\t} else {\n\t\t\t// OAuth: replace any existing OAuth credential, keep API keys\n\t\t\tconst existing = this.getCredentialsForProvider(provider);\n\t\t\tconst apiKeys = existing.filter((c) => c.type === \"api_key\");\n\t\t\tif (apiKeys.length === 0) {\n\t\t\t\tthis.data[provider] = credential;\n\t\t\t\tthis.persistProviderChange(provider, credential);\n\t\t\t} else {\n\t\t\t\tconst updated = [...apiKeys, credential];\n\t\t\t\tthis.data[provider] = updated;\n\t\t\t\tthis.persistProviderChange(provider, updated);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove all credentials for a provider.\n\t */\n\tremove(provider: string): void {\n\t\tdelete this.data[provider];\n\t\tthis.providerRoundRobinIndex.delete(provider);\n\t\tthis.credentialBackoff.delete(provider);\n\t\tthis.providerBackoff.delete(provider);\n\t\tthis.persistProviderChange(provider, undefined);\n\t}\n\n\t/**\n\t * List all providers with credentials.\n\t */\n\tlist(): string[] {\n\t\treturn Object.keys(this.data);\n\t}\n\n\t/**\n\t * Check if credentials exist for a provider in auth.json.\n\t */\n\thas(provider: string): boolean {\n\t\treturn provider in this.data;\n\t}\n\n\t/**\n\t * Check if any form of auth is configured for a provider.\n\t * Unlike getApiKey(), this doesn't refresh OAuth tokens.\n\t */\n\thasAuth(provider: string): boolean {\n\t\tif (this.runtimeOverrides.has(provider)) return true;\n\t\tif (this.data[provider]) return true;\n\t\tif (getEnvApiKey(provider)) return true;\n\t\tif (this.fallbackResolver?.(provider)) return true;\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get all credentials (for passing to getOAuthApiKey).\n\t * Returns normalized format where each provider has a single credential\n\t * (the first one) for backward compatibility with OAuth refresh.\n\t *\n\t * NOTE: For providers with multiple API keys, only the first credential is\n\t * returned. This is intentional — callers use this for OAuth refresh only,\n\t * which is always single-credential. Do not use for API key enumeration.\n\t */\n\tgetAll(): Record<string, AuthCredential> {\n\t\tconst result: Record<string, AuthCredential> = {};\n\t\tfor (const [provider, entry] of Object.entries(this.data)) {\n\t\t\tresult[provider] = Array.isArray(entry) ? entry[0] : entry;\n\t\t}\n\t\treturn result;\n\t}\n\n\tdrainErrors(): Error[] {\n\t\tconst drained = [...this.errors];\n\t\tthis.errors = [];\n\t\treturn drained;\n\t}\n\n\t/**\n\t * Login to an OAuth provider.\n\t */\n\tasync login(providerId: OAuthProviderId, callbacks: OAuthLoginCallbacks): Promise<void> {\n\t\tconst provider = getOAuthProvider(providerId);\n\t\tif (!provider) {\n\t\t\tthrow new Error(`Unknown OAuth provider: ${providerId}`);\n\t\t}\n\n\t\tconst credentials = await provider.login(callbacks);\n\t\tthis.set(providerId, { type: \"oauth\", ...credentials });\n\t}\n\n\t/**\n\t * Logout from a provider.\n\t */\n\tlogout(provider: string): void {\n\t\tthis.remove(provider);\n\t}\n\n\t/**\n\t * Returns true when the provider has credentials configured but all of them\n\t * are currently in a backoff window (e.g. rate-limited or quota exhausted).\n\t * Returns false when there are no credentials or at least one is available.\n\t */\n\tareAllCredentialsBackedOff(provider: string): boolean {\n\t\tconst credentials = this.getCredentialsForProvider(provider);\n\t\tif (credentials.length === 0) return false;\n\t\tfor (let i = 0; i < credentials.length; i++) {\n\t\t\tif (!this.isCredentialBackedOff(provider, i)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Mark an entire provider as exhausted.\n\t * Called when all credentials for a provider are backed off.\n\t */\n\tmarkProviderExhausted(provider: string, errorType: UsageLimitErrorType): void {\n\t\tconst backoffMs = getBackoffDuration(errorType);\n\t\tthis.providerBackoff.set(provider, Date.now() + backoffMs);\n\t}\n\n\t/**\n\t * Check if a provider is currently available (not backed off at provider level).\n\t */\n\tisProviderAvailable(provider: string): boolean {\n\t\tconst expiresAt = this.providerBackoff.get(provider);\n\t\tif (expiresAt === undefined) return true;\n\t\tif (Date.now() >= expiresAt) {\n\t\t\tthis.providerBackoff.delete(provider);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get milliseconds remaining until provider backoff expires.\n\t * Returns 0 if provider is available.\n\t */\n\tgetProviderBackoffRemaining(provider: string): number {\n\t\tconst expiresAt = this.providerBackoff.get(provider);\n\t\tif (expiresAt === undefined) return 0;\n\t\tconst remaining = expiresAt - Date.now();\n\t\tif (remaining <= 0) {\n\t\t\tthis.providerBackoff.delete(provider);\n\t\t\treturn 0;\n\t\t}\n\t\treturn remaining;\n\t}\n\n\t/**\n\t * Check if a credential index is currently backed off.\n\t */\n\tprivate isCredentialBackedOff(provider: string, index: number): boolean {\n\t\tconst providerBackoff = this.credentialBackoff.get(provider);\n\t\tif (!providerBackoff) return false;\n\t\tconst expiresAt = providerBackoff.get(index);\n\t\tif (expiresAt === undefined) return false;\n\t\tif (Date.now() >= expiresAt) {\n\t\t\tproviderBackoff.delete(index);\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Select the best credential index for a provider.\n\t * - If sessionId is provided, uses session-sticky hashing as the starting point.\n\t * - Otherwise, uses round-robin as the starting point.\n\t * - Skips credentials that are currently backed off.\n\t * - Returns -1 if all credentials are backed off.\n\t */\n\tprivate selectCredentialIndex(provider: string, credentials: AuthCredential[], sessionId?: string): number {\n\t\tif (credentials.length === 0) return -1;\n\t\tif (credentials.length === 1) {\n\t\t\treturn this.isCredentialBackedOff(provider, 0) ? -1 : 0;\n\t\t}\n\n\t\tlet startIndex: number;\n\t\tif (sessionId) {\n\t\t\tstartIndex = hashString(sessionId) % credentials.length;\n\t\t} else {\n\t\t\tconst current = this.providerRoundRobinIndex.get(provider) ?? 0;\n\t\t\tstartIndex = current % credentials.length;\n\t\t\tthis.providerRoundRobinIndex.set(provider, current + 1);\n\t\t}\n\n\t\t// Try starting from the preferred index, wrapping around\n\t\tfor (let offset = 0; offset < credentials.length; offset++) {\n\t\t\tconst index = (startIndex + offset) % credentials.length;\n\t\t\tif (!this.isCredentialBackedOff(provider, index)) {\n\t\t\t\treturn index;\n\t\t\t}\n\t\t}\n\n\t\t// All credentials are backed off\n\t\treturn -1;\n\t}\n\n\t/**\n\t * Mark a credential as rate-limited. Finds the credential that was most\n\t * recently used for this provider+session and backs it off.\n\t *\n\t * @returns true if another credential is available (caller should retry),\n\t * false if all credentials for this provider are backed off.\n\t */\n\tmarkUsageLimitReached(\n\t\tprovider: string,\n\t\tsessionId?: string,\n\t\toptions?: { errorType?: UsageLimitErrorType },\n\t): boolean {\n\t\tconst credentials = this.getCredentialsForProvider(provider);\n\t\tif (credentials.length === 0) return false;\n\n\t\tconst errorType = options?.errorType ?? \"rate_limit\";\n\n\t\t// For unknown/transport errors (e.g. connection reset, \"terminated\"),\n\t\t// don't back off the only credential — it would make getApiKey() return\n\t\t// undefined and surface a misleading \"Authentication failed\" message.\n\t\tif (errorType === \"unknown\" && credentials.length === 1) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst backoffMs = getBackoffDuration(errorType);\n\n\t\t// Determine which credential was just used (same logic as selectCredentialIndex\n\t\t// but without incrementing round-robin)\n\t\tlet usedIndex: number;\n\t\tif (credentials.length === 1) {\n\t\t\tusedIndex = 0;\n\t\t} else if (sessionId) {\n\t\t\tusedIndex = hashString(sessionId) % credentials.length;\n\t\t} else {\n\t\t\t// Round-robin was already incremented in getApiKey, so the last-used\n\t\t\t// index is (current - 1). Note: in a concurrent scenario where another\n\t\t\t// getApiKey call fires between the original request and this backoff call,\n\t\t\t// we may back off the wrong credential index. This is acceptable because:\n\t\t\t// (a) pi runs single-threaded event loop, (b) backing off the wrong key\n\t\t\t// is safe — it self-heals when the backoff expires.\n\t\t\tconst current = this.providerRoundRobinIndex.get(provider) ?? 0;\n\t\t\tusedIndex = ((current - 1) % credentials.length + credentials.length) % credentials.length;\n\t\t}\n\n\t\t// Set backoff for this credential\n\t\tlet providerBackoff = this.credentialBackoff.get(provider);\n\t\tif (!providerBackoff) {\n\t\t\tproviderBackoff = new Map();\n\t\t\tthis.credentialBackoff.set(provider, providerBackoff);\n\t\t}\n\t\tproviderBackoff.set(usedIndex, Date.now() + backoffMs);\n\n\t\t// Check if any credential is still available\n\t\tfor (let i = 0; i < credentials.length; i++) {\n\t\t\tif (!this.isCredentialBackedOff(provider, i)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Refresh OAuth token with backend locking to prevent race conditions.\n\t * Multiple pi instances may try to refresh simultaneously when tokens expire.\n\t */\n\tprivate async refreshOAuthTokenWithLock(\n\t\tproviderId: OAuthProviderId,\n\t): Promise<{ apiKey: string; newCredentials: OAuthCredentials } | null> {\n\t\tconst provider = getOAuthProvider(providerId);\n\t\tif (!provider) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst result = await this.storage.withLockAsync(async (current) => {\n\t\t\tconst currentData = this.parseStorageData(current);\n\t\t\tthis.data = currentData;\n\t\t\tthis.loadError = null;\n\n\t\t\t// Find the OAuth credential for this provider\n\t\t\tconst creds = this.getCredentialsForProvider(providerId);\n\t\t\tconst cred = creds.find((c) => c.type === \"oauth\");\n\t\t\tif (!cred || cred.type !== \"oauth\") {\n\t\t\t\treturn { result: null };\n\t\t\t}\n\n\t\t\tif (Date.now() < cred.expires) {\n\t\t\t\treturn { result: { apiKey: provider.getApiKey(cred), newCredentials: cred } };\n\t\t\t}\n\n\t\t\tconst oauthCreds: Record<string, OAuthCredentials> = {};\n\t\t\tfor (const [key, value] of Object.entries(currentData)) {\n\t\t\t\tconst first = Array.isArray(value) ? value.find((c) => c.type === \"oauth\") : value;\n\t\t\t\tif (first?.type === \"oauth\") {\n\t\t\t\t\toauthCreds[key] = first;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst refreshed = await getOAuthApiKey(providerId, oauthCreds);\n\t\t\tif (!refreshed) {\n\t\t\t\treturn { result: null };\n\t\t\t}\n\n\t\t\t// Update the OAuth credential in-place within the array\n\t\t\tconst existingEntry = currentData[providerId];\n\t\t\tconst newOAuthCred: OAuthCredential = { type: \"oauth\", ...refreshed.newCredentials };\n\t\t\tlet updatedEntry: AuthCredential | AuthCredential[];\n\n\t\t\tif (Array.isArray(existingEntry)) {\n\t\t\t\tupdatedEntry = existingEntry.map((c) => (c.type === \"oauth\" ? newOAuthCred : c));\n\t\t\t} else {\n\t\t\t\tupdatedEntry = newOAuthCred;\n\t\t\t}\n\n\t\t\tconst merged: AuthStorageData = {\n\t\t\t\t...currentData,\n\t\t\t\t[providerId]: updatedEntry,\n\t\t\t};\n\t\t\tthis.data = merged;\n\t\t\tthis.loadError = null;\n\t\t\treturn { result: refreshed, next: JSON.stringify(merged, null, 2) };\n\t\t});\n\n\t\t// Notify listeners after credential change (e.g., model registry refresh)\n\t\tif (result) {\n\t\t\tqueueMicrotask(() => this.notifyCredentialChange());\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Resolve an API key from a single credential.\n\t */\n\tprivate async resolveCredentialApiKey(\n\t\tproviderId: string,\n\t\tcred: AuthCredential,\n\t): Promise<string | undefined> {\n\t\tif (cred.type === \"api_key\") {\n\t\t\treturn resolveConfigValue(cred.key);\n\t\t}\n\n\t\tif (cred.type === \"oauth\") {\n\t\t\tconst provider = getOAuthProvider(providerId);\n\t\t\tif (!provider) return undefined;\n\n\t\t\tconst needsRefresh = Date.now() >= cred.expires;\n\t\t\tif (needsRefresh) {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.refreshOAuthTokenWithLock(providerId);\n\t\t\t\t\tif (result) return result.apiKey;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.recordError(error);\n\t\t\t\t\tthis.reload();\n\t\t\t\t\tconst updatedCreds = this.getCredentialsForProvider(providerId);\n\t\t\t\t\tconst updatedOAuth = updatedCreds.find((c) => c.type === \"oauth\");\n\t\t\t\t\tif (updatedOAuth?.type === \"oauth\" && Date.now() < updatedOAuth.expires) {\n\t\t\t\t\t\treturn provider.getApiKey(updatedOAuth);\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn provider.getApiKey(cred);\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Get API key for a provider.\n\t * Priority:\n\t * 1. Runtime override (CLI --api-key)\n\t * 2. Credential(s) from auth.json (with round-robin / session-sticky selection)\n\t * 3. Environment variable\n\t * 4. Fallback resolver (models.json custom providers)\n\t *\n\t * @param providerId - The provider to get an API key for\n\t * @param sessionId - Optional session ID for sticky credential selection\n\t */\n\tasync getApiKey(providerId: string, sessionId?: string, options?: { baseUrl?: string }): Promise<string | undefined> {\n\t\t// If the model has a local baseUrl, return a dummy key to avoid auth blocking\n\t\tif (options?.baseUrl) {\n\t\t\ttry {\n\t\t\t\tconst hostname = new URL(options.baseUrl).hostname;\n\t\t\t\tif (hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"0.0.0.0\" || hostname === \"::1\") {\n\t\t\t\t\treturn \"local-no-key-needed\";\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tif (options.baseUrl.startsWith(\"unix:\")) {\n\t\t\t\t\treturn \"local-no-key-needed\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Runtime override takes highest priority\n\t\tconst runtimeKey = this.runtimeOverrides.get(providerId);\n\t\tif (runtimeKey) {\n\t\t\treturn runtimeKey;\n\t\t}\n\n\t\tconst credentials = this.getCredentialsForProvider(providerId);\n\n\t\tif (credentials.length > 0) {\n\t\t\tconst index = this.selectCredentialIndex(providerId, credentials, sessionId);\n\t\t\tif (index >= 0) {\n\t\t\t\tconst resolved = await this.resolveCredentialApiKey(providerId, credentials[index]);\n\t\t\t\tif (resolved) return resolved;\n\t\t\t\t// Credential unresolvable (e.g. type:\"oauth\" for a non-OAuth provider) —\n\t\t\t\t// fall through to env / fallback instead of returning undefined (#2083)\n\t\t\t}\n\t\t\t// All credentials backed off or unresolvable - fall through to env/fallback\n\t\t}\n\n\t\t// Fall back to environment variable\n\t\tconst envKey = getEnvApiKey(providerId);\n\t\tif (envKey) return envKey;\n\n\t\t// Fall back to custom resolver (e.g., models.json custom providers)\n\t\treturn this.fallbackResolver?.(providerId) ?? undefined;\n\t}\n\n\t/**\n\t * Get all registered OAuth providers\n\t */\n\tgetOAuthProviders() {\n\t\treturn getOAuthProviders();\n\t}\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* local-model-check.ts — Utility to detect if a model baseUrl is local.
|
|
3
|
+
*
|
|
4
|
+
* Leaf module with zero transitive dependencies on TypeScript parameter properties.
|
|
5
|
+
* Used by ModelRegistry and tests.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check if a model's baseUrl points to a local endpoint.
|
|
9
|
+
* Returns true for localhost, 127.0.0.1, 0.0.0.0, ::1, or unix socket paths.
|
|
10
|
+
* Returns false if baseUrl is empty (cloud provider) or points to a remote host.
|
|
11
|
+
*/
|
|
12
|
+
export declare function isLocalModel(model: {
|
|
13
|
+
baseUrl: string;
|
|
14
|
+
}): boolean;
|
|
15
|
+
//# sourceMappingURL=local-model-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-model-check.d.ts","sourceRoot":"","sources":["../../src/core/local-model-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAgChE"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* local-model-check.ts — Utility to detect if a model baseUrl is local.
|
|
3
|
+
*
|
|
4
|
+
* Leaf module with zero transitive dependencies on TypeScript parameter properties.
|
|
5
|
+
* Used by ModelRegistry and tests.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check if a model's baseUrl points to a local endpoint.
|
|
9
|
+
* Returns true for localhost, 127.0.0.1, 0.0.0.0, ::1, or unix socket paths.
|
|
10
|
+
* Returns false if baseUrl is empty (cloud provider) or points to a remote host.
|
|
11
|
+
*/
|
|
12
|
+
export function isLocalModel(model) {
|
|
13
|
+
const url = model.baseUrl;
|
|
14
|
+
if (!url)
|
|
15
|
+
return false;
|
|
16
|
+
// Unix socket paths
|
|
17
|
+
if (url.startsWith("unix://") || url.startsWith("unix:"))
|
|
18
|
+
return true;
|
|
19
|
+
try {
|
|
20
|
+
const parsed = new URL(url);
|
|
21
|
+
const hostname = parsed.hostname;
|
|
22
|
+
if (hostname === "localhost" ||
|
|
23
|
+
hostname === "127.0.0.1" ||
|
|
24
|
+
hostname === "0.0.0.0" ||
|
|
25
|
+
hostname === "::1" ||
|
|
26
|
+
hostname === "[::1]") {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// If URL parsing fails, check raw string for local patterns
|
|
32
|
+
if (url.includes("localhost") ||
|
|
33
|
+
url.includes("127.0.0.1") ||
|
|
34
|
+
url.includes("0.0.0.0") ||
|
|
35
|
+
url.includes("[::1]")) {
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=local-model-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-model-check.js","sourceRoot":"","sources":["../../src/core/local-model-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,KAA0B;IACtD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC;IAC1B,IAAI,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IAEvB,oBAAoB;IACpB,IAAI,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtE,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QACjC,IACC,QAAQ,KAAK,WAAW;YACxB,QAAQ,KAAK,WAAW;YACxB,QAAQ,KAAK,SAAS;YACtB,QAAQ,KAAK,KAAK;YAClB,QAAQ,KAAK,OAAO,EACnB,CAAC;YACF,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,4DAA4D;QAC5D,IACC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC;YACzB,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC;YACzB,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;YACvB,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,EACpB,CAAC;YACF,OAAO,IAAI,CAAC;QACb,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC","sourcesContent":["/**\n * local-model-check.ts — Utility to detect if a model baseUrl is local.\n *\n * Leaf module with zero transitive dependencies on TypeScript parameter properties.\n * Used by ModelRegistry and tests.\n */\n\n/**\n * Check if a model's baseUrl points to a local endpoint.\n * Returns true for localhost, 127.0.0.1, 0.0.0.0, ::1, or unix socket paths.\n * Returns false if baseUrl is empty (cloud provider) or points to a remote host.\n */\nexport function isLocalModel(model: { baseUrl: string }): boolean {\n\tconst url = model.baseUrl;\n\tif (!url) return false;\n\n\t// Unix socket paths\n\tif (url.startsWith(\"unix://\") || url.startsWith(\"unix:\")) return true;\n\n\ttry {\n\t\tconst parsed = new URL(url);\n\t\tconst hostname = parsed.hostname;\n\t\tif (\n\t\t\thostname === \"localhost\" ||\n\t\t\thostname === \"127.0.0.1\" ||\n\t\t\thostname === \"0.0.0.0\" ||\n\t\t\thostname === \"::1\" ||\n\t\t\thostname === \"[::1]\"\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t} catch {\n\t\t// If URL parsing fails, check raw string for local patterns\n\t\tif (\n\t\t\turl.includes(\"localhost\") ||\n\t\t\turl.includes(\"127.0.0.1\") ||\n\t\t\turl.includes(\"0.0.0.0\") ||\n\t\t\turl.includes(\"[::1]\")\n\t\t) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n"]}
|
|
@@ -115,6 +115,17 @@ export declare class ModelRegistry {
|
|
|
115
115
|
* Convert DiscoveryResult[] into Model<Api>[] with default values.
|
|
116
116
|
*/
|
|
117
117
|
private convertDiscoveredModels;
|
|
118
|
+
/**
|
|
119
|
+
* Check if a model's baseUrl points to a local endpoint.
|
|
120
|
+
* Delegates to standalone isLocalModel() function.
|
|
121
|
+
*/
|
|
122
|
+
static isLocalModel(model: Model<Api>): boolean;
|
|
123
|
+
/**
|
|
124
|
+
* Check if all models in the registry are local.
|
|
125
|
+
* Returns true only if every model passes isLocalModel().
|
|
126
|
+
* Returns false if there are no models.
|
|
127
|
+
*/
|
|
128
|
+
isAllLocalChain(): boolean;
|
|
118
129
|
}
|
|
119
130
|
/**
|
|
120
131
|
* Input type for registerProvider API.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-registry.d.ts","sourceRoot":"","sources":["../../src/core/model-registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACN,KAAK,GAAG,EACR,KAAK,2BAA2B,EAChC,KAAK,OAAO,EAIZ,KAAK,KAAK,EACV,KAAK,sBAAsB,EAK3B,KAAK,mBAAmB,EACxB,MAAM,YAAY,CAAC;AAOpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"model-registry.d.ts","sourceRoot":"","sources":["../../src/core/model-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,7 @@ import { getAgentDir } from "../config.js";
|
|
|
11
11
|
import { ModelDiscoveryCache } from "./discovery-cache.js";
|
|
12
12
|
import { getDiscoverableProviders, getDiscoveryAdapter } from "./model-discovery.js";
|
|
13
13
|
import { resolveConfigValue, resolveHeaders } from "./resolve-config-value.js";
|
|
14
|
+
import { isLocalModel } from "./local-model-check.js";
|
|
14
15
|
const Ajv = AjvModule.default || AjvModule;
|
|
15
16
|
const ajv = new Ajv();
|
|
16
17
|
// Schema for OpenRouter routing preferences
|
|
@@ -439,7 +440,7 @@ export class ModelRegistry {
|
|
|
439
440
|
const authMode = this.getProviderAuthMode(model.provider);
|
|
440
441
|
if (authMode === "externalCli" || authMode === "none")
|
|
441
442
|
return undefined;
|
|
442
|
-
return this.authStorage.getApiKey(model.provider, sessionId);
|
|
443
|
+
return this.authStorage.getApiKey(model.provider, sessionId, { baseUrl: model.baseUrl });
|
|
443
444
|
}
|
|
444
445
|
/**
|
|
445
446
|
* Get API key for a provider.
|
|
@@ -670,5 +671,23 @@ export class ModelRegistry {
|
|
|
670
671
|
}
|
|
671
672
|
return converted;
|
|
672
673
|
}
|
|
674
|
+
/**
|
|
675
|
+
* Check if a model's baseUrl points to a local endpoint.
|
|
676
|
+
* Delegates to standalone isLocalModel() function.
|
|
677
|
+
*/
|
|
678
|
+
static isLocalModel(model) {
|
|
679
|
+
return isLocalModel(model);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Check if all models in the registry are local.
|
|
683
|
+
* Returns true only if every model passes isLocalModel().
|
|
684
|
+
* Returns false if there are no models.
|
|
685
|
+
*/
|
|
686
|
+
isAllLocalChain() {
|
|
687
|
+
const models = this.getAll();
|
|
688
|
+
if (models.length === 0)
|
|
689
|
+
return false;
|
|
690
|
+
return models.every((m) => isLocalModel(m));
|
|
691
|
+
}
|
|
673
692
|
}
|
|
674
693
|
//# sourceMappingURL=model-registry.js.map
|