@ashx-j/lunr-ai 0.2.23 → 0.2.25-dev.13.1

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.
Files changed (58) hide show
  1. package/dist/api/anthropic-claude-code-bridge.d.ts +6 -0
  2. package/dist/api/anthropic-claude-code-bridge.d.ts.map +1 -0
  3. package/dist/api/anthropic-claude-code-bridge.js +582 -0
  4. package/dist/api/anthropic-claude-code-bridge.js.map +1 -0
  5. package/dist/api/anthropic-messages.d.ts.map +1 -1
  6. package/dist/api/anthropic-messages.js +7 -19
  7. package/dist/api/anthropic-messages.js.map +1 -1
  8. package/dist/auth/anthropic-route.d.ts +7 -0
  9. package/dist/auth/anthropic-route.d.ts.map +1 -0
  10. package/dist/auth/anthropic-route.js +25 -0
  11. package/dist/auth/anthropic-route.js.map +1 -0
  12. package/dist/auth/oauth/anthropic.d.ts +1 -6
  13. package/dist/auth/oauth/anthropic.d.ts.map +1 -1
  14. package/dist/auth/oauth/anthropic.js +214 -277
  15. package/dist/auth/oauth/anthropic.js.map +1 -1
  16. package/dist/auth/resolve.d.ts.map +1 -1
  17. package/dist/auth/resolve.js +27 -0
  18. package/dist/auth/resolve.js.map +1 -1
  19. package/dist/auth/types.d.ts +15 -2
  20. package/dist/auth/types.d.ts.map +1 -1
  21. package/dist/auth/types.js.map +1 -1
  22. package/dist/cli.d.ts.map +1 -1
  23. package/dist/cli.js +2 -0
  24. package/dist/cli.js.map +1 -1
  25. package/dist/env-api-keys.d.ts.map +1 -1
  26. package/dist/env-api-keys.js +1 -2
  27. package/dist/env-api-keys.js.map +1 -1
  28. package/dist/index.d.ts +1 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +1 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/models.d.ts.map +1 -1
  33. package/dist/models.js +19 -3
  34. package/dist/models.js.map +1 -1
  35. package/dist/providers/anthropic.d.ts.map +1 -1
  36. package/dist/providers/anthropic.js +32 -3
  37. package/dist/providers/anthropic.js.map +1 -1
  38. package/dist/providers/radius.d.ts.map +1 -1
  39. package/dist/providers/radius.js +5 -1
  40. package/dist/providers/radius.js.map +1 -1
  41. package/dist/types.d.ts +13 -0
  42. package/dist/types.d.ts.map +1 -1
  43. package/dist/types.js.map +1 -1
  44. package/package.json +15 -2
  45. package/vendor/hermes-claude-subscription-directsdk/ATTRIBUTION.md +9 -0
  46. package/vendor/hermes-claude-subscription-directsdk/LICENSE +21 -0
  47. package/vendor/hermes-claude-subscription-directsdk/README.md +179 -0
  48. package/vendor/hermes-claude-subscription-directsdk/admission.py +201 -0
  49. package/vendor/hermes-claude-subscription-directsdk/agent/reasoning_effort.py +17 -0
  50. package/vendor/hermes-claude-subscription-directsdk/directsdk.py +629 -0
  51. package/vendor/hermes-claude-subscription-directsdk/directsdk_setup.py +116 -0
  52. package/vendor/hermes-claude-subscription-directsdk/inert_mcp.py +24 -0
  53. package/vendor/hermes-claude-subscription-directsdk/lunr_bridge.py +89 -0
  54. package/vendor/hermes-claude-subscription-directsdk/lunr_setup_bridge.py +49 -0
  55. package/vendor/hermes-claude-subscription-directsdk/manifest.json +32 -0
  56. package/vendor/hermes-claude-subscription-directsdk/model_catalog.py +44 -0
  57. package/vendor/hermes-claude-subscription-directsdk/patches/0001-lunr-lifecycle-hooks.patch +14 -0
  58. package/vendor/hermes-claude-subscription-directsdk/tools/schema_sanitizer.py +23 -0
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAGX,WAAW,EACX,UAAU,EAEV,eAAe,EAGf,YAAY,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,kBAAkB,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7G,MAAM,WAAW,uBAAuB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,WAAW,CAAC;CAClB;AAED,qBAAa,WAAY,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAE/B,YAAY,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAIhF;CACD;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACxC,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,EAC5C,WAAW,EAAE,eAAe,EAC5B,WAAW,EAAE,WAAW,EACxB,SAAS,CAAC,EAAE,uBAAuB,GACjC,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CA2BjC","sourcesContent":["import type { ProviderEnv } from \"../types.ts\";\nimport type {\n\tApiKeyAuth,\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tCredential,\n\tCredentialStore,\n\tOAuthAuth,\n\tOAuthCredential,\n\tProviderAuth,\n} from \"./types.ts\";\n\nexport type ModelsErrorCode = \"model_source\" | \"model_validation\" | \"provider\" | \"stream\" | \"auth\" | \"oauth\";\n\nexport interface AuthResolutionOverrides {\n\tapiKey?: string;\n\tenv?: ProviderEnv;\n}\n\nexport class ModelsError extends Error {\n\treadonly code: ModelsErrorCode;\n\n\tconstructor(code: ModelsErrorCode, message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options);\n\t\tthis.name = \"ModelsError\";\n\t\tthis.code = code;\n\t}\n}\n\n/**\n * Auth resolution shared by the `Models` and `ImagesModels` collections.\n * A stored credential owns the provider: ambient/env is consulted only when\n * nothing is stored. No silent env fallback after a failed refresh or for a\n * credential type without a matching handler.\n */\nexport async function resolveProviderAuth(\n\tprovider: { id: string; auth: ProviderAuth },\n\tcredentials: CredentialStore,\n\tauthContext: AuthContext,\n\toverrides?: AuthResolutionOverrides,\n): Promise<AuthResult | undefined> {\n\tconst requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;\n\n\tif (overrides?.apiKey !== undefined && provider.auth.apiKey) {\n\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {\n\t\t\ttype: \"api_key\",\n\t\t\tkey: overrides.apiKey,\n\t\t\tenv: overrides.env,\n\t\t});\n\t}\n\n\tconst stored = await readCredential(credentials, provider.id);\n\tif (stored) {\n\t\tif (stored.type === \"oauth\" && provider.auth.oauth) {\n\t\t\treturn resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);\n\t\t}\n\t\tif (stored.type === \"api_key\" && provider.auth.apiKey) {\n\t\t\tconst credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;\n\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, credential);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// Ambient (env vars, AWS profiles, ADC files).\n\treturn provider.auth.apiKey\n\t\t? resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, undefined)\n\t\t: undefined;\n}\n\nfunction overlayEnvAuthContext(base: AuthContext, env: ProviderEnv): AuthContext {\n\treturn {\n\t\tenv: async (name) => env[name] || (await base.env(name)),\n\t\tfileExists: (path) => base.fileExists(path),\n\t};\n}\n\n/**\n * OAuth resolution with double-checked locking (same pattern as today's\n * AuthStorage): valid tokens cost zero locks; expired tokens lock, re-check\n * expiry under the lock, refresh once globally, and persist the rotated\n * credential before release.\n */\nasync function resolveStoredOAuth(\n\tcredentials: CredentialStore,\n\tproviderId: string,\n\toauth: OAuthAuth,\n\tstored: OAuthCredential,\n): Promise<AuthResult | undefined> {\n\tlet credential = stored;\n\n\tif (Date.now() >= credential.expires) {\n\t\t// Optimistic check said expired; the authoritative check runs under the lock.\n\t\tlet post: Credential | undefined;\n\t\ttry {\n\t\t\tpost = await credentials.modify(providerId, async (current) => {\n\t\t\t\tif (current?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\t\t\tif (Date.now() < current.expires) return undefined; // another process/request refreshed\n\t\t\t\ttry {\n\t\t\t\t\treturn await oauth.refresh(current);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new ModelsError(\"oauth\", `OAuth refresh failed for ${providerId}`, { cause: error });\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof ModelsError) throw error;\n\t\t\tthrow new ModelsError(\"auth\", `Credential store modify failed for ${providerId}`, { cause: error });\n\t\t}\n\t\tif (post?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\tcredential = post;\n\t}\n\n\ttry {\n\t\treturn { auth: await oauth.toAuth(credential), source: \"OAuth\" };\n\t} catch (error) {\n\t\tthrow new ModelsError(\"oauth\", `OAuth auth derivation failed for ${providerId}`, { cause: error });\n\t}\n}\n\nasync function resolveApiKey(\n\tauthContext: AuthContext,\n\tapiKey: ApiKeyAuth,\n\tproviderId: string,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<AuthResult | undefined> {\n\ttry {\n\t\treturn await apiKey.resolve({ ctx: authContext, credential });\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `API key auth failed for provider ${providerId}`, { cause: error });\n\t}\n}\n\nasync function readCredential(credentials: CredentialStore, providerId: string): Promise<Credential | undefined> {\n\ttry {\n\t\treturn await credentials.read(providerId);\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `Credential store read failed for ${providerId}`, { cause: error });\n\t}\n}\n"]}
1
+ {"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAGX,WAAW,EACX,UAAU,EAEV,eAAe,EAGf,YAAY,EACZ,MAAM,YAAY,CAAC;AAEpB,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,kBAAkB,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAE7G,MAAM,WAAW,uBAAuB;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,WAAW,CAAC;CAClB;AAED,qBAAa,WAAY,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAE/B,YAAY,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAIhF;CACD;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACxC,QAAQ,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,EAC5C,WAAW,EAAE,eAAe,EAC5B,WAAW,EAAE,WAAW,EACxB,SAAS,CAAC,EAAE,uBAAuB,GACjC,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAuDjC","sourcesContent":["import type { ProviderEnv } from \"../types.ts\";\nimport { ANTHROPIC_SETUP_REQUIRED, isAnthropicOAuthToken } from \"./anthropic-route.ts\";\nimport type {\n\tApiKeyAuth,\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tCredential,\n\tCredentialStore,\n\tOAuthAuth,\n\tOAuthCredential,\n\tProviderAuth,\n} from \"./types.ts\";\n\nexport type ModelsErrorCode = \"model_source\" | \"model_validation\" | \"provider\" | \"stream\" | \"auth\" | \"oauth\";\n\nexport interface AuthResolutionOverrides {\n\tapiKey?: string;\n\tenv?: ProviderEnv;\n}\n\nexport class ModelsError extends Error {\n\treadonly code: ModelsErrorCode;\n\n\tconstructor(code: ModelsErrorCode, message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options);\n\t\tthis.name = \"ModelsError\";\n\t\tthis.code = code;\n\t}\n}\n\n/**\n * Auth resolution shared by the `Models` and `ImagesModels` collections.\n * A stored credential owns the provider: ambient/env is consulted only when\n * nothing is stored. No silent env fallback after a failed refresh or for a\n * credential type without a matching handler.\n */\nexport async function resolveProviderAuth(\n\tprovider: { id: string; auth: ProviderAuth },\n\tcredentials: CredentialStore,\n\tauthContext: AuthContext,\n\toverrides?: AuthResolutionOverrides,\n): Promise<AuthResult | undefined> {\n\tconst requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;\n\n\tif (provider.id === \"anthropic\" && isAnthropicOAuthToken(overrides?.apiKey)) {\n\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t}\n\tif (overrides?.apiKey !== undefined && provider.auth.apiKey) {\n\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {\n\t\t\ttype: \"api_key\",\n\t\t\tkey: overrides.apiKey,\n\t\t\tenv: overrides.env,\n\t\t});\n\t}\n\n\tconst stored = await readCredential(credentials, provider.id);\n\tif (stored) {\n\t\tif (provider.id === \"anthropic\" && stored.type === \"oauth\") {\n\t\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t\t}\n\t\tif (\n\t\t\tstored.type === \"external_claude_code\" &&\n\t\t\tprovider.id === \"anthropic\" &&\n\t\t\tstored.version === 1 &&\n\t\t\tstored.manager === \"claude-code\"\n\t\t) {\n\t\t\tconst apiKey = await requestAuthContext.env(\"ANTHROPIC_API_KEY\");\n\t\t\tif (apiKey && provider.auth.apiKey)\n\t\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {\n\t\t\t\t\ttype: \"api_key\",\n\t\t\t\t\tkey: apiKey,\n\t\t\t\t});\n\t\t\tif (await requestAuthContext.env(\"ANTHROPIC_OAUTH_TOKEN\"))\n\t\t\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t\t\treturn { auth: { externalClaudeCode: stored }, source: \"Claude Code subscription\" };\n\t\t}\n\t\tif (stored.type === \"oauth\" && provider.auth.oauth) {\n\t\t\treturn resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);\n\t\t}\n\t\tif (stored.type === \"api_key\" && provider.auth.apiKey) {\n\t\t\tif (provider.id === \"anthropic\" && isAnthropicOAuthToken(stored.key)) {\n\t\t\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t\t\t}\n\t\t\tconst credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;\n\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, credential);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// Ambient (env vars, AWS profiles, ADC files).\n\tif (provider.id === \"anthropic\" && (await requestAuthContext.env(\"ANTHROPIC_OAUTH_TOKEN\"))) {\n\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t}\n\treturn provider.auth.apiKey\n\t\t? resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, undefined)\n\t\t: undefined;\n}\n\nfunction overlayEnvAuthContext(base: AuthContext, env: ProviderEnv): AuthContext {\n\treturn {\n\t\tenv: async (name) => env[name] || (await base.env(name)),\n\t\tfileExists: (path) => base.fileExists(path),\n\t};\n}\n\n/**\n * OAuth resolution with double-checked locking (same pattern as today's\n * AuthStorage): valid tokens cost zero locks; expired tokens lock, re-check\n * expiry under the lock, refresh once globally, and persist the rotated\n * credential before release.\n */\nasync function resolveStoredOAuth(\n\tcredentials: CredentialStore,\n\tproviderId: string,\n\toauth: OAuthAuth,\n\tstored: OAuthCredential,\n): Promise<AuthResult | undefined> {\n\tlet credential = stored;\n\n\tif (Date.now() >= credential.expires) {\n\t\t// Optimistic check said expired; the authoritative check runs under the lock.\n\t\tlet post: Credential | undefined;\n\t\ttry {\n\t\t\tpost = await credentials.modify(providerId, async (current) => {\n\t\t\t\tif (current?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\t\t\tif (Date.now() < current.expires) return undefined; // another process/request refreshed\n\t\t\t\ttry {\n\t\t\t\t\treturn await oauth.refresh(current);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new ModelsError(\"oauth\", `OAuth refresh failed for ${providerId}`, { cause: error });\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof ModelsError) throw error;\n\t\t\tthrow new ModelsError(\"auth\", `Credential store modify failed for ${providerId}`, { cause: error });\n\t\t}\n\t\tif (post?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\tcredential = post;\n\t}\n\n\ttry {\n\t\treturn { auth: await oauth.toAuth(credential), source: \"OAuth\" };\n\t} catch (error) {\n\t\tthrow new ModelsError(\"oauth\", `OAuth auth derivation failed for ${providerId}`, { cause: error });\n\t}\n}\n\nasync function resolveApiKey(\n\tauthContext: AuthContext,\n\tapiKey: ApiKeyAuth,\n\tproviderId: string,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<AuthResult | undefined> {\n\ttry {\n\t\treturn await apiKey.resolve({ ctx: authContext, credential });\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `API key auth failed for provider ${providerId}`, { cause: error });\n\t}\n}\n\nasync function readCredential(credentials: CredentialStore, providerId: string): Promise<Credential | undefined> {\n\ttry {\n\t\treturn await credentials.read(providerId);\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `Credential store read failed for ${providerId}`, { cause: error });\n\t}\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { ANTHROPIC_SETUP_REQUIRED, isAnthropicOAuthToken } from "./anthropic-route.js";
1
2
  export class ModelsError extends Error {
2
3
  code;
3
4
  constructor(code, message, options) {
@@ -14,6 +15,9 @@ export class ModelsError extends Error {
14
15
  */
15
16
  export async function resolveProviderAuth(provider, credentials, authContext, overrides) {
16
17
  const requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;
18
+ if (provider.id === "anthropic" && isAnthropicOAuthToken(overrides?.apiKey)) {
19
+ throw new ModelsError("auth", ANTHROPIC_SETUP_REQUIRED);
20
+ }
17
21
  if (overrides?.apiKey !== undefined && provider.auth.apiKey) {
18
22
  return resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {
19
23
  type: "api_key",
@@ -23,16 +27,39 @@ export async function resolveProviderAuth(provider, credentials, authContext, ov
23
27
  }
24
28
  const stored = await readCredential(credentials, provider.id);
25
29
  if (stored) {
30
+ if (provider.id === "anthropic" && stored.type === "oauth") {
31
+ throw new ModelsError("auth", ANTHROPIC_SETUP_REQUIRED);
32
+ }
33
+ if (stored.type === "external_claude_code" &&
34
+ provider.id === "anthropic" &&
35
+ stored.version === 1 &&
36
+ stored.manager === "claude-code") {
37
+ const apiKey = await requestAuthContext.env("ANTHROPIC_API_KEY");
38
+ if (apiKey && provider.auth.apiKey)
39
+ return resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {
40
+ type: "api_key",
41
+ key: apiKey,
42
+ });
43
+ if (await requestAuthContext.env("ANTHROPIC_OAUTH_TOKEN"))
44
+ throw new ModelsError("auth", ANTHROPIC_SETUP_REQUIRED);
45
+ return { auth: { externalClaudeCode: stored }, source: "Claude Code subscription" };
46
+ }
26
47
  if (stored.type === "oauth" && provider.auth.oauth) {
27
48
  return resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);
28
49
  }
29
50
  if (stored.type === "api_key" && provider.auth.apiKey) {
51
+ if (provider.id === "anthropic" && isAnthropicOAuthToken(stored.key)) {
52
+ throw new ModelsError("auth", ANTHROPIC_SETUP_REQUIRED);
53
+ }
30
54
  const credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;
31
55
  return resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, credential);
32
56
  }
33
57
  return undefined;
34
58
  }
35
59
  // Ambient (env vars, AWS profiles, ADC files).
60
+ if (provider.id === "anthropic" && (await requestAuthContext.env("ANTHROPIC_OAUTH_TOKEN"))) {
61
+ throw new ModelsError("auth", ANTHROPIC_SETUP_REQUIRED);
62
+ }
36
63
  return provider.auth.apiKey
37
64
  ? resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, undefined)
38
65
  : undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"AAoBA,MAAM,OAAO,WAAY,SAAQ,KAAK;IAC5B,IAAI,CAAkB;IAE/B,YAAY,IAAqB,EAAE,OAAe,EAAE,OAA6B,EAAE;QAClF,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;QAC1B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IAAA,CACjB;CACD;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,QAA4C,EAC5C,WAA4B,EAC5B,WAAwB,EACxB,SAAmC,EACD;IAClC,MAAM,kBAAkB,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,qBAAqB,CAAC,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IAE5G,IAAI,SAAS,EAAE,MAAM,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7D,OAAO,aAAa,CAAC,kBAAkB,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE;YAC3E,IAAI,EAAE,SAAS;YACf,GAAG,EAAE,SAAS,CAAC,MAAM;YACrB,GAAG,EAAE,SAAS,CAAC,GAAG;SAClB,CAAC,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC9D,IAAI,MAAM,EAAE,CAAC;QACZ,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACpD,OAAO,kBAAkB,CAAC,WAAW,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACvD,MAAM,UAAU,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;YACrG,OAAO,aAAa,CAAC,kBAAkB,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACzF,CAAC;QACD,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,+CAA+C;IAC/C,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM;QAC1B,CAAC,CAAC,aAAa,CAAC,kBAAkB,EAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC;QACjF,CAAC,CAAC,SAAS,CAAC;AAAA,CACb;AAED,SAAS,qBAAqB,CAAC,IAAiB,EAAE,GAAgB,EAAe;IAChF,OAAO;QACN,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxD,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;KAC3C,CAAC;AAAA,CACF;AAED;;;;;GAKG;AACH,KAAK,UAAU,kBAAkB,CAChC,WAA4B,EAC5B,UAAkB,EAClB,KAAgB,EAChB,MAAuB,EACW;IAClC,IAAI,UAAU,GAAG,MAAM,CAAC;IAExB,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACtC,8EAA8E;QAC9E,IAAI,IAA4B,CAAC;QACjC,IAAI,CAAC;YACJ,IAAI,GAAG,MAAM,WAAW,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC;gBAC9D,IAAI,OAAO,EAAE,IAAI,KAAK,OAAO;oBAAE,OAAO,SAAS,CAAC,CAAC,uBAAuB;gBACxE,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO;oBAAE,OAAO,SAAS,CAAC,CAAC,oCAAoC;gBACxF,IAAI,CAAC;oBACJ,OAAO,MAAM,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACrC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,4BAA4B,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;gBAC5F,CAAC;YAAA,CACD,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,IAAI,KAAK,YAAY,WAAW;gBAAE,MAAM,KAAK,CAAC;YAC9C,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,sCAAsC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QACrG,CAAC;QACD,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO;YAAE,OAAO,SAAS,CAAC,CAAC,uBAAuB;QACrE,UAAU,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,IAAI,CAAC;QACJ,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IAClE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,oCAAoC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACpG,CAAC;AAAA,CACD;AAED,KAAK,UAAU,aAAa,CAC3B,WAAwB,EACxB,MAAkB,EAClB,UAAkB,EAClB,UAAwC,EACN;IAClC,IAAI,CAAC;QACJ,OAAO,MAAM,MAAM,CAAC,OAAO,CAAC,EAAE,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;IAC/D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,oCAAoC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACnG,CAAC;AAAA,CACD;AAED,KAAK,UAAU,cAAc,CAAC,WAA4B,EAAE,UAAkB,EAAmC;IAChH,IAAI,CAAC;QACJ,OAAO,MAAM,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,MAAM,IAAI,WAAW,CAAC,MAAM,EAAE,oCAAoC,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IACnG,CAAC;AAAA,CACD","sourcesContent":["import type { ProviderEnv } from \"../types.ts\";\nimport type {\n\tApiKeyAuth,\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tCredential,\n\tCredentialStore,\n\tOAuthAuth,\n\tOAuthCredential,\n\tProviderAuth,\n} from \"./types.ts\";\n\nexport type ModelsErrorCode = \"model_source\" | \"model_validation\" | \"provider\" | \"stream\" | \"auth\" | \"oauth\";\n\nexport interface AuthResolutionOverrides {\n\tapiKey?: string;\n\tenv?: ProviderEnv;\n}\n\nexport class ModelsError extends Error {\n\treadonly code: ModelsErrorCode;\n\n\tconstructor(code: ModelsErrorCode, message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options);\n\t\tthis.name = \"ModelsError\";\n\t\tthis.code = code;\n\t}\n}\n\n/**\n * Auth resolution shared by the `Models` and `ImagesModels` collections.\n * A stored credential owns the provider: ambient/env is consulted only when\n * nothing is stored. No silent env fallback after a failed refresh or for a\n * credential type without a matching handler.\n */\nexport async function resolveProviderAuth(\n\tprovider: { id: string; auth: ProviderAuth },\n\tcredentials: CredentialStore,\n\tauthContext: AuthContext,\n\toverrides?: AuthResolutionOverrides,\n): Promise<AuthResult | undefined> {\n\tconst requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;\n\n\tif (overrides?.apiKey !== undefined && provider.auth.apiKey) {\n\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {\n\t\t\ttype: \"api_key\",\n\t\t\tkey: overrides.apiKey,\n\t\t\tenv: overrides.env,\n\t\t});\n\t}\n\n\tconst stored = await readCredential(credentials, provider.id);\n\tif (stored) {\n\t\tif (stored.type === \"oauth\" && provider.auth.oauth) {\n\t\t\treturn resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);\n\t\t}\n\t\tif (stored.type === \"api_key\" && provider.auth.apiKey) {\n\t\t\tconst credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;\n\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, credential);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// Ambient (env vars, AWS profiles, ADC files).\n\treturn provider.auth.apiKey\n\t\t? resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, undefined)\n\t\t: undefined;\n}\n\nfunction overlayEnvAuthContext(base: AuthContext, env: ProviderEnv): AuthContext {\n\treturn {\n\t\tenv: async (name) => env[name] || (await base.env(name)),\n\t\tfileExists: (path) => base.fileExists(path),\n\t};\n}\n\n/**\n * OAuth resolution with double-checked locking (same pattern as today's\n * AuthStorage): valid tokens cost zero locks; expired tokens lock, re-check\n * expiry under the lock, refresh once globally, and persist the rotated\n * credential before release.\n */\nasync function resolveStoredOAuth(\n\tcredentials: CredentialStore,\n\tproviderId: string,\n\toauth: OAuthAuth,\n\tstored: OAuthCredential,\n): Promise<AuthResult | undefined> {\n\tlet credential = stored;\n\n\tif (Date.now() >= credential.expires) {\n\t\t// Optimistic check said expired; the authoritative check runs under the lock.\n\t\tlet post: Credential | undefined;\n\t\ttry {\n\t\t\tpost = await credentials.modify(providerId, async (current) => {\n\t\t\t\tif (current?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\t\t\tif (Date.now() < current.expires) return undefined; // another process/request refreshed\n\t\t\t\ttry {\n\t\t\t\t\treturn await oauth.refresh(current);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new ModelsError(\"oauth\", `OAuth refresh failed for ${providerId}`, { cause: error });\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof ModelsError) throw error;\n\t\t\tthrow new ModelsError(\"auth\", `Credential store modify failed for ${providerId}`, { cause: error });\n\t\t}\n\t\tif (post?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\tcredential = post;\n\t}\n\n\ttry {\n\t\treturn { auth: await oauth.toAuth(credential), source: \"OAuth\" };\n\t} catch (error) {\n\t\tthrow new ModelsError(\"oauth\", `OAuth auth derivation failed for ${providerId}`, { cause: error });\n\t}\n}\n\nasync function resolveApiKey(\n\tauthContext: AuthContext,\n\tapiKey: ApiKeyAuth,\n\tproviderId: string,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<AuthResult | undefined> {\n\ttry {\n\t\treturn await apiKey.resolve({ ctx: authContext, credential });\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `API key auth failed for provider ${providerId}`, { cause: error });\n\t}\n}\n\nasync function readCredential(credentials: CredentialStore, providerId: string): Promise<Credential | undefined> {\n\ttry {\n\t\treturn await credentials.read(providerId);\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `Credential store read failed for ${providerId}`, { cause: error });\n\t}\n}\n"]}
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../src/auth/resolve.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProviderEnv } from \"../types.ts\";\nimport { ANTHROPIC_SETUP_REQUIRED, isAnthropicOAuthToken } from \"./anthropic-route.ts\";\nimport type {\n\tApiKeyAuth,\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tCredential,\n\tCredentialStore,\n\tOAuthAuth,\n\tOAuthCredential,\n\tProviderAuth,\n} from \"./types.ts\";\n\nexport type ModelsErrorCode = \"model_source\" | \"model_validation\" | \"provider\" | \"stream\" | \"auth\" | \"oauth\";\n\nexport interface AuthResolutionOverrides {\n\tapiKey?: string;\n\tenv?: ProviderEnv;\n}\n\nexport class ModelsError extends Error {\n\treadonly code: ModelsErrorCode;\n\n\tconstructor(code: ModelsErrorCode, message: string, options?: { cause?: unknown }) {\n\t\tsuper(message, options);\n\t\tthis.name = \"ModelsError\";\n\t\tthis.code = code;\n\t}\n}\n\n/**\n * Auth resolution shared by the `Models` and `ImagesModels` collections.\n * A stored credential owns the provider: ambient/env is consulted only when\n * nothing is stored. No silent env fallback after a failed refresh or for a\n * credential type without a matching handler.\n */\nexport async function resolveProviderAuth(\n\tprovider: { id: string; auth: ProviderAuth },\n\tcredentials: CredentialStore,\n\tauthContext: AuthContext,\n\toverrides?: AuthResolutionOverrides,\n): Promise<AuthResult | undefined> {\n\tconst requestAuthContext = overrides?.env ? overlayEnvAuthContext(authContext, overrides.env) : authContext;\n\n\tif (provider.id === \"anthropic\" && isAnthropicOAuthToken(overrides?.apiKey)) {\n\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t}\n\tif (overrides?.apiKey !== undefined && provider.auth.apiKey) {\n\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {\n\t\t\ttype: \"api_key\",\n\t\t\tkey: overrides.apiKey,\n\t\t\tenv: overrides.env,\n\t\t});\n\t}\n\n\tconst stored = await readCredential(credentials, provider.id);\n\tif (stored) {\n\t\tif (provider.id === \"anthropic\" && stored.type === \"oauth\") {\n\t\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t\t}\n\t\tif (\n\t\t\tstored.type === \"external_claude_code\" &&\n\t\t\tprovider.id === \"anthropic\" &&\n\t\t\tstored.version === 1 &&\n\t\t\tstored.manager === \"claude-code\"\n\t\t) {\n\t\t\tconst apiKey = await requestAuthContext.env(\"ANTHROPIC_API_KEY\");\n\t\t\tif (apiKey && provider.auth.apiKey)\n\t\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, {\n\t\t\t\t\ttype: \"api_key\",\n\t\t\t\t\tkey: apiKey,\n\t\t\t\t});\n\t\t\tif (await requestAuthContext.env(\"ANTHROPIC_OAUTH_TOKEN\"))\n\t\t\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t\t\treturn { auth: { externalClaudeCode: stored }, source: \"Claude Code subscription\" };\n\t\t}\n\t\tif (stored.type === \"oauth\" && provider.auth.oauth) {\n\t\t\treturn resolveStoredOAuth(credentials, provider.id, provider.auth.oauth, stored);\n\t\t}\n\t\tif (stored.type === \"api_key\" && provider.auth.apiKey) {\n\t\t\tif (provider.id === \"anthropic\" && isAnthropicOAuthToken(stored.key)) {\n\t\t\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t\t\t}\n\t\t\tconst credential = overrides?.env ? { ...stored, env: { ...stored.env, ...overrides.env } } : stored;\n\t\t\treturn resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, credential);\n\t\t}\n\t\treturn undefined;\n\t}\n\n\t// Ambient (env vars, AWS profiles, ADC files).\n\tif (provider.id === \"anthropic\" && (await requestAuthContext.env(\"ANTHROPIC_OAUTH_TOKEN\"))) {\n\t\tthrow new ModelsError(\"auth\", ANTHROPIC_SETUP_REQUIRED);\n\t}\n\treturn provider.auth.apiKey\n\t\t? resolveApiKey(requestAuthContext, provider.auth.apiKey, provider.id, undefined)\n\t\t: undefined;\n}\n\nfunction overlayEnvAuthContext(base: AuthContext, env: ProviderEnv): AuthContext {\n\treturn {\n\t\tenv: async (name) => env[name] || (await base.env(name)),\n\t\tfileExists: (path) => base.fileExists(path),\n\t};\n}\n\n/**\n * OAuth resolution with double-checked locking (same pattern as today's\n * AuthStorage): valid tokens cost zero locks; expired tokens lock, re-check\n * expiry under the lock, refresh once globally, and persist the rotated\n * credential before release.\n */\nasync function resolveStoredOAuth(\n\tcredentials: CredentialStore,\n\tproviderId: string,\n\toauth: OAuthAuth,\n\tstored: OAuthCredential,\n): Promise<AuthResult | undefined> {\n\tlet credential = stored;\n\n\tif (Date.now() >= credential.expires) {\n\t\t// Optimistic check said expired; the authoritative check runs under the lock.\n\t\tlet post: Credential | undefined;\n\t\ttry {\n\t\t\tpost = await credentials.modify(providerId, async (current) => {\n\t\t\t\tif (current?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\t\t\tif (Date.now() < current.expires) return undefined; // another process/request refreshed\n\t\t\t\ttry {\n\t\t\t\t\treturn await oauth.refresh(current);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new ModelsError(\"oauth\", `OAuth refresh failed for ${providerId}`, { cause: error });\n\t\t\t\t}\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error instanceof ModelsError) throw error;\n\t\t\tthrow new ModelsError(\"auth\", `Credential store modify failed for ${providerId}`, { cause: error });\n\t\t}\n\t\tif (post?.type !== \"oauth\") return undefined; // logged out meanwhile\n\t\tcredential = post;\n\t}\n\n\ttry {\n\t\treturn { auth: await oauth.toAuth(credential), source: \"OAuth\" };\n\t} catch (error) {\n\t\tthrow new ModelsError(\"oauth\", `OAuth auth derivation failed for ${providerId}`, { cause: error });\n\t}\n}\n\nasync function resolveApiKey(\n\tauthContext: AuthContext,\n\tapiKey: ApiKeyAuth,\n\tproviderId: string,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<AuthResult | undefined> {\n\ttry {\n\t\treturn await apiKey.resolve({ ctx: authContext, credential });\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `API key auth failed for provider ${providerId}`, { cause: error });\n\t}\n}\n\nasync function readCredential(credentials: CredentialStore, providerId: string): Promise<Credential | undefined> {\n\ttry {\n\t\treturn await credentials.read(providerId);\n\t} catch (error) {\n\t\tthrow new ModelsError(\"auth\", `Credential store read failed for ${providerId}`, { cause: error });\n\t}\n}\n"]}
@@ -7,6 +7,7 @@ export interface ModelAuth {
7
7
  apiKey?: string;
8
8
  headers?: ProviderHeaders;
9
9
  baseUrl?: string;
10
+ externalClaudeCode?: ExternalClaudeCodeCredential;
10
11
  }
