@caupulican/pi-ai 0.80.34 → 0.80.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/env-api-keys.d.ts.map +1 -1
- package/dist/env-api-keys.js +6 -0
- package/dist/env-api-keys.js.map +1 -1
- package/dist/models.generated.d.ts +615 -151
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +506 -104
- package/dist/models.generated.js.map +1 -1
- package/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/dist/providers/openai-responses-shared.js +33 -5
- package/dist/providers/openai-responses-shared.js.map +1 -1
- package/dist/providers/openai-responses.d.ts.map +1 -1
- package/dist/providers/openai-responses.js +35 -8
- package/dist/providers/openai-responses.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ Unified LLM API with automatic model discovery, provider configuration, token an
|
|
|
51
51
|
## Supported Providers
|
|
52
52
|
|
|
53
53
|
- **OpenAI**
|
|
54
|
+
- **Fugu** (Sakana API, OpenAI Responses-compatible)
|
|
54
55
|
- **Azure OpenAI (Responses)**
|
|
55
56
|
- **OpenAI Codex** (ChatGPT Plus/Pro subscription, requires OAuth, see below)
|
|
56
57
|
- **DeepSeek**
|
|
@@ -1099,6 +1100,7 @@ In Node.js environments, you can set environment variables to avoid passing API
|
|
|
1099
1100
|
| Provider | Environment Variable(s) |
|
|
1100
1101
|
|----------|------------------------|
|
|
1101
1102
|
| OpenAI | `OPENAI_API_KEY` |
|
|
1103
|
+
| Fugu | `SAKANA_API_KEY` or `FUGU_API_KEY` (`FUGU_BASE_URL` optional) |
|
|
1102
1104
|
| Azure OpenAI | `AZURE_OPENAI_API_KEY` + `AZURE_OPENAI_BASE_URL` (e.g. `https://{resource}.openai.azure.com`) or `AZURE_OPENAI_RESOURCE_NAME`. Supports `*.openai.azure.com` and `*.cognitiveservices.azure.com`; root endpoints auto-normalize to `/openai/v1`. Optional: `AZURE_OPENAI_API_VERSION` (default `v1`), `AZURE_OPENAI_DEPLOYMENT_NAME_MAP`. |
|
|
1103
1105
|
| Anthropic | `ANTHROPIC_API_KEY` or `ANTHROPIC_OAUTH_TOKEN` |
|
|
1104
1106
|
| DeepSeek | `DEEPSEEK_API_KEY` |
|
|
@@ -1284,6 +1286,8 @@ const response = await complete(model, {
|
|
|
1284
1286
|
|
|
1285
1287
|
**OpenAI Codex**: Requires a ChatGPT Plus or Pro subscription. Provides access to GPT-5.x Codex models with extended context windows and reasoning capabilities. The library automatically handles session-based prompt caching when `sessionId` is provided in stream options. You can set `transport` in stream options to `"sse"`, `"websocket"`, or `"auto"` for Codex Responses transport selection. When using WebSocket with a `sessionId`, connections are reused per session and expire after 5 minutes of inactivity.
|
|
1286
1288
|
|
|
1289
|
+
**Fugu**: Uses the Sakana API at `https://api.sakana.ai/v1` through the OpenAI Responses wire API. Set `SAKANA_API_KEY` (preferred, matching Sakana's Codex/Fugu setup) or `FUGU_API_KEY`. `FUGU_BASE_URL` can override the endpoint and is normalized to include `/v1`. Pi exposes `fugu` and `fugu-ultra`; both accept `high` and `xhigh` reasoning levels and may need higher client timeouts for complex tasks.
|
|
1290
|
+
|
|
1287
1291
|
**Azure OpenAI (Responses)**: Uses the Responses API only. Set `AZURE_OPENAI_API_KEY` and either `AZURE_OPENAI_BASE_URL` or `AZURE_OPENAI_RESOURCE_NAME`. `AZURE_OPENAI_BASE_URL` supports both `https://<resource>.openai.azure.com` and `https://<resource>.cognitiveservices.azure.com`; root endpoints are normalized to `.../openai/v1` automatically. Use `AZURE_OPENAI_API_VERSION` (defaults to `v1`) to override the API version if needed. Deployment names are treated as model IDs by default, override with `azureDeploymentName` or `AZURE_OPENAI_DEPLOYMENT_NAME_MAP` using comma-separated `model-id=deployment` pairs (for example `gpt-4o-mini=my-deployment,gpt-4o=prod`). Legacy deployment-based URLs are intentionally unsupported.
|
|
1288
1292
|
|
|
1289
1293
|
**GitHub Copilot**: If you get "The requested model is not supported" error, enable the model manually in VS Code: open Copilot Chat, click the model selector, select the model (warning icon), and click "Enable".
|
|
@@ -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,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"env-api-keys.d.ts","sourceRoot":"","sources":["../src/env-api-keys.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAqHhD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AAC3E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;AASpE;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAC1E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,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 } from \"./types.ts\";\n\nlet _procEnvCache: Map<string, string> | null = null;\n\n/**\n * Fallback for https://github.com/oven-sh/bun/issues/27802\n * Bun compiled binaries have an empty `process.env` inside sandbox\n * environments on Linux. We can recover the env from `/proc/self/environ`.\n */\nfunction getProcEnv(key: string): string | undefined {\n\tif (!process.versions?.bun) return undefined;\n\tif (typeof process === \"undefined\") return undefined;\n\n\t// If process.env already has entries, the bug is not triggered.\n\tif (Object.keys(process.env).length > 0) return undefined;\n\n\tif (_procEnvCache === null) {\n\t\t_procEnvCache = new Map();\n\t\ttry {\n\t\t\tconst { readFileSync } = require(\"node:fs\") as typeof import(\"node:fs\");\n\t\t\tconst data = readFileSync(\"/proc/self/environ\", \"utf-8\");\n\t\t\tfor (const entry of data.split(\"\\0\")) {\n\t\t\t\tconst idx = entry.indexOf(\"=\");\n\t\t\t\tif (idx > 0) {\n\t\t\t\t\t_procEnvCache.set(entry.slice(0, idx), entry.slice(idx + 1));\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// /proc/self/environ may not be readable.\n\t\t}\n\t}\n\n\treturn _procEnvCache.get(key);\n}\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(): boolean {\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 = process.env.GOOGLE_APPLICATION_CREDENTIALS || getProcEnv(\"GOOGLE_APPLICATION_CREDENTIALS\");\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\t// Sakana's Codex/Fugu integration documents SAKANA_API_KEY. The models page\n\t// examples also accept FUGU_API_KEY/FUGU_BASE_URL, so keep FUGU_API_KEY as\n\t// a compatibility fallback while preferring the provider-level key.\n\tif (provider === \"fugu\") {\n\t\treturn [\"SAKANA_API_KEY\", \"FUGU_API_KEY\"];\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\topenai: \"OPENAI_API_KEY\",\n\t\t\"azure-openai-responses\": \"AZURE_OPENAI_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\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_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};\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): string[] | undefined;\nexport function findEnvKeys(provider: string): string[] | undefined;\nexport function findEnvKeys(provider: string): string[] | undefined {\n\tconst envVars = getApiKeyEnvVars(provider);\n\tif (!envVars) return undefined;\n\n\tconst found = envVars.filter((envVar) => !!process.env[envVar] || !!getProcEnv(envVar));\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): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined {\n\tconst envKeys = findEnvKeys(provider);\n\tif (envKeys?.[0]) {\n\t\treturn process.env[envKeys[0]] || getProcEnv(envKeys[0]);\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();\n\t\tconst hasProject = !!(\n\t\t\tprocess.env.GOOGLE_CLOUD_PROJECT ||\n\t\t\tprocess.env.GCLOUD_PROJECT ||\n\t\t\tgetProcEnv(\"GOOGLE_CLOUD_PROJECT\") ||\n\t\t\tgetProcEnv(\"GCLOUD_PROJECT\")\n\t\t);\n\t\tconst hasLocation = !!(process.env.GOOGLE_CLOUD_LOCATION || getProcEnv(\"GOOGLE_CLOUD_LOCATION\"));\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\tprocess.env.AWS_PROFILE ||\n\t\t\t(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n\t\t\tprocess.env.AWS_BEARER_TOKEN_BEDROCK ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||\n\t\t\tprocess.env.AWS_WEB_IDENTITY_TOKEN_FILE ||\n\t\t\tgetProcEnv(\"AWS_PROFILE\") ||\n\t\t\t(getProcEnv(\"AWS_ACCESS_KEY_ID\") && getProcEnv(\"AWS_SECRET_ACCESS_KEY\")) ||\n\t\t\tgetProcEnv(\"AWS_BEARER_TOKEN_BEDROCK\") ||\n\t\t\tgetProcEnv(\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\") ||\n\t\t\tgetProcEnv(\"AWS_CONTAINER_CREDENTIALS_FULL_URI\") ||\n\t\t\tgetProcEnv(\"AWS_WEB_IDENTITY_TOKEN_FILE\")\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
|
package/dist/env-api-keys.js
CHANGED
|
@@ -92,6 +92,12 @@ function getApiKeyEnvVars(provider) {
|
|
|
92
92
|
if (provider === "anthropic") {
|
|
93
93
|
return ["ANTHROPIC_OAUTH_TOKEN", "ANTHROPIC_API_KEY"];
|
|
94
94
|
}
|
|
95
|
+
// Sakana's Codex/Fugu integration documents SAKANA_API_KEY. The models page
|
|
96
|
+
// examples also accept FUGU_API_KEY/FUGU_BASE_URL, so keep FUGU_API_KEY as
|
|
97
|
+
// a compatibility fallback while preferring the provider-level key.
|
|
98
|
+
if (provider === "fugu") {
|
|
99
|
+
return ["SAKANA_API_KEY", "FUGU_API_KEY"];
|
|
100
|
+
}
|
|
95
101
|
const envMap = {
|
|
96
102
|
openai: "OPENAI_API_KEY",
|
|
97
103
|
"azure-openai-responses": "AZURE_OPENAI_API_KEY",
|
package/dist/env-api-keys.js.map
CHANGED
|
@@ -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 } from \"./types.ts\";\n\nlet _procEnvCache: Map<string, string> | null = null;\n\n/**\n * Fallback for https://github.com/oven-sh/bun/issues/27802\n * Bun compiled binaries have an empty `process.env` inside sandbox\n * environments on Linux. We can recover the env from `/proc/self/environ`.\n */\nfunction getProcEnv(key: string): string | undefined {\n\tif (!process.versions?.bun) return undefined;\n\tif (typeof process === \"undefined\") return undefined;\n\n\t// If process.env already has entries, the bug is not triggered.\n\tif (Object.keys(process.env).length > 0) return undefined;\n\n\tif (_procEnvCache === null) {\n\t\t_procEnvCache = new Map();\n\t\ttry {\n\t\t\tconst { readFileSync } = require(\"node:fs\") as typeof import(\"node:fs\");\n\t\t\tconst data = readFileSync(\"/proc/self/environ\", \"utf-8\");\n\t\t\tfor (const entry of data.split(\"\\0\")) {\n\t\t\t\tconst idx = entry.indexOf(\"=\");\n\t\t\t\tif (idx > 0) {\n\t\t\t\t\t_procEnvCache.set(entry.slice(0, idx), entry.slice(idx + 1));\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// /proc/self/environ may not be readable.\n\t\t}\n\t}\n\n\treturn _procEnvCache.get(key);\n}\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(): boolean {\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 = process.env.GOOGLE_APPLICATION_CREDENTIALS || getProcEnv(\"GOOGLE_APPLICATION_CREDENTIALS\");\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\topenai: \"OPENAI_API_KEY\",\n\t\t\"azure-openai-responses\": \"AZURE_OPENAI_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\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_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};\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): string[] | undefined;\nexport function findEnvKeys(provider: string): string[] | undefined;\nexport function findEnvKeys(provider: string): string[] | undefined {\n\tconst envVars = getApiKeyEnvVars(provider);\n\tif (!envVars) return undefined;\n\n\tconst found = envVars.filter((envVar) => !!process.env[envVar] || !!getProcEnv(envVar));\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): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined {\n\tconst envKeys = findEnvKeys(provider);\n\tif (envKeys?.[0]) {\n\t\treturn process.env[envKeys[0]] || getProcEnv(envKeys[0]);\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();\n\t\tconst hasProject = !!(\n\t\t\tprocess.env.GOOGLE_CLOUD_PROJECT ||\n\t\t\tprocess.env.GCLOUD_PROJECT ||\n\t\t\tgetProcEnv(\"GOOGLE_CLOUD_PROJECT\") ||\n\t\t\tgetProcEnv(\"GCLOUD_PROJECT\")\n\t\t);\n\t\tconst hasLocation = !!(process.env.GOOGLE_CLOUD_LOCATION || getProcEnv(\"GOOGLE_CLOUD_LOCATION\"));\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\tprocess.env.AWS_PROFILE ||\n\t\t\t(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n\t\t\tprocess.env.AWS_BEARER_TOKEN_BEDROCK ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||\n\t\t\tprocess.env.AWS_WEB_IDENTITY_TOKEN_FILE ||\n\t\t\tgetProcEnv(\"AWS_PROFILE\") ||\n\t\t\t(getProcEnv(\"AWS_ACCESS_KEY_ID\") && getProcEnv(\"AWS_SECRET_ACCESS_KEY\")) ||\n\t\t\tgetProcEnv(\"AWS_BEARER_TOKEN_BEDROCK\") ||\n\t\t\tgetProcEnv(\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\") ||\n\t\t\tgetProcEnv(\"AWS_CONTAINER_CREDENTIALS_FULL_URI\") ||\n\t\t\tgetProcEnv(\"AWS_WEB_IDENTITY_TOKEN_FILE\")\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 } from \"./types.ts\";\n\nlet _procEnvCache: Map<string, string> | null = null;\n\n/**\n * Fallback for https://github.com/oven-sh/bun/issues/27802\n * Bun compiled binaries have an empty `process.env` inside sandbox\n * environments on Linux. We can recover the env from `/proc/self/environ`.\n */\nfunction getProcEnv(key: string): string | undefined {\n\tif (!process.versions?.bun) return undefined;\n\tif (typeof process === \"undefined\") return undefined;\n\n\t// If process.env already has entries, the bug is not triggered.\n\tif (Object.keys(process.env).length > 0) return undefined;\n\n\tif (_procEnvCache === null) {\n\t\t_procEnvCache = new Map();\n\t\ttry {\n\t\t\tconst { readFileSync } = require(\"node:fs\") as typeof import(\"node:fs\");\n\t\t\tconst data = readFileSync(\"/proc/self/environ\", \"utf-8\");\n\t\t\tfor (const entry of data.split(\"\\0\")) {\n\t\t\t\tconst idx = entry.indexOf(\"=\");\n\t\t\t\tif (idx > 0) {\n\t\t\t\t\t_procEnvCache.set(entry.slice(0, idx), entry.slice(idx + 1));\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// /proc/self/environ may not be readable.\n\t\t}\n\t}\n\n\treturn _procEnvCache.get(key);\n}\n\nlet cachedVertexAdcCredentialsExists: boolean | null = null;\n\nfunction hasVertexAdcCredentials(): boolean {\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 = process.env.GOOGLE_APPLICATION_CREDENTIALS || getProcEnv(\"GOOGLE_APPLICATION_CREDENTIALS\");\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\t// Sakana's Codex/Fugu integration documents SAKANA_API_KEY. The models page\n\t// examples also accept FUGU_API_KEY/FUGU_BASE_URL, so keep FUGU_API_KEY as\n\t// a compatibility fallback while preferring the provider-level key.\n\tif (provider === \"fugu\") {\n\t\treturn [\"SAKANA_API_KEY\", \"FUGU_API_KEY\"];\n\t}\n\n\tconst envMap: Record<string, string> = {\n\t\topenai: \"OPENAI_API_KEY\",\n\t\t\"azure-openai-responses\": \"AZURE_OPENAI_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\topenrouter: \"OPENROUTER_API_KEY\",\n\t\t\"vercel-ai-gateway\": \"AI_GATEWAY_API_KEY\",\n\t\tzai: \"ZAI_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};\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): string[] | undefined;\nexport function findEnvKeys(provider: string): string[] | undefined;\nexport function findEnvKeys(provider: string): string[] | undefined {\n\tconst envVars = getApiKeyEnvVars(provider);\n\tif (!envVars) return undefined;\n\n\tconst found = envVars.filter((envVar) => !!process.env[envVar] || !!getProcEnv(envVar));\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): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined;\nexport function getEnvApiKey(provider: string): string | undefined {\n\tconst envKeys = findEnvKeys(provider);\n\tif (envKeys?.[0]) {\n\t\treturn process.env[envKeys[0]] || getProcEnv(envKeys[0]);\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();\n\t\tconst hasProject = !!(\n\t\t\tprocess.env.GOOGLE_CLOUD_PROJECT ||\n\t\t\tprocess.env.GCLOUD_PROJECT ||\n\t\t\tgetProcEnv(\"GOOGLE_CLOUD_PROJECT\") ||\n\t\t\tgetProcEnv(\"GCLOUD_PROJECT\")\n\t\t);\n\t\tconst hasLocation = !!(process.env.GOOGLE_CLOUD_LOCATION || getProcEnv(\"GOOGLE_CLOUD_LOCATION\"));\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\tprocess.env.AWS_PROFILE ||\n\t\t\t(process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) ||\n\t\t\tprocess.env.AWS_BEARER_TOKEN_BEDROCK ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||\n\t\t\tprocess.env.AWS_CONTAINER_CREDENTIALS_FULL_URI ||\n\t\t\tprocess.env.AWS_WEB_IDENTITY_TOKEN_FILE ||\n\t\t\tgetProcEnv(\"AWS_PROFILE\") ||\n\t\t\t(getProcEnv(\"AWS_ACCESS_KEY_ID\") && getProcEnv(\"AWS_SECRET_ACCESS_KEY\")) ||\n\t\t\tgetProcEnv(\"AWS_BEARER_TOKEN_BEDROCK\") ||\n\t\t\tgetProcEnv(\"AWS_CONTAINER_CREDENTIALS_RELATIVE_URI\") ||\n\t\t\tgetProcEnv(\"AWS_CONTAINER_CREDENTIALS_FULL_URI\") ||\n\t\t\tgetProcEnv(\"AWS_WEB_IDENTITY_TOKEN_FILE\")\n\t\t) {\n\t\t\treturn \"<authenticated>\";\n\t\t}\n\t}\n\n\treturn undefined;\n}\n"]}
|