@jacobbd/relay-ai 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -1
- package/dist/{chunk-RTZ3X3KZ.js → chunk-2GUFTECU.js} +233 -22
- package/dist/chunk-2GUFTECU.js.map +1 -0
- package/dist/cli.js +8 -4
- package/dist/cli.js.map +1 -1
- package/dist/{ui-command-PJG4Y2QY.js → ui-command-64SLLWW4.js} +2 -2
- package/package.json +3 -1
- package/dist/chunk-RTZ3X3KZ.js.map +0 -1
- /package/dist/{ui-command-PJG4Y2QY.js.map → ui-command-64SLLWW4.js.map} +0 -0
package/README.md
CHANGED
|
@@ -9,7 +9,11 @@
|
|
|
9
9
|
|
|
10
10
|
[](https://www.npmjs.com/package/@jacobbd/relay-ai)
|
|
11
11
|
[](LICENSE)
|
|
12
|
-
|
|
12
|
+
|
|
13
|
+
> ☕ **If you find relay-ai useful, consider [buying me a coffee](https://buymeacoffee.com/jacobbd).**
|
|
14
|
+
> It's free and built in my spare time — but testing every provider runs up a real AI bill. A coffee helps me cover it and keep shipping. Thank you! 🙏
|
|
15
|
+
>
|
|
16
|
+
> <a href="https://buymeacoffee.com/jacobbd"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="42"></a>
|
|
13
17
|
|
|
14
18
|
<p align="center">
|
|
15
19
|
<a href="https://youtu.be/IvsUPHLhX0o">
|
|
@@ -570,6 +574,12 @@ The deprecated `OPENCODE_STARTER_HOME` env var still works as a fallback for `RE
|
|
|
570
574
|
|
|
571
575
|
Private beta right now. Issues and PRs welcome on GitHub.
|
|
572
576
|
|
|
577
|
+
## Support
|
|
578
|
+
|
|
579
|
+
If relay-ai saves you time or money, you can help cover the AI bills that go into building and testing it against every provider. Any support is hugely appreciated. 🙏
|
|
580
|
+
|
|
581
|
+
<a href="https://buymeacoffee.com/jacobbd"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="42"></a>
|
|
582
|
+
|
|
573
583
|
## Disclaimer
|
|
574
584
|
|
|
575
585
|
This project and its creator have **no affiliation** with OpenCode, Anthropic, Claude, Google, GitHub, OpenAI, xAI, or any other vendor named or integrated here. Trademarks belong to their respective owners.
|
|
@@ -11,7 +11,7 @@ import { join } from "path";
|
|
|
11
11
|
// package.json
|
|
12
12
|
var package_default = {
|
|
13
13
|
name: "@jacobbd/relay-ai",
|
|
14
|
-
version: "0.4.
|
|
14
|
+
version: "0.4.1",
|
|
15
15
|
publishConfig: {
|
|
16
16
|
access: "public"
|
|
17
17
|
},
|
|
@@ -81,10 +81,12 @@ var package_default = {
|
|
|
81
81
|
picocolors: "^1.1.1",
|
|
82
82
|
"smol-toml": "^1.6.1",
|
|
83
83
|
"venice-ai-sdk-provider": "^2.0.2",
|
|
84
|
+
ws: "^8.21.0",
|
|
84
85
|
zod: "^3.25.76"
|
|
85
86
|
},
|
|
86
87
|
devDependencies: {
|
|
87
88
|
"@types/node": "^22.0.0",
|
|
89
|
+
"@types/ws": "^8.18.1",
|
|
88
90
|
"@vitest/coverage-v8": "^2.1.9",
|
|
89
91
|
tsup: "^8.0.0",
|
|
90
92
|
typescript: "^5.5.0",
|
|
@@ -112,6 +114,9 @@ var BACKENDS = {
|
|
|
112
114
|
baseUrl: "https://opencode.ai/zen/go"
|
|
113
115
|
}
|
|
114
116
|
};
|
|
117
|
+
var CODEX_RESPONSES_LITE_WS_URL = "wss://chatgpt.com/backend-api/codex/responses";
|
|
118
|
+
var CODEX_RESPONSES_LITE_VERSION = "0.144.1";
|
|
119
|
+
var CODEX_RESPONSES_WEBSOCKETS_BETA = "responses_websockets=2026-02-06";
|
|
115
120
|
var CONFLICTING_ENV_VARS = [
|
|
116
121
|
"CLAUDE_CODE_USE_VERTEX",
|
|
117
122
|
"ANTHROPIC_VERTEX_PROJECT_ID",
|
|
@@ -312,6 +317,161 @@ async function runOpenAiDeviceCodeFlow(onDeviceCode, opts) {
|
|
|
312
317
|
return pollOpenAiDeviceCodeToken(deviceData, opts);
|
|
313
318
|
}
|
|
314
319
|
|
|
320
|
+
// src/oauth/responses-websocket.ts
|
|
321
|
+
var RESPONSES_LITE_HEADER = "x-openai-internal-codex-responses-lite";
|
|
322
|
+
var TERMINAL_EVENT_TYPES = /* @__PURE__ */ new Set(["response.completed", "response.failed", "response.incomplete"]);
|
|
323
|
+
function toHeaderRecord(headers) {
|
|
324
|
+
const out = {};
|
|
325
|
+
if (!headers) return out;
|
|
326
|
+
if (headers instanceof Headers) {
|
|
327
|
+
headers.forEach((value, key) => {
|
|
328
|
+
out[key] = value;
|
|
329
|
+
});
|
|
330
|
+
} else if (Array.isArray(headers)) {
|
|
331
|
+
for (const [key, value] of headers) out[key] = value;
|
|
332
|
+
} else {
|
|
333
|
+
for (const [key, value] of Object.entries(headers)) out[key] = String(value);
|
|
334
|
+
}
|
|
335
|
+
return out;
|
|
336
|
+
}
|
|
337
|
+
function hasResponsesLiteHeader(headers) {
|
|
338
|
+
return Object.entries(headers).some(
|
|
339
|
+
([k, v]) => k.toLowerCase() === RESPONSES_LITE_HEADER && v.toLowerCase() === "true"
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
function bodyToString(body) {
|
|
343
|
+
if (body == null) return "";
|
|
344
|
+
if (typeof body === "string") return body;
|
|
345
|
+
if (body instanceof Uint8Array) return Buffer.from(body).toString("utf8");
|
|
346
|
+
if (body instanceof ArrayBuffer) return Buffer.from(new Uint8Array(body)).toString("utf8");
|
|
347
|
+
return String(body);
|
|
348
|
+
}
|
|
349
|
+
function applyResponsesLiteShape(payload) {
|
|
350
|
+
const reasoning = payload.reasoning && typeof payload.reasoning === "object" ? { ...payload.reasoning } : {};
|
|
351
|
+
reasoning.context = "all_turns";
|
|
352
|
+
return {
|
|
353
|
+
...payload,
|
|
354
|
+
reasoning,
|
|
355
|
+
parallel_tool_calls: false,
|
|
356
|
+
store: false
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
function createResponsesWebSocketFetch(wsUrl, log7) {
|
|
360
|
+
const debug = (msg) => {
|
|
361
|
+
try {
|
|
362
|
+
log7?.(`ws: ${msg}`);
|
|
363
|
+
} catch {
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
return async (_input, init) => {
|
|
367
|
+
const { WebSocket } = await import("ws");
|
|
368
|
+
const headers = toHeaderRecord(init?.headers);
|
|
369
|
+
headers["OpenAI-Beta"] = CODEX_RESPONSES_WEBSOCKETS_BETA;
|
|
370
|
+
debug(`connecting ${wsUrl} headers=[${Object.keys(headers).join(", ")}]`);
|
|
371
|
+
let payload = {};
|
|
372
|
+
try {
|
|
373
|
+
payload = JSON.parse(bodyToString(init?.body));
|
|
374
|
+
} catch {
|
|
375
|
+
payload = {};
|
|
376
|
+
}
|
|
377
|
+
if (hasResponsesLiteHeader(headers)) {
|
|
378
|
+
payload = applyResponsesLiteShape(payload);
|
|
379
|
+
}
|
|
380
|
+
const outgoing = JSON.stringify({ type: "response.create", ...payload });
|
|
381
|
+
const encoder = new TextEncoder();
|
|
382
|
+
let socket;
|
|
383
|
+
let frameCount = 0;
|
|
384
|
+
const stream = new ReadableStream({
|
|
385
|
+
start(controller) {
|
|
386
|
+
let closed = false;
|
|
387
|
+
const close = () => {
|
|
388
|
+
if (closed) return;
|
|
389
|
+
closed = true;
|
|
390
|
+
try {
|
|
391
|
+
controller.close();
|
|
392
|
+
} catch {
|
|
393
|
+
}
|
|
394
|
+
try {
|
|
395
|
+
socket.close();
|
|
396
|
+
} catch {
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
const fail = (message) => {
|
|
400
|
+
if (closed) return;
|
|
401
|
+
debug(`fail: ${message}`);
|
|
402
|
+
try {
|
|
403
|
+
controller.enqueue(encoder.encode(
|
|
404
|
+
`data: ${JSON.stringify({ type: "error", error: { message } })}
|
|
405
|
+
|
|
406
|
+
`
|
|
407
|
+
));
|
|
408
|
+
} catch {
|
|
409
|
+
}
|
|
410
|
+
close();
|
|
411
|
+
};
|
|
412
|
+
socket = new WebSocket(wsUrl, { headers });
|
|
413
|
+
socket.on("open", () => {
|
|
414
|
+
debug(`open \u2014 sending ${outgoing.length}B payload`);
|
|
415
|
+
socket.send(outgoing);
|
|
416
|
+
});
|
|
417
|
+
socket.on("unexpected-response", (_req, res) => {
|
|
418
|
+
debug(`unexpected-response status=${res.statusCode}`);
|
|
419
|
+
});
|
|
420
|
+
socket.on("message", (data) => {
|
|
421
|
+
const text4 = Array.isArray(data) ? Buffer.concat(data).toString("utf8") : data.toString("utf8");
|
|
422
|
+
frameCount += 1;
|
|
423
|
+
if (frameCount <= 3) debug(`frame#${frameCount}: ${text4.slice(0, 200)}`);
|
|
424
|
+
let event;
|
|
425
|
+
try {
|
|
426
|
+
event = JSON.parse(text4);
|
|
427
|
+
} catch {
|
|
428
|
+
controller.enqueue(encoder.encode(`data: ${text4.replace(/\r?\n/g, " ")}
|
|
429
|
+
|
|
430
|
+
`));
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
controller.enqueue(encoder.encode(`data: ${JSON.stringify(event)}
|
|
434
|
+
|
|
435
|
+
`));
|
|
436
|
+
const type = event.type;
|
|
437
|
+
if (typeof type === "string" && TERMINAL_EVENT_TYPES.has(type)) {
|
|
438
|
+
debug(`terminal event: ${type} (after ${frameCount} frames)`);
|
|
439
|
+
close();
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
socket.on("error", (err) => fail(err.message));
|
|
443
|
+
socket.on("close", (code, reason) => {
|
|
444
|
+
debug(`close code=${code} frames=${frameCount}${reason?.length ? ` reason=${reason.toString("utf8").slice(0, 200)}` : ""}`);
|
|
445
|
+
if (closed) return;
|
|
446
|
+
if (code === 1e3 || code === 1005) {
|
|
447
|
+
close();
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
fail(`WebSocket closed (${code})${reason?.length ? `: ${reason.toString("utf8")}` : ""}`);
|
|
451
|
+
});
|
|
452
|
+
const signal = init?.signal;
|
|
453
|
+
if (signal) {
|
|
454
|
+
if (signal.aborted) {
|
|
455
|
+
close();
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
signal.addEventListener("abort", close, { once: true });
|
|
459
|
+
}
|
|
460
|
+
},
|
|
461
|
+
cancel() {
|
|
462
|
+
try {
|
|
463
|
+
socket?.close();
|
|
464
|
+
} catch {
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
return new Response(stream, {
|
|
469
|
+
status: 200,
|
|
470
|
+
headers: { "content-type": "text/event-stream; charset=utf-8" }
|
|
471
|
+
});
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
|
|
315
475
|
// src/oauth/claude-identity.ts
|
|
316
476
|
import { createHash, randomUUID } from "crypto";
|
|
317
477
|
var CLAUDE_CODE_CLI_VERSION = "2.1.195";
|
|
@@ -504,14 +664,21 @@ async function createLanguageModel(spec) {
|
|
|
504
664
|
if (npm === "@ai-sdk/openai") {
|
|
505
665
|
const { createOpenAI } = await import("@ai-sdk/openai");
|
|
506
666
|
const accountId = spec.authType === "oauth" ? spec.oauthAccountId ?? extractOpenAiAccountId({ access_token: apiKey }) : void 0;
|
|
507
|
-
const
|
|
667
|
+
const oauthOptions = spec.authType === "oauth" ? {
|
|
508
668
|
apiKey,
|
|
509
669
|
baseURL: "https://chatgpt.com/backend-api/codex",
|
|
510
670
|
headers: {
|
|
511
671
|
...accountId ? { "ChatGPT-Account-Id": accountId } : {},
|
|
512
|
-
originator: "relay-ai"
|
|
513
|
-
|
|
514
|
-
|
|
672
|
+
originator: "relay-ai",
|
|
673
|
+
// Responses-Lite models (backend prefer_websockets/use_responses_lite,
|
|
674
|
+
// e.g. gpt-5.6-luna) require these on the request.
|
|
675
|
+
...spec.useResponsesLite ? { version: CODEX_RESPONSES_LITE_VERSION, "x-openai-internal-codex-responses-lite": "true" } : {}
|
|
676
|
+
},
|
|
677
|
+
// Models the backend flags with prefer_websockets are only served over
|
|
678
|
+
// the WebSocket Responses transport, not HTTP.
|
|
679
|
+
...spec.preferWebSockets ? { fetch: createResponsesWebSocketFetch(CODEX_RESPONSES_LITE_WS_URL, spec.onDebug) } : {}
|
|
680
|
+
} : { apiKey };
|
|
681
|
+
const openai = createOpenAI(oauthOptions);
|
|
515
682
|
return shouldUseOpenAiResponsesEndpoint(modelId) ? openai.responses(modelId) : openai.chat(modelId);
|
|
516
683
|
}
|
|
517
684
|
if (npm === "@ai-sdk/xai") {
|
|
@@ -5490,7 +5657,10 @@ function startProxyCatalog(routes, defaultAliasId, debug = false) {
|
|
|
5490
5657
|
authType: route.authType,
|
|
5491
5658
|
oauthAccountId: route.oauthAccountId,
|
|
5492
5659
|
providerData: route.providerData,
|
|
5493
|
-
headers: route.headers
|
|
5660
|
+
headers: route.headers,
|
|
5661
|
+
useResponsesLite: route.useResponsesLite,
|
|
5662
|
+
preferWebSockets: route.preferWebSockets,
|
|
5663
|
+
onDebug: (msg) => plog(() => msg)
|
|
5494
5664
|
});
|
|
5495
5665
|
if (clientWantsStream) {
|
|
5496
5666
|
res.writeHead(200, {
|
|
@@ -5620,7 +5790,9 @@ function startProxy(completionsUrl, modelId, debug = false, contextWindow, sdk,
|
|
|
5620
5790
|
providerData: sdk?.providerData,
|
|
5621
5791
|
supportedParameters: sdk?.supportedParameters,
|
|
5622
5792
|
reasoning: sdk?.reasoning,
|
|
5623
|
-
interleavedReasoningField: sdk?.interleavedReasoningField
|
|
5793
|
+
interleavedReasoningField: sdk?.interleavedReasoningField,
|
|
5794
|
+
useResponsesLite: sdk?.useResponsesLite,
|
|
5795
|
+
preferWebSockets: sdk?.preferWebSockets
|
|
5624
5796
|
}], clientModelId, debug);
|
|
5625
5797
|
}
|
|
5626
5798
|
|
|
@@ -6480,7 +6652,9 @@ function cachedModelToLocal(cached, provider) {
|
|
|
6480
6652
|
contextWindow: cached.contextWindow ?? resolveContextWindow(id),
|
|
6481
6653
|
supportedParameters: cached.supportedParameters,
|
|
6482
6654
|
reasoning: cached.reasoning ?? modelsDev?.reasoning,
|
|
6483
|
-
interleavedReasoningField: cached.interleavedReasoningField ?? modelsDev?.interleaved?.field
|
|
6655
|
+
interleavedReasoningField: cached.interleavedReasoningField ?? modelsDev?.interleaved?.field,
|
|
6656
|
+
useResponsesLite: cached.useResponsesLite,
|
|
6657
|
+
preferWebSockets: cached.preferWebSockets
|
|
6484
6658
|
};
|
|
6485
6659
|
}
|
|
6486
6660
|
function providerAllowsAnonymousFreeModels(provider) {
|
|
@@ -6642,6 +6816,8 @@ function localProvidersToServerModels(localProviders) {
|
|
|
6642
6816
|
supportedParameters: model.supportedParameters,
|
|
6643
6817
|
reasoning: model.reasoning,
|
|
6644
6818
|
interleavedReasoningField: model.interleavedReasoningField,
|
|
6819
|
+
useResponsesLite: model.useResponsesLite,
|
|
6820
|
+
preferWebSockets: model.preferWebSockets,
|
|
6645
6821
|
headers: provider.headers,
|
|
6646
6822
|
providerData: provider.providerData
|
|
6647
6823
|
}))
|
|
@@ -7209,7 +7385,9 @@ async function getOrInitLanguageModel(modelCache, model, npm, baseURL, apiKey, v
|
|
|
7209
7385
|
authType: model.authType,
|
|
7210
7386
|
oauthAccountId: model.oauthAccountId,
|
|
7211
7387
|
vertex,
|
|
7212
|
-
headers: model.headers
|
|
7388
|
+
headers: model.headers,
|
|
7389
|
+
useResponsesLite: model.useResponsesLite,
|
|
7390
|
+
preferWebSockets: model.preferWebSockets
|
|
7213
7391
|
});
|
|
7214
7392
|
modelCache.set(cacheKey, languageModel);
|
|
7215
7393
|
}
|
|
@@ -8211,7 +8389,9 @@ function parseModelList(body, npm) {
|
|
|
8211
8389
|
freeStatus,
|
|
8212
8390
|
modelFormat: format,
|
|
8213
8391
|
npm,
|
|
8214
|
-
supportedParameters: Array.isArray(row.supported_parameters) ? row.supported_parameters : void 0
|
|
8392
|
+
supportedParameters: Array.isArray(row.supported_parameters) ? row.supported_parameters : void 0,
|
|
8393
|
+
useResponsesLite: typeof row.use_responses_lite === "boolean" ? row.use_responses_lite : void 0,
|
|
8394
|
+
preferWebSockets: typeof row.prefer_websockets === "boolean" ? row.prefer_websockets : void 0
|
|
8215
8395
|
});
|
|
8216
8396
|
}
|
|
8217
8397
|
return models;
|
|
@@ -8727,7 +8907,7 @@ var OPENAI_OAUTH_MODEL_SEEDS = [
|
|
|
8727
8907
|
// GPT-5.6 family (Sol / Terra / Luna)
|
|
8728
8908
|
{ id: "gpt-5.6-sol", name: "GPT-5.6 Sol", reasoning: true },
|
|
8729
8909
|
{ id: "gpt-5.6-terra", name: "GPT-5.6 Terra", reasoning: true },
|
|
8730
|
-
{ id: "gpt-5.6-luna", name: "GPT-5.6 Luna", reasoning: true },
|
|
8910
|
+
{ id: "gpt-5.6-luna", name: "GPT-5.6 Luna", reasoning: true, useResponsesLite: true, preferWebSockets: true },
|
|
8731
8911
|
// GPT-5.5 family (Pro)
|
|
8732
8912
|
{ id: "gpt-5.5", name: "GPT-5.5", reasoning: true },
|
|
8733
8913
|
// GPT-5.4 family
|
|
@@ -8754,7 +8934,9 @@ function buildOpenAiOAuthModels() {
|
|
|
8754
8934
|
contextWindow: resolveContextWindow(seed.id),
|
|
8755
8935
|
modelFormat: "openai",
|
|
8756
8936
|
npm: "@ai-sdk/openai",
|
|
8757
|
-
reasoning: seed.reasoning
|
|
8937
|
+
reasoning: seed.reasoning,
|
|
8938
|
+
useResponsesLite: seed.useResponsesLite,
|
|
8939
|
+
preferWebSockets: seed.preferWebSockets
|
|
8758
8940
|
};
|
|
8759
8941
|
});
|
|
8760
8942
|
}
|
|
@@ -8882,30 +9064,57 @@ async function refreshOAuthProvider(provider, accessToken) {
|
|
|
8882
9064
|
if (tpl === "antigravity") return refreshAntigravityOAuthModels(accessToken);
|
|
8883
9065
|
throw new Error(`refreshOAuthProvider: unsupported template "${tpl}"`);
|
|
8884
9066
|
}
|
|
9067
|
+
function readCapabilityFlags(m) {
|
|
9068
|
+
const bool = (v) => typeof v === "boolean" ? v : void 0;
|
|
9069
|
+
return {
|
|
9070
|
+
useResponsesLite: bool(m["use_responses_lite"]),
|
|
9071
|
+
preferWebSockets: bool(m["prefer_websockets"])
|
|
9072
|
+
};
|
|
9073
|
+
}
|
|
8885
9074
|
function parseOpenAiModelEntries(body) {
|
|
8886
9075
|
if (!body || typeof body !== "object") return [];
|
|
8887
9076
|
const b = body;
|
|
8888
9077
|
if (Array.isArray(b.models)) {
|
|
8889
|
-
return b.models.map((m) => ({
|
|
9078
|
+
return b.models.map((m) => ({
|
|
9079
|
+
id: m.slug ?? "",
|
|
9080
|
+
name: m.title ?? m.name ?? m.slug ?? "",
|
|
9081
|
+
context_window: m.context_window,
|
|
9082
|
+
...readCapabilityFlags(m)
|
|
9083
|
+
})).filter((m) => m.id.length > 0);
|
|
8890
9084
|
}
|
|
8891
9085
|
if (Array.isArray(b.data)) {
|
|
8892
|
-
return b.data.map((m) => ({
|
|
9086
|
+
return b.data.map((m) => ({
|
|
9087
|
+
id: m.id ?? "",
|
|
9088
|
+
name: m.name ?? m.id ?? "",
|
|
9089
|
+
context_window: m.context_window,
|
|
9090
|
+
...readCapabilityFlags(m)
|
|
9091
|
+
})).filter((m) => m.id.length > 0);
|
|
8893
9092
|
}
|
|
8894
9093
|
return [];
|
|
8895
9094
|
}
|
|
8896
|
-
function buildDynamicOAuthModel(
|
|
8897
|
-
|
|
9095
|
+
function buildDynamicOAuthModel(entry, seedById) {
|
|
9096
|
+
const seed = seedById.get(entry.id);
|
|
9097
|
+
if (seed) {
|
|
9098
|
+
return {
|
|
9099
|
+
...seed,
|
|
9100
|
+
useResponsesLite: entry.useResponsesLite ?? seed.useResponsesLite,
|
|
9101
|
+
preferWebSockets: entry.preferWebSockets ?? seed.preferWebSockets
|
|
9102
|
+
};
|
|
9103
|
+
}
|
|
9104
|
+
const { id } = entry;
|
|
8898
9105
|
const prefix = id.split("-")[0] ?? id;
|
|
8899
9106
|
return {
|
|
8900
9107
|
id,
|
|
8901
|
-
name,
|
|
9108
|
+
name: entry.name,
|
|
8902
9109
|
upstreamModelId: id,
|
|
8903
9110
|
family: prefix,
|
|
8904
9111
|
brand: deriveBrand(prefix),
|
|
8905
|
-
contextWindow:
|
|
9112
|
+
contextWindow: entry.context_window ?? resolveContextWindow(id),
|
|
8906
9113
|
modelFormat: "openai",
|
|
8907
9114
|
npm: "@ai-sdk/openai",
|
|
8908
|
-
reasoning: modelPrefersResponsesApi(id)
|
|
9115
|
+
reasoning: modelPrefersResponsesApi(id),
|
|
9116
|
+
useResponsesLite: entry.useResponsesLite,
|
|
9117
|
+
preferWebSockets: entry.preferWebSockets
|
|
8909
9118
|
};
|
|
8910
9119
|
}
|
|
8911
9120
|
async function fetchJsonWithAuth(url, accessToken, timeoutMs) {
|
|
@@ -8932,7 +9141,7 @@ async function fetchJsonWithAuth(url, accessToken, timeoutMs) {
|
|
|
8932
9141
|
async function refreshOpenAiOAuthModels(accessToken) {
|
|
8933
9142
|
const TIMEOUT_MS = 1e4;
|
|
8934
9143
|
const seedById = new Map(buildOpenAiOAuthModels().map((m) => [m.id, m]));
|
|
8935
|
-
const toModels = (entries) => entries.map((
|
|
9144
|
+
const toModels = (entries) => entries.map((entry) => buildDynamicOAuthModel(entry, seedById));
|
|
8936
9145
|
const claudeVersion = getInstalledClaudeVersion();
|
|
8937
9146
|
const codexResult = await fetchJsonWithAuth(
|
|
8938
9147
|
`https://chatgpt.com/backend-api/codex/models?client_version=${claudeVersion}`,
|
|
@@ -9268,7 +9477,9 @@ function modelToCached(model) {
|
|
|
9268
9477
|
apiUrl: model.apiBaseUrl,
|
|
9269
9478
|
supportedParameters: model.supportedParameters,
|
|
9270
9479
|
reasoning: model.reasoning,
|
|
9271
|
-
interleavedReasoningField: model.interleavedReasoningField
|
|
9480
|
+
interleavedReasoningField: model.interleavedReasoningField,
|
|
9481
|
+
useResponsesLite: model.useResponsesLite,
|
|
9482
|
+
preferWebSockets: model.preferWebSockets
|
|
9272
9483
|
};
|
|
9273
9484
|
}
|
|
9274
9485
|
function localProviderToRegistry(provider, opts) {
|
|
@@ -10193,4 +10404,4 @@ export {
|
|
|
10193
10404
|
quitClaudeAppGracefully,
|
|
10194
10405
|
launchOrRestartClaudeApp
|
|
10195
10406
|
};
|
|
10196
|
-
//# sourceMappingURL=chunk-
|
|
10407
|
+
//# sourceMappingURL=chunk-2GUFTECU.js.map
|