11
12
  /**
12
13
  * Stored api-key credential. `env` holds provider-scoped environment/config
@@ -29,7 +30,17 @@ export interface OAuthCredential extends OAuthCredentials {
29
30
  type: "oauth";
30
31
  }
31
32
  /** One type-tagged credential per provider — the shape of today's auth.json. */
32
- export type Credential = ApiKeyCredential | OAuthCredential;
33
+ export interface ExternalClaudeCodeCredential {
34
+ type: "external_claude_code";
35
+ version: 1;
36
+ manager: "claude-code";
37
+ command: string;
38
+ python: string;
39
+ configDir?: string;
40
+ accountFingerprint?: string;
41
+ routes?: string[];
42
+ }
43
+ export type Credential = ApiKeyCredential | OAuthCredential | ExternalClaudeCodeCredential;
33
44
  /** Non-secret credential metadata for account/status enumeration. */
34
45
  export interface CredentialInfo {
35
46
  providerId: string;
@@ -154,6 +165,8 @@ export interface AuthInteraction {
154
165
  signal?: AbortSignal;
155
166
  prompt(prompt: AuthPrompt): Promise<string>;
156
167
  notify(event: AuthEvent): void;
168
+ /** Interactive terminal handoff for external account login, never used by headless callers. */
169
+ handoff?(command: string, args: readonly string[], env: Record<string, string>): Promise<void>;
157
170
  }
158
171
  /**
159
172
  * Api-key auth: stored key/provider env plus ambient sources (env vars, AWS
@@ -194,7 +207,7 @@ export interface OAuthAuth {
194
207
  name: string;
195
208
  /** Selector label for the subscription login option, e.g. "Sign in with SuperGrok or X Premium". */
196
209
  loginLabel?: string;
197
- login(interaction: AuthInteraction): Promise<OAuthCredential>;
210
+ login(interaction: AuthInteraction): Promise<OAuthCredential | ExternalClaudeCodeCredential>;
198
211
  /**
199
212
  * Exchange the refresh token. Network call; throws on failure
200
213
  * (invalid_grant etc.). `Models` runs this under the store lock.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProviderEnv, ProviderHeaders } from \"../types.ts\";\n\n/**\n * Request auth for a single model request. If a value cannot be expressed as\n * `apiKey`, `headers`, or `baseUrl`, it is provider config, not auth.\n */\nexport interface ModelAuth {\n\tapiKey?: string;\n\theaders?: ProviderHeaders;\n\tbaseUrl?: string;\n}\n\n/**\n * Stored api-key credential. `env` holds provider-scoped environment/config\n * values such as Cloudflare account/gateway ids.\n */\nexport interface ApiKeyCredential {\n\ttype: \"api_key\";\n\tkey?: string;\n\tenv?: ProviderEnv;\n}\n\n/** OAuth token data returned by extension compatibility flows. */\nexport interface OAuthCredentials {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\t[key: string]: unknown;\n}\n\n/** Stored canonical OAuth credential. */\nexport interface OAuthCredential extends OAuthCredentials {\n\ttype: \"oauth\";\n}\n\n/** One type-tagged credential per provider — the shape of today's auth.json. */\nexport type Credential = ApiKeyCredential | OAuthCredential;\n\n/** Non-secret credential metadata for account/status enumeration. */\nexport interface CredentialInfo {\n\tproviderId: string;\n\ttype: Credential[\"type\"];\n}\n\n/**\n * App-owned credential storage, keyed by `Provider.id`, one credential per\n * provider. `modify` is the only write path, so every mutation is a\n * serialized read-modify-write; `Models.getAuth()` runs OAuth refresh inside\n * `modify` so concurrent requests cannot double-refresh a rotated token. The\n * app persists a credential after login via\n * `modify(provider.id, async () => credential)`. Login/logout orchestration\n * is app-owned.\n *\n * Error semantics: `read` resolves `undefined` for missing entries. Methods\n * reject only on storage failure; `Models` wraps such rejections in\n * `ModelsError` with code \"auth\". Best-effort stores that serve an in-memory\n * view and record persistence errors internally (like coding-agent's\n * AuthStorage) are valid implementations.\n */\nexport interface CredentialStore {\n\t/**\n\t * Read the stored credential, possibly expired. Display/status use;\n\t * resolved request auth comes from `Models.getAuth()`.\n\t */\n\tread(providerId: string): Promise<Credential | undefined>;\n\n\t/**\n\t * List stored credential metadata without resolving or exposing secrets.\n\t * Implementations must not execute configured API-key commands while listing.\n\t */\n\tlist(): Promise<readonly CredentialInfo[]>;\n\n\t/**\n\t * Serialized write — the only write path. `fn` sees the current credential\n\t * because correct writes (refresh, login-during-refresh) depend on it;\n\t * return the new credential, or undefined to leave the entry unchanged.\n\t * Mutual exclusion per provider id, cross-process too where the backing\n\t * store supports it (e.g. a file lock). Resolves with the post-write\n\t * credential. Rejections from `fn` propagate.\n\t */\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t): Promise<Credential | undefined>;\n\n\t/** Remove a credential (logout). Implementations serialize this against `modify`. */\n\tdelete(providerId: string): Promise<void>;\n}\n\n/** Environment access for auth resolution. Injectable for tests and browsers. */\nexport interface AuthContext {\n\tenv(name: string): Promise<string | undefined>;\n\t/** Check whether a file exists. Supports a leading `~`. Always false in browsers. */\n\tfileExists(path: string): Promise<boolean>;\n}\n\n/** Result of resolving auth for a model. */\nexport interface AuthResult {\n\tauth: ModelAuth;\n\t/** Provider-scoped environment/config values resolved from credentials and ambient context. */\n\tenv?: ProviderEnv;\n\t/** Human-readable label for status UI: \"ANTHROPIC_API_KEY\", \"OAuth\", \"~/.aws/credentials\". */\n\tsource?: string;\n}\n\nexport interface AuthCheck {\n\tsource?: string;\n\ttype: \"api_key\" | \"oauth\";\n}\n\nexport type AuthType = \"api_key\" | \"oauth\";\n\n/**\n * Prompt shown to the user during login. `signal` lets the flow cancel a\n * pending prompt when an out-of-band event resolves the step, e.g. a\n * `manual_code` prompt raced against a callback server, aborted when the\n * callback wins.\n */\nexport type AuthPrompt = { signal?: AbortSignal } & (\n\t| { type: \"text\"; message: string; placeholder?: string }\n\t| { type: \"secret\"; message: string; placeholder?: string }\n\t| { type: \"select\"; message: string; options: readonly { id: string; label: string; description?: string }[] }\n\t| { type: \"manual_code\"; message: string; placeholder?: string }\n);\n\nexport interface AuthInfoLink {\n\turl: string;\n\tlabel?: string;\n}\n\nexport type AuthEvent =\n\t| { type: \"info\"; message: string; links?: readonly AuthInfoLink[] }\n\t| { type: \"auth_url\"; url: string; instructions?: string }\n\t| {\n\t\t\ttype: \"device_code\";\n\t\t\tuserCode: string;\n\t\t\tverificationUri: string;\n\t\t\tintervalSeconds?: number;\n\t\t\texpiresInSeconds?: number;\n\t }\n\t| { type: \"progress\"; message: string };\n\n/**\n * Login interaction callbacks serving both api-key and OAuth flows.\n *\n * `prompt()` returns the entered/selected string (`select` returns the option\n * id). Rejects on cancel/abort. `signal` aborts the whole login flow;\n * per-prompt cancellation uses `AuthPrompt.signal`.\n */\nexport interface AuthInteraction {\n\tsignal?: AbortSignal;\n\n\tprompt(prompt: AuthPrompt): Promise<string>;\n\tnotify(event: AuthEvent): void;\n}\n\n/**\n * Api-key auth: stored key/provider env plus ambient sources (env vars, AWS\n * profiles, ADC files). Ambient-only providers omit `login`.\n */\nexport interface ApiKeyAuth {\n\t/** Display name, e.g. \"Anthropic API key\". */\n\tname: string;\n\n\t/** Interactive setup (prompt for key/provider env). Absent = ambient-only. */\n\tlogin?(interaction: AuthInteraction): Promise<ApiKeyCredential>;\n\n\t/**\n\t * Optional side-effect-free availability check. Use this when `resolve()` may\n\t * execute commands or perform other request-time work. Missing means Models\n\t * checks availability by resolving auth.\n\t */\n\tcheck?(input: { ctx: AuthContext; credential?: ApiKeyCredential }): Promise<AuthCheck | undefined>;\n\n\t/**\n\t * Resolve auth from the stored credential and/or ambient sources, merging\n\t * per field (`credential.key ?? env(\"...\")`, `credential.env?.NAME ?? env(\"...\")`).\n\t * undefined = not configured. Resolution is provider-scoped; model-specific\n\t * endpoint preparation happens after auth has been resolved.\n\t */\n\tresolve(input: { ctx: AuthContext; credential?: ApiKeyCredential }): Promise<AuthResult | undefined>;\n}\n\n/**\n * OAuth auth. The `refresh`/`toAuth` split lets `Models` own the locked\n * refresh pattern: `refresh` produces a credential, `toAuth` derives request\n * auth from whatever credential ends up stored.\n */\nexport interface OAuthAuth {\n\t/** Display name, e.g. \"Anthropic (Claude Pro/Max)\". */\n\tname: string;\n\n\t/** Selector label for the subscription login option, e.g. \"Sign in with SuperGrok or X Premium\". */\n\tloginLabel?: string;\n\n\tlogin(interaction: AuthInteraction): Promise<OAuthCredential>;\n\n\t/**\n\t * Exchange the refresh token. Network call; throws on failure\n\t * (invalid_grant etc.). `Models` runs this under the store lock.\n\t */\n\trefresh(credential: OAuthCredential, signal?: AbortSignal): Promise<OAuthCredential>;\n\n\t/**\n\t * Side-effect-free derivation of request auth from a valid credential.\n\t * Covers per-credential baseUrl (GitHub Copilot). Async so lazy wrappers\n\t * can load the implementation on first use.\n\t */\n\ttoAuth(credential: OAuthCredential): Promise<ModelAuth>;\n}\n\n/**\n * Provider auth. At least one of `apiKey`/`oauth` must be present: even\n * ambient-credential providers and keyless local servers provide `apiKey`\n * auth whose `resolve()` reports whether the provider is configured.\n */\nexport interface ProviderAuth {\n\tapiKey?: ApiKeyAuth;\n\toauth?: OAuthAuth;\n}\n"]}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProviderEnv, ProviderHeaders } from \"../types.ts\";\n\n/**\n * Request auth for a single model request. If a value cannot be expressed as\n * `apiKey`, `headers`, or `baseUrl`, it is provider config, not auth.\n */\nexport interface ModelAuth {\n\tapiKey?: string;\n\theaders?: ProviderHeaders;\n\tbaseUrl?: string;\n\texternalClaudeCode?: ExternalClaudeCodeCredential;\n}\n\n/**\n * Stored api-key credential. `env` holds provider-scoped environment/config\n * values such as Cloudflare account/gateway ids.\n */\nexport interface ApiKeyCredential {\n\ttype: \"api_key\";\n\tkey?: string;\n\tenv?: ProviderEnv;\n}\n\n/** OAuth token data returned by extension compatibility flows. */\nexport interface OAuthCredentials {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\t[key: string]: unknown;\n}\n\n/** Stored canonical OAuth credential. */\nexport interface OAuthCredential extends OAuthCredentials {\n\ttype: \"oauth\";\n}\n\n/** One type-tagged credential per provider — the shape of today's auth.json. */\nexport interface ExternalClaudeCodeCredential {\n\ttype: \"external_claude_code\";\n\tversion: 1;\n\tmanager: \"claude-code\";\n\tcommand: string;\n\tpython: string;\n\tconfigDir?: string;\n\taccountFingerprint?: string;\n\troutes?: string[];\n}\n\nexport type Credential = ApiKeyCredential | OAuthCredential | ExternalClaudeCodeCredential;\n\n/** Non-secret credential metadata for account/status enumeration. */\nexport interface CredentialInfo {\n\tproviderId: string;\n\ttype: Credential[\"type\"];\n}\n\n/**\n * App-owned credential storage, keyed by `Provider.id`, one credential per\n * provider. `modify` is the only write path, so every mutation is a\n * serialized read-modify-write; `Models.getAuth()` runs OAuth refresh inside\n * `modify` so concurrent requests cannot double-refresh a rotated token. The\n * app persists a credential after login via\n * `modify(provider.id, async () => credential)`. Login/logout orchestration\n * is app-owned.\n *\n * Error semantics: `read` resolves `undefined` for missing entries. Methods\n * reject only on storage failure; `Models` wraps such rejections in\n * `ModelsError` with code \"auth\". Best-effort stores that serve an in-memory\n * view and record persistence errors internally (like coding-agent's\n * AuthStorage) are valid implementations.\n */\nexport interface CredentialStore {\n\t/**\n\t * Read the stored credential, possibly expired. Display/status use;\n\t * resolved request auth comes from `Models.getAuth()`.\n\t */\n\tread(providerId: string): Promise<Credential | undefined>;\n\n\t/**\n\t * List stored credential metadata without resolving or exposing secrets.\n\t * Implementations must not execute configured API-key commands while listing.\n\t */\n\tlist(): Promise<readonly CredentialInfo[]>;\n\n\t/**\n\t * Serialized write — the only write path. `fn` sees the current credential\n\t * because correct writes (refresh, login-during-refresh) depend on it;\n\t * return the new credential, or undefined to leave the entry unchanged.\n\t * Mutual exclusion per provider id, cross-process too where the backing\n\t * store supports it (e.g. a file lock). Resolves with the post-write\n\t * credential. Rejections from `fn` propagate.\n\t */\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t): Promise<Credential | undefined>;\n\n\t/** Remove a credential (logout). Implementations serialize this against `modify`. */\n\tdelete(providerId: string): Promise<void>;\n}\n\n/** Environment access for auth resolution. Injectable for tests and browsers. */\nexport interface AuthContext {\n\tenv(name: string): Promise<string | undefined>;\n\t/** Check whether a file exists. Supports a leading `~`. Always false in browsers. */\n\tfileExists(path: string): Promise<boolean>;\n}\n\n/** Result of resolving auth for a model. */\nexport interface AuthResult {\n\tauth: ModelAuth;\n\t/** Provider-scoped environment/config values resolved from credentials and ambient context. */\n\tenv?: ProviderEnv;\n\t/** Human-readable label for status UI: \"ANTHROPIC_API_KEY\", \"OAuth\", \"~/.aws/credentials\". */\n\tsource?: string;\n}\n\nexport interface AuthCheck {\n\tsource?: string;\n\ttype: \"api_key\" | \"oauth\";\n}\n\nexport type AuthType = \"api_key\" | \"oauth\";\n\n/**\n * Prompt shown to the user during login. `signal` lets the flow cancel a\n * pending prompt when an out-of-band event resolves the step, e.g. a\n * `manual_code` prompt raced against a callback server, aborted when the\n * callback wins.\n */\nexport type AuthPrompt = { signal?: AbortSignal } & (\n\t| { type: \"text\"; message: string; placeholder?: string }\n\t| { type: \"secret\"; message: string; placeholder?: string }\n\t| { type: \"select\"; message: string; options: readonly { id: string; label: string; description?: string }[] }\n\t| { type: \"manual_code\"; message: string; placeholder?: string }\n);\n\nexport interface AuthInfoLink {\n\turl: string;\n\tlabel?: string;\n}\n\nexport type AuthEvent =\n\t| { type: \"info\"; message: string; links?: readonly AuthInfoLink[] }\n\t| { type: \"auth_url\"; url: string; instructions?: string }\n\t| {\n\t\t\ttype: \"device_code\";\n\t\t\tuserCode: string;\n\t\t\tverificationUri: string;\n\t\t\tintervalSeconds?: number;\n\t\t\texpiresInSeconds?: number;\n\t }\n\t| { type: \"progress\"; message: string };\n\n/**\n * Login interaction callbacks serving both api-key and OAuth flows.\n *\n * `prompt()` returns the entered/selected string (`select` returns the option\n * id). Rejects on cancel/abort. `signal` aborts the whole login flow;\n * per-prompt cancellation uses `AuthPrompt.signal`.\n */\nexport interface AuthInteraction {\n\tsignal?: AbortSignal;\n\n\tprompt(prompt: AuthPrompt): Promise<string>;\n\tnotify(event: AuthEvent): void;\n\t/** Interactive terminal handoff for external account login, never used by headless callers. */\n\thandoff?(command: string, args: readonly string[], env: Record<string, string>): Promise<void>;\n}\n\n/**\n * Api-key auth: stored key/provider env plus ambient sources (env vars, AWS\n * profiles, ADC files). Ambient-only providers omit `login`.\n */\nexport interface ApiKeyAuth {\n\t/** Display name, e.g. \"Anthropic API key\". */\n\tname: string;\n\n\t/** Interactive setup (prompt for key/provider env). Absent = ambient-only. */\n\tlogin?(interaction: AuthInteraction): Promise<ApiKeyCredential>;\n\n\t/**\n\t * Optional side-effect-free availability check. Use this when `resolve()` may\n\t * execute commands or perform other request-time work. Missing means Models\n\t * checks availability by resolving auth.\n\t */\n\tcheck?(input: { ctx: AuthContext; credential?: ApiKeyCredential }): Promise<AuthCheck | undefined>;\n\n\t/**\n\t * Resolve auth from the stored credential and/or ambient sources, merging\n\t * per field (`credential.key ?? env(\"...\")`, `credential.env?.NAME ?? env(\"...\")`).\n\t * undefined = not configured. Resolution is provider-scoped; model-specific\n\t * endpoint preparation happens after auth has been resolved.\n\t */\n\tresolve(input: { ctx: AuthContext; credential?: ApiKeyCredential }): Promise<AuthResult | undefined>;\n}\n\n/**\n * OAuth auth. The `refresh`/`toAuth` split lets `Models` own the locked\n * refresh pattern: `refresh` produces a credential, `toAuth` derives request\n * auth from whatever credential ends up stored.\n */\nexport interface OAuthAuth {\n\t/** Display name, e.g. \"Anthropic (Claude Pro/Max)\". */\n\tname: string;\n\n\t/** Selector label for the subscription login option, e.g. \"Sign in with SuperGrok or X Premium\". */\n\tloginLabel?: string;\n\n\tlogin(interaction: AuthInteraction): Promise<OAuthCredential | ExternalClaudeCodeCredential>;\n\n\t/**\n\t * Exchange the refresh token. Network call; throws on failure\n\t * (invalid_grant etc.). `Models` runs this under the store lock.\n\t */\n\trefresh(credential: OAuthCredential, signal?: AbortSignal): Promise<OAuthCredential>;\n\n\t/**\n\t * Side-effect-free derivation of request auth from a valid credential.\n\t * Covers per-credential baseUrl (GitHub Copilot). Async so lazy wrappers\n\t * can load the implementation on first use.\n\t */\n\ttoAuth(credential: OAuthCredential): Promise<ModelAuth>;\n}\n\n/**\n * Provider auth. At least one of `apiKey`/`oauth` must be present: even\n * ambient-credential providers and keyless local servers provide `apiKey`\n * auth whose `resolve()` reports whether the provider is configured.\n */\nexport interface ProviderAuth {\n\tapiKey?: ApiKeyAuth;\n\toauth?: OAuthAuth;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ProviderEnv, ProviderHeaders } from \"../types.ts\";\n\n/**\n * Request auth for a single model request. If a value cannot be expressed as\n * `apiKey`, `headers`, or `baseUrl`, it is provider config, not auth.\n */\nexport interface ModelAuth {\n\tapiKey?: string;\n\theaders?: ProviderHeaders;\n\tbaseUrl?: string;\n}\n\n/**\n * Stored api-key credential. `env` holds provider-scoped environment/config\n * values such as Cloudflare account/gateway ids.\n */\nexport interface ApiKeyCredential {\n\ttype: \"api_key\";\n\tkey?: string;\n\tenv?: ProviderEnv;\n}\n\n/** OAuth token data returned by extension compatibility flows. */\nexport interface OAuthCredentials {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\t[key: string]: unknown;\n}\n\n/** Stored canonical OAuth credential. */\nexport interface OAuthCredential extends OAuthCredentials {\n\ttype: \"oauth\";\n}\n\n/** One type-tagged credential per provider — the shape of today's auth.json. */\nexport type Credential = ApiKeyCredential | OAuthCredential;\n\n/** Non-secret credential metadata for account/status enumeration. */\nexport interface CredentialInfo {\n\tproviderId: string;\n\ttype: Credential[\"type\"];\n}\n\n/**\n * App-owned credential storage, keyed by `Provider.id`, one credential per\n * provider. `modify` is the only write path, so every mutation is a\n * serialized read-modify-write; `Models.getAuth()` runs OAuth refresh inside\n * `modify` so concurrent requests cannot double-refresh a rotated token. The\n * app persists a credential after login via\n * `modify(provider.id, async () => credential)`. Login/logout orchestration\n * is app-owned.\n *\n * Error semantics: `read` resolves `undefined` for missing entries. Methods\n * reject only on storage failure; `Models` wraps such rejections in\n * `ModelsError` with code \"auth\". Best-effort stores that serve an in-memory\n * view and record persistence errors internally (like coding-agent's\n * AuthStorage) are valid implementations.\n */\nexport interface CredentialStore {\n\t/**\n\t * Read the stored credential, possibly expired. Display/status use;\n\t * resolved request auth comes from `Models.getAuth()`.\n\t */\n\tread(providerId: string): Promise<Credential | undefined>;\n\n\t/**\n\t * List stored credential metadata without resolving or exposing secrets.\n\t * Implementations must not execute configured API-key commands while listing.\n\t */\n\tlist(): Promise<readonly CredentialInfo[]>;\n\n\t/**\n\t * Serialized write — the only write path. `fn` sees the current credential\n\t * because correct writes (refresh, login-during-refresh) depend on it;\n\t * return the new credential, or undefined to leave the entry unchanged.\n\t * Mutual exclusion per provider id, cross-process too where the backing\n\t * store supports it (e.g. a file lock). Resolves with the post-write\n\t * credential. Rejections from `fn` propagate.\n\t */\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t): Promise<Credential | undefined>;\n\n\t/** Remove a credential (logout). Implementations serialize this against `modify`. */\n\tdelete(providerId: string): Promise<void>;\n}\n\n/** Environment access for auth resolution. Injectable for tests and browsers. */\nexport interface AuthContext {\n\tenv(name: string): Promise<string | undefined>;\n\t/** Check whether a file exists. Supports a leading `~`. Always false in browsers. */\n\tfileExists(path: string): Promise<boolean>;\n}\n\n/** Result of resolving auth for a model. */\nexport interface AuthResult {\n\tauth: ModelAuth;\n\t/** Provider-scoped environment/config values resolved from credentials and ambient context. */\n\tenv?: ProviderEnv;\n\t/** Human-readable label for status UI: \"ANTHROPIC_API_KEY\", \"OAuth\", \"~/.aws/credentials\". */\n\tsource?: string;\n}\n\nexport interface AuthCheck {\n\tsource?: string;\n\ttype: \"api_key\" | \"oauth\";\n}\n\nexport type AuthType = \"api_key\" | \"oauth\";\n\n/**\n * Prompt shown to the user during login. `signal` lets the flow cancel a\n * pending prompt when an out-of-band event resolves the step, e.g. a\n * `manual_code` prompt raced against a callback server, aborted when the\n * callback wins.\n */\nexport type AuthPrompt = { signal?: AbortSignal } & (\n\t| { type: \"text\"; message: string; placeholder?: string }\n\t| { type: \"secret\"; message: string; placeholder?: string }\n\t| { type: \"select\"; message: string; options: readonly { id: string; label: string; description?: string }[] }\n\t| { type: \"manual_code\"; message: string; placeholder?: string }\n);\n\nexport interface AuthInfoLink {\n\turl: string;\n\tlabel?: string;\n}\n\nexport type AuthEvent =\n\t| { type: \"info\"; message: string; links?: readonly AuthInfoLink[] }\n\t| { type: \"auth_url\"; url: string; instructions?: string }\n\t| {\n\t\t\ttype: \"device_code\";\n\t\t\tuserCode: string;\n\t\t\tverificationUri: string;\n\t\t\tintervalSeconds?: number;\n\t\t\texpiresInSeconds?: number;\n\t }\n\t| { type: \"progress\"; message: string };\n\n/**\n * Login interaction callbacks serving both api-key and OAuth flows.\n *\n * `prompt()` returns the entered/selected string (`select` returns the option\n * id). Rejects on cancel/abort. `signal` aborts the whole login flow;\n * per-prompt cancellation uses `AuthPrompt.signal`.\n */\nexport interface AuthInteraction {\n\tsignal?: AbortSignal;\n\n\tprompt(prompt: AuthPrompt): Promise<string>;\n\tnotify(event: AuthEvent): void;\n}\n\n/**\n * Api-key auth: stored key/provider env plus ambient sources (env vars, AWS\n * profiles, ADC files). Ambient-only providers omit `login`.\n */\nexport interface ApiKeyAuth {\n\t/** Display name, e.g. \"Anthropic API key\". */\n\tname: string;\n\n\t/** Interactive setup (prompt for key/provider env). Absent = ambient-only. */\n\tlogin?(interaction: AuthInteraction): Promise<ApiKeyCredential>;\n\n\t/**\n\t * Optional side-effect-free availability check. Use this when `resolve()` may\n\t * execute commands or perform other request-time work. Missing means Models\n\t * checks availability by resolving auth.\n\t */\n\tcheck?(input: { ctx: AuthContext; credential?: ApiKeyCredential }): Promise<AuthCheck | undefined>;\n\n\t/**\n\t * Resolve auth from the stored credential and/or ambient sources, merging\n\t * per field (`credential.key ?? env(\"...\")`, `credential.env?.NAME ?? env(\"...\")`).\n\t * undefined = not configured. Resolution is provider-scoped; model-specific\n\t * endpoint preparation happens after auth has been resolved.\n\t */\n\tresolve(input: { ctx: AuthContext; credential?: ApiKeyCredential }): Promise<AuthResult | undefined>;\n}\n\n/**\n * OAuth auth. The `refresh`/`toAuth` split lets `Models` own the locked\n * refresh pattern: `refresh` produces a credential, `toAuth` derives request\n * auth from whatever credential ends up stored.\n */\nexport interface OAuthAuth {\n\t/** Display name, e.g. \"Anthropic (Claude Pro/Max)\". */\n\tname: string;\n\n\t/** Selector label for the subscription login option, e.g. \"Sign in with SuperGrok or X Premium\". */\n\tloginLabel?: string;\n\n\tlogin(interaction: AuthInteraction): Promise<OAuthCredential>;\n\n\t/**\n\t * Exchange the refresh token. Network call; throws on failure\n\t * (invalid_grant etc.). `Models` runs this under the store lock.\n\t */\n\trefresh(credential: OAuthCredential, signal?: AbortSignal): Promise<OAuthCredential>;\n\n\t/**\n\t * Side-effect-free derivation of request auth from a valid credential.\n\t * Covers per-credential baseUrl (GitHub Copilot). Async so lazy wrappers\n\t * can load the implementation on first use.\n\t */\n\ttoAuth(credential: OAuthCredential): Promise<ModelAuth>;\n}\n\n/**\n * Provider auth. At least one of `apiKey`/`oauth` must be present: even\n * ambient-credential providers and keyless local servers provide `apiKey`\n * auth whose `resolve()` reports whether the provider is configured.\n */\nexport interface ProviderAuth {\n\tapiKey?: ApiKeyAuth;\n\toauth?: OAuthAuth;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ProviderEnv, ProviderHeaders } from \"../types.ts\";\n\n/**\n * Request auth for a single model request. If a value cannot be expressed as\n * `apiKey`, `headers`, or `baseUrl`, it is provider config, not auth.\n */\nexport interface ModelAuth {\n\tapiKey?: string;\n\theaders?: ProviderHeaders;\n\tbaseUrl?: string;\n\texternalClaudeCode?: ExternalClaudeCodeCredential;\n}\n\n/**\n * Stored api-key credential. `env` holds provider-scoped environment/config\n * values such as Cloudflare account/gateway ids.\n */\nexport interface ApiKeyCredential {\n\ttype: \"api_key\";\n\tkey?: string;\n\tenv?: ProviderEnv;\n}\n\n/** OAuth token data returned by extension compatibility flows. */\nexport interface OAuthCredentials {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\t[key: string]: unknown;\n}\n\n/** Stored canonical OAuth credential. */\nexport interface OAuthCredential extends OAuthCredentials {\n\ttype: \"oauth\";\n}\n\n/** One type-tagged credential per provider — the shape of today's auth.json. */\nexport interface ExternalClaudeCodeCredential {\n\ttype: \"external_claude_code\";\n\tversion: 1;\n\tmanager: \"claude-code\";\n\tcommand: string;\n\tpython: string;\n\tconfigDir?: string;\n\taccountFingerprint?: string;\n\troutes?: string[];\n}\n\nexport type Credential = ApiKeyCredential | OAuthCredential | ExternalClaudeCodeCredential;\n\n/** Non-secret credential metadata for account/status enumeration. */\nexport interface CredentialInfo {\n\tproviderId: string;\n\ttype: Credential[\"type\"];\n}\n\n/**\n * App-owned credential storage, keyed by `Provider.id`, one credential per\n * provider. `modify` is the only write path, so every mutation is a\n * serialized read-modify-write; `Models.getAuth()` runs OAuth refresh inside\n * `modify` so concurrent requests cannot double-refresh a rotated token. The\n * app persists a credential after login via\n * `modify(provider.id, async () => credential)`. Login/logout orchestration\n * is app-owned.\n *\n * Error semantics: `read` resolves `undefined` for missing entries. Methods\n * reject only on storage failure; `Models` wraps such rejections in\n * `ModelsError` with code \"auth\". Best-effort stores that serve an in-memory\n * view and record persistence errors internally (like coding-agent's\n * AuthStorage) are valid implementations.\n */\nexport interface CredentialStore {\n\t/**\n\t * Read the stored credential, possibly expired. Display/status use;\n\t * resolved request auth comes from `Models.getAuth()`.\n\t */\n\tread(providerId: string): Promise<Credential | undefined>;\n\n\t/**\n\t * List stored credential metadata without resolving or exposing secrets.\n\t * Implementations must not execute configured API-key commands while listing.\n\t */\n\tlist(): Promise<readonly CredentialInfo[]>;\n\n\t/**\n\t * Serialized write — the only write path. `fn` sees the current credential\n\t * because correct writes (refresh, login-during-refresh) depend on it;\n\t * return the new credential, or undefined to leave the entry unchanged.\n\t * Mutual exclusion per provider id, cross-process too where the backing\n\t * store supports it (e.g. a file lock). Resolves with the post-write\n\t * credential. Rejections from `fn` propagate.\n\t */\n\tmodify(\n\t\tproviderId: string,\n\t\tfn: (current: Credential | undefined) => Promise<Credential | undefined>,\n\t): Promise<Credential | undefined>;\n\n\t/** Remove a credential (logout). Implementations serialize this against `modify`. */\n\tdelete(providerId: string): Promise<void>;\n}\n\n/** Environment access for auth resolution. Injectable for tests and browsers. */\nexport interface AuthContext {\n\tenv(name: string): Promise<string | undefined>;\n\t/** Check whether a file exists. Supports a leading `~`. Always false in browsers. */\n\tfileExists(path: string): Promise<boolean>;\n}\n\n/** Result of resolving auth for a model. */\nexport interface AuthResult {\n\tauth: ModelAuth;\n\t/** Provider-scoped environment/config values resolved from credentials and ambient context. */\n\tenv?: ProviderEnv;\n\t/** Human-readable label for status UI: \"ANTHROPIC_API_KEY\", \"OAuth\", \"~/.aws/credentials\". */\n\tsource?: string;\n}\n\nexport interface AuthCheck {\n\tsource?: string;\n\ttype: \"api_key\" | \"oauth\";\n}\n\nexport type AuthType = \"api_key\" | \"oauth\";\n\n/**\n * Prompt shown to the user during login. `signal` lets the flow cancel a\n * pending prompt when an out-of-band event resolves the step, e.g. a\n * `manual_code` prompt raced against a callback server, aborted when the\n * callback wins.\n */\nexport type AuthPrompt = { signal?: AbortSignal } & (\n\t| { type: \"text\"; message: string; placeholder?: string }\n\t| { type: \"secret\"; message: string; placeholder?: string }\n\t| { type: \"select\"; message: string; options: readonly { id: string; label: string; description?: string }[] }\n\t| { type: \"manual_code\"; message: string; placeholder?: string }\n);\n\nexport interface AuthInfoLink {\n\turl: string;\n\tlabel?: string;\n}\n\nexport type AuthEvent =\n\t| { type: \"info\"; message: string; links?: readonly AuthInfoLink[] }\n\t| { type: \"auth_url\"; url: string; instructions?: string }\n\t| {\n\t\t\ttype: \"device_code\";\n\t\t\tuserCode: string;\n\t\t\tverificationUri: string;\n\t\t\tintervalSeconds?: number;\n\t\t\texpiresInSeconds?: number;\n\t }\n\t| { type: \"progress\"; message: string };\n\n/**\n * Login interaction callbacks serving both api-key and OAuth flows.\n *\n * `prompt()` returns the entered/selected string (`select` returns the option\n * id). Rejects on cancel/abort. `signal` aborts the whole login flow;\n * per-prompt cancellation uses `AuthPrompt.signal`.\n */\nexport interface AuthInteraction {\n\tsignal?: AbortSignal;\n\n\tprompt(prompt: AuthPrompt): Promise<string>;\n\tnotify(event: AuthEvent): void;\n\t/** Interactive terminal handoff for external account login, never used by headless callers. */\n\thandoff?(command: string, args: readonly string[], env: Record<string, string>): Promise<void>;\n}\n\n/**\n * Api-key auth: stored key/provider env plus ambient sources (env vars, AWS\n * profiles, ADC files). Ambient-only providers omit `login`.\n */\nexport interface ApiKeyAuth {\n\t/** Display name, e.g. \"Anthropic API key\". */\n\tname: string;\n\n\t/** Interactive setup (prompt for key/provider env). Absent = ambient-only. */\n\tlogin?(interaction: AuthInteraction): Promise<ApiKeyCredential>;\n\n\t/**\n\t * Optional side-effect-free availability check. Use this when `resolve()` may\n\t * execute commands or perform other request-time work. Missing means Models\n\t * checks availability by resolving auth.\n\t */\n\tcheck?(input: { ctx: AuthContext; credential?: ApiKeyCredential }): Promise<AuthCheck | undefined>;\n\n\t/**\n\t * Resolve auth from the stored credential and/or ambient sources, merging\n\t * per field (`credential.key ?? env(\"...\")`, `credential.env?.NAME ?? env(\"...\")`).\n\t * undefined = not configured. Resolution is provider-scoped; model-specific\n\t * endpoint preparation happens after auth has been resolved.\n\t */\n\tresolve(input: { ctx: AuthContext; credential?: ApiKeyCredential }): Promise<AuthResult | undefined>;\n}\n\n/**\n * OAuth auth. The `refresh`/`toAuth` split lets `Models` own the locked\n * refresh pattern: `refresh` produces a credential, `toAuth` derives request\n * auth from whatever credential ends up stored.\n */\nexport interface OAuthAuth {\n\t/** Display name, e.g. \"Anthropic (Claude Pro/Max)\". */\n\tname: string;\n\n\t/** Selector label for the subscription login option, e.g. \"Sign in with SuperGrok or X Premium\". */\n\tloginLabel?: string;\n\n\tlogin(interaction: AuthInteraction): Promise<OAuthCredential | ExternalClaudeCodeCredential>;\n\n\t/**\n\t * Exchange the refresh token. Network call; throws on failure\n\t * (invalid_grant etc.). `Models` runs this under the store lock.\n\t */\n\trefresh(credential: OAuthCredential, signal?: AbortSignal): Promise<OAuthCredential>;\n\n\t/**\n\t * Side-effect-free derivation of request auth from a valid credential.\n\t * Covers per-credential baseUrl (GitHub Copilot). Async so lazy wrappers\n\t * can load the implementation on first use.\n\t */\n\ttoAuth(credential: OAuthCredential): Promise<ModelAuth>;\n}\n\n/**\n * Provider auth. At least one of `apiKey`/`oauth` must be present: even\n * ambient-credential providers and keyless local servers provide `apiKey`\n * auth whose `resolve()` reports whether the provider is configured.\n */\nexport interface ProviderAuth {\n\tapiKey?: ApiKeyAuth;\n\toauth?: OAuthAuth;\n}\n"]}
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport type { AuthPrompt, OAuthCredential, Provider } from \"./index.ts\";\nimport { builtinProviders } from \"./providers/all.ts\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = builtinProviders().filter(\n\t(provider): provider is Provider & { auth: { oauth: NonNullable<Provider[\"auth\"][\"oauth\"]> } } =>\n\t\tprovider.auth.oauth !== undefined,\n);\n\nfunction prompt(rl: ReturnType<typeof createInterface>, question: string): Promise<string> {\n\treturn new Promise((resolve) => rl.question(question, resolve));\n}\n\nfunction loadAuth(): Record<string, OAuthCredential> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\")) as Record<string, OAuthCredential>;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, OAuthCredential>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function answerPrompt(rl: ReturnType<typeof createInterface>, authPrompt: AuthPrompt): Promise<string> {\n\tif (authPrompt.type === \"select\") {\n\t\tconsole.log(`\\n${authPrompt.message}`);\n\t\tfor (let index = 0; index < authPrompt.options.length; index++) {\n\t\t\tconsole.log(` ${index + 1}. ${authPrompt.options[index].label}`);\n\t\t}\n\t\tconst choice = Number.parseInt(await prompt(rl, `Enter number (1-${authPrompt.options.length}): `), 10) - 1;\n\t\tconst selected = authPrompt.options[choice];\n\t\tif (!selected) throw new Error(\"Invalid selection\");\n\t\treturn selected.id;\n\t}\n\treturn prompt(rl, `${authPrompt.message}${authPrompt.placeholder ? ` (${authPrompt.placeholder})` : \"\"}: `);\n}\n\nasync function login(providerId: string): Promise<void> {\n\tconst provider = PROVIDERS.find((entry) => entry.id === providerId);\n\tif (!provider) throw new Error(`Unknown provider: ${providerId}`);\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\ttry {\n\t\tconst credential = await provider.auth.oauth.login({\n\t\t\tprompt: (authPrompt) => answerPrompt(rl, authPrompt),\n\t\t\tnotify: (event) => {\n\t\t\t\tswitch (event.type) {\n\t\t\t\t\tcase \"auth_url\":\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${event.url}`);\n\t\t\t\t\t\tif (event.instructions) console.log(event.instructions);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"device_code\":\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${event.verificationUri}`);\n\t\t\t\t\t\tconsole.log(`Enter code: ${event.userCode}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"info\":\n\t\t\t\t\tcase \"progress\":\n\t\t\t\t\t\tconsole.log(event.message);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tconst auth = loadAuth();\n\t\tauth[providerId] = credential;\n\t\tsaveAuth(auth);\n\t\tconsole.log(`\\nCredentials saved to ${AUTH_FILE}`);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nasync function main(): Promise<void> {\n\tconst args = process.argv.slice(2);\n\tconst command = args[0];\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconst providerList = PROVIDERS.map((provider) => ` ${provider.id.padEnd(20)} ${provider.name}`).join(\"\\n\");\n\t\tconsole.log(\n\t\t\t`Usage: npx @ashx-j/lunr-ai <command> [provider]\\n\\nCommands:\\n login [provider] Login to an OAuth provider\\n list List available providers\\n\\nProviders:\\n${providerList}`,\n\t\t);\n\t\treturn;\n\t}\n\tif (command === \"list\") {\n\t\tfor (const provider of PROVIDERS) console.log(`${provider.id.padEnd(20)} ${provider.name}`);\n\t\treturn;\n\t}\n\tif (command === \"login\") {\n\t\tlet providerId = args[1];\n\t\tif (!providerId) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\ttry {\n\t\t\t\tfor (let index = 0; index < PROVIDERS.length; index++) {\n\t\t\t\t\tconsole.log(` ${index + 1}. ${PROVIDERS[index].name}`);\n\t\t\t\t}\n\t\t\t\tconst index = Number.parseInt(await prompt(rl, `Enter number (1-${PROVIDERS.length}): `), 10) - 1;\n\t\t\t\tproviderId = PROVIDERS[index]?.id;\n\t\t\t} finally {\n\t\t\t\trl.close();\n\t\t\t}\n\t\t}\n\t\tif (!providerId || !PROVIDERS.some((provider) => provider.id === providerId)) {\n\t\t\tthrow new Error(`Unknown provider: ${providerId ?? \"\"}`);\n\t\t}\n\t\tawait login(providerId);\n\t\treturn;\n\t}\n\tthrow new Error(`Unknown command: ${command}`);\n}\n\nmain().catch((error: unknown) => {\n\tconsole.error(\"Error:\", error instanceof Error ? error.message : String(error));\n\tprocess.exit(1);\n});\n"]}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"","sourcesContent":["#!/usr/bin/env node\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport type { AuthPrompt, OAuthCredential, Provider } from \"./index.ts\";\nimport { builtinProviders } from \"./providers/all.ts\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = builtinProviders().filter(\n\t(provider): provider is Provider & { auth: { oauth: NonNullable<Provider[\"auth\"][\"oauth\"]> } } =>\n\t\tprovider.auth.oauth !== undefined,\n);\n\nfunction prompt(rl: ReturnType<typeof createInterface>, question: string): Promise<string> {\n\treturn new Promise((resolve) => rl.question(question, resolve));\n}\n\nfunction loadAuth(): Record<string, OAuthCredential> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\")) as Record<string, OAuthCredential>;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, OAuthCredential>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function answerPrompt(rl: ReturnType<typeof createInterface>, authPrompt: AuthPrompt): Promise<string> {\n\tif (authPrompt.type === \"select\") {\n\t\tconsole.log(`\\n${authPrompt.message}`);\n\t\tfor (let index = 0; index < authPrompt.options.length; index++) {\n\t\t\tconsole.log(` ${index + 1}. ${authPrompt.options[index].label}`);\n\t\t}\n\t\tconst choice = Number.parseInt(await prompt(rl, `Enter number (1-${authPrompt.options.length}): `), 10) - 1;\n\t\tconst selected = authPrompt.options[choice];\n\t\tif (!selected) throw new Error(\"Invalid selection\");\n\t\treturn selected.id;\n\t}\n\treturn prompt(rl, `${authPrompt.message}${authPrompt.placeholder ? ` (${authPrompt.placeholder})` : \"\"}: `);\n}\n\nasync function login(providerId: string): Promise<void> {\n\tconst provider = PROVIDERS.find((entry) => entry.id === providerId);\n\tif (!provider) throw new Error(`Unknown provider: ${providerId}`);\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\ttry {\n\t\tconst credential = await provider.auth.oauth.login({\n\t\t\tprompt: (authPrompt) => answerPrompt(rl, authPrompt),\n\t\t\tnotify: (event) => {\n\t\t\t\tswitch (event.type) {\n\t\t\t\t\tcase \"auth_url\":\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${event.url}`);\n\t\t\t\t\t\tif (event.instructions) console.log(event.instructions);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"device_code\":\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${event.verificationUri}`);\n\t\t\t\t\t\tconsole.log(`Enter code: ${event.userCode}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"info\":\n\t\t\t\t\tcase \"progress\":\n\t\t\t\t\t\tconsole.log(event.message);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tif (credential.type !== \"oauth\") throw new Error(\"Use lunr /login anthropic for Claude Code setup\");\n\t\tconst auth = loadAuth();\n\t\tauth[providerId] = credential;\n\t\tsaveAuth(auth);\n\t\tconsole.log(`\\nCredentials saved to ${AUTH_FILE}`);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nasync function main(): Promise<void> {\n\tconst args = process.argv.slice(2);\n\tconst command = args[0];\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconst providerList = PROVIDERS.map((provider) => ` ${provider.id.padEnd(20)} ${provider.name}`).join(\"\\n\");\n\t\tconsole.log(\n\t\t\t`Usage: npx @ashx-j/lunr-ai <command> [provider]\\n\\nCommands:\\n login [provider] Login to an OAuth provider\\n list List available providers\\n\\nProviders:\\n${providerList}`,\n\t\t);\n\t\treturn;\n\t}\n\tif (command === \"list\") {\n\t\tfor (const provider of PROVIDERS) console.log(`${provider.id.padEnd(20)} ${provider.name}`);\n\t\treturn;\n\t}\n\tif (command === \"login\") {\n\t\tlet providerId = args[1];\n\t\tif (!providerId) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\ttry {\n\t\t\t\tfor (let index = 0; index < PROVIDERS.length; index++) {\n\t\t\t\t\tconsole.log(` ${index + 1}. ${PROVIDERS[index].name}`);\n\t\t\t\t}\n\t\t\t\tconst index = Number.parseInt(await prompt(rl, `Enter number (1-${PROVIDERS.length}): `), 10) - 1;\n\t\t\t\tproviderId = PROVIDERS[index]?.id;\n\t\t\t} finally {\n\t\t\t\trl.close();\n\t\t\t}\n\t\t}\n\t\tif (!providerId || !PROVIDERS.some((provider) => provider.id === providerId)) {\n\t\t\tthrow new Error(`Unknown provider: ${providerId ?? \"\"}`);\n\t\t}\n\t\tawait login(providerId);\n\t\treturn;\n\t}\n\tthrow new Error(`Unknown command: ${command}`);\n}\n\nmain().catch((error: unknown) => {\n\tconsole.error(\"Error:\", error instanceof Error ? error.message : String(error));\n\tprocess.exit(1);\n});\n"]}
package/dist/cli.js CHANGED
@@ -60,6 +60,8 @@ async function login(providerId) {
60
60
  }
