@mariozechner/pi-ai 0.39.1 → 0.40.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.
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 \"fs\";\nimport { createInterface } from \"readline\";\nimport { loginAnthropic } from \"./utils/oauth/anthropic.js\";\nimport { loginGitHubCopilot } from \"./utils/oauth/github-copilot.js\";\nimport { loginAntigravity } from \"./utils/oauth/google-antigravity.js\";\nimport { loginGeminiCli } from \"./utils/oauth/google-gemini-cli.js\";\nimport { getOAuthProviders } from \"./utils/oauth/index.js\";\nimport { loginOpenAICodex } from \"./utils/oauth/openai-codex.js\";\nimport type { OAuthCredentials, OAuthProvider } from \"./utils/oauth/types.js\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = getOAuthProviders();\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, { type: \"oauth\" } & OAuthCredentials> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\"));\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, { type: \"oauth\" } & OAuthCredentials>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function login(provider: OAuthProvider): Promise<void> {\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\n\tconst promptFn = (msg: string) => prompt(rl, `${msg} `);\n\n\ttry {\n\t\tlet credentials: OAuthCredentials;\n\n\t\tswitch (provider) {\n\t\t\tcase \"anthropic\":\n\t\t\t\tcredentials = await loginAnthropic(\n\t\t\t\t\t(url) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${url}\\n`);\n\t\t\t\t\t},\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\treturn await promptFn(\"Paste the authorization code:\");\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase \"github-copilot\":\n\t\t\t\tcredentials = await loginGitHubCopilot({\n\t\t\t\t\tonAuth: (url, instructions) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${url}`);\n\t\t\t\t\t\tif (instructions) console.log(instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\tonPrompt: async (p) => {\n\t\t\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t\t\t},\n\t\t\t\t\tonProgress: (msg) => console.log(msg),\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"google-gemini-cli\":\n\t\t\t\tcredentials = await loginGeminiCli(\n\t\t\t\t\t(info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\t(msg) => console.log(msg),\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase \"google-antigravity\":\n\t\t\t\tcredentials = await loginAntigravity(\n\t\t\t\t\t(info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\t(msg) => console.log(msg),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"openai-codex\":\n\t\t\t\tcredentials = await loginOpenAICodex({\n\t\t\t\t\tonAuth: (info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\tonPrompt: async (p) => {\n\t\t\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t\t\t},\n\t\t\t\t\tonProgress: (msg) => console.log(msg),\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t}\n\n\t\tconst auth = loadAuth();\n\t\tauth[provider] = { type: \"oauth\", ...credentials };\n\t\tsaveAuth(auth);\n\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\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconsole.log(`Usage: npx @mariozechner/pi-ai <command> [provider]\n\nCommands:\n login [provider] Login to an OAuth provider\n list List available providers\n\nProviders:\n anthropic Anthropic (Claude Pro/Max)\n github-copilot GitHub Copilot\n google-gemini-cli Google Gemini CLI\n google-antigravity Antigravity (Gemini 3, Claude, GPT-OSS)\n openai-codex OpenAI Codex (ChatGPT Plus/Pro)\n\nExamples:\n npx @mariozechner/pi-ai login # interactive provider selection\n npx @mariozechner/pi-ai login anthropic # login to specific provider\n npx @mariozechner/pi-ai list # list providers\n`);\n\t\treturn;\n\t}\n\n\tif (command === \"list\") {\n\t\tconsole.log(\"Available OAuth providers:\\n\");\n\t\tfor (const p of PROVIDERS) {\n\t\t\tconsole.log(` ${p.id.padEnd(20)} ${p.name}`);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (command === \"login\") {\n\t\tlet provider = args[1] as OAuthProvider | undefined;\n\n\t\tif (!provider) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\tconsole.log(\"Select a provider:\\n\");\n\t\t\tfor (let i = 0; i < PROVIDERS.length; i++) {\n\t\t\t\tconsole.log(` ${i + 1}. ${PROVIDERS[i].name}`);\n\t\t\t}\n\t\t\tconsole.log();\n\n\t\t\tconst choice = await prompt(rl, `Enter number (1-${PROVIDERS.length}): `);\n\t\t\trl.close();\n\n\t\t\tconst index = parseInt(choice, 10) - 1;\n\t\t\tif (index < 0 || index >= PROVIDERS.length) {\n\t\t\t\tconsole.error(\"Invalid selection\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\tprovider = PROVIDERS[index].id;\n\t\t}\n\n\t\tif (!PROVIDERS.some((p) => p.id === provider)) {\n\t\t\tconsole.error(`Unknown provider: ${provider}`);\n\t\t\tconsole.error(`Use 'npx @mariozechner/pi-ai list' to see available providers`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsole.log(`Logging in to ${provider}...`);\n\t\tawait login(provider);\n\t\treturn;\n\t}\n\n\tconsole.error(`Unknown command: ${command}`);\n\tconsole.error(`Use 'npx @mariozechner/pi-ai --help' for usage`);\n\tprocess.exit(1);\n}\n\nmain().catch((err) => {\n\tconsole.error(\"Error:\", err.message);\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 \"fs\";\nimport { createInterface } from \"readline\";\nimport { loginGitHubCopilot } from \"./utils/oauth/github-copilot.js\";\nimport { loginAntigravity } from \"./utils/oauth/google-antigravity.js\";\nimport { loginGeminiCli } from \"./utils/oauth/google-gemini-cli.js\";\nimport { getOAuthProviders } from \"./utils/oauth/index.js\";\nimport { loginOpenAICodex } from \"./utils/oauth/openai-codex.js\";\nimport type { OAuthCredentials, OAuthProvider } from \"./utils/oauth/types.js\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = getOAuthProviders();\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, { type: \"oauth\" } & OAuthCredentials> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\"));\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, { type: \"oauth\" } & OAuthCredentials>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function login(provider: OAuthProvider): Promise<void> {\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\n\tconst promptFn = (msg: string) => prompt(rl, `${msg} `);\n\n\ttry {\n\t\tlet credentials: OAuthCredentials;\n\n\t\tswitch (provider) {\n\t\t\tcase \"github-copilot\":\n\t\t\t\tcredentials = await loginGitHubCopilot({\n\t\t\t\t\tonAuth: (url, instructions) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${url}`);\n\t\t\t\t\t\tif (instructions) console.log(instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\tonPrompt: async (p) => {\n\t\t\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t\t\t},\n\t\t\t\t\tonProgress: (msg) => console.log(msg),\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"google-gemini-cli\":\n\t\t\t\tcredentials = await loginGeminiCli(\n\t\t\t\t\t(info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\t(msg) => console.log(msg),\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase \"google-antigravity\":\n\t\t\t\tcredentials = await loginAntigravity(\n\t\t\t\t\t(info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\t(msg) => console.log(msg),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"openai-codex\":\n\t\t\t\tcredentials = await loginOpenAICodex({\n\t\t\t\t\tonAuth: (info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\tonPrompt: async (p) => {\n\t\t\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t\t\t},\n\t\t\t\t\tonProgress: (msg) => console.log(msg),\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t}\n\n\t\tconst auth = loadAuth();\n\t\tauth[provider] = { type: \"oauth\", ...credentials };\n\t\tsaveAuth(auth);\n\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\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconsole.log(`Usage: npx @mariozechner/pi-ai <command> [provider]\n\nCommands:\n login [provider] Login to an OAuth provider\n list List available providers\n\nProviders:\n github-copilot GitHub Copilot\n google-gemini-cli Google Gemini CLI\n google-antigravity Antigravity (Gemini 3, Claude, GPT-OSS)\n openai-codex OpenAI Codex (ChatGPT Plus/Pro)\n\nExamples:\n npx @mariozechner/pi-ai login # interactive provider selection\n npx @mariozechner/pi-ai login anthropic # login to specific provider\n npx @mariozechner/pi-ai list # list providers\n`);\n\t\treturn;\n\t}\n\n\tif (command === \"list\") {\n\t\tconsole.log(\"Available OAuth providers:\\n\");\n\t\tfor (const p of PROVIDERS) {\n\t\t\tconsole.log(` ${p.id.padEnd(20)} ${p.name}`);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (command === \"login\") {\n\t\tlet provider = args[1] as OAuthProvider | undefined;\n\n\t\tif (!provider) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\tconsole.log(\"Select a provider:\\n\");\n\t\t\tfor (let i = 0; i < PROVIDERS.length; i++) {\n\t\t\t\tconsole.log(` ${i + 1}. ${PROVIDERS[i].name}`);\n\t\t\t}\n\t\t\tconsole.log();\n\n\t\t\tconst choice = await prompt(rl, `Enter number (1-${PROVIDERS.length}): `);\n\t\t\trl.close();\n\n\t\t\tconst index = parseInt(choice, 10) - 1;\n\t\t\tif (index < 0 || index >= PROVIDERS.length) {\n\t\t\t\tconsole.error(\"Invalid selection\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\tprovider = PROVIDERS[index].id;\n\t\t}\n\n\t\tif (!PROVIDERS.some((p) => p.id === provider)) {\n\t\t\tconsole.error(`Unknown provider: ${provider}`);\n\t\t\tconsole.error(`Use 'npx @mariozechner/pi-ai list' to see available providers`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsole.log(`Logging in to ${provider}...`);\n\t\tawait login(provider);\n\t\treturn;\n\t}\n\n\tconsole.error(`Unknown command: ${command}`);\n\tconsole.error(`Use 'npx @mariozechner/pi-ai --help' for usage`);\n\tprocess.exit(1);\n}\n\nmain().catch((err) => {\n\tconsole.error(\"Error:\", err.message);\n\tprocess.exit(1);\n});\n"]}
package/dist/cli.js CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { existsSync, readFileSync, writeFileSync } from "fs";
3
3
  import { createInterface } from "readline";
4
- import { loginAnthropic } from "./utils/oauth/anthropic.js";
5
4
  import { loginGitHubCopilot } from "./utils/oauth/github-copilot.js";
6
5
  import { loginAntigravity } from "./utils/oauth/google-antigravity.js";
7
6
  import { loginGeminiCli } from "./utils/oauth/google-gemini-cli.js";
