pi2dsh 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2920 +1,4 @@
1
1
 
2
- import { n as __require } from "../rolldown-runtime-D-uZhY3_.mjs";
3
2
  import { c as uuidv7, t as typebox_exports } from "../build-DsGYAgiT.mjs";
4
- //#region src/compat/vendor/pi-ai-overflow.ts
5
- /**
6
- * Regex patterns to detect context overflow errors from different providers.
7
- *
8
- * These patterns match error messages returned when the input exceeds
9
- * the model's context window.
10
- *
11
- * Provider-specific patterns (with example error messages):
12
- *
13
- * - Anthropic: "prompt is too long: 213462 tokens > 200000 maximum"
14
- * - Anthropic: "413 {\"error\":{\"type\":\"request_too_large\",\"message\":\"Request exceeds the maximum size\"}}"
15
- * - OpenAI: "Your input exceeds the context window of this model"
16
- * - OpenAI/LiteLLM: "Requested token count exceeds the model's maximum context length of 131072 tokens"
17
- * - OpenAI-compatible: "Input length (265330) exceeds model's maximum context length (262144)."
18
- * - Google: "The input token count (1196265) exceeds the maximum number of tokens allowed (1048575)"
19
- * - xAI: "This model's maximum prompt length is 131072 but the request contains 537812 tokens"
20
- * - Groq: "Please reduce the length of the messages or completion"
21
- * - OpenRouter: "This endpoint's maximum context length is X tokens. However, you requested about Y tokens"
22
- * - OpenRouter/Poolside: "Input length X exceeds the maximum allowed input length of Y tokens."
23
- * - Together AI: "The input (X tokens) is longer than the model's context length (Y tokens)."
24
- * - llama.cpp: "the request exceeds the available context size, try increasing it"
25
- * - LM Studio: "tokens to keep from the initial prompt is greater than the context length"
26
- * - GitHub Copilot: "prompt token count of X exceeds the limit of Y"
27
- * - MiniMax: "invalid params, context window exceeds limit"
28
- * - Kimi For Coding: "Your request exceeded model token limit: X (requested: Y)"
29
- * - DS4: "Prompt has X tokens, but the configured context size is Y tokens"
30
- * - Cerebras: "400/413 status code (no body)"
31
- * - Mistral: "Prompt contains X tokens ... too large for model with Y maximum context length"
32
- * - z.ai: Does NOT error, accepts overflow silently - handled via usage.input > contextWindow
33
- * - Xiaomi MiMo: Truncates input to fill contextWindow exactly, then returns finish_reason "length"
34
- * with output=0 (no room left to generate). Detected via stopReason "length" + zero output +
35
- * input filling the context window.
36
- * - DashScope/Qwen: "Range of input length should be [1, X]" (HTTP 400 invalid_parameter_error)
37
- * - Ollama: Some deployments truncate silently, others return errors like "prompt too long; exceeded max context length by X tokens"
38
- */
39
- const OVERFLOW_PATTERNS = [
40
- /prompt is too long/i,
41
- /request_too_large/i,
42
- /input is too long for requested model/i,
43
- /exceeds the context window/i,
44
- /exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\d,]+ tokens?|\s*\([\d,]+\))/i,
45
- /input token count.*exceeds the maximum/i,
46
- /maximum prompt length is \d+/i,
47
- /reduce the length of the messages/i,
48
- /maximum context length is \d+ tokens/i,
49
- /exceeds (?:the )?maximum allowed input length of [\d,]+ tokens?/i,
50
- /input \(\d+ tokens\) is longer than the model'?s context length \(\d+ tokens\)/i,
51
- /exceeds the limit of \d+/i,
52
- /exceeds the available context size/i,
53
- /greater than the context length/i,
54
- /context window exceeds limit/i,
55
- /exceeded model token limit/i,
56
- /too large for model with \d+ maximum context length/i,
57
- /prompt has [\d,]+ tokens?, but the configured context size is [\d,]+ tokens?/i,
58
- /model_context_window_exceeded/i,
59
- /prompt too long; exceeded (?:max )?context length/i,
60
- /range of input length should be/i,
61
- /context[_ ]length[_ ]exceeded/i,
62
- /too many tokens/i,
63
- /token limit exceeded/i,
64
- /^4(?:00|13)\s*(?:status code)?\s*\(no body\)/i
65
- ];
66
- /**
67
- * Patterns that indicate non-overflow errors (e.g. rate limiting, server errors).
68
- * Error messages matching any of these are excluded from overflow detection
69
- * even if they also match an OVERFLOW_PATTERN.
70
- *
71
- * Example: Bedrock formats throttling errors as "ThrottlingException: Too many tokens,
72
- * please wait before trying again." which would match the /too many tokens/i overflow
73
- * pattern without this exclusion.
74
- */
75
- const NON_OVERFLOW_PATTERNS = [
76
- /^(Throttling error|Service unavailable):/i,
77
- /rate limit/i,
78
- /too many requests/i
79
- ];
80
- /**
81
- * Check if an assistant message represents a context overflow error.
82
- *
83
- * This handles three cases:
84
- * 1. Error-based overflow: Most providers return stopReason "error" with a
85
- * specific error message pattern.
86
- * 2. Silent overflow: Some providers accept overflow requests and return
87
- * successfully. For these, we check if usage.input exceeds the context window.
88
- * 3. Length-stop overflow: Xiaomi MiMo can return "length" with zero output when
89
- * the input fills the context window.
90
- *
91
- * ## Reliability by Provider
92
- *
93
- * **Reliable detection (returns error with detectable message):**
94
- * - Anthropic: "prompt is too long: X tokens > Y maximum" or "request_too_large"
95
- * - OpenAI (Completions & Responses): "exceeds the context window", "exceeds the model's maximum context length of X tokens", or "exceeds model's maximum context length (X)"
96
- * - Google Gemini: "input token count exceeds the maximum"
97
- * - xAI (Grok): "maximum prompt length is X but request contains Y"
98
- * - Groq: "reduce the length of the messages"
99
- * - Cerebras: 400/413 status code (no body)
100
- * - Mistral: "Prompt contains X tokens ... too large for model with Y maximum context length"
101
- * - OpenRouter (most backends): "maximum context length is X tokens"
102
- * - OpenRouter/Poolside: "Input length X exceeds the maximum allowed input length of Y tokens."
103
- * - Together AI: "The input (X tokens) is longer than the model's context length (Y tokens)."
104
- * - llama.cpp: "exceeds the available context size"
105
- * - LM Studio: "greater than the context length"
106
- * - Kimi For Coding: "exceeded model token limit: X (requested: Y)"
107
- * - DS4: "Prompt has X tokens, but the configured context size is Y tokens"
108
- * - DashScope/Qwen: "Range of input length should be [1, X]"
109
- *
110
- * **Unreliable detection:**
111
- * - z.ai: Sometimes accepts overflow silently (detectable via usage.input > contextWindow),
112
- * sometimes returns rate limit errors. Pass contextWindow param to detect silent overflow.
113
- * - Xiaomi MiMo: Truncates input to fit contextWindow then returns stopReason "length" with
114
- * output=0. Pass contextWindow param to detect via the "filled context + zero output" signal.
115
- * - Ollama: May truncate input silently for some setups, but may also return explicit
116
- * overflow errors that match the patterns above. Silent truncation still cannot be
117
- * detected here because we do not know the expected token count.
118
- *
119
- * ## Custom Providers
120
- *
121
- * If you've added custom models via settings.json, this function may not detect
122
- * overflow errors from those providers. To add support:
123
- *
124
- * 1. Send a request that exceeds the model's context window
125
- * 2. Check the errorMessage in the response
126
- * 3. Create a regex pattern that matches the error
127
- * 4. The pattern should be added to OVERFLOW_PATTERNS in this file, or
128
- * check the errorMessage yourself before calling this function
129
- *
130
- * @param message - The assistant message to check
131
- * @param contextWindow - Optional context window size for detecting silent overflow (z.ai)
132
- * @returns true if the message indicates a context overflow
133
- */
134
- function isContextOverflow(message, contextWindow) {
135
- if (message.stopReason === "error" && message.errorMessage) {
136
- if (!NON_OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage)) && OVERFLOW_PATTERNS.some((p) => p.test(message.errorMessage))) return true;
137
- }
138
- if (contextWindow && message.stopReason === "stop") {
139
- if (message.usage.input + message.usage.cacheRead > contextWindow) return true;
140
- }
141
- if (contextWindow && message.stopReason === "length" && message.usage.output === 0) {
142
- if (message.usage.input + message.usage.cacheRead >= contextWindow * .99) return true;
143
- }
144
- return false;
145
- }
146
- /**
147
- * Check whether a length stop ended below the caller or model's intended output limit.
148
- * Such responses may be caused by context pressure or provider-side truncation, so callers
149
- * can make one bounded compact-and-retry attempt. `desiredMaxOutput` must be the original
150
- * limit before any context-based clamping.
151
- */
152
- function isRecoverableLength(message, desiredMaxOutput) {
153
- return message.stopReason === "length" && desiredMaxOutput > 0 && message.usage.output < desiredMaxOutput;
154
- }
155
- //#endregion
156
- //#region src/compat/vendor/pi-ai-retry.ts
157
- function buildProviderErrorPattern(patterns) {
158
- return new RegExp(patterns.join("|"), "i");
159
- }
160
- const NON_RETRYABLE_PROVIDER_LIMIT_ERROR_PATTERN = buildProviderErrorPattern([
161
- "GoUsageLimitError",
162
- "FreeUsageLimitError",
163
- "Monthly usage limit reached",
164
- "available balance",
165
- "insufficient_quota",
166
- "out of budget",
167
- "quota exceeded",
168
- "billing"
169
- ]);
170
- const RETRYABLE_PROVIDER_ERROR_PATTERN = buildProviderErrorPattern([
171
- "overloaded",
172
- "rate.?limit",
173
- "too many requests",
174
- "429",
175
- "500",
176
- "502",
177
- "503",
178
- "504",
179
- "524",
180
- "service.?unavailable",
181
- "server.?error",
182
- "internal.?error",
183
- "provider.?returned.?error",
184
- "exceeded request buffer limit while retrying upstream",
185
- "network.?error",
186
- "connection.?error",
187
- "connection.?refused",
188
- "connection.?lost",
189
- "other side closed",
190
- "fetch failed",
191
- "getaddrinfo",
192
- "ENOTFOUND",
193
- "EAI_AGAIN",
194
- "upstream.?connect",
195
- "reset before headers",
196
- "socket hang up",
197
- "socket connection was closed",
198
- "timed? out",
199
- "timeout",
200
- "terminated",
201
- "websocket.?closed",
202
- "websocket.?error",
203
- "ended without",
204
- "stream ended before message_stop",
205
- "stream ended before a terminal response event",
206
- "http2 request did not get a response",
207
- "retry delay",
208
- "you can retry your request",
209
- "try your request again",
210
- "please retry your request",
211
- "ResourceExhausted"
212
- ]);
213
- /**
214
- * Classifies whether a failed assistant message looks like a transient provider
215
- * or transport error, so callers can decide if the last assistant turn should be
216
- * restarted.
217
- *
218
- * This does not implement retry policy. Callers should first handle context
219
- * overflow separately, then apply their own retry budget, backoff, and reporting
220
- * before restarting the assistant turn.
221
- */
222
- function isRetryableAssistantError(message) {
223
- if (message.stopReason !== "error" || !message.errorMessage) return false;
224
- const errorMessage = message.errorMessage;
225
- if (NON_RETRYABLE_PROVIDER_LIMIT_ERROR_PATTERN.test(errorMessage)) return false;
226
- return RETRYABLE_PROVIDER_ERROR_PATTERN.test(errorMessage);
227
- }
228
- //#endregion
229
- //#region src/compat/vendor/pi-ai-event-stream.ts
230
- var EventStream = class {
231
- queue = [];
232
- waiting = [];
233
- done = false;
234
- finalResultPromise;
235
- resolveFinalResult;
236
- isComplete;
237
- extractResult;
238
- constructor(isComplete, extractResult) {
239
- this.isComplete = isComplete;
240
- this.extractResult = extractResult;
241
- this.finalResultPromise = new Promise((resolve) => {
242
- this.resolveFinalResult = resolve;
243
- });
244
- }
245
- push(event) {
246
- if (this.done) return;
247
- if (this.isComplete(event)) {
248
- this.done = true;
249
- this.resolveFinalResult(this.extractResult(event));
250
- }
251
- const waiter = this.waiting.shift();
252
- if (waiter) waiter({
253
- value: event,
254
- done: false
255
- });
256
- else this.queue.push(event);
257
- }
258
- end(result) {
259
- this.done = true;
260
- if (result !== void 0) this.resolveFinalResult(result);
261
- while (this.waiting.length > 0) this.waiting.shift()({
262
- value: void 0,
263
- done: true
264
- });
265
- }
266
- async *[Symbol.asyncIterator]() {
267
- while (true) if (this.queue.length > 0) yield this.queue.shift();
268
- else if (this.done) return;
269
- else {
270
- const result = await new Promise((resolve) => this.waiting.push(resolve));
271
- if (result.done) return;
272
- yield result.value;
273
- }
274
- }
275
- result() {
276
- return this.finalResultPromise;
277
- }
278
- };
279
- var AssistantMessageEventStream = class extends EventStream {
280
- constructor() {
281
- super((event) => event.type === "done" || event.type === "error", (event) => {
282
- if (event.type === "done") return event.message;
283
- else if (event.type === "error") return event.error;
284
- throw new Error("Unexpected event type for final result");
285
- });
286
- }
287
- };
288
- //#endregion
289
- //#region src/compat/vendor/pi-ai-lazy.ts
290
- function createSetupErrorMessage(model, error) {
291
- return {
292
- role: "assistant",
293
- content: [],
294
- api: model.api,
295
- provider: model.provider,
296
- model: model.id,
297
- usage: {
298
- input: 0,
299
- output: 0,
300
- cacheRead: 0,
301
- cacheWrite: 0,
302
- totalTokens: 0,
303
- cost: {
304
- input: 0,
305
- output: 0,
306
- cacheRead: 0,
307
- cacheWrite: 0,
308
- total: 0
309
- }
310
- },
311
- stopReason: "error",
312
- errorMessage: error instanceof Error ? error.message : String(error),
313
- timestamp: Date.now()
314
- };
315
- }
316
- function hasResult(source) {
317
- return typeof source.result === "function";
318
- }
319
- async function forwardStream(target, source) {
320
- for await (const event of source) target.push(event);
321
- target.end(hasResult(source) ? await source.result() : void 0);
322
- }
323
- /**
324
- * Returns a stream synchronously while running async setup (auth resolution,
325
- * lazy module loading) behind it. Setup failures terminate the stream with an
326
- * error event.
327
- */
328
- function lazyStream(model, setup) {
329
- const outer = new AssistantMessageEventStream();
330
- setup().then((inner) => forwardStream(outer, inner)).catch((error) => {
331
- const message = createSetupErrorMessage(model, error);
332
- outer.push({
333
- type: "error",
334
- reason: "error",
335
- error: message
336
- });
337
- outer.end(message);
338
- });
339
- return outer;
340
- }
341
- function lazyApi(load, capabilities) {
342
- const api = {
343
- stream: (model, context, options) => lazyStream(model, async () => (await load()).stream(model, context, options)),
344
- streamSimple: (model, context, options) => lazyStream(model, async () => (await load()).streamSimple(model, context, options))
345
- };
346
- if (capabilities?.fetchDeferred) api.fetchDeferred = (model, handle, options) => lazyStream(model, async () => {
347
- const implementation = await load();
348
- if (!implementation.fetchDeferred) throw new Error("API does not support deferred responses");
349
- return implementation.fetchDeferred(model, handle, options);
350
- });
351
- if (capabilities?.cancelDeferred) api.cancelDeferred = async (model, handle, options) => {
352
- const implementation = await load();
353
- if (!implementation.cancelDeferred) throw new Error("API cannot cancel deferred responses");
354
- await implementation.cancelDeferred(model, handle, options);
355
- };
356
- return api;
357
- }
358
- //#endregion
359
- //#region src/compat/vendor/pi-ai-provider.ts
360
- function withCauseDetail(message, cause) {
361
- if (cause === void 0 || cause === null) return message;
362
- const detail = formatThrownValue(cause).trim();
363
- if (!detail || message.includes(detail)) return message;
364
- return `${message}: ${detail}`;
365
- }
366
- var ModelsError = class extends Error {
367
- code;
368
- constructor(code, message, options) {
369
- super(withCauseDetail(message, options?.cause), options);
370
- this.name = "ModelsError";
371
- this.code = code;
372
- }
373
- };
374
- /**
375
- * Builds a provider from parts. Built-in provider factories and models.json
376
- * custom providers both go through this. A single `api` streams all models;
377
- * an `api` map dispatches on `model.api`, and a model whose api has no entry
378
- * produces a stream error.
379
- */
380
- function createProvider(input) {
381
- const baselineModels = input.models;
382
- let dynamicModels = [];
383
- const fetchModels = input.fetchModels;
384
- const currentModels = () => {
385
- const merged = [...baselineModels];
386
- for (const model of dynamicModels) {
387
- const index = merged.findIndex((entry) => entry.id === model.id);
388
- if (index >= 0) merged[index] = model;
389
- else merged.push(model);
390
- }
391
- return merged;
392
- };
393
- const single = typeof input.api.stream === "function" ? input.api : void 0;
394
- const byApi = single ? void 0 : input.api;
395
- const apiFor = (model) => single ?? byApi?.[model.api];
396
- const dispatch = (model, run) => {
397
- const streams = apiFor(model);
398
- if (!streams) return lazyStream(model, async () => {
399
- throw new ModelsError("stream", `Provider ${input.id} has no API implementation for "${model.api}"`);
400
- });
401
- return run(streams);
402
- };
403
- const provider = {
404
- id: input.id,
405
- name: input.name ?? input.id,
406
- baseUrl: input.baseUrl,
407
- headers: input.headers,
408
- auth: input.auth,
409
- getModels: currentModels,
410
- refreshModels: fetchModels ? async (context) => {
411
- if (context.stored) {
412
- const restored = context.stored.models.filter((model) => model.provider === input.id).map((model) => model);
413
- if (!await context.publish({ update: () => {
414
- dynamicModels = restored;
415
- } })) return;
416
- }
417
- if (!context.allowNetwork || context.signal.aborted) return;
418
- const refreshed = await fetchModels(context);
419
- if (context.signal.aborted) return;
420
- await context.publish({
421
- persist: {
422
- models: refreshed,
423
- checkedAt: Date.now()
424
- },
425
- update: () => {
426
- dynamicModels = refreshed;
427
- }
428
- });
429
- } : void 0,
430
- filterModels: input.filterModels,
431
- stream: (model, context, options) => dispatch(model, (streams) => streams.stream(model, context, options)),
432
- streamSimple: (model, context, options) => dispatch(model, (streams) => streams.streamSimple(model, context, options))
433
- };
434
- const streams = single ? [single] : Object.values(byApi ?? {}).filter((entry) => entry !== void 0);
435
- if (streams.some((entry) => entry.fetchDeferred !== void 0)) provider.fetchDeferred = (model, handle, options) => lazyStream(model, async () => {
436
- const implementation = apiFor(model);
437
- if (!implementation?.fetchDeferred) throw new ModelsError("provider", `Provider ${input.id} does not support deferred responses for "${model.api}"`);
438
- return implementation.fetchDeferred(model, handle, options);
439
- });
440
- if (streams.some((entry) => entry.cancelDeferred !== void 0)) provider.cancelDeferred = async (model, handle, options) => {
441
- const implementation = apiFor(model);
442
- if (!implementation?.cancelDeferred) throw new ModelsError("provider", `Provider ${input.id} cannot cancel deferred responses for "${model.api}"`);
443
- await implementation.cancelDeferred(model, handle, options);
444
- };
445
- return provider;
446
- }
447
- //#endregion
448
- //#region src/compat/vendor/pi-oauth-flows/provider-env.ts
449
- let procEnvCache = null;
450
- /**
451
- * Fallback for https://github.com/oven-sh/bun/issues/27802.
452
- * Bun compiled binaries can expose an empty process.env inside Linux sandboxes
453
- * even though /proc/self/environ contains the environment.
454
- *
455
- * This intentionally duplicates restoreSandboxEnv() in
456
- * packages/coding-agent/src/bun/restore-sandbox-env.ts. The ai package can be
457
- * used directly, without going through that entrypoint, so provider env lookup
458
- * must not depend on process.env having been patched.
459
- */
460
- function getBunSandboxEnvValue(name) {
461
- if (typeof process === "undefined" || !process.versions?.bun || Object.keys(process.env).length > 0) return;
462
- if (procEnvCache === null) {
463
- procEnvCache = /* @__PURE__ */ new Map();
464
- try {
465
- const { readFileSync } = __require("node:fs");
466
- const data = readFileSync("/proc/self/environ", "utf-8");
467
- for (const entry of data.split("\0")) {
468
- const idx = entry.indexOf("=");
469
- if (idx > 0) procEnvCache.set(entry.slice(0, idx), entry.slice(idx + 1));
470
- }
471
- } catch {}
472
- }
473
- return procEnvCache.get(name);
474
- }
475
- /**
476
- * Resolve a provider env value from scoped overrides, normal process.env, then
477
- * the duplicated Bun sandbox fallback for direct pi-ai consumers.
478
- */
479
- function getProviderEnvValue(name, env) {
480
- return env?.[name] || (typeof process !== "undefined" ? process.env[name] : void 0) || getBunSandboxEnvValue(name) || void 0;
481
- }
482
- //#endregion
483
- //#region src/compat/vendor/pi-oauth-flows/device-code.ts
484
- const CANCEL_MESSAGE = "Login cancelled";
485
- const TIMEOUT_MESSAGE = "Device flow timed out";
486
- const SLOW_DOWN_TIMEOUT_MESSAGE = "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.";
487
- const MINIMUM_INTERVAL_MS = 1e3;
488
- const DEFAULT_POLL_INTERVAL_SECONDS$1 = 5;
489
- const SLOW_DOWN_INTERVAL_INCREMENT_MS = 5e3;
490
- function abortableSleep(ms, signal, cancelMessage) {
491
- return new Promise((resolve, reject) => {
492
- if (signal.aborted) {
493
- reject(new Error(cancelMessage));
494
- return;
495
- }
496
- const onAbort = () => {
497
- clearTimeout(timeout);
498
- reject(new Error(cancelMessage));
499
- };
500
- const timeout = setTimeout(() => {
501
- signal.removeEventListener("abort", onAbort);
502
- resolve();
503
- }, ms);
504
- signal.addEventListener("abort", onAbort, { once: true });
505
- });
506
- }
507
- async function pollOAuthDeviceCodeFlow(options) {
508
- const deadline = typeof options.expiresInSeconds === "number" ? Date.now() + options.expiresInSeconds * 1e3 : Number.POSITIVE_INFINITY;
509
- let intervalMs = Math.max(MINIMUM_INTERVAL_MS, Math.floor((options.intervalSeconds ?? DEFAULT_POLL_INTERVAL_SECONDS$1) * 1e3));
510
- let slowDownResponses = 0;
511
- if (options.waitBeforeFirstPoll) {
512
- const remainingMs = deadline - Date.now();
513
- if (remainingMs > 0) await abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);
514
- }
515
- while (Date.now() < deadline) {
516
- if (options.signal.aborted) throw new Error(CANCEL_MESSAGE);
517
- const result = await options.poll();
518
- if (result.status === "complete") return result.value;
519
- if (result.status === "failed") throw new Error(result.message);
520
- if (result.status === "slow_down") {
521
- slowDownResponses += 1;
522
- intervalMs = typeof result.intervalSeconds === "number" && Number.isFinite(result.intervalSeconds) && result.intervalSeconds > 0 ? Math.max(MINIMUM_INTERVAL_MS, Math.floor(result.intervalSeconds * 1e3)) : Math.max(MINIMUM_INTERVAL_MS, intervalMs + SLOW_DOWN_INTERVAL_INCREMENT_MS);
523
- }
524
- const remainingMs = deadline - Date.now();
525
- if (remainingMs <= 0) break;
526
- await abortableSleep(Math.min(intervalMs, remainingMs), options.signal, CANCEL_MESSAGE);
527
- }
528
- throw new Error(slowDownResponses > 0 ? SLOW_DOWN_TIMEOUT_MESSAGE : TIMEOUT_MESSAGE);
529
- }
530
- //#endregion
531
- //#region src/compat/vendor/pi-oauth-flows/oauth-page.ts
532
- const LOGO_SVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 800" aria-hidden="true"><path fill="#fff" fill-rule="evenodd" d="M165.29 165.29 H517.36 V400 H400 V517.36 H282.65 V634.72 H165.29 Z M282.65 282.65 V400 H400 V282.65 Z"/><path fill="#fff" d="M517.36 400 H634.72 V634.72 H517.36 Z"/></svg>`;
533
- function escapeHtml(value) {
534
- return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;").replaceAll("'", "&#39;");
535
- }
536
- function renderPage(options) {
537
- const title = escapeHtml(options.title);
538
- const heading = escapeHtml(options.heading);
539
- const message = escapeHtml(options.message);
540
- const details = options.details ? escapeHtml(options.details) : void 0;
541
- return `<!doctype html>
542
- <html lang="en">
543
- <head>
544
- <meta charset="utf-8" />
545
- <meta name="viewport" content="width=device-width, initial-scale=1" />
546
- <title>${title}</title>
547
- <style>
548
- :root {
549
- --text: #fafafa;
550
- --text-dim: #a1a1aa;
551
- --page-bg: #09090b;
552
- --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
553
- --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
554
- }
555
- * { box-sizing: border-box; }
556
- html { color-scheme: dark; }
557
- body {
558
- margin: 0;
559
- min-height: 100vh;
560
- display: flex;
561
- align-items: center;
562
- justify-content: center;
563
- padding: 24px;
564
- background: var(--page-bg);
565
- color: var(--text);
566
- font-family: var(--font-sans);
567
- text-align: center;
568
- }
569
- main {
570
- width: 100%;
571
- max-width: 560px;
572
- display: flex;
573
- flex-direction: column;
574
- align-items: center;
575
- justify-content: center;
576
- }
577
- .logo {
578
- width: 72px;
579
- height: 72px;
580
- display: block;
581
- margin-bottom: 24px;
582
- }
583
- h1 {
584
- margin: 0 0 10px;
585
- font-size: 28px;
586
- line-height: 1.15;
587
- font-weight: 650;
588
- color: var(--text);
589
- }
590
- p {
591
- margin: 0;
592
- line-height: 1.7;
593
- color: var(--text-dim);
594
- font-size: 15px;
595
- }
596
- .details {
597
- margin-top: 16px;
598
- font-family: var(--font-mono);
599
- font-size: 13px;
600
- color: var(--text-dim);
601
- white-space: pre-wrap;
602
- word-break: break-word;
603
- }
604
- </style>
605
- </head>
606
- <body>
607
- <main>
608
- <div class="logo">${LOGO_SVG}</div>
609
- <h1>${heading}</h1>
610
- <p>${message}</p>
611
- ${details ? `<div class="details">${details}</div>` : ""}
612
- </main>
613
- </body>
614
- </html>`;
615
- }
616
- function oauthSuccessHtml(message) {
617
- return renderPage({
618
- title: "Authentication successful",
619
- heading: "Authentication successful",
620
- message
621
- });
622
- }
623
- function oauthErrorHtml(message, details) {
624
- return renderPage({
625
- title: "Authentication failed",
626
- heading: "Authentication failed",
627
- message,
628
- details
629
- });
630
- }
631
- //#endregion
632
- //#region src/compat/vendor/pi-oauth-flows/pkce.ts
633
- /**
634
- * PKCE utilities using Web Crypto API.
635
- * Works in both Node.js 20+ and browsers.
636
- */
637
- /**
638
- * Encode bytes as base64url string.
639
- */
640
- function base64urlEncode(bytes) {
641
- let binary = "";
642
- for (const byte of bytes) binary += String.fromCharCode(byte);
643
- return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
644
- }
645
- /**
646
- * Generate PKCE code verifier and challenge.
647
- * Uses Web Crypto API for cross-platform compatibility.
648
- */
649
- async function generatePKCE() {
650
- const verifierBytes = /* @__PURE__ */ new Uint8Array(32);
651
- crypto.getRandomValues(verifierBytes);
652
- const verifier = base64urlEncode(verifierBytes);
653
- const data = new TextEncoder().encode(verifier);
654
- const hashBuffer = await crypto.subtle.digest("SHA-256", data);
655
- return {
656
- verifier,
657
- challenge: base64urlEncode(new Uint8Array(hashBuffer))
658
- };
659
- }
660
- //#endregion
661
- //#region src/compat/vendor/pi-oauth-flows/openai-codex.ts
662
- /**
663
- * OpenAI Codex (ChatGPT OAuth) flow
664
- *
665
- * NOTE: This module uses Node.js crypto and http for the OAuth callback.
666
- * It is only intended for CLI use, not browser environments.
667
- */
668
- let _randomBytes = null;
669
- let _http = null;
670
- if (typeof process !== "undefined" && (process.versions?.node || process.versions?.bun)) {
671
- import("node:crypto").then((m) => {
672
- _randomBytes = m.randomBytes;
673
- });
674
- import("node:http").then((m) => {
675
- _http = m;
676
- });
677
- }
678
- const CLIENT_ID$3 = "app_EMoamEEZ73f0CkXaXp7hrann";
679
- const AUTH_BASE_URL = "https://auth.openai.com";
680
- const AUTHORIZE_URL$1 = `${AUTH_BASE_URL}/oauth/authorize`;
681
- const TOKEN_URL$1 = `${AUTH_BASE_URL}/oauth/token`;
682
- const REDIRECT_URI$1 = "http://localhost:1455/auth/callback";
683
- const DEVICE_USER_CODE_URL = `${AUTH_BASE_URL}/api/accounts/deviceauth/usercode`;
684
- const DEVICE_TOKEN_URL = `${AUTH_BASE_URL}/api/accounts/deviceauth/token`;
685
- const DEVICE_VERIFICATION_URI = `${AUTH_BASE_URL}/codex/device`;
686
- const DEVICE_REDIRECT_URI = `${AUTH_BASE_URL}/deviceauth/callback`;
687
- const DEVICE_CODE_TIMEOUT_SECONDS$1 = 900;
688
- const OPENAI_CODEX_BROWSER_LOGIN_METHOD = "browser";
689
- const OPENAI_CODEX_DEVICE_CODE_LOGIN_METHOD = "device_code";
690
- const SCOPE = "openid profile email offline_access";
691
- const JWT_CLAIM_PATH = "https://api.openai.com/auth";
692
- function getCallbackHost() {
693
- return getProviderEnvValue("PI_OAUTH_CALLBACK_HOST") || "127.0.0.1";
694
- }
695
- function createState() {
696
- if (!_randomBytes) throw new Error("OpenAI Codex OAuth is only available in Node.js environments");
697
- return _randomBytes(16).toString("hex");
698
- }
699
- function parseAuthorizationInput$1(input) {
700
- const value = input.trim();
701
- if (!value) return {};
702
- try {
703
- const url = new URL(value);
704
- return {
705
- code: url.searchParams.get("code") ?? void 0,
706
- state: url.searchParams.get("state") ?? void 0
707
- };
708
- } catch {}
709
- if (value.includes("#")) {
710
- const [code, state] = value.split("#", 2);
711
- return {
712
- code,
713
- state
714
- };
715
- }
716
- if (value.includes("code=")) {
717
- const params = new URLSearchParams(value);
718
- return {
719
- code: params.get("code") ?? void 0,
720
- state: params.get("state") ?? void 0
721
- };
722
- }
723
- return { code: value };
724
- }
725
- function decodeJwt(token) {
726
- try {
727
- const parts = token.split(".");
728
- if (parts.length !== 3) return null;
729
- const payload = parts[1] ?? "";
730
- const decoded = atob(payload);
731
- return JSON.parse(decoded);
732
- } catch {
733
- return null;
734
- }
735
- }
736
- async function fetchWithLoginCancellation(input, init) {
737
- try {
738
- return await fetch(input, init);
739
- } catch (error) {
740
- if (init.signal?.aborted) throw new Error("Login cancelled");
741
- throw error;
742
- }
743
- }
744
- async function readTokenResponse(response, operation) {
745
- if (!response.ok) {
746
- const text = await response.text().catch(() => "");
747
- throw new Error(`OpenAI Codex token ${operation} failed (${response.status}): ${text || response.statusText}`);
748
- }
749
- const json = await response.json();
750
- if (!json?.access_token || !json.refresh_token || typeof json.expires_in !== "number") throw new Error(`OpenAI Codex token ${operation} response missing fields: ${JSON.stringify(json)}`);
751
- return {
752
- access: json.access_token,
753
- refresh: json.refresh_token,
754
- expires: Date.now() + json.expires_in * 1e3
755
- };
756
- }
757
- async function exchangeAuthorizationCode$1(code, verifier, redirectUri, signal) {
758
- return readTokenResponse(await fetchWithLoginCancellation(TOKEN_URL$1, {
759
- method: "POST",
760
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
761
- body: new URLSearchParams({
762
- grant_type: "authorization_code",
763
- client_id: CLIENT_ID$3,
764
- code,
765
- code_verifier: verifier,
766
- redirect_uri: redirectUri
767
- }),
768
- signal
769
- }), "exchange");
770
- }
771
- async function refreshAccessToken(refreshToken, signal) {
772
- let response;
773
- try {
774
- response = await fetch(TOKEN_URL$1, {
775
- method: "POST",
776
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
777
- body: new URLSearchParams({
778
- grant_type: "refresh_token",
779
- refresh_token: refreshToken,
780
- client_id: CLIENT_ID$3
781
- }),
782
- signal
783
- });
784
- } catch (error) {
785
- throw new Error(`OpenAI Codex token refresh error: ${error instanceof Error ? error.message : String(error)}`);
786
- }
787
- return readTokenResponse(response, "refresh");
788
- }
789
- async function startOpenAICodexDeviceAuth(signal) {
790
- const response = await fetchWithLoginCancellation(DEVICE_USER_CODE_URL, {
791
- method: "POST",
792
- headers: { "Content-Type": "application/json" },
793
- body: JSON.stringify({ client_id: CLIENT_ID$3 }),
794
- signal
795
- });
796
- if (!response.ok) {
797
- if (response.status === 404) throw new Error("OpenAI Codex device code login is not enabled for this server. Use browser login or verify the server URL.");
798
- const responseBody = await response.text().catch(() => "");
799
- throw new Error(`OpenAI Codex device code request failed with status ${response.status}${responseBody ? `: ${responseBody}` : ""}`);
800
- }
801
- const json = await response.json();
802
- const intervalSeconds = typeof json?.interval === "string" ? Number(json.interval.trim()) : json?.interval;
803
- if (!json?.device_auth_id || !json.user_code || typeof intervalSeconds !== "number" || !Number.isFinite(intervalSeconds) || intervalSeconds < 0) throw new Error(`Invalid OpenAI Codex device code response: ${JSON.stringify(json)}`);
804
- return {
805
- deviceAuthId: json.device_auth_id,
806
- userCode: json.user_code,
807
- intervalSeconds
808
- };
809
- }
810
- async function pollOpenAICodexDeviceAuth(device, signal) {
811
- return pollOAuthDeviceCodeFlow({
812
- intervalSeconds: device.intervalSeconds,
813
- expiresInSeconds: DEVICE_CODE_TIMEOUT_SECONDS$1,
814
- signal,
815
- poll: async () => {
816
- const response = await fetchWithLoginCancellation(DEVICE_TOKEN_URL, {
817
- method: "POST",
818
- headers: { "Content-Type": "application/json" },
819
- body: JSON.stringify({
820
- device_auth_id: device.deviceAuthId,
821
- user_code: device.userCode
822
- }),
823
- signal
824
- });
825
- if (response.ok) {
826
- const json = await response.json();
827
- if (!json?.authorization_code || !json.code_verifier) return {
828
- status: "failed",
829
- message: `Invalid OpenAI Codex device auth token response: ${JSON.stringify(json)}`
830
- };
831
- return {
832
- status: "complete",
833
- value: {
834
- authorizationCode: json.authorization_code,
835
- codeVerifier: json.code_verifier
836
- }
837
- };
838
- }
839
- if (response.status === 403 || response.status === 404) return { status: "pending" };
840
- const responseBody = await response.text().catch(() => "");
841
- let errorCode;
842
- try {
843
- const error = JSON.parse(responseBody)?.error;
844
- errorCode = typeof error === "object" ? error?.code : error;
845
- } catch {}
846
- if (errorCode === "deviceauth_authorization_pending") return { status: "pending" };
847
- if (errorCode === "slow_down") return { status: "slow_down" };
848
- return {
849
- status: "failed",
850
- message: `OpenAI Codex device auth failed with status ${response.status}${responseBody ? `: ${responseBody}` : ""}`
851
- };
852
- }
853
- });
854
- }
855
- async function createAuthorizationFlow(originator = "pi") {
856
- const { verifier, challenge } = await generatePKCE();
857
- const state = createState();
858
- const url = new URL(AUTHORIZE_URL$1);
859
- url.searchParams.set("response_type", "code");
860
- url.searchParams.set("client_id", CLIENT_ID$3);
861
- url.searchParams.set("redirect_uri", REDIRECT_URI$1);
862
- url.searchParams.set("scope", SCOPE);
863
- url.searchParams.set("code_challenge", challenge);
864
- url.searchParams.set("code_challenge_method", "S256");
865
- url.searchParams.set("state", state);
866
- url.searchParams.set("id_token_add_organizations", "true");
867
- url.searchParams.set("codex_cli_simplified_flow", "true");
868
- url.searchParams.set("originator", originator);
869
- return {
870
- verifier,
871
- state,
872
- url: url.toString()
873
- };
874
- }
875
- function startLocalOAuthServer(state) {
876
- if (!_http) throw new Error("OpenAI Codex OAuth is only available in Node.js environments");
877
- let settleWait;
878
- const waitForCodePromise = new Promise((resolve) => {
879
- let settled = false;
880
- settleWait = (value) => {
881
- if (settled) return;
882
- settled = true;
883
- resolve(value);
884
- };
885
- });
886
- const server = _http.createServer((req, res) => {
887
- try {
888
- const url = new URL(req.url || "", "http://localhost");
889
- if (url.pathname !== "/auth/callback") {
890
- res.statusCode = 404;
891
- res.setHeader("Content-Type", "text/html; charset=utf-8");
892
- res.end(oauthErrorHtml("Callback route not found."));
893
- return;
894
- }
895
- if (url.searchParams.get("state") !== state) {
896
- res.statusCode = 400;
897
- res.setHeader("Content-Type", "text/html; charset=utf-8");
898
- res.end(oauthErrorHtml("State mismatch."));
899
- return;
900
- }
901
- const code = url.searchParams.get("code");
902
- if (!code) {
903
- res.statusCode = 400;
904
- res.setHeader("Content-Type", "text/html; charset=utf-8");
905
- res.end(oauthErrorHtml("Missing authorization code."));
906
- return;
907
- }
908
- res.statusCode = 200;
909
- res.setHeader("Content-Type", "text/html; charset=utf-8");
910
- res.end(oauthSuccessHtml("OpenAI authentication completed. You can close this window."));
911
- settleWait?.({ code });
912
- } catch {
913
- res.statusCode = 500;
914
- res.setHeader("Content-Type", "text/html; charset=utf-8");
915
- res.end(oauthErrorHtml("Internal error while processing OAuth callback."));
916
- }
917
- });
918
- return new Promise((resolve) => {
919
- server.listen(1455, getCallbackHost(), () => {
920
- resolve({
921
- close: () => server.close(),
922
- cancelWait: () => {
923
- settleWait?.(null);
924
- },
925
- waitForCode: () => waitForCodePromise
926
- });
927
- }).on("error", (_err) => {
928
- settleWait?.(null);
929
- resolve({
930
- close: () => {
931
- try {
932
- server.close();
933
- } catch {}
934
- },
935
- cancelWait: () => {},
936
- waitForCode: async () => null
937
- });
938
- });
939
- });
940
- }
941
- function getAccountId(accessToken) {
942
- const accountId = (decodeJwt(accessToken)?.[JWT_CLAIM_PATH])?.chatgpt_account_id;
943
- return typeof accountId === "string" && accountId.length > 0 ? accountId : null;
944
- }
945
- function credentialsFromToken(token) {
946
- const accountId = getAccountId(token.access);
947
- if (!accountId) throw new Error("Failed to extract accountId from token");
948
- return {
949
- type: "oauth",
950
- access: token.access,
951
- refresh: token.refresh,
952
- expires: token.expires,
953
- accountId
954
- };
955
- }
956
- async function exchangeAuthorizationCodeForCredentials(code, verifier, redirectUri, signal) {
957
- return credentialsFromToken(await exchangeAuthorizationCode$1(code, verifier, redirectUri, signal));
958
- }
959
- async function loginOpenAICodexDeviceCode(interaction) {
960
- const device = await startOpenAICodexDeviceAuth(interaction.signal);
961
- interaction.notify({
962
- type: "device_code",
963
- userCode: device.userCode,
964
- verificationUri: DEVICE_VERIFICATION_URI,
965
- intervalSeconds: device.intervalSeconds,
966
- expiresInSeconds: DEVICE_CODE_TIMEOUT_SECONDS$1
967
- });
968
- const code = await pollOpenAICodexDeviceAuth(device, interaction.signal);
969
- return exchangeAuthorizationCodeForCredentials(code.authorizationCode, code.codeVerifier, DEVICE_REDIRECT_URI, interaction.signal);
970
- }
971
- async function loginOpenAICodex(interaction) {
972
- const { verifier, state, url } = await createAuthorizationFlow();
973
- const server = await startLocalOAuthServer(state);
974
- const manualAbort = new AbortController();
975
- const onAbort = () => server.cancelWait();
976
- interaction.signal.addEventListener("abort", onAbort, { once: true });
977
- if (interaction.signal.aborted) onAbort();
978
- let code;
979
- let manualCode;
980
- let manualError;
981
- interaction.notify({
982
- type: "auth_url",
983
- url,
984
- instructions: "A browser window should open. Complete login to finish."
985
- });
986
- try {
987
- const manualPromise = interaction.prompt({
988
- type: "manual_code",
989
- message: "Complete login in your browser, or paste the authorization code / redirect URL here:",
990
- placeholder: REDIRECT_URI$1,
991
- signal: manualAbort.signal
992
- }).then((input) => {
993
- manualCode = input;
994
- server.cancelWait();
995
- }).catch((error) => {
996
- manualError = error instanceof Error ? error : new Error(String(error));
997
- server.cancelWait();
998
- });
999
- const result = await server.waitForCode();
1000
- if (manualError) throw manualError;
1001
- if (result?.code) code = result.code;
1002
- else if (manualCode) {
1003
- const parsed = parseAuthorizationInput$1(manualCode);
1004
- if (parsed.state && parsed.state !== state) throw new Error("State mismatch");
1005
- code = parsed.code;
1006
- }
1007
- if (!code) {
1008
- await manualPromise;
1009
- if (manualError) throw manualError;
1010
- if (manualCode) {
1011
- const parsed = parseAuthorizationInput$1(manualCode);
1012
- if (parsed.state && parsed.state !== state) throw new Error("State mismatch");
1013
- code = parsed.code;
1014
- }
1015
- }
1016
- if (!code) throw new Error("Missing authorization code");
1017
- return exchangeAuthorizationCodeForCredentials(code, verifier, REDIRECT_URI$1, interaction.signal);
1018
- } finally {
1019
- interaction.signal.removeEventListener("abort", onAbort);
1020
- manualAbort.abort();
1021
- server.close();
1022
- }
1023
- }
1024
- /**
1025
- * Refresh OpenAI Codex OAuth token
1026
- */
1027
- async function refreshOpenAICodexToken(refreshToken, signal) {
1028
- return credentialsFromToken(await refreshAccessToken(refreshToken, signal));
1029
- }
1030
- const openaiCodexOAuth = {
1031
- name: "OpenAI (ChatGPT Plus/Pro)",
1032
- isSubscription: true,
1033
- async login(interaction) {
1034
- const method = await interaction.prompt({
1035
- type: "select",
1036
- message: "Select OpenAI Codex login method:",
1037
- options: [{
1038
- id: OPENAI_CODEX_BROWSER_LOGIN_METHOD,
1039
- label: "Browser login (default)"
1040
- }, {
1041
- id: OPENAI_CODEX_DEVICE_CODE_LOGIN_METHOD,
1042
- label: "Device code login (headless)"
1043
- }]
1044
- });
1045
- if (method === OPENAI_CODEX_DEVICE_CODE_LOGIN_METHOD) return loginOpenAICodexDeviceCode(interaction);
1046
- if (method !== OPENAI_CODEX_BROWSER_LOGIN_METHOD) throw new Error(`Unknown OpenAI Codex login method: ${method}`);
1047
- return loginOpenAICodex(interaction);
1048
- },
1049
- refresh: (credential, signal) => refreshOpenAICodexToken(credential.refresh, signal),
1050
- async toAuth(credential) {
1051
- return { apiKey: credential.access };
1052
- }
1053
- };
1054
- //#endregion
1055
- //#region src/compat/vendor/pi-oauth-flows/anthropic.ts
1056
- /**
1057
- * Anthropic OAuth flow (Claude Pro/Max)
1058
- *
1059
- * NOTE: This module uses Node.js http.createServer for the OAuth callback server.
1060
- * It is only intended for CLI use, not browser environments.
1061
- */
1062
- let nodeApis = null;
1063
- let nodeApisPromise = null;
1064
- const decode$1 = (s) => atob(s);
1065
- const CLIENT_ID$2 = decode$1("OWQxYzI1MGEtZTYxYi00NGQ5LTg4ZWQtNTk0NGQxOTYyZjVl");
1066
- const AUTHORIZE_URL = "https://claude.ai/oauth/authorize";
1067
- const TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
1068
- const CALLBACK_HOST = getProviderEnvValue("PI_OAUTH_CALLBACK_HOST") || "127.0.0.1";
1069
- const CALLBACK_PORT = 53692;
1070
- const CALLBACK_PATH = "/callback";
1071
- const REDIRECT_URI = `http://localhost:${CALLBACK_PORT}${CALLBACK_PATH}`;
1072
- const SCOPES = "org:create_api_key user:profile user:inference user:sessions:claude_code user:mcp_servers user:file_upload";
1073
- async function getNodeApis() {
1074
- if (nodeApis) return nodeApis;
1075
- if (!nodeApisPromise) {
1076
- if (typeof process === "undefined" || !process.versions?.node && !process.versions?.bun) throw new Error("Anthropic OAuth is only available in Node.js environments");
1077
- nodeApisPromise = import("node:http").then((httpModule) => ({ createServer: httpModule.createServer }));
1078
- }
1079
- nodeApis = await nodeApisPromise;
1080
- return nodeApis;
1081
- }
1082
- function parseAuthorizationInput(input) {
1083
- const value = input.trim();
1084
- if (!value) return {};
1085
- try {
1086
- const url = new URL(value);
1087
- return {
1088
- code: url.searchParams.get("code") ?? void 0,
1089
- state: url.searchParams.get("state") ?? void 0
1090
- };
1091
- } catch {}
1092
- if (value.includes("#")) {
1093
- const [code, state] = value.split("#", 2);
1094
- return {
1095
- code,
1096
- state
1097
- };
1098
- }
1099
- if (value.includes("code=")) {
1100
- const params = new URLSearchParams(value);
1101
- return {
1102
- code: params.get("code") ?? void 0,
1103
- state: params.get("state") ?? void 0
1104
- };
1105
- }
1106
- return { code: value };
1107
- }
1108
- function formatErrorDetails(error) {
1109
- if (error instanceof Error) {
1110
- const details = [`${error.name}: ${error.message}`];
1111
- const errorWithCode = error;
1112
- if (errorWithCode.code) details.push(`code=${errorWithCode.code}`);
1113
- if (typeof errorWithCode.errno !== "undefined") details.push(`errno=${String(errorWithCode.errno)}`);
1114
- if (typeof error.cause !== "undefined") details.push(`cause=${formatErrorDetails(error.cause)}`);
1115
- if (error.stack) details.push(`stack=${error.stack}`);
1116
- return details.join("; ");
1117
- }
1118
- return String(error);
1119
- }
1120
- async function startCallbackServer(expectedState) {
1121
- const { createServer } = await getNodeApis();
1122
- return new Promise((resolve, reject) => {
1123
- let settleWait;
1124
- const waitForCodePromise = new Promise((resolveWait) => {
1125
- let settled = false;
1126
- settleWait = (value) => {
1127
- if (settled) return;
1128
- settled = true;
1129
- resolveWait(value);
1130
- };
1131
- });
1132
- const server = createServer((req, res) => {
1133
- try {
1134
- const url = new URL(req.url || "", "http://localhost");
1135
- if (url.pathname !== CALLBACK_PATH) {
1136
- res.writeHead(404, { "Content-Type": "text/html; charset=utf-8" });
1137
- res.end(oauthErrorHtml("Callback route not found."));
1138
- return;
1139
- }
1140
- const code = url.searchParams.get("code");
1141
- const state = url.searchParams.get("state");
1142
- const error = url.searchParams.get("error");
1143
- if (error) {
1144
- res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
1145
- res.end(oauthErrorHtml("Anthropic authentication did not complete.", `Error: ${error}`));
1146
- return;
1147
- }
1148
- if (!code || !state) {
1149
- res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
1150
- res.end(oauthErrorHtml("Missing code or state parameter."));
1151
- return;
1152
- }
1153
- if (state !== expectedState) {
1154
- res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" });
1155
- res.end(oauthErrorHtml("State mismatch."));
1156
- return;
1157
- }
1158
- res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
1159
- res.end(oauthSuccessHtml("Anthropic authentication completed. You can close this window."));
1160
- settleWait?.({
1161
- code,
1162
- state
1163
- });
1164
- } catch {
1165
- res.writeHead(500, { "Content-Type": "text/plain; charset=utf-8" });
1166
- res.end("Internal error");
1167
- }
1168
- });
1169
- server.on("error", (err) => {
1170
- reject(err);
1171
- });
1172
- server.listen(CALLBACK_PORT, CALLBACK_HOST, () => {
1173
- resolve({
1174
- server,
1175
- redirectUri: REDIRECT_URI,
1176
- cancelWait: () => {
1177
- settleWait?.(null);
1178
- },
1179
- waitForCode: () => waitForCodePromise
1180
- });
1181
- });
1182
- });
1183
- }
1184
- async function postJson(url, body, signal) {
1185
- const response = await fetch(url, {
1186
- method: "POST",
1187
- headers: {
1188
- "Content-Type": "application/json",
1189
- Accept: "application/json"
1190
- },
1191
- body: JSON.stringify(body),
1192
- signal: AbortSignal.any([signal, AbortSignal.timeout(3e4)])
1193
- });
1194
- const responseBody = await response.text();
1195
- if (!response.ok) throw new Error(`HTTP request failed. status=${response.status}; url=${url}; body=${responseBody}`);
1196
- return responseBody;
1197
- }
1198
- async function exchangeAuthorizationCode(code, state, verifier, redirectUri, signal) {
1199
- let responseBody;
1200
- try {
1201
- responseBody = await postJson(TOKEN_URL, {
1202
- grant_type: "authorization_code",
1203
- client_id: CLIENT_ID$2,
1204
- code,
1205
- state,
1206
- redirect_uri: redirectUri,
1207
- code_verifier: verifier
1208
- }, signal);
1209
- } catch (error) {
1210
- throw new Error(`Token exchange request failed. url=${TOKEN_URL}; redirect_uri=${redirectUri}; response_type=authorization_code; details=${formatErrorDetails(error)}`);
1211
- }
1212
- let tokenData;
1213
- try {
1214
- tokenData = JSON.parse(responseBody);
1215
- } catch (error) {
1216
- throw new Error(`Token exchange returned invalid JSON. url=${TOKEN_URL}; body=${responseBody}; details=${formatErrorDetails(error)}`);
1217
- }
1218
- return {
1219
- type: "oauth",
1220
- refresh: tokenData.refresh_token,
1221
- access: tokenData.access_token,
1222
- expires: Date.now() + tokenData.expires_in * 1e3 - 3e5
1223
- };
1224
- }
1225
- async function loginAnthropic(interaction) {
1226
- const { verifier, challenge } = await generatePKCE();
1227
- const server = await startCallbackServer(verifier);
1228
- const manualAbort = new AbortController();
1229
- const onAbort = () => server.cancelWait();
1230
- interaction.signal.addEventListener("abort", onAbort, { once: true });
1231
- if (interaction.signal.aborted) onAbort();
1232
- let code;
1233
- let state;
1234
- let manualInput;
1235
- let manualError;
1236
- try {
1237
- const authParams = new URLSearchParams({
1238
- code: "true",
1239
- client_id: CLIENT_ID$2,
1240
- response_type: "code",
1241
- redirect_uri: REDIRECT_URI,
1242
- scope: SCOPES,
1243
- code_challenge: challenge,
1244
- code_challenge_method: "S256",
1245
- state: verifier
1246
- });
1247
- interaction.notify({
1248
- type: "auth_url",
1249
- url: `${AUTHORIZE_URL}?${authParams.toString()}`,
1250
- instructions: "Complete login in your browser. If the browser is on another machine, paste the final redirect URL here."
1251
- });
1252
- const manualPromise = interaction.prompt({
1253
- type: "manual_code",
1254
- message: "Complete login in your browser, or paste the authorization code / redirect URL here:",
1255
- placeholder: REDIRECT_URI,
1256
- signal: manualAbort.signal
1257
- }).then((input) => {
1258
- manualInput = input;
1259
- server.cancelWait();
1260
- }).catch((error) => {
1261
- manualError = error instanceof Error ? error : new Error(String(error));
1262
- server.cancelWait();
1263
- });
1264
- const result = await server.waitForCode();
1265
- if (manualError) throw manualError;
1266
- if (result?.code) {
1267
- code = result.code;
1268
- state = result.state;
1269
- } else if (manualInput) {
1270
- const parsed = parseAuthorizationInput(manualInput);
1271
- if (parsed.state && parsed.state !== verifier) throw new Error("OAuth state mismatch");
1272
- code = parsed.code;
1273
- state = parsed.state ?? verifier;
1274
- }
1275
- if (!code) {
1276
- await manualPromise;
1277
- if (manualError) throw manualError;
1278
- if (manualInput) {
1279
- const parsed = parseAuthorizationInput(manualInput);
1280
- if (parsed.state && parsed.state !== verifier) throw new Error("OAuth state mismatch");
1281
- code = parsed.code;
1282
- state = parsed.state ?? verifier;
1283
- }
1284
- }
1285
- if (!code) throw new Error("Missing authorization code");
1286
- if (!state) throw new Error("Missing OAuth state");
1287
- interaction.notify({
1288
- type: "progress",
1289
- message: "Exchanging authorization code for tokens..."
1290
- });
1291
- return exchangeAuthorizationCode(code, state, verifier, REDIRECT_URI, interaction.signal);
1292
- } finally {
1293
- interaction.signal.removeEventListener("abort", onAbort);
1294
- manualAbort.abort();
1295
- server.server.close();
1296
- }
1297
- }
1298
- /**
1299
- * Refresh Anthropic OAuth token
1300
- */
1301
- async function refreshAnthropicToken(refreshToken, signal) {
1302
- let responseBody;
1303
- try {
1304
- responseBody = await postJson(TOKEN_URL, {
1305
- grant_type: "refresh_token",
1306
- client_id: CLIENT_ID$2,
1307
- refresh_token: refreshToken
1308
- }, signal);
1309
- } catch (error) {
1310
- throw new Error(`Anthropic token refresh request failed. url=${TOKEN_URL}; details=${formatErrorDetails(error)}`);
1311
- }
1312
- let data;
1313
- try {
1314
- data = JSON.parse(responseBody);
1315
- } catch (error) {
1316
- throw new Error(`Anthropic token refresh returned invalid JSON. url=${TOKEN_URL}; body=${responseBody}; details=${formatErrorDetails(error)}`);
1317
- }
1318
- return {
1319
- type: "oauth",
1320
- refresh: data.refresh_token,
1321
- access: data.access_token,
1322
- expires: Date.now() + data.expires_in * 1e3 - 3e5
1323
- };
1324
- }
1325
- const anthropicOAuth = {
1326
- name: "Anthropic (Claude Pro/Max)",
1327
- isSubscription: true,
1328
- login: loginAnthropic,
1329
- refresh: (credential, signal) => refreshAnthropicToken(credential.refresh, signal),
1330
- async toAuth(credential) {
1331
- return { apiKey: credential.access };
1332
- }
1333
- };
1334
- //#endregion
1335
- //#region src/compat/vendor/pi-oauth-flows/data/github-copilot.json
1336
- var github_copilot_default = {
1337
- "anthropic-messages": {
1338
- "claude-haiku-4.5": {
1339
- "id": "claude-haiku-4.5",
1340
- "name": "Claude Haiku 4.5 (latest)",
1341
- "api": "anthropic-messages",
1342
- "provider": "github-copilot",
1343
- "baseUrl": "https://api.individual.githubcopilot.com",
1344
- "reasoning": true,
1345
- "input": ["text", "image"],
1346
- "cost": {
1347
- "input": 1,
1348
- "output": 5,
1349
- "cacheRead": .1,
1350
- "cacheWrite": 1.25
1351
- },
1352
- "contextWindow": 2e5,
1353
- "maxTokens": 64e3,
1354
- "headers": {
1355
- "User-Agent": "GitHubCopilotChat/0.35.0",
1356
- "Editor-Version": "vscode/1.107.0",
1357
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1358
- "Copilot-Integration-Id": "vscode-chat"
1359
- },
1360
- "compat": { "supportsEagerToolInputStreaming": false }
1361
- },
1362
- "claude-opus-4.5": {
1363
- "id": "claude-opus-4.5",
1364
- "name": "Claude Opus 4.5 (latest)",
1365
- "api": "anthropic-messages",
1366
- "provider": "github-copilot",
1367
- "baseUrl": "https://api.individual.githubcopilot.com",
1368
- "reasoning": true,
1369
- "input": ["text", "image"],
1370
- "cost": {
1371
- "input": 5,
1372
- "output": 25,
1373
- "cacheRead": .5,
1374
- "cacheWrite": 6.25
1375
- },
1376
- "contextWindow": 2e5,
1377
- "maxTokens": 32e3,
1378
- "headers": {
1379
- "User-Agent": "GitHubCopilotChat/0.35.0",
1380
- "Editor-Version": "vscode/1.107.0",
1381
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1382
- "Copilot-Integration-Id": "vscode-chat"
1383
- }
1384
- },
1385
- "claude-opus-4.6": {
1386
- "id": "claude-opus-4.6",
1387
- "name": "Claude Opus 4.6",
1388
- "api": "anthropic-messages",
1389
- "provider": "github-copilot",
1390
- "baseUrl": "https://api.individual.githubcopilot.com",
1391
- "reasoning": true,
1392
- "input": ["text", "image"],
1393
- "cost": {
1394
- "input": 5,
1395
- "output": 25,
1396
- "cacheRead": .5,
1397
- "cacheWrite": 6.25
1398
- },
1399
- "contextWindow": 1e6,
1400
- "maxTokens": 32e3,
1401
- "headers": {
1402
- "User-Agent": "GitHubCopilotChat/0.35.0",
1403
- "Editor-Version": "vscode/1.107.0",
1404
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1405
- "Copilot-Integration-Id": "vscode-chat"
1406
- },
1407
- "thinkingLevelMap": { "max": "max" },
1408
- "compat": { "forceAdaptiveThinking": true }
1409
- },
1410
- "claude-opus-4.7": {
1411
- "id": "claude-opus-4.7",
1412
- "name": "Claude Opus 4.7",
1413
- "api": "anthropic-messages",
1414
- "provider": "github-copilot",
1415
- "baseUrl": "https://api.individual.githubcopilot.com",
1416
- "reasoning": true,
1417
- "input": ["text", "image"],
1418
- "cost": {
1419
- "input": 5,
1420
- "output": 25,
1421
- "cacheRead": .5,
1422
- "cacheWrite": 6.25
1423
- },
1424
- "contextWindow": 1e6,
1425
- "maxTokens": 32e3,
1426
- "headers": {
1427
- "User-Agent": "GitHubCopilotChat/0.35.0",
1428
- "Editor-Version": "vscode/1.107.0",
1429
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1430
- "Copilot-Integration-Id": "vscode-chat"
1431
- },
1432
- "thinkingLevelMap": {
1433
- "xhigh": "xhigh",
1434
- "max": "max",
1435
- "minimal": "low"
1436
- },
1437
- "compat": {
1438
- "forceAdaptiveThinking": true,
1439
- "supportsTemperature": false
1440
- }
1441
- },
1442
- "claude-opus-4.8": {
1443
- "id": "claude-opus-4.8",
1444
- "name": "Claude Opus 4.8",
1445
- "api": "anthropic-messages",
1446
- "provider": "github-copilot",
1447
- "baseUrl": "https://api.individual.githubcopilot.com",
1448
- "reasoning": true,
1449
- "input": ["text", "image"],
1450
- "cost": {
1451
- "input": 5,
1452
- "output": 25,
1453
- "cacheRead": .5,
1454
- "cacheWrite": 6.25
1455
- },
1456
- "contextWindow": 1e6,
1457
- "maxTokens": 64e3,
1458
- "headers": {
1459
- "User-Agent": "GitHubCopilotChat/0.35.0",
1460
- "Editor-Version": "vscode/1.107.0",
1461
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1462
- "Copilot-Integration-Id": "vscode-chat"
1463
- },
1464
- "thinkingLevelMap": {
1465
- "xhigh": "xhigh",
1466
- "max": "max",
1467
- "minimal": "low"
1468
- },
1469
- "compat": {
1470
- "forceAdaptiveThinking": true,
1471
- "supportsTemperature": false
1472
- }
1473
- },
1474
- "claude-opus-5": {
1475
- "id": "claude-opus-5",
1476
- "name": "Claude Opus 5",
1477
- "api": "anthropic-messages",
1478
- "provider": "github-copilot",
1479
- "baseUrl": "https://api.individual.githubcopilot.com",
1480
- "reasoning": true,
1481
- "input": ["text", "image"],
1482
- "cost": {
1483
- "input": 5,
1484
- "output": 25,
1485
- "cacheRead": .5,
1486
- "cacheWrite": 6.25
1487
- },
1488
- "contextWindow": 1e6,
1489
- "maxTokens": 64e3,
1490
- "headers": {
1491
- "User-Agent": "GitHubCopilotChat/0.35.0",
1492
- "Editor-Version": "vscode/1.107.0",
1493
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1494
- "Copilot-Integration-Id": "vscode-chat"
1495
- },
1496
- "thinkingLevelMap": {
1497
- "xhigh": "xhigh",
1498
- "max": "max",
1499
- "minimal": "low"
1500
- },
1501
- "compat": {
1502
- "forceAdaptiveThinking": true,
1503
- "supportsTemperature": false
1504
- }
1505
- },
1506
- "claude-sonnet-4": {
1507
- "id": "claude-sonnet-4",
1508
- "name": "Claude Sonnet 4 (latest)",
1509
- "api": "anthropic-messages",
1510
- "provider": "github-copilot",
1511
- "baseUrl": "https://api.individual.githubcopilot.com",
1512
- "reasoning": true,
1513
- "input": ["text", "image"],
1514
- "cost": {
1515
- "input": 3,
1516
- "output": 15,
1517
- "cacheRead": .3,
1518
- "cacheWrite": 3.75
1519
- },
1520
- "contextWindow": 216e3,
1521
- "maxTokens": 16e3,
1522
- "headers": {
1523
- "User-Agent": "GitHubCopilotChat/0.35.0",
1524
- "Editor-Version": "vscode/1.107.0",
1525
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1526
- "Copilot-Integration-Id": "vscode-chat"
1527
- },
1528
- "compat": { "supportsEagerToolInputStreaming": false }
1529
- },
1530
- "claude-sonnet-4.5": {
1531
- "id": "claude-sonnet-4.5",
1532
- "name": "Claude Sonnet 4.5 (latest)",
1533
- "api": "anthropic-messages",
1534
- "provider": "github-copilot",
1535
- "baseUrl": "https://api.individual.githubcopilot.com",
1536
- "reasoning": true,
1537
- "input": ["text", "image"],
1538
- "cost": {
1539
- "input": 3,
1540
- "output": 15,
1541
- "cacheRead": .3,
1542
- "cacheWrite": 3.75
1543
- },
1544
- "contextWindow": 2e5,
1545
- "maxTokens": 32e3,
1546
- "headers": {
1547
- "User-Agent": "GitHubCopilotChat/0.35.0",
1548
- "Editor-Version": "vscode/1.107.0",
1549
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1550
- "Copilot-Integration-Id": "vscode-chat"
1551
- },
1552
- "compat": { "supportsEagerToolInputStreaming": false }
1553
- },
1554
- "claude-sonnet-4.6": {
1555
- "id": "claude-sonnet-4.6",
1556
- "name": "Claude Sonnet 4.6",
1557
- "api": "anthropic-messages",
1558
- "provider": "github-copilot",
1559
- "baseUrl": "https://api.individual.githubcopilot.com",
1560
- "reasoning": true,
1561
- "input": ["text", "image"],
1562
- "cost": {
1563
- "input": 3,
1564
- "output": 15,
1565
- "cacheRead": .3,
1566
- "cacheWrite": 3.75
1567
- },
1568
- "contextWindow": 1e6,
1569
- "maxTokens": 32e3,
1570
- "headers": {
1571
- "User-Agent": "GitHubCopilotChat/0.35.0",
1572
- "Editor-Version": "vscode/1.107.0",
1573
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1574
- "Copilot-Integration-Id": "vscode-chat"
1575
- },
1576
- "thinkingLevelMap": {
1577
- "max": "max",
1578
- "minimal": "low"
1579
- },
1580
- "compat": { "forceAdaptiveThinking": true }
1581
- },
1582
- "claude-sonnet-5": {
1583
- "id": "claude-sonnet-5",
1584
- "name": "Claude Sonnet 5",
1585
- "api": "anthropic-messages",
1586
- "provider": "github-copilot",
1587
- "baseUrl": "https://api.individual.githubcopilot.com",
1588
- "reasoning": true,
1589
- "input": ["text", "image"],
1590
- "cost": {
1591
- "input": 2,
1592
- "output": 10,
1593
- "cacheRead": .2,
1594
- "cacheWrite": 2.5
1595
- },
1596
- "contextWindow": 1e6,
1597
- "maxTokens": 128e3,
1598
- "headers": {
1599
- "User-Agent": "GitHubCopilotChat/0.35.0",
1600
- "Editor-Version": "vscode/1.107.0",
1601
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1602
- "Copilot-Integration-Id": "vscode-chat"
1603
- },
1604
- "thinkingLevelMap": {
1605
- "xhigh": "xhigh",
1606
- "max": "max"
1607
- },
1608
- "compat": { "forceAdaptiveThinking": true }
1609
- }
1610
- },
1611
- "openai-completions": {
1612
- "claude-fable-5": {
1613
- "id": "claude-fable-5",
1614
- "name": "Claude Fable 5",
1615
- "api": "openai-completions",
1616
- "provider": "github-copilot",
1617
- "baseUrl": "https://api.individual.githubcopilot.com",
1618
- "reasoning": true,
1619
- "input": ["text", "image"],
1620
- "cost": {
1621
- "input": 10,
1622
- "output": 50,
1623
- "cacheRead": 1,
1624
- "cacheWrite": 12.5
1625
- },
1626
- "contextWindow": 1e6,
1627
- "maxTokens": 128e3,
1628
- "headers": {
1629
- "User-Agent": "GitHubCopilotChat/0.35.0",
1630
- "Editor-Version": "vscode/1.107.0",
1631
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1632
- "Copilot-Integration-Id": "vscode-chat"
1633
- },
1634
- "compat": {
1635
- "supportsStore": false,
1636
- "supportsDeveloperRole": false,
1637
- "supportsReasoningEffort": false
1638
- },
1639
- "thinkingLevelMap": {
1640
- "off": null,
1641
- "xhigh": "xhigh",
1642
- "max": "max"
1643
- }
1644
- },
1645
- "gemini-3.1-pro-preview": {
1646
- "id": "gemini-3.1-pro-preview",
1647
- "name": "Gemini 3.1 Pro Preview",
1648
- "api": "openai-completions",
1649
- "provider": "github-copilot",
1650
- "baseUrl": "https://api.individual.githubcopilot.com",
1651
- "reasoning": true,
1652
- "input": ["text", "image"],
1653
- "cost": {
1654
- "input": 2,
1655
- "output": 12,
1656
- "cacheRead": .2,
1657
- "cacheWrite": 0,
1658
- "tiers": [{
1659
- "inputTokensAbove": 2e5,
1660
- "input": 4,
1661
- "output": 18,
1662
- "cacheRead": .4,
1663
- "cacheWrite": 0
1664
- }]
1665
- },
1666
- "contextWindow": 1e6,
1667
- "maxTokens": 64e3,
1668
- "headers": {
1669
- "User-Agent": "GitHubCopilotChat/0.35.0",
1670
- "Editor-Version": "vscode/1.107.0",
1671
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1672
- "Copilot-Integration-Id": "vscode-chat"
1673
- },
1674
- "compat": {
1675
- "supportsStore": false,
1676
- "supportsDeveloperRole": false,
1677
- "supportsReasoningEffort": false
1678
- }
1679
- },
1680
- "gemini-3.5-flash": {
1681
- "id": "gemini-3.5-flash",
1682
- "name": "Gemini 3.5 Flash",
1683
- "api": "openai-completions",
1684
- "provider": "github-copilot",
1685
- "baseUrl": "https://api.individual.githubcopilot.com",
1686
- "reasoning": true,
1687
- "input": ["text", "image"],
1688
- "cost": {
1689
- "input": 1.5,
1690
- "output": 9,
1691
- "cacheRead": .15,
1692
- "cacheWrite": 0
1693
- },
1694
- "contextWindow": 2e5,
1695
- "maxTokens": 64e3,
1696
- "headers": {
1697
- "User-Agent": "GitHubCopilotChat/0.35.0",
1698
- "Editor-Version": "vscode/1.107.0",
1699
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1700
- "Copilot-Integration-Id": "vscode-chat"
1701
- },
1702
- "compat": {
1703
- "supportsStore": false,
1704
- "supportsDeveloperRole": false,
1705
- "supportsReasoningEffort": false
1706
- }
1707
- },
1708
- "gemini-3.6-flash": {
1709
- "id": "gemini-3.6-flash",
1710
- "name": "Gemini 3.6 Flash",
1711
- "api": "openai-completions",
1712
- "provider": "github-copilot",
1713
- "baseUrl": "https://api.individual.githubcopilot.com",
1714
- "reasoning": true,
1715
- "input": ["text", "image"],
1716
- "cost": {
1717
- "input": 1.5,
1718
- "output": 7.5,
1719
- "cacheRead": .15,
1720
- "cacheWrite": 0
1721
- },
1722
- "contextWindow": 1e6,
1723
- "maxTokens": 64e3,
1724
- "headers": {
1725
- "User-Agent": "GitHubCopilotChat/0.35.0",
1726
- "Editor-Version": "vscode/1.107.0",
1727
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1728
- "Copilot-Integration-Id": "vscode-chat"
1729
- },
1730
- "compat": {
1731
- "supportsStore": false,
1732
- "supportsDeveloperRole": false,
1733
- "supportsReasoningEffort": false
1734
- }
1735
- },
1736
- "gpt-4.1": {
1737
- "id": "gpt-4.1",
1738
- "name": "GPT-4.1",
1739
- "api": "openai-completions",
1740
- "provider": "github-copilot",
1741
- "baseUrl": "https://api.individual.githubcopilot.com",
1742
- "reasoning": false,
1743
- "input": ["text", "image"],
1744
- "cost": {
1745
- "input": 2,
1746
- "output": 8,
1747
- "cacheRead": .5,
1748
- "cacheWrite": 0
1749
- },
1750
- "contextWindow": 128e3,
1751
- "maxTokens": 16384,
1752
- "headers": {
1753
- "User-Agent": "GitHubCopilotChat/0.35.0",
1754
- "Editor-Version": "vscode/1.107.0",
1755
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1756
- "Copilot-Integration-Id": "vscode-chat"
1757
- },
1758
- "compat": {
1759
- "supportsStore": false,
1760
- "supportsDeveloperRole": false,
1761
- "supportsReasoningEffort": false
1762
- }
1763
- },
1764
- "kimi-k2.7-code": {
1765
- "id": "kimi-k2.7-code",
1766
- "name": "Kimi K2.7 Code",
1767
- "api": "openai-completions",
1768
- "provider": "github-copilot",
1769
- "baseUrl": "https://api.individual.githubcopilot.com",
1770
- "reasoning": true,
1771
- "input": ["text", "image"],
1772
- "cost": {
1773
- "input": .95,
1774
- "output": 4,
1775
- "cacheRead": .19,
1776
- "cacheWrite": 0
1777
- },
1778
- "contextWindow": 256e3,
1779
- "maxTokens": 32e3,
1780
- "headers": {
1781
- "User-Agent": "GitHubCopilotChat/0.35.0",
1782
- "Editor-Version": "vscode/1.107.0",
1783
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1784
- "Copilot-Integration-Id": "vscode-chat"
1785
- },
1786
- "compat": {
1787
- "supportsStore": false,
1788
- "supportsDeveloperRole": false,
1789
- "supportsReasoningEffort": false
1790
- }
1791
- },
1792
- "kimi-k3": {
1793
- "id": "kimi-k3",
1794
- "name": "Kimi K3",
1795
- "api": "openai-completions",
1796
- "provider": "github-copilot",
1797
- "baseUrl": "https://api.individual.githubcopilot.com",
1798
- "reasoning": true,
1799
- "input": ["text", "image"],
1800
- "cost": {
1801
- "input": .95,
1802
- "output": 4,
1803
- "cacheRead": .19,
1804
- "cacheWrite": 0
1805
- },
1806
- "contextWindow": 1048576,
1807
- "maxTokens": 131072,
1808
- "headers": {
1809
- "User-Agent": "GitHubCopilotChat/0.35.0",
1810
- "Editor-Version": "vscode/1.107.0",
1811
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1812
- "Copilot-Integration-Id": "vscode-chat"
1813
- },
1814
- "compat": {
1815
- "supportsStore": false,
1816
- "supportsDeveloperRole": false,
1817
- "supportsReasoningEffort": false
1818
- }
1819
- }
1820
- },
1821
- "openai-responses": {
1822
- "gpt-5-mini": {
1823
- "id": "gpt-5-mini",
1824
- "name": "GPT-5 Mini",
1825
- "api": "openai-responses",
1826
- "provider": "github-copilot",
1827
- "baseUrl": "https://api.individual.githubcopilot.com",
1828
- "reasoning": true,
1829
- "input": ["text", "image"],
1830
- "cost": {
1831
- "input": .25,
1832
- "output": 2,
1833
- "cacheRead": .025,
1834
- "cacheWrite": 0
1835
- },
1836
- "contextWindow": 264e3,
1837
- "maxTokens": 64e3,
1838
- "headers": {
1839
- "User-Agent": "GitHubCopilotChat/0.35.0",
1840
- "Editor-Version": "vscode/1.107.0",
1841
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1842
- "Copilot-Integration-Id": "vscode-chat"
1843
- },
1844
- "thinkingLevelMap": {
1845
- "off": null,
1846
- "minimal": "low",
1847
- "low": "low",
1848
- "medium": "medium",
1849
- "high": "high",
1850
- "xhigh": null,
1851
- "max": null
1852
- },
1853
- "compat": { "supportsOpenAIGrammarTools": true }
1854
- },
1855
- "gpt-5.2": {
1856
- "id": "gpt-5.2",
1857
- "name": "GPT-5.2",
1858
- "api": "openai-responses",
1859
- "provider": "github-copilot",
1860
- "baseUrl": "https://api.individual.githubcopilot.com",
1861
- "reasoning": true,
1862
- "input": ["text", "image"],
1863
- "cost": {
1864
- "input": 1.75,
1865
- "output": 14,
1866
- "cacheRead": .175,
1867
- "cacheWrite": 0
1868
- },
1869
- "contextWindow": 4e5,
1870
- "maxTokens": 128e3,
1871
- "headers": {
1872
- "User-Agent": "GitHubCopilotChat/0.35.0",
1873
- "Editor-Version": "vscode/1.107.0",
1874
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1875
- "Copilot-Integration-Id": "vscode-chat"
1876
- },
1877
- "thinkingLevelMap": {
1878
- "off": null,
1879
- "minimal": "low",
1880
- "xhigh": "xhigh"
1881
- },
1882
- "compat": { "supportsOpenAIGrammarTools": true }
1883
- },
1884
- "gpt-5.2-codex": {
1885
- "id": "gpt-5.2-codex",
1886
- "name": "GPT-5.2 Codex",
1887
- "api": "openai-responses",
1888
- "provider": "github-copilot",
1889
- "baseUrl": "https://api.individual.githubcopilot.com",
1890
- "reasoning": true,
1891
- "input": ["text", "image"],
1892
- "cost": {
1893
- "input": 1.75,
1894
- "output": 14,
1895
- "cacheRead": .175,
1896
- "cacheWrite": 0
1897
- },
1898
- "contextWindow": 4e5,
1899
- "maxTokens": 128e3,
1900
- "headers": {
1901
- "User-Agent": "GitHubCopilotChat/0.35.0",
1902
- "Editor-Version": "vscode/1.107.0",
1903
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1904
- "Copilot-Integration-Id": "vscode-chat"
1905
- },
1906
- "thinkingLevelMap": {
1907
- "off": null,
1908
- "minimal": "low",
1909
- "xhigh": "xhigh"
1910
- },
1911
- "compat": { "supportsOpenAIGrammarTools": true }
1912
- },
1913
- "gpt-5.3-codex": {
1914
- "id": "gpt-5.3-codex",
1915
- "name": "GPT-5.3 Codex",
1916
- "api": "openai-responses",
1917
- "provider": "github-copilot",
1918
- "baseUrl": "https://api.individual.githubcopilot.com",
1919
- "reasoning": true,
1920
- "input": ["text", "image"],
1921
- "cost": {
1922
- "input": 1.75,
1923
- "output": 14,
1924
- "cacheRead": .175,
1925
- "cacheWrite": 0
1926
- },
1927
- "contextWindow": 1e6,
1928
- "maxTokens": 128e3,
1929
- "headers": {
1930
- "User-Agent": "GitHubCopilotChat/0.35.0",
1931
- "Editor-Version": "vscode/1.107.0",
1932
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1933
- "Copilot-Integration-Id": "vscode-chat"
1934
- },
1935
- "thinkingLevelMap": {
1936
- "off": null,
1937
- "minimal": "low",
1938
- "low": "low",
1939
- "medium": "medium",
1940
- "high": "high",
1941
- "xhigh": "xhigh",
1942
- "max": null
1943
- },
1944
- "compat": { "supportsOpenAIGrammarTools": true }
1945
- },
1946
- "gpt-5.4": {
1947
- "id": "gpt-5.4",
1948
- "name": "GPT-5.4",
1949
- "api": "openai-responses",
1950
- "provider": "github-copilot",
1951
- "baseUrl": "https://api.individual.githubcopilot.com",
1952
- "reasoning": true,
1953
- "input": ["text", "image"],
1954
- "cost": {
1955
- "input": 2.5,
1956
- "output": 15,
1957
- "cacheRead": .25,
1958
- "cacheWrite": 0,
1959
- "tiers": [{
1960
- "inputTokensAbove": 272e3,
1961
- "input": 5,
1962
- "output": 22.5,
1963
- "cacheRead": .5,
1964
- "cacheWrite": 0
1965
- }]
1966
- },
1967
- "contextWindow": 1e6,
1968
- "maxTokens": 128e3,
1969
- "headers": {
1970
- "User-Agent": "GitHubCopilotChat/0.35.0",
1971
- "Editor-Version": "vscode/1.107.0",
1972
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
1973
- "Copilot-Integration-Id": "vscode-chat"
1974
- },
1975
- "thinkingLevelMap": {
1976
- "off": null,
1977
- "minimal": "low",
1978
- "low": "low",
1979
- "medium": "medium",
1980
- "high": "high",
1981
- "xhigh": "xhigh",
1982
- "max": null
1983
- },
1984
- "compat": { "supportsOpenAIGrammarTools": true }
1985
- },
1986
- "gpt-5.4-mini": {
1987
- "id": "gpt-5.4-mini",
1988
- "name": "GPT-5.4 mini",
1989
- "api": "openai-responses",
1990
- "provider": "github-copilot",
1991
- "baseUrl": "https://api.individual.githubcopilot.com",
1992
- "reasoning": true,
1993
- "input": ["text", "image"],
1994
- "cost": {
1995
- "input": .75,
1996
- "output": 4.5,
1997
- "cacheRead": .075,
1998
- "cacheWrite": 0
1999
- },
2000
- "contextWindow": 4e5,
2001
- "maxTokens": 128e3,
2002
- "headers": {
2003
- "User-Agent": "GitHubCopilotChat/0.35.0",
2004
- "Editor-Version": "vscode/1.107.0",
2005
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
2006
- "Copilot-Integration-Id": "vscode-chat"
2007
- },
2008
- "thinkingLevelMap": {
2009
- "off": null,
2010
- "minimal": "low",
2011
- "low": "low",
2012
- "medium": "medium",
2013
- "high": "high",
2014
- "xhigh": "xhigh",
2015
- "max": null
2016
- },
2017
- "compat": { "supportsOpenAIGrammarTools": true }
2018
- },
2019
- "gpt-5.4-nano": {
2020
- "id": "gpt-5.4-nano",
2021
- "name": "GPT-5.4 nano",
2022
- "api": "openai-responses",
2023
- "provider": "github-copilot",
2024
- "baseUrl": "https://api.individual.githubcopilot.com",
2025
- "reasoning": true,
2026
- "input": ["text", "image"],
2027
- "cost": {
2028
- "input": .2,
2029
- "output": 1.25,
2030
- "cacheRead": .02,
2031
- "cacheWrite": 0
2032
- },
2033
- "contextWindow": 4e5,
2034
- "maxTokens": 128e3,
2035
- "headers": {
2036
- "User-Agent": "GitHubCopilotChat/0.35.0",
2037
- "Editor-Version": "vscode/1.107.0",
2038
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
2039
- "Copilot-Integration-Id": "vscode-chat"
2040
- },
2041
- "thinkingLevelMap": {
2042
- "off": null,
2043
- "minimal": "low",
2044
- "xhigh": "xhigh"
2045
- },
2046
- "compat": { "supportsOpenAIGrammarTools": true }
2047
- },
2048
- "gpt-5.5": {
2049
- "id": "gpt-5.5",
2050
- "name": "GPT-5.5",
2051
- "api": "openai-responses",
2052
- "provider": "github-copilot",
2053
- "baseUrl": "https://api.individual.githubcopilot.com",
2054
- "reasoning": true,
2055
- "input": ["text", "image"],
2056
- "cost": {
2057
- "input": 5,
2058
- "output": 30,
2059
- "cacheRead": .5,
2060
- "cacheWrite": 0,
2061
- "tiers": [{
2062
- "inputTokensAbove": 272e3,
2063
- "input": 10,
2064
- "output": 45,
2065
- "cacheRead": 1,
2066
- "cacheWrite": 0
2067
- }]
2068
- },
2069
- "contextWindow": 1e6,
2070
- "maxTokens": 128e3,
2071
- "headers": {
2072
- "User-Agent": "GitHubCopilotChat/0.35.0",
2073
- "Editor-Version": "vscode/1.107.0",
2074
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
2075
- "Copilot-Integration-Id": "vscode-chat"
2076
- },
2077
- "thinkingLevelMap": {
2078
- "off": null,
2079
- "minimal": "low",
2080
- "low": "low",
2081
- "medium": "medium",
2082
- "high": "high",
2083
- "xhigh": "xhigh",
2084
- "max": null
2085
- },
2086
- "compat": { "supportsOpenAIGrammarTools": true }
2087
- },
2088
- "gpt-5.6-luna": {
2089
- "id": "gpt-5.6-luna",
2090
- "name": "GPT-5.6 Luna",
2091
- "api": "openai-responses",
2092
- "provider": "github-copilot",
2093
- "baseUrl": "https://api.individual.githubcopilot.com",
2094
- "reasoning": true,
2095
- "input": ["text", "image"],
2096
- "cost": {
2097
- "input": .2,
2098
- "output": 1.2,
2099
- "cacheRead": .02,
2100
- "cacheWrite": 0,
2101
- "tiers": [{
2102
- "inputTokensAbove": 2e5,
2103
- "input": .4,
2104
- "output": 1.8,
2105
- "cacheRead": .04,
2106
- "cacheWrite": 0
2107
- }]
2108
- },
2109
- "contextWindow": 105e4,
2110
- "maxTokens": 128e3,
2111
- "headers": {
2112
- "User-Agent": "GitHubCopilotChat/0.35.0",
2113
- "Editor-Version": "vscode/1.107.0",
2114
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
2115
- "Copilot-Integration-Id": "vscode-chat"
2116
- },
2117
- "thinkingLevelMap": {
2118
- "off": null,
2119
- "minimal": "low",
2120
- "low": "low",
2121
- "medium": "medium",
2122
- "high": "high",
2123
- "xhigh": "xhigh",
2124
- "max": "max"
2125
- },
2126
- "compat": { "supportsOpenAIGrammarTools": true }
2127
- },
2128
- "gpt-5.6-sol": {
2129
- "id": "gpt-5.6-sol",
2130
- "name": "GPT-5.6 Sol",
2131
- "api": "openai-responses",
2132
- "provider": "github-copilot",
2133
- "baseUrl": "https://api.individual.githubcopilot.com",
2134
- "reasoning": true,
2135
- "input": ["text", "image"],
2136
- "cost": {
2137
- "input": 5,
2138
- "output": 30,
2139
- "cacheRead": .5,
2140
- "cacheWrite": 6.25,
2141
- "tiers": [{
2142
- "inputTokensAbove": 272e3,
2143
- "input": 10,
2144
- "output": 45,
2145
- "cacheRead": 1,
2146
- "cacheWrite": 12.5
2147
- }]
2148
- },
2149
- "contextWindow": 105e4,
2150
- "maxTokens": 128e3,
2151
- "headers": {
2152
- "User-Agent": "GitHubCopilotChat/0.35.0",
2153
- "Editor-Version": "vscode/1.107.0",
2154
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
2155
- "Copilot-Integration-Id": "vscode-chat"
2156
- },
2157
- "thinkingLevelMap": {
2158
- "off": null,
2159
- "minimal": "low",
2160
- "low": "low",
2161
- "medium": "medium",
2162
- "high": "high",
2163
- "xhigh": "xhigh",
2164
- "max": "max"
2165
- },
2166
- "compat": { "supportsOpenAIGrammarTools": true }
2167
- },
2168
- "gpt-5.6-terra": {
2169
- "id": "gpt-5.6-terra",
2170
- "name": "GPT-5.6 Terra",
2171
- "api": "openai-responses",
2172
- "provider": "github-copilot",
2173
- "baseUrl": "https://api.individual.githubcopilot.com",
2174
- "reasoning": true,
2175
- "input": ["text", "image"],
2176
- "cost": {
2177
- "input": 2,
2178
- "output": 12,
2179
- "cacheRead": .2,
2180
- "cacheWrite": 0,
2181
- "tiers": [{
2182
- "inputTokensAbove": 272e3,
2183
- "input": 4,
2184
- "output": 18,
2185
- "cacheRead": .4,
2186
- "cacheWrite": 0
2187
- }]
2188
- },
2189
- "contextWindow": 105e4,
2190
- "maxTokens": 128e3,
2191
- "headers": {
2192
- "User-Agent": "GitHubCopilotChat/0.35.0",
2193
- "Editor-Version": "vscode/1.107.0",
2194
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
2195
- "Copilot-Integration-Id": "vscode-chat"
2196
- },
2197
- "thinkingLevelMap": {
2198
- "off": null,
2199
- "minimal": "low",
2200
- "low": "low",
2201
- "medium": "medium",
2202
- "high": "high",
2203
- "xhigh": "xhigh",
2204
- "max": "max"
2205
- },
2206
- "compat": { "supportsOpenAIGrammarTools": true }
2207
- },
2208
- "grok-4.5": {
2209
- "id": "grok-4.5",
2210
- "name": "Grok 4.5",
2211
- "api": "openai-responses",
2212
- "provider": "github-copilot",
2213
- "baseUrl": "https://api.individual.githubcopilot.com",
2214
- "reasoning": true,
2215
- "input": ["text", "image"],
2216
- "cost": {
2217
- "input": 2,
2218
- "output": 6,
2219
- "cacheRead": .5,
2220
- "cacheWrite": 0,
2221
- "tiers": [{
2222
- "inputTokensAbove": 2e5,
2223
- "input": 4,
2224
- "output": 12,
2225
- "cacheRead": 1,
2226
- "cacheWrite": 0
2227
- }]
2228
- },
2229
- "contextWindow": 5e5,
2230
- "maxTokens": 128e3,
2231
- "headers": {
2232
- "User-Agent": "GitHubCopilotChat/0.35.0",
2233
- "Editor-Version": "vscode/1.107.0",
2234
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
2235
- "Copilot-Integration-Id": "vscode-chat"
2236
- },
2237
- "thinkingLevelMap": {
2238
- "off": null,
2239
- "minimal": null,
2240
- "low": "low",
2241
- "medium": "medium",
2242
- "high": "high",
2243
- "xhigh": null,
2244
- "max": null
2245
- }
2246
- },
2247
- "mai-code-1-flash-picker": {
2248
- "id": "mai-code-1-flash-picker",
2249
- "name": "MAI-Code-1-Flash",
2250
- "api": "openai-responses",
2251
- "provider": "github-copilot",
2252
- "baseUrl": "https://api.individual.githubcopilot.com",
2253
- "reasoning": true,
2254
- "input": ["text"],
2255
- "cost": {
2256
- "input": .75,
2257
- "output": 4.5,
2258
- "cacheRead": .075,
2259
- "cacheWrite": 0
2260
- },
2261
- "contextWindow": 256e3,
2262
- "maxTokens": 128e3,
2263
- "headers": {
2264
- "User-Agent": "GitHubCopilotChat/0.35.0",
2265
- "Editor-Version": "vscode/1.107.0",
2266
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
2267
- "Copilot-Integration-Id": "vscode-chat"
2268
- },
2269
- "thinkingLevelMap": {
2270
- "off": null,
2271
- "minimal": null,
2272
- "low": "low",
2273
- "medium": "medium",
2274
- "high": "high",
2275
- "xhigh": null,
2276
- "max": null
2277
- }
2278
- }
2279
- }
2280
- };
2281
- //#endregion
2282
- //#region src/compat/vendor/pi-oauth-flows/model-catalog.ts
2283
- function flattenModelCatalog(_provider, groups) {
2284
- return Object.assign({}, ...Object.values(groups));
2285
- }
2286
- //#endregion
2287
- //#region src/compat/vendor/pi-oauth-flows/github-copilot.models.ts
2288
- const GITHUB_COPILOT_MODELS = flattenModelCatalog("github-copilot", github_copilot_default);
2289
- //#endregion
2290
- //#region src/compat/vendor/pi-oauth-flows/github-copilot.ts
2291
- /**
2292
- * GitHub Copilot OAuth flow
2293
- */
2294
- const decode = (s) => atob(s);
2295
- const CLIENT_ID$1 = decode("SXYxLmI1MDdhMDhjODdlY2ZlOTg=");
2296
- const COPILOT_HEADERS = {
2297
- "User-Agent": "GitHubCopilotChat/0.35.0",
2298
- "Editor-Version": "vscode/1.107.0",
2299
- "Editor-Plugin-Version": "copilot-chat/0.35.0",
2300
- "Copilot-Integration-Id": "vscode-chat"
2301
- };
2302
- const COPILOT_API_VERSION = "2026-06-01";
2303
- function normalizeDomain(input) {
2304
- const trimmed = input.trim();
2305
- if (!trimmed) return null;
2306
- try {
2307
- return (trimmed.includes("://") ? new URL(trimmed) : new URL(`https://${trimmed}`)).hostname;
2308
- } catch {
2309
- return null;
2310
- }
2311
- }
2312
- function getUrls(domain) {
2313
- return {
2314
- deviceCodeUrl: `https://${domain}/login/device/code`,
2315
- accessTokenUrl: `https://${domain}/login/oauth/access_token`,
2316
- copilotTokenUrl: `https://api.${domain}/copilot_internal/v2/token`
2317
- };
2318
- }
2319
- /**
2320
- * Parse the proxy-ep from a Copilot token and convert to API base URL.
2321
- * Token format: tid=...;exp=...;proxy-ep=proxy.individual.githubcopilot.com;...
2322
- * Returns API URL like https://api.individual.githubcopilot.com
2323
- */
2324
- function getBaseUrlFromToken(token) {
2325
- const match = token.match(/proxy-ep=([^;]+)/);
2326
- if (!match) return null;
2327
- return `https://${match[1].replace(/^proxy\./, "api.")}`;
2328
- }
2329
- function getGitHubCopilotBaseUrl(token, enterpriseDomain) {
2330
- if (token) {
2331
- const urlFromToken = getBaseUrlFromToken(token);
2332
- if (urlFromToken) return urlFromToken;
2333
- }
2334
- if (enterpriseDomain) return `https://copilot-api.${enterpriseDomain}`;
2335
- return "https://api.individual.githubcopilot.com";
2336
- }
2337
- function asRecord(value) {
2338
- return value && typeof value === "object" ? value : void 0;
2339
- }
2340
- function parseAvailableCopilotModelIds(raw, allowPolicyFallback) {
2341
- const data = asRecord(raw)?.data;
2342
- if (!Array.isArray(data)) throw new Error("Invalid Copilot models response");
2343
- const pickerIds = [];
2344
- const policyEnabledIds = [];
2345
- for (const rawItem of data) {
2346
- const item = asRecord(rawItem);
2347
- const id = item?.id;
2348
- if (!item || typeof id !== "string") continue;
2349
- if (asRecord(asRecord(item.capabilities)?.supports)?.tool_calls === false) continue;
2350
- const policy = asRecord(item.policy);
2351
- if (item.model_picker_enabled === true && policy?.state !== "disabled") pickerIds.push(id);
2352
- if (policy?.state === "enabled") policyEnabledIds.push(id);
2353
- }
2354
- return pickerIds.length > 0 || !allowPolicyFallback ? pickerIds : policyEnabledIds;
2355
- }
2356
- async function fetchAvailableGitHubCopilotModelIds(copilotToken, enterpriseDomain, signal) {
2357
- const baseUrl = getGitHubCopilotBaseUrl(copilotToken, enterpriseDomain);
2358
- const allowPolicyFallback = baseUrl === "https://api.individual.githubcopilot.com";
2359
- return parseAvailableCopilotModelIds(await fetchJson(`${baseUrl}/models`, {
2360
- headers: {
2361
- Accept: "application/json",
2362
- Authorization: `Bearer ${copilotToken}`,
2363
- ...COPILOT_HEADERS,
2364
- "X-GitHub-Api-Version": COPILOT_API_VERSION
2365
- },
2366
- signal: AbortSignal.any([signal, AbortSignal.timeout(5e3)])
2367
- }), allowPolicyFallback);
2368
- }
2369
- async function fetchJson(url, init) {
2370
- const response = await fetch(url, init);
2371
- if (!response.ok) {
2372
- const text = await response.text();
2373
- throw new Error(`${response.status} ${response.statusText}: ${text}`);
2374
- }
2375
- return response.json();
2376
- }
2377
- async function startDeviceFlow(domain, signal) {
2378
- const data = await fetchJson(getUrls(domain).deviceCodeUrl, {
2379
- method: "POST",
2380
- headers: {
2381
- Accept: "application/json",
2382
- "Content-Type": "application/x-www-form-urlencoded",
2383
- "User-Agent": "GitHubCopilotChat/0.35.0"
2384
- },
2385
- body: new URLSearchParams({
2386
- client_id: CLIENT_ID$1,
2387
- scope: "read:user"
2388
- }),
2389
- signal
2390
- });
2391
- if (!data || typeof data !== "object") throw new Error("Invalid device code response");
2392
- const deviceCode = data.device_code;
2393
- const userCode = data.user_code;
2394
- const verificationUri = data.verification_uri;
2395
- const interval = data.interval;
2396
- const expiresIn = data.expires_in;
2397
- if (typeof deviceCode !== "string" || typeof userCode !== "string" || typeof verificationUri !== "string" || interval !== void 0 && typeof interval !== "number" || typeof expiresIn !== "number") throw new Error("Invalid device code response fields");
2398
- let parsedUri;
2399
- try {
2400
- parsedUri = new URL(verificationUri);
2401
- } catch {
2402
- throw new Error("Untrusted verification_uri in device code response");
2403
- }
2404
- if (parsedUri.protocol !== "https:" && parsedUri.protocol !== "http:") throw new Error("Untrusted verification_uri in device code response");
2405
- return {
2406
- device_code: deviceCode,
2407
- user_code: userCode,
2408
- verification_uri: parsedUri.href,
2409
- interval,
2410
- expires_in: expiresIn
2411
- };
2412
- }
2413
- async function pollForGitHubAccessToken(domain, device, signal) {
2414
- const urls = getUrls(domain);
2415
- return pollOAuthDeviceCodeFlow({
2416
- intervalSeconds: device.interval,
2417
- expiresInSeconds: device.expires_in,
2418
- waitBeforeFirstPoll: true,
2419
- signal,
2420
- poll: async () => {
2421
- const raw = await fetchJson(urls.accessTokenUrl, {
2422
- method: "POST",
2423
- headers: {
2424
- Accept: "application/json",
2425
- "Content-Type": "application/x-www-form-urlencoded",
2426
- "User-Agent": "GitHubCopilotChat/0.35.0"
2427
- },
2428
- body: new URLSearchParams({
2429
- client_id: CLIENT_ID$1,
2430
- device_code: device.device_code,
2431
- grant_type: "urn:ietf:params:oauth:grant-type:device_code"
2432
- }),
2433
- signal
2434
- });
2435
- if (raw && typeof raw === "object" && typeof raw.access_token === "string") return {
2436
- status: "complete",
2437
- value: raw.access_token
2438
- };
2439
- if (raw && typeof raw === "object" && typeof raw.error === "string") {
2440
- const { error, error_description: description, interval } = raw;
2441
- if (error === "authorization_pending") return { status: "pending" };
2442
- if (error === "slow_down") return {
2443
- status: "slow_down",
2444
- intervalSeconds: typeof interval === "number" ? interval : void 0
2445
- };
2446
- return {
2447
- status: "failed",
2448
- message: `Device flow failed: ${error}${description ? `: ${description}` : ""}`
2449
- };
2450
- }
2451
- return {
2452
- status: "failed",
2453
- message: "Invalid device token response"
2454
- };
2455
- }
2456
- });
2457
- }
2458
- async function refreshGitHubCopilotAccessToken(refreshToken, enterpriseDomain, signal) {
2459
- const raw = await fetchJson(getUrls(enterpriseDomain || "github.com").copilotTokenUrl, {
2460
- headers: {
2461
- Accept: "application/json",
2462
- Authorization: `Bearer ${refreshToken}`,
2463
- ...COPILOT_HEADERS
2464
- },
2465
- signal
2466
- });
2467
- if (!raw || typeof raw !== "object") throw new Error("Invalid Copilot token response");
2468
- const token = raw.token;
2469
- const expiresAt = raw.expires_at;
2470
- if (typeof token !== "string" || typeof expiresAt !== "number") throw new Error("Invalid Copilot token response fields");
2471
- return {
2472
- type: "oauth",
2473
- refresh: refreshToken,
2474
- access: token,
2475
- expires: expiresAt * 1e3 - 3e5,
2476
- enterpriseUrl: enterpriseDomain
2477
- };
2478
- }
2479
- /**
2480
- * Refresh GitHub Copilot token
2481
- */
2482
- async function refreshGitHubCopilotToken(refreshToken, enterpriseDomain, signal) {
2483
- const credentials = await refreshGitHubCopilotAccessToken(refreshToken, enterpriseDomain, signal);
2484
- return {
2485
- ...credentials,
2486
- availableModelIds: await fetchAvailableGitHubCopilotModelIds(credentials.access, enterpriseDomain, signal)
2487
- };
2488
- }
2489
- /**
2490
- * Enable a model for the user's GitHub Copilot account.
2491
- * This is required for some models (like Claude, Grok) before they can be used.
2492
- */
2493
- async function enableGitHubCopilotModel(token, modelId, enterpriseDomain, signal) {
2494
- const url = `${getGitHubCopilotBaseUrl(token, enterpriseDomain)}/models/${modelId}/policy`;
2495
- try {
2496
- return (await fetch(url, {
2497
- method: "POST",
2498
- headers: {
2499
- "Content-Type": "application/json",
2500
- Authorization: `Bearer ${token}`,
2501
- ...COPILOT_HEADERS,
2502
- "openai-intent": "chat-policy",
2503
- "x-interaction-type": "chat-policy"
2504
- },
2505
- body: JSON.stringify({ state: "enabled" }),
2506
- signal
2507
- })).ok;
2508
- } catch (error) {
2509
- if (signal.aborted) throw error;
2510
- return false;
2511
- }
2512
- }
2513
- /**
2514
- * Enable all known GitHub Copilot models that may require policy acceptance.
2515
- * Called after successful login to ensure all models are available.
2516
- */
2517
- async function enableAllGitHubCopilotModels(token, enterpriseDomain, signal) {
2518
- const models = Object.values(GITHUB_COPILOT_MODELS);
2519
- await Promise.all(models.map(async (model) => {
2520
- await enableGitHubCopilotModel(token, model.id, enterpriseDomain, signal);
2521
- }));
2522
- }
2523
- async function loginGitHubCopilot(interaction) {
2524
- const input = await interaction.prompt({
2525
- type: "text",
2526
- message: "GitHub Enterprise URL/domain (blank for github.com)",
2527
- placeholder: "company.ghe.com"
2528
- });
2529
- if (interaction.signal.aborted) throw new Error("Login cancelled");
2530
- const trimmed = input.trim();
2531
- const enterpriseDomain = normalizeDomain(input);
2532
- if (trimmed && !enterpriseDomain) throw new Error("Invalid GitHub Enterprise URL/domain");
2533
- const domain = enterpriseDomain || "github.com";
2534
- const device = await startDeviceFlow(domain, interaction.signal);
2535
- interaction.notify({
2536
- type: "device_code",
2537
- userCode: device.user_code,
2538
- verificationUri: device.verification_uri,
2539
- intervalSeconds: device.interval,
2540
- expiresInSeconds: device.expires_in
2541
- });
2542
- const credentials = await refreshGitHubCopilotAccessToken(await pollForGitHubAccessToken(domain, device, interaction.signal), enterpriseDomain ?? void 0, interaction.signal);
2543
- interaction.notify({
2544
- type: "progress",
2545
- message: "Enabling models..."
2546
- });
2547
- await enableAllGitHubCopilotModels(credentials.access, enterpriseDomain ?? void 0, interaction.signal);
2548
- return {
2549
- ...credentials,
2550
- availableModelIds: await fetchAvailableGitHubCopilotModelIds(credentials.access, enterpriseDomain ?? void 0, interaction.signal)
2551
- };
2552
- }
2553
- function copilotEnterpriseDomain(credential) {
2554
- const enterpriseUrl = credential.enterpriseUrl;
2555
- if (typeof enterpriseUrl !== "string" || !enterpriseUrl) return void 0;
2556
- return normalizeDomain(enterpriseUrl) ?? void 0;
2557
- }
2558
- const githubCopilotOAuth = {
2559
- name: "GitHub Copilot",
2560
- isSubscription: true,
2561
- login: loginGitHubCopilot,
2562
- refresh: (credential, signal) => refreshGitHubCopilotToken(credential.refresh, copilotEnterpriseDomain(credential), signal),
2563
- /** Derive the credential-specific proxy endpoint for each request. */
2564
- async toAuth(credential) {
2565
- return {
2566
- apiKey: credential.access,
2567
- baseUrl: getGitHubCopilotBaseUrl(credential.access, copilotEnterpriseDomain(credential))
2568
- };
2569
- }
2570
- };
2571
- //#endregion
2572
- //#region src/compat/vendor/pi-oauth-flows/kimi-coding.ts
2573
- /**
2574
- * Kimi Code (subscription) OAuth flow
2575
- *
2576
- * RFC 8628 device authorization grant against https://auth.kimi.com with JSON
2577
- * responses. The access token authenticates requests to
2578
- * https://api.kimi.com/coding as an `Authorization: Bearer` header.
2579
- */
2580
- const CLIENT_ID = "17e5f671-d194-4dfb-9706-5516cb48c098";
2581
- const DEFAULT_OAUTH_HOST = "https://auth.kimi.com";
2582
- const DEVICE_CODE_TIMEOUT_SECONDS = 900;
2583
- const DEFAULT_POLL_INTERVAL_SECONDS = 5;
2584
- const REQUEST_TIMEOUT_MS = 3e4;
2585
- const REFRESH_MAX_RETRIES = 3;
2586
- function getOauthHost() {
2587
- return (getProviderEnvValue("KIMI_CODE_OAUTH_HOST") || getProviderEnvValue("KIMI_OAUTH_HOST") || DEFAULT_OAUTH_HOST).replace(/\/+$/, "");
2588
- }
2589
- function requestSignal(signal) {
2590
- return AbortSignal.any([AbortSignal.timeout(REQUEST_TIMEOUT_MS), signal]);
2591
- }
2592
- function formUrlEncode(fields) {
2593
- return new URLSearchParams(fields).toString();
2594
- }
2595
- async function readJson(response) {
2596
- try {
2597
- const json = await response.json();
2598
- return json && typeof json === "object" ? json : null;
2599
- } catch {
2600
- return null;
2601
- }
2602
- }
2603
- /** The verification URI is opened in the user's browser; only http(s) URLs are trusted. */
2604
- function trustedHttpUrl(value) {
2605
- if (typeof value !== "string" || !value) return null;
2606
- try {
2607
- const url = new URL(value);
2608
- if (url.protocol !== "https:" && url.protocol !== "http:") return null;
2609
- return url.href;
2610
- } catch {
2611
- return null;
2612
- }
2613
- }
2614
- async function startDeviceAuthorization(oauthHost, signal) {
2615
- const response = await fetch(`${oauthHost}/api/oauth/device_authorization`, {
2616
- method: "POST",
2617
- headers: {
2618
- "Content-Type": "application/x-www-form-urlencoded",
2619
- Accept: "application/json"
2620
- },
2621
- body: formUrlEncode({ client_id: CLIENT_ID }),
2622
- signal: requestSignal(signal)
2623
- });
2624
- if (!response.ok) {
2625
- const text = await response.text().catch(() => "");
2626
- throw new Error(`Kimi Code device authorization failed with status ${response.status}${text ? `: ${text}` : ""}`);
2627
- }
2628
- const json = await readJson(response);
2629
- const deviceCode = json?.device_code;
2630
- const userCode = json?.user_code;
2631
- const verificationUri = json?.verification_uri;
2632
- const verificationUriComplete = json?.verification_uri_complete;
2633
- if (typeof deviceCode !== "string" || typeof userCode !== "string" || typeof verificationUri !== "string" || typeof verificationUriComplete !== "string" || !trustedHttpUrl(verificationUriComplete) || !trustedHttpUrl(verificationUri)) throw new Error(`Invalid Kimi Code device authorization response: ${JSON.stringify(json)}`);
2634
- const interval = json?.interval;
2635
- const expiresIn = json?.expires_in;
2636
- return {
2637
- deviceCode,
2638
- userCode,
2639
- verificationUri,
2640
- verificationUriComplete,
2641
- intervalSeconds: typeof interval === "number" && Number.isFinite(interval) && interval > 0 ? interval : DEFAULT_POLL_INTERVAL_SECONDS,
2642
- expiresInSeconds: typeof expiresIn === "number" && Number.isFinite(expiresIn) && expiresIn > 0 ? expiresIn : DEVICE_CODE_TIMEOUT_SECONDS
2643
- };
2644
- }
2645
- function parseTokenResponse(json, operation) {
2646
- const accessToken = json?.access_token;
2647
- const refreshToken = json?.refresh_token;
2648
- const expiresIn = json?.expires_in;
2649
- if (typeof accessToken !== "string" || !accessToken || typeof refreshToken !== "string" || !refreshToken || typeof expiresIn !== "number" || !Number.isFinite(expiresIn) || expiresIn <= 0) throw new Error(`Kimi Code token ${operation} response missing fields: ${JSON.stringify(json)}`);
2650
- return {
2651
- access: accessToken,
2652
- refresh: refreshToken,
2653
- expires: Date.now() + expiresIn * 1e3
2654
- };
2655
- }
2656
- async function pollForToken(oauthHost, device, signal) {
2657
- return pollOAuthDeviceCodeFlow({
2658
- intervalSeconds: device.intervalSeconds,
2659
- expiresInSeconds: device.expiresInSeconds,
2660
- waitBeforeFirstPoll: true,
2661
- signal,
2662
- poll: async () => {
2663
- const response = await fetch(`${oauthHost}/api/oauth/token`, {
2664
- method: "POST",
2665
- headers: {
2666
- "Content-Type": "application/x-www-form-urlencoded",
2667
- Accept: "application/json"
2668
- },
2669
- body: formUrlEncode({
2670
- client_id: CLIENT_ID,
2671
- device_code: device.deviceCode,
2672
- grant_type: "urn:ietf:params:oauth:grant-type:device_code"
2673
- }),
2674
- signal: requestSignal(signal)
2675
- });
2676
- if (response.status >= 500) {
2677
- const text = await response.text().catch(() => "");
2678
- return {
2679
- status: "failed",
2680
- message: `Kimi Code device token request failed with status ${response.status}${text ? `: ${text}` : ""}`
2681
- };
2682
- }
2683
- const json = await readJson(response);
2684
- if (response.ok && typeof json?.access_token === "string") try {
2685
- return {
2686
- status: "complete",
2687
- value: parseTokenResponse(json, "poll")
2688
- };
2689
- } catch (error) {
2690
- return {
2691
- status: "failed",
2692
- message: error instanceof Error ? error.message : String(error)
2693
- };
2694
- }
2695
- const error = json?.error;
2696
- const description = typeof json?.error_description === "string" ? `: ${json.error_description}` : "";
2697
- if (error === "authorization_pending") return { status: "pending" };
2698
- if (error === "slow_down") {
2699
- const interval = json?.interval;
2700
- return {
2701
- status: "slow_down",
2702
- intervalSeconds: typeof interval === "number" && interval > 0 ? interval : void 0
2703
- };
2704
- }
2705
- if (error === "expired_token") return {
2706
- status: "failed",
2707
- message: "Kimi Code device authorization expired. Please restart login."
2708
- };
2709
- if (error === "access_denied") return {
2710
- status: "failed",
2711
- message: "Kimi Code login was denied."
2712
- };
2713
- return {
2714
- status: "failed",
2715
- message: `Kimi Code device token request failed (status ${response.status})${typeof error === "string" ? `: ${error}${description}` : ""}`
2716
- };
2717
- }
2718
- });
2719
- }
2720
- function sleep(ms, signal) {
2721
- return new Promise((resolve, reject) => {
2722
- signal.throwIfAborted();
2723
- const onAbort = () => {
2724
- clearTimeout(timeout);
2725
- reject(signal.reason);
2726
- };
2727
- const timeout = setTimeout(() => {
2728
- signal.removeEventListener("abort", onAbort);
2729
- resolve();
2730
- }, ms);
2731
- signal.addEventListener("abort", onAbort, { once: true });
2732
- });
2733
- }
2734
- function isRetryableRefreshFailure(response) {
2735
- return response.status === 429 || response.status >= 500;
2736
- }
2737
- async function refreshToken(oauthHost, refreshTokenValue, signal) {
2738
- let lastError;
2739
- for (let attempt = 0; attempt <= REFRESH_MAX_RETRIES; attempt++) {
2740
- if (attempt > 0) await sleep(1e3 * 2 ** (attempt - 1), signal);
2741
- if (signal.aborted) throw new Error("Kimi Code token refresh aborted");
2742
- let response;
2743
- try {
2744
- response = await fetch(`${oauthHost}/api/oauth/token`, {
2745
- method: "POST",
2746
- headers: {
2747
- "Content-Type": "application/x-www-form-urlencoded",
2748
- Accept: "application/json"
2749
- },
2750
- body: formUrlEncode({
2751
- client_id: CLIENT_ID,
2752
- grant_type: "refresh_token",
2753
- refresh_token: refreshTokenValue
2754
- }),
2755
- signal: requestSignal(signal)
2756
- });
2757
- } catch (error) {
2758
- lastError = error instanceof Error ? error : new Error(String(error));
2759
- continue;
2760
- }
2761
- const json = await readJson(response);
2762
- if (response.ok) return parseTokenResponse(json, "refresh");
2763
- if (response.status === 401 || response.status === 403 || json?.error === "invalid_grant") {
2764
- const description = typeof json?.error_description === "string" ? `: ${json.error_description}` : "";
2765
- throw new Error(`Kimi Code token refresh unauthorized (status ${response.status})${description}`);
2766
- }
2767
- if (isRetryableRefreshFailure(response) && attempt < REFRESH_MAX_RETRIES) {
2768
- lastError = /* @__PURE__ */ new Error(`Kimi Code token refresh failed with status ${response.status}`);
2769
- continue;
2770
- }
2771
- const text = JSON.stringify(json);
2772
- throw new Error(`Kimi Code token refresh failed with status ${response.status}${text ? `: ${text}` : ""}`);
2773
- }
2774
- throw lastError ?? /* @__PURE__ */ new Error("Kimi Code token refresh failed");
2775
- }
2776
- async function loginKimiCoding(interaction) {
2777
- const oauthHost = getOauthHost();
2778
- const device = await startDeviceAuthorization(oauthHost, interaction.signal);
2779
- interaction.notify({
2780
- type: "device_code",
2781
- userCode: device.userCode,
2782
- verificationUri: device.verificationUriComplete,
2783
- intervalSeconds: device.intervalSeconds,
2784
- expiresInSeconds: device.expiresInSeconds
2785
- });
2786
- const token = await pollForToken(oauthHost, device, interaction.signal);
2787
- return {
2788
- type: "oauth",
2789
- access: token.access,
2790
- refresh: token.refresh,
2791
- expires: token.expires
2792
- };
2793
- }
2794
- const kimiCodingOAuth = {
2795
- name: "Kimi Code (subscription)",
2796
- isSubscription: true,
2797
- loginLabel: "Sign in with Kimi Code",
2798
- login: loginKimiCoding,
2799
- refresh: async (credential, signal) => {
2800
- const token = await refreshToken(getOauthHost(), credential.refresh, signal);
2801
- return {
2802
- type: "oauth",
2803
- access: token.access,
2804
- refresh: token.refresh,
2805
- expires: token.expires
2806
- };
2807
- },
2808
- async toAuth(credential) {
2809
- return { headers: { Authorization: `Bearer ${credential.access}` } };
2810
- }
2811
- };
2812
- //#endregion
2813
- //#region src/compat/pi-ai.ts
2814
- const EXTENDED_THINKING_LEVELS = [
2815
- "off",
2816
- "minimal",
2817
- "low",
2818
- "medium",
2819
- "high",
2820
- "xhigh",
2821
- "max"
2822
- ];
2823
- function getSupportedThinkingLevels(model) {
2824
- return EXTENDED_THINKING_LEVELS.filter((level) => {
2825
- const mapped = model.thinkingLevelMap?.[level];
2826
- if (mapped === null) return false;
2827
- if (level === "xhigh" || level === "max") return mapped !== void 0;
2828
- return true;
2829
- });
2830
- }
2831
- function clampThinkingLevel(model, level) {
2832
- const availableLevels = getSupportedThinkingLevels(model);
2833
- if (availableLevels.includes(level)) return level;
2834
- const requestedIndex = EXTENDED_THINKING_LEVELS.indexOf(level);
2835
- if (requestedIndex === -1) return availableLevels[0] ?? "off";
2836
- for (let i = requestedIndex; i < EXTENDED_THINKING_LEVELS.length; i += 1) {
2837
- const candidate = EXTENDED_THINKING_LEVELS[i];
2838
- if (availableLevels.includes(candidate)) return candidate;
2839
- }
2840
- for (let i = requestedIndex - 1; i >= 0; i -= 1) {
2841
- const candidate = EXTENDED_THINKING_LEVELS[i];
2842
- if (availableLevels.includes(candidate)) return candidate;
2843
- }
2844
- return availableLevels[0] ?? "off";
2845
- }
2846
- function modelsAreEqual(a, b) {
2847
- if (a === null || a === void 0 || b === null || b === void 0) return false;
2848
- return a.id === b.id && a.provider === b.provider;
2849
- }
2850
- function contentText(content, separator = "\n") {
2851
- if (typeof content === "string") return content;
2852
- return content.filter((block) => block.type === "text").map((block) => String(block.text ?? "")).join(separator);
2853
- }
2854
- const compatProviders = /* @__PURE__ */ new Map();
2855
- function registerProvider(name, provider) {
2856
- compatProviders.set(name, provider);
2857
- }
2858
- function getProviders() {
2859
- return [...compatProviders.keys()];
2860
- }
2861
- function getProvider(name) {
2862
- return compatProviders.get(name);
2863
- }
2864
- function getModel(_provider, _id) {}
2865
- function getModels(_provider) {
2866
- return [];
2867
- }
2868
- function unbridgedTransport(api) {
2869
- throw new Error(`pi2dsh: the ${api} protocol client is not bridged; model transports stay native to DSH llm/credentials`);
2870
- }
2871
- function openAICompletionsApi() {
2872
- return lazyApi(async () => unbridgedTransport("openai-completions"), void 0);
2873
- }
2874
- function openAIResponsesApi() {
2875
- return lazyApi(async () => unbridgedTransport("openai-responses"), {
2876
- fetchDeferred: true,
2877
- cancelDeferred: true
2878
- });
2879
- }
2880
- function anthropicMessagesApi() {
2881
- return lazyApi(async () => unbridgedTransport("anthropic-messages"), void 0);
2882
- }
2883
- function builtinProviders() {
2884
- const entry = (id, name, baseUrl, oauth) => ({
2885
- id,
2886
- name,
2887
- api: "openai-completions",
2888
- baseUrl,
2889
- models: [],
2890
- auth: { oauth }
2891
- });
2892
- return [
2893
- entry("openai-codex", "OpenAI (ChatGPT Plus/Pro)", "https://chatgpt.com/backend-api/codex", openaiCodexOAuth),
2894
- entry("anthropic", "Anthropic", "https://api.anthropic.com", anthropicOAuth),
2895
- entry("github-copilot", "GitHub Copilot", "https://api.githubcopilot.com", githubCopilotOAuth),
2896
- entry("kimi-coding", "Kimi Code", "https://api.moonshot.ai/anthropic", kimiCodingOAuth)
2897
- ];
2898
- }
2899
- const loadOpenAICodexOAuth = async () => openaiCodexOAuth;
2900
- const loadAnthropicOAuth = async () => anthropicOAuth;
2901
- const loadGitHubCopilotOAuth = async () => githubCopilotOAuth;
2902
- const loadKimiCodingOAuth = async () => kimiCodingOAuth;
2903
- function complete(..._args) {
2904
- throw new Error("pi2dsh: pi-ai complete() routes model calls through Pi provider SDKs; use DSH llm adapters instead");
2905
- }
2906
- function stream(..._args) {
2907
- throw new Error("pi2dsh: pi-ai stream() routes model calls through Pi provider SDKs; use DSH llm adapters instead");
2908
- }
2909
- function StringEnum(values, options = {}) {
2910
- return {
2911
- type: "string",
2912
- enum: values,
2913
- ...options.description !== void 0 ? { description: options.description } : {},
2914
- ...options.default !== void 0 ? { default: options.default } : {}
2915
- };
2916
- }
2917
- //#endregion
2918
- export { AssistantMessageEventStream, ModelsError, StringEnum, typebox_exports as Type, anthropicMessagesApi, anthropicOAuth, builtinProviders, clampThinkingLevel, complete, contentText, createProvider, generatePKCE, getModel, getModels, getProvider, getProviders, getSupportedThinkingLevels, githubCopilotOAuth, isContextOverflow, isRecoverableLength, isRetryableAssistantError, kimiCodingOAuth, lazyApi, lazyStream, loadAnthropicOAuth, loadGitHubCopilotOAuth, loadKimiCodingOAuth, loadOpenAICodexOAuth, modelsAreEqual, openAICompletionsApi, openAIResponsesApi, openaiCodexOAuth, pollOAuthDeviceCodeFlow, registerProvider, stream, uuidv7 };
2919
-
2920
- //# sourceMappingURL=pi-ai.mjs.map
3
+ import { A as pollOAuthDeviceCodeFlow, C as stream, D as anthropicOAuth, E as githubCopilotOAuth, F as AssistantMessageEventStream, I as isRetryableAssistantError, L as isContextOverflow, M as createProvider, N as lazyApi, O as openaiCodexOAuth, P as lazyStream, R as isRecoverableLength, S as registerProvider, T as kimiCodingOAuth, _ as loadOpenAICodexOAuth, a as complete, b as openAIResponsesApi, c as getApiProviders, d as getProvider, f as getProviders, g as loadKimiCodingOAuth, h as loadGitHubCopilotOAuth, i as clampThinkingLevel, j as ModelsError, k as generatePKCE, l as getModel, m as loadAnthropicOAuth, n as anthropicMessagesApi, o as contentText, p as getSupportedThinkingLevels, r as builtinProviders, s as getApiProvider, t as StringEnum, u as getModels, v as modelsAreEqual, w as unregisterApiProviders, x as registerApiProvider, y as openAICompletionsApi } from "../pi-ai-CWFlgigJ.mjs";
4
+ export { AssistantMessageEventStream, ModelsError, StringEnum, typebox_exports as Type, anthropicMessagesApi, anthropicOAuth, builtinProviders, clampThinkingLevel, complete, contentText, createProvider, generatePKCE, getApiProvider, getApiProviders, getModel, getModels, getProvider, getProviders, getSupportedThinkingLevels, githubCopilotOAuth, isContextOverflow, isRecoverableLength, isRetryableAssistantError, kimiCodingOAuth, lazyApi, lazyStream, loadAnthropicOAuth, loadGitHubCopilotOAuth, loadKimiCodingOAuth, loadOpenAICodexOAuth, modelsAreEqual, openAICompletionsApi, openAIResponsesApi, openaiCodexOAuth, pollOAuthDeviceCodeFlow, registerApiProvider, registerProvider, stream, unregisterApiProviders, uuidv7 };