@bastani/pi-ai 0.9.14 → 0.9.15
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 +72 -0
- package/NOTICE.md +4 -5
- package/README.md +6 -4
- package/dist/api/anthropic-messages.d.ts.map +1 -1
- package/dist/api/anthropic-messages.js +55 -25
- package/dist/api/anthropic-messages.js.map +1 -1
- package/dist/api/azure-openai-responses.d.ts +2 -0
- package/dist/api/azure-openai-responses.d.ts.map +1 -1
- package/dist/api/azure-openai-responses.js +9 -2
- package/dist/api/azure-openai-responses.js.map +1 -1
- package/dist/api/bedrock-converse-stream.d.ts.map +1 -1
- package/dist/api/bedrock-converse-stream.js +132 -8
- package/dist/api/bedrock-converse-stream.js.map +1 -1
- package/dist/api/github-copilot-headers.d.ts +22 -1
- package/dist/api/github-copilot-headers.d.ts.map +1 -1
- package/dist/api/github-copilot-headers.js +30 -0
- package/dist/api/github-copilot-headers.js.map +1 -1
- package/dist/api/google-generative-ai.d.ts +2 -2
- package/dist/api/google-generative-ai.d.ts.map +1 -1
- package/dist/api/google-generative-ai.js +28 -18
- package/dist/api/google-generative-ai.js.map +1 -1
- package/dist/api/google-shared.d.ts +5 -2
- package/dist/api/google-shared.d.ts.map +1 -1
- package/dist/api/google-shared.js +16 -0
- package/dist/api/google-shared.js.map +1 -1
- package/dist/api/google-vertex.d.ts +2 -2
- package/dist/api/google-vertex.d.ts.map +1 -1
- package/dist/api/google-vertex.js +15 -11
- package/dist/api/google-vertex.js.map +1 -1
- package/dist/api/mistral-conversations.d.ts.map +1 -1
- package/dist/api/mistral-conversations.js +15 -5
- package/dist/api/mistral-conversations.js.map +1 -1
- package/dist/api/openai-codex-responses.d.ts.map +1 -1
- package/dist/api/openai-codex-responses.js +15 -6
- package/dist/api/openai-codex-responses.js.map +1 -1
- package/dist/api/openai-completions.d.ts +3 -2
- package/dist/api/openai-completions.d.ts.map +1 -1
- package/dist/api/openai-completions.js +142 -94
- package/dist/api/openai-completions.js.map +1 -1
- package/dist/api/openai-responses.d.ts.map +1 -1
- package/dist/api/openai-responses.js +20 -10
- package/dist/api/openai-responses.js.map +1 -1
- package/dist/api/pi-messages.d.ts.map +1 -1
- package/dist/api/pi-messages.js +23 -5
- package/dist/api/pi-messages.js.map +1 -1
- package/dist/api/simple-options.d.ts +4 -0
- package/dist/api/simple-options.d.ts.map +1 -1
- package/dist/api/simple-options.js +18 -10
- package/dist/api/simple-options.js.map +1 -1
- package/dist/auth/oauth/device-code.d.ts +1 -0
- package/dist/auth/oauth/device-code.d.ts.map +1 -1
- package/dist/auth/oauth/device-code.js +1 -1
- package/dist/auth/oauth/device-code.js.map +1 -1
- package/dist/auth/oauth/github-copilot.d.ts.map +1 -1
- package/dist/auth/oauth/github-copilot.js +98 -34
- package/dist/auth/oauth/github-copilot.js.map +1 -1
- package/dist/auth/oauth/kimi-coding.d.ts.map +1 -1
- package/dist/auth/oauth/kimi-coding.js +1 -14
- package/dist/auth/oauth/kimi-coding.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.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/anthropic.json +1 -1
- package/dist/providers/data/baseten.json +1 -1
- package/dist/providers/data/cerebras.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/github-copilot.json +1 -1
- package/dist/providers/data/google-vertex.json +1 -1
- package/dist/providers/data/google.json +1 -1
- package/dist/providers/data/huggingface.json +1 -1
- package/dist/providers/data/nvidia.json +1 -1
- package/dist/providers/data/opencode-go.json +1 -1
- package/dist/providers/data/opencode.json +1 -1
- package/dist/providers/data/openrouter.json +1 -1
- package/dist/providers/data/qwen-token-plan-cn.json +1 -1
- package/dist/providers/data/qwen-token-plan-individual.json +1 -1
- package/dist/providers/data/qwen-token-plan.json +1 -1
- package/dist/providers/data/together.json +1 -1
- package/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/dist/providers/data/xai.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-ams.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-cn.json +1 -1
- package/dist/providers/data/xiaomi-token-plan-sgp.json +1 -1
- package/dist/providers/data/xiaomi.json +1 -1
- package/dist/providers/data/zai-coding-cn.json +1 -1
- package/dist/providers/data/zai.json +1 -1
- package/dist/providers/github-copilot-env.d.ts +36 -0
- package/dist/providers/github-copilot-env.d.ts.map +1 -0
- package/dist/providers/github-copilot-env.js +94 -0
- package/dist/providers/github-copilot-env.js.map +1 -0
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.d.ts.map +1 -1
- package/dist/providers/xai.js +1 -5
- package/dist/providers/xai.js.map +1 -1
- package/dist/types.d.ts +43 -5
- 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 +14 -0
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/sleep.d.ts +2 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +15 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/stream-deadline.d.ts +74 -0
- package/dist/utils/stream-deadline.d.ts.map +1 -0
- package/dist/utils/stream-deadline.js +196 -0
- package/dist/utils/stream-deadline.js.map +1 -0
- package/package.json +118 -120
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pi-messages.js","sourceRoot":"","sources":["../../src/api/pi-messages.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * pi-messages API implementation.\n *\n * Streams pi's own message protocol directly to a backend: the request is a\n * single POST of `{ model, context, options }` to `<baseUrl>/messages`, the\n * response is an SSE stream of serialized assistant-message events plus a\n * terminal `done`/`error` event. This is the wire protocol spoken by the\n * Radius gateway, but any backend implementing it can be used, e.g. via a\n * models.json custom provider with `\"api\": \"pi-messages\"`.\n */\n\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tThinkingLevel,\n\tToolCall,\n} from \"../types.ts\";\nimport { appendAssistantMessageDiagnostic, createAssistantMessageDiagnostic } from \"../utils/diagnostics.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { parseStreamingJson } from \"../utils/json-parse.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\n\nexport interface PiMessagesOptions extends StreamOptions {\n\treasoning?: ThinkingLevel;\n\ttoolChoice?: \"auto\" | \"none\" | \"required\" | { type: \"function\"; function: { name: string } };\n\t/** Ask the backend for debug metadata (e.g. routing response headers). */\n\tdebug?: boolean;\n}\n\ntype PiMessagesUsage = AssistantMessage[\"usage\"];\ntype PiMessagesStopReason = AssistantMessage[\"stopReason\"];\n\n/** Impact summary of a server-side message rewrite (e.g. a gateway policy). */\nexport type PiMessagesRewriteImpact = {\n\tpolicyId: string;\n\tpolicyVersion: number;\n\tchanged: boolean;\n\ttokenCountChange: number;\n\tmessageCountChange: number;\n\tsystemPromptChanged: boolean;\n};\n\n/** Serialized assistant-message event as sent by a pi-messages backend. */\nexport type PiMessagesEvent =\n\t| { type: \"start\" }\n\t| { type: \"text_start\"; contentIndex: number }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string }\n\t| { type: \"text_end\"; contentIndex: number; content: string; contentSignature?: string }\n\t| { type: \"thinking_start\"; contentIndex: number }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string }\n\t| {\n\t\t\ttype: \"thinking_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tcontentSignature?: string;\n\t\t\tredacted?: boolean;\n\t }\n\t| { type: \"toolcall_start\"; contentIndex: number; id: string; toolName: string }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n\t| { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: Extract<PiMessagesStopReason, \"stop\" | \"length\" | \"toolUse\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t }\n\t| {\n\t\t\ttype: \"error\";\n\t\t\treason: Extract<PiMessagesStopReason, \"aborted\" | \"error\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\terrorMessage?: string;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t };\n\ntype PiMessagesErrorBody = {\n\terror?: {\n\t\tmessage?: unknown;\n\t\tcode?: unknown;\n\t\tdetails?: unknown;\n\t\t[key: string]: unknown;\n\t};\n};\n\nexport class PiMessagesResponseError extends Error {\n\tcode?: string;\n\treadonly diagnosticDetails: Record<string, unknown>;\n\n\tconstructor(message: string, code: string | undefined, diagnosticDetails: Record<string, unknown>) {\n\t\tsuper(message);\n\t\tthis.name = \"PiMessagesResponseError\";\n\t\tthis.code = code;\n\t\tthis.diagnosticDetails = diagnosticDetails;\n\t}\n}\n\nfunction parsePiMessagesErrorBody(body: string): PiMessagesErrorBody | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(body) as PiMessagesErrorBody | null;\n\t\tconst error = parsed?.error;\n\t\treturn parsed && typeof error === \"object\" && error !== null && !Array.isArray(error) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction truncateDiagnosticString(value: string): string {\n\tconst maxLength = 8192;\n\treturn value.length > maxLength ? `${value.slice(0, maxLength)}…` : value;\n}\n\nfunction formatPiMessagesResponseError(\n\tresponse: Response,\n\tbody: string,\n\terrorBody: PiMessagesErrorBody | undefined,\n): string {\n\tconst message = typeof errorBody?.error?.message === \"string\" ? errorBody.error.message : undefined;\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\tconst suffix = message ?? body;\n\tconst codeSuffix = code ? ` (${code})` : \"\";\n\treturn `${response.status} ${response.statusText}: ${suffix}${codeSuffix}`;\n}\n\nfunction createPiMessagesResponseError(\n\tmodel: Model<\"pi-messages\">,\n\turl: URL,\n\tresponse: Response,\n\tbody: string,\n): PiMessagesResponseError {\n\tconst errorBody = parsePiMessagesErrorBody(body);\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\treturn new PiMessagesResponseError(formatPiMessagesResponseError(response, body, errorBody), code, {\n\t\tversion: 1,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\turl: url.toString(),\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\terror: errorBody?.error,\n\t\tbody: errorBody ? undefined : truncateDiagnosticString(body),\n\t\ttimestampMs: Date.now(),\n\t});\n}\n\nfunction createEmptyUsage(): PiMessagesUsage {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t};\n}\n\nfunction appendRewriteDiagnostic(message: AssistantMessage, rewrite: PiMessagesRewriteImpact | undefined): void {\n\tif (!rewrite) {\n\t\treturn;\n\t}\n\tappendAssistantMessageDiagnostic(message, {\n\t\ttype: \"pi_messages_rewrite\",\n\t\ttimestamp: Date.now(),\n\t\tdetails: { ...rewrite },\n\t});\n}\n\nfunction createEventConverter(model: Model<\"pi-messages\">) {\n\tconst partial: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"pending\",\n\t\ttimestamp: Date.now(),\n\t};\n\tconst toolJson = new Map<number, string>();\n\n\treturn (event: PiMessagesEvent): AssistantMessageEvent => {\n\t\tswitch (event.type) {\n\t\t\tcase \"done\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: event.usage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"done\", reason: event.reason, message: partial };\n\t\t\tcase \"error\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: event.usage,\n\t\t\t\t\terrorMessage: event.errorMessage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"error\", reason: event.reason, error: partial };\n\t\t\tcase \"start\":\n\t\t\t\tbreak;\n\t\t\tcase \"text_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"text\", text: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"text_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { text: string }).text += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"text_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\ttext: event.content,\n\t\t\t\t\ttextSignature: event.contentSignature,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"thinking\", thinking: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { thinking: string }).thinking += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\tthinking: event.content,\n\t\t\t\t\tthinkingSignature: event.contentSignature,\n\t\t\t\t\tredacted: event.redacted,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_start\":\n\t\t\t\tpartial.content[event.contentIndex] = {\n\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\tid: event.id,\n\t\t\t\t\tname: event.toolName,\n\t\t\t\t\targuments: {},\n\t\t\t\t};\n\t\t\t\ttoolJson.set(event.contentIndex, \"\");\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_delta\": {\n\t\t\t\tconst json = `${toolJson.get(event.contentIndex) ?? \"\"}${event.delta}`;\n\t\t\t\ttoolJson.set(event.contentIndex, json);\n\t\t\t\t(partial.content[event.contentIndex] as ToolCall).arguments =\n\t\t\t\t\tparseStreamingJson<ToolCall[\"arguments\"]>(json);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"toolcall_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, event.toolCall);\n\t\t\t\ttoolJson.delete(event.contentIndex);\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\t\ttoolCall: partial.content[event.contentIndex] as ToolCall,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t}\n\n\t\treturn { ...event, partial } as AssistantMessageEvent;\n\t};\n}\n\nasync function* readPiMessagesEvents(stream: ReadableStream<Uint8Array>): AsyncGenerator<PiMessagesEvent> {\n\tconst decoder = new TextDecoder();\n\tconst reader = stream.getReader();\n\tlet buffer = \"\";\n\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tbuffer += done ? decoder.decode() : decoder.decode(value, { stream: true });\n\t\t\tbuffer = buffer.replace(/\\r\\n/g, \"\\n\");\n\n\t\t\tlet split = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (split !== -1) {\n\t\t\t\tconst event = parsePiMessagesEvent(buffer.slice(0, split));\n\t\t\t\tif (event) {\n\t\t\t\t\tyield event;\n\t\t\t\t}\n\t\t\t\tbuffer = buffer.slice(split + 2);\n\t\t\t\tsplit = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (buffer.trim()) {\n\t\t\tconst event = parsePiMessagesEvent(buffer);\n\t\t\tif (event) {\n\t\t\t\tyield event;\n\t\t\t}\n\t\t}\n\t} finally {\n\t\treader.releaseLock();\n\t}\n}\n\nfunction parsePiMessagesEvent(raw: string): PiMessagesEvent | undefined {\n\tconst data = raw\n\t\t.split(\"\\n\")\n\t\t.find((line) => line.startsWith(\"data:\"))\n\t\t?.slice(5)\n\t\t.trim();\n\n\treturn data && data !== \"[DONE]\" ? (JSON.parse(data) as PiMessagesEvent) : undefined;\n}\n\nfunction createErrorEvent(model: Model<\"pi-messages\">, error: unknown, aborted: boolean): AssistantMessageEvent {\n\tconst reason = aborted ? \"aborted\" : \"error\";\n\tconst assistantMessage: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: reason,\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n\n\tif (!aborted && error instanceof PiMessagesResponseError) {\n\t\tappendAssistantMessageDiagnostic(\n\t\t\tassistantMessage,\n\t\t\tcreateAssistantMessageDiagnostic(\"pi_messages_response_failure\", error, error.diagnosticDetails),\n\t\t);\n\t}\n\n\treturn { type: \"error\", reason, error: assistantMessage };\n}\n\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention | undefined {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\t// Backend defaults apply when unset; only the legacy env opt-in is mapped.\n\treturn getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\" ? \"long\" : undefined;\n}\n\nexport const stream: StreamFunction<\"pi-messages\", PiMessagesOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: PiMessagesOptions,\n): AssistantMessageEventStream => {\n\tconst eventStream = new AssistantMessageEventStream();\n\tconst convertEvent = createEventConverter(model);\n\n\tvoid (async () => {\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key provided for provider \"${model.provider}\"`);\n\t\t\t}\n\n\t\t\tconst url = new URL(`${model.baseUrl.replace(/\\/+$/u, \"\")}/messages`);\n\t\t\tif (options?.debug) {\n\t\t\t\turl.searchParams.set(\"debug\", \"1\");\n\t\t\t}\n\n\t\t\tlet payload: unknown = {\n\t\t\t\tmodel: model.id,\n\t\t\t\tcontext,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options?.temperature,\n\t\t\t\t\tmaxTokens: options?.maxTokens,\n\t\t\t\t\treasoning: options?.reasoning,\n\t\t\t\t\tcacheRetention: resolveCacheRetention(options?.cacheRetention, options?.env),\n\t\t\t\t\tsessionId: options?.sessionId,\n\t\t\t\t\ttoolChoice: options?.toolChoice,\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst nextPayload = await options?.onPayload?.(payload, model);\n\t\t\tif (nextPayload !== undefined) {\n\t\t\t\tpayload = nextPayload;\n\t\t\t}\n\n\t\t\tconst response = await (options?.fetch ?? globalThis.fetch)(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${apiKey}`,\n\t\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\t...providerHeadersToRecord(options?.headers),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\tsignal: options?.signal,\n\t\t\t});\n\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst body = await response.text();\n\t\t\t\tthrow createPiMessagesResponseError(model, url, response, body);\n\t\t\t}\n\t\t\tif (!response.body) {\n\t\t\t\tthrow new Error(`${model.provider} response has no body`);\n\t\t\t}\n\n\t\t\tfor await (const piEvent of readPiMessagesEvents(response.body)) {\n\t\t\t\tconst event = convertEvent(piEvent);\n\t\t\t\teventStream.push(event);\n\t\t\t\tif (event.type === \"done\" || event.type === \"error\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new Error(`${model.provider} stream ended without a terminal event`);\n\t\t} catch (error) {\n\t\t\teventStream.push(createErrorEvent(model, error, options?.signal?.aborted ?? false));\n\t\t}\n\t})();\n\n\treturn eventStream;\n};\n\nexport const streamSimple: StreamFunction<\"pi-messages\", SimpleStreamOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst extra = options as PiMessagesOptions | undefined;\n\treturn stream(model, context, {\n\t\t...options,\n\t\treasoning: options?.reasoning,\n\t\ttoolChoice: extra?.toolChoice,\n\t\tdebug: extra?.debug,\n\t});\n};\n"]}
|
|
1
|
+
{"version":3,"file":"pi-messages.js","sourceRoot":"","sources":["../../src/api/pi-messages.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * pi-messages API implementation.\n *\n * Streams pi's own message protocol directly to a backend: the request is a\n * single POST of `{ model, context, options }` to `<baseUrl>/messages`, the\n * response is an SSE stream of serialized assistant-message events plus a\n * terminal `done`/`error` event. This is the wire protocol spoken by the\n * Radius gateway, but any backend implementing it can be used, e.g. via a\n * models.json custom provider with `\"api\": \"pi-messages\"`.\n */\n\nimport type {\n\tAssistantMessage,\n\tAssistantMessageEvent,\n\tCacheRetention,\n\tContext,\n\tModel,\n\tProviderEnv,\n\tSimpleStreamOptions,\n\tStreamFunction,\n\tStreamOptions,\n\tThinkingLevel,\n\tToolCall,\n} from \"../types.ts\";\nimport { appendAssistantMessageDiagnostic, createAssistantMessageDiagnostic } from \"../utils/diagnostics.ts\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.ts\";\nimport { headersToRecord, providerHeadersToRecord } from \"../utils/headers.ts\";\nimport { parseStreamingJson } from \"../utils/json-parse.ts\";\nimport { createStreamDeadline, withStreamDeadline } from \"../utils/stream-deadline.ts\";\nimport { getProviderEnvValue } from \"../utils/provider-env.ts\";\n\nexport interface PiMessagesOptions extends StreamOptions {\n\treasoning?: ThinkingLevel;\n\ttoolChoice?: \"auto\" | \"none\" | \"required\" | { type: \"function\"; function: { name: string } };\n\t/** Ask the backend for debug metadata (e.g. routing response headers). */\n\tdebug?: boolean;\n}\n\ntype PiMessagesUsage = AssistantMessage[\"usage\"];\ntype PiMessagesStopReason = AssistantMessage[\"stopReason\"];\n\n/** Impact summary of a server-side message rewrite (e.g. a gateway policy). */\nexport type PiMessagesRewriteImpact = {\n\tpolicyId: string;\n\tpolicyVersion: number;\n\tchanged: boolean;\n\ttokenCountChange: number;\n\tmessageCountChange: number;\n\tsystemPromptChanged: boolean;\n};\n\n/** Serialized assistant-message event as sent by a pi-messages backend. */\nexport type PiMessagesEvent =\n\t| { type: \"start\" }\n\t| { type: \"text_start\"; contentIndex: number }\n\t| { type: \"text_delta\"; contentIndex: number; delta: string }\n\t| { type: \"text_end\"; contentIndex: number; content: string; contentSignature?: string }\n\t| { type: \"thinking_start\"; contentIndex: number }\n\t| { type: \"thinking_delta\"; contentIndex: number; delta: string }\n\t| {\n\t\t\ttype: \"thinking_end\";\n\t\t\tcontentIndex: number;\n\t\t\tcontent: string;\n\t\t\tcontentSignature?: string;\n\t\t\tredacted?: boolean;\n\t }\n\t| { type: \"toolcall_start\"; contentIndex: number; id: string; toolName: string }\n\t| { type: \"toolcall_delta\"; contentIndex: number; delta: string }\n\t| { type: \"toolcall_end\"; contentIndex: number; toolCall: ToolCall }\n\t| {\n\t\t\ttype: \"done\";\n\t\t\treason: Extract<PiMessagesStopReason, \"stop\" | \"length\" | \"toolUse\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t }\n\t| {\n\t\t\ttype: \"error\";\n\t\t\treason: Extract<PiMessagesStopReason, \"aborted\" | \"error\">;\n\t\t\tusage: PiMessagesUsage;\n\t\t\terrorMessage?: string;\n\t\t\tresponseId?: string;\n\t\t\trewrite?: PiMessagesRewriteImpact;\n\t };\n\ntype PiMessagesErrorBody = {\n\terror?: {\n\t\tmessage?: unknown;\n\t\tcode?: unknown;\n\t\tdetails?: unknown;\n\t\t[key: string]: unknown;\n\t};\n};\n\nexport class PiMessagesResponseError extends Error {\n\tcode?: string;\n\treadonly diagnosticDetails: Record<string, unknown>;\n\n\tconstructor(message: string, code: string | undefined, diagnosticDetails: Record<string, unknown>) {\n\t\tsuper(message);\n\t\tthis.name = \"PiMessagesResponseError\";\n\t\tthis.code = code;\n\t\tthis.diagnosticDetails = diagnosticDetails;\n\t}\n}\n\nfunction parsePiMessagesErrorBody(body: string): PiMessagesErrorBody | undefined {\n\ttry {\n\t\tconst parsed = JSON.parse(body) as PiMessagesErrorBody | null;\n\t\tconst error = parsed?.error;\n\t\treturn parsed && typeof error === \"object\" && error !== null && !Array.isArray(error) ? parsed : undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nfunction truncateDiagnosticString(value: string): string {\n\tconst maxLength = 8192;\n\treturn value.length > maxLength ? `${value.slice(0, maxLength)}…` : value;\n}\n\nfunction formatPiMessagesResponseError(\n\tresponse: Response,\n\tbody: string,\n\terrorBody: PiMessagesErrorBody | undefined,\n): string {\n\tconst message = typeof errorBody?.error?.message === \"string\" ? errorBody.error.message : undefined;\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\tconst suffix = message ?? body;\n\tconst codeSuffix = code ? ` (${code})` : \"\";\n\treturn `${response.status} ${response.statusText}: ${suffix}${codeSuffix}`;\n}\n\nfunction createPiMessagesResponseError(\n\tmodel: Model<\"pi-messages\">,\n\turl: URL,\n\tresponse: Response,\n\tbody: string,\n): PiMessagesResponseError {\n\tconst errorBody = parsePiMessagesErrorBody(body);\n\tconst code = typeof errorBody?.error?.code === \"string\" ? errorBody.error.code : undefined;\n\treturn new PiMessagesResponseError(formatPiMessagesResponseError(response, body, errorBody), code, {\n\t\tversion: 1,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\turl: url.toString(),\n\t\tstatus: response.status,\n\t\tstatusText: response.statusText,\n\t\terror: errorBody?.error,\n\t\tbody: errorBody ? undefined : truncateDiagnosticString(body),\n\t\ttimestampMs: Date.now(),\n\t});\n}\n\nfunction createEmptyUsage(): PiMessagesUsage {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotalTokens: 0,\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t};\n}\n\nfunction appendRewriteDiagnostic(message: AssistantMessage, rewrite: PiMessagesRewriteImpact | undefined): void {\n\tif (!rewrite) {\n\t\treturn;\n\t}\n\tappendAssistantMessageDiagnostic(message, {\n\t\ttype: \"pi_messages_rewrite\",\n\t\ttimestamp: Date.now(),\n\t\tdetails: { ...rewrite },\n\t});\n}\n\nfunction createEventConverter(model: Model<\"pi-messages\">) {\n\tconst partial: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: \"pending\",\n\t\ttimestamp: Date.now(),\n\t};\n\tconst toolJson = new Map<number, string>();\n\n\treturn (event: PiMessagesEvent): AssistantMessageEvent => {\n\t\tswitch (event.type) {\n\t\t\tcase \"done\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: event.usage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"done\", reason: event.reason, message: partial };\n\t\t\tcase \"error\":\n\t\t\t\tObject.assign(partial, {\n\t\t\t\t\tstopReason: event.reason,\n\t\t\t\t\tusage: event.usage,\n\t\t\t\t\terrorMessage: event.errorMessage,\n\t\t\t\t\tresponseId: event.responseId,\n\t\t\t\t});\n\t\t\t\tappendRewriteDiagnostic(partial, event.rewrite);\n\t\t\t\treturn { type: \"error\", reason: event.reason, error: partial };\n\t\t\tcase \"start\":\n\t\t\t\tbreak;\n\t\t\tcase \"text_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"text\", text: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"text_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { text: string }).text += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"text_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\ttext: event.content,\n\t\t\t\t\ttextSignature: event.contentSignature,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_start\":\n\t\t\t\tpartial.content[event.contentIndex] = { type: \"thinking\", thinking: \"\" };\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_delta\":\n\t\t\t\t(partial.content[event.contentIndex] as { thinking: string }).thinking += event.delta;\n\t\t\t\tbreak;\n\t\t\tcase \"thinking_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, {\n\t\t\t\t\tthinking: event.content,\n\t\t\t\t\tthinkingSignature: event.contentSignature,\n\t\t\t\t\tredacted: event.redacted,\n\t\t\t\t});\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_start\":\n\t\t\t\tpartial.content[event.contentIndex] = {\n\t\t\t\t\ttype: \"toolCall\",\n\t\t\t\t\tid: event.id,\n\t\t\t\t\tname: event.toolName,\n\t\t\t\t\targuments: {},\n\t\t\t\t};\n\t\t\t\ttoolJson.set(event.contentIndex, \"\");\n\t\t\t\tbreak;\n\t\t\tcase \"toolcall_delta\": {\n\t\t\t\tconst json = `${toolJson.get(event.contentIndex) ?? \"\"}${event.delta}`;\n\t\t\t\ttoolJson.set(event.contentIndex, json);\n\t\t\t\t(partial.content[event.contentIndex] as ToolCall).arguments =\n\t\t\t\t\tparseStreamingJson<ToolCall[\"arguments\"]>(json);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"toolcall_end\":\n\t\t\t\tObject.assign(partial.content[event.contentIndex]!, event.toolCall);\n\t\t\t\ttoolJson.delete(event.contentIndex);\n\t\t\t\treturn {\n\t\t\t\t\ttype: \"toolcall_end\",\n\t\t\t\t\tcontentIndex: event.contentIndex,\n\t\t\t\t\ttoolCall: partial.content[event.contentIndex] as ToolCall,\n\t\t\t\t\tpartial,\n\t\t\t\t};\n\t\t}\n\n\t\treturn { ...event, partial } as AssistantMessageEvent;\n\t};\n}\n\nasync function* readPiMessagesEvents(\n\tstream: ReadableStream<Uint8Array>,\n\tsignal?: AbortSignal,\n): AsyncGenerator<PiMessagesEvent> {\n\tconst decoder = new TextDecoder();\n\tconst reader = stream.getReader();\n\tlet buffer = \"\";\n\tconst onAbort = () => {\n\t\tvoid reader.cancel().catch(() => {});\n\t};\n\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\ttry {\n\t\twhile (true) {\n\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Request was aborted\");\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Request was aborted\");\n\t\t\tbuffer += done ? decoder.decode() : decoder.decode(value, { stream: true });\n\t\t\tbuffer = buffer.replace(/\\r\\n/g, \"\\n\");\n\n\t\t\tlet split = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (split !== -1) {\n\t\t\t\tconst event = parsePiMessagesEvent(buffer.slice(0, split));\n\t\t\t\tif (event) {\n\t\t\t\t\tyield event;\n\t\t\t\t}\n\t\t\t\tbuffer = buffer.slice(split + 2);\n\t\t\t\tsplit = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\n\t\t\tif (done) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (buffer.trim()) {\n\t\t\tconst event = parsePiMessagesEvent(buffer);\n\t\t\tif (event) {\n\t\t\t\tyield event;\n\t\t\t}\n\t\t}\n\t} finally {\n\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\ttry {\n\t\t\tawait reader.cancel();\n\t\t} catch {}\n\t\treader.releaseLock();\n\t}\n}\n\nfunction parsePiMessagesEvent(raw: string): PiMessagesEvent | undefined {\n\tconst data = raw\n\t\t.split(\"\\n\")\n\t\t.find((line) => line.startsWith(\"data:\"))\n\t\t?.slice(5)\n\t\t.trim();\n\n\treturn data && data !== \"[DONE]\" ? (JSON.parse(data) as PiMessagesEvent) : undefined;\n}\n\nfunction createErrorEvent(model: Model<\"pi-messages\">, error: unknown, aborted: boolean): AssistantMessageEvent {\n\tconst reason = aborted ? \"aborted\" : \"error\";\n\tconst assistantMessage: AssistantMessage = {\n\t\trole: \"assistant\",\n\t\tcontent: [],\n\t\tapi: model.api,\n\t\tprovider: model.provider,\n\t\tmodel: model.id,\n\t\tusage: createEmptyUsage(),\n\t\tstopReason: reason,\n\t\terrorMessage: error instanceof Error ? error.message : String(error),\n\t\ttimestamp: Date.now(),\n\t};\n\n\tif (!aborted && error instanceof PiMessagesResponseError) {\n\t\tappendAssistantMessageDiagnostic(\n\t\t\tassistantMessage,\n\t\t\tcreateAssistantMessageDiagnostic(\"pi_messages_response_failure\", error, error.diagnosticDetails),\n\t\t);\n\t}\n\n\treturn { type: \"error\", reason, error: assistantMessage };\n}\n\nfunction resolveCacheRetention(cacheRetention?: CacheRetention, env?: ProviderEnv): CacheRetention | undefined {\n\tif (cacheRetention) {\n\t\treturn cacheRetention;\n\t}\n\t// Backend defaults apply when unset; only the legacy env opt-in is mapped.\n\treturn getProviderEnvValue(\"PI_CACHE_RETENTION\", env) === \"long\" ? \"long\" : undefined;\n}\n\nexport const stream: StreamFunction<\"pi-messages\", PiMessagesOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: PiMessagesOptions,\n): AssistantMessageEventStream => {\n\tconst eventStream = new AssistantMessageEventStream();\n\tconst convertEvent = createEventConverter(model);\n\n\tvoid (async () => {\n\t\tconst streamDeadline = createStreamDeadline(options?.streamDeadlineMs, options?.signal);\n\t\ttry {\n\t\t\tconst apiKey = options?.apiKey;\n\t\t\tif (!apiKey) {\n\t\t\t\tthrow new Error(`No API key provided for provider \"${model.provider}\"`);\n\t\t\t}\n\n\t\t\tconst url = new URL(`${model.baseUrl.replace(/\\/+$/u, \"\")}/messages`);\n\t\t\tif (options?.debug) {\n\t\t\t\turl.searchParams.set(\"debug\", \"1\");\n\t\t\t}\n\n\t\t\tlet payload: unknown = {\n\t\t\t\tmodel: model.id,\n\t\t\t\tcontext,\n\t\t\t\toptions: {\n\t\t\t\t\ttemperature: options?.temperature,\n\t\t\t\t\tmaxTokens: options?.maxTokens,\n\t\t\t\t\treasoning: options?.reasoning,\n\t\t\t\t\tcacheRetention: resolveCacheRetention(options?.cacheRetention, options?.env),\n\t\t\t\t\tsessionId: options?.sessionId,\n\t\t\t\t\ttoolChoice: options?.toolChoice,\n\t\t\t\t},\n\t\t\t};\n\t\t\tconst nextPayload = await options?.onPayload?.(payload, model);\n\t\t\tif (nextPayload !== undefined) {\n\t\t\t\tpayload = nextPayload;\n\t\t\t}\n\n\t\t\tconst response = await (options?.fetch ?? globalThis.fetch)(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tauthorization: `Bearer ${apiKey}`,\n\t\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\t...providerHeadersToRecord({ ...model.headers, ...options?.headers }),\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(payload),\n\t\t\t\tsignal: streamDeadline.signal,\n\t\t\t});\n\n\t\t\tawait options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);\n\n\t\t\tif (!response.ok) {\n\t\t\t\tconst body = await response.text();\n\t\t\t\tthrow createPiMessagesResponseError(model, url, response, body);\n\t\t\t}\n\t\t\tif (!response.body) {\n\t\t\t\tthrow new Error(`${model.provider} response has no body`);\n\t\t\t}\n\n\t\t\tfor await (const piEvent of withStreamDeadline(\n\t\t\t\treadPiMessagesEvents(response.body, streamDeadline.signal),\n\t\t\t\tstreamDeadline.deadlineMs,\n\t\t\t\tstreamDeadline.abort,\n\t\t\t)) {\n\t\t\t\tconst event = convertEvent(piEvent);\n\t\t\t\teventStream.push(event);\n\t\t\t\tif (event.type === \"done\" || event.type === \"error\") {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthrow new Error(`${model.provider} stream ended without a terminal event`);\n\t\t} catch (error) {\n\t\t\teventStream.push(createErrorEvent(model, error, options?.signal?.aborted ?? false));\n\t\t} finally {\n\t\t\tstreamDeadline.cleanup();\n\t\t}\n\t})();\n\n\treturn eventStream;\n};\n\nexport const streamSimple: StreamFunction<\"pi-messages\", SimpleStreamOptions> = (\n\tmodel: Model<\"pi-messages\">,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n): AssistantMessageEventStream => {\n\tconst extra = options as PiMessagesOptions | undefined;\n\treturn stream(model, context, {\n\t\t...options,\n\t\treasoning: options?.reasoning,\n\t\ttoolChoice: options?.toolChoice,\n\t\tdebug: extra?.debug,\n\t});\n};\n"]}
|
|
@@ -3,7 +3,11 @@ export declare function clampMaxTokensToContext(model: Model<Api>, context: Cont
|
|
|
3
3
|
export declare function buildBaseOptions(model: Model<Api>, context: Context, options?: SimpleStreamOptions, apiKey?: string): StreamOptions;
|
|
4
4
|
/** Tokens always left for the answer when a thinking budget shares the response ceiling. */
|
|
5
5
|
export declare const MIN_ANSWER_TOKENS = 1024;
|
|
6
|
+
export declare const DEFAULT_THINKING_BUDGETS: ThinkingBudgets;
|
|
6
7
|
export declare function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, "xhigh" | "max"> | undefined;
|
|
8
|
+
export declare function thinkingBudgetForLevel(reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): number;
|
|
9
|
+
/** Cap a thinking budget so at least MIN_ANSWER_TOKENS remain under a shared response ceiling. */
|
|
10
|
+
export declare function clampThinkingBudgetToAnswerRoom(thinkingBudget: number, ceiling: number): number;
|
|
7
11
|
export declare function adjustMaxTokensForThinking(baseMaxTokens: number | undefined, modelMaxTokens: number, reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): {
|
|
8
12
|
maxTokens: number;
|
|
9
13
|
thinkingBudget: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simple-options.d.ts","sourceRoot":"","sources":["../../src/api/simple-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,OAAO,EACP,KAAK,EACL,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,aAAa,EACb,MAAM,aAAa,CAAC;AAMrB,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAItG;AAED,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,EAC7B,MAAM,CAAC,EAAE,MAAM,GACb,aAAa,
|
|
1
|
+
{"version":3,"file":"simple-options.d.ts","sourceRoot":"","sources":["../../src/api/simple-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,GAAG,EACH,OAAO,EACP,KAAK,EACL,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,aAAa,EACb,MAAM,aAAa,CAAC;AAMrB,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAItG;AAED,wBAAgB,gBAAgB,CAC/B,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,CAAC,EAAE,mBAAmB,EAC7B,MAAM,CAAC,EAAE,MAAM,GACb,aAAa,CA2Bf;AAED,4FAA4F;AAC5F,eAAO,MAAM,iBAAiB,OAAO,CAAC;AAEtC,eAAO,MAAM,wBAAwB,EAAE,eAKtC,CAAC;AAEF,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC,aAAa,EAAE,OAAO,GAAG,KAAK,CAAC,GAAG,SAAS,CAErH;AAED,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,aAAa,EAAE,aAAa,CAAC,EAAE,eAAe,GAAG,MAAM,CAI7G;AAED,kGAAkG;AAClG,wBAAgB,+BAA+B,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/F;AAED,wBAAgB,0BAA0B,CAEzC,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,aAAa,EAC7B,aAAa,CAAC,EAAE,eAAe,GAC7B;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAU/C","sourcesContent":["import type {\n\tApi,\n\tContext,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamOptions,\n\tThinkingBudgets,\n\tThinkingLevel,\n} from \"../types.ts\";\nimport { estimateContextTokens } from \"../utils/estimate.ts\";\n\nconst CONTEXT_SAFETY_TOKENS = 4096;\nconst MIN_MAX_TOKENS = 1;\n\nexport function clampMaxTokensToContext(model: Model<Api>, context: Context, maxTokens: number): number {\n\tif (model.contextWindow <= 0) return Math.max(MIN_MAX_TOKENS, maxTokens);\n\tconst available = model.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;\n\treturn Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));\n}\n\nexport function buildBaseOptions(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n\tapiKey?: string,\n): StreamOptions {\n\tconst samplingParams =\n\t\tmodel.samplingParams || options?.samplingParams\n\t\t\t? { ...model.samplingParams, ...options?.samplingParams }\n\t\t\t: undefined;\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tsamplingParams,\n\t\tmaxTokens: clampMaxTokensToContext(model, context, options?.maxTokens ?? model.maxTokens),\n\t\tsignal: options?.signal,\n\t\ttelemetryContext: options?.telemetryContext,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\tfetch: options?.fetch,\n\t\ttransport: options?.transport,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\twebsocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,\n\t\tstreamDeadlineMs: options?.streamDeadlineMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t\tenv: options?.env,\n\t};\n}\n\n/** Tokens always left for the answer when a thinking budget shares the response ceiling. */\nexport const MIN_ANSWER_TOKENS = 1024;\n\nexport const DEFAULT_THINKING_BUDGETS: ThinkingBudgets = {\n\tminimal: 1024,\n\tlow: 2048,\n\tmedium: 8192,\n\thigh: 16384,\n};\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\" | \"max\"> | undefined {\n\treturn effort === \"xhigh\" || effort === \"max\" ? \"high\" : effort;\n}\n\nexport function thinkingBudgetForLevel(reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): number {\n\tconst budgets = { ...DEFAULT_THINKING_BUDGETS, ...customBudgets };\n\tconst level = clampReasoning(reasoningLevel)!;\n\treturn budgets[level]!;\n}\n\n/** Cap a thinking budget so at least MIN_ANSWER_TOKENS remain under a shared response ceiling. */\nexport function clampThinkingBudgetToAnswerRoom(thinkingBudget: number, ceiling: number): number {\n\treturn Math.min(thinkingBudget, Math.max(0, ceiling - MIN_ANSWER_TOKENS));\n}\n\nexport function adjustMaxTokensForThinking(\n\t// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.\n\tbaseMaxTokens: number | undefined,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): { maxTokens: number; thinkingBudget: number } {\n\tlet thinkingBudget = thinkingBudgetForLevel(reasoningLevel, customBudgets);\n\tconst maxTokens =\n\t\tbaseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = clampThinkingBudgetToAnswerRoom(thinkingBudget, maxTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
|
|
@@ -27,6 +27,7 @@ export function buildBaseOptions(model, context, options, apiKey) {
|
|
|
27
27
|
onResponse: options?.onResponse,
|
|
28
28
|
timeoutMs: options?.timeoutMs,
|
|
29
29
|
websocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,
|
|
30
|
+
streamDeadlineMs: options?.streamDeadlineMs,
|
|
30
31
|
maxRetries: options?.maxRetries,
|
|
31
32
|
maxRetryDelayMs: options?.maxRetryDelayMs,
|
|
32
33
|
metadata: options?.metadata,
|
|
@@ -35,24 +36,31 @@ export function buildBaseOptions(model, context, options, apiKey) {
|
|
|
35
36
|
}
|
|
36
37
|
/** Tokens always left for the answer when a thinking budget shares the response ceiling. */
|
|
37
38
|
export const MIN_ANSWER_TOKENS = 1024;
|
|
39
|
+
export const DEFAULT_THINKING_BUDGETS = {
|
|
40
|
+
minimal: 1024,
|
|
41
|
+
low: 2048,
|
|
42
|
+
medium: 8192,
|
|
43
|
+
high: 16384,
|
|
44
|
+
};
|
|
38
45
|
export function clampReasoning(effort) {
|
|
39
46
|
return effort === "xhigh" || effort === "max" ? "high" : effort;
|
|
40
47
|
}
|
|
48
|
+
export function thinkingBudgetForLevel(reasoningLevel, customBudgets) {
|
|
49
|
+
const budgets = { ...DEFAULT_THINKING_BUDGETS, ...customBudgets };
|
|
50
|
+
const level = clampReasoning(reasoningLevel);
|
|
51
|
+
return budgets[level];
|
|
52
|
+
}
|
|
53
|
+
/** Cap a thinking budget so at least MIN_ANSWER_TOKENS remain under a shared response ceiling. */
|
|
54
|
+
export function clampThinkingBudgetToAnswerRoom(thinkingBudget, ceiling) {
|
|
55
|
+
return Math.min(thinkingBudget, Math.max(0, ceiling - MIN_ANSWER_TOKENS));
|
|
56
|
+
}
|
|
41
57
|
export function adjustMaxTokensForThinking(
|
|
42
58
|
// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.
|
|
43
59
|
baseMaxTokens, modelMaxTokens, reasoningLevel, customBudgets) {
|
|
44
|
-
|
|
45
|
-
minimal: 1024,
|
|
46
|
-
low: 2048,
|
|
47
|
-
medium: 8192,
|
|
48
|
-
high: 16384,
|
|
49
|
-
};
|
|
50
|
-
const budgets = { ...defaultBudgets, ...customBudgets };
|
|
51
|
-
const level = clampReasoning(reasoningLevel);
|
|
52
|
-
let thinkingBudget = budgets[level];
|
|
60
|
+
let thinkingBudget = thinkingBudgetForLevel(reasoningLevel, customBudgets);
|
|
53
61
|
const maxTokens = baseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);
|
|
54
62
|
if (maxTokens <= thinkingBudget) {
|
|
55
|
-
thinkingBudget =
|
|
63
|
+
thinkingBudget = clampThinkingBudgetToAnswerRoom(thinkingBudget, maxTokens);
|
|
56
64
|
}
|
|
57
65
|
return { maxTokens, thinkingBudget };
|
|
58
66
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simple-options.js","sourceRoot":"","sources":["../../src/api/simple-options.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,qBAAqB,GAAG,IAAI,CAAC;AACnC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,MAAM,UAAU,uBAAuB,CAAC,KAAiB,EAAE,OAAgB,EAAE,SAAiB,EAAU;IACvG,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,KAAK,CAAC,aAAa,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,qBAAqB,CAAC;IACtG,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,CAAC;AAAA,CAChE;AAED,MAAM,UAAU,gBAAgB,CAC/B,KAAiB,EACjB,OAAgB,EAChB,OAA6B,EAC7B,MAAe,EACC;IAChB,MAAM,cAAc,GACnB,KAAK,CAAC,cAAc,IAAI,OAAO,EAAE,cAAc;QAC9C,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,cAAc,EAAE,GAAG,OAAO,EAAE,cAAc,EAAE;QACzD,CAAC,CAAC,SAAS,CAAC;IACd,OAAO;QACN,WAAW,EAAE,OAAO,EAAE,WAAW;QACjC,cAAc;QACd,SAAS,EAAE,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;QACzF,MAAM,EAAE,OAAO,EAAE,MAAM;QACvB,gBAAgB,EAAE,OAAO,EAAE,gBAAgB;QAC3C,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM;QACjC,KAAK,EAAE,OAAO,EAAE,KAAK;QACrB,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,cAAc,EAAE,OAAO,EAAE,cAAc;QACvC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,OAAO,EAAE,OAAO,EAAE,OAAO;QACzB,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,yBAAyB,EAAE,OAAO,EAAE,yBAAyB;QAC7D,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,eAAe,EAAE,OAAO,EAAE,eAAe;QACzC,QAAQ,EAAE,OAAO,EAAE,QAAQ;QAC3B,GAAG,EAAE,OAAO,EAAE,GAAG;KACjB,CAAC;AAAA,CACF;AAED,4FAA4F;AAC5F,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC,MAAM,UAAU,cAAc,CAAC,MAAiC,EAAuD;IACtH,OAAO,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAAA,CAChE;AAED,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"simple-options.js","sourceRoot":"","sources":["../../src/api/simple-options.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,qBAAqB,GAAG,IAAI,CAAC;AACnC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEzB,MAAM,UAAU,uBAAuB,CAAC,KAAiB,EAAE,OAAgB,EAAE,SAAiB,EAAU;IACvG,IAAI,KAAK,CAAC,aAAa,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,KAAK,CAAC,aAAa,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,qBAAqB,CAAC;IACtG,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC,CAAC;AAAA,CAChE;AAED,MAAM,UAAU,gBAAgB,CAC/B,KAAiB,EACjB,OAAgB,EAChB,OAA6B,EAC7B,MAAe,EACC;IAChB,MAAM,cAAc,GACnB,KAAK,CAAC,cAAc,IAAI,OAAO,EAAE,cAAc;QAC9C,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,cAAc,EAAE,GAAG,OAAO,EAAE,cAAc,EAAE;QACzD,CAAC,CAAC,SAAS,CAAC;IACd,OAAO;QACN,WAAW,EAAE,OAAO,EAAE,WAAW;QACjC,cAAc;QACd,SAAS,EAAE,uBAAuB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,IAAI,KAAK,CAAC,SAAS,CAAC;QACzF,MAAM,EAAE,OAAO,EAAE,MAAM;QACvB,gBAAgB,EAAE,OAAO,EAAE,gBAAgB;QAC3C,MAAM,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM;QACjC,KAAK,EAAE,OAAO,EAAE,KAAK;QACrB,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,cAAc,EAAE,OAAO,EAAE,cAAc;QACvC,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,OAAO,EAAE,OAAO,EAAE,OAAO;QACzB,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,SAAS,EAAE,OAAO,EAAE,SAAS;QAC7B,yBAAyB,EAAE,OAAO,EAAE,yBAAyB;QAC7D,gBAAgB,EAAE,OAAO,EAAE,gBAAgB;QAC3C,UAAU,EAAE,OAAO,EAAE,UAAU;QAC/B,eAAe,EAAE,OAAO,EAAE,eAAe;QACzC,QAAQ,EAAE,OAAO,EAAE,QAAQ;QAC3B,GAAG,EAAE,OAAO,EAAE,GAAG;KACjB,CAAC;AAAA,CACF;AAED,4FAA4F;AAC5F,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAEtC,MAAM,CAAC,MAAM,wBAAwB,GAAoB;IACxD,OAAO,EAAE,IAAI;IACb,GAAG,EAAE,IAAI;IACT,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,KAAK;CACX,CAAC;AAEF,MAAM,UAAU,cAAc,CAAC,MAAiC,EAAuD;IACtH,OAAO,MAAM,KAAK,OAAO,IAAI,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAAA,CAChE;AAED,MAAM,UAAU,sBAAsB,CAAC,cAA6B,EAAE,aAA+B,EAAU;IAC9G,MAAM,OAAO,GAAG,EAAE,GAAG,wBAAwB,EAAE,GAAG,aAAa,EAAE,CAAC;IAClE,MAAM,KAAK,GAAG,cAAc,CAAC,cAAc,CAAE,CAAC;IAC9C,OAAO,OAAO,CAAC,KAAK,CAAE,CAAC;AAAA,CACvB;AAED,kGAAkG;AAClG,MAAM,UAAU,+BAA+B,CAAC,cAAsB,EAAE,OAAe,EAAU;IAChG,OAAO,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC;AAAA,CAC1E;AAED,MAAM,UAAU,0BAA0B;AACzC,wFAAwF;AACxF,aAAiC,EACjC,cAAsB,EACtB,cAA6B,EAC7B,aAA+B,EACiB;IAChD,IAAI,cAAc,GAAG,sBAAsB,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IAC3E,MAAM,SAAS,GACd,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,GAAG,cAAc,EAAE,cAAc,CAAC,CAAC;IAEzG,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;QACjC,cAAc,GAAG,+BAA+B,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AAAA,CACrC","sourcesContent":["import type {\n\tApi,\n\tContext,\n\tModel,\n\tSimpleStreamOptions,\n\tStreamOptions,\n\tThinkingBudgets,\n\tThinkingLevel,\n} from \"../types.ts\";\nimport { estimateContextTokens } from \"../utils/estimate.ts\";\n\nconst CONTEXT_SAFETY_TOKENS = 4096;\nconst MIN_MAX_TOKENS = 1;\n\nexport function clampMaxTokensToContext(model: Model<Api>, context: Context, maxTokens: number): number {\n\tif (model.contextWindow <= 0) return Math.max(MIN_MAX_TOKENS, maxTokens);\n\tconst available = model.contextWindow - estimateContextTokens(context).tokens - CONTEXT_SAFETY_TOKENS;\n\treturn Math.min(maxTokens, Math.max(MIN_MAX_TOKENS, available));\n}\n\nexport function buildBaseOptions(\n\tmodel: Model<Api>,\n\tcontext: Context,\n\toptions?: SimpleStreamOptions,\n\tapiKey?: string,\n): StreamOptions {\n\tconst samplingParams =\n\t\tmodel.samplingParams || options?.samplingParams\n\t\t\t? { ...model.samplingParams, ...options?.samplingParams }\n\t\t\t: undefined;\n\treturn {\n\t\ttemperature: options?.temperature,\n\t\tsamplingParams,\n\t\tmaxTokens: clampMaxTokensToContext(model, context, options?.maxTokens ?? model.maxTokens),\n\t\tsignal: options?.signal,\n\t\ttelemetryContext: options?.telemetryContext,\n\t\tapiKey: apiKey || options?.apiKey,\n\t\tfetch: options?.fetch,\n\t\ttransport: options?.transport,\n\t\tcacheRetention: options?.cacheRetention,\n\t\tsessionId: options?.sessionId,\n\t\theaders: options?.headers,\n\t\tonPayload: options?.onPayload,\n\t\tonResponse: options?.onResponse,\n\t\ttimeoutMs: options?.timeoutMs,\n\t\twebsocketConnectTimeoutMs: options?.websocketConnectTimeoutMs,\n\t\tstreamDeadlineMs: options?.streamDeadlineMs,\n\t\tmaxRetries: options?.maxRetries,\n\t\tmaxRetryDelayMs: options?.maxRetryDelayMs,\n\t\tmetadata: options?.metadata,\n\t\tenv: options?.env,\n\t};\n}\n\n/** Tokens always left for the answer when a thinking budget shares the response ceiling. */\nexport const MIN_ANSWER_TOKENS = 1024;\n\nexport const DEFAULT_THINKING_BUDGETS: ThinkingBudgets = {\n\tminimal: 1024,\n\tlow: 2048,\n\tmedium: 8192,\n\thigh: 16384,\n};\n\nexport function clampReasoning(effort: ThinkingLevel | undefined): Exclude<ThinkingLevel, \"xhigh\" | \"max\"> | undefined {\n\treturn effort === \"xhigh\" || effort === \"max\" ? \"high\" : effort;\n}\n\nexport function thinkingBudgetForLevel(reasoningLevel: ThinkingLevel, customBudgets?: ThinkingBudgets): number {\n\tconst budgets = { ...DEFAULT_THINKING_BUDGETS, ...customBudgets };\n\tconst level = clampReasoning(reasoningLevel)!;\n\treturn budgets[level]!;\n}\n\n/** Cap a thinking budget so at least MIN_ANSWER_TOKENS remain under a shared response ceiling. */\nexport function clampThinkingBudgetToAnswerRoom(thinkingBudget: number, ceiling: number): number {\n\treturn Math.min(thinkingBudget, Math.max(0, ceiling - MIN_ANSWER_TOKENS));\n}\n\nexport function adjustMaxTokensForThinking(\n\t// Undefined means no explicit caller cap. Use the model cap and fit thinking inside it.\n\tbaseMaxTokens: number | undefined,\n\tmodelMaxTokens: number,\n\treasoningLevel: ThinkingLevel,\n\tcustomBudgets?: ThinkingBudgets,\n): { maxTokens: number; thinkingBudget: number } {\n\tlet thinkingBudget = thinkingBudgetForLevel(reasoningLevel, customBudgets);\n\tconst maxTokens =\n\t\tbaseMaxTokens === undefined ? modelMaxTokens : Math.min(baseMaxTokens + thinkingBudget, modelMaxTokens);\n\n\tif (maxTokens <= thinkingBudget) {\n\t\tthinkingBudget = clampThinkingBudgetToAnswerRoom(thinkingBudget, maxTokens);\n\t}\n\n\treturn { maxTokens, thinkingBudget };\n}\n"]}
|
|
@@ -18,6 +18,7 @@ export type OAuthDeviceCodePollOptions<T> = {
|
|
|
18
18
|
poll: () => Promise<OAuthDeviceCodePollResult<T>>;
|
|
19
19
|
signal: AbortSignal;
|
|
20
20
|
};
|
|
21
|
+
export declare function abortableSleep(ms: number, signal: AbortSignal, cancelMessage: string): Promise<void>;
|
|
21
22
|
export declare function pollOAuthDeviceCodeFlow<T>(options: OAuthDeviceCodePollOptions<T>): Promise<T>;
|
|
22
23
|
export {};
|
|
23
24
|
//# sourceMappingURL=device-code.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-code.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/device-code.ts"],"names":[],"mappings":"AAUA,KAAK,mCAAmC,GACrC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,MAAM,yBAAyB,CAAC,CAAC,IAAI,mCAAmC,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAElH,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,EAAE,WAAW,CAAC;CACpB,CAAC;
|
|
1
|
+
{"version":3,"file":"device-code.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/device-code.ts"],"names":[],"mappings":"AAUA,KAAK,mCAAmC,GACrC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,MAAM,yBAAyB,CAAC,CAAC,IAAI,mCAAmC,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC;AAElH,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,IAAI,EAAE,MAAM,OAAO,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBpG;AAED,wBAAsB,uBAAuB,CAAC,CAAC,EAAE,OAAO,EAAE,0BAA0B,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAoDnG","sourcesContent":["const CANCEL_MESSAGE = \"Login cancelled\";\nconst TIMEOUT_MESSAGE = \"Device flow timed out\";\nconst SLOW_DOWN_TIMEOUT_MESSAGE =\n\t\"Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.\";\nconst MINIMUM_INTERVAL_MS = 1000;\n// RFC 8628 section 3.2: if the authorization server omits `interval`, the client must use 5 seconds.\nconst DEFAULT_POLL_INTERVAL_SECONDS = 5;\n// RFC 8628 section 3.5: `slow_down` means the polling interval must increase by 5 seconds.\nconst SLOW_DOWN_INTERVAL_INCREMENT_MS = 5000;\n\ntype OAuthDeviceCodeIncompletePollResult =\n\t| { status: \"pending\" }\n\t| { status: \"slow_down\"; intervalSeconds?: number }\n\t| { status: \"failed\"; message: string };\n\nexport type OAuthDeviceCodePollResult<T> = OAuthDeviceCodeIncompletePollResult | { status: \"complete\"; value: T };\n\nexport type OAuthDeviceCodePollOptions<T> = {\n\tintervalSeconds?: number;\n\texpiresInSeconds?: number;\n\twaitBeforeFirstPoll?: boolean;\n\tpoll: () => Promise<OAuthDeviceCodePollResult<T>>;\n\tsignal: AbortSignal;\n};\n\nexport function abortableSleep(ms: number, signal: AbortSignal, cancelMessage: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal.aborted) {\n\t\t\treject(new Error(cancelMessage));\n\t\t\treturn;\n\t\t}\n\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\treject(new Error(cancelMessage));\n\t\t};\n\t\tconst timeout = setTimeout(() => {\n\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\nexport async function pollOAuthDeviceCodeFlow<T>(options: OAuthDeviceCodePollOptions<T>): Promise<T> {\n\tconst deadline =\n\t\ttypeof options.expiresInSeconds === \"number\"\n\t\t\t? Date.now() + options.expiresInSeconds * 1000\n\t\t\t: Number.POSITIVE_INFINITY;\n\tlet intervalMs = Math.max(\n\t\tMINIMUM_INTERVAL_MS,\n\t\tMath.floor((options.intervalSeconds ?? DEFAULT_POLL_INTERVAL_SECONDS) * 1000),\n\t);\n\n\tlet slowDownResponses = 0;\n\tif (options.waitBeforeFirstPoll) {\n\t\tconst remainingMs = deadline - Date.now();\n\t\tif (remainingMs > 0) {\n\t\t\tawait abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);\n\t\t}\n\t}\n\n\twhile (Date.now() < deadline) {\n\t\tif (options.signal.aborted) {\n\t\t\tthrow new Error(CANCEL_MESSAGE);\n\t\t}\n\n\t\tconst result = await options.poll();\n\t\tif (result.status === \"complete\") {\n\t\t\treturn result.value;\n\t\t}\n\t\tif (result.status === \"failed\") {\n\t\t\tthrow new Error(result.message);\n\t\t}\n\t\tif (result.status === \"slow_down\") {\n\t\t\tslowDownResponses += 1;\n\t\t\t// Use the server-provided interval when given (GitHub reports the new required minimum\n\t\t\t// in `interval`); trusting only a client-tracked value risks polling early forever under\n\t\t\t// WSL/VM clock drift. Otherwise apply RFC 8628 section 3.5: increase by 5 seconds.\n\t\t\tintervalMs =\n\t\t\t\ttypeof result.intervalSeconds === \"number\" &&\n\t\t\t\tNumber.isFinite(result.intervalSeconds) &&\n\t\t\t\tresult.intervalSeconds > 0\n\t\t\t\t\t? Math.max(MINIMUM_INTERVAL_MS, Math.floor(result.intervalSeconds * 1000))\n\t\t\t\t\t: Math.max(MINIMUM_INTERVAL_MS, intervalMs + SLOW_DOWN_INTERVAL_INCREMENT_MS);\n\t\t}\n\n\t\tconst remainingMs = deadline - Date.now();\n\t\tif (remainingMs <= 0) {\n\t\t\tbreak;\n\t\t}\n\n\t\tawait abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);\n\t}\n\n\tthrow new Error(slowDownResponses > 0 ? SLOW_DOWN_TIMEOUT_MESSAGE : TIMEOUT_MESSAGE);\n}\n"]}
|
|
@@ -6,7 +6,7 @@ const MINIMUM_INTERVAL_MS = 1000;
|
|
|
6
6
|
const DEFAULT_POLL_INTERVAL_SECONDS = 5;
|
|
7
7
|
// RFC 8628 section 3.5: `slow_down` means the polling interval must increase by 5 seconds.
|
|
8
8
|
const SLOW_DOWN_INTERVAL_INCREMENT_MS = 5000;
|
|
9
|
-
function abortableSleep(ms, signal, cancelMessage) {
|
|
9
|
+
export function abortableSleep(ms, signal, cancelMessage) {
|
|
10
10
|
return new Promise((resolve, reject) => {
|
|
11
11
|
if (signal.aborted) {
|
|
12
12
|
reject(new Error(cancelMessage));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device-code.js","sourceRoot":"","sources":["../../../src/auth/oauth/device-code.ts"],"names":[],"mappings":"AAAA,MAAM,cAAc,GAAG,iBAAiB,CAAC;AACzC,MAAM,eAAe,GAAG,uBAAuB,CAAC;AAChD,MAAM,yBAAyB,GAC9B,gLAAgL,CAAC;AAClL,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACjC,qGAAqG;AACrG,MAAM,6BAA6B,GAAG,CAAC,CAAC;AACxC,2FAA2F;AAC3F,MAAM,+BAA+B,GAAG,IAAI,CAAC;AAiB7C,
|
|
1
|
+
{"version":3,"file":"device-code.js","sourceRoot":"","sources":["../../../src/auth/oauth/device-code.ts"],"names":[],"mappings":"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","sourcesContent":["const CANCEL_MESSAGE = \"Login cancelled\";\nconst TIMEOUT_MESSAGE = \"Device flow timed out\";\nconst SLOW_DOWN_TIMEOUT_MESSAGE =\n\t\"Device flow timed out after one or more slow_down responses. This is often caused by clock drift in WSL or VM environments. Please sync or restart the VM clock and try again.\";\nconst MINIMUM_INTERVAL_MS = 1000;\n// RFC 8628 section 3.2: if the authorization server omits `interval`, the client must use 5 seconds.\nconst DEFAULT_POLL_INTERVAL_SECONDS = 5;\n// RFC 8628 section 3.5: `slow_down` means the polling interval must increase by 5 seconds.\nconst SLOW_DOWN_INTERVAL_INCREMENT_MS = 5000;\n\ntype OAuthDeviceCodeIncompletePollResult =\n\t| { status: \"pending\" }\n\t| { status: \"slow_down\"; intervalSeconds?: number }\n\t| { status: \"failed\"; message: string };\n\nexport type OAuthDeviceCodePollResult<T> = OAuthDeviceCodeIncompletePollResult | { status: \"complete\"; value: T };\n\nexport type OAuthDeviceCodePollOptions<T> = {\n\tintervalSeconds?: number;\n\texpiresInSeconds?: number;\n\twaitBeforeFirstPoll?: boolean;\n\tpoll: () => Promise<OAuthDeviceCodePollResult<T>>;\n\tsignal: AbortSignal;\n};\n\nexport function abortableSleep(ms: number, signal: AbortSignal, cancelMessage: string): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal.aborted) {\n\t\t\treject(new Error(cancelMessage));\n\t\t\treturn;\n\t\t}\n\n\t\tconst onAbort = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\treject(new Error(cancelMessage));\n\t\t};\n\t\tconst timeout = setTimeout(() => {\n\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\tresolve();\n\t\t}, ms);\n\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t});\n}\n\nexport async function pollOAuthDeviceCodeFlow<T>(options: OAuthDeviceCodePollOptions<T>): Promise<T> {\n\tconst deadline =\n\t\ttypeof options.expiresInSeconds === \"number\"\n\t\t\t? Date.now() + options.expiresInSeconds * 1000\n\t\t\t: Number.POSITIVE_INFINITY;\n\tlet intervalMs = Math.max(\n\t\tMINIMUM_INTERVAL_MS,\n\t\tMath.floor((options.intervalSeconds ?? DEFAULT_POLL_INTERVAL_SECONDS) * 1000),\n\t);\n\n\tlet slowDownResponses = 0;\n\tif (options.waitBeforeFirstPoll) {\n\t\tconst remainingMs = deadline - Date.now();\n\t\tif (remainingMs > 0) {\n\t\t\tawait abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);\n\t\t}\n\t}\n\n\twhile (Date.now() < deadline) {\n\t\tif (options.signal.aborted) {\n\t\t\tthrow new Error(CANCEL_MESSAGE);\n\t\t}\n\n\t\tconst result = await options.poll();\n\t\tif (result.status === \"complete\") {\n\t\t\treturn result.value;\n\t\t}\n\t\tif (result.status === \"failed\") {\n\t\t\tthrow new Error(result.message);\n\t\t}\n\t\tif (result.status === \"slow_down\") {\n\t\t\tslowDownResponses += 1;\n\t\t\t// Use the server-provided interval when given (GitHub reports the new required minimum\n\t\t\t// in `interval`); trusting only a client-tracked value risks polling early forever under\n\t\t\t// WSL/VM clock drift. Otherwise apply RFC 8628 section 3.5: increase by 5 seconds.\n\t\t\tintervalMs =\n\t\t\t\ttypeof result.intervalSeconds === \"number\" &&\n\t\t\t\tNumber.isFinite(result.intervalSeconds) &&\n\t\t\t\tresult.intervalSeconds > 0\n\t\t\t\t\t? Math.max(MINIMUM_INTERVAL_MS, Math.floor(result.intervalSeconds * 1000))\n\t\t\t\t\t: Math.max(MINIMUM_INTERVAL_MS, intervalMs + SLOW_DOWN_INTERVAL_INCREMENT_MS);\n\t\t}\n\n\t\tconst remainingMs = deadline - Date.now();\n\t\tif (remainingMs <= 0) {\n\t\t\tbreak;\n\t\t}\n\n\t\tawait abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);\n\t}\n\n\tthrow new Error(slowDownResponses > 0 ? SLOW_DOWN_TIMEOUT_MESSAGE : TIMEOUT_MESSAGE);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github-copilot.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/github-copilot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAA4C,MAAM,aAAa,CAAC;AA6YvF,eAAO,MAAM,kBAAkB,EAAE,SAchC,CAAC","sourcesContent":["/**\n * GitHub Copilot OAuth flow\n */\n\nimport { GITHUB_COPILOT_MODELS } from \"../../providers/github-copilot.models.ts\";\nimport type { OAuthAuth, OAuthCredential, ProviderAuthInteraction } from \"../types.ts\";\nimport { pollOAuthDeviceCodeFlow } from \"./device-code.ts\";\n\nconst decode = (s: string) => atob(s);\nconst CLIENT_ID = decode(\"SXYxLmI1MDdhMDhjODdlY2ZlOTg=\");\n\nconst COPILOT_HEADERS = {\n\t\"User-Agent\": \"GitHubCopilotChat/0.35.0\",\n\t\"Editor-Version\": \"vscode/1.107.0\",\n\t\"Editor-Plugin-Version\": \"copilot-chat/0.35.0\",\n\t\"Copilot-Integration-Id\": \"vscode-chat\",\n} as const;\nconst COPILOT_API_VERSION = \"2026-06-01\";\nconst COPILOT_POLICY_CONCURRENCY = 4;\n\ntype DeviceCodeResponse = {\n\tdevice_code: string;\n\tuser_code: string;\n\tverification_uri: string;\n\tinterval?: number;\n\texpires_in: number;\n};\n\ntype DeviceTokenSuccessResponse = {\n\taccess_token: string;\n\ttoken_type?: string;\n\tscope?: string;\n};\n\ntype DeviceTokenErrorResponse = {\n\terror: string;\n\terror_description?: string;\n\tinterval?: number;\n};\n\nfunction normalizeDomain(input: string): string | null {\n\tconst trimmed = input.trim();\n\tif (!trimmed) return null;\n\ttry {\n\t\tconst url = trimmed.includes(\"://\") ? new URL(trimmed) : new URL(`https://${trimmed}`);\n\t\treturn url.hostname;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction getUrls(domain: string): {\n\tdeviceCodeUrl: string;\n\taccessTokenUrl: string;\n\tcopilotTokenUrl: string;\n} {\n\treturn {\n\t\tdeviceCodeUrl: `https://${domain}/login/device/code`,\n\t\taccessTokenUrl: `https://${domain}/login/oauth/access_token`,\n\t\tcopilotTokenUrl: `https://api.${domain}/copilot_internal/v2/token`,\n\t};\n}\n\n/**\n * Parse the proxy-ep from a Copilot token and convert to API base URL.\n * Token format: tid=...;exp=...;proxy-ep=proxy.individual.githubcopilot.com;...\n * Returns API URL like https://api.individual.githubcopilot.com\n */\nfunction getBaseUrlFromToken(token: string): string | null {\n\tconst match = token.match(/proxy-ep=([^;]+)/);\n\tif (!match) return null;\n\tconst proxyHost = match[1];\n\t// Convert proxy.xxx to api.xxx\n\tconst apiHost = proxyHost.replace(/^proxy\\./, \"api.\");\n\treturn `https://${apiHost}`;\n}\n\nfunction getGitHubCopilotBaseUrl(token?: string, enterpriseDomain?: string): string {\n\t// If we have a token, extract the base URL from proxy-ep\n\tif (token) {\n\t\tconst urlFromToken = getBaseUrlFromToken(token);\n\t\tif (urlFromToken) return urlFromToken;\n\t}\n\t// Fallback for enterprise or if token parsing fails\n\tif (enterpriseDomain) return `https://copilot-api.${enterpriseDomain}`;\n\treturn \"https://api.individual.githubcopilot.com\";\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n\treturn value && typeof value === \"object\" ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction parseAvailableCopilotModelIds(raw: unknown, allowPolicyFallback: boolean): string[] {\n\tconst data = asRecord(raw)?.data;\n\tif (!Array.isArray(data)) {\n\t\tthrow new Error(\"Invalid Copilot models response\");\n\t}\n\n\tconst pickerIds: string[] = [];\n\tconst policyEnabledIds: string[] = [];\n\tfor (const rawItem of data) {\n\t\tconst item = asRecord(rawItem);\n\t\tconst id = item?.id;\n\t\tif (!item || typeof id !== \"string\") continue;\n\n\t\tconst capabilities = asRecord(item.capabilities);\n\t\tconst supports = asRecord(capabilities?.supports);\n\t\tif (supports?.tool_calls === false) continue;\n\t\tconst policy = asRecord(item.policy);\n\t\tif (item.model_picker_enabled === true && policy?.state !== \"disabled\") pickerIds.push(id);\n\t\tif (policy?.state === \"enabled\") policyEnabledIds.push(id);\n\t}\n\treturn pickerIds.length > 0 || !allowPolicyFallback ? pickerIds : policyEnabledIds;\n}\n\nasync function fetchAvailableGitHubCopilotModelIds(\n\tcopilotToken: string,\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n): Promise<string[]> {\n\tconst baseUrl = getGitHubCopilotBaseUrl(copilotToken, enterpriseDomain);\n\t// Some Individual accounts return false for every picker flag despite explicit enabled policies.\n\t// Limit the fallback to that endpoint so other account types keep strict picker semantics.\n\tconst allowPolicyFallback = baseUrl === \"https://api.individual.githubcopilot.com\";\n\tconst raw = await fetchJson(`${baseUrl}/models`, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t\tAuthorization: `Bearer ${copilotToken}`,\n\t\t\t...COPILOT_HEADERS,\n\t\t\t\"X-GitHub-Api-Version\": COPILOT_API_VERSION,\n\t\t},\n\t\tsignal: AbortSignal.any([signal, AbortSignal.timeout(5000)]),\n\t});\n\treturn parseAvailableCopilotModelIds(raw, allowPolicyFallback);\n}\n\nasync function fetchJson(url: string, init: RequestInit): Promise<unknown> {\n\tconst response = await fetch(url, init);\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new Error(`${response.status} ${response.statusText}: ${text}`);\n\t}\n\treturn response.json();\n}\n\nasync function startDeviceFlow(domain: string, signal: AbortSignal): Promise<DeviceCodeResponse> {\n\tconst urls = getUrls(domain);\n\tconst data = await fetchJson(urls.deviceCodeUrl, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\"User-Agent\": \"GitHubCopilotChat/0.35.0\",\n\t\t},\n\t\tbody: new URLSearchParams({\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tscope: \"read:user\",\n\t\t}),\n\t\tsignal,\n\t});\n\n\tif (!data || typeof data !== \"object\") {\n\t\tthrow new Error(\"Invalid device code response\");\n\t}\n\n\tconst deviceCode = (data as Record<string, unknown>).device_code;\n\tconst userCode = (data as Record<string, unknown>).user_code;\n\tconst verificationUri = (data as Record<string, unknown>).verification_uri;\n\tconst interval = (data as Record<string, unknown>).interval;\n\tconst expiresIn = (data as Record<string, unknown>).expires_in;\n\n\tif (\n\t\ttypeof deviceCode !== \"string\" ||\n\t\ttypeof userCode !== \"string\" ||\n\t\ttypeof verificationUri !== \"string\" ||\n\t\t(interval !== undefined && typeof interval !== \"number\") ||\n\t\ttypeof expiresIn !== \"number\"\n\t) {\n\t\tthrow new Error(\"Invalid device code response fields\");\n\t}\n\n\t// The verification URI is opened in the user's browser and to prevent `open` from\n\t// opening an executable or similar, we force it to be a URL.\n\tlet parsedUri: URL;\n\ttry {\n\t\tparsedUri = new URL(verificationUri);\n\t} catch {\n\t\tthrow new Error(\"Untrusted verification_uri in device code response\");\n\t}\n\tif (parsedUri.protocol !== \"https:\" && parsedUri.protocol !== \"http:\") {\n\t\tthrow new Error(\"Untrusted verification_uri in device code response\");\n\t}\n\n\treturn {\n\t\tdevice_code: deviceCode,\n\t\tuser_code: userCode,\n\t\tverification_uri: parsedUri.href,\n\t\tinterval,\n\t\texpires_in: expiresIn,\n\t};\n}\n\nasync function pollForGitHubAccessToken(\n\tdomain: string,\n\tdevice: DeviceCodeResponse,\n\tsignal: AbortSignal,\n): Promise<string> {\n\tconst urls = getUrls(domain);\n\treturn pollOAuthDeviceCodeFlow<string>({\n\t\tintervalSeconds: device.interval,\n\t\texpiresInSeconds: device.expires_in,\n\t\twaitBeforeFirstPoll: true,\n\t\tsignal,\n\t\tpoll: async () => {\n\t\t\tconst raw = await fetchJson(urls.accessTokenUrl, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\"User-Agent\": \"GitHubCopilotChat/0.35.0\",\n\t\t\t\t},\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tclient_id: CLIENT_ID,\n\t\t\t\t\tdevice_code: device.device_code,\n\t\t\t\t\tgrant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n\t\t\t\t}),\n\t\t\t\tsignal,\n\t\t\t});\n\n\t\t\tif (raw && typeof raw === \"object\" && typeof (raw as DeviceTokenSuccessResponse).access_token === \"string\") {\n\t\t\t\treturn { status: \"complete\", value: (raw as DeviceTokenSuccessResponse).access_token };\n\t\t\t}\n\n\t\t\tif (raw && typeof raw === \"object\" && typeof (raw as DeviceTokenErrorResponse).error === \"string\") {\n\t\t\t\tconst { error, error_description: description, interval } = raw as DeviceTokenErrorResponse;\n\t\t\t\tif (error === \"authorization_pending\") {\n\t\t\t\t\treturn { status: \"pending\" };\n\t\t\t\t}\n\n\t\t\t\tif (error === \"slow_down\") {\n\t\t\t\t\treturn { status: \"slow_down\", intervalSeconds: typeof interval === \"number\" ? interval : undefined };\n\t\t\t\t}\n\n\t\t\t\tconst descriptionSuffix = description ? `: ${description}` : \"\";\n\t\t\t\treturn { status: \"failed\", message: `Device flow failed: ${error}${descriptionSuffix}` };\n\t\t\t}\n\n\t\t\treturn { status: \"failed\", message: \"Invalid device token response\" };\n\t\t},\n\t});\n}\n\nasync function refreshGitHubCopilotAccessToken(\n\trefreshToken: string,\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n): Promise<OAuthCredential> {\n\tconst domain = enterpriseDomain || \"github.com\";\n\tconst urls = getUrls(domain);\n\n\tconst raw = await fetchJson(urls.copilotTokenUrl, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t\tAuthorization: `Bearer ${refreshToken}`,\n\t\t\t...COPILOT_HEADERS,\n\t\t},\n\t\tsignal,\n\t});\n\n\tif (!raw || typeof raw !== \"object\") {\n\t\tthrow new Error(\"Invalid Copilot token response\");\n\t}\n\n\tconst token = (raw as Record<string, unknown>).token;\n\tconst expiresAt = (raw as Record<string, unknown>).expires_at;\n\n\tif (typeof token !== \"string\" || typeof expiresAt !== \"number\") {\n\t\tthrow new Error(\"Invalid Copilot token response fields\");\n\t}\n\n\treturn {\n\t\ttype: \"oauth\",\n\t\trefresh: refreshToken,\n\t\taccess: token,\n\t\texpires: expiresAt * 1000 - 5 * 60 * 1000,\n\t\tenterpriseUrl: enterpriseDomain,\n\t};\n}\n\n/**\n * Refresh GitHub Copilot token\n */\nasync function refreshGitHubCopilotToken(\n\trefreshToken: string,\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n): Promise<OAuthCredential> {\n\tconst credentials = await refreshGitHubCopilotAccessToken(refreshToken, enterpriseDomain, signal);\n\treturn {\n\t\t...credentials,\n\t\tavailableModelIds: await fetchAvailableGitHubCopilotModelIds(credentials.access, enterpriseDomain, signal),\n\t};\n}\n\n/**\n * Enable a model for the user's GitHub Copilot account.\n * This is required for some models (like Claude, Grok) before they can be used.\n */\nasync function enableGitHubCopilotModel(\n\ttoken: string,\n\tmodelId: string,\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n): Promise<boolean> {\n\tconst baseUrl = getGitHubCopilotBaseUrl(token, enterpriseDomain);\n\tconst url = `${baseUrl}/models/${modelId}/policy`;\n\n\ttry {\n\t\tconst response = await fetch(url, {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\t...COPILOT_HEADERS,\n\t\t\t\t\"openai-intent\": \"chat-policy\",\n\t\t\t\t\"x-interaction-type\": \"chat-policy\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({ state: \"enabled\" }),\n\t\t\tsignal,\n\t\t});\n\t\treturn response.ok;\n\t} catch (error) {\n\t\tif (signal.aborted) throw error;\n\t\treturn false;\n\t}\n}\n\n/**\n * Enable all known GitHub Copilot models that may require policy acceptance.\n * Called after successful login to ensure all models are available.\n */\nasync function enableAllGitHubCopilotModels(\n\ttoken: string,\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n): Promise<void> {\n\tconst models = Object.values(GITHUB_COPILOT_MODELS);\n\tfor (let index = 0; index < models.length; index += COPILOT_POLICY_CONCURRENCY) {\n\t\tawait Promise.all(\n\t\t\tmodels.slice(index, index + COPILOT_POLICY_CONCURRENCY).map(async (model) => {\n\t\t\t\tawait enableGitHubCopilotModel(token, model.id, enterpriseDomain, signal);\n\t\t\t}),\n\t\t);\n\t}\n}\n\nasync function loginGitHubCopilot(interaction: ProviderAuthInteraction): Promise<OAuthCredential> {\n\tconst input = await interaction.prompt({\n\t\ttype: \"text\",\n\t\tmessage: \"GitHub Enterprise URL/domain (blank for github.com)\",\n\t\tplaceholder: \"company.ghe.com\",\n\t});\n\tif (interaction.signal.aborted) throw new Error(\"Login cancelled\");\n\n\tconst trimmed = input.trim();\n\tconst enterpriseDomain = normalizeDomain(input);\n\tif (trimmed && !enterpriseDomain) throw new Error(\"Invalid GitHub Enterprise URL/domain\");\n\tconst domain = enterpriseDomain || \"github.com\";\n\n\tconst device = await startDeviceFlow(domain, interaction.signal);\n\tinteraction.notify({\n\t\ttype: \"device_code\",\n\t\tuserCode: device.user_code,\n\t\tverificationUri: device.verification_uri,\n\t\tintervalSeconds: device.interval,\n\t\texpiresInSeconds: device.expires_in,\n\t});\n\n\tconst githubAccessToken = await pollForGitHubAccessToken(domain, device, interaction.signal);\n\tconst credentials = await refreshGitHubCopilotAccessToken(\n\t\tgithubAccessToken,\n\t\tenterpriseDomain ?? undefined,\n\t\tinteraction.signal,\n\t);\n\tinteraction.notify({ type: \"progress\", message: \"Enabling models...\" });\n\tawait enableAllGitHubCopilotModels(credentials.access, enterpriseDomain ?? undefined, interaction.signal);\n\treturn {\n\t\t...credentials,\n\t\tavailableModelIds: await fetchAvailableGitHubCopilotModelIds(\n\t\t\tcredentials.access,\n\t\t\tenterpriseDomain ?? undefined,\n\t\t\tinteraction.signal,\n\t\t),\n\t};\n}\n\nfunction copilotEnterpriseDomain(credential: OAuthCredential): string | undefined {\n\tconst enterpriseUrl = credential.enterpriseUrl;\n\tif (typeof enterpriseUrl !== \"string\" || !enterpriseUrl) return undefined;\n\treturn normalizeDomain(enterpriseUrl) ?? undefined;\n}\n\nexport const githubCopilotOAuth: OAuthAuth = {\n\tname: \"GitHub Copilot\",\n\tisSubscription: true,\n\tlogin: loginGitHubCopilot,\n\trefresh: (credential, signal) =>\n\t\trefreshGitHubCopilotToken(credential.refresh, copilotEnterpriseDomain(credential), signal),\n\n\t/** Derive the credential-specific proxy endpoint for each request. */\n\tasync toAuth(credential) {\n\t\treturn {\n\t\t\tapiKey: credential.access,\n\t\t\tbaseUrl: getGitHubCopilotBaseUrl(credential.access, copilotEnterpriseDomain(credential)),\n\t\t};\n\t},\n};\n"]}
|
|
1
|
+
{"version":3,"file":"github-copilot.d.ts","sourceRoot":"","sources":["../../../src/auth/oauth/github-copilot.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,SAAS,EAA4C,MAAM,aAAa,CAAC;AAsevF,eAAO,MAAM,kBAAkB,EAAE,SAchC,CAAC","sourcesContent":["/**\n * GitHub Copilot OAuth flow\n */\n\nimport { GITHUB_COPILOT_MODELS } from \"../../providers/github-copilot.models.ts\";\nimport { sleep } from \"../../utils/sleep.ts\";\nimport type { OAuthAuth, OAuthCredential, ProviderAuthInteraction } from \"../types.ts\";\nimport { pollOAuthDeviceCodeFlow } from \"./device-code.ts\";\n\nconst decode = (s: string) => atob(s);\nconst CLIENT_ID = decode(\"SXYxLmI1MDdhMDhjODdlY2ZlOTg=\");\n\nconst COPILOT_HEADERS = {\n\t\"User-Agent\": \"GitHubCopilotChat/0.35.0\",\n\t\"Editor-Version\": \"vscode/1.107.0\",\n\t\"Editor-Plugin-Version\": \"copilot-chat/0.35.0\",\n\t\"Copilot-Integration-Id\": \"vscode-chat\",\n} as const;\nconst COPILOT_API_VERSION = \"2026-06-01\";\n\ntype DeviceCodeResponse = {\n\tdevice_code: string;\n\tuser_code: string;\n\tverification_uri: string;\n\tinterval?: number;\n\texpires_in: number;\n};\n\ntype DeviceTokenSuccessResponse = {\n\taccess_token: string;\n\ttoken_type?: string;\n\tscope?: string;\n};\n\ntype DeviceTokenErrorResponse = {\n\terror: string;\n\terror_description?: string;\n\tinterval?: number;\n};\n\nfunction normalizeDomain(input: string): string | null {\n\tconst trimmed = input.trim();\n\tif (!trimmed) return null;\n\ttry {\n\t\tconst url = trimmed.includes(\"://\") ? new URL(trimmed) : new URL(`https://${trimmed}`);\n\t\treturn url.hostname;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction getUrls(domain: string): {\n\tdeviceCodeUrl: string;\n\taccessTokenUrl: string;\n\tcopilotTokenUrl: string;\n} {\n\treturn {\n\t\tdeviceCodeUrl: `https://${domain}/login/device/code`,\n\t\taccessTokenUrl: `https://${domain}/login/oauth/access_token`,\n\t\tcopilotTokenUrl: `https://api.${domain}/copilot_internal/v2/token`,\n\t};\n}\n\n/**\n * Parse the proxy-ep from a Copilot token and convert to API base URL.\n * Token format: tid=...;exp=...;proxy-ep=proxy.individual.githubcopilot.com;...\n * Returns API URL like https://api.individual.githubcopilot.com\n */\nfunction getBaseUrlFromToken(token: string): string | null {\n\tconst match = token.match(/proxy-ep=([^;]+)/);\n\tif (!match) return null;\n\tconst proxyHost = match[1];\n\t// Convert proxy.xxx to api.xxx\n\tconst apiHost = proxyHost.replace(/^proxy\\./, \"api.\");\n\treturn `https://${apiHost}`;\n}\n\nfunction getGitHubCopilotBaseUrl(token?: string, enterpriseDomain?: string): string {\n\t// If we have a token, extract the base URL from proxy-ep\n\tif (token) {\n\t\tconst urlFromToken = getBaseUrlFromToken(token);\n\t\tif (urlFromToken) return urlFromToken;\n\t}\n\t// Fallback for enterprise or if token parsing fails\n\tif (enterpriseDomain) return `https://copilot-api.${enterpriseDomain}`;\n\treturn \"https://api.individual.githubcopilot.com\";\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n\treturn value && typeof value === \"object\" ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction parseGitHubCopilotModelCatalog(raw: unknown, allowPolicyFallback: boolean) {\n\tconst data = asRecord(raw)?.data;\n\tif (!Array.isArray(data)) {\n\t\tthrow new Error(\"Invalid Copilot models response\");\n\t}\n\n\tconst accountModels = data.flatMap((rawItem) => {\n\t\tconst item = asRecord(rawItem);\n\t\tconst id = item?.id;\n\t\tif (!item || typeof id !== \"string\") return [];\n\n\t\tconst capabilities = asRecord(item.capabilities);\n\t\tconst supports = asRecord(capabilities?.supports);\n\t\tif (supports?.tool_calls === false) return [];\n\n\t\treturn [\n\t\t\t{\n\t\t\t\tid,\n\t\t\t\tpickerEnabled: item.model_picker_enabled === true,\n\t\t\t\tpolicyState: asRecord(item.policy)?.state,\n\t\t\t},\n\t\t];\n\t});\n\tconst pickerModelIds = accountModels\n\t\t.filter((model) => model.pickerEnabled && model.policyState !== \"disabled\")\n\t\t.map((model) => model.id);\n\tconst usePolicyFallback = allowPolicyFallback && pickerModelIds.length === 0;\n\tconst availableModelIds =\n\t\tpickerModelIds.length > 0 || !allowPolicyFallback\n\t\t\t? pickerModelIds\n\t\t\t: accountModels.filter((model) => model.policyState === \"enabled\").map((model) => model.id);\n\tconst policyModelIds = accountModels\n\t\t.filter(\n\t\t\t(model) =>\n\t\t\t\tmodel.policyState === \"unconfigured\" &&\n\t\t\t\tObject.hasOwn(GITHUB_COPILOT_MODELS, model.id) &&\n\t\t\t\t(model.pickerEnabled || usePolicyFallback),\n\t\t)\n\t\t.map((model) => model.id);\n\treturn { availableModelIds, policyModelIds };\n}\n\nasync function fetchWithRateLimitRetry(\n\turl: string,\n\tinit: RequestInit,\n\tsignal: AbortSignal,\n\tretryPolicy: { maxRetries: number; maxElapsedMs: number },\n): Promise<Response> {\n\tconst retryBudgetSignal =\n\t\tretryPolicy.maxRetries > 0 && retryPolicy.maxElapsedMs > 0\n\t\t\t? AbortSignal.timeout(retryPolicy.maxElapsedMs)\n\t\t\t: undefined;\n\tconst requestSignal = retryBudgetSignal ? AbortSignal.any([signal, retryBudgetSignal]) : signal;\n\tconst retryDeadline = retryBudgetSignal ? Date.now() + retryPolicy.maxElapsedMs : undefined;\n\tfor (let retry = 0; ; retry++) {\n\t\tconst response = await fetch(url, {\n\t\t\t...init,\n\t\t\tsignal: AbortSignal.any([requestSignal, AbortSignal.timeout(5000)]),\n\t\t});\n\t\tif (response.status !== 429 || retry === retryPolicy.maxRetries) return response;\n\n\t\tconst retryAfter = response.headers.get(\"retry-after\");\n\t\tlet delayMs = 500 * 2 ** retry;\n\t\tif (retryAfter) {\n\t\t\tconst seconds = Number.parseFloat(retryAfter);\n\t\t\tdelayMs = Number.isNaN(seconds) ? Date.parse(retryAfter) - Date.now() : seconds * 1000;\n\t\t\tif (!Number.isFinite(delayMs)) return response;\n\t\t}\n\t\tdelayMs = Math.max(0, delayMs);\n\t\tif (retryDeadline !== undefined && delayMs >= retryDeadline - Date.now()) return response;\n\t\tawait response.body?.cancel();\n\t\tawait sleep(delayMs, requestSignal);\n\t}\n}\n\nasync function fetchGitHubCopilotModels(\n\tcopilotToken: string,\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n\tretryPolicy: { maxRetries: number; maxElapsedMs: number },\n) {\n\tconst baseUrl = getGitHubCopilotBaseUrl(copilotToken, enterpriseDomain);\n\t// Some Individual accounts return false for every picker flag despite explicit enabled policies.\n\t// Limit the fallback to that endpoint so other account types keep strict picker semantics.\n\tconst allowPolicyFallback = baseUrl === \"https://api.individual.githubcopilot.com\";\n\tconst response = await fetchWithRateLimitRetry(\n\t\t`${baseUrl}/models`,\n\t\t{\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${copilotToken}`,\n\t\t\t\t...COPILOT_HEADERS,\n\t\t\t\t\"X-GitHub-Api-Version\": COPILOT_API_VERSION,\n\t\t\t},\n\t\t},\n\t\tsignal,\n\t\tretryPolicy,\n\t);\n\tif (!response.ok) {\n\t\tthrow new Error(`${response.status} ${response.statusText}: ${await response.text()}`);\n\t}\n\treturn parseGitHubCopilotModelCatalog(await response.json(), allowPolicyFallback);\n}\n\nasync function fetchJson(url: string, init: RequestInit): Promise<unknown> {\n\tconst response = await fetch(url, init);\n\tif (!response.ok) {\n\t\tconst text = await response.text();\n\t\tthrow new Error(`${response.status} ${response.statusText}: ${text}`);\n\t}\n\treturn response.json();\n}\n\nasync function startDeviceFlow(domain: string, signal: AbortSignal): Promise<DeviceCodeResponse> {\n\tconst urls = getUrls(domain);\n\tconst data = await fetchJson(urls.deviceCodeUrl, {\n\t\tmethod: \"POST\",\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\"User-Agent\": \"GitHubCopilotChat/0.35.0\",\n\t\t},\n\t\tbody: new URLSearchParams({\n\t\t\tclient_id: CLIENT_ID,\n\t\t\tscope: \"read:user\",\n\t\t}),\n\t\tsignal,\n\t});\n\n\tif (!data || typeof data !== \"object\") {\n\t\tthrow new Error(\"Invalid device code response\");\n\t}\n\n\tconst deviceCode = (data as Record<string, unknown>).device_code;\n\tconst userCode = (data as Record<string, unknown>).user_code;\n\tconst verificationUri = (data as Record<string, unknown>).verification_uri;\n\tconst interval = (data as Record<string, unknown>).interval;\n\tconst expiresIn = (data as Record<string, unknown>).expires_in;\n\n\tif (\n\t\ttypeof deviceCode !== \"string\" ||\n\t\ttypeof userCode !== \"string\" ||\n\t\ttypeof verificationUri !== \"string\" ||\n\t\t(interval !== undefined && typeof interval !== \"number\") ||\n\t\ttypeof expiresIn !== \"number\"\n\t) {\n\t\tthrow new Error(\"Invalid device code response fields\");\n\t}\n\n\t// The verification URI is opened in the user's browser and to prevent `open` from\n\t// opening an executable or similar, we force it to be a URL.\n\tlet parsedUri: URL;\n\ttry {\n\t\tparsedUri = new URL(verificationUri);\n\t} catch {\n\t\tthrow new Error(\"Untrusted verification_uri in device code response\");\n\t}\n\tif (parsedUri.protocol !== \"https:\" && parsedUri.protocol !== \"http:\") {\n\t\tthrow new Error(\"Untrusted verification_uri in device code response\");\n\t}\n\n\treturn {\n\t\tdevice_code: deviceCode,\n\t\tuser_code: userCode,\n\t\tverification_uri: parsedUri.href,\n\t\tinterval,\n\t\texpires_in: expiresIn,\n\t};\n}\n\nasync function pollForGitHubAccessToken(\n\tdomain: string,\n\tdevice: DeviceCodeResponse,\n\tsignal: AbortSignal,\n): Promise<string> {\n\tconst urls = getUrls(domain);\n\treturn pollOAuthDeviceCodeFlow<string>({\n\t\tintervalSeconds: device.interval,\n\t\texpiresInSeconds: device.expires_in,\n\t\twaitBeforeFirstPoll: true,\n\t\tsignal,\n\t\tpoll: async () => {\n\t\t\tconst raw = await fetchJson(urls.accessTokenUrl, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\t\"Content-Type\": \"application/x-www-form-urlencoded\",\n\t\t\t\t\t\"User-Agent\": \"GitHubCopilotChat/0.35.0\",\n\t\t\t\t},\n\t\t\t\tbody: new URLSearchParams({\n\t\t\t\t\tclient_id: CLIENT_ID,\n\t\t\t\t\tdevice_code: device.device_code,\n\t\t\t\t\tgrant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n\t\t\t\t}),\n\t\t\t\tsignal,\n\t\t\t});\n\n\t\t\tif (raw && typeof raw === \"object\" && typeof (raw as DeviceTokenSuccessResponse).access_token === \"string\") {\n\t\t\t\treturn { status: \"complete\", value: (raw as DeviceTokenSuccessResponse).access_token };\n\t\t\t}\n\n\t\t\tif (raw && typeof raw === \"object\" && typeof (raw as DeviceTokenErrorResponse).error === \"string\") {\n\t\t\t\tconst { error, error_description: description, interval } = raw as DeviceTokenErrorResponse;\n\t\t\t\tif (error === \"authorization_pending\") {\n\t\t\t\t\treturn { status: \"pending\" };\n\t\t\t\t}\n\n\t\t\t\tif (error === \"slow_down\") {\n\t\t\t\t\treturn { status: \"slow_down\", intervalSeconds: typeof interval === \"number\" ? interval : undefined };\n\t\t\t\t}\n\n\t\t\t\tconst descriptionSuffix = description ? `: ${description}` : \"\";\n\t\t\t\treturn { status: \"failed\", message: `Device flow failed: ${error}${descriptionSuffix}` };\n\t\t\t}\n\n\t\t\treturn { status: \"failed\", message: \"Invalid device token response\" };\n\t\t},\n\t});\n}\n\nasync function refreshGitHubCopilotAccessToken(\n\trefreshToken: string,\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n): Promise<OAuthCredential> {\n\tconst domain = enterpriseDomain || \"github.com\";\n\tconst urls = getUrls(domain);\n\n\tconst raw = await fetchJson(urls.copilotTokenUrl, {\n\t\theaders: {\n\t\t\tAccept: \"application/json\",\n\t\t\tAuthorization: `Bearer ${refreshToken}`,\n\t\t\t...COPILOT_HEADERS,\n\t\t},\n\t\tsignal,\n\t});\n\n\tif (!raw || typeof raw !== \"object\") {\n\t\tthrow new Error(\"Invalid Copilot token response\");\n\t}\n\n\tconst token = (raw as Record<string, unknown>).token;\n\tconst expiresAt = (raw as Record<string, unknown>).expires_at;\n\n\tif (typeof token !== \"string\" || typeof expiresAt !== \"number\") {\n\t\tthrow new Error(\"Invalid Copilot token response fields\");\n\t}\n\n\treturn {\n\t\ttype: \"oauth\",\n\t\trefresh: refreshToken,\n\t\taccess: token,\n\t\texpires: expiresAt * 1000 - 5 * 60 * 1000,\n\t\tenterpriseUrl: enterpriseDomain,\n\t};\n}\n\n/**\n * Refresh GitHub Copilot token\n */\nasync function refreshGitHubCopilotToken(\n\trefreshToken: string,\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n): Promise<OAuthCredential> {\n\tconst credentials = await refreshGitHubCopilotAccessToken(refreshToken, enterpriseDomain, signal);\n\tconst { availableModelIds } = await fetchGitHubCopilotModels(credentials.access, enterpriseDomain, signal, {\n\t\tmaxRetries: 0,\n\t\tmaxElapsedMs: 0,\n\t});\n\treturn {\n\t\t...credentials,\n\t\tavailableModelIds,\n\t};\n}\n\n/**\n * Enable a model for the user's GitHub Copilot account.\n * This is required for some models (like Claude, Grok) before they can be used.\n */\nasync function enableGitHubCopilotModel(\n\ttoken: string,\n\tmodelId: string,\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n): Promise<boolean> {\n\tconst baseUrl = getGitHubCopilotBaseUrl(token, enterpriseDomain);\n\tconst url = `${baseUrl}/models/${modelId}/policy`;\n\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetchWithRateLimitRetry(\n\t\t\turl,\n\t\t\t{\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\tAuthorization: `Bearer ${token}`,\n\t\t\t\t\t...COPILOT_HEADERS,\n\t\t\t\t\t\"openai-intent\": \"chat-policy\",\n\t\t\t\t\t\"x-interaction-type\": \"chat-policy\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({ state: \"enabled\" }),\n\t\t\t},\n\t\t\tsignal,\n\t\t\t{ maxRetries: 2, maxElapsedMs: 5000 },\n\t\t);\n\t} catch (error) {\n\t\tif (signal.aborted) throw error;\n\t\treturn false;\n\t}\n\tif (response.status === 429) {\n\t\tthrow new Error(`${response.status} ${response.statusText}: ${await response.text()}`);\n\t}\n\treturn response.ok;\n}\n\n/**\n * Enable the requested GitHub Copilot models and return the successful IDs.\n * Policy updates are best effort; exhausted rate limiting stops the batch.\n */\nasync function enableGitHubCopilotModels(\n\ttoken: string,\n\tmodelIds: readonly string[],\n\tenterpriseDomain: string | undefined,\n\tsignal: AbortSignal,\n): Promise<string[]> {\n\tconst enabledModelIds: string[] = [];\n\tfor (const modelId of modelIds) {\n\t\ttry {\n\t\t\tif (await enableGitHubCopilotModel(token, modelId, enterpriseDomain, signal)) {\n\t\t\t\tenabledModelIds.push(modelId);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (signal.aborted) throw error;\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn enabledModelIds;\n}\n\nasync function loginGitHubCopilot(interaction: ProviderAuthInteraction): Promise<OAuthCredential> {\n\tconst input = await interaction.prompt({\n\t\ttype: \"text\",\n\t\tmessage: \"GitHub Enterprise URL/domain (blank for github.com)\",\n\t\tplaceholder: \"company.ghe.com\",\n\t});\n\tif (interaction.signal.aborted) throw new Error(\"Login cancelled\");\n\n\tconst trimmed = input.trim();\n\tconst enterpriseDomain = normalizeDomain(input);\n\tif (trimmed && !enterpriseDomain) throw new Error(\"Invalid GitHub Enterprise URL/domain\");\n\tconst domain = enterpriseDomain || \"github.com\";\n\n\tconst device = await startDeviceFlow(domain, interaction.signal);\n\tinteraction.notify({\n\t\ttype: \"device_code\",\n\t\tuserCode: device.user_code,\n\t\tverificationUri: device.verification_uri,\n\t\tintervalSeconds: device.interval,\n\t\texpiresInSeconds: device.expires_in,\n\t});\n\n\tconst githubAccessToken = await pollForGitHubAccessToken(domain, device, interaction.signal);\n\tconst credentials = await refreshGitHubCopilotAccessToken(\n\t\tgithubAccessToken,\n\t\tenterpriseDomain ?? undefined,\n\t\tinteraction.signal,\n\t);\n\tconst models = await fetchGitHubCopilotModels(\n\t\tcredentials.access,\n\t\tenterpriseDomain ?? undefined,\n\t\tinteraction.signal,\n\t\t{\n\t\t\tmaxRetries: 2,\n\t\t\tmaxElapsedMs: 5000,\n\t\t},\n\t);\n\tlet enabledModelIds: string[] = [];\n\tif (models.policyModelIds.length > 0) {\n\t\tinteraction.notify({ type: \"progress\", message: \"Enabling models...\" });\n\t\tenabledModelIds = await enableGitHubCopilotModels(\n\t\t\tcredentials.access,\n\t\t\tmodels.policyModelIds,\n\t\t\tenterpriseDomain ?? undefined,\n\t\t\tinteraction.signal,\n\t\t);\n\t}\n\treturn {\n\t\t...credentials,\n\t\tavailableModelIds: [...new Set([...models.availableModelIds, ...enabledModelIds])],\n\t};\n}\n\nfunction copilotEnterpriseDomain(credential: OAuthCredential): string | undefined {\n\tconst enterpriseUrl = credential.enterpriseUrl;\n\tif (typeof enterpriseUrl !== \"string\" || !enterpriseUrl) return undefined;\n\treturn normalizeDomain(enterpriseUrl) ?? undefined;\n}\n\nexport const githubCopilotOAuth: OAuthAuth = {\n\tname: \"GitHub Copilot\",\n\tisSubscription: true,\n\tlogin: loginGitHubCopilot,\n\trefresh: (credential, signal) =>\n\t\trefreshGitHubCopilotToken(credential.refresh, copilotEnterpriseDomain(credential), signal),\n\n\t/** Derive the credential-specific proxy endpoint for each request. */\n\tasync toAuth(credential) {\n\t\treturn {\n\t\t\tapiKey: credential.access,\n\t\t\tbaseUrl: getGitHubCopilotBaseUrl(credential.access, copilotEnterpriseDomain(credential)),\n\t\t};\n\t},\n};\n"]}
|