@bastani/pi-ai 0.9.26-alpha.2 → 0.9.26-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +18 -0
- package/NOTICE.md +1 -1
- package/README.md +3 -1
- package/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +20 -32
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/dist/api/bedrock-converse-stream.js +25 -2
- package/dist/api/bedrock-converse-stream.js.map +1 -1
- package/dist/api/cloudflare-workers-ai-system-one.d.ts.map +1 -1
- package/dist/api/cloudflare-workers-ai-system-one.js +13 -8
- package/dist/api/cloudflare-workers-ai-system-one.js.map +1 -1
- package/dist/auth/oauth/openai-chatgpt.d.ts.map +1 -1
- package/dist/auth/oauth/openai-chatgpt.js +5 -0
- package/dist/auth/oauth/openai-chatgpt.js.map +1 -1
- package/dist/providers/data/.manifest.json +1 -1
- package/dist/providers/data/amazon-bedrock.json +1 -1
- package/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/dist/providers/data/cloudflare-workers-ai.json +1 -1
- package/dist/providers/data/opencode.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/radius.json +1 -1
- package/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js +1 -0
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/transcript.d.ts +5 -2
- package/dist/utils/transcript.d.ts.map +1 -1
- package/dist/utils/transcript.js +5 -2
- package/dist/utils/transcript.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloudflare-workers-ai-system-one.js","sourceRoot":"","sources":["../../src/api/cloudflare-workers-ai-system-one.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAA2B,MAAM,wBAAwB,CAAC;AAE9F,MAAM,KAAK,GAAG,uBAAuB,CAAC;AAEtC,SAAS,sBAAsB,CAAC,MAAe;IAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,MAAM;aACrB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;aAClG,MAAM,CAAC,CAAC,OAAO,EAAqB,EAAE,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;QAChE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,GAAG,KAAK,WAAW,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAC1E,CAAC;IACD,OAAO,GAAG,KAAK,iBAAiB,CAAC;AAClC,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"cloudflare-workers-ai-system-one.js","sourceRoot":"","sources":["../../src/api/cloudflare-workers-ai-system-one.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAA2B,MAAM,wBAAwB,CAAC;AAE9F,MAAM,KAAK,GAAG,uBAAuB,CAAC;AAEtC,SAAS,sBAAsB,CAAC,MAAe;IAC9C,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,MAAM;aACrB,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;aAClG,MAAM,CAAC,CAAC,OAAO,EAAqB,EAAE,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;QAChE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,GAAG,KAAK,WAAW,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAC1E,CAAC;IACD,OAAO,GAAG,KAAK,iBAAiB,CAAC;AAClC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,SAAS,GAAuB;IACrC,GAAG,EAAE,kCAAkC;IACvC,KAAK,EAAE,KAAK;IACZ,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC;IACxE,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAClE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;QAChB,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,kCAAkC,CAAC,CAAC;QACjF,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACjF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,kCAAkC,CAAC,CAAC;QACnF,IAAI,SAAS,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QACvC,IAAI,MAAM,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,iCAAiC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,kCAAkC,CAAC,CAAC;QAC1F,OAAO,MAAM,CAAC,MAAM,CAAC;IACtB,CAAC;CACD,CAAC;AAEF,6GAA6G;AAC7G,MAAM,CAAC,MAAM,QAAQ,GAA0C,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAC1F,iBAAiB,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC","sourcesContent":["import type { ClassifierFunction, ClassifierOptions } from \"../types.ts\";\nimport { classifySystemOne, isRecord, type SystemOneTransport } from \"./system-one-shared.ts\";\n\nconst LABEL = \"Cloudflare Workers AI\";\n\nfunction cloudflareErrorMessage(errors: unknown): string {\n\tif (Array.isArray(errors)) {\n\t\tconst messages = errors\n\t\t\t.map((error) => (isRecord(error) && typeof error.message === \"string\" ? error.message : undefined))\n\t\t\t.filter((message): message is string => message !== undefined);\n\t\tif (messages.length > 0) return `${LABEL} error: ${messages.join(\"; \")}`;\n\t}\n\treturn `${LABEL} request failed`;\n}\n\n/**\n * System One models on the Workers AI REST endpoint:\n * `POST /accounts/{account}/ai/run` with `{ model, input }`. The REST API wraps the model\n * output in Cloudflare's API envelope. Third-party models such as `typesafe/jev` add a run record:\n * `{ success, result: { state: \"Completed\", result: { answers, usage } } }`.\n * https://developers.cloudflare.com/ai/models/typesafe/jev/\n * Cloudflare-hosted models such as `@cf/cloudflare/clef` return the output directly:\n * `{ success, result: { model, answers, usage } }`.\n * https://developers.cloudflare.com/workers-ai/models/clef/\n */\nconst transport: SystemOneTransport = {\n\tapi: \"cloudflare-workers-ai-system-one\",\n\tlabel: LABEL,\n\turl: (model) => new URL(\"run\", `${model.baseUrl.replace(/\\/+$/u, \"\")}/`),\n\tpayload: (model, request) => ({ model: model.id, input: request }),\n\toutput: (body) => {\n\t\tif (!isRecord(body)) throw new Error(`${LABEL} returned an unexpected response`);\n\t\tif (body.success === false) throw new Error(cloudflareErrorMessage(body.errors));\n\t\tconst result = body.result;\n\t\tif (!isRecord(result)) throw new Error(`${LABEL} returned an unexpected response`);\n\t\tif (\"answers\" in result) return result;\n\t\tif (result.state !== \"Completed\") {\n\t\t\tthrow new Error(`${LABEL} run did not complete (state: ${String(result.state)})`);\n\t\t}\n\t\tif (!isRecord(result.result)) throw new Error(`${LABEL} returned an unexpected response`);\n\t\treturn result.result;\n\t},\n};\n\n/** Cloudflare Workers AI System One classification with public `bool` values mapped to wire-level `noul`. */\nexport const classify: ClassifierFunction<ClassifierOptions> = (model, context, options) =>\n\tclassifySystemOne(transport, model, context, options);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-chatgpt.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/openai-chatgpt.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAgB,SAAS,EAA4C,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"openai-chatgpt.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/openai-chatgpt.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAgB,SAAS,EAA4C,MAAM,aAAa,CAAC;AA6QrG,eAAO,MAAM,kBAAkB,EAAE,SAUhC,CAAC"}
|
|
@@ -187,6 +187,11 @@ async function loginOpenAIChatGPT(interaction, options) {
|
|
|
187
187
|
callback = await startCallbackServer(state);
|
|
188
188
|
}
|
|
189
189
|
catch (error) {
|
|
190
|
+
// A port held by another pending login or the Codex CLI would receive the browser's callback and
|
|
191
|
+
// reject it as a state mismatch, so fail with a clear error instead of offering the paste prompt.
|
|
192
|
+
if (error instanceof Error && "code" in error && error.code === "EADDRINUSE") {
|
|
193
|
+
throw new Error(`Port ${CALLBACK_PORT} is in use, probably by an unfinished login in another Atomic session or by the Codex CLI. Cancel that login and try again.`);
|
|
194
|
+
}
|
|
190
195
|
interaction.notify({
|
|
191
196
|
type: "info",
|
|
192
197
|
message: `Could not listen on ${REDIRECT_URI}; paste the final redirect URL to continue. ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-chatgpt.js","sourceRoot":"","sources":["../../../src/auth/oauth/openai-chatgpt.ts"],"names":[],"mappings":"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","sourcesContent":["/** Direct OpenAI Responses API token sharing through Sign in with ChatGPT. */\nimport { randomBytes } from \"node:crypto\";\nimport { createServer, type Server, type ServerResponse } from \"node:http\";\nimport { oauthErrorHtml, oauthSuccessHtml } from \"../../utils/oauth-page.ts\";\nimport { getProviderEnvValue } from \"../../utils/provider-env.ts\";\nimport type { LoginOptions, OAuthAuth, OAuthCredential, ProviderAuthInteraction } from \"../types.ts\";\nimport { generatePKCE } from \"./pkce.ts\";\n\nconst DYNAMIC_CLIENT_ID = \"dynamic_agent_client\";\nconst AGENT_NAME_HINT = \"Atomic\";\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst AUTHORIZE_URL = \"https://auth.openai.com/api/accounts/authorize\";\nconst TOKEN_URL = \"https://auth.openai.com/api/accounts/oauth/token\";\nconst RESOURCE = \"https://api.openai.com/v1\";\nconst CALLBACK_HOST = getProviderEnvValue(\"PI_OAUTH_CALLBACK_HOST\") || \"127.0.0.1\";\nconst CALLBACK_PORT = 1455;\nconst CALLBACK_PATH = \"/auth/callback\";\nconst REDIRECT_URI = `http://127.0.0.1:${CALLBACK_PORT}${CALLBACK_PATH}`;\nconst DIRECT_TOKEN_SCOPE = \"chatgpt.tokens.use.direct\";\nconst SCOPE = `openid profile email offline_access resource.invoke ${DIRECT_TOKEN_SCOPE}`;\nconst EXPIRY_MARGIN_MS = 3 * 60 * 1000;\n\ntype AuthorizationResult = { code: string; clientId: string };\ntype CallbackServer = { server: Server; result: Promise<AuthorizationResult> };\ntype TokenResponse = {\n\taccess_token?: unknown;\n\trefresh_token?: unknown;\n\texpires_in?: unknown;\n\tid_token?: unknown;\n\tscope?: unknown;\n};\n\nfunction randomValue(): string {\n\treturn randomBytes(32).toString(\"base64url\");\n}\n\nfunction authorizationResultFromCallback(url: URL, expectedState: string): AuthorizationResult {\n\tconst code = url.searchParams.get(\"code\");\n\tif (!code) throw new Error(\"Missing authorization code\");\n\tconst state = url.searchParams.get(\"state\");\n\tif (!state) throw new Error(\"Missing OAuth state\");\n\tif (state !== expectedState) throw new Error(\"OAuth state mismatch\");\n\tconst clientId = url.searchParams.get(\"client_id\")?.trim();\n\tif (!clientId) throw new Error(\"OpenAI OAuth registration callback did not contain an issued client ID\");\n\treturn { code, clientId };\n}\n\nfunction authorizationResultFromManualInput(input: string, expectedState: string): AuthorizationResult {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(input.trim());\n\t} catch {\n\t\tthrow new Error(\"Paste the full callback URL from the browser\");\n\t}\n\tconst expected = new URL(REDIRECT_URI);\n\tif (url.origin !== expected.origin || url.pathname !== expected.pathname) {\n\t\tthrow new Error(`The pasted callback URL must start with ${REDIRECT_URI}`);\n\t}\n\tconst error = url.searchParams.get(\"error\");\n\tif (error) throw new Error(`ChatGPT authorization failed: ${error}`);\n\treturn authorizationResultFromCallback(url, expectedState);\n}\n\nfunction sendHtml(response: ServerResponse, status: number, body: string): void {\n\tresponse.writeHead(status, { \"Content-Type\": \"text/html; charset=utf-8\" });\n\tresponse.end(body);\n}\n\nfunction startCallbackServer(expectedState: string): Promise<CallbackServer> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet resolveResult!: (result: AuthorizationResult) => void;\n\t\tlet rejectResult!: (error: Error) => void;\n\t\tconst result = new Promise<AuthorizationResult>((resolveAuthorization, rejectAuthorization) => {\n\t\t\tresolveResult = resolveAuthorization;\n\t\t\trejectResult = rejectAuthorization;\n\t\t});\n\t\tconst server = createServer((request, response) => {\n\t\t\ttry {\n\t\t\t\tconst url = new URL(request.url || \"\", REDIRECT_URI);\n\t\t\t\tif (url.pathname !== CALLBACK_PATH) {\n\t\t\t\t\tsendHtml(response, 404, oauthErrorHtml(\"Callback route not found.\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst error = url.searchParams.get(\"error\");\n\t\t\t\tif (error) {\n\t\t\t\t\tsendHtml(response, 400, oauthErrorHtml(\"ChatGPT was not connected.\", `Error: ${error}`));\n\t\t\t\t\trejectResult(new Error(`ChatGPT authorization failed: ${error}`));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet authorizationResult: AuthorizationResult;\n\t\t\t\ttry {\n\t\t\t\t\tauthorizationResult = authorizationResultFromCallback(url, expectedState);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = error instanceof Error ? error.message : \"Invalid callback\";\n\t\t\t\t\tsendHtml(response, 400, oauthErrorHtml(message));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsendHtml(response, 200, oauthSuccessHtml(\"ChatGPT authentication completed. You can close this window.\"));\n\t\t\t\tresolveResult(authorizationResult);\n\t\t\t} catch {\n\t\t\t\tsendHtml(response, 500, oauthErrorHtml(\"Internal error while processing the callback.\"));\n\t\t\t}\n\t\t});\n\t\tserver.once(\"error\", reject);\n\t\tserver.listen(CALLBACK_PORT, CALLBACK_HOST, () => {\n\t\t\tserver.removeListener(\"error\", reject);\n\t\t\tserver.on(\"error\", rejectResult);\n\t\t\tresolve({ server, result });\n\t\t});\n\t});\n}\n\nasync function requestToken(body: URLSearchParams, signal: AbortSignal): Promise<TokenResponse> {\n\tconst response = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { accept: \"application/json\", \"content-type\": \"application/x-www-form-urlencoded\" },\n\t\tbody,\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tconst responseBody = await response.text().catch(() => \"\");\n\t\tthrow new Error(`OpenAI OAuth token request failed (${response.status}): ${responseBody || response.statusText}`);\n\t}\n\tconst data: unknown = await response.json();\n\tif (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n\t\tthrow new Error(\"OpenAI OAuth token response must be an object\");\n\t}\n\treturn data as TokenResponse;\n}\n\nfunction requireTokenString(value: unknown, field: \"access_token\" | \"refresh_token\" | \"scope\"): string {\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(`OpenAI OAuth token response has invalid ${field}`);\n\t}\n\treturn value;\n}\n\nfunction credentialFromTokenResponse(token: TokenResponse, clientId: string): OAuthCredential {\n\tconst access = requireTokenString(token.access_token, \"access_token\");\n\tconst refresh = requireTokenString(token.refresh_token, \"refresh_token\");\n\tconst scope = requireTokenString(token.scope, \"scope\");\n\tif (typeof token.expires_in !== \"number\" || !Number.isFinite(token.expires_in) || token.expires_in <= 0) {\n\t\tthrow new Error(\"OpenAI OAuth token response has invalid expires_in\");\n\t}\n\tconst scopes = scope.trim().split(/\\s+/).filter(Boolean);\n\tif (!scopes.includes(DIRECT_TOKEN_SCOPE)) {\n\t\tthrow new Error(`OpenAI OAuth grant did not include ${DIRECT_TOKEN_SCOPE}`);\n\t}\n\treturn {\n\t\ttype: \"oauth\",\n\t\taccess,\n\t\trefresh,\n\t\texpires: Date.now() + token.expires_in * 1000 - EXPIRY_MARGIN_MS,\n\t\tclientId,\n\t\tscopes,\n\t};\n}\n\nasync function exchangeAuthorizationCode(\n\tcode: string,\n\tverifier: string,\n\tclientId: string,\n\tsignal: AbortSignal,\n): Promise<OAuthCredential> {\n\tconst token = await requestToken(\n\t\tnew URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: clientId,\n\t\t\tcode,\n\t\t\tcode_verifier: verifier,\n\t\t\tredirect_uri: REDIRECT_URI,\n\t\t\tresource: RESOURCE,\n\t\t}),\n\t\tsignal,\n\t);\n\t// The ID token is required by the response contract, but is not used for profile data.\n\tif (typeof token.id_token !== \"string\" || token.id_token.trim().length === 0) {\n\t\tthrow new Error(\"OpenAI OAuth token response did not contain an ID token\");\n\t}\n\treturn credentialFromTokenResponse(token, clientId);\n}\n\nasync function refreshAccessToken(credential: OAuthCredential, signal: AbortSignal): Promise<OAuthCredential> {\n\tconst clientId = credential.clientId;\n\tif (typeof clientId !== \"string\" || clientId.trim().length === 0) {\n\t\tthrow new Error(\"Stored OpenAI OAuth credential does not contain an issued client ID; reconnect ChatGPT\");\n\t}\n\tconst token = await requestToken(\n\t\tnew URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: clientId,\n\t\t\trefresh_token: credential.refresh,\n\t\t\tresource: RESOURCE,\n\t\t}),\n\t\tsignal,\n\t);\n\treturn credentialFromTokenResponse(token, clientId);\n}\n\nfunction agentHostId(deviceId: string | undefined): string {\n\tif (!deviceId || !UUID_PATTERN.test(deviceId)) {\n\t\tthrow new Error(\"Sign in with ChatGPT requires a device ID (UUID) for this installation\");\n\t}\n\treturn `urn:uuid:${deviceId.toLowerCase()}`;\n}\n\nasync function loginOpenAIChatGPT(\n\tinteraction: ProviderAuthInteraction,\n\toptions?: LoginOptions,\n): Promise<OAuthCredential> {\n\tconst hostId = agentHostId(options?.getDeviceId?.());\n\tconst { verifier, challenge } = await generatePKCE();\n\tconst state = randomValue();\n\tconst nonce = randomValue();\n\tlet callback: CallbackServer | undefined;\n\ttry {\n\t\tcallback = await startCallbackServer(state);\n\t} catch (error) {\n\t\tinteraction.notify({\n\t\t\ttype: \"info\",\n\t\t\tmessage: `Could not listen on ${REDIRECT_URI}; paste the final redirect URL to continue. ${error instanceof Error ? error.message : String(error)}`,\n\t\t});\n\t}\n\tconst authorizationUrl = new URL(AUTHORIZE_URL);\n\tauthorizationUrl.search = new URLSearchParams({\n\t\tclient_id: DYNAMIC_CLIENT_ID,\n\t\tagent_name_hint: AGENT_NAME_HINT,\n\t\text_agent_host_id: hostId,\n\t\tresponse_type: \"code\",\n\t\tredirect_uri: REDIRECT_URI,\n\t\tresource: RESOURCE,\n\t\tscope: SCOPE,\n\t\tstate,\n\t\tcode_challenge: challenge,\n\t\tcode_challenge_method: \"S256\",\n\t\tnonce,\n\t}).toString();\n\tinteraction.notify({\n\t\ttype: \"auth_url\",\n\t\turl: authorizationUrl.toString(),\n\t\tinstructions:\n\t\t\t\"Complete sign-in in your browser. If the callback does not complete, paste the final redirect URL here.\",\n\t});\n\tconst manualAbort = new AbortController();\n\tconst manualCode = interaction\n\t\t.prompt({\n\t\t\ttype: \"manual_code\",\n\t\t\tmessage: \"Complete login in your browser, or paste the final redirect URL here:\",\n\t\t\tplaceholder: REDIRECT_URI,\n\t\t\tsignal: AbortSignal.any([manualAbort.signal, interaction.signal]),\n\t\t})\n\t\t.then((input) => authorizationResultFromManualInput(input, state));\n\ttry {\n\t\tconst result = await (callback ? Promise.race([callback.result, manualCode]) : manualCode);\n\t\tinteraction.notify({ type: \"progress\", message: \"Exchanging authorization code for tokens...\" });\n\t\treturn await exchangeAuthorizationCode(result.code, verifier, result.clientId, interaction.signal);\n\t} catch (error) {\n\t\tif (interaction.signal.aborted) throw new Error(\"Login cancelled\");\n\t\tthrow error;\n\t} finally {\n\t\tmanualAbort.abort();\n\t\tcallback?.server.close();\n\t\t// Spare browser connections must not deliver a later login to this old server.\n\t\tcallback?.server.closeAllConnections();\n\t}\n}\n\nexport const openaiChatGPTOAuth: OAuthAuth = {\n\tname: \"OpenAI (ChatGPT subscription)\",\n\tusesCallbackServer: true,\n\tisSubscription: true,\n\tloginLabel: \"Sign in with ChatGPT\",\n\tlogin: loginOpenAIChatGPT,\n\trefresh: refreshAccessToken,\n\tasync toAuth(credential) {\n\t\treturn { apiKey: credential.access };\n\t},\n};\n"]}
|
|
1
|
+
{"version":3,"file":"openai-chatgpt.js","sourceRoot":"","sources":["../../../src/auth/oauth/openai-chatgpt.ts"],"names":[],"mappings":"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","sourcesContent":["/** Direct OpenAI Responses API token sharing through Sign in with ChatGPT. */\nimport { randomBytes } from \"node:crypto\";\nimport { createServer, type Server, type ServerResponse } from \"node:http\";\nimport { oauthErrorHtml, oauthSuccessHtml } from \"../../utils/oauth-page.ts\";\nimport { getProviderEnvValue } from \"../../utils/provider-env.ts\";\nimport type { LoginOptions, OAuthAuth, OAuthCredential, ProviderAuthInteraction } from \"../types.ts\";\nimport { generatePKCE } from \"./pkce.ts\";\n\nconst DYNAMIC_CLIENT_ID = \"dynamic_agent_client\";\nconst AGENT_NAME_HINT = \"Atomic\";\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst AUTHORIZE_URL = \"https://auth.openai.com/api/accounts/authorize\";\nconst TOKEN_URL = \"https://auth.openai.com/api/accounts/oauth/token\";\nconst RESOURCE = \"https://api.openai.com/v1\";\nconst CALLBACK_HOST = getProviderEnvValue(\"PI_OAUTH_CALLBACK_HOST\") || \"127.0.0.1\";\nconst CALLBACK_PORT = 1455;\nconst CALLBACK_PATH = \"/auth/callback\";\nconst REDIRECT_URI = `http://127.0.0.1:${CALLBACK_PORT}${CALLBACK_PATH}`;\nconst DIRECT_TOKEN_SCOPE = \"chatgpt.tokens.use.direct\";\nconst SCOPE = `openid profile email offline_access resource.invoke ${DIRECT_TOKEN_SCOPE}`;\nconst EXPIRY_MARGIN_MS = 3 * 60 * 1000;\n\ntype AuthorizationResult = { code: string; clientId: string };\ntype CallbackServer = { server: Server; result: Promise<AuthorizationResult> };\ntype TokenResponse = {\n\taccess_token?: unknown;\n\trefresh_token?: unknown;\n\texpires_in?: unknown;\n\tid_token?: unknown;\n\tscope?: unknown;\n};\n\nfunction randomValue(): string {\n\treturn randomBytes(32).toString(\"base64url\");\n}\n\nfunction authorizationResultFromCallback(url: URL, expectedState: string): AuthorizationResult {\n\tconst code = url.searchParams.get(\"code\");\n\tif (!code) throw new Error(\"Missing authorization code\");\n\tconst state = url.searchParams.get(\"state\");\n\tif (!state) throw new Error(\"Missing OAuth state\");\n\tif (state !== expectedState) throw new Error(\"OAuth state mismatch\");\n\tconst clientId = url.searchParams.get(\"client_id\")?.trim();\n\tif (!clientId) throw new Error(\"OpenAI OAuth registration callback did not contain an issued client ID\");\n\treturn { code, clientId };\n}\n\nfunction authorizationResultFromManualInput(input: string, expectedState: string): AuthorizationResult {\n\tlet url: URL;\n\ttry {\n\t\turl = new URL(input.trim());\n\t} catch {\n\t\tthrow new Error(\"Paste the full callback URL from the browser\");\n\t}\n\tconst expected = new URL(REDIRECT_URI);\n\tif (url.origin !== expected.origin || url.pathname !== expected.pathname) {\n\t\tthrow new Error(`The pasted callback URL must start with ${REDIRECT_URI}`);\n\t}\n\tconst error = url.searchParams.get(\"error\");\n\tif (error) throw new Error(`ChatGPT authorization failed: ${error}`);\n\treturn authorizationResultFromCallback(url, expectedState);\n}\n\nfunction sendHtml(response: ServerResponse, status: number, body: string): void {\n\tresponse.writeHead(status, { \"Content-Type\": \"text/html; charset=utf-8\" });\n\tresponse.end(body);\n}\n\nfunction startCallbackServer(expectedState: string): Promise<CallbackServer> {\n\treturn new Promise((resolve, reject) => {\n\t\tlet resolveResult!: (result: AuthorizationResult) => void;\n\t\tlet rejectResult!: (error: Error) => void;\n\t\tconst result = new Promise<AuthorizationResult>((resolveAuthorization, rejectAuthorization) => {\n\t\t\tresolveResult = resolveAuthorization;\n\t\t\trejectResult = rejectAuthorization;\n\t\t});\n\t\tconst server = createServer((request, response) => {\n\t\t\ttry {\n\t\t\t\tconst url = new URL(request.url || \"\", REDIRECT_URI);\n\t\t\t\tif (url.pathname !== CALLBACK_PATH) {\n\t\t\t\t\tsendHtml(response, 404, oauthErrorHtml(\"Callback route not found.\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst error = url.searchParams.get(\"error\");\n\t\t\t\tif (error) {\n\t\t\t\t\tsendHtml(response, 400, oauthErrorHtml(\"ChatGPT was not connected.\", `Error: ${error}`));\n\t\t\t\t\trejectResult(new Error(`ChatGPT authorization failed: ${error}`));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlet authorizationResult: AuthorizationResult;\n\t\t\t\ttry {\n\t\t\t\t\tauthorizationResult = authorizationResultFromCallback(url, expectedState);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconst message = error instanceof Error ? error.message : \"Invalid callback\";\n\t\t\t\t\tsendHtml(response, 400, oauthErrorHtml(message));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tsendHtml(response, 200, oauthSuccessHtml(\"ChatGPT authentication completed. You can close this window.\"));\n\t\t\t\tresolveResult(authorizationResult);\n\t\t\t} catch {\n\t\t\t\tsendHtml(response, 500, oauthErrorHtml(\"Internal error while processing the callback.\"));\n\t\t\t}\n\t\t});\n\t\tserver.once(\"error\", reject);\n\t\tserver.listen(CALLBACK_PORT, CALLBACK_HOST, () => {\n\t\t\tserver.removeListener(\"error\", reject);\n\t\t\tserver.on(\"error\", rejectResult);\n\t\t\tresolve({ server, result });\n\t\t});\n\t});\n}\n\nasync function requestToken(body: URLSearchParams, signal: AbortSignal): Promise<TokenResponse> {\n\tconst response = await fetch(TOKEN_URL, {\n\t\tmethod: \"POST\",\n\t\theaders: { accept: \"application/json\", \"content-type\": \"application/x-www-form-urlencoded\" },\n\t\tbody,\n\t\tsignal,\n\t});\n\tif (!response.ok) {\n\t\tconst responseBody = await response.text().catch(() => \"\");\n\t\tthrow new Error(`OpenAI OAuth token request failed (${response.status}): ${responseBody || response.statusText}`);\n\t}\n\tconst data: unknown = await response.json();\n\tif (typeof data !== \"object\" || data === null || Array.isArray(data)) {\n\t\tthrow new Error(\"OpenAI OAuth token response must be an object\");\n\t}\n\treturn data as TokenResponse;\n}\n\nfunction requireTokenString(value: unknown, field: \"access_token\" | \"refresh_token\" | \"scope\"): string {\n\tif (typeof value !== \"string\" || value.trim().length === 0) {\n\t\tthrow new Error(`OpenAI OAuth token response has invalid ${field}`);\n\t}\n\treturn value;\n}\n\nfunction credentialFromTokenResponse(token: TokenResponse, clientId: string): OAuthCredential {\n\tconst access = requireTokenString(token.access_token, \"access_token\");\n\tconst refresh = requireTokenString(token.refresh_token, \"refresh_token\");\n\tconst scope = requireTokenString(token.scope, \"scope\");\n\tif (typeof token.expires_in !== \"number\" || !Number.isFinite(token.expires_in) || token.expires_in <= 0) {\n\t\tthrow new Error(\"OpenAI OAuth token response has invalid expires_in\");\n\t}\n\tconst scopes = scope.trim().split(/\\s+/).filter(Boolean);\n\tif (!scopes.includes(DIRECT_TOKEN_SCOPE)) {\n\t\tthrow new Error(`OpenAI OAuth grant did not include ${DIRECT_TOKEN_SCOPE}`);\n\t}\n\treturn {\n\t\ttype: \"oauth\",\n\t\taccess,\n\t\trefresh,\n\t\texpires: Date.now() + token.expires_in * 1000 - EXPIRY_MARGIN_MS,\n\t\tclientId,\n\t\tscopes,\n\t};\n}\n\nasync function exchangeAuthorizationCode(\n\tcode: string,\n\tverifier: string,\n\tclientId: string,\n\tsignal: AbortSignal,\n): Promise<OAuthCredential> {\n\tconst token = await requestToken(\n\t\tnew URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tclient_id: clientId,\n\t\t\tcode,\n\t\t\tcode_verifier: verifier,\n\t\t\tredirect_uri: REDIRECT_URI,\n\t\t\tresource: RESOURCE,\n\t\t}),\n\t\tsignal,\n\t);\n\t// The ID token is required by the response contract, but is not used for profile data.\n\tif (typeof token.id_token !== \"string\" || token.id_token.trim().length === 0) {\n\t\tthrow new Error(\"OpenAI OAuth token response did not contain an ID token\");\n\t}\n\treturn credentialFromTokenResponse(token, clientId);\n}\n\nasync function refreshAccessToken(credential: OAuthCredential, signal: AbortSignal): Promise<OAuthCredential> {\n\tconst clientId = credential.clientId;\n\tif (typeof clientId !== \"string\" || clientId.trim().length === 0) {\n\t\tthrow new Error(\"Stored OpenAI OAuth credential does not contain an issued client ID; reconnect ChatGPT\");\n\t}\n\tconst token = await requestToken(\n\t\tnew URLSearchParams({\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tclient_id: clientId,\n\t\t\trefresh_token: credential.refresh,\n\t\t\tresource: RESOURCE,\n\t\t}),\n\t\tsignal,\n\t);\n\treturn credentialFromTokenResponse(token, clientId);\n}\n\nfunction agentHostId(deviceId: string | undefined): string {\n\tif (!deviceId || !UUID_PATTERN.test(deviceId)) {\n\t\tthrow new Error(\"Sign in with ChatGPT requires a device ID (UUID) for this installation\");\n\t}\n\treturn `urn:uuid:${deviceId.toLowerCase()}`;\n}\n\nasync function loginOpenAIChatGPT(\n\tinteraction: ProviderAuthInteraction,\n\toptions?: LoginOptions,\n): Promise<OAuthCredential> {\n\tconst hostId = agentHostId(options?.getDeviceId?.());\n\tconst { verifier, challenge } = await generatePKCE();\n\tconst state = randomValue();\n\tconst nonce = randomValue();\n\tlet callback: CallbackServer | undefined;\n\ttry {\n\t\tcallback = await startCallbackServer(state);\n\t} catch (error) {\n\t\t// A port held by another pending login or the Codex CLI would receive the browser's callback and\n\t\t// reject it as a state mismatch, so fail with a clear error instead of offering the paste prompt.\n\t\tif (error instanceof Error && \"code\" in error && error.code === \"EADDRINUSE\") {\n\t\t\tthrow new Error(\n\t\t\t\t`Port ${CALLBACK_PORT} is in use, probably by an unfinished login in another Atomic session or by the Codex CLI. Cancel that login and try again.`,\n\t\t\t);\n\t\t}\n\t\tinteraction.notify({\n\t\t\ttype: \"info\",\n\t\t\tmessage: `Could not listen on ${REDIRECT_URI}; paste the final redirect URL to continue. ${error instanceof Error ? error.message : String(error)}`,\n\t\t});\n\t}\n\tconst authorizationUrl = new URL(AUTHORIZE_URL);\n\tauthorizationUrl.search = new URLSearchParams({\n\t\tclient_id: DYNAMIC_CLIENT_ID,\n\t\tagent_name_hint: AGENT_NAME_HINT,\n\t\text_agent_host_id: hostId,\n\t\tresponse_type: \"code\",\n\t\tredirect_uri: REDIRECT_URI,\n\t\tresource: RESOURCE,\n\t\tscope: SCOPE,\n\t\tstate,\n\t\tcode_challenge: challenge,\n\t\tcode_challenge_method: \"S256\",\n\t\tnonce,\n\t}).toString();\n\tinteraction.notify({\n\t\ttype: \"auth_url\",\n\t\turl: authorizationUrl.toString(),\n\t\tinstructions:\n\t\t\t\"Complete sign-in in your browser. If the callback does not complete, paste the final redirect URL here.\",\n\t});\n\tconst manualAbort = new AbortController();\n\tconst manualCode = interaction\n\t\t.prompt({\n\t\t\ttype: \"manual_code\",\n\t\t\tmessage: \"Complete login in your browser, or paste the final redirect URL here:\",\n\t\t\tplaceholder: REDIRECT_URI,\n\t\t\tsignal: AbortSignal.any([manualAbort.signal, interaction.signal]),\n\t\t})\n\t\t.then((input) => authorizationResultFromManualInput(input, state));\n\ttry {\n\t\tconst result = await (callback ? Promise.race([callback.result, manualCode]) : manualCode);\n\t\tinteraction.notify({ type: \"progress\", message: \"Exchanging authorization code for tokens...\" });\n\t\treturn await exchangeAuthorizationCode(result.code, verifier, result.clientId, interaction.signal);\n\t} catch (error) {\n\t\tif (interaction.signal.aborted) throw new Error(\"Login cancelled\");\n\t\tthrow error;\n\t} finally {\n\t\tmanualAbort.abort();\n\t\tcallback?.server.close();\n\t\t// Spare browser connections must not deliver a later login to this old server.\n\t\tcallback?.server.closeAllConnections();\n\t}\n}\n\nexport const openaiChatGPTOAuth: OAuthAuth = {\n\tname: \"OpenAI (ChatGPT subscription)\",\n\tusesCallbackServer: true,\n\tisSubscription: true,\n\tloginLabel: \"Sign in with ChatGPT\",\n\tlogin: loginOpenAIChatGPT,\n\trefresh: refreshAccessToken,\n\tasync toAuth(credential) {\n\t\treturn { apiKey: credential.access };\n\t},\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"schemaVersion":6,"generatedAt":"2026-10-
|
|
1
|
+
{"schemaVersion":6,"generatedAt":"2026-10-03T02:59:58.302Z","structureHash":"b48e1997f871abcbd98b3a68eb9875798b237290b0aa4b57b2e4198f0b92356c","files":{"amazon-bedrock.json":"ad077e3178b52c63019a9409150e1d8e4210ed942cc226684972118d02961b26","ant-ling.json":"628feab3ef6c7d80ce96f75999804e1d9f05fec3851e5302e30fff3b69db90f6","anthropic.json":"c436c0f1f984e0a04f9d472533c20ce38c8da101d23484d6d7fe7892cdaa6830","azure-openai-responses.json":"bddff8380252746bbf6ee9901d6299e00ec0cc38facb6013b46b43c6ef231fdd","baseten.json":"b04d1423d6958bec857ffccc36726f091ec1a8f3a09cf0836b64cc94b0ee697d","cerebras.json":"3eccb58c5de3d0dc7ba49dc6e477ba29f00cb3150ce0a35cc90d59e6b5ab368e","cloudflare-ai-gateway.json":"52fdf8d6a45d6412ccd47577b23095f4a20123f058ea1b9b35202bc9188fa40e","cloudflare-workers-ai.json":"d04336a61cacfd0cadbc2f3d30cd3b552e3d153e5a320658a31ba1bab8f01c83","deepseek.json":"10a296fb3e898f7715c80890c8af0af4f5fd58f22dbcd6612fdc5d762157ccdc","fireworks.json":"8db3c11f65a5d76260d5040a5dc5a9ef0f35b92de8505a30907c2355c2837b36","github-copilot.json":"2362c7f129b6fca87ac45e06463ddb0f080477f820fd4eba55c150b0aeb99cba","google-vertex.json":"40090c680538bc867f2624d986a449f361be4dfa6ba96d7a27402050f036e009","google.json":"c0f5a633e5e5a5044432db3e537f4bc674d4de18df09325c6349547fcc13cabe","groq.json":"910952ad9dad07856983459d63fce0148dba1203edd7b10d801a77c5824f3405","huggingface.json":"1b8604bd31a5e05fe43a40ec1ec6dfc1a51a28b0b020151ef057fab43f57c923","kimi-coding.json":"582250b920454d98940da3e7e99d30b807edbea28f2eb8ac15f658d2ef41e8fc","meta.json":"0c7e9a370a7005c5a89dc94f0f93bc67b8935c3f802de324f11af6ff56fff429","minimax-cn.json":"f962c20ee6a6a342820f778e9dc363a18a524bf11998f6e2c57f2989915d62e5","minimax.json":"17a432f80d0ea6dd26eade80a4314250d3a855678601728a5f70dd8fa0d21dd2","mistral.json":"10f33bff9adf1248f7e6848e5890c265399f1f94e5b42cfdc28c109d547af98d","moonshotai-cn.json":"79c9585dc84ee525ebaebbc78b3c55f3d369ec884d4f943488f1e0b14e3587f5","moonshotai.json":"1da2c4e34f22aef17a07c974d85bdee8e1b68b6dc712e3769c935b3f1e7dadca","nvidia.json":"a75e963dc81779e3eec01c051b12277c15ec37c5b94ab51ece9e9ccb3b16407c","openai-codex.json":"0c6c33c094d3175641a64a13215aa3b8c229964bb2c896e04cac1e2d2edf4a63","openai.json":"31e704f9e0ce46d0c2265eacd51a8d80e64ac52d5f3ca9679880fc0e0d79e057","opencode-go.json":"d05b3eb87b81c6e5a94801484e668e660fe60c68f06a972b716d581c3bbd7c25","opencode.json":"a09e138be9aa51117950614674197c9ee700594e2c1fbd339783d1a7c6ab90e2","openrouter.json":"cc78aa420737f34288bb4c3994e340c9f592094128a045a40d49cfb52093ef3d","qwen-token-plan-cn.json":"2469a4091c474ec3db0a49a9962d8d2726c074ad9065b96bc4e0c87861c4c6c5","qwen-token-plan-individual.json":"0fb7cf64faf39d1a3b0a884210a86c87084b805eda15644f5f39293287b959dd","qwen-token-plan.json":"eff10620cb577142de4ec02698d5961a71fda2fe4f6ae7ea9432bad9d6844176","radius.json":"2a161f9d1ef2618ee7ace421cc10ee1c7ecc89e122d32937ef5d9a31444bdb23","together.json":"52293df62191c8e799ae3632f8ab1b3f52ee626aee0280677086627b32864bf7","typesafe.json":"a4429a2f696d5cc5273969af61a7310bda07d6bdcd27bf9ac9c76c534cc43716","vercel-ai-gateway.json":"f6fb592b4864e133fd75d12cc8b98947fc6cca77c4a1f40a4bca89cc44f2c13a","xai.json":"879c49b78b663a52a220ac4ee013e726b10c4f50aaa03bc58ee53a4b54c76928","xiaomi-token-plan-ams.json":"ca65178f4525d9705bc8d085ed136cecbe149c4080e857ea6a64ae643d2ac00a","xiaomi-token-plan-cn.json":"b065326926681c2262084e59c1c19ebdaf146c07107b5242c76b456becf74db0","xiaomi-token-plan-sgp.json":"92c3d6d707f81fd9cd2b6d1fb57dc431d90ba51e10fe49d97bc8806035c23492","xiaomi.json":"b81d01a374f7b558728c78d81f4168efa9c8996e6e2b5618409a8094b083c759","zai-coding-cn.json":"ee5ee705fb6e413a6088db5e3616c27fce802a8ece6c355f1db35490d787f610","zai.json":"58e6642fdfb736f0b9a4a277c760c536a3cea66a030abbfb2615f7b2851d5c6f"}}
|