@wrongstack/providers 0.265.1 → 0.268.0

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/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { expectDefined, ProviderError, StreamHangError, safeParse, sanitizeJsonString, WrongStackError, ERROR_CODES } from '@wrongstack/core';
1
+ import { expectDefined, ProviderError, compactToolDefinitionForWire, StreamHangError, safeParse, sanitizeJsonString, WrongStackError, ERROR_CODES } from '@wrongstack/core';
2
2
  import { Readable } from 'stream';
3
3
  import { toErrorMessage } from '@wrongstack/core/utils';
4
4
  import { randomUUID } from 'crypto';
@@ -271,6 +271,13 @@ var init_aggregate = __esm({
271
271
 
272
272
  // src/anthropic.ts
273
273
  init_tool_input();
274
+
275
+ // src/object-utils.ts
276
+ function isPlainObject(value) {
277
+ return typeof value === "object" && value !== null && !Array.isArray(value);
278
+ }
279
+
280
+ // src/error-parse.ts
274
281
  function parseProviderHttpError(providerId, status, rawText) {
275
282
  const body = parseBody(rawText);
276
283
  const retryable = isRetryable(status, body.type);
@@ -288,9 +295,9 @@ function parseBody(rawText) {
288
295
  } catch {
289
296
  return body;
290
297
  }
291
- if (!isRecord(parsed)) return body;
298
+ if (!isPlainObject(parsed)) return body;
292
299
  const errField = parsed["error"];
293
- if (isRecord(errField)) {
300
+ if (isPlainObject(errField)) {
294
301
  const t = stringOf(errField["type"]) ?? stringOf(errField["status"]);
295
302
  const m = stringOf(errField["message"]);
296
303
  if (t) body.type = t;
@@ -317,9 +324,6 @@ function isRetryable(status, type) {
317
324
  if (type === "overloaded_error" || type === "rate_limit_error") return true;
318
325
  return false;
319
326
  }
320
- function isRecord(v) {
321
- return typeof v === "object" && v !== null && !Array.isArray(v);
322
- }
323
327
  function stringOf(v) {
324
328
  return typeof v === "string" && v.length > 0 ? v : void 0;
325
329
  }
@@ -362,6 +366,45 @@ var CAPABILITIES_BY_FAMILY = {
362
366
  maxContext: 0,
363
367
  cacheControl: "none"
364
368
  },
369
+ // Claude Pro/Max via OAuth (Sign in with Claude). Same wire as anthropic.
370
+ "anthropic-oauth": {
371
+ tools: true,
372
+ parallelTools: true,
373
+ vision: true,
374
+ streaming: true,
375
+ promptCache: true,
376
+ systemPrompt: true,
377
+ jsonMode: false,
378
+ reasoning: false,
379
+ maxContext: 2e5,
380
+ cacheControl: "native"
381
+ },
382
+ // GitHub Copilot subscription (OpenAI chat/completions-compatible wire).
383
+ "github-copilot": {
384
+ tools: true,
385
+ parallelTools: true,
386
+ vision: true,
387
+ streaming: true,
388
+ promptCache: false,
389
+ systemPrompt: true,
390
+ jsonMode: true,
391
+ reasoning: false,
392
+ maxContext: 128e3,
393
+ cacheControl: "auto"
394
+ },
395
+ // ChatGPT-backend Responses API (Sign in with ChatGPT / Codex subscription).
396
+ "openai-codex": {
397
+ tools: true,
398
+ parallelTools: true,
399
+ vision: true,
400
+ streaming: true,
401
+ promptCache: true,
402
+ systemPrompt: true,
403
+ jsonMode: false,
404
+ reasoning: true,
405
+ maxContext: 272e3,
406
+ cacheControl: "auto"
407
+ },
365
408
  google: {
366
409
  tools: true,
367
410
  parallelTools: true,
@@ -535,20 +578,18 @@ function normalizeGemini(stop) {
535
578
  return "end_turn";
536
579
  }
537
580
  }
538
-
539
- // src/tool-format/to-anthropic.ts
540
581
  var _cache = /* @__PURE__ */ new WeakMap();
541
582
  function toolsToAnthropic(tools) {
542
583
  const hit = _cache.get(tools);
543
584
  if (hit) return hit;
544
- const result = tools.map((t) => ({
545
- name: t.name,
546
- description: t.description,
547
- input_schema: t.inputSchema ?? {
548
- type: "object",
549
- properties: {}
550
- }
551
- }));
585
+ const result = tools.map((t) => {
586
+ const compact = compactToolDefinitionForWire(t);
587
+ return {
588
+ name: compact.name,
589
+ description: compact.description,
590
+ input_schema: compact.inputSchema
591
+ };
592
+ });
552
593
  _cache.set(tools, result);
553
594
  return result;
554
595
  }
@@ -682,7 +723,7 @@ var WireAdapter = class {
682
723
  if (this.streamHangTimeoutMs > 0) {
683
724
  sseBody = this.wrapWithHangDetection(sseBody, req.model);
684
725
  }
685
- yield* this.parseStream(sseBody, req.model);
726
+ yield* this.parseStream(sseBody, req.model, req);
686
727
  }
687
728
  /**
688
729
  * Wrap a readable stream body to log a compact status line per incoming
@@ -854,7 +895,12 @@ var AnthropicProvider = class extends WireAdapter {
854
895
  messages: req.messages.map((m) => this.normalizeMessage(m)),
855
896
  stream: true
856
897
  };
857
- if (req.system && req.system.length > 0) body["system"] = req.system;
898
+ if (req.system && req.system.length > 0) {
899
+ const systemBlocks = req.system;
900
+ body["system"] = systemBlocks.map(
901
+ (b, index) => req.cache?.ttl && index === systemBlocks.length - 1 ? { ...b, cache_control: { type: "ephemeral", ttl: req.cache.ttl } } : b
902
+ );
903
+ }
858
904
  if (req.tools && req.tools.length > 0) body["tools"] = toolsToAnthropic(req.tools);
859
905
  if (req.temperature !== void 0) body["temperature"] = req.temperature;
860
906
  if (req.topP !== void 0) body["top_p"] = req.topP;
@@ -862,20 +908,42 @@ var AnthropicProvider = class extends WireAdapter {
862
908
  if (req.toolChoice) body["tool_choice"] = req.toolChoice;
863
909
  return body;
864
910
  }
865
- parseStream(body, fallbackModel) {
866
- return parseAnthropicStream(body, fallbackModel);
911
+ parseStream(body, fallbackModel, req) {
912
+ return parseAnthropicStream(body, fallbackModel, req.cache?.ttl);
867
913
  }
868
914
  translateError(status, text) {
869
915
  return parseProviderHttpError(this.id, status, text);
870
916
  }
871
917
  normalizeMessage(m) {
872
- return {
873
- role: m.role === "system" ? "user" : m.role,
874
- content: typeof m.content === "string" ? m.content : m.content
875
- };
918
+ const role = m.role === "system" ? "user" : m.role;
919
+ if (typeof m.content === "string") return { role, content: m.content };
920
+ return { role, content: m.content.map((b) => sanitizeAnthropicBlock(b)) };
876
921
  }
877
922
  };
878
- async function* parseAnthropicStream(body, fallbackModel) {
923
+ function sanitizeAnthropicBlock(b) {
924
+ switch (b.type) {
925
+ case "text":
926
+ return b.cache_control ? { type: "text", text: b.text, cache_control: b.cache_control } : { type: "text", text: b.text };
927
+ case "tool_use":
928
+ return { type: "tool_use", id: b.id, name: b.name, input: b.input };
929
+ case "tool_result": {
930
+ const out = {
931
+ type: "tool_result",
932
+ tool_use_id: b.tool_use_id,
933
+ content: b.content
934
+ };
935
+ if (b.is_error) out["is_error"] = true;
936
+ return out;
937
+ }
938
+ case "thinking":
939
+ return b.signature ? { type: "thinking", thinking: b.thinking, signature: b.signature } : { type: "thinking", thinking: b.thinking };
940
+ case "image":
941
+ return { type: "image", source: b.source };
942
+ default:
943
+ return b;
944
+ }
945
+ }
946
+ async function* parseAnthropicStream(body, fallbackModel, cacheTtl) {
879
947
  const blocks = /* @__PURE__ */ new Map();
880
948
  let model = fallbackModel;
881
949
  let usage = { input: 0, output: 0 };
@@ -892,11 +960,14 @@ async function* parseAnthropicStream(body, fallbackModel) {
892
960
  case "message_start": {
893
961
  const message = ev["message"];
894
962
  if (message?.model) model = message.model;
963
+ const cacheWrite = message?.usage?.cache_creation_input_tokens;
895
964
  usage = {
896
965
  input: message?.usage?.input_tokens ?? 0,
897
966
  output: 0,
898
967
  cacheRead: message?.usage?.cache_read_input_tokens,
899
- cacheWrite: message?.usage?.cache_creation_input_tokens
968
+ cacheWrite,
969
+ cacheWrite5m: cacheTtl === "1h" ? void 0 : cacheWrite,
970
+ cacheWrite1h: cacheTtl === "1h" ? cacheWrite : void 0
900
971
  };
901
972
  if (!started) {
902
973
  started = true;
@@ -977,12 +1048,575 @@ async function* parseAnthropicStream(body, fallbackModel) {
977
1048
  yield { type: "message_stop", stopReason, usage };
978
1049
  }
979
1050
  }
980
- var DEFAULT_BASE2 = "https://generativelanguage.googleapis.com/v1beta";
1051
+ var CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
1052
+ var TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
1053
+ var DEFAULT_BASE2 = "https://api.anthropic.com";
1054
+ var ANTHROPIC_VERSION = "2023-06-01";
1055
+ var OAUTH_BETA = "claude-code-20250219,oauth-2025-04-20";
1056
+ var REFRESH_SKEW_MS = 6e4;
1057
+ var CLAUDE_CODE_VERSION = "2.1.75";
1058
+ var CLAUDE_CODE_SYSTEM_PROMPT = "You are Claude Code, Anthropic's official CLI for Claude.";
1059
+ var CLAUDE_CODE_TOOLS = [
1060
+ "Read",
1061
+ "Write",
1062
+ "Edit",
1063
+ "Bash",
1064
+ "Grep",
1065
+ "Glob",
1066
+ "AskUserQuestion",
1067
+ "EnterPlanMode",
1068
+ "ExitPlanMode",
1069
+ "KillShell",
1070
+ "NotebookEdit",
1071
+ "Skill",
1072
+ "Task",
1073
+ "TaskOutput",
1074
+ "TodoWrite",
1075
+ "WebFetch",
1076
+ "WebSearch"
1077
+ ];
1078
+ var CC_TOOL_BY_LOWER = new Map(CLAUDE_CODE_TOOLS.map((t) => [t.toLowerCase(), t]));
1079
+ function toClaudeCodeName(name) {
1080
+ return CC_TOOL_BY_LOWER.get(name.toLowerCase()) ?? name;
1081
+ }
1082
+ function fromClaudeCodeName(name, tools) {
1083
+ const lower = name.toLowerCase();
1084
+ const match = tools?.find((t) => t.name.toLowerCase() === lower);
1085
+ return match?.name ?? name;
1086
+ }
1087
+ async function refreshAnthropicOAuthToken(refreshToken, signal) {
1088
+ const res = await fetch(TOKEN_URL, {
1089
+ method: "POST",
1090
+ headers: { "content-type": "application/json", accept: "application/json" },
1091
+ body: JSON.stringify({
1092
+ grant_type: "refresh_token",
1093
+ client_id: CLIENT_ID,
1094
+ refresh_token: refreshToken
1095
+ }),
1096
+ signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(3e4)]) : AbortSignal.timeout(3e4)
1097
+ });
1098
+ if (!res.ok) {
1099
+ const text = await res.text().catch(() => "");
1100
+ throw new Error(`Claude token refresh failed (${res.status}): ${text || res.statusText}`);
1101
+ }
1102
+ const json = await res.json();
1103
+ if (!json?.access_token || !json.refresh_token || typeof json.expires_in !== "number") {
1104
+ throw new Error("Claude token refresh response missing fields");
1105
+ }
1106
+ return {
1107
+ access: json.access_token,
1108
+ refresh: json.refresh_token,
1109
+ expires: Date.now() + json.expires_in * 1e3
1110
+ };
1111
+ }
1112
+ var AnthropicOAuthProvider = class extends AnthropicProvider {
1113
+ id;
1114
+ capabilities;
1115
+ access;
1116
+ refresh;
1117
+ expiresAt;
1118
+ onRefresh;
1119
+ refreshFn;
1120
+ constructor(opts) {
1121
+ super({
1122
+ apiKey: opts.credentials.accessToken,
1123
+ baseUrl: opts.baseUrl ?? DEFAULT_BASE2,
1124
+ fetchImpl: opts.fetchImpl,
1125
+ streamOpts: opts.streamOpts
1126
+ });
1127
+ this.id = opts.id ?? "anthropic-oauth";
1128
+ this.capabilities = capabilitiesForFamily("anthropic-oauth");
1129
+ this.access = opts.credentials.accessToken;
1130
+ this.refresh = opts.credentials.refreshToken;
1131
+ this.expiresAt = opts.credentials.expiresAt;
1132
+ this.onRefresh = opts.onRefresh;
1133
+ this.refreshFn = opts.refreshFn ?? refreshAnthropicOAuthToken;
1134
+ }
1135
+ async *stream(req, opts) {
1136
+ await this.ensureFreshToken(opts.signal);
1137
+ try {
1138
+ yield* this.remapToolNames(super.stream(req, opts), req.tools);
1139
+ } catch (err) {
1140
+ if (err instanceof ProviderError && err.status === 401 && this.refresh) {
1141
+ await this.doRefresh(opts.signal);
1142
+ yield* this.remapToolNames(super.stream(req, opts), req.tools);
1143
+ return;
1144
+ }
1145
+ throw err;
1146
+ }
1147
+ }
1148
+ /** Map Claude-Code-cased tool_use names in the stream back to real names. */
1149
+ async *remapToolNames(events, tools) {
1150
+ for await (const ev of events) {
1151
+ if ((ev.type === "tool_use_start" || ev.type === "content_block_start") && typeof ev.name === "string") {
1152
+ yield { ...ev, name: fromClaudeCodeName(ev.name, tools) };
1153
+ } else {
1154
+ yield ev;
1155
+ }
1156
+ }
1157
+ }
1158
+ async ensureFreshToken(signal) {
1159
+ if (!this.refresh) return;
1160
+ if (this.expiresAt !== void 0 && Date.now() < this.expiresAt - REFRESH_SKEW_MS) return;
1161
+ await this.doRefresh(signal);
1162
+ }
1163
+ async doRefresh(signal) {
1164
+ if (!this.refresh) return;
1165
+ const t = await this.refreshFn(this.refresh, signal);
1166
+ this.access = t.access;
1167
+ this.refresh = t.refresh;
1168
+ this.expiresAt = t.expires;
1169
+ this.onRefresh?.({ accessToken: t.access, refreshToken: t.refresh, expiresAt: t.expires });
1170
+ }
1171
+ buildHeaders(_req) {
1172
+ return {
1173
+ "content-type": "application/json",
1174
+ accept: "text/event-stream",
1175
+ "anthropic-version": ANTHROPIC_VERSION,
1176
+ authorization: `Bearer ${this.access}`,
1177
+ "anthropic-beta": OAUTH_BETA,
1178
+ // Present as the official Claude Code CLI so the subscription backend
1179
+ // accepts the request and the client isn't trivially fingerprinted.
1180
+ "user-agent": `claude-cli/${CLAUDE_CODE_VERSION}`,
1181
+ "x-app": "cli",
1182
+ "anthropic-dangerous-direct-browser-access": "true"
1183
+ };
1184
+ }
1185
+ buildBody(req) {
1186
+ const body = super.buildBody(req);
1187
+ const existing = body["system"] ?? [];
1188
+ const alreadyLed = existing[0]?.text?.startsWith(CLAUDE_CODE_SYSTEM_PROMPT) === true;
1189
+ body["system"] = alreadyLed ? existing : [{ type: "text", text: CLAUDE_CODE_SYSTEM_PROMPT }, ...existing];
1190
+ const tools = body["tools"];
1191
+ if (Array.isArray(tools)) {
1192
+ for (const t of tools) {
1193
+ if (typeof t.name === "string") t.name = toClaudeCodeName(t.name);
1194
+ }
1195
+ }
1196
+ const messages = body["messages"];
1197
+ if (Array.isArray(messages)) {
1198
+ for (const m of messages) {
1199
+ if (!Array.isArray(m.content)) continue;
1200
+ for (const block of m.content) {
1201
+ if (block?.type === "tool_use" && typeof block.name === "string") {
1202
+ block.name = toClaudeCodeName(block.name);
1203
+ }
1204
+ }
1205
+ }
1206
+ }
1207
+ return body;
1208
+ }
1209
+ };
1210
+
1211
+ // src/openai.ts
1212
+ init_tool_input();
1213
+ var _cache2 = /* @__PURE__ */ new WeakMap();
1214
+ function toolsToOpenAI(tools) {
1215
+ const hit = _cache2.get(tools);
1216
+ if (hit) return hit;
1217
+ const result = tools.map((t) => {
1218
+ const compact = compactToolDefinitionForWire(t);
1219
+ return {
1220
+ type: "function",
1221
+ function: {
1222
+ name: compact.name,
1223
+ description: compact.description,
1224
+ parameters: compact.inputSchema
1225
+ }
1226
+ };
1227
+ });
1228
+ _cache2.set(tools, result);
1229
+ return result;
1230
+ }
1231
+ function messagesToOpenAI(system, messages, opts = {}) {
1232
+ const emptyContentMode = opts.emptyToolCallContent ?? "empty_string";
1233
+ const out = [];
1234
+ if (system && system.length > 0) {
1235
+ const sysText = system.map((b) => b.text).join("\n\n");
1236
+ if (opts.systemAsMessage) {
1237
+ out.push({ role: "user", content: sysText });
1238
+ } else {
1239
+ out.push({ role: "system", content: sysText });
1240
+ }
1241
+ }
1242
+ for (const msg of messages) {
1243
+ if (msg.role === "user") {
1244
+ const blocks = normalizeContent(msg.content);
1245
+ const toolResults = blocks.filter((b) => b.type === "tool_result");
1246
+ const others = blocks.filter((b) => b.type !== "tool_result");
1247
+ for (const r of toolResults) {
1248
+ const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
1249
+ out.push({
1250
+ role: "tool",
1251
+ tool_call_id: r.tool_use_id,
1252
+ content
1253
+ });
1254
+ }
1255
+ if (others.length > 0) {
1256
+ out.push({
1257
+ role: "user",
1258
+ content: opts.flattenContentToString ? blocksToString(others) : blocksToContentArray(others)
1259
+ });
1260
+ }
1261
+ } else if (msg.role === "assistant") {
1262
+ const blocks = normalizeContent(msg.content);
1263
+ const textBlocks = blocks.filter((b) => b.type === "text");
1264
+ const toolUses = blocks.filter((b) => b.type === "tool_use");
1265
+ const thinkingBlocks = blocks.filter((b) => b.type === "thinking");
1266
+ const text = textBlocks.map((b) => b.text).join("");
1267
+ const reasoning = thinkingBlocks.map((b) => b.thinking).filter((t) => t && t.length > 0).join("");
1268
+ const toolCalls = toolUses.map((u) => ({
1269
+ id: u.id,
1270
+ type: "function",
1271
+ function: { name: u.name, arguments: JSON.stringify(u.input) }
1272
+ }));
1273
+ const message = { role: "assistant" };
1274
+ if (toolCalls.length > 0) {
1275
+ message.tool_calls = toolCalls;
1276
+ if (text) {
1277
+ message.content = text;
1278
+ } else {
1279
+ message.content = emptyContentMode === "null" ? null : "";
1280
+ }
1281
+ } else {
1282
+ message.content = text;
1283
+ }
1284
+ if (reasoning.length > 0) {
1285
+ message.reasoning_content = reasoning;
1286
+ }
1287
+ out.push(message);
1288
+ }
1289
+ }
1290
+ return out;
1291
+ }
1292
+ function normalizeContent(content) {
1293
+ return typeof content === "string" ? [{ type: "text", text: content }] : content;
1294
+ }
1295
+ function blocksToString(blocks) {
1296
+ return blocks.map((b) => {
1297
+ if (b.type === "text") return b.text;
1298
+ if (b.type === "image") return "[image]";
1299
+ return "";
1300
+ }).join("");
1301
+ }
1302
+ function blocksToContentArray(blocks) {
1303
+ const hasImage = blocks.some((b) => b.type === "image");
1304
+ if (!hasImage) {
1305
+ return blocks.filter((b) => b.type === "text").map((b) => b.text).join("");
1306
+ }
1307
+ return blocks.map((b) => {
1308
+ if (b.type === "text") return { type: "text", text: b.text };
1309
+ if (b.type === "image") {
1310
+ const url = b.source.type === "url" ? b.source.url ?? "" : `data:${b.source.media_type ?? "image/png"};base64,${b.source.data ?? ""}`;
1311
+ return { type: "image_url", image_url: { url } };
1312
+ }
1313
+ return null;
1314
+ }).filter((c) => c !== null);
1315
+ }
1316
+
1317
+ // src/openai.ts
1318
+ var DEFAULT_BASE3 = "https://api.openai.com/v1";
1319
+ var OpenAIProvider = class extends WireAdapter {
1320
+ id;
1321
+ capabilities;
1322
+ opts;
1323
+ constructor(opts) {
1324
+ super(opts.apiKey, opts.baseUrl ?? DEFAULT_BASE3, opts.fetchImpl, opts.streamOpts);
1325
+ this.opts = opts;
1326
+ this.id = opts.id ?? "openai";
1327
+ this.capabilities = capabilitiesForFamily("openai", {
1328
+ parallelTools: !opts.quirks?.parallelToolsDisabled,
1329
+ systemPrompt: !opts.quirks?.systemAsMessage,
1330
+ ...opts.capabilities
1331
+ });
1332
+ }
1333
+ buildUrl(_req) {
1334
+ const base = this.baseUrl.replace(/\/+$/, "");
1335
+ if (/\/chat\/completions$/.test(base)) return base;
1336
+ if (/\/v\d+(\/[a-z0-9_-]+)*$/i.test(base)) return `${base}/chat/completions`;
1337
+ return `${base}/v1/chat/completions`;
1338
+ }
1339
+ buildHeaders(req) {
1340
+ const headers = {
1341
+ ...super.buildHeaders(req),
1342
+ authorization: `Bearer ${this.apiKey}`
1343
+ };
1344
+ if (this.opts.organization) {
1345
+ headers["openai-organization"] = this.opts.organization;
1346
+ }
1347
+ return headers;
1348
+ }
1349
+ /**
1350
+ * The request field used to cap output length. Real OpenAI deprecated
1351
+ * `max_tokens` and the newer model families (gpt-4o, o1/o3/o4) 400 on it —
1352
+ * they require `max_completion_tokens`. OpenAI-compatible endpoints that
1353
+ * still only accept `max_tokens` override this. See issue #10.
1354
+ */
1355
+ tokenLimitParam() {
1356
+ return "max_completion_tokens";
1357
+ }
1358
+ buildBody(req) {
1359
+ const body = {
1360
+ model: req.model,
1361
+ messages: messagesToOpenAI(this.stripCacheControl(req), req.messages, {
1362
+ ...this.opts.quirks
1363
+ }),
1364
+ [this.tokenLimitParam()]: req.maxTokens,
1365
+ stream: true,
1366
+ stream_options: { include_usage: true }
1367
+ };
1368
+ if (req.tools && req.tools.length > 0) {
1369
+ body["tools"] = toolsToOpenAI(req.tools);
1370
+ if (req.toolChoice) {
1371
+ if (typeof req.toolChoice === "string") {
1372
+ body["tool_choice"] = req.toolChoice === "required" ? "required" : req.toolChoice;
1373
+ } else {
1374
+ body["tool_choice"] = {
1375
+ type: "function",
1376
+ function: { name: req.toolChoice.name }
1377
+ };
1378
+ }
1379
+ }
1380
+ }
1381
+ if (req.temperature !== void 0) body["temperature"] = req.temperature;
1382
+ if (req.topP !== void 0) body["top_p"] = req.topP;
1383
+ if (req.stopSequences) body["stop"] = req.stopSequences;
1384
+ return body;
1385
+ }
1386
+ parseStream(body, fallbackModel) {
1387
+ return parseOpenAIStream(body, fallbackModel);
1388
+ }
1389
+ translateError(status, text) {
1390
+ return parseProviderHttpError(this.id, status, text);
1391
+ }
1392
+ stripCacheControl(req) {
1393
+ if (!req.system) return void 0;
1394
+ return req.system.map((b) => {
1395
+ const { cache_control: _cc, ...rest } = b;
1396
+ return rest;
1397
+ });
1398
+ }
1399
+ };
1400
+ async function* parseOpenAIStream(body, fallbackModel) {
1401
+ let model = fallbackModel;
1402
+ let usage = { input: 0, output: 0 };
1403
+ let stopReason = "end_turn";
1404
+ let started = false;
1405
+ let thinkingOpen = false;
1406
+ const toolByIndex = /* @__PURE__ */ new Map();
1407
+ for await (const msg of parseSSE(body)) {
1408
+ if (!msg.data || msg.data === "[DONE]") continue;
1409
+ const parsed = safeParse(msg.data);
1410
+ if (!parsed.ok || !parsed.value) continue;
1411
+ const obj = parsed.value;
1412
+ if (typeof obj["model"] === "string") model = obj["model"];
1413
+ if (!started) {
1414
+ started = true;
1415
+ yield { type: "message_start", model };
1416
+ }
1417
+ const choices = obj["choices"];
1418
+ const choice = choices?.[0];
1419
+ const reasoningDelta = typeof choice?.delta?.reasoning_content === "string" ? choice.delta.reasoning_content : typeof choice?.delta?.reasoning === "string" ? choice.delta.reasoning : void 0;
1420
+ if (reasoningDelta && reasoningDelta.length > 0) {
1421
+ if (!thinkingOpen) {
1422
+ thinkingOpen = true;
1423
+ yield { type: "thinking_start" };
1424
+ }
1425
+ yield { type: "thinking_delta", text: reasoningDelta };
1426
+ }
1427
+ if (choice?.delta?.content) {
1428
+ if (thinkingOpen) {
1429
+ thinkingOpen = false;
1430
+ yield { type: "thinking_stop" };
1431
+ }
1432
+ yield { type: "text_delta", text: choice.delta.content };
1433
+ }
1434
+ if (choice?.delta?.tool_calls) {
1435
+ if (thinkingOpen) {
1436
+ thinkingOpen = false;
1437
+ yield { type: "thinking_stop" };
1438
+ }
1439
+ for (const tc of choice.delta.tool_calls) {
1440
+ const idx = tc.index ?? 0;
1441
+ let entry = toolByIndex.get(idx);
1442
+ if (!entry) {
1443
+ entry = {
1444
+ id: tc.id,
1445
+ name: tc.function?.name,
1446
+ argBuf: "",
1447
+ emittedStart: false,
1448
+ emittedArgLength: 0
1449
+ };
1450
+ toolByIndex.set(idx, entry);
1451
+ } else {
1452
+ if (tc.id && !entry.id) entry.id = tc.id;
1453
+ if (tc.function?.name && !entry.name) entry.name = tc.function.name;
1454
+ }
1455
+ if (tc.function?.arguments) {
1456
+ entry.argBuf += tc.function.arguments;
1457
+ }
1458
+ if (!entry.emittedStart && entry.id && entry.name) {
1459
+ entry.emittedStart = true;
1460
+ yield { type: "tool_use_start", id: entry.id, name: entry.name };
1461
+ }
1462
+ if (entry.emittedStart && entry.id && entry.emittedArgLength < entry.argBuf.length) {
1463
+ const partial = entry.argBuf.slice(entry.emittedArgLength);
1464
+ entry.emittedArgLength = entry.argBuf.length;
1465
+ yield {
1466
+ type: "tool_use_input_delta",
1467
+ id: entry.id,
1468
+ partial
1469
+ };
1470
+ }
1471
+ }
1472
+ }
1473
+ if (choice?.finish_reason) {
1474
+ stopReason = normalizeOpenAI(choice.finish_reason);
1475
+ }
1476
+ const u = obj["usage"];
1477
+ if (u) {
1478
+ const hasDeepSeekCacheFields = u.prompt_cache_hit_tokens !== void 0 || u.prompt_cache_miss_tokens !== void 0;
1479
+ const cached = u.prompt_tokens_details?.cached_tokens ?? u.prompt_cache_hit_tokens ?? 0;
1480
+ const promptTotal = u.prompt_tokens ?? u.input_tokens ?? (hasDeepSeekCacheFields ? (u.prompt_cache_hit_tokens ?? 0) + (u.prompt_cache_miss_tokens ?? 0) : usage.input + cached);
1481
+ usage = {
1482
+ input: u.prompt_cache_miss_tokens ?? Math.max(0, promptTotal - cached),
1483
+ output: u.completion_tokens ?? usage.output,
1484
+ cacheRead: cached || usage.cacheRead
1485
+ };
1486
+ }
1487
+ }
1488
+ if (thinkingOpen) {
1489
+ yield { type: "thinking_stop" };
1490
+ }
1491
+ for (const entry of toolByIndex.values()) {
1492
+ if (!entry.name) continue;
1493
+ if (!entry.id) entry.id = `call_${randomUUID()}`;
1494
+ if (!entry.emittedStart) {
1495
+ yield { type: "tool_use_start", id: entry.id, name: entry.name };
1496
+ }
1497
+ const input = parseToolInput(entry.argBuf);
1498
+ yield { type: "tool_use_stop", id: entry.id, input };
1499
+ }
1500
+ if (started) {
1501
+ yield { type: "message_stop", stopReason, usage };
1502
+ }
1503
+ }
1504
+
1505
+ // src/github-copilot.ts
1506
+ var COPILOT_TOKEN_URL = "https://api.github.com/copilot_internal/v2/token";
1507
+ var COPILOT_API_VERSION = "2026-06-01";
1508
+ var COPILOT_HEADERS = {
1509
+ "User-Agent": "GitHubCopilotChat/0.35.0",
1510
+ "Editor-Version": "vscode/1.107.0",
1511
+ "Editor-Plugin-Version": "copilot-chat/0.35.0",
1512
+ "Copilot-Integration-Id": "vscode-chat"
1513
+ };
1514
+ var DEFAULT_API_BASE = "https://api.individual.githubcopilot.com";
1515
+ var REFRESH_SKEW_MS2 = 6e4;
1516
+ function copilotBaseUrlFromToken(token) {
1517
+ if (token) {
1518
+ const m = token.match(/proxy-ep=([^;]+)/);
1519
+ if (m?.[1]) return `https://${m[1].replace(/^proxy\./, "api.")}`;
1520
+ }
1521
+ return DEFAULT_API_BASE;
1522
+ }
1523
+ async function refreshCopilotToken(githubToken, signal) {
1524
+ const res = await fetch(COPILOT_TOKEN_URL, {
1525
+ headers: {
1526
+ accept: "application/json",
1527
+ authorization: `Bearer ${githubToken}`,
1528
+ ...COPILOT_HEADERS
1529
+ },
1530
+ signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(15e3)]) : AbortSignal.timeout(15e3)
1531
+ });
1532
+ if (!res.ok) {
1533
+ const text = await res.text().catch(() => "");
1534
+ throw new Error(`Copilot token request failed (${res.status}): ${text || res.statusText}`);
1535
+ }
1536
+ const json = await res.json();
1537
+ if (!json?.token || typeof json.expires_at !== "number") {
1538
+ throw new Error("Copilot token response missing fields");
1539
+ }
1540
+ return { token: json.token, expires: json.expires_at * 1e3 };
1541
+ }
1542
+ var GitHubCopilotProvider = class extends OpenAIProvider {
1543
+ capabilities;
1544
+ copilotToken;
1545
+ githubToken;
1546
+ expiresAt;
1547
+ apiBase;
1548
+ onRefresh;
1549
+ refreshFn;
1550
+ constructor(opts) {
1551
+ const apiBase = copilotBaseUrlFromToken(opts.credentials.copilotToken);
1552
+ super({
1553
+ // OpenAIProvider requires a non-empty apiKey; use a placeholder when the
1554
+ // Copilot token is empty (it will be minted before the first request).
1555
+ apiKey: opts.credentials.copilotToken || "pending",
1556
+ baseUrl: apiBase,
1557
+ id: opts.id ?? "github-copilot",
1558
+ fetchImpl: opts.fetchImpl,
1559
+ streamOpts: opts.streamOpts,
1560
+ capabilities: opts.capabilities
1561
+ });
1562
+ this.copilotToken = opts.credentials.copilotToken;
1563
+ this.githubToken = opts.credentials.githubToken;
1564
+ this.expiresAt = opts.credentials.expiresAt;
1565
+ this.apiBase = apiBase;
1566
+ this.onRefresh = opts.onRefresh;
1567
+ this.refreshFn = opts.refreshFn ?? refreshCopilotToken;
1568
+ this.capabilities = capabilitiesForFamily("github-copilot", { ...opts.capabilities });
1569
+ }
1570
+ async *stream(req, opts) {
1571
+ await this.ensureFreshToken(opts.signal);
1572
+ try {
1573
+ yield* super.stream(req, opts);
1574
+ } catch (err) {
1575
+ if (err instanceof ProviderError && err.status === 401 && this.githubToken) {
1576
+ await this.doRefresh(opts.signal);
1577
+ yield* super.stream(req, opts);
1578
+ return;
1579
+ }
1580
+ throw err;
1581
+ }
1582
+ }
1583
+ async ensureFreshToken(signal) {
1584
+ const stale = this.expiresAt === void 0 || Date.now() >= this.expiresAt - REFRESH_SKEW_MS2;
1585
+ if (!this.copilotToken || stale && this.githubToken) {
1586
+ await this.doRefresh(signal);
1587
+ }
1588
+ }
1589
+ async doRefresh(signal) {
1590
+ if (!this.githubToken) return;
1591
+ const t = await this.refreshFn(this.githubToken, signal);
1592
+ this.copilotToken = t.token;
1593
+ this.expiresAt = t.expires;
1594
+ this.apiBase = copilotBaseUrlFromToken(t.token);
1595
+ this.onRefresh?.({
1596
+ accessToken: t.token,
1597
+ refreshToken: this.githubToken,
1598
+ expiresAt: t.expires
1599
+ });
1600
+ }
1601
+ buildUrl(_req) {
1602
+ return `${this.apiBase.replace(/\/+$/, "")}/chat/completions`;
1603
+ }
1604
+ buildHeaders(_req) {
1605
+ return {
1606
+ "content-type": "application/json",
1607
+ accept: "text/event-stream",
1608
+ authorization: `Bearer ${this.copilotToken}`,
1609
+ "X-GitHub-Api-Version": COPILOT_API_VERSION,
1610
+ ...COPILOT_HEADERS
1611
+ };
1612
+ }
1613
+ };
1614
+ var DEFAULT_BASE4 = "https://generativelanguage.googleapis.com/v1beta";
981
1615
  var GoogleProvider = class extends WireAdapter {
982
1616
  id;
983
1617
  capabilities;
984
1618
  constructor(opts) {
985
- super(opts.apiKey, opts.baseUrl ?? DEFAULT_BASE2, opts.fetchImpl, opts.streamOpts);
1619
+ super(opts.apiKey, opts.baseUrl ?? DEFAULT_BASE4, opts.fetchImpl, opts.streamOpts);
986
1620
  this.id = opts.id ?? "google";
987
1621
  this.capabilities = capabilitiesForFamily("google", {
988
1622
  ...opts.capabilities
@@ -1027,14 +1661,17 @@ var GoogleProvider = class extends WireAdapter {
1027
1661
  }
1028
1662
  };
1029
1663
  function toolsToGemini(tools) {
1030
- return tools.map((t) => ({
1031
- name: t.name,
1032
- description: t.description,
1033
- parameters: sanitizeSchemaForGemini(t.inputSchema) ?? {
1034
- type: "object",
1035
- properties: {}
1036
- }
1037
- }));
1664
+ return tools.map((t) => {
1665
+ const compact = compactToolDefinitionForWire(t);
1666
+ return {
1667
+ name: compact.name,
1668
+ description: compact.description,
1669
+ parameters: sanitizeSchemaForGemini(compact.inputSchema) ?? {
1670
+ type: "object",
1671
+ properties: {}
1672
+ }
1673
+ };
1674
+ });
1038
1675
  }
1039
1676
  var GEMINI_ALLOWED_KEYS = /* @__PURE__ */ new Set([
1040
1677
  "type",
@@ -1197,301 +1834,356 @@ async function* parseGoogleStream(body, fallbackModel) {
1197
1834
  }
1198
1835
  }
1199
1836
 
1200
- // src/openai.ts
1837
+ // src/openai-codex.ts
1201
1838
  init_tool_input();
1202
-
1203
- // src/tool-format/to-openai.ts
1204
- var _cache2 = /* @__PURE__ */ new WeakMap();
1205
- function toolsToOpenAI(tools) {
1206
- const hit = _cache2.get(tools);
1839
+ var _toolCache = /* @__PURE__ */ new WeakMap();
1840
+ function toolsToResponses(tools) {
1841
+ const hit = _toolCache.get(tools);
1207
1842
  if (hit) return hit;
1208
- const result = tools.map((t) => ({
1209
- type: "function",
1210
- function: {
1211
- name: t.name,
1212
- description: t.description ?? "",
1213
- parameters: t.inputSchema ?? {
1214
- type: "object",
1215
- properties: {}
1216
- }
1217
- }
1218
- }));
1219
- _cache2.set(tools, result);
1843
+ const result = tools.map((t) => {
1844
+ const compact = compactToolDefinitionForWire(t);
1845
+ return {
1846
+ type: "function",
1847
+ name: compact.name,
1848
+ description: compact.description,
1849
+ parameters: compact.inputSchema,
1850
+ strict: false
1851
+ };
1852
+ });
1853
+ _toolCache.set(tools, result);
1220
1854
  return result;
1221
1855
  }
1222
- function messagesToOpenAI(system, messages, opts = {}) {
1223
- const emptyContentMode = opts.emptyToolCallContent ?? "empty_string";
1856
+ function normalizeContent2(content) {
1857
+ return typeof content === "string" ? [{ type: "text", text: content }] : content;
1858
+ }
1859
+ function imageUrl(b) {
1860
+ return b.source.type === "url" ? b.source.url ?? "" : `data:${b.source.media_type ?? "image/png"};base64,${b.source.data ?? ""}`;
1861
+ }
1862
+ function messagesToResponsesInput(messages) {
1224
1863
  const out = [];
1225
- if (system && system.length > 0) {
1226
- const sysText = system.map((b) => b.text).join("\n\n");
1227
- if (opts.systemAsMessage) {
1228
- out.push({ role: "user", content: sysText });
1229
- } else {
1230
- out.push({ role: "system", content: sysText });
1231
- }
1232
- }
1233
1864
  for (const msg of messages) {
1865
+ const blocks = normalizeContent2(msg.content);
1234
1866
  if (msg.role === "user") {
1235
- const blocks = normalizeContent(msg.content);
1236
1867
  const toolResults = blocks.filter((b) => b.type === "tool_result");
1237
- const others = blocks.filter((b) => b.type !== "tool_result");
1238
1868
  for (const r of toolResults) {
1239
- const content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
1240
1869
  out.push({
1241
- role: "tool",
1242
- tool_call_id: r.tool_use_id,
1243
- content
1244
- });
1245
- }
1246
- if (others.length > 0) {
1247
- out.push({
1248
- role: "user",
1249
- content: opts.flattenContentToString ? blocksToString(others) : blocksToContentArray(others)
1870
+ type: "function_call_output",
1871
+ call_id: r.tool_use_id,
1872
+ output: typeof r.content === "string" ? r.content : JSON.stringify(r.content)
1250
1873
  });
1251
1874
  }
1252
- } else if (msg.role === "assistant") {
1253
- const blocks = normalizeContent(msg.content);
1254
- const textBlocks = blocks.filter((b) => b.type === "text");
1255
- const toolUses = blocks.filter((b) => b.type === "tool_use");
1256
- const thinkingBlocks = blocks.filter((b) => b.type === "thinking");
1257
- const text = textBlocks.map((b) => b.text).join("");
1258
- const reasoning = thinkingBlocks.map((b) => b.thinking).filter((t) => t && t.length > 0).join("");
1259
- const toolCalls = toolUses.map((u) => ({
1260
- id: u.id,
1261
- type: "function",
1262
- function: { name: u.name, arguments: JSON.stringify(u.input) }
1263
- }));
1264
- const message = { role: "assistant" };
1265
- if (toolCalls.length > 0) {
1266
- message.tool_calls = toolCalls;
1267
- if (text) {
1268
- message.content = text;
1269
- } else {
1270
- message.content = emptyContentMode === "null" ? null : "";
1271
- }
1272
- } else {
1273
- message.content = text;
1875
+ const others = blocks.filter((b) => b.type !== "tool_result");
1876
+ if (others.length > 0) {
1877
+ const content = others.map((b) => {
1878
+ if (b.type === "text") return { type: "input_text", text: b.text };
1879
+ if (b.type === "image") {
1880
+ return { type: "input_image", detail: "auto", image_url: imageUrl(b) };
1881
+ }
1882
+ return null;
1883
+ }).filter((c) => c !== null);
1884
+ if (content.length > 0) out.push({ role: "user", content });
1274
1885
  }
1275
- if (reasoning.length > 0) {
1276
- message.reasoning_content = reasoning;
1886
+ } else if (msg.role === "assistant") {
1887
+ const textBlocks = blocks.filter((b) => b.type === "text");
1888
+ const toolUses = blocks.filter((b) => b.type === "tool_use");
1889
+ const text = textBlocks.map((b) => b.text).join("");
1890
+ if (text.length > 0) {
1891
+ out.push({
1892
+ type: "message",
1893
+ role: "assistant",
1894
+ content: [{ type: "output_text", text, annotations: [] }],
1895
+ status: "completed"
1896
+ });
1897
+ }
1898
+ for (const u of toolUses) {
1899
+ out.push({
1900
+ type: "function_call",
1901
+ call_id: u.id,
1902
+ name: u.name,
1903
+ arguments: JSON.stringify(u.input ?? {})
1904
+ });
1277
1905
  }
1278
- out.push(message);
1279
1906
  }
1280
1907
  }
1281
1908
  return out;
1282
1909
  }
1283
- function normalizeContent(content) {
1284
- return typeof content === "string" ? [{ type: "text", text: content }] : content;
1285
- }
1286
- function blocksToString(blocks) {
1287
- return blocks.map((b) => {
1288
- if (b.type === "text") return b.text;
1289
- if (b.type === "image") return "[image]";
1290
- return "";
1291
- }).join("");
1292
- }
1293
- function blocksToContentArray(blocks) {
1294
- const hasImage = blocks.some((b) => b.type === "image");
1295
- if (!hasImage) {
1296
- return blocks.filter((b) => b.type === "text").map((b) => b.text).join("");
1910
+
1911
+ // src/openai-codex.ts
1912
+ var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
1913
+ var TOKEN_URL2 = "https://auth.openai.com/oauth/token";
1914
+ var JWT_CLAIM_PATH = "https://api.openai.com/auth";
1915
+ var DEFAULT_CODEX_BASE = "https://chatgpt.com/backend-api";
1916
+ var REFRESH_SKEW_MS3 = 6e4;
1917
+ async function refreshCodexAccessToken(refreshToken, signal) {
1918
+ const res = await fetch(TOKEN_URL2, {
1919
+ method: "POST",
1920
+ headers: { "content-type": "application/x-www-form-urlencoded" },
1921
+ body: new URLSearchParams({
1922
+ grant_type: "refresh_token",
1923
+ client_id: CLIENT_ID2,
1924
+ refresh_token: refreshToken
1925
+ }).toString(),
1926
+ signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(3e4)]) : AbortSignal.timeout(3e4)
1927
+ });
1928
+ if (!res.ok) {
1929
+ const text = await res.text().catch(() => "");
1930
+ throw new Error(`Codex token refresh failed (${res.status}): ${text || res.statusText}`);
1297
1931
  }
1298
- return blocks.map((b) => {
1299
- if (b.type === "text") return { type: "text", text: b.text };
1300
- if (b.type === "image") {
1301
- const url = b.source.type === "url" ? b.source.url ?? "" : `data:${b.source.media_type ?? "image/png"};base64,${b.source.data ?? ""}`;
1302
- return { type: "image_url", image_url: { url } };
1303
- }
1932
+ const json = await res.json();
1933
+ if (!json?.access_token || !json.refresh_token || typeof json.expires_in !== "number") {
1934
+ throw new Error("Codex token refresh response missing fields");
1935
+ }
1936
+ return {
1937
+ access: json.access_token,
1938
+ refresh: json.refresh_token,
1939
+ expires: Date.now() + json.expires_in * 1e3
1940
+ };
1941
+ }
1942
+ function extractAccountId(token) {
1943
+ try {
1944
+ const parts = token.split(".");
1945
+ if (parts.length !== 3) return null;
1946
+ const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
1947
+ const auth = payload[JWT_CLAIM_PATH];
1948
+ const id = auth?.chatgpt_account_id;
1949
+ return typeof id === "string" && id.length > 0 ? id : null;
1950
+ } catch {
1304
1951
  return null;
1305
- }).filter((c) => c !== null);
1952
+ }
1306
1953
  }
1307
-
1308
- // src/openai.ts
1309
- var DEFAULT_BASE3 = "https://api.openai.com/v1";
1310
- var OpenAIProvider = class extends WireAdapter {
1954
+ var OpenAICodexProvider = class extends WireAdapter {
1311
1955
  id;
1312
1956
  capabilities;
1313
- opts;
1957
+ access;
1958
+ refresh;
1959
+ expiresAt;
1960
+ accountId;
1961
+ onRefresh;
1962
+ refreshFn;
1963
+ reasoningEffort;
1314
1964
  constructor(opts) {
1315
- super(opts.apiKey, opts.baseUrl ?? DEFAULT_BASE3, opts.fetchImpl, opts.streamOpts);
1316
- this.opts = opts;
1317
- this.id = opts.id ?? "openai";
1318
- this.capabilities = capabilitiesForFamily("openai", {
1319
- parallelTools: !opts.quirks?.parallelToolsDisabled,
1320
- systemPrompt: !opts.quirks?.systemAsMessage,
1321
- ...opts.capabilities
1965
+ super(
1966
+ opts.credentials.accessToken,
1967
+ opts.baseUrl ?? DEFAULT_CODEX_BASE,
1968
+ opts.fetchImpl,
1969
+ opts.streamOpts
1970
+ );
1971
+ this.id = opts.id ?? "openai-codex";
1972
+ this.access = opts.credentials.accessToken;
1973
+ this.refresh = opts.credentials.refreshToken;
1974
+ this.expiresAt = opts.credentials.expiresAt;
1975
+ this.accountId = opts.credentials.accountId ?? extractAccountId(this.access) ?? void 0;
1976
+ this.onRefresh = opts.onRefresh;
1977
+ this.refreshFn = opts.refreshFn ?? refreshCodexAccessToken;
1978
+ this.reasoningEffort = opts.reasoningEffort ?? "medium";
1979
+ this.capabilities = capabilitiesForFamily("openai-codex", { ...opts.capabilities });
1980
+ }
1981
+ async *stream(req, opts) {
1982
+ await this.ensureFreshToken(opts.signal);
1983
+ try {
1984
+ yield* super.stream(req, opts);
1985
+ } catch (err) {
1986
+ if (err instanceof ProviderError && err.status === 401 && this.refresh) {
1987
+ await this.doRefresh(opts.signal);
1988
+ yield* super.stream(req, opts);
1989
+ return;
1990
+ }
1991
+ throw err;
1992
+ }
1993
+ }
1994
+ async ensureFreshToken(signal) {
1995
+ if (!this.refresh) return;
1996
+ if (this.expiresAt !== void 0 && Date.now() < this.expiresAt - REFRESH_SKEW_MS3) return;
1997
+ await this.doRefresh(signal);
1998
+ }
1999
+ async doRefresh(signal) {
2000
+ if (!this.refresh) return;
2001
+ const t = await this.refreshFn(this.refresh, signal);
2002
+ this.access = t.access;
2003
+ this.refresh = t.refresh;
2004
+ this.expiresAt = t.expires;
2005
+ this.accountId = extractAccountId(t.access) ?? this.accountId;
2006
+ this.onRefresh?.({
2007
+ accessToken: t.access,
2008
+ refreshToken: t.refresh,
2009
+ expiresAt: t.expires,
2010
+ accountId: this.accountId
1322
2011
  });
1323
2012
  }
1324
2013
  buildUrl(_req) {
1325
- const base = this.baseUrl.replace(/\/+$/, "");
1326
- if (/\/chat\/completions$/.test(base)) return base;
1327
- if (/\/v\d+(\/[a-z0-9_-]+)*$/i.test(base)) return `${base}/chat/completions`;
1328
- return `${base}/v1/chat/completions`;
2014
+ return resolveCodexUrl(this.baseUrl);
1329
2015
  }
1330
- buildHeaders(req) {
2016
+ buildHeaders(_req) {
1331
2017
  const headers = {
1332
- ...super.buildHeaders(req),
1333
- authorization: `Bearer ${this.apiKey}`
2018
+ ...super.buildHeaders(_req),
2019
+ authorization: `Bearer ${this.access}`,
2020
+ originator: "wrongstack",
2021
+ "OpenAI-Beta": "responses=experimental"
1334
2022
  };
1335
- if (this.opts.organization) {
1336
- headers["openai-organization"] = this.opts.organization;
1337
- }
2023
+ if (this.accountId) headers["chatgpt-account-id"] = this.accountId;
1338
2024
  return headers;
1339
2025
  }
1340
- /**
1341
- * The request field used to cap output length. Real OpenAI deprecated
1342
- * `max_tokens` and the newer model families (gpt-4o, o1/o3/o4) 400 on it —
1343
- * they require `max_completion_tokens`. OpenAI-compatible endpoints that
1344
- * still only accept `max_tokens` override this. See issue #10.
1345
- */
1346
- tokenLimitParam() {
1347
- return "max_completion_tokens";
1348
- }
1349
2026
  buildBody(req) {
2027
+ const instructions = req.system && req.system.length > 0 ? req.system.map((b) => b.text).join("\n\n") : "You are a helpful assistant.";
1350
2028
  const body = {
1351
2029
  model: req.model,
1352
- messages: messagesToOpenAI(this.stripCacheControl(req), req.messages, {
1353
- ...this.opts.quirks
1354
- }),
1355
- [this.tokenLimitParam()]: req.maxTokens,
2030
+ // The ChatGPT Codex backend rejects `store: true` ("Store must be set to
2031
+ // false"). We send the full conversation as `input` each turn.
2032
+ store: false,
1356
2033
  stream: true,
1357
- stream_options: { include_usage: true }
2034
+ instructions,
2035
+ input: messagesToResponsesInput(req.messages),
2036
+ include: ["reasoning.encrypted_content"],
2037
+ parallel_tool_calls: true
1358
2038
  };
1359
2039
  if (req.tools && req.tools.length > 0) {
1360
- body["tools"] = toolsToOpenAI(req.tools);
1361
- if (req.toolChoice) {
1362
- if (typeof req.toolChoice === "string") {
1363
- body["tool_choice"] = req.toolChoice === "required" ? "required" : req.toolChoice;
1364
- } else {
1365
- body["tool_choice"] = {
1366
- type: "function",
1367
- function: { name: req.toolChoice.name }
1368
- };
1369
- }
1370
- }
2040
+ body["tools"] = toolsToResponses(req.tools);
2041
+ body["tool_choice"] = mapToolChoice(req.toolChoice);
1371
2042
  }
1372
2043
  if (req.temperature !== void 0) body["temperature"] = req.temperature;
1373
2044
  if (req.topP !== void 0) body["top_p"] = req.topP;
1374
- if (req.stopSequences) body["stop"] = req.stopSequences;
2045
+ if (this.reasoningEffort !== "none") {
2046
+ body["reasoning"] = { effort: this.reasoningEffort, summary: "auto" };
2047
+ }
1375
2048
  return body;
1376
2049
  }
1377
2050
  parseStream(body, fallbackModel) {
1378
- return parseOpenAIStream(body, fallbackModel);
2051
+ return parseCodexResponsesStream(body, fallbackModel);
1379
2052
  }
1380
2053
  translateError(status, text) {
1381
2054
  return parseProviderHttpError(this.id, status, text);
1382
2055
  }
1383
- stripCacheControl(req) {
1384
- if (!req.system) return void 0;
1385
- return req.system.map((b) => {
1386
- const { cache_control: _cc, ...rest } = b;
1387
- return rest;
1388
- });
1389
- }
1390
2056
  };
1391
- async function* parseOpenAIStream(body, fallbackModel) {
2057
+ function resolveCodexUrl(baseUrl) {
2058
+ const raw = baseUrl && baseUrl.trim().length > 0 ? baseUrl : DEFAULT_CODEX_BASE;
2059
+ const normalized = raw.replace(/\/+$/, "");
2060
+ if (normalized.endsWith("/codex/responses")) return normalized;
2061
+ if (normalized.endsWith("/codex")) return `${normalized}/responses`;
2062
+ return `${normalized}/codex/responses`;
2063
+ }
2064
+ function mapToolChoice(choice) {
2065
+ if (choice === void 0) return "auto";
2066
+ if (choice === "auto" || choice === "required" || choice === "none") return choice;
2067
+ return { type: "function", name: choice.name };
2068
+ }
2069
+ async function* parseCodexResponsesStream(body, fallbackModel) {
1392
2070
  let model = fallbackModel;
2071
+ let started = false;
1393
2072
  let usage = { input: 0, output: 0 };
1394
2073
  let stopReason = "end_turn";
1395
- let started = false;
1396
- let thinkingOpen = false;
1397
- const toolByIndex = /* @__PURE__ */ new Map();
2074
+ let sawToolUse = false;
2075
+ let toolCallId;
2076
+ let toolArgBuf = "";
2077
+ const ensureStart = () => {
2078
+ if (started) return void 0;
2079
+ started = true;
2080
+ return { type: "message_start", model };
2081
+ };
1398
2082
  for await (const msg of parseSSE(body)) {
1399
2083
  if (!msg.data || msg.data === "[DONE]") continue;
1400
2084
  const parsed = safeParse(msg.data);
1401
2085
  if (!parsed.ok || !parsed.value) continue;
1402
- const obj = parsed.value;
1403
- if (typeof obj["model"] === "string") model = obj["model"];
1404
- if (!started) {
1405
- started = true;
1406
- yield { type: "message_start", model };
1407
- }
1408
- const choices = obj["choices"];
1409
- const choice = choices?.[0];
1410
- const reasoningDelta = typeof choice?.delta?.reasoning_content === "string" ? choice.delta.reasoning_content : typeof choice?.delta?.reasoning === "string" ? choice.delta.reasoning : void 0;
1411
- if (reasoningDelta && reasoningDelta.length > 0) {
1412
- if (!thinkingOpen) {
1413
- thinkingOpen = true;
1414
- yield { type: "thinking_start" };
2086
+ const evt = parsed.value;
2087
+ const type = typeof evt["type"] === "string" ? evt["type"] : "";
2088
+ switch (type) {
2089
+ case "response.created":
2090
+ case "response.in_progress": {
2091
+ const resp = evt["response"];
2092
+ if (typeof resp?.model === "string") model = resp.model;
2093
+ const s = ensureStart();
2094
+ if (s) yield s;
2095
+ break;
1415
2096
  }
1416
- yield { type: "thinking_delta", text: reasoningDelta };
1417
- }
1418
- if (choice?.delta?.content) {
1419
- if (thinkingOpen) {
1420
- thinkingOpen = false;
1421
- yield { type: "thinking_stop" };
2097
+ case "response.output_item.added": {
2098
+ const s = ensureStart();
2099
+ if (s) yield s;
2100
+ const item = evt["item"];
2101
+ if (!item) break;
2102
+ if (item.type === "reasoning") {
2103
+ yield { type: "thinking_start" };
2104
+ } else if (item.type === "function_call") {
2105
+ toolCallId = item.call_id ?? item.id ?? `call_${Math.random().toString(36).slice(2)}`;
2106
+ toolArgBuf = item.arguments ?? "";
2107
+ sawToolUse = true;
2108
+ yield { type: "tool_use_start", id: toolCallId, name: item.name ?? "unknown" };
2109
+ if (toolArgBuf.length > 0) {
2110
+ yield { type: "tool_use_input_delta", id: toolCallId, partial: toolArgBuf };
2111
+ }
2112
+ }
2113
+ break;
1422
2114
  }
1423
- yield { type: "text_delta", text: choice.delta.content };
1424
- }
1425
- if (choice?.delta?.tool_calls) {
1426
- if (thinkingOpen) {
1427
- thinkingOpen = false;
1428
- yield { type: "thinking_stop" };
2115
+ case "response.output_text.delta":
2116
+ case "response.refusal.delta": {
2117
+ const delta = typeof evt["delta"] === "string" ? evt["delta"] : "";
2118
+ if (delta) yield { type: "text_delta", text: delta };
2119
+ break;
1429
2120
  }
1430
- for (const tc of choice.delta.tool_calls) {
1431
- const idx = tc.index ?? 0;
1432
- let entry = toolByIndex.get(idx);
1433
- if (!entry) {
1434
- entry = {
1435
- id: tc.id,
1436
- name: tc.function?.name,
1437
- argBuf: "",
1438
- emittedStart: false,
1439
- emittedArgLength: 0
1440
- };
1441
- toolByIndex.set(idx, entry);
1442
- } else {
1443
- if (tc.id && !entry.id) entry.id = tc.id;
1444
- if (tc.function?.name && !entry.name) entry.name = tc.function.name;
1445
- }
1446
- if (tc.function?.arguments) {
1447
- entry.argBuf += tc.function.arguments;
1448
- }
1449
- if (!entry.emittedStart && entry.id && entry.name) {
1450
- entry.emittedStart = true;
1451
- yield { type: "tool_use_start", id: entry.id, name: entry.name };
2121
+ case "response.reasoning_text.delta":
2122
+ case "response.reasoning_summary_text.delta": {
2123
+ const delta = typeof evt["delta"] === "string" ? evt["delta"] : "";
2124
+ if (delta) yield { type: "thinking_delta", text: delta };
2125
+ break;
2126
+ }
2127
+ case "response.function_call_arguments.delta": {
2128
+ const delta = typeof evt["delta"] === "string" ? evt["delta"] : "";
2129
+ if (toolCallId && delta) {
2130
+ toolArgBuf += delta;
2131
+ yield { type: "tool_use_input_delta", id: toolCallId, partial: delta };
1452
2132
  }
1453
- if (entry.emittedStart && entry.id && entry.emittedArgLength < entry.argBuf.length) {
1454
- const partial = entry.argBuf.slice(entry.emittedArgLength);
1455
- entry.emittedArgLength = entry.argBuf.length;
1456
- yield {
1457
- type: "tool_use_input_delta",
1458
- id: entry.id,
1459
- partial
1460
- };
2133
+ break;
2134
+ }
2135
+ case "response.function_call_arguments.done": {
2136
+ const args = typeof evt["arguments"] === "string" ? evt["arguments"] : void 0;
2137
+ if (args !== void 0) toolArgBuf = args;
2138
+ break;
2139
+ }
2140
+ case "response.output_item.done": {
2141
+ const item = evt["item"];
2142
+ if (!item) break;
2143
+ if (item.type === "reasoning") {
2144
+ yield { type: "thinking_stop" };
2145
+ } else if (item.type === "function_call") {
2146
+ const id = item.call_id ?? toolCallId ?? `call_${Math.random().toString(36).slice(2)}`;
2147
+ const raw = item.arguments && item.arguments.length > 0 ? item.arguments : toolArgBuf;
2148
+ yield { type: "tool_use_stop", id, input: parseToolInput(raw || "{}") };
2149
+ toolCallId = void 0;
2150
+ toolArgBuf = "";
1461
2151
  }
2152
+ break;
2153
+ }
2154
+ case "response.completed":
2155
+ case "response.incomplete": {
2156
+ const resp = evt["response"];
2157
+ if (resp?.usage) usage = normalizeUsage(resp.usage);
2158
+ stopReason = mapResponsesStatus(resp?.status, sawToolUse);
2159
+ break;
2160
+ }
2161
+ case "error":
2162
+ case "response.failed": {
2163
+ const message = evt["message"] ?? evt["response"]?.error?.message ?? "Codex response failed";
2164
+ throw new ProviderError(message, 502, true, "openai-codex", {
2165
+ body: { message }
2166
+ });
1462
2167
  }
1463
2168
  }
1464
- if (choice?.finish_reason) {
1465
- stopReason = normalizeOpenAI(choice.finish_reason);
1466
- }
1467
- const u = obj["usage"];
1468
- if (u) {
1469
- const hasDeepSeekCacheFields = u.prompt_cache_hit_tokens !== void 0 || u.prompt_cache_miss_tokens !== void 0;
1470
- const cached = u.prompt_tokens_details?.cached_tokens ?? u.prompt_cache_hit_tokens ?? 0;
1471
- const promptTotal = u.prompt_tokens ?? u.input_tokens ?? (hasDeepSeekCacheFields ? (u.prompt_cache_hit_tokens ?? 0) + (u.prompt_cache_miss_tokens ?? 0) : usage.input + cached);
1472
- usage = {
1473
- input: u.prompt_cache_miss_tokens ?? Math.max(0, promptTotal - cached),
1474
- output: u.completion_tokens ?? usage.output,
1475
- cacheRead: cached || usage.cacheRead
1476
- };
1477
- }
1478
- }
1479
- if (thinkingOpen) {
1480
- yield { type: "thinking_stop" };
1481
- }
1482
- for (const entry of toolByIndex.values()) {
1483
- if (!entry.name) continue;
1484
- if (!entry.id) entry.id = `call_${randomUUID()}`;
1485
- if (!entry.emittedStart) {
1486
- yield { type: "tool_use_start", id: entry.id, name: entry.name };
1487
- }
1488
- const input = parseToolInput(entry.argBuf);
1489
- yield { type: "tool_use_stop", id: entry.id, input };
1490
2169
  }
1491
2170
  if (started) {
1492
2171
  yield { type: "message_stop", stopReason, usage };
1493
2172
  }
1494
2173
  }
2174
+ function normalizeUsage(u) {
2175
+ const cached = u.input_tokens_details?.cached_tokens ?? 0;
2176
+ const total = u.input_tokens ?? 0;
2177
+ return {
2178
+ input: Math.max(0, total - cached),
2179
+ output: u.output_tokens ?? 0,
2180
+ cacheRead: cached || void 0
2181
+ };
2182
+ }
2183
+ function mapResponsesStatus(status, sawToolUse) {
2184
+ if (status === "incomplete") return "max_tokens";
2185
+ return sawToolUse ? "tool_use" : "end_turn";
2186
+ }
1495
2187
 
1496
2188
  // src/openai-compatible.ts
1497
2189
  var VALID_QUIRK_KEYS = /* @__PURE__ */ new Set([
@@ -1501,7 +2193,8 @@ var VALID_QUIRK_KEYS = /* @__PURE__ */ new Set([
1501
2193
  "preserveToolCallIds",
1502
2194
  "parallelToolsDisabled",
1503
2195
  "jsonArgumentsBuggy",
1504
- "emptyToolCallContent"
2196
+ "emptyToolCallContent",
2197
+ "thinkingParam"
1505
2198
  ]);
1506
2199
  function isCompatibilityQuirks(value) {
1507
2200
  if (value === void 0) return true;
@@ -1511,6 +2204,8 @@ function isCompatibilityQuirks(value) {
1511
2204
  if (!VALID_QUIRK_KEYS.has(key)) return false;
1512
2205
  if (key === "emptyToolCallContent") {
1513
2206
  if (v !== "null" && v !== "empty_string") return false;
2207
+ } else if (key === "thinkingParam") {
2208
+ if (v !== "zai-glm" && v !== "kimi-toggle" && v !== "always-on") return false;
1514
2209
  } else if (typeof v !== "boolean") {
1515
2210
  return false;
1516
2211
  }
@@ -1551,6 +2246,11 @@ var OpenAICompatibleProvider = class extends OpenAIProvider {
1551
2246
  tokenLimitParam() {
1552
2247
  return "max_tokens";
1553
2248
  }
2249
+ buildBody(req) {
2250
+ const body = super.buildBody(req);
2251
+ applyThinkingParams(body, req, this.opts.quirks?.thinkingParam);
2252
+ return body;
2253
+ }
1554
2254
  buildHeaders(req) {
1555
2255
  return {
1556
2256
  ...super.buildHeaders(req),
@@ -1558,6 +2258,36 @@ var OpenAICompatibleProvider = class extends OpenAIProvider {
1558
2258
  };
1559
2259
  }
1560
2260
  };
2261
+ function applyThinkingParams(body, req, mode) {
2262
+ if (!mode || !req.reasoning) return;
2263
+ if (mode === "always-on") {
2264
+ return;
2265
+ }
2266
+ if (req.reasoning.enabled === false) {
2267
+ body["thinking"] = { type: "disabled" };
2268
+ return;
2269
+ }
2270
+ if (mode === "kimi-toggle" && req.reasoning.enabled === true) {
2271
+ body["thinking"] = { type: "enabled" };
2272
+ }
2273
+ if (mode === "zai-glm" && req.reasoning.effort) {
2274
+ body["reasoning_effort"] = mapZaiReasoningEffort(req.reasoning.effort);
2275
+ }
2276
+ }
2277
+ function mapZaiReasoningEffort(effort) {
2278
+ switch (effort) {
2279
+ case "none":
2280
+ case "minimal":
2281
+ return "none";
2282
+ case "low":
2283
+ case "medium":
2284
+ return "high";
2285
+ case "xhigh":
2286
+ return "max";
2287
+ default:
2288
+ return effort;
2289
+ }
2290
+ }
1561
2291
 
1562
2292
  // src/wire-format.ts
1563
2293
  var WireFormatProvider = class extends WireAdapter {
@@ -2158,14 +2888,17 @@ function buildGenConfig(req) {
2158
2888
  return cfg;
2159
2889
  }
2160
2890
  function toolsToGemini2(tools) {
2161
- return tools.map((t) => ({
2162
- name: t.name,
2163
- description: t.description,
2164
- parameters: sanitizeSchemaForGemini2(t.inputSchema) ?? {
2165
- type: "object",
2166
- properties: {}
2167
- }
2168
- }));
2891
+ return tools.map((t) => {
2892
+ const compact = compactToolDefinitionForWire(t);
2893
+ return {
2894
+ name: compact.name,
2895
+ description: compact.description,
2896
+ parameters: sanitizeSchemaForGemini2(compact.inputSchema) ?? {
2897
+ type: "object",
2898
+ properties: {}
2899
+ }
2900
+ };
2901
+ });
2169
2902
  }
2170
2903
  var GEMINI_ALLOWED_KEYS2 = /* @__PURE__ */ new Set([
2171
2904
  "type",
@@ -2350,9 +3083,6 @@ function normalizeToolResultContent(raw, opts) {
2350
3083
  if (raw === void 0 || raw === null) return "";
2351
3084
  return JSON.stringify(raw);
2352
3085
  }
2353
- function isPlainObject(v) {
2354
- return typeof v === "object" && v !== null && !Array.isArray(v);
2355
- }
2356
3086
  function contentFromOpenAI(choice, opts = {}) {
2357
3087
  const out = [];
2358
3088
  const text = choice.message.content;
@@ -2419,6 +3149,11 @@ function parseToolArguments(raw, toolName, toolCallId, opts) {
2419
3149
  }
2420
3150
 
2421
3151
  // src/index.ts
3152
+ var _oauthPersist;
3153
+ function setOAuthTokenPersister(fn) {
3154
+ _oauthPersist = fn;
3155
+ }
3156
+ var setCodexTokenPersister = setOAuthTokenPersister;
2422
3157
  async function buildProviderFactoriesFromRegistry(opts) {
2423
3158
  const providers = await opts.registry.listProviders();
2424
3159
  const factories = [];
@@ -2459,6 +3194,13 @@ function resolveActiveKey(cfg) {
2459
3194
  }
2460
3195
  return cfg.apiKey && cfg.apiKey.length > 0 ? cfg.apiKey : void 0;
2461
3196
  }
3197
+ function resolveActiveKeyEntry(cfg) {
3198
+ if (Array.isArray(cfg.apiKeys) && cfg.apiKeys.length > 0) {
3199
+ const active = cfg.activeKey ? cfg.apiKeys.find((k) => k.label === cfg.activeKey) : void 0;
3200
+ return active ?? cfg.apiKeys[0];
3201
+ }
3202
+ return void 0;
3203
+ }
2462
3204
  function makeProvider(p, cfg) {
2463
3205
  const family = cfg.family ?? p.family;
2464
3206
  const envVars = cfg.envVars && cfg.envVars.length > 0 ? cfg.envVars : p.envVars;
@@ -2497,6 +3239,48 @@ function makeProvider(p, cfg) {
2497
3239
  headers: cfg.headers,
2498
3240
  quirks: validateQuirks(p.id, cfg.quirks)
2499
3241
  });
3242
+ case "openai-codex": {
3243
+ const entry = resolveActiveKeyEntry(cfg);
3244
+ const parsedExpiry = entry?.expiresAt ? Date.parse(entry.expiresAt) : Number.NaN;
3245
+ return new OpenAICodexProvider({
3246
+ id: p.id,
3247
+ baseUrl,
3248
+ credentials: {
3249
+ accessToken: expectDefined(apiKey),
3250
+ refreshToken: entry?.refreshToken,
3251
+ expiresAt: Number.isFinite(parsedExpiry) ? parsedExpiry : void 0,
3252
+ accountId: entry?.accountId
3253
+ },
3254
+ onRefresh: (creds) => _oauthPersist?.(p.id, creds)
3255
+ });
3256
+ }
3257
+ case "anthropic-oauth": {
3258
+ const entry = resolveActiveKeyEntry(cfg);
3259
+ const parsedExpiry = entry?.expiresAt ? Date.parse(entry.expiresAt) : Number.NaN;
3260
+ return new AnthropicOAuthProvider({
3261
+ id: p.id,
3262
+ baseUrl,
3263
+ credentials: {
3264
+ accessToken: expectDefined(apiKey),
3265
+ refreshToken: entry?.refreshToken,
3266
+ expiresAt: Number.isFinite(parsedExpiry) ? parsedExpiry : void 0
3267
+ },
3268
+ onRefresh: (creds) => _oauthPersist?.(p.id, creds)
3269
+ });
3270
+ }
3271
+ case "github-copilot": {
3272
+ const entry = resolveActiveKeyEntry(cfg);
3273
+ const parsedExpiry = entry?.expiresAt ? Date.parse(entry.expiresAt) : Number.NaN;
3274
+ return new GitHubCopilotProvider({
3275
+ id: p.id,
3276
+ credentials: {
3277
+ copilotToken: resolveActiveKey(cfg) ?? "",
3278
+ githubToken: entry?.refreshToken,
3279
+ expiresAt: Number.isFinite(parsedExpiry) ? parsedExpiry : void 0
3280
+ },
3281
+ onRefresh: (creds) => _oauthPersist?.(p.id, creds)
3282
+ });
3283
+ }
2500
3284
  case "google":
2501
3285
  return new GoogleProvider({ id: p.id, apiKey: expectDefined(apiKey), baseUrl });
2502
3286
  default:
@@ -2541,6 +3325,6 @@ function validateQuirks(providerId, quirks) {
2541
3325
  });
2542
3326
  }
2543
3327
 
2544
- export { AnthropicProvider, CAPABILITIES_BY_FAMILY, GoogleProvider, OpenAICompatibleProvider, OpenAIProvider, WireAdapter, WireFormatProvider, anthropicWireFormat, buildProviderFactoriesFromRegistry, capabilitiesFor, capabilitiesForFamily, contentFromAnthropic, contentFromOpenAI, createWireFormatFactory, defaultDebugStreamCallback, defineWireFormat, googleWireFormat, isDebugStreamEnabled, makeProviderFromConfig, messagesToOpenAI, mistralWireFormat, normalizeAnthropic, normalizeOpenAI, openaiWireFormat, parseProviderHttpError, pushDebugChunkStats, setDebugStreamCallback, setDebugStreamEnabled, toolsToAnthropic, toolsToOpenAI };
3328
+ export { AnthropicOAuthProvider, AnthropicProvider, CAPABILITIES_BY_FAMILY, CLAUDE_CODE_SYSTEM_PROMPT, GitHubCopilotProvider, GoogleProvider, OpenAICodexProvider, OpenAICompatibleProvider, OpenAIProvider, WireAdapter, WireFormatProvider, anthropicWireFormat, buildProviderFactoriesFromRegistry, capabilitiesFor, capabilitiesForFamily, contentFromAnthropic, contentFromOpenAI, copilotBaseUrlFromToken, createWireFormatFactory, defaultDebugStreamCallback, defineWireFormat, extractAccountId, googleWireFormat, isDebugStreamEnabled, makeProviderFromConfig, messagesToOpenAI, mistralWireFormat, normalizeAnthropic, normalizeOpenAI, openaiWireFormat, parseProviderHttpError, pushDebugChunkStats, refreshAnthropicOAuthToken, refreshCodexAccessToken, refreshCopilotToken, resolveCodexUrl, setCodexTokenPersister, setDebugStreamCallback, setDebugStreamEnabled, setOAuthTokenPersister, toolsToAnthropic, toolsToOpenAI };
2545
3329
  //# sourceMappingURL=index.js.map
2546
3330
  //# sourceMappingURL=index.js.map