@jacobbd/relay-ai 0.4.0 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,17 +9,17 @@
9
9
 
10
10
  [![npm version](https://img.shields.io/npm/v/@jacobbd/relay-ai)](https://www.npmjs.com/package/@jacobbd/relay-ai)
11
11
  [![License](https://img.shields.io/npm/l/@jacobbd/relay-ai)](LICENSE)
12
- [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-FFDD00?style=flat-square&logo=buy-me-a-coffee&logoColor=black)](https://buymeacoffee.com/jacobbd)
13
12
 
14
- <p align="center">
15
- <a href="https://youtu.be/IvsUPHLhX0o">
16
- <img src="assets/demo-part1-thumbnail.png" alt="relay-ai demo — installation, configuration, Claude Code, Claude Cowork & Claude Code Desktop (Part 1)" width="100%">
17
- </a>
18
- </p>
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>
17
+
18
+ 📺 **Watch the Demos**
19
19
 
20
- > 🎥 **Watch the Demos:**
21
- > - **Demo (Part 1):** Installation · Configuration · Claude Code · Claude Cowork & Claude Code Desktop — [watch on YouTube](https://youtu.be/IvsUPHLhX0o)
22
- > - **Demo (Part 2):** OpenAI Codex CLI & Codex Desktop App — [watch on YouTube](https://youtu.be/42oiOB8IAu4)
20
+ | **Claude Code / Cowork / Desktop** | **Codex CLI & Desktop App** | **Gemini CLI** |
21
+ |:---:|:---:|:---:|
22
+ | [![Claude Demo](https://img.youtube.com/vi/IvsUPHLhX0o/mqdefault.jpg)](https://youtu.be/IvsUPHLhX0o) | [![Codex Demo](https://img.youtube.com/vi/42oiOB8IAu4/mqdefault.jpg)](https://youtu.be/42oiOB8IAu4) | [![Gemini Demo](https://img.youtube.com/vi/g7JKvqOHJl4/mqdefault.jpg)](https://www.youtube.com/watch?v=g7JKvqOHJl4) |
23
23
 
24
24
  **relay-ai** is an interactive CLI — and now a **visual launcher** — that connects AI coding tools to any provider and runs local API gateways on your machine. It supports **Claude Code**, **Claude Desktop (Cowork + Code)**, the **OpenAI Codex CLI**, the **ChatGPT desktop app in Codex mode (macOS + Windows)**, **Google Gemini CLI**, and experimental **Antigravity CLI / IDE** support.
25
25
 
@@ -570,6 +570,12 @@ The deprecated `OPENCODE_STARTER_HOME` env var still works as a fallback for `RE
570
570
 
571
571
  Private beta right now. Issues and PRs welcome on GitHub.
572
572
 
573
+ ## Support
574
+
575
+ 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. 🙏
576
+
577
+ <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>
578
+
573
579
  ## Disclaimer
574
580
 
575
581
  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.0",
14
+ version: "0.4.3",
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 openai = createOpenAI(spec.authType === "oauth" ? {
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
- } : { apiKey });
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
  }))
@@ -7111,10 +7287,12 @@ async function handleAnthropicMessages(req, res, options, modelCache, plog) {
7111
7287
  sendJson(res, 200, anthropicResponse);
7112
7288
  }
7113
7289
  } catch (err) {
7114
- const message = err instanceof Error ? err.message : String(err);
7290
+ const message = formatUpstreamError(err);
7115
7291
  plog(`sdk error npm=${model.npm} upstream=${upstreamModelId(model)}: ${message}`);
7116
- if (!res.headersSent) sendJson(res, 502, { error: { message } });
7117
- else res.end();
7292
+ if (!res.headersSent) {
7293
+ const status = upstreamHttpStatus(err, message);
7294
+ sendJson(res, status === 500 ? 502 : status, { error: { message } });
7295
+ } else res.end();
7118
7296
  }
7119
7297
  return;
7120
7298
  }
@@ -7164,10 +7342,12 @@ async function handleOpenAIChatCompletions(req, res, options, modelCache, plog)
7164
7342
  sendJson(res, 200, response);
7165
7343
  }
7166
7344
  } catch (err) {
7167
- const message = err instanceof Error ? err.message : String(err);
7345
+ const message = formatUpstreamError(err);
7168
7346
  plog(`sdk error npm=${model.npm} upstream=${upstreamModelId(model)}: ${message}`);
7169
- if (!res.headersSent) sendJson(res, 502, { error: { message } });
7170
- else res.end();
7347
+ if (!res.headersSent) {
7348
+ const status = upstreamHttpStatus(err, message);
7349
+ sendJson(res, status === 500 ? 502 : status, { error: { message } });
7350
+ } else res.end();
7171
7351
  }
7172
7352
  }
7173
7353
  function lookupModel(res, catalog, modelId) {
@@ -7209,7 +7389,9 @@ async function getOrInitLanguageModel(modelCache, model, npm, baseURL, apiKey, v
7209
7389
  authType: model.authType,
7210
7390
  oauthAccountId: model.oauthAccountId,
7211
7391
  vertex,
7212
- headers: model.headers
7392
+ headers: model.headers,
7393
+ useResponsesLite: model.useResponsesLite,
7394
+ preferWebSockets: model.preferWebSockets
7213
7395
  });
7214
7396
  modelCache.set(cacheKey, languageModel);
7215
7397
  }
@@ -8211,7 +8393,9 @@ function parseModelList(body, npm) {
8211
8393
  freeStatus,
8212
8394
  modelFormat: format,
8213
8395
  npm,
8214
- supportedParameters: Array.isArray(row.supported_parameters) ? row.supported_parameters : void 0
8396
+ supportedParameters: Array.isArray(row.supported_parameters) ? row.supported_parameters : void 0,
8397
+ useResponsesLite: typeof row.use_responses_lite === "boolean" ? row.use_responses_lite : void 0,
8398
+ preferWebSockets: typeof row.prefer_websockets === "boolean" ? row.prefer_websockets : void 0
8215
8399
  });
8216
8400
  }
8217
8401
  return models;
@@ -8727,7 +8911,7 @@ var OPENAI_OAUTH_MODEL_SEEDS = [
8727
8911
  // GPT-5.6 family (Sol / Terra / Luna)
8728
8912
  { id: "gpt-5.6-sol", name: "GPT-5.6 Sol", reasoning: true },
8729
8913
  { 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 },
8914
+ { id: "gpt-5.6-luna", name: "GPT-5.6 Luna", reasoning: true, useResponsesLite: true, preferWebSockets: true },
8731
8915
  // GPT-5.5 family (Pro)
8732
8916
  { id: "gpt-5.5", name: "GPT-5.5", reasoning: true },
8733
8917
  // GPT-5.4 family
@@ -8754,7 +8938,9 @@ function buildOpenAiOAuthModels() {
8754
8938
  contextWindow: resolveContextWindow(seed.id),
8755
8939
  modelFormat: "openai",
8756
8940
  npm: "@ai-sdk/openai",
8757
- reasoning: seed.reasoning
8941
+ reasoning: seed.reasoning,
8942
+ useResponsesLite: seed.useResponsesLite,
8943
+ preferWebSockets: seed.preferWebSockets
8758
8944
  };
8759
8945
  });
8760
8946
  }
@@ -8882,30 +9068,57 @@ async function refreshOAuthProvider(provider, accessToken) {
8882
9068
  if (tpl === "antigravity") return refreshAntigravityOAuthModels(accessToken);
8883
9069
  throw new Error(`refreshOAuthProvider: unsupported template "${tpl}"`);
8884
9070
  }
9071
+ function readCapabilityFlags(m) {
9072
+ const bool = (v) => typeof v === "boolean" ? v : void 0;
9073
+ return {
9074
+ useResponsesLite: bool(m["use_responses_lite"]),
9075
+ preferWebSockets: bool(m["prefer_websockets"])
9076
+ };
9077
+ }
8885
9078
  function parseOpenAiModelEntries(body) {
8886
9079
  if (!body || typeof body !== "object") return [];
8887
9080
  const b = body;
8888
9081
  if (Array.isArray(b.models)) {
8889
- return b.models.map((m) => ({ id: m.slug ?? "", name: m.title ?? m.name ?? m.slug ?? "", context_window: m.context_window })).filter((m) => m.id.length > 0);
9082
+ return b.models.map((m) => ({
9083
+ id: m.slug ?? "",
9084
+ name: m.title ?? m.name ?? m.slug ?? "",
9085
+ context_window: m.context_window,
9086
+ ...readCapabilityFlags(m)
9087
+ })).filter((m) => m.id.length > 0);
8890
9088
  }
8891
9089
  if (Array.isArray(b.data)) {
8892
- return b.data.map((m) => ({ id: m.id ?? "", name: m.name ?? m.id ?? "", context_window: m.context_window })).filter((m) => m.id.length > 0);
9090
+ return b.data.map((m) => ({
9091
+ id: m.id ?? "",
9092
+ name: m.name ?? m.id ?? "",
9093
+ context_window: m.context_window,
9094
+ ...readCapabilityFlags(m)
9095
+ })).filter((m) => m.id.length > 0);
8893
9096
  }
8894
9097
  return [];
8895
9098
  }
8896
- function buildDynamicOAuthModel(id, name, contextWindow, seedById) {
8897
- if (seedById.has(id)) return seedById.get(id);
9099
+ function buildDynamicOAuthModel(entry, seedById) {
9100
+ const seed = seedById.get(entry.id);
9101
+ if (seed) {
9102
+ return {
9103
+ ...seed,
9104
+ useResponsesLite: entry.useResponsesLite ?? seed.useResponsesLite,
9105
+ preferWebSockets: entry.preferWebSockets ?? seed.preferWebSockets
9106
+ };
9107
+ }
9108
+ const { id } = entry;
8898
9109
  const prefix = id.split("-")[0] ?? id;
8899
9110
  return {
8900
9111
  id,
8901
- name,
9112
+ name: entry.name,
8902
9113
  upstreamModelId: id,
8903
9114
  family: prefix,
8904
9115
  brand: deriveBrand(prefix),
8905
- contextWindow: contextWindow ?? resolveContextWindow(id),
9116
+ contextWindow: entry.context_window ?? resolveContextWindow(id),
8906
9117
  modelFormat: "openai",
8907
9118
  npm: "@ai-sdk/openai",
8908
- reasoning: modelPrefersResponsesApi(id)
9119
+ reasoning: modelPrefersResponsesApi(id),
9120
+ useResponsesLite: entry.useResponsesLite,
9121
+ preferWebSockets: entry.preferWebSockets
8909
9122
  };
8910
9123
  }
8911
9124
  async function fetchJsonWithAuth(url, accessToken, timeoutMs) {
@@ -8932,7 +9145,7 @@ async function fetchJsonWithAuth(url, accessToken, timeoutMs) {
8932
9145
  async function refreshOpenAiOAuthModels(accessToken) {
8933
9146
  const TIMEOUT_MS = 1e4;
8934
9147
  const seedById = new Map(buildOpenAiOAuthModels().map((m) => [m.id, m]));
8935
- const toModels = (entries) => entries.map(({ id, name, context_window }) => buildDynamicOAuthModel(id, name, context_window, seedById));
9148
+ const toModels = (entries) => entries.map((entry) => buildDynamicOAuthModel(entry, seedById));
8936
9149
  const claudeVersion = getInstalledClaudeVersion();
8937
9150
  const codexResult = await fetchJsonWithAuth(
8938
9151
  `https://chatgpt.com/backend-api/codex/models?client_version=${claudeVersion}`,
@@ -9268,7 +9481,9 @@ function modelToCached(model) {
9268
9481
  apiUrl: model.apiBaseUrl,
9269
9482
  supportedParameters: model.supportedParameters,
9270
9483
  reasoning: model.reasoning,
9271
- interleavedReasoningField: model.interleavedReasoningField
9484
+ interleavedReasoningField: model.interleavedReasoningField,
9485
+ useResponsesLite: model.useResponsesLite,
9486
+ preferWebSockets: model.preferWebSockets
9272
9487
  };
9273
9488
  }
9274
9489
  function localProviderToRegistry(provider, opts) {
@@ -10193,4 +10408,4 @@ export {
10193
10408
  quitClaudeAppGracefully,
10194
10409
  launchOrRestartClaudeApp
10195
10410
  };
10196
- //# sourceMappingURL=chunk-RTZ3X3KZ.js.map
10411
+ //# sourceMappingURL=chunk-VSXPAZX4.js.map