61
61
  },
62
62
  });
63
+ if (credential.type !== "oauth")
64
+ throw new Error("Use lunr /login anthropic for Claude Code setup");
63
65
  const auth = loadAuth();
64
66
  auth[providerId] = credential;
65
67
  saveAuth(auth);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport type { AuthPrompt, OAuthCredential, Provider } from \"./index.ts\";\nimport { builtinProviders } from \"./providers/all.ts\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = builtinProviders().filter(\n\t(provider): provider is Provider & { auth: { oauth: NonNullable<Provider[\"auth\"][\"oauth\"]> } } =>\n\t\tprovider.auth.oauth !== undefined,\n);\n\nfunction prompt(rl: ReturnType<typeof createInterface>, question: string): Promise<string> {\n\treturn new Promise((resolve) => rl.question(question, resolve));\n}\n\nfunction loadAuth(): Record<string, OAuthCredential> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\")) as Record<string, OAuthCredential>;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, OAuthCredential>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function answerPrompt(rl: ReturnType<typeof createInterface>, authPrompt: AuthPrompt): Promise<string> {\n\tif (authPrompt.type === \"select\") {\n\t\tconsole.log(`\\n${authPrompt.message}`);\n\t\tfor (let index = 0; index < authPrompt.options.length; index++) {\n\t\t\tconsole.log(` ${index + 1}. ${authPrompt.options[index].label}`);\n\t\t}\n\t\tconst choice = Number.parseInt(await prompt(rl, `Enter number (1-${authPrompt.options.length}): `), 10) - 1;\n\t\tconst selected = authPrompt.options[choice];\n\t\tif (!selected) throw new Error(\"Invalid selection\");\n\t\treturn selected.id;\n\t}\n\treturn prompt(rl, `${authPrompt.message}${authPrompt.placeholder ? ` (${authPrompt.placeholder})` : \"\"}: `);\n}\n\nasync function login(providerId: string): Promise<void> {\n\tconst provider = PROVIDERS.find((entry) => entry.id === providerId);\n\tif (!provider) throw new Error(`Unknown provider: ${providerId}`);\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\ttry {\n\t\tconst credential = await provider.auth.oauth.login({\n\t\t\tprompt: (authPrompt) => answerPrompt(rl, authPrompt),\n\t\t\tnotify: (event) => {\n\t\t\t\tswitch (event.type) {\n\t\t\t\t\tcase \"auth_url\":\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${event.url}`);\n\t\t\t\t\t\tif (event.instructions) console.log(event.instructions);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"device_code\":\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${event.verificationUri}`);\n\t\t\t\t\t\tconsole.log(`Enter code: ${event.userCode}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"info\":\n\t\t\t\t\tcase \"progress\":\n\t\t\t\t\t\tconsole.log(event.message);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tconst auth = loadAuth();\n\t\tauth[providerId] = credential;\n\t\tsaveAuth(auth);\n\t\tconsole.log(`\\nCredentials saved to ${AUTH_FILE}`);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nasync function main(): Promise<void> {\n\tconst args = process.argv.slice(2);\n\tconst command = args[0];\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconst providerList = PROVIDERS.map((provider) => ` ${provider.id.padEnd(20)} ${provider.name}`).join(\"\\n\");\n\t\tconsole.log(\n\t\t\t`Usage: npx @ashx-j/lunr-ai <command> [provider]\\n\\nCommands:\\n login [provider] Login to an OAuth provider\\n list List available providers\\n\\nProviders:\\n${providerList}`,\n\t\t);\n\t\treturn;\n\t}\n\tif (command === \"list\") {\n\t\tfor (const provider of PROVIDERS) console.log(`${provider.id.padEnd(20)} ${provider.name}`);\n\t\treturn;\n\t}\n\tif (command === \"login\") {\n\t\tlet providerId = args[1];\n\t\tif (!providerId) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\ttry {\n\t\t\t\tfor (let index = 0; index < PROVIDERS.length; index++) {\n\t\t\t\t\tconsole.log(` ${index + 1}. ${PROVIDERS[index].name}`);\n\t\t\t\t}\n\t\t\t\tconst index = Number.parseInt(await prompt(rl, `Enter number (1-${PROVIDERS.length}): `), 10) - 1;\n\t\t\t\tproviderId = PROVIDERS[index]?.id;\n\t\t\t} finally {\n\t\t\t\trl.close();\n\t\t\t}\n\t\t}\n\t\tif (!providerId || !PROVIDERS.some((provider) => provider.id === providerId)) {\n\t\t\tthrow new Error(`Unknown provider: ${providerId ?? \"\"}`);\n\t\t}\n\t\tawait login(providerId);\n\t\treturn;\n\t}\n\tthrow new Error(`Unknown command: ${command}`);\n}\n\nmain().catch((error: unknown) => {\n\tconsole.error(\"Error:\", error instanceof Error ? error.message : String(error));\n\tprocess.exit(1);\n});\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport type { AuthPrompt, OAuthCredential, Provider } from \"./index.ts\";\nimport { builtinProviders } from \"./providers/all.ts\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = builtinProviders().filter(\n\t(provider): provider is Provider & { auth: { oauth: NonNullable<Provider[\"auth\"][\"oauth\"]> } } =>\n\t\tprovider.auth.oauth !== undefined,\n);\n\nfunction prompt(rl: ReturnType<typeof createInterface>, question: string): Promise<string> {\n\treturn new Promise((resolve) => rl.question(question, resolve));\n}\n\nfunction loadAuth(): Record<string, OAuthCredential> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\")) as Record<string, OAuthCredential>;\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, OAuthCredential>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function answerPrompt(rl: ReturnType<typeof createInterface>, authPrompt: AuthPrompt): Promise<string> {\n\tif (authPrompt.type === \"select\") {\n\t\tconsole.log(`\\n${authPrompt.message}`);\n\t\tfor (let index = 0; index < authPrompt.options.length; index++) {\n\t\t\tconsole.log(` ${index + 1}. ${authPrompt.options[index].label}`);\n\t\t}\n\t\tconst choice = Number.parseInt(await prompt(rl, `Enter number (1-${authPrompt.options.length}): `), 10) - 1;\n\t\tconst selected = authPrompt.options[choice];\n\t\tif (!selected) throw new Error(\"Invalid selection\");\n\t\treturn selected.id;\n\t}\n\treturn prompt(rl, `${authPrompt.message}${authPrompt.placeholder ? ` (${authPrompt.placeholder})` : \"\"}: `);\n}\n\nasync function login(providerId: string): Promise<void> {\n\tconst provider = PROVIDERS.find((entry) => entry.id === providerId);\n\tif (!provider) throw new Error(`Unknown provider: ${providerId}`);\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\ttry {\n\t\tconst credential = await provider.auth.oauth.login({\n\t\t\tprompt: (authPrompt) => answerPrompt(rl, authPrompt),\n\t\t\tnotify: (event) => {\n\t\t\t\tswitch (event.type) {\n\t\t\t\t\tcase \"auth_url\":\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${event.url}`);\n\t\t\t\t\t\tif (event.instructions) console.log(event.instructions);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"device_code\":\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${event.verificationUri}`);\n\t\t\t\t\t\tconsole.log(`Enter code: ${event.userCode}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"info\":\n\t\t\t\t\tcase \"progress\":\n\t\t\t\t\t\tconsole.log(event.message);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\t\t});\n\t\tif (credential.type !== \"oauth\") throw new Error(\"Use lunr /login anthropic for Claude Code setup\");\n\t\tconst auth = loadAuth();\n\t\tauth[providerId] = credential;\n\t\tsaveAuth(auth);\n\t\tconsole.log(`\\nCredentials saved to ${AUTH_FILE}`);\n\t} finally {\n\t\trl.close();\n\t}\n}\n\nasync function main(): Promise<void> {\n\tconst args = process.argv.slice(2);\n\tconst command = args[0];\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconst providerList = PROVIDERS.map((provider) => ` ${provider.id.padEnd(20)} ${provider.name}`).join(\"\\n\");\n\t\tconsole.log(\n\t\t\t`Usage: npx @ashx-j/lunr-ai <command> [provider]\\n\\nCommands:\\n login [provider] Login to an OAuth provider\\n list List available providers\\n\\nProviders:\\n${providerList}`,\n\t\t);\n\t\treturn;\n\t}\n\tif (command === \"list\") {\n\t\tfor (const provider of PROVIDERS) console.log(`${provider.id.padEnd(20)} ${provider.name}`);\n\t\treturn;\n\t}\n\tif (command === \"login\") {\n\t\tlet providerId = args[1];\n\t\tif (!providerId) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\ttry {\n\t\t\t\tfor (let index = 0; index < PROVIDERS.length; index++) {\n\t\t\t\t\tconsole.log(` ${index + 1}. ${PROVIDERS[index].name}`);\n\t\t\t\t}\n\t\t\t\tconst index = Number.parseInt(await prompt(rl, `Enter number (1-${PROVIDERS.length}): `), 10) - 1;\n\t\t\t\tproviderId = PROVIDERS[index]?.id;\n\t\t\t} finally {\n\t\t\t\trl.close();\n\t\t\t}\n\t\t}\n\t\tif (!providerId || !PROVIDERS.some((provider) => provider.id === providerId)) {\n\t\t\tthrow new Error(`Unknown provider: ${providerId ?? \"\"}`);\n\t\t}\n\t\tawait login(providerId);\n\t\treturn;\n\t}\n\tthrow new Error(`Unknown command: ${command}`);\n}\n\nmain().catch((error: unknown) => {\n\tconsole.error(\"Error:\", error instanceof Error ? error.message : String(error));\n\tprocess.exit(1);\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"env-api-keys.d.ts","sourceRoot":"","sources":["../src/env-api-keys.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA2F7D;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AAC9F,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AASvF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAC7F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC","sourcesContent":["// NEVER convert to top-level imports - breaks browser/Vite builds\nlet _existsSync: typeof import(\"node:fs\").existsSync | null = null;\nlet _homedir: typeof import(\"node:os\").homedir | null = null;\nlet _join: typeof import(\"node:path\").join | null = null;\n\ntype DynamicImport = (specifier: string) => Promise<unknown>;\n\nconst dynamicImport: DynamicImport = (specifier) => import(specifier);\nconst NODE_FS_SPECIFIER = \"node:\" + \"fs\";\nconst NODE_OS_SPECIFIER = \"node:\" + \"os\";\nconst NODE_PATH_SPECIFIER = \"node:\" + \"path\";\n\n// Eagerly load in Node.js/Bun environment only\nif (typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun)) {\n\tdynamicImport(NODE_FS_SPECIFIER).then((m) => {\n\t\t_existsSync = (m as typeof import(\"node:fs\")).existsSync;\n\t});\n\tdynamicImport(NODE_OS_SPECIFIER).then((m) => {\n\t\t_homedir = (m as typeof import(\"node:os\")).homedir;\n\t});\n\tdynamicImport(NODE_PATH_SPECIFIER).then((m) => {\n\t\t_join = (m as typeof import(\"node:path\")).join;\n\t});\n}\n\nimport type { KnownProvider, ProviderEnv } from \"./types.ts\";\nimport { getProviderEnvValue } from \"./utils/provider-env.ts\";\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(env?: ProviderEnv): boolean {\n\tconst explicitCredentialsPath = env?.GOOGLE_APPLICATION_CREDENTIALS;\n\tif (explicitCredentialsPath) {\n\t\treturn _existsSync ? _existsSync(explicitCredentialsPath) : false;\n\t}\n\n\tif (cachedVertexAdcCredentialsExists === null) {\n\t\t// If node modules haven't loaded yet (async import race at startup),\n\t\t// return false WITHOUT caching so the next call retries once they're ready.\n\t\t// Only cache false permanently in a browser environment where fs is never available.\n\t\tif (!_existsSync || !_homedir || !_join) {\n\t\t\tconst isNode = typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun);\n\t\t\tif (!isNode) {\n\t\t\t\t// Definitively in a browser — safe to cache false permanently\n\t\t\t\tcachedVertexAdcCredentialsExists = false;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)\n\t\tconst gacPath = getProviderEnvValue(\"GOOGLE_APPLICATION_CREDENTIALS\", env);\n\t\tif (gacPath) {\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(gacPath);\n\t\t} else {\n\t\t\t// Fall back to default ADC path (lazy evaluation)\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(\n\t\t\t\t_join(_homedir(), \".config\", \"gcloud\", \"application_default_credentials.json\"),\n\t\t\t);\n\t\t}\n\t}\n\treturn cachedVertexAdcCredentialsExists;\n}\n\nfunction getApiKeyEnvVars(provider: string): readonly string[] | undefined {\n\tif (provider === \"github-copilot\") {\n\t\treturn [\"COPILOT_GITHUB_TOKEN\"];\n\t}\n\n\t// ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY\n\tif (provider === \"anthropic\") {\n\t\treturn [\"ANTHROPIC_OAUTH_TOKEN\", \"ANTHROPIC_API_KEY\"];\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\t\"ant-ling\": \"ANT_LING_API_KEY\",\n\t\topenai: \"OPENAI_API_KEY\",\n\t\t\"azure-openai-responses\": \"AZURE_OPENAI_API_KEY\",\n\t\tnvidia: \"NVIDIA_API_KEY\",\n\t\tdeepseek: \"DEEPSEEK_API_KEY\",\n\t\tgoogle: \"GEMINI_API_KEY\",\n\t\t\"google-vertex\": \"GOOGLE_CLOUD_API_KEY\",\n\t\tgroq: \"GROQ_API_KEY\",\n\t\tcerebras: \"CEREBRAS_API_KEY\",\n\t\txai: \"XAI_API_KEY\",\n\t\tradius: \"RADIUS_API_KEY\",\n\t\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_API_KEY\",\n\t\t\"zai-coding-cn\": \"ZAI_CODING_CN_API_KEY\",\n\t\tmistral: \"MISTRAL_API_KEY\",\n\t\tminimax: \"MINIMAX_API_KEY\",\n\t\t\"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n\t\tmoonshotai: \"MOONSHOT_API_KEY\",\n\t\t\"moonshotai-cn\": \"MOONSHOT_API_KEY\",\n\t\thuggingface: \"HF_TOKEN\",\n\t\tfireworks: \"FIREWORKS_API_KEY\",\n\t\ttogether: \"TOGETHER_API_KEY\",\n\t\topencode: \"OPENCODE_API_KEY\",\n\t\t\"opencode-go\": \"OPENCODE_API_KEY\",\n\t\t\"kimi-coding\": \"KIMI_API_KEY\",\n\t\t\"cloudflare-workers-ai\": \"CLOUDFLARE_API_KEY\",\n\t\t\"cloudflare-ai-gateway\": \"CLOUDFLARE_API_KEY\",\n\t\txiaomi: \"XIAOMI_API_KEY\",\n\t\t\"xiaomi-token-plan-cn\": \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n\t\t\"xiaomi-token-plan-ams\": \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n\t\t\"xiaomi-token-plan-sgp\": \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n\t\t\"qwen-token-plan\": \"DASHSCOPE_TOKEN_PLAN_API_KEY\",\n\t\t\"qwen-token-plan-cn\": \"DASHSCOPE_TOKEN_PLAN_CN_API_KEY\",\n\t\t\"qwen-cloud\": \"DASHSCOPE_API_KEY\",\n\t\t\"qwen-cloud-cn\": \"DASHSCOPE_API_KEY\",\n\t};\n\n\tconst envVar = envMap[provider];\n\treturn envVar ? [envVar] : undefined;\n}\n\n/**\n * Find configured environment variables that can provide an API key for a provider.\n *\n * This only reports actual API key variables. It intentionally excludes ambient\n * credential sources such as AWS profiles, AWS IAM credentials, and Google\n * Application Default Credentials.\n */\nexport function findEnvKeys(provider: KnownProvider, env?: ProviderEnv): string[] | undefined;\nexport function findEnvKeys(provider: string, env?: ProviderEnv): string[] | undefined;\nexport function findEnvKeys(provider: string, env?: ProviderEnv): string[] | undefined {\n\tconst envVars = getApiKeyEnvVars(provider);\n\tif (!envVars) return undefined;\n\n\tconst found = envVars.filter((envVar) => !!getProviderEnvValue(envVar, env));\n\treturn found.length > 0 ? found : undefined;\n}\n\n/**\n * Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.\n *\n * Will not return API keys for providers that require OAuth tokens.\n */\nexport function getEnvApiKey(provider: KnownProvider, env?: ProviderEnv): string | undefined;\nexport function getEnvApiKey(provider: string, env?: ProviderEnv): string | undefined;\nexport function getEnvApiKey(provider: string, env?: ProviderEnv): string | undefined {\n\tconst envKeys = findEnvKeys(provider, env);\n\tif (envKeys?.[0]) {\n\t\treturn getProviderEnvValue(envKeys[0], env);\n\t}\n\n\t// Vertex AI supports either an explicit API key or Application Default Credentials.\n\t// Auth is configured via `gcloud auth application-default login`.\n\tif (provider === \"google-vertex\") {\n\t\tconst hasCredentials = hasVertexAdcCredentials(env);\n\t\tconst hasProject = !!(\n\t\t\tgetProviderEnvValue(\"GOOGLE_CLOUD_PROJECT\", env) || getProviderEnvValue(\"GCLOUD_PROJECT\", env)\n\t\t);\n\t\tconst hasLocation = !!getProviderEnvValue(\"GOOGLE_CLOUD_LOCATION\", env);\n\n\t\tif (hasCredentials && hasProject && hasLocation) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tif (provider === \"amazon-bedrock\") {\n\t\t// Amazon Bedrock supports multiple credential sources:\n\t\t// 1. AWS_PROFILE - named profile from ~/.aws/credentials\n\t\t// 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys\n\t\t// 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock bearer token\n\t\t// 4. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - ECS task roles\n\t\t// 5. AWS_CONTAINER_CREDENTIALS_FULL_URI - ECS task roles (full URI)\n\t\t// 6. AWS_WEB_IDENTITY_TOKEN_FILE - IRSA (IAM Roles for Service Accounts)\n\t\tif (\n\t\t\tgetProviderEnvValue(\"AWS_PROFILE\", env) ||\n\t\t\t(getProviderEnvValue(\"AWS_ACCESS_KEY_ID\", env) && getProviderEnvValue(\"AWS_SECRET_ACCESS_KEY\", env)) ||\n\t\t\tgetProviderEnvValue(\"AWS_BEARER_TOKEN_BEDROCK\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_FULL_URI\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_WEB_IDENTITY_TOKEN_FILE\", env)\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