@@ -31,13 +30,6 @@ async function login(provider) {
31
30
  try {
32
31
  let credentials;
33
32
  switch (provider) {
34
- case "anthropic":
35
- credentials = await loginAnthropic((url) => {
36
- console.log(`\nOpen this URL in your browser:\n${url}\n`);
37
- }, async () => {
38
- return await promptFn("Paste the authorization code:");
39
- });
40
- break;
41
33
  case "github-copilot":
42
34
  credentials = await loginGitHubCopilot({
43
35
  onAuth: (url, instructions) => {
@@ -103,7 +95,6 @@ Commands:
103
95
  list List available providers
104
96
 
105
97
  Providers:
106
- anthropic Anthropic (Claude Pro/Max)
107
98
  github-copilot GitHub Copilot
108
99
  google-gemini-cli Google Gemini CLI
109
100
  google-antigravity Antigravity (Gemini 3, Claude, GPT-OSS)
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 \"fs\";\nimport { createInterface } from \"readline\";\nimport { loginAnthropic } from \"./utils/oauth/anthropic.js\";\nimport { loginGitHubCopilot } from \"./utils/oauth/github-copilot.js\";\nimport { loginAntigravity } from \"./utils/oauth/google-antigravity.js\";\nimport { loginGeminiCli } from \"./utils/oauth/google-gemini-cli.js\";\nimport { getOAuthProviders } from \"./utils/oauth/index.js\";\nimport { loginOpenAICodex } from \"./utils/oauth/openai-codex.js\";\nimport type { OAuthCredentials, OAuthProvider } from \"./utils/oauth/types.js\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = getOAuthProviders();\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, { type: \"oauth\" } & OAuthCredentials> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\"));\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, { type: \"oauth\" } & OAuthCredentials>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function login(provider: OAuthProvider): Promise<void> {\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\n\tconst promptFn = (msg: string) => prompt(rl, `${msg} `);\n\n\ttry {\n\t\tlet credentials: OAuthCredentials;\n\n\t\tswitch (provider) {\n\t\t\tcase \"anthropic\":\n\t\t\t\tcredentials = await loginAnthropic(\n\t\t\t\t\t(url) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${url}\\n`);\n\t\t\t\t\t},\n\t\t\t\t\tasync () => {\n\t\t\t\t\t\treturn await promptFn(\"Paste the authorization code:\");\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase \"github-copilot\":\n\t\t\t\tcredentials = await loginGitHubCopilot({\n\t\t\t\t\tonAuth: (url, instructions) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${url}`);\n\t\t\t\t\t\tif (instructions) console.log(instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\tonPrompt: async (p) => {\n\t\t\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t\t\t},\n\t\t\t\t\tonProgress: (msg) => console.log(msg),\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"google-gemini-cli\":\n\t\t\t\tcredentials = await loginGeminiCli(\n\t\t\t\t\t(info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\t(msg) => console.log(msg),\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase \"google-antigravity\":\n\t\t\t\tcredentials = await loginAntigravity(\n\t\t\t\t\t(info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\t(msg) => console.log(msg),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"openai-codex\":\n\t\t\t\tcredentials = await loginOpenAICodex({\n\t\t\t\t\tonAuth: (info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\tonPrompt: async (p) => {\n\t\t\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t\t\t},\n\t\t\t\t\tonProgress: (msg) => console.log(msg),\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t}\n\n\t\tconst auth = loadAuth();\n\t\tauth[provider] = { type: \"oauth\", ...credentials };\n\t\tsaveAuth(auth);\n\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\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconsole.log(`Usage: npx @mariozechner/pi-ai <command> [provider]\n\nCommands:\n login [provider] Login to an OAuth provider\n list List available providers\n\nProviders:\n anthropic Anthropic (Claude Pro/Max)\n github-copilot GitHub Copilot\n google-gemini-cli Google Gemini CLI\n google-antigravity Antigravity (Gemini 3, Claude, GPT-OSS)\n openai-codex OpenAI Codex (ChatGPT Plus/Pro)\n\nExamples:\n npx @mariozechner/pi-ai login # interactive provider selection\n npx @mariozechner/pi-ai login anthropic # login to specific provider\n npx @mariozechner/pi-ai list # list providers\n`);\n\t\treturn;\n\t}\n\n\tif (command === \"list\") {\n\t\tconsole.log(\"Available OAuth providers:\\n\");\n\t\tfor (const p of PROVIDERS) {\n\t\t\tconsole.log(` ${p.id.padEnd(20)} ${p.name}`);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (command === \"login\") {\n\t\tlet provider = args[1] as OAuthProvider | undefined;\n\n\t\tif (!provider) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\tconsole.log(\"Select a provider:\\n\");\n\t\t\tfor (let i = 0; i < PROVIDERS.length; i++) {\n\t\t\t\tconsole.log(` ${i + 1}. ${PROVIDERS[i].name}`);\n\t\t\t}\n\t\t\tconsole.log();\n\n\t\t\tconst choice = await prompt(rl, `Enter number (1-${PROVIDERS.length}): `);\n\t\t\trl.close();\n\n\t\t\tconst index = parseInt(choice, 10) - 1;\n\t\t\tif (index < 0 || index >= PROVIDERS.length) {\n\t\t\t\tconsole.error(\"Invalid selection\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\tprovider = PROVIDERS[index].id;\n\t\t}\n\n\t\tif (!PROVIDERS.some((p) => p.id === provider)) {\n\t\t\tconsole.error(`Unknown provider: ${provider}`);\n\t\t\tconsole.error(`Use 'npx @mariozechner/pi-ai list' to see available providers`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsole.log(`Logging in to ${provider}...`);\n\t\tawait login(provider);\n\t\treturn;\n\t}\n\n\tconsole.error(`Unknown command: ${command}`);\n\tconsole.error(`Use 'npx @mariozechner/pi-ai --help' for usage`);\n\tprocess.exit(1);\n}\n\nmain().catch((err) => {\n\tconsole.error(\"Error:\", err.message);\n\tprocess.exit(1);\n});\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,MAAM,SAAS,GAAG,WAAW,CAAC;AAC9B,MAAM,SAAS,GAAG,iBAAiB,EAAE,CAAC;AAEtC,SAAS,MAAM,CAAC,EAAsC,EAAE,QAAgB,EAAmB;IAC1F,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAAA,CAChE;AAED,SAAS,QAAQ,GAAyD;IACzE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;IACX,CAAC;AAAA,CACD;AAED,SAAS,QAAQ,CAAC,IAA0D,EAAQ;IACnF,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAAA,CACjE;AAED,KAAK,UAAU,KAAK,CAAC,QAAuB,EAAiB;IAC5D,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAE7E,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;IAExD,IAAI,CAAC;QACJ,IAAI,WAA6B,CAAC;QAElC,QAAQ,QAAQ,EAAE,CAAC;YAClB,KAAK,gBAAgB;gBACpB,WAAW,GAAG,MAAM,kBAAkB,CAAC;oBACtC,MAAM,EAAE,CAAC,GAAG,EAAE,YAAY,EAAE,EAAE,CAAC;wBAC9B,OAAO,CAAC,GAAG,CAAC,qCAAqC,GAAG,EAAE,CAAC,CAAC;wBACxD,IAAI,YAAY;4BAAE,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;wBAC5C,OAAO,CAAC,GAAG,EAAE,CAAC;oBAAA,CACd;oBACD,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;wBACtB,OAAO,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;oBAAA,CACpF;oBACD,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;iBACrC,CAAC,CAAC;gBACH,MAAM;YAEP,KAAK,mBAAmB;gBACvB,WAAW,GAAG,MAAM,cAAc,CACjC,CAAC,IAAI,EAAE,EAAE,CAAC;oBACT,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;oBAC7D,IAAI,IAAI,CAAC,YAAY;wBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;oBACtD,OAAO,CAAC,GAAG,EAAE,CAAC;gBAAA,CACd,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CACzB,CAAC;gBACF,MAAM;YAEP,KAAK,oBAAoB;gBACxB,WAAW,GAAG,MAAM,gBAAgB,CACnC,CAAC,IAAI,EAAE,EAAE,CAAC;oBACT,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;oBAC7D,IAAI,IAAI,CAAC,YAAY;wBAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;oBACtD,OAAO,CAAC,GAAG,EAAE,CAAC;gBAAA,CACd,EACD,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CACzB,CAAC;gBACF,MAAM;YACP,KAAK,cAAc;gBAClB,WAAW,GAAG,MAAM,gBAAgB,CAAC;oBACpC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;wBACjB,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;wBAC7D,IAAI,IAAI,CAAC,YAAY;4BAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;wBACtD,OAAO,CAAC,GAAG,EAAE,CAAC;oBAAA,CACd;oBACD,QAAQ,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;wBACtB,OAAO,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;oBAAA,CACpF;oBACD,UAAU,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;iBACrC,CAAC,CAAC;gBACH,MAAM;QACR,CAAC;QAED,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,WAAW,EAAE,CAAC;QACnD,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,OAAO,CAAC,GAAG,CAAC,0BAA0B,SAAS,EAAE,CAAC,CAAC;IACpD,CAAC;YAAS,CAAC;QACV,EAAE,CAAC,KAAK,EAAE,CAAC;IACZ,CAAC;AAAA,CACD;AAED,KAAK,UAAU,IAAI,GAAkB;IACpC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAExB,IAAI,CAAC,OAAO,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QAChF,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;CAgBb,CAAC,CAAC;QACD,OAAO;IACR,CAAC;IAED,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;QAC5C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO;IACR,CAAC;IAED,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;QACzB,IAAI,QAAQ,GAAG,IAAI,CAAC,CAAC,CAA8B,CAAC;QAEpD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;YAC7E,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACjD,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,CAAC;YAEd,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,EAAE,mBAAmB,SAAS,CAAC,MAAM,KAAK,CAAC,CAAC;YAC1E,EAAE,CAAC,KAAK,EAAE,CAAC;YAEX,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;gBAC5C,OAAO,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjB,CAAC;YACD,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;YAC/C,OAAO,CAAC,KAAK,CAAC,+DAA+D,CAAC,CAAC;YAC/E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,iBAAiB,QAAQ,KAAK,CAAC,CAAC;QAC5C,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;QACtB,OAAO;IACR,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,CAChB;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;IACrB,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAAA,CAChB,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\n\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { createInterface } from \"readline\";\nimport { loginGitHubCopilot } from \"./utils/oauth/github-copilot.js\";\nimport { loginAntigravity } from \"./utils/oauth/google-antigravity.js\";\nimport { loginGeminiCli } from \"./utils/oauth/google-gemini-cli.js\";\nimport { getOAuthProviders } from \"./utils/oauth/index.js\";\nimport { loginOpenAICodex } from \"./utils/oauth/openai-codex.js\";\nimport type { OAuthCredentials, OAuthProvider } from \"./utils/oauth/types.js\";\n\nconst AUTH_FILE = \"auth.json\";\nconst PROVIDERS = getOAuthProviders();\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, { type: \"oauth\" } & OAuthCredentials> {\n\tif (!existsSync(AUTH_FILE)) return {};\n\ttry {\n\t\treturn JSON.parse(readFileSync(AUTH_FILE, \"utf-8\"));\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nfunction saveAuth(auth: Record<string, { type: \"oauth\" } & OAuthCredentials>): void {\n\twriteFileSync(AUTH_FILE, JSON.stringify(auth, null, 2), \"utf-8\");\n}\n\nasync function login(provider: OAuthProvider): Promise<void> {\n\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\n\tconst promptFn = (msg: string) => prompt(rl, `${msg} `);\n\n\ttry {\n\t\tlet credentials: OAuthCredentials;\n\n\t\tswitch (provider) {\n\t\t\tcase \"github-copilot\":\n\t\t\t\tcredentials = await loginGitHubCopilot({\n\t\t\t\t\tonAuth: (url, instructions) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${url}`);\n\t\t\t\t\t\tif (instructions) console.log(instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\tonPrompt: async (p) => {\n\t\t\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t\t\t},\n\t\t\t\t\tonProgress: (msg) => console.log(msg),\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"google-gemini-cli\":\n\t\t\t\tcredentials = await loginGeminiCli(\n\t\t\t\t\t(info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\t(msg) => console.log(msg),\n\t\t\t\t);\n\t\t\t\tbreak;\n\n\t\t\tcase \"google-antigravity\":\n\t\t\t\tcredentials = await loginAntigravity(\n\t\t\t\t\t(info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\t(msg) => console.log(msg),\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"openai-codex\":\n\t\t\t\tcredentials = await loginOpenAICodex({\n\t\t\t\t\tonAuth: (info) => {\n\t\t\t\t\t\tconsole.log(`\\nOpen this URL in your browser:\\n${info.url}`);\n\t\t\t\t\t\tif (info.instructions) console.log(info.instructions);\n\t\t\t\t\t\tconsole.log();\n\t\t\t\t\t},\n\t\t\t\t\tonPrompt: async (p) => {\n\t\t\t\t\t\treturn await promptFn(`${p.message}${p.placeholder ? ` (${p.placeholder})` : \"\"}:`);\n\t\t\t\t\t},\n\t\t\t\t\tonProgress: (msg) => console.log(msg),\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t}\n\n\t\tconst auth = loadAuth();\n\t\tauth[provider] = { type: \"oauth\", ...credentials };\n\t\tsaveAuth(auth);\n\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\n\tif (!command || command === \"help\" || command === \"--help\" || command === \"-h\") {\n\t\tconsole.log(`Usage: npx @mariozechner/pi-ai <command> [provider]\n\nCommands:\n login [provider] Login to an OAuth provider\n list List available providers\n\nProviders:\n github-copilot GitHub Copilot\n google-gemini-cli Google Gemini CLI\n google-antigravity Antigravity (Gemini 3, Claude, GPT-OSS)\n openai-codex OpenAI Codex (ChatGPT Plus/Pro)\n\nExamples:\n npx @mariozechner/pi-ai login # interactive provider selection\n npx @mariozechner/pi-ai login anthropic # login to specific provider\n npx @mariozechner/pi-ai list # list providers\n`);\n\t\treturn;\n\t}\n\n\tif (command === \"list\") {\n\t\tconsole.log(\"Available OAuth providers:\\n\");\n\t\tfor (const p of PROVIDERS) {\n\t\t\tconsole.log(` ${p.id.padEnd(20)} ${p.name}`);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (command === \"login\") {\n\t\tlet provider = args[1] as OAuthProvider | undefined;\n\n\t\tif (!provider) {\n\t\t\tconst rl = createInterface({ input: process.stdin, output: process.stdout });\n\t\t\tconsole.log(\"Select a provider:\\n\");\n\t\t\tfor (let i = 0; i < PROVIDERS.length; i++) {\n\t\t\t\tconsole.log(` ${i + 1}. ${PROVIDERS[i].name}`);\n\t\t\t}\n\t\t\tconsole.log();\n\n\t\t\tconst choice = await prompt(rl, `Enter number (1-${PROVIDERS.length}): `);\n\t\t\trl.close();\n\n\t\t\tconst index = parseInt(choice, 10) - 1;\n\t\t\tif (index < 0 || index >= PROVIDERS.length) {\n\t\t\t\tconsole.error(\"Invalid selection\");\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\tprovider = PROVIDERS[index].id;\n\t\t}\n\n\t\tif (!PROVIDERS.some((p) => p.id === provider)) {\n\t\t\tconsole.error(`Unknown provider: ${provider}`);\n\t\t\tconsole.error(`Use 'npx @mariozechner/pi-ai list' to see available providers`);\n\t\t\tprocess.exit(1);\n\t\t}\n\n\t\tconsole.log(`Logging in to ${provider}...`);\n\t\tawait login(provider);\n\t\treturn;\n\t}\n\n\tconsole.error(`Unknown command: ${command}`);\n\tconsole.error(`Use 'npx @mariozechner/pi-ai --help' for usage`);\n\tprocess.exit(1);\n}\n\nmain().catch((err) => {\n\tconsole.error(\"Error:\", err.message);\n\tprocess.exit(1);\n});\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAQX,cAAc,EACd,aAAa,EAMb,MAAM,aAAa,CAAC;AA2DrB,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACtE;AAED,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,oBAAoB,CA6LhE,CAAC","sourcesContent":["import Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n\tContentBlockParam,\n\tMessageCreateParamsStreaming,\n\tMessageParam,\n} from \"@anthropic-ai/sdk/resources/messages.js\";\nimport { calculateCost } from \"../models.js\";\nimport { getEnvApiKey } from \"../stream.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tImageContent,\n\tMessage,\n\tModel,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\n\nimport { transformMessages } from \"./transorm-messages.js\";\n\n/**\n * Convert content blocks to Anthropic API format\n */\nfunction convertContentBlocks(content: (TextContent | ImageContent)[]):\n\t| string\n\t| Array<\n\t\t\t| { type: \"text\"; text: string }\n\t\t\t| {\n\t\t\t\t\ttype: \"image\";\n\t\t\t\t\tsource: {\n\t\t\t\t\t\ttype: \"base64\";\n\t\t\t\t\t\tmedia_type: \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\";\n\t\t\t\t\t\tdata: string;\n\t\t\t\t\t};\n\t\t\t }\n\t > {\n\t// If only text blocks, return as concatenated string for simplicity\n\tconst hasImages = content.some((c) => c.type === \"image\");\n\tif (!hasImages) {\n\t\treturn sanitizeSurrogates(content.map((c) => (c as TextContent).text).join(\"\\n\"));\n\t}\n\n\t// If we have images, convert to content block array\n\tconst blocks = content.map((block) => {\n\t\tif (block.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: sanitizeSurrogates(block.text),\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image\" as const,\n\t\t\tsource: {\n\t\t\t\ttype: \"base64\" as const,\n\t\t\t\tmedia_type: block.mimeType as \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n\t\t\t\tdata: block.data,\n\t\t\t},\n\t\t};\n\t});\n\n\t// If only images (no text), add placeholder text block\n\tconst hasText = blocks.some((b) => b.type === \"text\");\n\tif (!hasText) {\n\t\tblocks.unshift({\n\t\t\ttype: \"text\" as const,\n\t\t\ttext: \"(see attached image)\",\n\t\t});\n\t}\n\n\treturn blocks;\n}\n\nexport interface AnthropicOptions extends StreamOptions {\n\tthinkingEnabled?: boolean;\n\tthinkingBudgetTokens?: number;\n\tinterleavedThinking?: boolean;\n\ttoolChoice?: \"auto\" | \"any\" | \"none\" | { type: \"tool\"; name: string };\n}\n\nexport const streamAnthropic: StreamFunction<\"anthropic-messages\"> = (\n\tmodel: Model<\"anthropic-messages\">,\n\tcontext: Context,\n\toptions?: AnthropicOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"anthropic-messages\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? \"\";\n\t\t\tconst { client, isOAuthToken } = createClient(model, apiKey, options?.interleavedThinking ?? true);\n\t\t\tconst params = buildParams(model, context, isOAuthToken, options);\n\t\t\tconst anthropicStream = client.messages.stream({ ...params, stream: true }, { signal: options?.signal });\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\ttype Block = (ThinkingContent | TextContent | (ToolCall & { partialJson: string })) & { index: number };\n\t\t\tconst blocks = output.content as Block[];\n\n\t\t\tfor await (const event of anthropicStream) {\n\t\t\t\tif (event.type === \"message_start\") {\n\t\t\t\t\t// Capture initial token usage from message_start event\n\t\t\t\t\t// This ensures we have input token counts even if the stream is aborted early\n\t\t\t\t\toutput.usage.input = event.message.usage.input_tokens || 0;\n\t\t\t\t\toutput.usage.output = event.message.usage.output_tokens || 0;\n\t\t\t\t\toutput.usage.cacheRead = event.message.usage.cache_read_input_tokens || 0;\n\t\t\t\t\toutput.usage.cacheWrite = event.message.usage.cache_creation_input_tokens || 0;\n\t\t\t\t\t// Anthropic doesn't provide total_tokens, compute from components\n\t\t\t\t\toutput.usage.totalTokens =\n\t\t\t\t\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t} else if (event.type === \"content_block_start\") {\n\t\t\t\t\tif (event.content_block.type === \"text\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t} else if (event.content_block.type === \"thinking\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: \"\",\n\t\t\t\t\t\t\tthinkingSignature: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t} else if (event.content_block.type === \"tool_use\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: event.content_block.id,\n\t\t\t\t\t\t\tname: event.content_block.name,\n\t\t\t\t\t\t\targuments: event.content_block.input as Record<string, any>,\n\t\t\t\t\t\t\tpartialJson: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"content_block_delta\") {\n\t\t\t\t\tif (event.delta.type === \"text_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"text\") {\n\t\t\t\t\t\t\tblock.text += event.delta.text;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.text,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"thinking_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"thinking\") {\n\t\t\t\t\t\t\tblock.thinking += event.delta.thinking;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.thinking,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"input_json_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"toolCall\") {\n\t\t\t\t\t\t\tblock.partialJson += event.delta.partial_json;\n\t\t\t\t\t\t\tblock.arguments = parseStreamingJson(block.partialJson);\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.partial_json,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"signature_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"thinking\") {\n\t\t\t\t\t\t\tblock.thinkingSignature = block.thinkingSignature || \"\";\n\t\t\t\t\t\t\tblock.thinkingSignature += event.delta.signature;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"content_block_stop\") {\n\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\tif (block) {\n\t\t\t\t\t\tdelete (block as any).index;\n\t\t\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tcontent: block.text,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tcontent: block.thinking,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\t\t\tblock.arguments = parseStreamingJson(block.partialJson);\n\t\t\t\t\t\t\tdelete (block as any).partialJson;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\ttoolCall: block,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"message_delta\") {\n\t\t\t\t\tif (event.delta.stop_reason) {\n\t\t\t\t\t\toutput.stopReason = mapStopReason(event.delta.stop_reason);\n\t\t\t\t\t}\n\t\t\t\t\toutput.usage.input = event.usage.input_tokens || 0;\n\t\t\t\t\toutput.usage.output = event.usage.output_tokens || 0;\n\t\t\t\t\toutput.usage.cacheRead = event.usage.cache_read_input_tokens || 0;\n\t\t\t\t\toutput.usage.cacheWrite = event.usage.cache_creation_input_tokens || 0;\n\t\t\t\t\t// Anthropic doesn't provide total_tokens, compute from components\n\t\t\t\t\toutput.usage.totalTokens =\n\t\t\t\t\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unkown error ocurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) delete (block as any).index;\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction createClient(\n\tmodel: Model<\"anthropic-messages\">,\n\tapiKey: string,\n\tinterleavedThinking: boolean,\n): { client: Anthropic; isOAuthToken: boolean } {\n\tconst betaFeatures = [\"fine-grained-tool-streaming-2025-05-14\"];\n\tif (interleavedThinking) {\n\t\tbetaFeatures.push(\"interleaved-thinking-2025-05-14\");\n\t}\n\n\tif (apiKey.includes(\"sk-ant-oat\")) {\n\t\tconst defaultHeaders = {\n\t\t\taccept: \"application/json\",\n\t\t\t\"anthropic-dangerous-direct-browser-access\": \"true\",\n\t\t\t\"anthropic-beta\": `oauth-2025-04-20,${betaFeatures.join(\",\")}`,\n\t\t\t...(model.headers || {}),\n\t\t};\n\n\t\tconst client = new Anthropic({\n\t\t\tapiKey: null,\n\t\t\tauthToken: apiKey,\n\t\t\tbaseURL: model.baseUrl,\n\t\t\tdefaultHeaders,\n\t\t\tdangerouslyAllowBrowser: true,\n\t\t});\n\n\t\treturn { client, isOAuthToken: true };\n\t} else {\n\t\tconst defaultHeaders = {\n\t\t\taccept: \"application/json\",\n\t\t\t\"anthropic-dangerous-direct-browser-access\": \"true\",\n\t\t\t\"anthropic-beta\": betaFeatures.join(\",\"),\n\t\t\t...(model.headers || {}),\n\t\t};\n\n\t\tconst client = new Anthropic({\n\t\t\tapiKey,\n\t\t\tbaseURL: model.baseUrl,\n\t\t\tdangerouslyAllowBrowser: true,\n\t\t\tdefaultHeaders,\n\t\t});\n\n\t\treturn { client, isOAuthToken: false };\n\t}\n}\n\nfunction buildParams(\n\tmodel: Model<\"anthropic-messages\">,\n\tcontext: Context,\n\tisOAuthToken: boolean,\n\toptions?: AnthropicOptions,\n): MessageCreateParamsStreaming {\n\tconst params: MessageCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tmessages: convertMessages(context.messages, model),\n\t\tmax_tokens: options?.maxTokens || (model.maxTokens / 3) | 0,\n\t\tstream: true,\n\t};\n\n\t// For OAuth tokens, we MUST include Claude Code identity\n\tif (isOAuthToken) {\n\t\tparams.system = [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: \"You are Claude Code, Anthropic's official CLI for Claude.\",\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t\tif (context.systemPrompt) {\n\t\t\tparams.system.push({\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(context.systemPrompt),\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t} else if (context.systemPrompt) {\n\t\t// Add cache control to system prompt for non-OAuth tokens\n\t\tparams.system = [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(context.systemPrompt),\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options.temperature;\n\t}\n\n\tif (context.tools) {\n\t\tparams.tools = convertTools(context.tools);\n\t}\n\n\tif (options?.thinkingEnabled && model.reasoning) {\n\t\tparams.thinking = {\n\t\t\ttype: \"enabled\",\n\t\t\tbudget_tokens: options.thinkingBudgetTokens || 1024,\n\t\t};\n\t}\n\n\tif (options?.toolChoice) {\n\t\tif (typeof options.toolChoice === \"string\") {\n\t\t\tparams.tool_choice = { type: options.toolChoice };\n\t\t} else {\n\t\t\tparams.tool_choice = options.toolChoice;\n\t\t}\n\t}\n\n\treturn params;\n}\n\n// Sanitize tool call IDs to match Anthropic's required pattern: ^[a-zA-Z0-9_-]+$\nfunction sanitizeToolCallId(id: string): string {\n\t// Replace any character that isn't alphanumeric, underscore, or hyphen with underscore\n\treturn id.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n}\n\nfunction convertMessages(messages: Message[], model: Model<\"anthropic-messages\">): MessageParam[] {\n\tconst params: MessageParam[] = [];\n\n\t// Transform messages for cross-provider compatibility\n\tconst transformedMessages = transformMessages(messages, model);\n\n\tfor (let i = 0; i < transformedMessages.length; i++) {\n\t\tconst msg = transformedMessages[i];\n\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tif (msg.content.trim().length > 0) {\n\t\t\t\t\tparams.push({\n\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\tcontent: sanitizeSurrogates(msg.content),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst blocks: ContentBlockParam[] = msg.content.map((item) => {\n\t\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\t\ttype: \"base64\",\n\t\t\t\t\t\t\t\tmedia_type: item.mimeType as \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n\t\t\t\t\t\t\t\tdata: item.data,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tlet filteredBlocks = !model?.input.includes(\"image\") ? blocks.filter((b) => b.type !== \"image\") : blocks;\n\t\t\t\tfilteredBlocks = filteredBlocks.filter((b) => {\n\t\t\t\t\tif (b.type === \"text\") {\n\t\t\t\t\t\treturn b.text.trim().length > 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\tif (filteredBlocks.length === 0) continue;\n\t\t\t\tparams.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: filteredBlocks,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst blocks: ContentBlockParam[] = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (block.text.trim().length === 0) continue;\n\t\t\t\t\tblocks.push({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: sanitizeSurrogates(block.text),\n\t\t\t\t\t});\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tif (block.thinking.trim().length === 0) continue;\n\t\t\t\t\t// If thinking signature is missing/empty (e.g., from aborted stream),\n\t\t\t\t\t// convert to plain text block without <thinking> tags to avoid API rejection\n\t\t\t\t\t// and prevent Claude from mimicking the tags in responses\n\t\t\t\t\tif (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) {\n\t\t\t\t\t\tblocks.push({\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(block.thinking),\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tblocks.push({\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: sanitizeSurrogates(block.thinking),\n\t\t\t\t\t\t\tsignature: block.thinkingSignature,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tblocks.push({\n\t\t\t\t\t\ttype: \"tool_use\",\n\t\t\t\t\t\tid: sanitizeToolCallId(block.id),\n\t\t\t\t\t\tname: block.name,\n\t\t\t\t\t\tinput: block.arguments,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (blocks.length === 0) continue;\n\t\t\tparams.push({\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: blocks,\n\t\t\t});\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\t// Collect all consecutive toolResult messages, needed for z.ai Anthropic endpoint\n\t\t\tconst toolResults: ContentBlockParam[] = [];\n\n\t\t\t// Add the current tool result\n\t\t\ttoolResults.push({\n\t\t\t\ttype: \"tool_result\",\n\t\t\t\ttool_use_id: sanitizeToolCallId(msg.toolCallId),\n\t\t\t\tcontent: convertContentBlocks(msg.content),\n\t\t\t\tis_error: msg.isError,\n\t\t\t});\n\n\t\t\t// Look ahead for consecutive toolResult messages\n\t\t\tlet j = i + 1;\n\t\t\twhile (j < transformedMessages.length && transformedMessages[j].role === \"toolResult\") {\n\t\t\t\tconst nextMsg = transformedMessages[j] as ToolResultMessage; // We know it's a toolResult\n\t\t\t\ttoolResults.push({\n\t\t\t\t\ttype: \"tool_result\",\n\t\t\t\t\ttool_use_id: sanitizeToolCallId(nextMsg.toolCallId),\n\t\t\t\t\tcontent: convertContentBlocks(nextMsg.content),\n\t\t\t\t\tis_error: nextMsg.isError,\n\t\t\t\t});\n\t\t\t\tj++;\n\t\t\t}\n\n\t\t\t// Skip the messages we've already processed\n\t\t\ti = j - 1;\n\n\t\t\t// Add a single user message with all tool results\n\t\t\tparams.push({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: toolResults,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Add cache_control to the last user message to cache conversation history\n\tif (params.length > 0) {\n\t\tconst lastMessage = params[params.length - 1];\n\t\tif (lastMessage.role === \"user\") {\n\t\t\t// Add cache control to the last content block\n\t\t\tif (Array.isArray(lastMessage.content)) {\n\t\t\t\tconst lastBlock = lastMessage.content[lastMessage.content.length - 1];\n\t\t\t\tif (\n\t\t\t\t\tlastBlock &&\n\t\t\t\t\t(lastBlock.type === \"text\" || lastBlock.type === \"image\" || lastBlock.type === \"tool_result\")\n\t\t\t\t) {\n\t\t\t\t\t(lastBlock as any).cache_control = { type: \"ephemeral\" };\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn params;\n}\n\nfunction convertTools(tools: Tool[]): Anthropic.Messages.Tool[] {\n\tif (!tools) return [];\n\n\treturn tools.map((tool) => {\n\t\tconst jsonSchema = tool.parameters as any; // TypeBox already generates JSON Schema\n\n\t\treturn {\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tinput_schema: {\n\t\t\t\ttype: \"object\" as const,\n\t\t\t\tproperties: jsonSchema.properties || {},\n\t\t\t\trequired: jsonSchema.required || [],\n\t\t\t},\n\t\t};\n\t});\n}\n\nfunction mapStopReason(reason: Anthropic.Messages.StopReason): StopReason {\n\tswitch (reason) {\n\t\tcase \"end_turn\":\n\t\t\treturn \"stop\";\n\t\tcase \"max_tokens\":\n\t\t\treturn \"length\";\n\t\tcase \"tool_use\":\n\t\t\treturn \"toolUse\";\n\t\tcase \"refusal\":\n\t\t\treturn \"error\";\n\t\tcase \"pause_turn\": // Stop is good enough -> resubmit\n\t\t\treturn \"stop\";\n\t\tcase \"stop_sequence\":\n\t\t\treturn \"stop\"; // We don't supply stop sequences, so this should never happen\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = reason;\n\t\t\tthrow new Error(`Unhandled stop reason: ${_exhaustive}`);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAQX,cAAc,EACd,aAAa,EAMb,MAAM,aAAa,CAAC;AA2DrB,MAAM,WAAW,gBAAiB,SAAQ,aAAa;IACtD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACtE;AAED,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,oBAAoB,CA6LhE,CAAC","sourcesContent":["import Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n\tContentBlockParam,\n\tMessageCreateParamsStreaming,\n\tMessageParam,\n} from \"@anthropic-ai/sdk/resources/messages.js\";\nimport { calculateCost } from \"../models.js\";\nimport { getEnvApiKey } from \"../stream.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tImageContent,\n\tMessage,\n\tModel,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\n\nimport { transformMessages } from \"./transorm-messages.js\";\n\n/**\n * Convert content blocks to Anthropic API format\n */\nfunction convertContentBlocks(content: (TextContent | ImageContent)[]):\n\t| string\n\t| Array<\n\t\t\t| { type: \"text\"; text: string }\n\t\t\t| {\n\t\t\t\t\ttype: \"image\";\n\t\t\t\t\tsource: {\n\t\t\t\t\t\ttype: \"base64\";\n\t\t\t\t\t\tmedia_type: \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\";\n\t\t\t\t\t\tdata: string;\n\t\t\t\t\t};\n\t\t\t }\n\t > {\n\t// If only text blocks, return as concatenated string for simplicity\n\tconst hasImages = content.some((c) => c.type === \"image\");\n\tif (!hasImages) {\n\t\treturn sanitizeSurrogates(content.map((c) => (c as TextContent).text).join(\"\\n\"));\n\t}\n\n\t// If we have images, convert to content block array\n\tconst blocks = content.map((block) => {\n\t\tif (block.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: sanitizeSurrogates(block.text),\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image\" as const,\n\t\t\tsource: {\n\t\t\t\ttype: \"base64\" as const,\n\t\t\t\tmedia_type: block.mimeType as \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n\t\t\t\tdata: block.data,\n\t\t\t},\n\t\t};\n\t});\n\n\t// If only images (no text), add placeholder text block\n\tconst hasText = blocks.some((b) => b.type === \"text\");\n\tif (!hasText) {\n\t\tblocks.unshift({\n\t\t\ttype: \"text\" as const,\n\t\t\ttext: \"(see attached image)\",\n\t\t});\n\t}\n\n\treturn blocks;\n}\n\nexport interface AnthropicOptions extends StreamOptions {\n\tthinkingEnabled?: boolean;\n\tthinkingBudgetTokens?: number;\n\tinterleavedThinking?: boolean;\n\ttoolChoice?: \"auto\" | \"any\" | \"none\" | { type: \"tool\"; name: string };\n}\n\nexport const streamAnthropic: StreamFunction<\"anthropic-messages\"> = (\n\tmodel: Model<\"anthropic-messages\">,\n\tcontext: Context,\n\toptions?: AnthropicOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"anthropic-messages\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? \"\";\n\t\t\tconst { client, isOAuthToken } = createClient(model, apiKey, options?.interleavedThinking ?? true);\n\t\t\tconst params = buildParams(model, context, isOAuthToken, options);\n\t\t\tconst anthropicStream = client.messages.stream({ ...params, stream: true }, { signal: options?.signal });\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\ttype Block = (ThinkingContent | TextContent | (ToolCall & { partialJson: string })) & { index: number };\n\t\t\tconst blocks = output.content as Block[];\n\n\t\t\tfor await (const event of anthropicStream) {\n\t\t\t\tif (event.type === \"message_start\") {\n\t\t\t\t\t// Capture initial token usage from message_start event\n\t\t\t\t\t// This ensures we have input token counts even if the stream is aborted early\n\t\t\t\t\toutput.usage.input = event.message.usage.input_tokens || 0;\n\t\t\t\t\toutput.usage.output = event.message.usage.output_tokens || 0;\n\t\t\t\t\toutput.usage.cacheRead = event.message.usage.cache_read_input_tokens || 0;\n\t\t\t\t\toutput.usage.cacheWrite = event.message.usage.cache_creation_input_tokens || 0;\n\t\t\t\t\t// Anthropic doesn't provide total_tokens, compute from components\n\t\t\t\t\toutput.usage.totalTokens =\n\t\t\t\t\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t} else if (event.type === \"content_block_start\") {\n\t\t\t\t\tif (event.content_block.type === \"text\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t} else if (event.content_block.type === \"thinking\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: \"\",\n\t\t\t\t\t\t\tthinkingSignature: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t} else if (event.content_block.type === \"tool_use\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: event.content_block.id,\n\t\t\t\t\t\t\tname: isOAuthToken ? event.content_block.name.substring(4) : event.content_block.name,\n\t\t\t\t\t\t\targuments: event.content_block.input as Record<string, any>,\n\t\t\t\t\t\t\tpartialJson: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"content_block_delta\") {\n\t\t\t\t\tif (event.delta.type === \"text_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"text\") {\n\t\t\t\t\t\t\tblock.text += event.delta.text;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.text,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"thinking_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"thinking\") {\n\t\t\t\t\t\t\tblock.thinking += event.delta.thinking;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.thinking,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"input_json_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"toolCall\") {\n\t\t\t\t\t\t\tblock.partialJson += event.delta.partial_json;\n\t\t\t\t\t\t\tblock.arguments = parseStreamingJson(block.partialJson);\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.partial_json,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"signature_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"thinking\") {\n\t\t\t\t\t\t\tblock.thinkingSignature = block.thinkingSignature || \"\";\n\t\t\t\t\t\t\tblock.thinkingSignature += event.delta.signature;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"content_block_stop\") {\n\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\tif (block) {\n\t\t\t\t\t\tdelete (block as any).index;\n\t\t\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tcontent: block.text,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tcontent: block.thinking,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\t\t\tblock.arguments = parseStreamingJson(block.partialJson);\n\t\t\t\t\t\t\tdelete (block as any).partialJson;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\ttoolCall: block,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"message_delta\") {\n\t\t\t\t\tif (event.delta.stop_reason) {\n\t\t\t\t\t\toutput.stopReason = mapStopReason(event.delta.stop_reason);\n\t\t\t\t\t}\n\t\t\t\t\toutput.usage.input = event.usage.input_tokens || 0;\n\t\t\t\t\toutput.usage.output = event.usage.output_tokens || 0;\n\t\t\t\t\toutput.usage.cacheRead = event.usage.cache_read_input_tokens || 0;\n\t\t\t\t\toutput.usage.cacheWrite = event.usage.cache_creation_input_tokens || 0;\n\t\t\t\t\t// Anthropic doesn't provide total_tokens, compute from components\n\t\t\t\t\toutput.usage.totalTokens =\n\t\t\t\t\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unkown error ocurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) delete (block as any).index;\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction isOAuthToken(apiKey: string): boolean {\n\treturn apiKey.includes(\"sk-ant-oat\");\n}\n\nfunction createClient(\n\tmodel: Model<\"anthropic-messages\">,\n\tapiKey: string,\n\tinterleavedThinking: boolean,\n): { client: Anthropic; isOAuthToken: boolean } {\n\tconst betaFeatures = [\"fine-grained-tool-streaming-2025-05-14\"];\n\tif (interleavedThinking) {\n\t\tbetaFeatures.push(\"interleaved-thinking-2025-05-14\");\n\t}\n\n\tconst oauthToken = isOAuthToken(apiKey);\n\tif (oauthToken) {\n\t\tconst defaultHeaders = {\n\t\t\taccept: \"application/json\",\n\t\t\t\"anthropic-dangerous-direct-browser-access\": \"true\",\n\t\t\t\"anthropic-beta\": `oauth-2025-04-20,${betaFeatures.join(\",\")}`,\n\t\t\t...(model.headers || {}),\n\t\t};\n\n\t\tconst client = new Anthropic({\n\t\t\tapiKey: null,\n\t\t\tauthToken: apiKey,\n\t\t\tbaseURL: model.baseUrl,\n\t\t\tdefaultHeaders,\n\t\t\tdangerouslyAllowBrowser: true,\n\t\t});\n\n\t\treturn { client, isOAuthToken: true };\n\t}\n\n\tconst defaultHeaders = {\n\t\taccept: \"application/json\",\n\t\t\"anthropic-dangerous-direct-browser-access\": \"true\",\n\t\t\"anthropic-beta\": betaFeatures.join(\",\"),\n\t\t...(model.headers || {}),\n\t};\n\n\tconst client = new Anthropic({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders,\n\t});\n\n\treturn { client, isOAuthToken: false };\n}\n\nfunction buildParams(\n\tmodel: Model<\"anthropic-messages\">,\n\tcontext: Context,\n\tisOAuthToken: boolean,\n\toptions?: AnthropicOptions,\n): MessageCreateParamsStreaming {\n\tconst params: MessageCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tmessages: convertMessages(context.messages, model, isOAuthToken),\n\t\tmax_tokens: options?.maxTokens || (model.maxTokens / 3) | 0,\n\t\tstream: true,\n\t};\n\n\t// For OAuth tokens, we MUST include Claude Code identity\n\tif (isOAuthToken) {\n\t\tparams.system = [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: \"You are Claude Code, Anthropic's official CLI for Claude.\",\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t\tif (context.systemPrompt) {\n\t\t\tparams.system.push({\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(context.systemPrompt),\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t} else if (context.systemPrompt) {\n\t\t// Add cache control to system prompt for non-OAuth tokens\n\t\tparams.system = [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(context.systemPrompt),\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options.temperature;\n\t}\n\n\tif (context.tools) {\n\t\tparams.tools = convertTools(context.tools, isOAuthToken);\n\t}\n\n\tif (options?.thinkingEnabled && model.reasoning) {\n\t\tparams.thinking = {\n\t\t\ttype: \"enabled\",\n\t\t\tbudget_tokens: options.thinkingBudgetTokens || 1024,\n\t\t};\n\t}\n\n\tif (options?.toolChoice) {\n\t\tif (typeof options.toolChoice === \"string\") {\n\t\t\tparams.tool_choice = { type: options.toolChoice };\n\t\t} else {\n\t\t\tparams.tool_choice = options.toolChoice;\n\t\t}\n\t}\n\n\treturn params;\n}\n\n// Sanitize tool call IDs to match Anthropic's required pattern: ^[a-zA-Z0-9_-]+$\nfunction sanitizeToolCallId(id: string): string {\n\t// Replace any character that isn't alphanumeric, underscore, or hyphen with underscore\n\treturn id.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n}\n\nfunction convertMessages(\n\tmessages: Message[],\n\tmodel: Model<\"anthropic-messages\">,\n\tisOAuthToken: boolean,\n): MessageParam[] {\n\tconst params: MessageParam[] = [];\n\n\t// Transform messages for cross-provider compatibility\n\tconst transformedMessages = transformMessages(messages, model);\n\n\tfor (let i = 0; i < transformedMessages.length; i++) {\n\t\tconst msg = transformedMessages[i];\n\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tif (msg.content.trim().length > 0) {\n\t\t\t\t\tparams.push({\n\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\tcontent: sanitizeSurrogates(msg.content),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst blocks: ContentBlockParam[] = msg.content.map((item) => {\n\t\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\t\ttype: \"base64\",\n\t\t\t\t\t\t\t\tmedia_type: item.mimeType as \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n\t\t\t\t\t\t\t\tdata: item.data,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tlet filteredBlocks = !model?.input.includes(\"image\") ? blocks.filter((b) => b.type !== \"image\") : blocks;\n\t\t\t\tfilteredBlocks = filteredBlocks.filter((b) => {\n\t\t\t\t\tif (b.type === \"text\") {\n\t\t\t\t\t\treturn b.text.trim().length > 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\tif (filteredBlocks.length === 0) continue;\n\t\t\t\tparams.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: filteredBlocks,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst blocks: ContentBlockParam[] = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (block.text.trim().length === 0) continue;\n\t\t\t\t\tblocks.push({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: sanitizeSurrogates(block.text),\n\t\t\t\t\t});\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tif (block.thinking.trim().length === 0) continue;\n\t\t\t\t\t// If thinking signature is missing/empty (e.g., from aborted stream),\n\t\t\t\t\t// convert to plain text block without <thinking> tags to avoid API rejection\n\t\t\t\t\t// and prevent Claude from mimicking the tags in responses\n\t\t\t\t\tif (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) {\n\t\t\t\t\t\tblocks.push({\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(block.thinking),\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tblocks.push({\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: sanitizeSurrogates(block.thinking),\n\t\t\t\t\t\t\tsignature: block.thinkingSignature,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tblocks.push({\n\t\t\t\t\t\ttype: \"tool_use\",\n\t\t\t\t\t\tid: sanitizeToolCallId(block.id),\n\t\t\t\t\t\tname: isOAuthToken ? `mcp_${block.name}` : block.name,\n\t\t\t\t\t\tinput: block.arguments,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (blocks.length === 0) continue;\n\t\t\tparams.push({\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: blocks,\n\t\t\t});\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\t// Collect all consecutive toolResult messages, needed for z.ai Anthropic endpoint\n\t\t\tconst toolResults: ContentBlockParam[] = [];\n\n\t\t\t// Add the current tool result\n\t\t\ttoolResults.push({\n\t\t\t\ttype: \"tool_result\",\n\t\t\t\ttool_use_id: sanitizeToolCallId(msg.toolCallId),\n\t\t\t\tcontent: convertContentBlocks(msg.content),\n\t\t\t\tis_error: msg.isError,\n\t\t\t});\n\n\t\t\t// Look ahead for consecutive toolResult messages\n\t\t\tlet j = i + 1;\n\t\t\twhile (j < transformedMessages.length && transformedMessages[j].role === \"toolResult\") {\n\t\t\t\tconst nextMsg = transformedMessages[j] as ToolResultMessage; // We know it's a toolResult\n\t\t\t\ttoolResults.push({\n\t\t\t\t\ttype: \"tool_result\",\n\t\t\t\t\ttool_use_id: sanitizeToolCallId(nextMsg.toolCallId),\n\t\t\t\t\tcontent: convertContentBlocks(nextMsg.content),\n\t\t\t\t\tis_error: nextMsg.isError,\n\t\t\t\t});\n\t\t\t\tj++;\n\t\t\t}\n\n\t\t\t// Skip the messages we've already processed\n\t\t\ti = j - 1;\n\n\t\t\t// Add a single user message with all tool results\n\t\t\tparams.push({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: toolResults,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Add cache_control to the last user message to cache conversation history\n\tif (params.length > 0) {\n\t\tconst lastMessage = params[params.length - 1];\n\t\tif (lastMessage.role === \"user\") {\n\t\t\t// Add cache control to the last content block\n\t\t\tif (Array.isArray(lastMessage.content)) {\n\t\t\t\tconst lastBlock = lastMessage.content[lastMessage.content.length - 1];\n\t\t\t\tif (\n\t\t\t\t\tlastBlock &&\n\t\t\t\t\t(lastBlock.type === \"text\" || lastBlock.type === \"image\" || lastBlock.type === \"tool_result\")\n\t\t\t\t) {\n\t\t\t\t\t(lastBlock as any).cache_control = { type: \"ephemeral\" };\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn params;\n}\n\nfunction convertTools(tools: Tool[], isOAuthToken: boolean): Anthropic.Messages.Tool[] {\n\tif (!tools) return [];\n\n\treturn tools.map((tool) => {\n\t\tconst jsonSchema = tool.parameters as any; // TypeBox already generates JSON Schema\n\n\t\treturn {\n\t\t\tname: isOAuthToken ? `mcp_${tool.name}` : tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tinput_schema: {\n\t\t\t\ttype: \"object\" as const,\n\t\t\t\tproperties: jsonSchema.properties || {},\n\t\t\t\trequired: jsonSchema.required || [],\n\t\t\t},\n\t\t};\n\t});\n}\n\nfunction mapStopReason(reason: Anthropic.Messages.StopReason): StopReason {\n\tswitch (reason) {\n\t\tcase \"end_turn\":\n\t\t\treturn \"stop\";\n\t\tcase \"max_tokens\":\n\t\t\treturn \"length\";\n\t\tcase \"tool_use\":\n\t\t\treturn \"toolUse\";\n\t\tcase \"refusal\":\n\t\t\treturn \"error\";\n\t\tcase \"pause_turn\": // Stop is good enough -> resubmit\n\t\t\treturn \"stop\";\n\t\tcase \"stop_sequence\":\n\t\t\treturn \"stop\"; // We don't supply stop sequences, so this should never happen\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = reason;\n\t\t\tthrow new Error(`Unhandled stop reason: ${_exhaustive}`);\n\t\t}\n\t}\n}\n"]}
@@ -105,7 +105,7 @@ export const streamAnthropic = (model, context, options) => {
105
105
  const block = {
106
106
  type: "toolCall",
107
107
  id: event.content_block.id,
108
- name: event.content_block.name,
108
+ name: isOAuthToken ? event.content_block.name.substring(4) : event.content_block.name,
109
109
  arguments: event.content_block.input,
110
110
  partialJson: "",
111
111
  index: event.index,
@@ -231,12 +231,16 @@ export const streamAnthropic = (model, context, options) => {
231
231
  })();
232
232
  return stream;
233
233
  };
234
+ function isOAuthToken(apiKey) {
235
+ return apiKey.includes("sk-ant-oat");
236
+ }
234
237
  function createClient(model, apiKey, interleavedThinking) {
235
238
  const betaFeatures = ["fine-grained-tool-streaming-2025-05-14"];
236
239
  if (interleavedThinking) {
237
240
  betaFeatures.push("interleaved-thinking-2025-05-14");
238
241
  }
239
- if (apiKey.includes("sk-ant-oat")) {
242
+ const oauthToken = isOAuthToken(apiKey);
243
+ if (oauthToken) {
240
244
  const defaultHeaders = {
241
245
  accept: "application/json",
242
246
  "anthropic-dangerous-direct-browser-access": "true",
@@ -252,26 +256,24 @@ function createClient(model, apiKey, interleavedThinking) {
252
256
  });
253
257
  return { client, isOAuthToken: true };
254
258
  }
255
- else {
256
- const defaultHeaders = {
257
- accept: "application/json",
258
- "anthropic-dangerous-direct-browser-access": "true",
259
- "anthropic-beta": betaFeatures.join(","),
260
- ...(model.headers || {}),
261
- };
262
- const client = new Anthropic({
263
- apiKey,
264
- baseURL: model.baseUrl,
265
- dangerouslyAllowBrowser: true,
266
- defaultHeaders,
267
- });
268
- return { client, isOAuthToken: false };
269
- }
259
+ const defaultHeaders = {
260
+ accept: "application/json",
261
+ "anthropic-dangerous-direct-browser-access": "true",
262
+ "anthropic-beta": betaFeatures.join(","),
263
+ ...(model.headers || {}),
264
+ };
265
+ const client = new Anthropic({
266
+ apiKey,
267
+ baseURL: model.baseUrl,
268
+ dangerouslyAllowBrowser: true,
269
+ defaultHeaders,
270
+ });
271
+ return { client, isOAuthToken: false };
270
272
  }
271
273
  function buildParams(model, context, isOAuthToken, options) {
272
274
  const params = {
273
275
  model: model.id,
274
- messages: convertMessages(context.messages, model),
276
+ messages: convertMessages(context.messages, model, isOAuthToken),
275
277
  max_tokens: options?.maxTokens || (model.maxTokens / 3) | 0,
276
278
  stream: true,
277
279
  };
@@ -312,7 +314,7 @@ function buildParams(model, context, isOAuthToken, options) {
312
314
  params.temperature = options.temperature;
313
315
  }
314
316
  if (context.tools) {
315
- params.tools = convertTools(context.tools);
317
+ params.tools = convertTools(context.tools, isOAuthToken);
316
318
  }
317
319
  if (options?.thinkingEnabled && model.reasoning) {
318
320
  params.thinking = {
@@ -335,7 +337,7 @@ function sanitizeToolCallId(id) {
335
337
  // Replace any character that isn't alphanumeric, underscore, or hyphen with underscore
336
338
  return id.replace(/[^a-zA-Z0-9_-]/g, "_");
337
339
  }
338
- function convertMessages(messages, model) {
340
+ function convertMessages(messages, model, isOAuthToken) {
339
341
  const params = [];
340
342
  // Transform messages for cross-provider compatibility
341
343
  const transformedMessages = transformMessages(messages, model);
@@ -419,7 +421,7 @@ function convertMessages(messages, model) {
419
421
  blocks.push({
420
422
  type: "tool_use",
421
423
  id: sanitizeToolCallId(block.id),
422
- name: block.name,
424
+ name: isOAuthToken ? `mcp_${block.name}` : block.name,
423
425
  input: block.arguments,
424
426
  });
425
427
  }
@@ -478,13 +480,13 @@ function convertMessages(messages, model) {
478
480
  }
479
481
  return params;
480
482
  }
481
- function convertTools(tools) {
483
+ function convertTools(tools, isOAuthToken) {
482
484
  if (!tools)
483
485
  return [];
484
486
  return tools.map((tool) => {
485
487
  const jsonSchema = tool.parameters; // TypeBox already generates JSON Schema
486
488
  return {
487
- name: tool.name,
489
+ name: isOAuthToken ? `mcp_${tool.name}` : tool.name,
488
490
  description: tool.description,
489
491
  input_schema: {
490
492
  type: "object",
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["import Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n\tContentBlockParam,\n\tMessageCreateParamsStreaming,\n\tMessageParam,\n} from \"@anthropic-ai/sdk/resources/messages.js\";\nimport { calculateCost } from \"../models.js\";\nimport { getEnvApiKey } from \"../stream.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tImageContent,\n\tMessage,\n\tModel,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\n\nimport { transformMessages } from \"./transorm-messages.js\";\n\n/**\n * Convert content blocks to Anthropic API format\n */\nfunction convertContentBlocks(content: (TextContent | ImageContent)[]):\n\t| string\n\t| Array<\n\t\t\t| { type: \"text\"; text: string }\n\t\t\t| {\n\t\t\t\t\ttype: \"image\";\n\t\t\t\t\tsource: {\n\t\t\t\t\t\ttype: \"base64\";\n\t\t\t\t\t\tmedia_type: \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\";\n\t\t\t\t\t\tdata: string;\n\t\t\t\t\t};\n\t\t\t }\n\t > {\n\t// If only text blocks, return as concatenated string for simplicity\n\tconst hasImages = content.some((c) => c.type === \"image\");\n\tif (!hasImages) {\n\t\treturn sanitizeSurrogates(content.map((c) => (c as TextContent).text).join(\"\\n\"));\n\t}\n\n\t// If we have images, convert to content block array\n\tconst blocks = content.map((block) => {\n\t\tif (block.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: sanitizeSurrogates(block.text),\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image\" as const,\n\t\t\tsource: {\n\t\t\t\ttype: \"base64\" as const,\n\t\t\t\tmedia_type: block.mimeType as \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n\t\t\t\tdata: block.data,\n\t\t\t},\n\t\t};\n\t});\n\n\t// If only images (no text), add placeholder text block\n\tconst hasText = blocks.some((b) => b.type === \"text\");\n\tif (!hasText) {\n\t\tblocks.unshift({\n\t\t\ttype: \"text\" as const,\n\t\t\ttext: \"(see attached image)\",\n\t\t});\n\t}\n\n\treturn blocks;\n}\n\nexport interface AnthropicOptions extends StreamOptions {\n\tthinkingEnabled?: boolean;\n\tthinkingBudgetTokens?: number;\n\tinterleavedThinking?: boolean;\n\ttoolChoice?: \"auto\" | \"any\" | \"none\" | { type: \"tool\"; name: string };\n}\n\nexport const streamAnthropic: StreamFunction<\"anthropic-messages\"> = (\n\tmodel: Model<\"anthropic-messages\">,\n\tcontext: Context,\n\toptions?: AnthropicOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"anthropic-messages\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? \"\";\n\t\t\tconst { client, isOAuthToken } = createClient(model, apiKey, options?.interleavedThinking ?? true);\n\t\t\tconst params = buildParams(model, context, isOAuthToken, options);\n\t\t\tconst anthropicStream = client.messages.stream({ ...params, stream: true }, { signal: options?.signal });\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\ttype Block = (ThinkingContent | TextContent | (ToolCall & { partialJson: string })) & { index: number };\n\t\t\tconst blocks = output.content as Block[];\n\n\t\t\tfor await (const event of anthropicStream) {\n\t\t\t\tif (event.type === \"message_start\") {\n\t\t\t\t\t// Capture initial token usage from message_start event\n\t\t\t\t\t// This ensures we have input token counts even if the stream is aborted early\n\t\t\t\t\toutput.usage.input = event.message.usage.input_tokens || 0;\n\t\t\t\t\toutput.usage.output = event.message.usage.output_tokens || 0;\n\t\t\t\t\toutput.usage.cacheRead = event.message.usage.cache_read_input_tokens || 0;\n\t\t\t\t\toutput.usage.cacheWrite = event.message.usage.cache_creation_input_tokens || 0;\n\t\t\t\t\t// Anthropic doesn't provide total_tokens, compute from components\n\t\t\t\t\toutput.usage.totalTokens =\n\t\t\t\t\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t} else if (event.type === \"content_block_start\") {\n\t\t\t\t\tif (event.content_block.type === \"text\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t} else if (event.content_block.type === \"thinking\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: \"\",\n\t\t\t\t\t\t\tthinkingSignature: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t} else if (event.content_block.type === \"tool_use\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: event.content_block.id,\n\t\t\t\t\t\t\tname: event.content_block.name,\n\t\t\t\t\t\t\targuments: event.content_block.input as Record<string, any>,\n\t\t\t\t\t\t\tpartialJson: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"content_block_delta\") {\n\t\t\t\t\tif (event.delta.type === \"text_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"text\") {\n\t\t\t\t\t\t\tblock.text += event.delta.text;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.text,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"thinking_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"thinking\") {\n\t\t\t\t\t\t\tblock.thinking += event.delta.thinking;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.thinking,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"input_json_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"toolCall\") {\n\t\t\t\t\t\t\tblock.partialJson += event.delta.partial_json;\n\t\t\t\t\t\t\tblock.arguments = parseStreamingJson(block.partialJson);\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.partial_json,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"signature_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"thinking\") {\n\t\t\t\t\t\t\tblock.thinkingSignature = block.thinkingSignature || \"\";\n\t\t\t\t\t\t\tblock.thinkingSignature += event.delta.signature;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"content_block_stop\") {\n\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\tif (block) {\n\t\t\t\t\t\tdelete (block as any).index;\n\t\t\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tcontent: block.text,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tcontent: block.thinking,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\t\t\tblock.arguments = parseStreamingJson(block.partialJson);\n\t\t\t\t\t\t\tdelete (block as any).partialJson;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\ttoolCall: block,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"message_delta\") {\n\t\t\t\t\tif (event.delta.stop_reason) {\n\t\t\t\t\t\toutput.stopReason = mapStopReason(event.delta.stop_reason);\n\t\t\t\t\t}\n\t\t\t\t\toutput.usage.input = event.usage.input_tokens || 0;\n\t\t\t\t\toutput.usage.output = event.usage.output_tokens || 0;\n\t\t\t\t\toutput.usage.cacheRead = event.usage.cache_read_input_tokens || 0;\n\t\t\t\t\toutput.usage.cacheWrite = event.usage.cache_creation_input_tokens || 0;\n\t\t\t\t\t// Anthropic doesn't provide total_tokens, compute from components\n\t\t\t\t\toutput.usage.totalTokens =\n\t\t\t\t\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unkown error ocurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) delete (block as any).index;\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction createClient(\n\tmodel: Model<\"anthropic-messages\">,\n\tapiKey: string,\n\tinterleavedThinking: boolean,\n): { client: Anthropic; isOAuthToken: boolean } {\n\tconst betaFeatures = [\"fine-grained-tool-streaming-2025-05-14\"];\n\tif (interleavedThinking) {\n\t\tbetaFeatures.push(\"interleaved-thinking-2025-05-14\");\n\t}\n\n\tif (apiKey.includes(\"sk-ant-oat\")) {\n\t\tconst defaultHeaders = {\n\t\t\taccept: \"application/json\",\n\t\t\t\"anthropic-dangerous-direct-browser-access\": \"true\",\n\t\t\t\"anthropic-beta\": `oauth-2025-04-20,${betaFeatures.join(\",\")}`,\n\t\t\t...(model.headers || {}),\n\t\t};\n\n\t\tconst client = new Anthropic({\n\t\t\tapiKey: null,\n\t\t\tauthToken: apiKey,\n\t\t\tbaseURL: model.baseUrl,\n\t\t\tdefaultHeaders,\n\t\t\tdangerouslyAllowBrowser: true,\n\t\t});\n\n\t\treturn { client, isOAuthToken: true };\n\t} else {\n\t\tconst defaultHeaders = {\n\t\t\taccept: \"application/json\",\n\t\t\t\"anthropic-dangerous-direct-browser-access\": \"true\",\n\t\t\t\"anthropic-beta\": betaFeatures.join(\",\"),\n\t\t\t...(model.headers || {}),\n\t\t};\n\n\t\tconst client = new Anthropic({\n\t\t\tapiKey,\n\t\t\tbaseURL: model.baseUrl,\n\t\t\tdangerouslyAllowBrowser: true,\n\t\t\tdefaultHeaders,\n\t\t});\n\n\t\treturn { client, isOAuthToken: false };\n\t}\n}\n\nfunction buildParams(\n\tmodel: Model<\"anthropic-messages\">,\n\tcontext: Context,\n\tisOAuthToken: boolean,\n\toptions?: AnthropicOptions,\n): MessageCreateParamsStreaming {\n\tconst params: MessageCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tmessages: convertMessages(context.messages, model),\n\t\tmax_tokens: options?.maxTokens || (model.maxTokens / 3) | 0,\n\t\tstream: true,\n\t};\n\n\t// For OAuth tokens, we MUST include Claude Code identity\n\tif (isOAuthToken) {\n\t\tparams.system = [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: \"You are Claude Code, Anthropic's official CLI for Claude.\",\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t\tif (context.systemPrompt) {\n\t\t\tparams.system.push({\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(context.systemPrompt),\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t} else if (context.systemPrompt) {\n\t\t// Add cache control to system prompt for non-OAuth tokens\n\t\tparams.system = [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(context.systemPrompt),\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options.temperature;\n\t}\n\n\tif (context.tools) {\n\t\tparams.tools = convertTools(context.tools);\n\t}\n\n\tif (options?.thinkingEnabled && model.reasoning) {\n\t\tparams.thinking = {\n\t\t\ttype: \"enabled\",\n\t\t\tbudget_tokens: options.thinkingBudgetTokens || 1024,\n\t\t};\n\t}\n\n\tif (options?.toolChoice) {\n\t\tif (typeof options.toolChoice === \"string\") {\n\t\t\tparams.tool_choice = { type: options.toolChoice };\n\t\t} else {\n\t\t\tparams.tool_choice = options.toolChoice;\n\t\t}\n\t}\n\n\treturn params;\n}\n\n// Sanitize tool call IDs to match Anthropic's required pattern: ^[a-zA-Z0-9_-]+$\nfunction sanitizeToolCallId(id: string): string {\n\t// Replace any character that isn't alphanumeric, underscore, or hyphen with underscore\n\treturn id.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n}\n\nfunction convertMessages(messages: Message[], model: Model<\"anthropic-messages\">): MessageParam[] {\n\tconst params: MessageParam[] = [];\n\n\t// Transform messages for cross-provider compatibility\n\tconst transformedMessages = transformMessages(messages, model);\n\n\tfor (let i = 0; i < transformedMessages.length; i++) {\n\t\tconst msg = transformedMessages[i];\n\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tif (msg.content.trim().length > 0) {\n\t\t\t\t\tparams.push({\n\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\tcontent: sanitizeSurrogates(msg.content),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst blocks: ContentBlockParam[] = msg.content.map((item) => {\n\t\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\t\ttype: \"base64\",\n\t\t\t\t\t\t\t\tmedia_type: item.mimeType as \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n\t\t\t\t\t\t\t\tdata: item.data,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tlet filteredBlocks = !model?.input.includes(\"image\") ? blocks.filter((b) => b.type !== \"image\") : blocks;\n\t\t\t\tfilteredBlocks = filteredBlocks.filter((b) => {\n\t\t\t\t\tif (b.type === \"text\") {\n\t\t\t\t\t\treturn b.text.trim().length > 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\tif (filteredBlocks.length === 0) continue;\n\t\t\t\tparams.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: filteredBlocks,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst blocks: ContentBlockParam[] = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (block.text.trim().length === 0) continue;\n\t\t\t\t\tblocks.push({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: sanitizeSurrogates(block.text),\n\t\t\t\t\t});\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tif (block.thinking.trim().length === 0) continue;\n\t\t\t\t\t// If thinking signature is missing/empty (e.g., from aborted stream),\n\t\t\t\t\t// convert to plain text block without <thinking> tags to avoid API rejection\n\t\t\t\t\t// and prevent Claude from mimicking the tags in responses\n\t\t\t\t\tif (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) {\n\t\t\t\t\t\tblocks.push({\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(block.thinking),\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tblocks.push({\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: sanitizeSurrogates(block.thinking),\n\t\t\t\t\t\t\tsignature: block.thinkingSignature,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tblocks.push({\n\t\t\t\t\t\ttype: \"tool_use\",\n\t\t\t\t\t\tid: sanitizeToolCallId(block.id),\n\t\t\t\t\t\tname: block.name,\n\t\t\t\t\t\tinput: block.arguments,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (blocks.length === 0) continue;\n\t\t\tparams.push({\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: blocks,\n\t\t\t});\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\t// Collect all consecutive toolResult messages, needed for z.ai Anthropic endpoint\n\t\t\tconst toolResults: ContentBlockParam[] = [];\n\n\t\t\t// Add the current tool result\n\t\t\ttoolResults.push({\n\t\t\t\ttype: \"tool_result\",\n\t\t\t\ttool_use_id: sanitizeToolCallId(msg.toolCallId),\n\t\t\t\tcontent: convertContentBlocks(msg.content),\n\t\t\t\tis_error: msg.isError,\n\t\t\t});\n\n\t\t\t// Look ahead for consecutive toolResult messages\n\t\t\tlet j = i + 1;\n\t\t\twhile (j < transformedMessages.length && transformedMessages[j].role === \"toolResult\") {\n\t\t\t\tconst nextMsg = transformedMessages[j] as ToolResultMessage; // We know it's a toolResult\n\t\t\t\ttoolResults.push({\n\t\t\t\t\ttype: \"tool_result\",\n\t\t\t\t\ttool_use_id: sanitizeToolCallId(nextMsg.toolCallId),\n\t\t\t\t\tcontent: convertContentBlocks(nextMsg.content),\n\t\t\t\t\tis_error: nextMsg.isError,\n\t\t\t\t});\n\t\t\t\tj++;\n\t\t\t}\n\n\t\t\t// Skip the messages we've already processed\n\t\t\ti = j - 1;\n\n\t\t\t// Add a single user message with all tool results\n\t\t\tparams.push({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: toolResults,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Add cache_control to the last user message to cache conversation history\n\tif (params.length > 0) {\n\t\tconst lastMessage = params[params.length - 1];\n\t\tif (lastMessage.role === \"user\") {\n\t\t\t// Add cache control to the last content block\n\t\t\tif (Array.isArray(lastMessage.content)) {\n\t\t\t\tconst lastBlock = lastMessage.content[lastMessage.content.length - 1];\n\t\t\t\tif (\n\t\t\t\t\tlastBlock &&\n\t\t\t\t\t(lastBlock.type === \"text\" || lastBlock.type === \"image\" || lastBlock.type === \"tool_result\")\n\t\t\t\t) {\n\t\t\t\t\t(lastBlock as any).cache_control = { type: \"ephemeral\" };\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn params;\n}\n\nfunction convertTools(tools: Tool[]): Anthropic.Messages.Tool[] {\n\tif (!tools) return [];\n\n\treturn tools.map((tool) => {\n\t\tconst jsonSchema = tool.parameters as any; // TypeBox already generates JSON Schema\n\n\t\treturn {\n\t\t\tname: tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tinput_schema: {\n\t\t\t\ttype: \"object\" as const,\n\t\t\t\tproperties: jsonSchema.properties || {},\n\t\t\t\trequired: jsonSchema.required || [],\n\t\t\t},\n\t\t};\n\t});\n}\n\nfunction mapStopReason(reason: Anthropic.Messages.StopReason): StopReason {\n\tswitch (reason) {\n\t\tcase \"end_turn\":\n\t\t\treturn \"stop\";\n\t\tcase \"max_tokens\":\n\t\t\treturn \"length\";\n\t\tcase \"tool_use\":\n\t\t\treturn \"toolUse\";\n\t\tcase \"refusal\":\n\t\t\treturn \"error\";\n\t\tcase \"pause_turn\": // Stop is good enough -> resubmit\n\t\t\treturn \"stop\";\n\t\tcase \"stop_sequence\":\n\t\t\treturn \"stop\"; // We don't supply stop sequences, so this should never happen\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = reason;\n\t\t\tthrow new Error(`Unhandled stop reason: ${_exhaustive}`);\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../src/providers/anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["import Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n\tContentBlockParam,\n\tMessageCreateParamsStreaming,\n\tMessageParam,\n} from \"@anthropic-ai/sdk/resources/messages.js\";\nimport { calculateCost } from \"../models.js\";\nimport { getEnvApiKey } from \"../stream.js\";\nimport type {\n\tApi,\n\tAssistantMessage,\n\tContext,\n\tImageContent,\n\tMessage,\n\tModel,\n\tStopReason,\n\tStreamFunction,\n\tStreamOptions,\n\tTextContent,\n\tThinkingContent,\n\tTool,\n\tToolCall,\n\tToolResultMessage,\n} from \"../types.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { parseStreamingJson } from \"../utils/json-parse.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\n\nimport { transformMessages } from \"./transorm-messages.js\";\n\n/**\n * Convert content blocks to Anthropic API format\n */\nfunction convertContentBlocks(content: (TextContent | ImageContent)[]):\n\t| string\n\t| Array<\n\t\t\t| { type: \"text\"; text: string }\n\t\t\t| {\n\t\t\t\t\ttype: \"image\";\n\t\t\t\t\tsource: {\n\t\t\t\t\t\ttype: \"base64\";\n\t\t\t\t\t\tmedia_type: \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\";\n\t\t\t\t\t\tdata: string;\n\t\t\t\t\t};\n\t\t\t }\n\t > {\n\t// If only text blocks, return as concatenated string for simplicity\n\tconst hasImages = content.some((c) => c.type === \"image\");\n\tif (!hasImages) {\n\t\treturn sanitizeSurrogates(content.map((c) => (c as TextContent).text).join(\"\\n\"));\n\t}\n\n\t// If we have images, convert to content block array\n\tconst blocks = content.map((block) => {\n\t\tif (block.type === \"text\") {\n\t\t\treturn {\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: sanitizeSurrogates(block.text),\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\ttype: \"image\" as const,\n\t\t\tsource: {\n\t\t\t\ttype: \"base64\" as const,\n\t\t\t\tmedia_type: block.mimeType as \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n\t\t\t\tdata: block.data,\n\t\t\t},\n\t\t};\n\t});\n\n\t// If only images (no text), add placeholder text block\n\tconst hasText = blocks.some((b) => b.type === \"text\");\n\tif (!hasText) {\n\t\tblocks.unshift({\n\t\t\ttype: \"text\" as const,\n\t\t\ttext: \"(see attached image)\",\n\t\t});\n\t}\n\n\treturn blocks;\n}\n\nexport interface AnthropicOptions extends StreamOptions {\n\tthinkingEnabled?: boolean;\n\tthinkingBudgetTokens?: number;\n\tinterleavedThinking?: boolean;\n\ttoolChoice?: \"auto\" | \"any\" | \"none\" | { type: \"tool\"; name: string };\n}\n\nexport const streamAnthropic: StreamFunction<\"anthropic-messages\"> = (\n\tmodel: Model<\"anthropic-messages\">,\n\tcontext: Context,\n\toptions?: AnthropicOptions,\n): AssistantMessageEventStream => {\n\tconst stream = new AssistantMessageEventStream();\n\n\t(async () => {\n\t\tconst output: AssistantMessage = {\n\t\t\trole: \"assistant\",\n\t\t\tcontent: [],\n\t\t\tapi: \"anthropic-messages\" as Api,\n\t\t\tprovider: model.provider,\n\t\t\tmodel: model.id,\n\t\t\tusage: {\n\t\t\t\tinput: 0,\n\t\t\t\toutput: 0,\n\t\t\t\tcacheRead: 0,\n\t\t\t\tcacheWrite: 0,\n\t\t\t\ttotalTokens: 0,\n\t\t\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t\t\t},\n\t\t\tstopReason: \"stop\",\n\t\t\ttimestamp: Date.now(),\n\t\t};\n\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey ?? getEnvApiKey(model.provider) ?? \"\";\n\t\t\tconst { client, isOAuthToken } = createClient(model, apiKey, options?.interleavedThinking ?? true);\n\t\t\tconst params = buildParams(model, context, isOAuthToken, options);\n\t\t\tconst anthropicStream = client.messages.stream({ ...params, stream: true }, { signal: options?.signal });\n\t\t\tstream.push({ type: \"start\", partial: output });\n\n\t\t\ttype Block = (ThinkingContent | TextContent | (ToolCall & { partialJson: string })) & { index: number };\n\t\t\tconst blocks = output.content as Block[];\n\n\t\t\tfor await (const event of anthropicStream) {\n\t\t\t\tif (event.type === \"message_start\") {\n\t\t\t\t\t// Capture initial token usage from message_start event\n\t\t\t\t\t// This ensures we have input token counts even if the stream is aborted early\n\t\t\t\t\toutput.usage.input = event.message.usage.input_tokens || 0;\n\t\t\t\t\toutput.usage.output = event.message.usage.output_tokens || 0;\n\t\t\t\t\toutput.usage.cacheRead = event.message.usage.cache_read_input_tokens || 0;\n\t\t\t\t\toutput.usage.cacheWrite = event.message.usage.cache_creation_input_tokens || 0;\n\t\t\t\t\t// Anthropic doesn't provide total_tokens, compute from components\n\t\t\t\t\toutput.usage.totalTokens =\n\t\t\t\t\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t} else if (event.type === \"content_block_start\") {\n\t\t\t\t\tif (event.content_block.type === \"text\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"text_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t} else if (event.content_block.type === \"thinking\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: \"\",\n\t\t\t\t\t\t\tthinkingSignature: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"thinking_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t} else if (event.content_block.type === \"tool_use\") {\n\t\t\t\t\t\tconst block: Block = {\n\t\t\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\t\t\tid: event.content_block.id,\n\t\t\t\t\t\t\tname: isOAuthToken ? event.content_block.name.substring(4) : event.content_block.name,\n\t\t\t\t\t\t\targuments: event.content_block.input as Record<string, any>,\n\t\t\t\t\t\t\tpartialJson: \"\",\n\t\t\t\t\t\t\tindex: event.index,\n\t\t\t\t\t\t};\n\t\t\t\t\t\toutput.content.push(block);\n\t\t\t\t\t\tstream.push({ type: \"toolcall_start\", contentIndex: output.content.length - 1, partial: output });\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"content_block_delta\") {\n\t\t\t\t\tif (event.delta.type === \"text_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"text\") {\n\t\t\t\t\t\t\tblock.text += event.delta.text;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.text,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"thinking_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"thinking\") {\n\t\t\t\t\t\t\tblock.thinking += event.delta.thinking;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.thinking,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"input_json_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"toolCall\") {\n\t\t\t\t\t\t\tblock.partialJson += event.delta.partial_json;\n\t\t\t\t\t\t\tblock.arguments = parseStreamingJson(block.partialJson);\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tdelta: event.delta.partial_json,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (event.delta.type === \"signature_delta\") {\n\t\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\t\tif (block && block.type === \"thinking\") {\n\t\t\t\t\t\t\tblock.thinkingSignature = block.thinkingSignature || \"\";\n\t\t\t\t\t\t\tblock.thinkingSignature += event.delta.signature;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"content_block_stop\") {\n\t\t\t\t\tconst index = blocks.findIndex((b) => b.index === event.index);\n\t\t\t\t\tconst block = blocks[index];\n\t\t\t\t\tif (block) {\n\t\t\t\t\t\tdelete (block as any).index;\n\t\t\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"text_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tcontent: block.text,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"thinking_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\tcontent: block.thinking,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\t\t\tblock.arguments = parseStreamingJson(block.partialJson);\n\t\t\t\t\t\t\tdelete (block as any).partialJson;\n\t\t\t\t\t\t\tstream.push({\n\t\t\t\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\t\t\t\tcontentIndex: index,\n\t\t\t\t\t\t\t\ttoolCall: block,\n\t\t\t\t\t\t\t\tpartial: output,\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (event.type === \"message_delta\") {\n\t\t\t\t\tif (event.delta.stop_reason) {\n\t\t\t\t\t\toutput.stopReason = mapStopReason(event.delta.stop_reason);\n\t\t\t\t\t}\n\t\t\t\t\toutput.usage.input = event.usage.input_tokens || 0;\n\t\t\t\t\toutput.usage.output = event.usage.output_tokens || 0;\n\t\t\t\t\toutput.usage.cacheRead = event.usage.cache_read_input_tokens || 0;\n\t\t\t\t\toutput.usage.cacheWrite = event.usage.cache_creation_input_tokens || 0;\n\t\t\t\t\t// Anthropic doesn't provide total_tokens, compute from components\n\t\t\t\t\toutput.usage.totalTokens =\n\t\t\t\t\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n\t\t\t\t\tcalculateCost(model, output.usage);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options?.signal?.aborted) {\n\t\t\t\tthrow new Error(\"Request was aborted\");\n\t\t\t}\n\n\t\t\tif (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n\t\t\t\tthrow new Error(\"An unkown error ocurred\");\n\t\t\t}\n\n\t\t\tstream.push({ type: \"done\", reason: output.stopReason, message: output });\n\t\t\tstream.end();\n\t\t} catch (error) {\n\t\t\tfor (const block of output.content) delete (block as any).index;\n\t\t\toutput.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n\t\t\toutput.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);\n\t\t\tstream.push({ type: \"error\", reason: output.stopReason, error: output });\n\t\t\tstream.end();\n\t\t}\n\t})();\n\n\treturn stream;\n};\n\nfunction isOAuthToken(apiKey: string): boolean {\n\treturn apiKey.includes(\"sk-ant-oat\");\n}\n\nfunction createClient(\n\tmodel: Model<\"anthropic-messages\">,\n\tapiKey: string,\n\tinterleavedThinking: boolean,\n): { client: Anthropic; isOAuthToken: boolean } {\n\tconst betaFeatures = [\"fine-grained-tool-streaming-2025-05-14\"];\n\tif (interleavedThinking) {\n\t\tbetaFeatures.push(\"interleaved-thinking-2025-05-14\");\n\t}\n\n\tconst oauthToken = isOAuthToken(apiKey);\n\tif (oauthToken) {\n\t\tconst defaultHeaders = {\n\t\t\taccept: \"application/json\",\n\t\t\t\"anthropic-dangerous-direct-browser-access\": \"true\",\n\t\t\t\"anthropic-beta\": `oauth-2025-04-20,${betaFeatures.join(\",\")}`,\n\t\t\t...(model.headers || {}),\n\t\t};\n\n\t\tconst client = new Anthropic({\n\t\t\tapiKey: null,\n\t\t\tauthToken: apiKey,\n\t\t\tbaseURL: model.baseUrl,\n\t\t\tdefaultHeaders,\n\t\t\tdangerouslyAllowBrowser: true,\n\t\t});\n\n\t\treturn { client, isOAuthToken: true };\n\t}\n\n\tconst defaultHeaders = {\n\t\taccept: \"application/json\",\n\t\t\"anthropic-dangerous-direct-browser-access\": \"true\",\n\t\t\"anthropic-beta\": betaFeatures.join(\",\"),\n\t\t...(model.headers || {}),\n\t};\n\n\tconst client = new Anthropic({\n\t\tapiKey,\n\t\tbaseURL: model.baseUrl,\n\t\tdangerouslyAllowBrowser: true,\n\t\tdefaultHeaders,\n\t});\n\n\treturn { client, isOAuthToken: false };\n}\n\nfunction buildParams(\n\tmodel: Model<\"anthropic-messages\">,\n\tcontext: Context,\n\tisOAuthToken: boolean,\n\toptions?: AnthropicOptions,\n): MessageCreateParamsStreaming {\n\tconst params: MessageCreateParamsStreaming = {\n\t\tmodel: model.id,\n\t\tmessages: convertMessages(context.messages, model, isOAuthToken),\n\t\tmax_tokens: options?.maxTokens || (model.maxTokens / 3) | 0,\n\t\tstream: true,\n\t};\n\n\t// For OAuth tokens, we MUST include Claude Code identity\n\tif (isOAuthToken) {\n\t\tparams.system = [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: \"You are Claude Code, Anthropic's official CLI for Claude.\",\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t\tif (context.systemPrompt) {\n\t\t\tparams.system.push({\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(context.systemPrompt),\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t} else if (context.systemPrompt) {\n\t\t// Add cache control to system prompt for non-OAuth tokens\n\t\tparams.system = [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: sanitizeSurrogates(context.systemPrompt),\n\t\t\t\tcache_control: {\n\t\t\t\t\ttype: \"ephemeral\",\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t}\n\n\tif (options?.temperature !== undefined) {\n\t\tparams.temperature = options.temperature;\n\t}\n\n\tif (context.tools) {\n\t\tparams.tools = convertTools(context.tools, isOAuthToken);\n\t}\n\n\tif (options?.thinkingEnabled && model.reasoning) {\n\t\tparams.thinking = {\n\t\t\ttype: \"enabled\",\n\t\t\tbudget_tokens: options.thinkingBudgetTokens || 1024,\n\t\t};\n\t}\n\n\tif (options?.toolChoice) {\n\t\tif (typeof options.toolChoice === \"string\") {\n\t\t\tparams.tool_choice = { type: options.toolChoice };\n\t\t} else {\n\t\t\tparams.tool_choice = options.toolChoice;\n\t\t}\n\t}\n\n\treturn params;\n}\n\n// Sanitize tool call IDs to match Anthropic's required pattern: ^[a-zA-Z0-9_-]+$\nfunction sanitizeToolCallId(id: string): string {\n\t// Replace any character that isn't alphanumeric, underscore, or hyphen with underscore\n\treturn id.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n}\n\nfunction convertMessages(\n\tmessages: Message[],\n\tmodel: Model<\"anthropic-messages\">,\n\tisOAuthToken: boolean,\n): MessageParam[] {\n\tconst params: MessageParam[] = [];\n\n\t// Transform messages for cross-provider compatibility\n\tconst transformedMessages = transformMessages(messages, model);\n\n\tfor (let i = 0; i < transformedMessages.length; i++) {\n\t\tconst msg = transformedMessages[i];\n\n\t\tif (msg.role === \"user\") {\n\t\t\tif (typeof msg.content === \"string\") {\n\t\t\t\tif (msg.content.trim().length > 0) {\n\t\t\t\t\tparams.push({\n\t\t\t\t\t\trole: \"user\",\n\t\t\t\t\t\tcontent: sanitizeSurrogates(msg.content),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst blocks: ContentBlockParam[] = msg.content.map((item) => {\n\t\t\t\t\tif (item.type === \"text\") {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(item.text),\n\t\t\t\t\t\t};\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\ttype: \"image\",\n\t\t\t\t\t\t\tsource: {\n\t\t\t\t\t\t\t\ttype: \"base64\",\n\t\t\t\t\t\t\t\tmedia_type: item.mimeType as \"image/jpeg\" | \"image/png\" | \"image/gif\" | \"image/webp\",\n\t\t\t\t\t\t\t\tdata: item.data,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tlet filteredBlocks = !model?.input.includes(\"image\") ? blocks.filter((b) => b.type !== \"image\") : blocks;\n\t\t\t\tfilteredBlocks = filteredBlocks.filter((b) => {\n\t\t\t\t\tif (b.type === \"text\") {\n\t\t\t\t\t\treturn b.text.trim().length > 0;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t});\n\t\t\t\tif (filteredBlocks.length === 0) continue;\n\t\t\t\tparams.push({\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: filteredBlocks,\n\t\t\t\t});\n\t\t\t}\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst blocks: ContentBlockParam[] = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\tif (block.text.trim().length === 0) continue;\n\t\t\t\t\tblocks.push({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: sanitizeSurrogates(block.text),\n\t\t\t\t\t});\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tif (block.thinking.trim().length === 0) continue;\n\t\t\t\t\t// If thinking signature is missing/empty (e.g., from aborted stream),\n\t\t\t\t\t// convert to plain text block without <thinking> tags to avoid API rejection\n\t\t\t\t\t// and prevent Claude from mimicking the tags in responses\n\t\t\t\t\tif (!block.thinkingSignature || block.thinkingSignature.trim().length === 0) {\n\t\t\t\t\t\tblocks.push({\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: sanitizeSurrogates(block.thinking),\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tblocks.push({\n\t\t\t\t\t\t\ttype: \"thinking\",\n\t\t\t\t\t\t\tthinking: sanitizeSurrogates(block.thinking),\n\t\t\t\t\t\t\tsignature: block.thinkingSignature,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tblocks.push({\n\t\t\t\t\t\ttype: \"tool_use\",\n\t\t\t\t\t\tid: sanitizeToolCallId(block.id),\n\t\t\t\t\t\tname: isOAuthToken ? `mcp_${block.name}` : block.name,\n\t\t\t\t\t\tinput: block.arguments,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (blocks.length === 0) continue;\n\t\t\tparams.push({\n\t\t\t\trole: \"assistant\",\n\t\t\t\tcontent: blocks,\n\t\t\t});\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\t// Collect all consecutive toolResult messages, needed for z.ai Anthropic endpoint\n\t\t\tconst toolResults: ContentBlockParam[] = [];\n\n\t\t\t// Add the current tool result\n\t\t\ttoolResults.push({\n\t\t\t\ttype: \"tool_result\",\n\t\t\t\ttool_use_id: sanitizeToolCallId(msg.toolCallId),\n\t\t\t\tcontent: convertContentBlocks(msg.content),\n\t\t\t\tis_error: msg.isError,\n\t\t\t});\n\n\t\t\t// Look ahead for consecutive toolResult messages\n\t\t\tlet j = i + 1;\n\t\t\twhile (j < transformedMessages.length && transformedMessages[j].role === \"toolResult\") {\n\t\t\t\tconst nextMsg = transformedMessages[j] as ToolResultMessage; // We know it's a toolResult\n\t\t\t\ttoolResults.push({\n\t\t\t\t\ttype: \"tool_result\",\n\t\t\t\t\ttool_use_id: sanitizeToolCallId(nextMsg.toolCallId),\n\t\t\t\t\tcontent: convertContentBlocks(nextMsg.content),\n\t\t\t\t\tis_error: nextMsg.isError,\n\t\t\t\t});\n\t\t\t\tj++;\n\t\t\t}\n\n\t\t\t// Skip the messages we've already processed\n\t\t\ti = j - 1;\n\n\t\t\t// Add a single user message with all tool results\n\t\t\tparams.push({\n\t\t\t\trole: \"user\",\n\t\t\t\tcontent: toolResults,\n\t\t\t});\n\t\t}\n\t}\n\n\t// Add cache_control to the last user message to cache conversation history\n\tif (params.length > 0) {\n\t\tconst lastMessage = params[params.length - 1];\n\t\tif (lastMessage.role === \"user\") {\n\t\t\t// Add cache control to the last content block\n\t\t\tif (Array.isArray(lastMessage.content)) {\n\t\t\t\tconst lastBlock = lastMessage.content[lastMessage.content.length - 1];\n\t\t\t\tif (\n\t\t\t\t\tlastBlock &&\n\t\t\t\t\t(lastBlock.type === \"text\" || lastBlock.type === \"image\" || lastBlock.type === \"tool_result\")\n\t\t\t\t) {\n\t\t\t\t\t(lastBlock as any).cache_control = { type: \"ephemeral\" };\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn params;\n}\n\nfunction convertTools(tools: Tool[], isOAuthToken: boolean): Anthropic.Messages.Tool[] {\n\tif (!tools) return [];\n\n\treturn tools.map((tool) => {\n\t\tconst jsonSchema = tool.parameters as any; // TypeBox already generates JSON Schema\n\n\t\treturn {\n\t\t\tname: isOAuthToken ? `mcp_${tool.name}` : tool.name,\n\t\t\tdescription: tool.description,\n\t\t\tinput_schema: {\n\t\t\t\ttype: \"object\" as const,\n\t\t\t\tproperties: jsonSchema.properties || {},\n\t\t\t\trequired: jsonSchema.required || [],\n\t\t\t},\n\t\t};\n\t});\n}\n\nfunction mapStopReason(reason: Anthropic.Messages.StopReason): StopReason {\n\tswitch (reason) {\n\t\tcase \"end_turn\":\n\t\t\treturn \"stop\";\n\t\tcase \"max_tokens\":\n\t\t\treturn \"length\";\n\t\tcase \"tool_use\":\n\t\t\treturn \"toolUse\";\n\t\tcase \"refusal\":\n\t\t\treturn \"error\";\n\t\tcase \"pause_turn\": // Stop is good enough -> resubmit\n\t\t\treturn \"stop\";\n\t\tcase \"stop_sequence\":\n\t\t\treturn \"stop\"; // We don't supply stop sequences, so this should never happen\n\t\tdefault: {\n\t\t\tconst _exhaustive: never = reason;\n\t\t\tthrow new Error(`Unhandled stop reason: ${_exhaustive}`);\n\t\t}\n\t}\n}\n"]}
@@ -8,7 +8,6 @@
8
8
  * - Google Cloud Code Assist (Gemini CLI)
9
9
  * - Antigravity (Gemini 3, Claude, GPT-OSS via Google Cloud)
10
10
  */
11
- export { loginAnthropic, refreshAnthropicToken } from "./anthropic.js";
12
11
  export { getGitHubCopilotBaseUrl, loginGitHubCopilot, normalizeDomain, refreshGitHubCopilotToken, } from "./github-copilot.js";
13
12
  export { loginAntigravity, refreshAntigravityToken, } from "./google-antigravity.js";
14
13
  export { loginGeminiCli, refreshGoogleCloudToken, } from "./google-gemini-cli.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvE,OAAO,EACN,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACN,gBAAgB,EAChB,uBAAuB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACN,cAAc,EACd,uBAAuB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACN,gBAAgB,EAChB,uBAAuB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,cAAc,YAAY,CAAC;AAW3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAErF;;;GAGG;AACH,wBAAsB,iBAAiB,CACtC,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,gBAAgB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CAkC3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CACnC,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAC3C,OAAO,CAAC;IAAE,cAAc,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAmBtE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,EAAE,CA4BvD","sourcesContent":["/**\n * OAuth credential management for AI providers.\n *\n * This module handles login, token refresh, and credential storage\n * for OAuth-based providers:\n * - Anthropic (Claude Pro/Max)\n * - GitHub Copilot\n * - Google Cloud Code Assist (Gemini CLI)\n * - Antigravity (Gemini 3, Claude, GPT-OSS via Google Cloud)\n */\n\n// Anthropic\nexport { loginAnthropic, refreshAnthropicToken } from \"./anthropic.js\";\n// GitHub Copilot\nexport {\n\tgetGitHubCopilotBaseUrl,\n\tloginGitHubCopilot,\n\tnormalizeDomain,\n\trefreshGitHubCopilotToken,\n} from \"./github-copilot.js\";\n// Google Antigravity\nexport {\n\tloginAntigravity,\n\trefreshAntigravityToken,\n} from \"./google-antigravity.js\";\n// Google Gemini CLI\nexport {\n\tloginGeminiCli,\n\trefreshGoogleCloudToken,\n} from \"./google-gemini-cli.js\";\n// OpenAI Codex (ChatGPT OAuth)\nexport {\n\tloginOpenAICodex,\n\trefreshOpenAICodexToken,\n} from \"./openai-codex.js\";\n\nexport * from \"./types.js\";\n\n// ============================================================================\n// High-level API\n// ============================================================================\n\nimport { refreshAnthropicToken } from \"./anthropic.js\";\nimport { refreshGitHubCopilotToken } from \"./github-copilot.js\";\nimport { refreshAntigravityToken } from \"./google-antigravity.js\";\nimport { refreshGoogleCloudToken } from \"./google-gemini-cli.js\";\nimport { refreshOpenAICodexToken } from \"./openai-codex.js\";\nimport type { OAuthCredentials, OAuthProvider, OAuthProviderInfo } from \"./types.js\";\n\n/**\n * Refresh token for any OAuth provider.\n * Saves the new credentials and returns the new access token.\n */\nexport async function refreshOAuthToken(\n\tprovider: OAuthProvider,\n\tcredentials: OAuthCredentials,\n): Promise<OAuthCredentials> {\n\tif (!credentials) {\n\t\tthrow new Error(`No OAuth credentials found for ${provider}`);\n\t}\n\n\tlet newCredentials: OAuthCredentials;\n\n\tswitch (provider) {\n\t\tcase \"anthropic\":\n\t\t\tnewCredentials = await refreshAnthropicToken(credentials.refresh);\n\t\t\tbreak;\n\t\tcase \"github-copilot\":\n\t\t\tnewCredentials = await refreshGitHubCopilotToken(credentials.refresh, credentials.enterpriseUrl);\n\t\t\tbreak;\n\t\tcase \"google-gemini-cli\":\n\t\t\tif (!credentials.projectId) {\n\t\t\t\tthrow new Error(\"Google Cloud credentials missing projectId\");\n\t\t\t}\n\t\t\tnewCredentials = await refreshGoogleCloudToken(credentials.refresh, credentials.projectId);\n\t\t\tbreak;\n\t\tcase \"google-antigravity\":\n\t\t\tif (!credentials.projectId) {\n\t\t\t\tthrow new Error(\"Antigravity credentials missing projectId\");\n\t\t\t}\n\t\t\tnewCredentials = await refreshAntigravityToken(credentials.refresh, credentials.projectId);\n\t\t\tbreak;\n\t\tcase \"openai-codex\":\n\t\t\tnewCredentials = await refreshOpenAICodexToken(credentials.refresh);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown OAuth provider: ${provider}`);\n\t}\n\n\treturn newCredentials;\n}\n\n/**\n * Get API key for a provider from OAuth credentials.\n * Automatically refreshes expired tokens.\n *\n * For google-gemini-cli and antigravity, returns JSON-encoded { token, projectId }\n *\n * @returns API key string, or null if no credentials\n * @throws Error if refresh fails\n */\nexport async function getOAuthApiKey(\n\tprovider: OAuthProvider,\n\tcredentials: Record<string, OAuthCredentials>,\n): Promise<{ newCredentials: OAuthCredentials; apiKey: string } | null> {\n\tlet creds = credentials[provider];\n\tif (!creds) {\n\t\treturn null;\n\t}\n\n\t// Refresh if expired\n\tif (Date.now() >= creds.expires) {\n\t\ttry {\n\t\t\tcreds = await refreshOAuthToken(provider, creds);\n\t\t} catch (_error) {\n\t\t\tthrow new Error(`Failed to refresh OAuth token for ${provider}`);\n\t\t}\n\t}\n\n\t// For providers that need projectId, return JSON\n\tconst needsProjectId = provider === \"google-gemini-cli\" || provider === \"google-antigravity\";\n\tconst apiKey = needsProjectId ? JSON.stringify({ token: creds.access, projectId: creds.projectId }) : creds.access;\n\treturn { newCredentials: creds, apiKey };\n}\n\n/**\n * Get list of OAuth providers\n */\nexport function getOAuthProviders(): OAuthProviderInfo[] {\n\treturn [\n\t\t{\n\t\t\tid: \"anthropic\",\n\t\t\tname: \"Anthropic (Claude Pro/Max)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"openai-codex\",\n\t\t\tname: \"ChatGPT Plus/Pro (Codex Subscription)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"github-copilot\",\n\t\t\tname: \"GitHub Copilot\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"google-gemini-cli\",\n\t\t\tname: \"Google Cloud Code Assist (Gemini CLI)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"google-antigravity\",\n\t\t\tname: \"Antigravity (Gemini 3, Claude, GPT-OSS)\",\n\t\t\tavailable: true,\n\t\t},\n\t];\n}\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EACN,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,GACzB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACN,gBAAgB,EAChB,uBAAuB,GACvB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACN,cAAc,EACd,uBAAuB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACN,gBAAgB,EAChB,uBAAuB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,cAAc,YAAY,CAAC;AAU3B,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAErF;;;GAGG;AACH,wBAAsB,iBAAiB,CACtC,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,gBAAgB,GAC3B,OAAO,CAAC,gBAAgB,CAAC,CA+B3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CACnC,QAAQ,EAAE,aAAa,EACvB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAC3C,OAAO,CAAC;IAAE,cAAc,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAmBtE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,iBAAiB,EAAE,CAuBvD","sourcesContent":["/**\n * OAuth credential management for AI providers.\n *\n * This module handles login, token refresh, and credential storage\n * for OAuth-based providers:\n * - Anthropic (Claude Pro/Max)\n * - GitHub Copilot\n * - Google Cloud Code Assist (Gemini CLI)\n * - Antigravity (Gemini 3, Claude, GPT-OSS via Google Cloud)\n */\n\n// GitHub Copilot\nexport {\n\tgetGitHubCopilotBaseUrl,\n\tloginGitHubCopilot,\n\tnormalizeDomain,\n\trefreshGitHubCopilotToken,\n} from \"./github-copilot.js\";\n// Google Antigravity\nexport {\n\tloginAntigravity,\n\trefreshAntigravityToken,\n} from \"./google-antigravity.js\";\n// Google Gemini CLI\nexport {\n\tloginGeminiCli,\n\trefreshGoogleCloudToken,\n} from \"./google-gemini-cli.js\";\n// OpenAI Codex (ChatGPT OAuth)\nexport {\n\tloginOpenAICodex,\n\trefreshOpenAICodexToken,\n} from \"./openai-codex.js\";\n\nexport * from \"./types.js\";\n\n// ============================================================================\n// High-level API\n// ============================================================================\n\nimport { refreshGitHubCopilotToken } from \"./github-copilot.js\";\nimport { refreshAntigravityToken } from \"./google-antigravity.js\";\nimport { refreshGoogleCloudToken } from \"./google-gemini-cli.js\";\nimport { refreshOpenAICodexToken } from \"./openai-codex.js\";\nimport type { OAuthCredentials, OAuthProvider, OAuthProviderInfo } from \"./types.js\";\n\n/**\n * Refresh token for any OAuth provider.\n * Saves the new credentials and returns the new access token.\n */\nexport async function refreshOAuthToken(\n\tprovider: OAuthProvider,\n\tcredentials: OAuthCredentials,\n): Promise<OAuthCredentials> {\n\tif (!credentials) {\n\t\tthrow new Error(`No OAuth credentials found for ${provider}`);\n\t}\n\n\tlet newCredentials: OAuthCredentials;\n\n\tswitch (provider) {\n\t\tcase \"github-copilot\":\n\t\t\tnewCredentials = await refreshGitHubCopilotToken(credentials.refresh, credentials.enterpriseUrl);\n\t\t\tbreak;\n\t\tcase \"google-gemini-cli\":\n\t\t\tif (!credentials.projectId) {\n\t\t\t\tthrow new Error(\"Google Cloud credentials missing projectId\");\n\t\t\t}\n\t\t\tnewCredentials = await refreshGoogleCloudToken(credentials.refresh, credentials.projectId);\n\t\t\tbreak;\n\t\tcase \"google-antigravity\":\n\t\t\tif (!credentials.projectId) {\n\t\t\t\tthrow new Error(\"Antigravity credentials missing projectId\");\n\t\t\t}\n\t\t\tnewCredentials = await refreshAntigravityToken(credentials.refresh, credentials.projectId);\n\t\t\tbreak;\n\t\tcase \"openai-codex\":\n\t\t\tnewCredentials = await refreshOpenAICodexToken(credentials.refresh);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown OAuth provider: ${provider}`);\n\t}\n\n\treturn newCredentials;\n}\n\n/**\n * Get API key for a provider from OAuth credentials.\n * Automatically refreshes expired tokens.\n *\n * For google-gemini-cli and antigravity, returns JSON-encoded { token, projectId }\n *\n * @returns API key string, or null if no credentials\n * @throws Error if refresh fails\n */\nexport async function getOAuthApiKey(\n\tprovider: OAuthProvider,\n\tcredentials: Record<string, OAuthCredentials>,\n): Promise<{ newCredentials: OAuthCredentials; apiKey: string } | null> {\n\tlet creds = credentials[provider];\n\tif (!creds) {\n\t\treturn null;\n\t}\n\n\t// Refresh if expired\n\tif (Date.now() >= creds.expires) {\n\t\ttry {\n\t\t\tcreds = await refreshOAuthToken(provider, creds);\n\t\t} catch (_error) {\n\t\t\tthrow new Error(`Failed to refresh OAuth token for ${provider}`);\n\t\t}\n\t}\n\n\t// For providers that need projectId, return JSON\n\tconst needsProjectId = provider === \"google-gemini-cli\" || provider === \"google-antigravity\";\n\tconst apiKey = needsProjectId ? JSON.stringify({ token: creds.access, projectId: creds.projectId }) : creds.access;\n\treturn { newCredentials: creds, apiKey };\n}\n\n/**\n * Get list of OAuth providers\n */\nexport function getOAuthProviders(): OAuthProviderInfo[] {\n\treturn [\n\t\t{\n\t\t\tid: \"openai-codex\",\n\t\t\tname: \"ChatGPT Plus/Pro (Codex Subscription)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"github-copilot\",\n\t\t\tname: \"GitHub Copilot\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"google-gemini-cli\",\n\t\t\tname: \"Google Cloud Code Assist (Gemini CLI)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"google-antigravity\",\n\t\t\tname: \"Antigravity (Gemini 3, Claude, GPT-OSS)\",\n\t\t\tavailable: true,\n\t\t},\n\t];\n}\n"]}
@@ -8,8 +8,6 @@
8
8
  * - Google Cloud Code Assist (Gemini CLI)
9
9
  * - Antigravity (Gemini 3, Claude, GPT-OSS via Google Cloud)
10
10
  */
11
- // Anthropic
12
- export { loginAnthropic, refreshAnthropicToken } from "./anthropic.js";
13
11
  // GitHub Copilot
14
12
  export { getGitHubCopilotBaseUrl, loginGitHubCopilot, normalizeDomain, refreshGitHubCopilotToken, } from "./github-copilot.js";
15
13
  // Google Antigravity
@@ -22,7 +20,6 @@ export * from "./types.js";
22
20
  // ============================================================================
23
21
  // High-level API
24
22
  // ============================================================================
25
- import { refreshAnthropicToken } from "./anthropic.js";
26
23
  import { refreshGitHubCopilotToken } from "./github-copilot.js";
27
24
  import { refreshAntigravityToken } from "./google-antigravity.js";
28
25
  import { refreshGoogleCloudToken } from "./google-gemini-cli.js";
@@ -37,9 +34,6 @@ export async function refreshOAuthToken(provider, credentials) {
37
34
  }
38
35
  let newCredentials;
39
36
  switch (provider) {
40
- case "anthropic":
41
- newCredentials = await refreshAnthropicToken(credentials.refresh);
42
- break;
43
37
  case "github-copilot":
44
38
  newCredentials = await refreshGitHubCopilotToken(credentials.refresh, credentials.enterpriseUrl);
45
39
  break;
@@ -96,11 +90,6 @@ export async function getOAuthApiKey(provider, credentials) {
96
90
  */
97
91
  export function getOAuthProviders() {
98
92
  return [
99
- {
100
- id: "anthropic",
101
- name: "Anthropic (Claude Pro/Max)",
102
- available: true,
103
- },
104
93
  {
105
94
  id: "openai-codex",
106
95
  name: "ChatGPT Plus/Pro (Codex Subscription)",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/oauth/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OAuth credential management for AI providers.\n *\n * This module handles login, token refresh, and credential storage\n * for OAuth-based providers:\n * - Anthropic (Claude Pro/Max)\n * - GitHub Copilot\n * - Google Cloud Code Assist (Gemini CLI)\n * - Antigravity (Gemini 3, Claude, GPT-OSS via Google Cloud)\n */\n\n// Anthropic\nexport { loginAnthropic, refreshAnthropicToken } from \"./anthropic.js\";\n// GitHub Copilot\nexport {\n\tgetGitHubCopilotBaseUrl,\n\tloginGitHubCopilot,\n\tnormalizeDomain,\n\trefreshGitHubCopilotToken,\n} from \"./github-copilot.js\";\n// Google Antigravity\nexport {\n\tloginAntigravity,\n\trefreshAntigravityToken,\n} from \"./google-antigravity.js\";\n// Google Gemini CLI\nexport {\n\tloginGeminiCli,\n\trefreshGoogleCloudToken,\n} from \"./google-gemini-cli.js\";\n// OpenAI Codex (ChatGPT OAuth)\nexport {\n\tloginOpenAICodex,\n\trefreshOpenAICodexToken,\n} from \"./openai-codex.js\";\n\nexport * from \"./types.js\";\n\n// ============================================================================\n// High-level API\n// ============================================================================\n\nimport { refreshAnthropicToken } from \"./anthropic.js\";\nimport { refreshGitHubCopilotToken } from \"./github-copilot.js\";\nimport { refreshAntigravityToken } from \"./google-antigravity.js\";\nimport { refreshGoogleCloudToken } from \"./google-gemini-cli.js\";\nimport { refreshOpenAICodexToken } from \"./openai-codex.js\";\nimport type { OAuthCredentials, OAuthProvider, OAuthProviderInfo } from \"./types.js\";\n\n/**\n * Refresh token for any OAuth provider.\n * Saves the new credentials and returns the new access token.\n */\nexport async function refreshOAuthToken(\n\tprovider: OAuthProvider,\n\tcredentials: OAuthCredentials,\n): Promise<OAuthCredentials> {\n\tif (!credentials) {\n\t\tthrow new Error(`No OAuth credentials found for ${provider}`);\n\t}\n\n\tlet newCredentials: OAuthCredentials;\n\n\tswitch (provider) {\n\t\tcase \"anthropic\":\n\t\t\tnewCredentials = await refreshAnthropicToken(credentials.refresh);\n\t\t\tbreak;\n\t\tcase \"github-copilot\":\n\t\t\tnewCredentials = await refreshGitHubCopilotToken(credentials.refresh, credentials.enterpriseUrl);\n\t\t\tbreak;\n\t\tcase \"google-gemini-cli\":\n\t\t\tif (!credentials.projectId) {\n\t\t\t\tthrow new Error(\"Google Cloud credentials missing projectId\");\n\t\t\t}\n\t\t\tnewCredentials = await refreshGoogleCloudToken(credentials.refresh, credentials.projectId);\n\t\t\tbreak;\n\t\tcase \"google-antigravity\":\n\t\t\tif (!credentials.projectId) {\n\t\t\t\tthrow new Error(\"Antigravity credentials missing projectId\");\n\t\t\t}\n\t\t\tnewCredentials = await refreshAntigravityToken(credentials.refresh, credentials.projectId);\n\t\t\tbreak;\n\t\tcase \"openai-codex\":\n\t\t\tnewCredentials = await refreshOpenAICodexToken(credentials.refresh);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown OAuth provider: ${provider}`);\n\t}\n\n\treturn newCredentials;\n}\n\n/**\n * Get API key for a provider from OAuth credentials.\n * Automatically refreshes expired tokens.\n *\n * For google-gemini-cli and antigravity, returns JSON-encoded { token, projectId }\n *\n * @returns API key string, or null if no credentials\n * @throws Error if refresh fails\n */\nexport async function getOAuthApiKey(\n\tprovider: OAuthProvider,\n\tcredentials: Record<string, OAuthCredentials>,\n): Promise<{ newCredentials: OAuthCredentials; apiKey: string } | null> {\n\tlet creds = credentials[provider];\n\tif (!creds) {\n\t\treturn null;\n\t}\n\n\t// Refresh if expired\n\tif (Date.now() >= creds.expires) {\n\t\ttry {\n\t\t\tcreds = await refreshOAuthToken(provider, creds);\n\t\t} catch (_error) {\n\t\t\tthrow new Error(`Failed to refresh OAuth token for ${provider}`);\n\t\t}\n\t}\n\n\t// For providers that need projectId, return JSON\n\tconst needsProjectId = provider === \"google-gemini-cli\" || provider === \"google-antigravity\";\n\tconst apiKey = needsProjectId ? JSON.stringify({ token: creds.access, projectId: creds.projectId }) : creds.access;\n\treturn { newCredentials: creds, apiKey };\n}\n\n/**\n * Get list of OAuth providers\n */\nexport function getOAuthProviders(): OAuthProviderInfo[] {\n\treturn [\n\t\t{\n\t\t\tid: \"anthropic\",\n\t\t\tname: \"Anthropic (Claude Pro/Max)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"openai-codex\",\n\t\t\tname: \"ChatGPT Plus/Pro (Codex Subscription)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"github-copilot\",\n\t\t\tname: \"GitHub Copilot\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"google-gemini-cli\",\n\t\t\tname: \"Google Cloud Code Assist (Gemini CLI)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"google-antigravity\",\n\t\t\tname: \"Antigravity (Gemini 3, Claude, GPT-OSS)\",\n\t\t\tavailable: true,\n\t\t},\n\t];\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/oauth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,iBAAiB;AACjB,OAAO,EACN,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,yBAAyB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,qBAAqB;AACrB,OAAO,EACN,gBAAgB,EAChB,uBAAuB,GACvB,MAAM,yBAAyB,CAAC;AACjC,oBAAoB;AACpB,OAAO,EACN,cAAc,EACd,uBAAuB,GACvB,MAAM,wBAAwB,CAAC;AAChC,+BAA+B;AAC/B,OAAO,EACN,gBAAgB,EAChB,uBAAuB,GACvB,MAAM,mBAAmB,CAAC;AAE3B,cAAc,YAAY,CAAC;AAE3B,+EAA+E;AAC/E,iBAAiB;AACjB,+EAA+E;AAE/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAG5D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACtC,QAAuB,EACvB,WAA6B,EACD;IAC5B,IAAI,CAAC,WAAW,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,kCAAkC,QAAQ,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,cAAgC,CAAC;IAErC,QAAQ,QAAQ,EAAE,CAAC;QAClB,KAAK,gBAAgB;YACpB,cAAc,GAAG,MAAM,yBAAyB,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;YACjG,MAAM;QACP,KAAK,mBAAmB;YACvB,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAC/D,CAAC;YACD,cAAc,GAAG,MAAM,uBAAuB,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;YAC3F,MAAM;QACP,KAAK,oBAAoB;YACxB,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC9D,CAAC;YACD,cAAc,GAAG,MAAM,uBAAuB,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;YAC3F,MAAM;QACP,KAAK,cAAc;YAClB,cAAc,GAAG,MAAM,uBAAuB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YACpE,MAAM;QACP;YACC,MAAM,IAAI,KAAK,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;IACzD,CAAC;IAED,OAAO,cAAc,CAAC;AAAA,CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,QAAuB,EACvB,WAA6C,EAC0B;IACvE,IAAI,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,CAAC,KAAK,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACb,CAAC;IAED,qBAAqB;IACrB,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC;YACJ,KAAK,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,qCAAqC,QAAQ,EAAE,CAAC,CAAC;QAClE,CAAC;IACF,CAAC;IAED,iDAAiD;IACjD,MAAM,cAAc,GAAG,QAAQ,KAAK,mBAAmB,IAAI,QAAQ,KAAK,oBAAoB,CAAC;IAC7F,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;IACnH,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAAA,CACzC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,GAAwB;IACxD,OAAO;QACN;YACC,EAAE,EAAE,cAAc;YAClB,IAAI,EAAE,uCAAuC;YAC7C,SAAS,EAAE,IAAI;SACf;QACD;YACC,EAAE,EAAE,gBAAgB;YACpB,IAAI,EAAE,gBAAgB;YACtB,SAAS,EAAE,IAAI;SACf;QACD;YACC,EAAE,EAAE,mBAAmB;YACvB,IAAI,EAAE,uCAAuC;YAC7C,SAAS,EAAE,IAAI;SACf;QACD;YACC,EAAE,EAAE,oBAAoB;YACxB,IAAI,EAAE,yCAAyC;YAC/C,SAAS,EAAE,IAAI;SACf;KACD,CAAC;AAAA,CACF","sourcesContent":["/**\n * OAuth credential management for AI providers.\n *\n * This module handles login, token refresh, and credential storage\n * for OAuth-based providers:\n * - Anthropic (Claude Pro/Max)\n * - GitHub Copilot\n * - Google Cloud Code Assist (Gemini CLI)\n * - Antigravity (Gemini 3, Claude, GPT-OSS via Google Cloud)\n */\n\n// GitHub Copilot\nexport {\n\tgetGitHubCopilotBaseUrl,\n\tloginGitHubCopilot,\n\tnormalizeDomain,\n\trefreshGitHubCopilotToken,\n} from \"./github-copilot.js\";\n// Google Antigravity\nexport {\n\tloginAntigravity,\n\trefreshAntigravityToken,\n} from \"./google-antigravity.js\";\n// Google Gemini CLI\nexport {\n\tloginGeminiCli,\n\trefreshGoogleCloudToken,\n} from \"./google-gemini-cli.js\";\n// OpenAI Codex (ChatGPT OAuth)\nexport {\n\tloginOpenAICodex,\n\trefreshOpenAICodexToken,\n} from \"./openai-codex.js\";\n\nexport * from \"./types.js\";\n\n// ============================================================================\n// High-level API\n// ============================================================================\n\nimport { refreshGitHubCopilotToken } from \"./github-copilot.js\";\nimport { refreshAntigravityToken } from \"./google-antigravity.js\";\nimport { refreshGoogleCloudToken } from \"./google-gemini-cli.js\";\nimport { refreshOpenAICodexToken } from \"./openai-codex.js\";\nimport type { OAuthCredentials, OAuthProvider, OAuthProviderInfo } from \"./types.js\";\n\n/**\n * Refresh token for any OAuth provider.\n * Saves the new credentials and returns the new access token.\n */\nexport async function refreshOAuthToken(\n\tprovider: OAuthProvider,\n\tcredentials: OAuthCredentials,\n): Promise<OAuthCredentials> {\n\tif (!credentials) {\n\t\tthrow new Error(`No OAuth credentials found for ${provider}`);\n\t}\n\n\tlet newCredentials: OAuthCredentials;\n\n\tswitch (provider) {\n\t\tcase \"github-copilot\":\n\t\t\tnewCredentials = await refreshGitHubCopilotToken(credentials.refresh, credentials.enterpriseUrl);\n\t\t\tbreak;\n\t\tcase \"google-gemini-cli\":\n\t\t\tif (!credentials.projectId) {\n\t\t\t\tthrow new Error(\"Google Cloud credentials missing projectId\");\n\t\t\t}\n\t\t\tnewCredentials = await refreshGoogleCloudToken(credentials.refresh, credentials.projectId);\n\t\t\tbreak;\n\t\tcase \"google-antigravity\":\n\t\t\tif (!credentials.projectId) {\n\t\t\t\tthrow new Error(\"Antigravity credentials missing projectId\");\n\t\t\t}\n\t\t\tnewCredentials = await refreshAntigravityToken(credentials.refresh, credentials.projectId);\n\t\t\tbreak;\n\t\tcase \"openai-codex\":\n\t\t\tnewCredentials = await refreshOpenAICodexToken(credentials.refresh);\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown OAuth provider: ${provider}`);\n\t}\n\n\treturn newCredentials;\n}\n\n/**\n * Get API key for a provider from OAuth credentials.\n * Automatically refreshes expired tokens.\n *\n * For google-gemini-cli and antigravity, returns JSON-encoded { token, projectId }\n *\n * @returns API key string, or null if no credentials\n * @throws Error if refresh fails\n */\nexport async function getOAuthApiKey(\n\tprovider: OAuthProvider,\n\tcredentials: Record<string, OAuthCredentials>,\n): Promise<{ newCredentials: OAuthCredentials; apiKey: string } | null> {\n\tlet creds = credentials[provider];\n\tif (!creds) {\n\t\treturn null;\n\t}\n\n\t// Refresh if expired\n\tif (Date.now() >= creds.expires) {\n\t\ttry {\n\t\t\tcreds = await refreshOAuthToken(provider, creds);\n\t\t} catch (_error) {\n\t\t\tthrow new Error(`Failed to refresh OAuth token for ${provider}`);\n\t\t}\n\t}\n\n\t// For providers that need projectId, return JSON\n\tconst needsProjectId = provider === \"google-gemini-cli\" || provider === \"google-antigravity\";\n\tconst apiKey = needsProjectId ? JSON.stringify({ token: creds.access, projectId: creds.projectId }) : creds.access;\n\treturn { newCredentials: creds, apiKey };\n}\n\n/**\n * Get list of OAuth providers\n */\nexport function getOAuthProviders(): OAuthProviderInfo[] {\n\treturn [\n\t\t{\n\t\t\tid: \"openai-codex\",\n\t\t\tname: \"ChatGPT Plus/Pro (Codex Subscription)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"github-copilot\",\n\t\t\tname: \"GitHub Copilot\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"google-gemini-cli\",\n\t\t\tname: \"Google Cloud Code Assist (Gemini CLI)\",\n\t\t\tavailable: true,\n\t\t},\n\t\t{\n\t\t\tid: \"google-antigravity\",\n\t\t\tname: \"Antigravity (Gemini 3, Claude, GPT-OSS)\",\n\t\t\tavailable: true,\n\t\t},\n\t];\n}\n"]}
@@ -7,7 +7,7 @@ export type OAuthCredentials = {
7
7
  email?: string;
8
8
  accountId?: string;
9
9
  };
10
- export type OAuthProvider = "anthropic" | "github-copilot" | "google-gemini-cli" | "google-antigravity" | "openai-codex";
10
+ export type OAuthProvider = "github-copilot" | "google-gemini-cli" | "google-antigravity" | "openai-codex";
11
11
  export type OAuthPrompt = {
12
12
  message: string;
13
13
  placeholder?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/oauth/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GACtB,WAAW,GACX,gBAAgB,GAChB,mBAAmB,GACnB,oBAAoB,GACpB,cAAc,CAAC;AAElB,MAAM,MAAM,WAAW,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,aAAa,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACnB","sourcesContent":["export type OAuthCredentials = {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\tenterpriseUrl?: string;\n\tprojectId?: string;\n\temail?: string;\n\taccountId?: string;\n};\n\nexport type OAuthProvider =\n\t| \"anthropic\"\n\t| \"github-copilot\"\n\t| \"google-gemini-cli\"\n\t| \"google-antigravity\"\n\t| \"openai-codex\";\n\nexport type OAuthPrompt = {\n\tmessage: string;\n\tplaceholder?: string;\n\tallowEmpty?: boolean;\n};\n\nexport type OAuthAuthInfo = {\n\turl: string;\n\tinstructions?: string;\n};\n\nexport interface OAuthProviderInfo {\n\tid: OAuthProvider;\n\tname: string;\n\tavailable: boolean;\n}\n"]}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/utils/oauth/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,oBAAoB,GAAG,cAAc,CAAC;AAE3G,MAAM,MAAM,WAAW,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,iBAAiB;IACjC,EAAE,EAAE,aAAa,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACnB","sourcesContent":["export type OAuthCredentials = {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\tenterpriseUrl?: string;\n\tprojectId?: string;\n\temail?: string;\n\taccountId?: string;\n};\n\nexport type OAuthProvider = \"github-copilot\" | \"google-gemini-cli\" | \"google-antigravity\" | \"openai-codex\";\n\nexport type OAuthPrompt = {\n\tmessage: string;\n\tplaceholder?: string;\n\tallowEmpty?: boolean;\n};\n\nexport type OAuthAuthInfo = {\n\turl: string;\n\tinstructions?: string;\n};\n\nexport interface OAuthProviderInfo {\n\tid: OAuthProvider;\n\tname: string;\n\tavailable: boolean;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/oauth/types.ts"],"names":[],"mappings":"","sourcesContent":["export type OAuthCredentials = {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\tenterpriseUrl?: string;\n\tprojectId?: string;\n\temail?: string;\n\taccountId?: string;\n};\n\nexport type OAuthProvider =\n\t| \"anthropic\"\n\t| \"github-copilot\"\n\t| \"google-gemini-cli\"\n\t| \"google-antigravity\"\n\t| \"openai-codex\";\n\nexport type OAuthPrompt = {\n\tmessage: string;\n\tplaceholder?: string;\n\tallowEmpty?: boolean;\n};\n\nexport type OAuthAuthInfo = {\n\turl: string;\n\tinstructions?: string;\n};\n\nexport interface OAuthProviderInfo {\n\tid: OAuthProvider;\n\tname: string;\n\tavailable: boolean;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/utils/oauth/types.ts"],"names":[],"mappings":"","sourcesContent":["export type OAuthCredentials = {\n\trefresh: string;\n\taccess: string;\n\texpires: number;\n\tenterpriseUrl?: string;\n\tprojectId?: string;\n\temail?: string;\n\taccountId?: string;\n};\n\nexport type OAuthProvider = \"github-copilot\" | \"google-gemini-cli\" | \"google-antigravity\" | \"openai-codex\";\n\nexport type OAuthPrompt = {\n\tmessage: string;\n\tplaceholder?: string;\n\tallowEmpty?: boolean;\n};\n\nexport type OAuthAuthInfo = {\n\turl: string;\n\tinstructions?: string;\n};\n\nexport interface OAuthProviderInfo {\n\tid: OAuthProvider;\n\tname: string;\n\tavailable: boolean;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mariozechner/pi-ai",
3
- "version": "0.39.1",
3
+ "version": "0.40.1",
4
4
  "description": "Unified LLM API with automatic model discovery and provider configuration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,16 +0,0 @@
1
- /**
2
- * Anthropic OAuth flow (Claude Pro/Max)
3
- */
4
- import type { OAuthCredentials } from "./types.js";
5
- /**
6
- * Login with Anthropic OAuth (device code flow)
7
- *
8
- * @param onAuthUrl - Callback to handle the authorization URL (e.g., open browser)
9
- * @param onPromptCode - Callback to prompt user for the authorization code
10
- */
11
- export declare function loginAnthropic(onAuthUrl: (url: string) => void, onPromptCode: () => Promise<string>): Promise<OAuthCredentials>;
12
- /**
13
- * Refresh Anthropic OAuth token
14
- */
15
- export declare function refreshAnthropicToken(refreshToken: string): Promise<OAuthCredentials>;
16
- //# sourceMappingURL=anthropic.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/utils/oauth/anthropic.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AASnD;;;;;GAKG;AACH,wBAAsB,cAAc,CACnC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,EAChC,YAAY,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GACjC,OAAO,CAAC,gBAAgB,CAAC,CA8D3B;AAED;;GAEG;AACH,wBAAsB,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA2B3F","sourcesContent":["/**\n * Anthropic OAuth flow (Claude Pro/Max)\n */\n\nimport { generatePKCE } from \"./pkce.js\";\nimport type { OAuthCredentials } from \"./types.js\";\n\nconst decode = (s: string) => atob(s);\nconst CLIENT_ID = decode(\"OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl\");\nconst AUTHORIZE_URL = \"https://claude.ai/oauth/authorize\";\nconst TOKEN_URL = \"https://console.anthropic.com/v1/oauth/token\";\nconst REDIRECT_URI = \"https://console.anthropic.com/oauth/code/callback\";\nconst SCOPES = \"org:create_api_key user:profile user:inference\";\n\n/**\n * Login with Anthropic OAuth (device code flow)\n *\n * @param onAuthUrl - Callback to handle the authorization URL (e.g., open browser)\n * @param onPromptCode - Callback to prompt user for the authorization code\n */\nexport async function loginAnthropic(\n\tonAuthUrl: (url: string) => void,\n\tonPromptCode: () => Promise<string>,\n): Promise<OAuthCredentials> {\n\tconst { verifier, challenge } = await generatePKCE();\n\n\t// Build authorization URL\n\tconst authParams = new URLSearchParams({\n\t\tcode: \"true\",\n\t\tclient_id: CLIENT_ID,\n\t\tresponse_type: \"code\",\n\t\tredirect_uri: REDIRECT_URI,\n\t\tscope: SCOPES,\n\t\tcode_challenge: challenge,\n\t\tcode_challenge_method: \"S256\",\n\t\tstate: verifier,\n\t});\n\n\tconst authUrl = `${AUTHORIZE_URL}?${authParams.toString()}`;\n\n\t// Notify caller with URL to open\n\tonAuthUrl(authUrl);\n\n\t// Wait for user to paste authorization code (format: code#state)\n\tconst authCode = await onPromptCode();\n\tconst splits = authCode.split(\"#\");\n\tconst code = splits[0];\n\tconst state = splits[1];\n\n\t// Exchange code for tokens\n\tconst tokenResponse = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tcode: code,\n\t\t\tstate: state,\n\t\t\tredirect_uri: REDIRECT_URI,\n\t\t\tcode_verifier: verifier,\n\t\t}),\n\t});\n\n\tif (!tokenResponse.ok) {\n\t\tconst error = await tokenResponse.text();\n\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t}\n\n\tconst tokenData = (await tokenResponse.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\texpires_in: number;\n\t};\n\n\t// Calculate expiry time (current time + expires_in seconds - 5 min buffer)\n\tconst expiresAt = Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000;\n\n\t// Save credentials\n\treturn {\n\t\trefresh: tokenData.refresh_token,\n\t\taccess: tokenData.access_token,\n\t\texpires: expiresAt,\n\t};\n}\n\n/**\n * Refresh Anthropic OAuth token\n */\nexport async function refreshAnthropicToken(refreshToken: string): Promise<OAuthCredentials> {\n\tconst response = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\tbody: JSON.stringify({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\trefresh_token: refreshToken,\n\t\t}),\n\t});\n\n\tif (!response.ok) {\n\t\tconst error = await response.text();\n\t\tthrow new Error(`Anthropic token refresh failed: ${error}`);\n\t}\n\n\tconst data = (await response.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\texpires_in: number;\n\t};\n\n\treturn {\n\t\trefresh: data.refresh_token,\n\t\taccess: data.access_token,\n\t\texpires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,\n\t};\n}\n"]}
@@ -1,91 +0,0 @@
1
- /**
2
- * Anthropic OAuth flow (Claude Pro/Max)
3
- */
4
- import { generatePKCE } from "./pkce.js";
5
- const decode = (s) => atob(s);
6
- const CLIENT_ID = decode("OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl");
7
- const AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
8
- const TOKEN_URL = "https://console.anthropic.com/v1/oauth/token";
9
- const REDIRECT_URI = "https://console.anthropic.com/oauth/code/callback";
10
- const SCOPES = "org:create_api_key user:profile user:inference";
11
- /**
12
- * Login with Anthropic OAuth (device code flow)
13
- *
14
- * @param onAuthUrl - Callback to handle the authorization URL (e.g., open browser)
15
- * @param onPromptCode - Callback to prompt user for the authorization code
16
- */
17
- export async function loginAnthropic(onAuthUrl, onPromptCode) {
18
- const { verifier, challenge } = await generatePKCE();
19
- // Build authorization URL
20
- const authParams = new URLSearchParams({
21
- code: "true",
22
- client_id: CLIENT_ID,
23
- response_type: "code",
24
- redirect_uri: REDIRECT_URI,
25
- scope: SCOPES,
26
- code_challenge: challenge,
27
- code_challenge_method: "S256",
28
- state: verifier,
29
- });
30
- const authUrl = `${AUTHORIZE_URL}?${authParams.toString()}`;
31
- // Notify caller with URL to open
32
- onAuthUrl(authUrl);
33
- // Wait for user to paste authorization code (format: code#state)
34
- const authCode = await onPromptCode();
35
- const splits = authCode.split("#");
36
- const code = splits[0];
37
- const state = splits[1];
38
- // Exchange code for tokens
39
- const tokenResponse = await fetch(TOKEN_URL, {
40
- method: "POST",
41
- headers: {
42
- "Content-Type": "application/json",
43
- },
44
- body: JSON.stringify({
45
- grant_type: "authorization_code",
46
- client_id: CLIENT_ID,
47
- code: code,
48
- state: state,
49
- redirect_uri: REDIRECT_URI,
50
- code_verifier: verifier,
51
- }),
52
- });
53
- if (!tokenResponse.ok) {
54
- const error = await tokenResponse.text();
55
- throw new Error(`Token exchange failed: ${error}`);
56
- }
57
- const tokenData = (await tokenResponse.json());
58
- // Calculate expiry time (current time + expires_in seconds - 5 min buffer)
59
- const expiresAt = Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000;
60
- // Save credentials
61
- return {
62
- refresh: tokenData.refresh_token,
63
- access: tokenData.access_token,
64
- expires: expiresAt,
65
- };
66
- }
67
- /**
68
- * Refresh Anthropic OAuth token
69
- */
70
- export async function refreshAnthropicToken(refreshToken) {
71
- const response = await fetch(TOKEN_URL, {
72
- method: "POST",
73
- headers: { "Content-Type": "application/json" },
74
- body: JSON.stringify({
75
- grant_type: "refresh_token",
76
- client_id: CLIENT_ID,
77
- refresh_token: refreshToken,
78
- }),
79
- });
80
- if (!response.ok) {
81
- const error = await response.text();
82
- throw new Error(`Anthropic token refresh failed: ${error}`);
83
- }
84
- const data = (await response.json());
85
- return {
86
- refresh: data.refresh_token,
87
- access: data.access_token,
88
- expires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,
89
- };
90
- }
91
- //# sourceMappingURL=anthropic.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/utils/oauth/anthropic.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Anthropic OAuth flow (Claude Pro/Max)\n */\n\nimport { generatePKCE } from \"./pkce.js\";\nimport type { OAuthCredentials } from \"./types.js\";\n\nconst decode = (s: string) => atob(s);\nconst CLIENT_ID = decode(\"OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl\");\nconst AUTHORIZE_URL = \"https://claude.ai/oauth/authorize\";\nconst TOKEN_URL = \"https://console.anthropic.com/v1/oauth/token\";\nconst REDIRECT_URI = \"https://console.anthropic.com/oauth/code/callback\";\nconst SCOPES = \"org:create_api_key user:profile user:inference\";\n\n/**\n * Login with Anthropic OAuth (device code flow)\n *\n * @param onAuthUrl - Callback to handle the authorization URL (e.g., open browser)\n * @param onPromptCode - Callback to prompt user for the authorization code\n */\nexport async function loginAnthropic(\n\tonAuthUrl: (url: string) => void,\n\tonPromptCode: () => Promise<string>,\n): Promise<OAuthCredentials> {\n\tconst { verifier, challenge } = await generatePKCE();\n\n\t// Build authorization URL\n\tconst authParams = new URLSearchParams({\n\t\tcode: \"true\",\n\t\tclient_id: CLIENT_ID,\n\t\tresponse_type: \"code\",\n\t\tredirect_uri: REDIRECT_URI,\n\t\tscope: SCOPES,\n\t\tcode_challenge: challenge,\n\t\tcode_challenge_method: \"S256\",\n\t\tstate: verifier,\n\t});\n\n\tconst authUrl = `${AUTHORIZE_URL}?${authParams.toString()}`;\n\n\t// Notify caller with URL to open\n\tonAuthUrl(authUrl);\n\n\t// Wait for user to paste authorization code (format: code#state)\n\tconst authCode = await onPromptCode();\n\tconst splits = authCode.split(\"#\");\n\tconst code = splits[0];\n\tconst state = splits[1];\n\n\t// Exchange code for tokens\n\tconst tokenResponse = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t},\n\t\tbody: JSON.stringify({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tcode: code,\n\t\t\tstate: state,\n\t\t\tredirect_uri: REDIRECT_URI,\n\t\t\tcode_verifier: verifier,\n\t\t}),\n\t});\n\n\tif (!tokenResponse.ok) {\n\t\tconst error = await tokenResponse.text();\n\t\tthrow new Error(`Token exchange failed: ${error}`);\n\t}\n\n\tconst tokenData = (await tokenResponse.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\texpires_in: number;\n\t};\n\n\t// Calculate expiry time (current time + expires_in seconds - 5 min buffer)\n\tconst expiresAt = Date.now() + tokenData.expires_in * 1000 - 5 * 60 * 1000;\n\n\t// Save credentials\n\treturn {\n\t\trefresh: tokenData.refresh_token,\n\t\taccess: tokenData.access_token,\n\t\texpires: expiresAt,\n\t};\n}\n\n/**\n * Refresh Anthropic OAuth token\n */\nexport async function refreshAnthropicToken(refreshToken: string): Promise<OAuthCredentials> {\n\tconst response = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\tbody: JSON.stringify({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: CLIENT_ID,\n\t\t\trefresh_token: refreshToken,\n\t\t}),\n\t});\n\n\tif (!response.ok) {\n\t\tconst error = await response.text();\n\t\tthrow new Error(`Anthropic token refresh failed: ${error}`);\n\t}\n\n\tconst data = (await response.json()) as {\n\t\taccess_token: string;\n\t\trefresh_token: string;\n\t\texpires_in: number;\n\t};\n\n\treturn {\n\t\trefresh: data.refresh_token,\n\t\taccess: data.access_token,\n\t\texpires: Date.now() + data.expires_in * 1000 - 5 * 60 * 1000,\n\t};\n}\n"]}