1
+ {"version":3,"file":"env-api-keys.d.ts","sourceRoot":"","sources":["../src/env-api-keys.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AA0F7D;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AAC9F,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AASvF;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAC7F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC","sourcesContent":["// NEVER convert to top-level imports - breaks browser/Vite builds\nlet _existsSync: typeof import(\"node:fs\").existsSync | null = null;\nlet _homedir: typeof import(\"node:os\").homedir | null = null;\nlet _join: typeof import(\"node:path\").join | null = null;\n\ntype DynamicImport = (specifier: string) => Promise<unknown>;\n\nconst dynamicImport: DynamicImport = (specifier) => import(specifier);\nconst NODE_FS_SPECIFIER = \"node:\" + \"fs\";\nconst NODE_OS_SPECIFIER = \"node:\" + \"os\";\nconst NODE_PATH_SPECIFIER = \"node:\" + \"path\";\n\n// Eagerly load in Node.js/Bun environment only\nif (typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun)) {\n\tdynamicImport(NODE_FS_SPECIFIER).then((m) => {\n\t\t_existsSync = (m as typeof import(\"node:fs\")).existsSync;\n\t});\n\tdynamicImport(NODE_OS_SPECIFIER).then((m) => {\n\t\t_homedir = (m as typeof import(\"node:os\")).homedir;\n\t});\n\tdynamicImport(NODE_PATH_SPECIFIER).then((m) => {\n\t\t_join = (m as typeof import(\"node:path\")).join;\n\t});\n}\n\nimport type { KnownProvider, ProviderEnv } from \"./types.ts\";\nimport { getProviderEnvValue } from \"./utils/provider-env.ts\";\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(env?: ProviderEnv): boolean {\n\tconst explicitCredentialsPath = env?.GOOGLE_APPLICATION_CREDENTIALS;\n\tif (explicitCredentialsPath) {\n\t\treturn _existsSync ? _existsSync(explicitCredentialsPath) : false;\n\t}\n\n\tif (cachedVertexAdcCredentialsExists === null) {\n\t\t// If node modules haven't loaded yet (async import race at startup),\n\t\t// return false WITHOUT caching so the next call retries once they're ready.\n\t\t// Only cache false permanently in a browser environment where fs is never available.\n\t\tif (!_existsSync || !_homedir || !_join) {\n\t\t\tconst isNode = typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun);\n\t\t\tif (!isNode) {\n\t\t\t\t// Definitively in a browser — safe to cache false permanently\n\t\t\t\tcachedVertexAdcCredentialsExists = false;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)\n\t\tconst gacPath = getProviderEnvValue(\"GOOGLE_APPLICATION_CREDENTIALS\", env);\n\t\tif (gacPath) {\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(gacPath);\n\t\t} else {\n\t\t\t// Fall back to default ADC path (lazy evaluation)\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(\n\t\t\t\t_join(_homedir(), \".config\", \"gcloud\", \"application_default_credentials.json\"),\n\t\t\t);\n\t\t}\n\t}\n\treturn cachedVertexAdcCredentialsExists;\n}\n\nfunction getApiKeyEnvVars(provider: string): readonly string[] | undefined {\n\tif (provider === \"github-copilot\") {\n\t\treturn [\"COPILOT_GITHUB_TOKEN\"];\n\t}\n\n\tif (provider === \"anthropic\") {\n\t\treturn [\"ANTHROPIC_API_KEY\"];\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\t\"ant-ling\": \"ANT_LING_API_KEY\",\n\t\topenai: \"OPENAI_API_KEY\",\n\t\t\"azure-openai-responses\": \"AZURE_OPENAI_API_KEY\",\n\t\tnvidia: \"NVIDIA_API_KEY\",\n\t\tdeepseek: \"DEEPSEEK_API_KEY\",\n\t\tgoogle: \"GEMINI_API_KEY\",\n\t\t\"google-vertex\": \"GOOGLE_CLOUD_API_KEY\",\n\t\tgroq: \"GROQ_API_KEY\",\n\t\tcerebras: \"CEREBRAS_API_KEY\",\n\t\txai: \"XAI_API_KEY\",\n\t\tradius: \"RADIUS_API_KEY\",\n\t\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_API_KEY\",\n\t\t\"zai-coding-cn\": \"ZAI_CODING_CN_API_KEY\",\n\t\tmistral: \"MISTRAL_API_KEY\",\n\t\tminimax: \"MINIMAX_API_KEY\",\n\t\t\"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n\t\tmoonshotai: \"MOONSHOT_API_KEY\",\n\t\t\"moonshotai-cn\": \"MOONSHOT_API_KEY\",\n\t\thuggingface: \"HF_TOKEN\",\n\t\tfireworks: \"FIREWORKS_API_KEY\",\n\t\ttogether: \"TOGETHER_API_KEY\",\n\t\topencode: \"OPENCODE_API_KEY\",\n\t\t\"opencode-go\": \"OPENCODE_API_KEY\",\n\t\t\"kimi-coding\": \"KIMI_API_KEY\",\n\t\t\"cloudflare-workers-ai\": \"CLOUDFLARE_API_KEY\",\n\t\t\"cloudflare-ai-gateway\": \"CLOUDFLARE_API_KEY\",\n\t\txiaomi: \"XIAOMI_API_KEY\",\n\t\t\"xiaomi-token-plan-cn\": \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n\t\t\"xiaomi-token-plan-ams\": \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n\t\t\"xiaomi-token-plan-sgp\": \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n\t\t\"qwen-token-plan\": \"DASHSCOPE_TOKEN_PLAN_API_KEY\",\n\t\t\"qwen-token-plan-cn\": \"DASHSCOPE_TOKEN_PLAN_CN_API_KEY\",\n\t\t\"qwen-cloud\": \"DASHSCOPE_API_KEY\",\n\t\t\"qwen-cloud-cn\": \"DASHSCOPE_API_KEY\",\n\t};\n\n\tconst envVar = envMap[provider];\n\treturn envVar ? [envVar] : undefined;\n}\n\n/**\n * Find configured environment variables that can provide an API key for a provider.\n *\n * This only reports actual API key variables. It intentionally excludes ambient\n * credential sources such as AWS profiles, AWS IAM credentials, and Google\n * Application Default Credentials.\n */\nexport function findEnvKeys(provider: KnownProvider, env?: ProviderEnv): string[] | undefined;\nexport function findEnvKeys(provider: string, env?: ProviderEnv): string[] | undefined;\nexport function findEnvKeys(provider: string, env?: ProviderEnv): string[] | undefined {\n\tconst envVars = getApiKeyEnvVars(provider);\n\tif (!envVars) return undefined;\n\n\tconst found = envVars.filter((envVar) => !!getProviderEnvValue(envVar, env));\n\treturn found.length > 0 ? found : undefined;\n}\n\n/**\n * Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.\n *\n * Will not return API keys for providers that require OAuth tokens.\n */\nexport function getEnvApiKey(provider: KnownProvider, env?: ProviderEnv): string | undefined;\nexport function getEnvApiKey(provider: string, env?: ProviderEnv): string | undefined;\nexport function getEnvApiKey(provider: string, env?: ProviderEnv): string | undefined {\n\tconst envKeys = findEnvKeys(provider, env);\n\tif (envKeys?.[0]) {\n\t\treturn getProviderEnvValue(envKeys[0], env);\n\t}\n\n\t// Vertex AI supports either an explicit API key or Application Default Credentials.\n\t// Auth is configured via `gcloud auth application-default login`.\n\tif (provider === \"google-vertex\") {\n\t\tconst hasCredentials = hasVertexAdcCredentials(env);\n\t\tconst hasProject = !!(\n\t\t\tgetProviderEnvValue(\"GOOGLE_CLOUD_PROJECT\", env) || getProviderEnvValue(\"GCLOUD_PROJECT\", env)\n\t\t);\n\t\tconst hasLocation = !!getProviderEnvValue(\"GOOGLE_CLOUD_LOCATION\", env);\n\n\t\tif (hasCredentials && hasProject && hasLocation) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tif (provider === \"amazon-bedrock\") {\n\t\t// Amazon Bedrock supports multiple credential sources:\n\t\t// 1. AWS_PROFILE - named profile from ~/.aws/credentials\n\t\t// 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys\n\t\t// 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock bearer token\n\t\t// 4. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - ECS task roles\n\t\t// 5. AWS_CONTAINER_CREDENTIALS_FULL_URI - ECS task roles (full URI)\n\t\t// 6. AWS_WEB_IDENTITY_TOKEN_FILE - IRSA (IAM Roles for Service Accounts)\n\t\tif (\n\t\t\tgetProviderEnvValue(\"AWS_PROFILE\", env) ||\n\t\t\t(getProviderEnvValue(\"AWS_ACCESS_KEY_ID\", env) && getProviderEnvValue(\"AWS_SECRET_ACCESS_KEY\", env)) ||\n\t\t\tgetProviderEnvValue(\"AWS_BEARER_TOKEN_BEDROCK\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_FULL_URI\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_WEB_IDENTITY_TOKEN_FILE\", env)\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
@@ -61,9 +61,8 @@ function getApiKeyEnvVars(provider) {
61
61
  if (provider === "github-copilot") {
62
62
  return ["COPILOT_GITHUB_TOKEN"];
63
63
  }
64
- // ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY
65
64
  if (provider === "anthropic") {
66
- return ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"];
65
+ return ["ANTHROPIC_API_KEY"];
67
66
  }
68
67
  const envMap = {
69
68
  "ant-ling": "ANT_LING_API_KEY",
@@ -1 +1 @@
1
- {"version":3,"file":"env-api-keys.js","sourceRoot":"","sources":["../src/env-api-keys.ts"],"names":[],"mappings":"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","sourcesContent":["// NEVER convert to top-level imports - breaks browser/Vite builds\nlet _existsSync: typeof import(\"node:fs\").existsSync | null = null;\nlet _homedir: typeof import(\"node:os\").homedir | null = null;\nlet _join: typeof import(\"node:path\").join | null = null;\n\ntype DynamicImport = (specifier: string) => Promise<unknown>;\n\nconst dynamicImport: DynamicImport = (specifier) => import(specifier);\nconst NODE_FS_SPECIFIER = \"node:\" + \"fs\";\nconst NODE_OS_SPECIFIER = \"node:\" + \"os\";\nconst NODE_PATH_SPECIFIER = \"node:\" + \"path\";\n\n// Eagerly load in Node.js/Bun environment only\nif (typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun)) {\n\tdynamicImport(NODE_FS_SPECIFIER).then((m) => {\n\t\t_existsSync = (m as typeof import(\"node:fs\")).existsSync;\n\t});\n\tdynamicImport(NODE_OS_SPECIFIER).then((m) => {\n\t\t_homedir = (m as typeof import(\"node:os\")).homedir;\n\t});\n\tdynamicImport(NODE_PATH_SPECIFIER).then((m) => {\n\t\t_join = (m as typeof import(\"node:path\")).join;\n\t});\n}\n\nimport type { KnownProvider, ProviderEnv } from \"./types.ts\";\nimport { getProviderEnvValue } from \"./utils/provider-env.ts\";\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(env?: ProviderEnv): boolean {\n\tconst explicitCredentialsPath = env?.GOOGLE_APPLICATION_CREDENTIALS;\n\tif (explicitCredentialsPath) {\n\t\treturn _existsSync ? _existsSync(explicitCredentialsPath) : false;\n\t}\n\n\tif (cachedVertexAdcCredentialsExists === null) {\n\t\t// If node modules haven't loaded yet (async import race at startup),\n\t\t// return false WITHOUT caching so the next call retries once they're ready.\n\t\t// Only cache false permanently in a browser environment where fs is never available.\n\t\tif (!_existsSync || !_homedir || !_join) {\n\t\t\tconst isNode = typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun);\n\t\t\tif (!isNode) {\n\t\t\t\t// Definitively in a browser — safe to cache false permanently\n\t\t\t\tcachedVertexAdcCredentialsExists = false;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)\n\t\tconst gacPath = getProviderEnvValue(\"GOOGLE_APPLICATION_CREDENTIALS\", env);\n\t\tif (gacPath) {\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(gacPath);\n\t\t} else {\n\t\t\t// Fall back to default ADC path (lazy evaluation)\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(\n\t\t\t\t_join(_homedir(), \".config\", \"gcloud\", \"application_default_credentials.json\"),\n\t\t\t);\n\t\t}\n\t}\n\treturn cachedVertexAdcCredentialsExists;\n}\n\nfunction getApiKeyEnvVars(provider: string): readonly string[] | undefined {\n\tif (provider === \"github-copilot\") {\n\t\treturn [\"COPILOT_GITHUB_TOKEN\"];\n\t}\n\n\t// ANTHROPIC_OAUTH_TOKEN takes precedence over ANTHROPIC_API_KEY\n\tif (provider === \"anthropic\") {\n\t\treturn [\"ANTHROPIC_OAUTH_TOKEN\", \"ANTHROPIC_API_KEY\"];\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\t\"ant-ling\": \"ANT_LING_API_KEY\",\n\t\topenai: \"OPENAI_API_KEY\",\n\t\t\"azure-openai-responses\": \"AZURE_OPENAI_API_KEY\",\n\t\tnvidia: \"NVIDIA_API_KEY\",\n\t\tdeepseek: \"DEEPSEEK_API_KEY\",\n\t\tgoogle: \"GEMINI_API_KEY\",\n\t\t\"google-vertex\": \"GOOGLE_CLOUD_API_KEY\",\n\t\tgroq: \"GROQ_API_KEY\",\n\t\tcerebras: \"CEREBRAS_API_KEY\",\n\t\txai: \"XAI_API_KEY\",\n\t\tradius: \"RADIUS_API_KEY\",\n\t\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_API_KEY\",\n\t\t\"zai-coding-cn\": \"ZAI_CODING_CN_API_KEY\",\n\t\tmistral: \"MISTRAL_API_KEY\",\n\t\tminimax: \"MINIMAX_API_KEY\",\n\t\t\"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n\t\tmoonshotai: \"MOONSHOT_API_KEY\",\n\t\t\"moonshotai-cn\": \"MOONSHOT_API_KEY\",\n\t\thuggingface: \"HF_TOKEN\",\n\t\tfireworks: \"FIREWORKS_API_KEY\",\n\t\ttogether: \"TOGETHER_API_KEY\",\n\t\topencode: \"OPENCODE_API_KEY\",\n\t\t\"opencode-go\": \"OPENCODE_API_KEY\",\n\t\t\"kimi-coding\": \"KIMI_API_KEY\",\n\t\t\"cloudflare-workers-ai\": \"CLOUDFLARE_API_KEY\",\n\t\t\"cloudflare-ai-gateway\": \"CLOUDFLARE_API_KEY\",\n\t\txiaomi: \"XIAOMI_API_KEY\",\n\t\t\"xiaomi-token-plan-cn\": \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n\t\t\"xiaomi-token-plan-ams\": \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n\t\t\"xiaomi-token-plan-sgp\": \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n\t\t\"qwen-token-plan\": \"DASHSCOPE_TOKEN_PLAN_API_KEY\",\n\t\t\"qwen-token-plan-cn\": \"DASHSCOPE_TOKEN_PLAN_CN_API_KEY\",\n\t\t\"qwen-cloud\": \"DASHSCOPE_API_KEY\",\n\t\t\"qwen-cloud-cn\": \"DASHSCOPE_API_KEY\",\n\t};\n\n\tconst envVar = envMap[provider];\n\treturn envVar ? [envVar] : undefined;\n}\n\n/**\n * Find configured environment variables that can provide an API key for a provider.\n *\n * This only reports actual API key variables. It intentionally excludes ambient\n * credential sources such as AWS profiles, AWS IAM credentials, and Google\n * Application Default Credentials.\n */\nexport function findEnvKeys(provider: KnownProvider, env?: ProviderEnv): string[] | undefined;\nexport function findEnvKeys(provider: string, env?: ProviderEnv): string[] | undefined;\nexport function findEnvKeys(provider: string, env?: ProviderEnv): string[] | undefined {\n\tconst envVars = getApiKeyEnvVars(provider);\n\tif (!envVars) return undefined;\n\n\tconst found = envVars.filter((envVar) => !!getProviderEnvValue(envVar, env));\n\treturn found.length > 0 ? found : undefined;\n}\n\n/**\n * Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.\n *\n * Will not return API keys for providers that require OAuth tokens.\n */\nexport function getEnvApiKey(provider: KnownProvider, env?: ProviderEnv): string | undefined;\nexport function getEnvApiKey(provider: string, env?: ProviderEnv): string | undefined;\nexport function getEnvApiKey(provider: string, env?: ProviderEnv): string | undefined {\n\tconst envKeys = findEnvKeys(provider, env);\n\tif (envKeys?.[0]) {\n\t\treturn getProviderEnvValue(envKeys[0], env);\n\t}\n\n\t// Vertex AI supports either an explicit API key or Application Default Credentials.\n\t// Auth is configured via `gcloud auth application-default login`.\n\tif (provider === \"google-vertex\") {\n\t\tconst hasCredentials = hasVertexAdcCredentials(env);\n\t\tconst hasProject = !!(\n\t\t\tgetProviderEnvValue(\"GOOGLE_CLOUD_PROJECT\", env) || getProviderEnvValue(\"GCLOUD_PROJECT\", env)\n\t\t);\n\t\tconst hasLocation = !!getProviderEnvValue(\"GOOGLE_CLOUD_LOCATION\", env);\n\n\t\tif (hasCredentials && hasProject && hasLocation) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tif (provider === \"amazon-bedrock\") {\n\t\t// Amazon Bedrock supports multiple credential sources:\n\t\t// 1. AWS_PROFILE - named profile from ~/.aws/credentials\n\t\t// 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys\n\t\t// 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock bearer token\n\t\t// 4. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - ECS task roles\n\t\t// 5. AWS_CONTAINER_CREDENTIALS_FULL_URI - ECS task roles (full URI)\n\t\t// 6. AWS_WEB_IDENTITY_TOKEN_FILE - IRSA (IAM Roles for Service Accounts)\n\t\tif (\n\t\t\tgetProviderEnvValue(\"AWS_PROFILE\", env) ||\n\t\t\t(getProviderEnvValue(\"AWS_ACCESS_KEY_ID\", env) && getProviderEnvValue(\"AWS_SECRET_ACCESS_KEY\", env)) ||\n\t\t\tgetProviderEnvValue(\"AWS_BEARER_TOKEN_BEDROCK\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_FULL_URI\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_WEB_IDENTITY_TOKEN_FILE\", env)\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
1
+ {"version":3,"file":"env-api-keys.js","sourceRoot":"","sources":["../src/env-api-keys.ts"],"names":[],"mappings":"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","sourcesContent":["// NEVER convert to top-level imports - breaks browser/Vite builds\nlet _existsSync: typeof import(\"node:fs\").existsSync | null = null;\nlet _homedir: typeof import(\"node:os\").homedir | null = null;\nlet _join: typeof import(\"node:path\").join | null = null;\n\ntype DynamicImport = (specifier: string) => Promise<unknown>;\n\nconst dynamicImport: DynamicImport = (specifier) => import(specifier);\nconst NODE_FS_SPECIFIER = \"node:\" + \"fs\";\nconst NODE_OS_SPECIFIER = \"node:\" + \"os\";\nconst NODE_PATH_SPECIFIER = \"node:\" + \"path\";\n\n// Eagerly load in Node.js/Bun environment only\nif (typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun)) {\n\tdynamicImport(NODE_FS_SPECIFIER).then((m) => {\n\t\t_existsSync = (m as typeof import(\"node:fs\")).existsSync;\n\t});\n\tdynamicImport(NODE_OS_SPECIFIER).then((m) => {\n\t\t_homedir = (m as typeof import(\"node:os\")).homedir;\n\t});\n\tdynamicImport(NODE_PATH_SPECIFIER).then((m) => {\n\t\t_join = (m as typeof import(\"node:path\")).join;\n\t});\n}\n\nimport type { KnownProvider, ProviderEnv } from \"./types.ts\";\nimport { getProviderEnvValue } from \"./utils/provider-env.ts\";\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(env?: ProviderEnv): boolean {\n\tconst explicitCredentialsPath = env?.GOOGLE_APPLICATION_CREDENTIALS;\n\tif (explicitCredentialsPath) {\n\t\treturn _existsSync ? _existsSync(explicitCredentialsPath) : false;\n\t}\n\n\tif (cachedVertexAdcCredentialsExists === null) {\n\t\t// If node modules haven't loaded yet (async import race at startup),\n\t\t// return false WITHOUT caching so the next call retries once they're ready.\n\t\t// Only cache false permanently in a browser environment where fs is never available.\n\t\tif (!_existsSync || !_homedir || !_join) {\n\t\t\tconst isNode = typeof process !== \"undefined\" && (process.versions?.node || process.versions?.bun);\n\t\t\tif (!isNode) {\n\t\t\t\t// Definitively in a browser — safe to cache false permanently\n\t\t\t\tcachedVertexAdcCredentialsExists = false;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t// Check GOOGLE_APPLICATION_CREDENTIALS env var first (standard way)\n\t\tconst gacPath = getProviderEnvValue(\"GOOGLE_APPLICATION_CREDENTIALS\", env);\n\t\tif (gacPath) {\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(gacPath);\n\t\t} else {\n\t\t\t// Fall back to default ADC path (lazy evaluation)\n\t\t\tcachedVertexAdcCredentialsExists = _existsSync(\n\t\t\t\t_join(_homedir(), \".config\", \"gcloud\", \"application_default_credentials.json\"),\n\t\t\t);\n\t\t}\n\t}\n\treturn cachedVertexAdcCredentialsExists;\n}\n\nfunction getApiKeyEnvVars(provider: string): readonly string[] | undefined {\n\tif (provider === \"github-copilot\") {\n\t\treturn [\"COPILOT_GITHUB_TOKEN\"];\n\t}\n\n\tif (provider === \"anthropic\") {\n\t\treturn [\"ANTHROPIC_API_KEY\"];\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\t\"ant-ling\": \"ANT_LING_API_KEY\",\n\t\topenai: \"OPENAI_API_KEY\",\n\t\t\"azure-openai-responses\": \"AZURE_OPENAI_API_KEY\",\n\t\tnvidia: \"NVIDIA_API_KEY\",\n\t\tdeepseek: \"DEEPSEEK_API_KEY\",\n\t\tgoogle: \"GEMINI_API_KEY\",\n\t\t\"google-vertex\": \"GOOGLE_CLOUD_API_KEY\",\n\t\tgroq: \"GROQ_API_KEY\",\n\t\tcerebras: \"CEREBRAS_API_KEY\",\n\t\txai: \"XAI_API_KEY\",\n\t\tradius: \"RADIUS_API_KEY\",\n\t\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_API_KEY\",\n\t\t\"zai-coding-cn\": \"ZAI_CODING_CN_API_KEY\",\n\t\tmistral: \"MISTRAL_API_KEY\",\n\t\tminimax: \"MINIMAX_API_KEY\",\n\t\t\"minimax-cn\": \"MINIMAX_CN_API_KEY\",\n\t\tmoonshotai: \"MOONSHOT_API_KEY\",\n\t\t\"moonshotai-cn\": \"MOONSHOT_API_KEY\",\n\t\thuggingface: \"HF_TOKEN\",\n\t\tfireworks: \"FIREWORKS_API_KEY\",\n\t\ttogether: \"TOGETHER_API_KEY\",\n\t\topencode: \"OPENCODE_API_KEY\",\n\t\t\"opencode-go\": \"OPENCODE_API_KEY\",\n\t\t\"kimi-coding\": \"KIMI_API_KEY\",\n\t\t\"cloudflare-workers-ai\": \"CLOUDFLARE_API_KEY\",\n\t\t\"cloudflare-ai-gateway\": \"CLOUDFLARE_API_KEY\",\n\t\txiaomi: \"XIAOMI_API_KEY\",\n\t\t\"xiaomi-token-plan-cn\": \"XIAOMI_TOKEN_PLAN_CN_API_KEY\",\n\t\t\"xiaomi-token-plan-ams\": \"XIAOMI_TOKEN_PLAN_AMS_API_KEY\",\n\t\t\"xiaomi-token-plan-sgp\": \"XIAOMI_TOKEN_PLAN_SGP_API_KEY\",\n\t\t\"qwen-token-plan\": \"DASHSCOPE_TOKEN_PLAN_API_KEY\",\n\t\t\"qwen-token-plan-cn\": \"DASHSCOPE_TOKEN_PLAN_CN_API_KEY\",\n\t\t\"qwen-cloud\": \"DASHSCOPE_API_KEY\",\n\t\t\"qwen-cloud-cn\": \"DASHSCOPE_API_KEY\",\n\t};\n\n\tconst envVar = envMap[provider];\n\treturn envVar ? [envVar] : undefined;\n}\n\n/**\n * Find configured environment variables that can provide an API key for a provider.\n *\n * This only reports actual API key variables. It intentionally excludes ambient\n * credential sources such as AWS profiles, AWS IAM credentials, and Google\n * Application Default Credentials.\n */\nexport function findEnvKeys(provider: KnownProvider, env?: ProviderEnv): string[] | undefined;\nexport function findEnvKeys(provider: string, env?: ProviderEnv): string[] | undefined;\nexport function findEnvKeys(provider: string, env?: ProviderEnv): string[] | undefined {\n\tconst envVars = getApiKeyEnvVars(provider);\n\tif (!envVars) return undefined;\n\n\tconst found = envVars.filter((envVar) => !!getProviderEnvValue(envVar, env));\n\treturn found.length > 0 ? found : undefined;\n}\n\n/**\n * Get API key for provider from known environment variables, e.g. OPENAI_API_KEY.\n *\n * Will not return API keys for providers that require OAuth tokens.\n */\nexport function getEnvApiKey(provider: KnownProvider, env?: ProviderEnv): string | undefined;\nexport function getEnvApiKey(provider: string, env?: ProviderEnv): string | undefined;\nexport function getEnvApiKey(provider: string, env?: ProviderEnv): string | undefined {\n\tconst envKeys = findEnvKeys(provider, env);\n\tif (envKeys?.[0]) {\n\t\treturn getProviderEnvValue(envKeys[0], env);\n\t}\n\n\t// Vertex AI supports either an explicit API key or Application Default Credentials.\n\t// Auth is configured via `gcloud auth application-default login`.\n\tif (provider === \"google-vertex\") {\n\t\tconst hasCredentials = hasVertexAdcCredentials(env);\n\t\tconst hasProject = !!(\n\t\t\tgetProviderEnvValue(\"GOOGLE_CLOUD_PROJECT\", env) || getProviderEnvValue(\"GCLOUD_PROJECT\", env)\n\t\t);\n\t\tconst hasLocation = !!getProviderEnvValue(\"GOOGLE_CLOUD_LOCATION\", env);\n\n\t\tif (hasCredentials && hasProject && hasLocation) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\tif (provider === \"amazon-bedrock\") {\n\t\t// Amazon Bedrock supports multiple credential sources:\n\t\t// 1. AWS_PROFILE - named profile from ~/.aws/credentials\n\t\t// 2. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - standard IAM keys\n\t\t// 3. AWS_BEARER_TOKEN_BEDROCK - Bedrock bearer token\n\t\t// 4. AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - ECS task roles\n\t\t// 5. AWS_CONTAINER_CREDENTIALS_FULL_URI - ECS task roles (full URI)\n\t\t// 6. AWS_WEB_IDENTITY_TOKEN_FILE - IRSA (IAM Roles for Service Accounts)\n\t\tif (\n\t\t\tgetProviderEnvValue(\"AWS_PROFILE\", env) ||\n\t\t\t(getProviderEnvValue(\"AWS_ACCESS_KEY_ID\", env) && getProviderEnvValue(\"AWS_SECRET_ACCESS_KEY\", env)) ||\n\t\t\tgetProviderEnvValue(\"AWS_BEARER_TOKEN_BEDROCK\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_CONTAINER_CREDENTIALS_FULL_URI\", env) ||\n\t\t\tgetProviderEnvValue(\"AWS_WEB_IDENTITY_TOKEN_FILE\", env)\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export type { OpenAICodexResponsesOptions, OpenAICodexWebSocketDebugStats } from
12
12
  export type { OpenAICompletionsOptions } from "./api/openai-completions.ts";
13
13
  export type { OpenAIResponsesOptions } from "./api/openai-responses.ts";
14
14
  export type { PiMessagesEvent, PiMessagesOptions, PiMessagesRewriteImpact } from "./api/pi-messages.ts";
15
+ export * from "./auth/anthropic-route.ts";
15
16
  export * from "./auth/context.ts";
16
17
  export * from "./auth/credential-store.ts";
17
18
  export * from "./auth/helpers.ts";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAO/B,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC/G,YAAY,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AACnF,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/F,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,cAAc,eAAe,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACnH,YAAY,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,YAAY,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACxG,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,YAAY,EACX,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,GACjB,MAAM,mCAAmC,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACN,sBAAsB,EACtB,iBAAiB,EACjB,8BAA8B,EAC9B,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,gCAAgC,EAChC,uBAAuB,GACvB,MAAM,iBAAiB,CAAC","sourcesContent":["export type { Static, TSchema } from \"typebox\";\nexport { Type } from \"typebox\";\n\n// Core only, side-effect free: no generated catalogs, no provider factories,\n// no api-registry, no OAuth implementations, no compat. Provider factories\n// live under \"@ashx-j/lunr-ai/providers/*\", API implementations under\n// \"@ashx-j/lunr-ai/api/*\", the old global API under\n// \"@ashx-j/lunr-ai/compat\".\nexport type { AnthropicEffort, AnthropicOptions, AnthropicThinkingDisplay } from \"./api/anthropic-messages.ts\";\nexport type { AzureOpenAIResponsesOptions } from \"./api/azure-openai-responses.ts\";\nexport type { BedrockOptions, BedrockThinkingDisplay } from \"./api/bedrock-converse-stream.ts\";\nexport type { GoogleOptions } from \"./api/google-generative-ai.ts\";\nexport type { GoogleThinkingLevel } from \"./api/google-shared.ts\";\nexport type { GoogleVertexOptions } from \"./api/google-vertex.ts\";\nexport * from \"./api/lazy.ts\";\nexport type { MistralOptions } from \"./api/mistral-conversations.ts\";\nexport type { OpenAICodexResponsesOptions, OpenAICodexWebSocketDebugStats } from \"./api/openai-codex-responses.ts\";\nexport type { OpenAICompletionsOptions } from \"./api/openai-completions.ts\";\nexport type { OpenAIResponsesOptions } from \"./api/openai-responses.ts\";\nexport type { PiMessagesEvent, PiMessagesOptions, PiMessagesRewriteImpact } from \"./api/pi-messages.ts\";\nexport * from \"./auth/context.ts\";\nexport * from \"./auth/credential-store.ts\";\nexport * from \"./auth/helpers.ts\";\nexport * from \"./auth/types.ts\";\nexport type {\n\tOAuthAuthInfo,\n\tOAuthDeviceCodeInfo,\n\tOAuthLoginCallbacks,\n\tOAuthPrompt,\n\tOAuthSelectOption,\n\tOAuthSelectPrompt,\n} from \"./compat/extension-oauth-types.ts\";\nexport * from \"./images-models.ts\";\nexport * from \"./models.ts\";\nexport * from \"./models-store.ts\";\nexport {\n\tcanonicalOpenAiModelId,\n\tisOpenAiChatModel,\n\tOPENAI_GPT6_THINKING_LEVEL_MAP,\n\tparseOpenAiGptVersion,\n\tsupportsOpenAiMax,\n\tsupportsOpenAiXhigh,\n\twithOpenAiEffortMetadata,\n} from \"./openai-effort.ts\";\nexport * from \"./providers/faux.ts\";\nexport * from \"./session-resources.ts\";\nexport * from \"./types.ts\";\nexport * from \"./utils/diagnostics.ts\";\nexport * from \"./utils/event-stream.ts\";\nexport * from \"./utils/json-parse.ts\";\nexport * from \"./utils/overflow.ts\";\nexport * from \"./utils/retry.ts\";\nexport * from \"./utils/typebox-helpers.ts\";\nexport * from \"./utils/validation.ts\";\nexport {\n\tparseXaiGrok4Minor,\n\tshouldUseXaiResponsesApi,\n\twithXaiEffortMetadata,\n\tXAI_GROK45_THINKING_LEVEL_MAP,\n\tXAI_GROK46_THINKING_LEVEL_MAP,\n\tXAI_RESPONSES_COMPAT,\n\tXAI_RESPONSES_EXCLUDED_MODEL_IDS,\n\tXAI_RESPONSES_MIN_MINOR,\n} from \"./xai-effort.ts\";\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAO/B,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC/G,YAAY,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AACnF,YAAY,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/F,YAAY,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAClE,cAAc,eAAe,CAAC;AAC9B,YAAY,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,2BAA2B,EAAE,8BAA8B,EAAE,MAAM,iCAAiC,CAAC;AACnH,YAAY,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,YAAY,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACxG,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,YAAY,EACX,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,GACjB,MAAM,mCAAmC,CAAC;AAC3C,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACN,sBAAsB,EACtB,iBAAiB,EACjB,8BAA8B,EAC9B,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,gCAAgC,EAChC,uBAAuB,GACvB,MAAM,iBAAiB,CAAC","sourcesContent":["export type { Static, TSchema } from \"typebox\";\nexport { Type } from \"typebox\";\n\n// Core only, side-effect free: no generated catalogs, no provider factories,\n// no api-registry, no OAuth implementations, no compat. Provider factories\n// live under \"@ashx-j/lunr-ai/providers/*\", API implementations under\n// \"@ashx-j/lunr-ai/api/*\", the old global API under\n// \"@ashx-j/lunr-ai/compat\".\nexport type { AnthropicEffort, AnthropicOptions, AnthropicThinkingDisplay } from \"./api/anthropic-messages.ts\";\nexport type { AzureOpenAIResponsesOptions } from \"./api/azure-openai-responses.ts\";\nexport type { BedrockOptions, BedrockThinkingDisplay } from \"./api/bedrock-converse-stream.ts\";\nexport type { GoogleOptions } from \"./api/google-generative-ai.ts\";\nexport type { GoogleThinkingLevel } from \"./api/google-shared.ts\";\nexport type { GoogleVertexOptions } from \"./api/google-vertex.ts\";\nexport * from \"./api/lazy.ts\";\nexport type { MistralOptions } from \"./api/mistral-conversations.ts\";\nexport type { OpenAICodexResponsesOptions, OpenAICodexWebSocketDebugStats } from \"./api/openai-codex-responses.ts\";\nexport type { OpenAICompletionsOptions } from \"./api/openai-completions.ts\";\nexport type { OpenAIResponsesOptions } from \"./api/openai-responses.ts\";\nexport type { PiMessagesEvent, PiMessagesOptions, PiMessagesRewriteImpact } from \"./api/pi-messages.ts\";\nexport * from \"./auth/anthropic-route.ts\";\nexport * from \"./auth/context.ts\";\nexport * from \"./auth/credential-store.ts\";\nexport * from \"./auth/helpers.ts\";\nexport * from \"./auth/types.ts\";\nexport type {\n\tOAuthAuthInfo,\n\tOAuthDeviceCodeInfo,\n\tOAuthLoginCallbacks,\n\tOAuthPrompt,\n\tOAuthSelectOption,\n\tOAuthSelectPrompt,\n} from \"./compat/extension-oauth-types.ts\";\nexport * from \"./images-models.ts\";\nexport * from \"./models.ts\";\nexport * from \"./models-store.ts\";\nexport {\n\tcanonicalOpenAiModelId,\n\tisOpenAiChatModel,\n\tOPENAI_GPT6_THINKING_LEVEL_MAP,\n\tparseOpenAiGptVersion,\n\tsupportsOpenAiMax,\n\tsupportsOpenAiXhigh,\n\twithOpenAiEffortMetadata,\n} from \"./openai-effort.ts\";\nexport * from \"./providers/faux.ts\";\nexport * from \"./session-resources.ts\";\nexport * from \"./types.ts\";\nexport * from \"./utils/diagnostics.ts\";\nexport * from \"./utils/event-stream.ts\";\nexport * from \"./utils/json-parse.ts\";\nexport * from \"./utils/overflow.ts\";\nexport * from \"./utils/retry.ts\";\nexport * from \"./utils/typebox-helpers.ts\";\nexport * from \"./utils/validation.ts\";\nexport {\n\tparseXaiGrok4Minor,\n\tshouldUseXaiResponsesApi,\n\twithXaiEffortMetadata,\n\tXAI_GROK45_THINKING_LEVEL_MAP,\n\tXAI_GROK46_THINKING_LEVEL_MAP,\n\tXAI_RESPONSES_COMPAT,\n\tXAI_RESPONSES_EXCLUDED_MODEL_IDS,\n\tXAI_RESPONSES_MIN_MINOR,\n} from \"./xai-effort.ts\";\n"]}
package/dist/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { Type } from "typebox";
2
2
  export * from "./api/lazy.js";
3
+ export * from "./auth/anthropic-route.js";
3
4
  export * from "./auth/context.js";
4
5
  export * from "./auth/credential-store.js";
5
6
  export * from "./auth/helpers.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAa/B,cAAc,eAAe,CAAC;AAM9B,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAShC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACN,sBAAsB,EACtB,iBAAiB,EACjB,8BAA8B,EAC9B,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,gCAAgC,EAChC,uBAAuB,GACvB,MAAM,iBAAiB,CAAC","sourcesContent":["export type { Static, TSchema } from \"typebox\";\nexport { Type } from \"typebox\";\n\n// Core only, side-effect free: no generated catalogs, no provider factories,\n// no api-registry, no OAuth implementations, no compat. Provider factories\n// live under \"@ashx-j/lunr-ai/providers/*\", API implementations under\n// \"@ashx-j/lunr-ai/api/*\", the old global API under\n// \"@ashx-j/lunr-ai/compat\".\nexport type { AnthropicEffort, AnthropicOptions, AnthropicThinkingDisplay } from \"./api/anthropic-messages.ts\";\nexport type { AzureOpenAIResponsesOptions } from \"./api/azure-openai-responses.ts\";\nexport type { BedrockOptions, BedrockThinkingDisplay } from \"./api/bedrock-converse-stream.ts\";\nexport type { GoogleOptions } from \"./api/google-generative-ai.ts\";\nexport type { GoogleThinkingLevel } from \"./api/google-shared.ts\";\nexport type { GoogleVertexOptions } from \"./api/google-vertex.ts\";\nexport * from \"./api/lazy.ts\";\nexport type { MistralOptions } from \"./api/mistral-conversations.ts\";\nexport type { OpenAICodexResponsesOptions, OpenAICodexWebSocketDebugStats } from \"./api/openai-codex-responses.ts\";\nexport type { OpenAICompletionsOptions } from \"./api/openai-completions.ts\";\nexport type { OpenAIResponsesOptions } from \"./api/openai-responses.ts\";\nexport type { PiMessagesEvent, PiMessagesOptions, PiMessagesRewriteImpact } from \"./api/pi-messages.ts\";\nexport * from \"./auth/context.ts\";\nexport * from \"./auth/credential-store.ts\";\nexport * from \"./auth/helpers.ts\";\nexport * from \"./auth/types.ts\";\nexport type {\n\tOAuthAuthInfo,\n\tOAuthDeviceCodeInfo,\n\tOAuthLoginCallbacks,\n\tOAuthPrompt,\n\tOAuthSelectOption,\n\tOAuthSelectPrompt,\n} from \"./compat/extension-oauth-types.ts\";\nexport * from \"./images-models.ts\";\nexport * from \"./models.ts\";\nexport * from \"./models-store.ts\";\nexport {\n\tcanonicalOpenAiModelId,\n\tisOpenAiChatModel,\n\tOPENAI_GPT6_THINKING_LEVEL_MAP,\n\tparseOpenAiGptVersion,\n\tsupportsOpenAiMax,\n\tsupportsOpenAiXhigh,\n\twithOpenAiEffortMetadata,\n} from \"./openai-effort.ts\";\nexport * from \"./providers/faux.ts\";\nexport * from \"./session-resources.ts\";\nexport * from \"./types.ts\";\nexport * from \"./utils/diagnostics.ts\";\nexport * from \"./utils/event-stream.ts\";\nexport * from \"./utils/json-parse.ts\";\nexport * from \"./utils/overflow.ts\";\nexport * from \"./utils/retry.ts\";\nexport * from \"./utils/typebox-helpers.ts\";\nexport * from \"./utils/validation.ts\";\nexport {\n\tparseXaiGrok4Minor,\n\tshouldUseXaiResponsesApi,\n\twithXaiEffortMetadata,\n\tXAI_GROK45_THINKING_LEVEL_MAP,\n\tXAI_GROK46_THINKING_LEVEL_MAP,\n\tXAI_RESPONSES_COMPAT,\n\tXAI_RESPONSES_EXCLUDED_MODEL_IDS,\n\tXAI_RESPONSES_MIN_MINOR,\n} from \"./xai-effort.ts\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAa/B,cAAc,eAAe,CAAC;AAM9B,cAAc,2BAA2B,CAAC;AAC1C,cAAc,mBAAmB,CAAC;AAClC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAShC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACN,sBAAsB,EACtB,iBAAiB,EACjB,8BAA8B,EAC9B,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,wBAAwB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,YAAY,CAAC;AAC3B,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,uBAAuB,CAAC;AACtC,OAAO,EACN,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,6BAA6B,EAC7B,6BAA6B,EAC7B,oBAAoB,EACpB,gCAAgC,EAChC,uBAAuB,GACvB,MAAM,iBAAiB,CAAC","sourcesContent":["export type { Static, TSchema } from \"typebox\";\nexport { Type } from \"typebox\";\n\n// Core only, side-effect free: no generated catalogs, no provider factories,\n// no api-registry, no OAuth implementations, no compat. Provider factories\n// live under \"@ashx-j/lunr-ai/providers/*\", API implementations under\n// \"@ashx-j/lunr-ai/api/*\", the old global API under\n// \"@ashx-j/lunr-ai/compat\".\nexport type { AnthropicEffort, AnthropicOptions, AnthropicThinkingDisplay } from \"./api/anthropic-messages.ts\";\nexport type { AzureOpenAIResponsesOptions } from \"./api/azure-openai-responses.ts\";\nexport type { BedrockOptions, BedrockThinkingDisplay } from \"./api/bedrock-converse-stream.ts\";\nexport type { GoogleOptions } from \"./api/google-generative-ai.ts\";\nexport type { GoogleThinkingLevel } from \"./api/google-shared.ts\";\nexport type { GoogleVertexOptions } from \"./api/google-vertex.ts\";\nexport * from \"./api/lazy.ts\";\nexport type { MistralOptions } from \"./api/mistral-conversations.ts\";\nexport type { OpenAICodexResponsesOptions, OpenAICodexWebSocketDebugStats } from \"./api/openai-codex-responses.ts\";\nexport type { OpenAICompletionsOptions } from \"./api/openai-completions.ts\";\nexport type { OpenAIResponsesOptions } from \"./api/openai-responses.ts\";\nexport type { PiMessagesEvent, PiMessagesOptions, PiMessagesRewriteImpact } from \"./api/pi-messages.ts\";\nexport * from \"./auth/anthropic-route.ts\";\nexport * from \"./auth/context.ts\";\nexport * from \"./auth/credential-store.ts\";\nexport * from \"./auth/helpers.ts\";\nexport * from \"./auth/types.ts\";\nexport type {\n\tOAuthAuthInfo,\n\tOAuthDeviceCodeInfo,\n\tOAuthLoginCallbacks,\n\tOAuthPrompt,\n\tOAuthSelectOption,\n\tOAuthSelectPrompt,\n} from \"./compat/extension-oauth-types.ts\";\nexport * from \"./images-models.ts\";\nexport * from \"./models.ts\";\nexport * from \"./models-store.ts\";\nexport {\n\tcanonicalOpenAiModelId,\n\tisOpenAiChatModel,\n\tOPENAI_GPT6_THINKING_LEVEL_MAP,\n\tparseOpenAiGptVersion,\n\tsupportsOpenAiMax,\n\tsupportsOpenAiXhigh,\n\twithOpenAiEffortMetadata,\n} from \"./openai-effort.ts\";\nexport * from \"./providers/faux.ts\";\nexport * from \"./session-resources.ts\";\nexport * from \"./types.ts\";\nexport * from \"./utils/diagnostics.ts\";\nexport * from \"./utils/event-stream.ts\";\nexport * from \"./utils/json-parse.ts\";\nexport * from \"./utils/overflow.ts\";\nexport * from \"./utils/retry.ts\";\nexport * from \"./utils/typebox-helpers.ts\";\nexport * from \"./utils/validation.ts\";\nexport {\n\tparseXaiGrok4Minor,\n\tshouldUseXaiResponsesApi,\n\twithXaiEffortMetadata,\n\tXAI_GROK45_THINKING_LEVEL_MAP,\n\tXAI_GROK46_THINKING_LEVEL_MAP,\n\tXAI_RESPONSES_COMPAT,\n\tXAI_RESPONSES_EXCLUDED_MODEL_IDS,\n\tXAI_RESPONSES_MIN_MINOR,\n} from \"./xai-effort.ts\";\n"]}