@bman654/clodex 2.2.1 → 2.3.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/README.md CHANGED
@@ -275,6 +275,15 @@ clodex --version # version
275
275
  - Proxied routes forward configured provider headers for API-key and OAuth authentication. Anonymous routes preserve non-credential headers while removing authorization, API-key, cookie, token, secret, and credential-bearing header names before dispatch.
276
276
  - `CLODEX_CLAUDE_PATH` overrides Claude Code binary discovery.
277
277
  - **Outbound proxy:** when `HTTP_PROXY`/`HTTPS_PROXY` (and optionally `NO_PROXY`) are set in clodex's environment, all clodex-originated network calls honor them — OAuth sign-in and token refresh, model-list and models.dev refreshes, upstream OpenAI API calls, and the ChatGPT/Codex OAuth WebSocket transport (tunneled via HTTP CONNECT).
278
+ - **Upstream retries:** set `CLODEX_UPSTREAM_MAX_RETRIES` to an integer from
279
+ `0` through `5` to override the SDK's default of two retries for retryable
280
+ provider failures. `0` disables retries. The SDK honors valid
281
+ `retry-after`/`retry-after-ms` headers and otherwise uses exponential
282
+ backoff. Larger integers clamp to `5` with a one-time warning because a sixth
283
+ retry cannot complete before the translated streaming paths' 120-second
284
+ no-data timeout. Unset, empty, or malformed values preserve the default. A
285
+ stream that fails after output begins cannot be replayed safely and still
286
+ terminates the request.
278
287
 
279
288
  ## Known limitations
280
289
 
package/dist/cli.js CHANGED
@@ -218,7 +218,7 @@ import { join } from "path";
218
218
  // package.json
219
219
  var package_default = {
220
220
  name: "@bman654/clodex",
221
- version: "2.2.1",
221
+ version: "2.3.0",
222
222
  publishConfig: {
223
223
  access: "public"
224
224
  },
@@ -4237,6 +4237,17 @@ function sanitizeMessage(message) {
4237
4237
  return line;
4238
4238
  }
4239
4239
 
4240
+ // src/tool-input-sanitize.ts
4241
+ function sanitizeToolInput(input, requiredProps) {
4242
+ const out = /* @__PURE__ */ Object.create(null);
4243
+ for (const [k, v] of Object.entries(input)) {
4244
+ if (v === null) continue;
4245
+ if (Array.isArray(v) && v.length === 0 && !requiredProps?.has(k)) continue;
4246
+ out[k] = v;
4247
+ }
4248
+ return out;
4249
+ }
4250
+
4240
4251
  // src/oauth/responses-websocket.ts
4241
4252
  var RESPONSES_LITE_HEADER = "x-openai-internal-codex-responses-lite";
4242
4253
  var TERMINAL_EVENT_TYPES = /* @__PURE__ */ new Set(["response.completed", "response.failed", "response.incomplete"]);
@@ -4485,6 +4496,61 @@ function warnReasoningNormalizationGap(fields, log12) {
4485
4496
  } catch {
4486
4497
  }
4487
4498
  }
4499
+ function toolArgumentNormalizationGap(expected, actual, requiredProps) {
4500
+ if (conversationItemKind(expected) !== "function_call") return void 0;
4501
+ if (conversationItemKind(actual) !== "function_call") return void 0;
4502
+ const left = expected;
4503
+ const right = actual;
4504
+ const callId = left.call_id;
4505
+ if (typeof callId !== "string" || !callId || callId !== right.call_id) return void 0;
4506
+ if (typeof left.name !== "string" || left.name !== right.name) return void 0;
4507
+ if (canonicalJson(normalizeToolCallJson(left)) === canonicalJson(normalizeToolCallJson(right))) {
4508
+ return void 0;
4509
+ }
4510
+ const required = requiredProps().get(left.name);
4511
+ const stripped = (item) => {
4512
+ if (typeof item.arguments !== "string") return void 0;
4513
+ const raw = item.arguments.trim();
4514
+ try {
4515
+ const parsed = raw === "" ? {} : JSON.parse(raw);
4516
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
4517
+ return canonicalJson({
4518
+ ...normalizeToolCallJson(item),
4519
+ arguments: canonicalJson(sanitizeToolInput(parsed, required))
4520
+ });
4521
+ } catch {
4522
+ return void 0;
4523
+ }
4524
+ };
4525
+ const leftStripped = stripped(left);
4526
+ const rightStripped = stripped(right);
4527
+ return {
4528
+ tool: left.name,
4529
+ equalAfterStrip: leftStripped !== void 0 && leftStripped === rightStripped
4530
+ };
4531
+ }
4532
+ var warnedToolArgumentGaps = /* @__PURE__ */ new Set();
4533
+ var MAX_TOOL_ARGUMENT_GAP_WARNINGS = 3;
4534
+ function warnToolArgumentNormalizationGap(gap, log12) {
4535
+ const tool3 = typeof gap.tool === "string" ? gap.tool : "unknown";
4536
+ const signature = `${tool3}:filler`;
4537
+ const message = `clodex: warning: tool call "${tool3}" failed the continuation match, but both sides are identical once clodex's filler-strip rule is applied, so the head should have matched. Prompt caching is degraded for this turn \u2014 please report it, with the adapter debug log from --trace if you can, at https://github.com/bman654/clodex/issues`;
4538
+ try {
4539
+ log12?.(`tool argument normalization gap: ${signature}`);
4540
+ } catch {
4541
+ }
4542
+ if (warnedToolArgumentGaps.has(signature)) return;
4543
+ if (warnedToolArgumentGaps.size >= MAX_TOOL_ARGUMENT_GAP_WARNINGS) return;
4544
+ warnedToolArgumentGaps.add(signature);
4545
+ try {
4546
+ process.stderr.write(`${message}
4547
+ `);
4548
+ if (warnedToolArgumentGaps.size === MAX_TOOL_ARGUMENT_GAP_WARNINGS) {
4549
+ process.stderr.write("clodex: warning: further tool-argument normalization warnings suppressed.\n");
4550
+ }
4551
+ } catch {
4552
+ }
4553
+ }
4488
4554
  function continuationMismatchDetails(entry, payload, log12, warnOnGap = false) {
4489
4555
  const full = inputArray(payload);
4490
4556
  const prefix = [...entry.requestInput ?? [], ...entry.expectedAssistant ?? []];
@@ -4500,6 +4566,34 @@ function continuationMismatchDetails(entry, payload, log12, warnOnGap = false) {
4500
4566
  const actual = mismatch < full.length ? full[mismatch] : void 0;
4501
4567
  const reasoningGap = reasoningNormalizationGap(expected, actual);
4502
4568
  if (reasoningGap && warnOnGap) warnReasoningNormalizationGap(reasoningGap, log12);
4569
+ let gapExpected = expected;
4570
+ if (conversationItemKind(expected) === "reasoning" && conversationItemKind(actual) === "function_call") {
4571
+ for (let index = mismatch; index < prefix.length; index += 1) {
4572
+ if (conversationItemKind(prefix[index]) !== "reasoning") {
4573
+ gapExpected = prefix[index];
4574
+ break;
4575
+ }
4576
+ }
4577
+ }
4578
+ let toolArgumentGap;
4579
+ try {
4580
+ toolArgumentGap = toolArgumentNormalizationGap(
4581
+ gapExpected,
4582
+ actual,
4583
+ // The head's own schema when it has one; the current turn's tools are only a
4584
+ // fallback for a head that predates the snapshot (see headRequiredToolProps).
4585
+ () => entry.headRequiredToolProps ?? requiredToolProps(payload)
4586
+ );
4587
+ } catch {
4588
+ }
4589
+ if (toolArgumentGap?.equalAfterStrip === true) {
4590
+ if (warnOnGap) warnToolArgumentNormalizationGap(toolArgumentGap, log12);
4591
+ } else if (toolArgumentGap && warnOnGap) {
4592
+ try {
4593
+ log12?.(`tool argument mismatch beyond the strip rule: ${String(toolArgumentGap.tool)}`);
4594
+ } catch {
4595
+ }
4596
+ }
4503
4597
  return {
4504
4598
  fullItems: full.length,
4505
4599
  expectedPrefixItems: prefix.length,
@@ -4517,12 +4611,31 @@ function continuationMismatchDetails(entry, payload, log12, warnOnGap = false) {
4517
4611
  entry.expectedAssistant ?? [],
4518
4612
  mismatch
4519
4613
  )
4520
- } : {}
4614
+ } : {},
4615
+ ...toolArgumentGap ? { toolArgumentNormalizationGap: toolArgumentGap } : {}
4521
4616
  };
4522
4617
  }
4523
- function continuationMismatchSummary(entry, payload, log12) {
4524
- const details = continuationMismatchDetails(entry, payload, log12, true);
4525
- return `full_items=${details.fullItems} expected_prefix_items=${details.expectedPrefixItems} first_mismatch=${details.firstMismatch} expected=${details.expectedKind} actual=${details.actualKind}`;
4618
+ function continuationMismatchSummary(entry, payload, log12, mismatchDump = false, precomputedDetails) {
4619
+ const details = precomputedDetails ?? continuationMismatchDetails(entry, payload, log12, true);
4620
+ let summary = `full_items=${details.fullItems} expected_prefix_items=${details.expectedPrefixItems} first_mismatch=${details.firstMismatch} expected=${details.expectedKind} actual=${details.actualKind}`;
4621
+ if (details.expectedHash || details.actualHash) {
4622
+ summary += ` expected_hash=${details.expectedHash ?? "none"} actual_hash=${details.actualHash ?? "none"}`;
4623
+ if (mismatchDump && log12) {
4624
+ const full = inputArray(payload);
4625
+ const prefix = [...entry.requestInput ?? [], ...entry.expectedAssistant ?? []];
4626
+ const index = details.firstMismatch;
4627
+ log12(`mismatch dump expected[${index}]: ${mismatchDumpLine(prefix, index)}`);
4628
+ log12(`mismatch dump actual[${index}]: ${mismatchDumpLine(full, index)}`);
4629
+ }
4630
+ }
4631
+ return summary;
4632
+ }
4633
+ function mismatchDumpLine(items, index) {
4634
+ if (index >= items.length) return "(absent)";
4635
+ const line = canonicalJson(normalizeToolCallJson(items[index]));
4636
+ const max = 2e3;
4637
+ const marker = " [truncated]";
4638
+ return line.length <= max ? line : line.slice(0, max - marker.length) + marker;
4526
4639
  }
4527
4640
  function canonicalItemStrings(items) {
4528
4641
  return items.map((item) => canonicalJson(normalizeToolCallJson([item])));
@@ -4639,6 +4752,7 @@ function emitContextDiagnostic(entry, ctx, details) {
4639
4752
  retried: ctx.retried,
4640
4753
  frameCount: ctx.frameCount,
4641
4754
  emittedModelData: ctx.emittedModelData,
4755
+ emittedDownstreamData: ctx.emittedDownstreamData,
4642
4756
  responseIdReceived: Boolean(ctx.responseId),
4643
4757
  inFlightMs: entry.inFlightStartedAt === void 0 ? void 0 : Math.max(0, entry.options.now() - entry.inFlightStartedAt),
4644
4758
  ...details
@@ -4831,8 +4945,42 @@ function withoutEphemeralFields(item) {
4831
4945
  }
4832
4946
  return out;
4833
4947
  }
4948
+ function requiredToolProps(payload) {
4949
+ const map = /* @__PURE__ */ new Map();
4950
+ const add = (tool3) => {
4951
+ if (!tool3 || typeof tool3 !== "object") return;
4952
+ const record = tool3;
4953
+ if (record.type === "namespace" && Array.isArray(record.tools)) {
4954
+ for (const nested of record.tools) add(nested);
4955
+ return;
4956
+ }
4957
+ if (record.type !== "function" || typeof record.name !== "string") return;
4958
+ const parameters = record.parameters;
4959
+ const required = parameters && typeof parameters === "object" && Array.isArray(parameters.required) ? parameters.required : [];
4960
+ map.set(record.name, new Set(required.filter((p13) => typeof p13 === "string")));
4961
+ };
4962
+ if (Array.isArray(payload.tools)) for (const tool3 of payload.tools) add(tool3);
4963
+ return map;
4964
+ }
4965
+ function sanitizedCallArguments(item, requiredProps) {
4966
+ if (typeof item.arguments !== "string") return item;
4967
+ const raw = item.arguments.trim();
4968
+ let parsed;
4969
+ try {
4970
+ parsed = raw === "" ? {} : JSON.parse(raw);
4971
+ } catch {
4972
+ return item;
4973
+ }
4974
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return item;
4975
+ const required = requiredProps.get(typeof item.name === "string" ? item.name : "");
4976
+ return {
4977
+ ...item,
4978
+ arguments: JSON.stringify(sanitizeToolInput(parsed, required))
4979
+ };
4980
+ }
4834
4981
  function expectedAssistantItems(ctx) {
4835
4982
  const output = [];
4983
+ const requiredProps = requiredToolProps(ctx.originalPayload);
4836
4984
  for (const [, accumulator] of [...ctx.outputByIndex.entries()].sort(([left], [right]) => left - right)) {
4837
4985
  const done = accumulator.done ?? {};
4838
4986
  const type = accumulator.type ?? (typeof done.type === "string" ? done.type : void 0);
@@ -4847,7 +4995,11 @@ function expectedAssistantItems(ctx) {
4847
4995
  output.push({ ...withoutEphemeralFields(done), type: "reasoning", summary });
4848
4996
  continue;
4849
4997
  }
4850
- if (type === "function_call" || type === "custom_tool_call") {
4998
+ if (type === "function_call") {
4999
+ output.push({ ...sanitizedCallArguments(withoutEphemeralFields(done), requiredProps), type });
5000
+ continue;
5001
+ }
5002
+ if (type === "custom_tool_call") {
4851
5003
  output.push({ ...withoutEphemeralFields(done), type });
4852
5004
  }
4853
5005
  }
@@ -4855,6 +5007,7 @@ function expectedAssistantItems(ctx) {
4855
5007
  }
4856
5008
  function encodeSse(ctx, event) {
4857
5009
  if (ctx.closed) return;
5010
+ ctx.emittedDownstreamData = true;
4858
5011
  ctx.controller.enqueue(ctx.encoder.encode(`data: ${JSON.stringify(event)}
4859
5012
 
4860
5013
  `));
@@ -4906,12 +5059,12 @@ function failContext(entry, ctx, message, diagnosticDetails, statusCode, retryAf
4906
5059
  closeContext(ctx);
4907
5060
  }
4908
5061
  function retryTransportFailure(entry, ctx, diagnosticDetails) {
4909
- if (ctx.closed || entry.current !== ctx || ctx.retried || ctx.frameCount !== 0 || ctx.emittedModelData) {
5062
+ if (ctx.closed || entry.current !== ctx || ctx.retried || !transportReplaySafe(ctx)) {
4910
5063
  return false;
4911
5064
  }
4912
5065
  ctx.retried = true;
4913
5066
  ctx.transportRetryPending = true;
4914
- entry.debug("transport failed before any response frame; retrying once with full context");
5067
+ entry.debug("transport failed before downstream output; retrying once with full context");
4915
5068
  emitContextDiagnostic(entry, ctx, {
4916
5069
  event: "ws_transport_retry",
4917
5070
  outcome: "started",
@@ -4945,9 +5098,9 @@ function retryTransportFailure(entry, ctx, diagnosticDetails) {
4945
5098
  function handleTransportFailure(entry, ctx, message, diagnosticDetails) {
4946
5099
  if (retryTransportFailure(entry, ctx, diagnosticDetails)) return;
4947
5100
  if (ctx.closed || entry.current !== ctx) return;
4948
- if (ctx.retried && ctx.frameCount === 0 && !ctx.emittedModelData) {
5101
+ if (ctx.retried && ctx.transportRetryPending && transportReplaySafe(ctx)) {
4949
5102
  ctx.transportRetryPending = false;
4950
- entry.debug("transport retry exhausted before any response frame");
5103
+ entry.debug("transport retry exhausted before downstream output");
4951
5104
  emitContextDiagnostic(entry, ctx, {
4952
5105
  event: "ws_transport_retry",
4953
5106
  outcome: "exhausted",
@@ -5051,6 +5204,9 @@ function resetContextForRetry(ctx) {
5051
5204
  ctx.recentUpstreamEventTypes = [];
5052
5205
  ctx.emittedProtocolAnomalies.clear();
5053
5206
  }
5207
+ function transportReplaySafe(ctx) {
5208
+ return !ctx.emittedDownstreamData && !ctx.emittedModelData && ctx.outputByIndex.size === 0;
5209
+ }
5054
5210
  function handleSocketMessage(entry, data) {
5055
5211
  const ctx = entry.current;
5056
5212
  if (!ctx || ctx.closed) return;
@@ -5165,6 +5321,7 @@ function handleSocketMessage(entry, data) {
5165
5321
  entry.responseId = ctx.responseId;
5166
5322
  entry.requestInput = inputArray(ctx.originalPayload);
5167
5323
  entry.expectedAssistant = expectedAssistantItems(ctx);
5324
+ entry.headRequiredToolProps = requiredToolProps(ctx.originalPayload);
5168
5325
  entry.canonicalPrefix = void 0;
5169
5326
  entry.canonicalEchoablePrefix = void 0;
5170
5327
  entry.promptFieldHashes = ctx.promptFieldHashes;
@@ -5294,6 +5451,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
5294
5451
  } catch {
5295
5452
  }
5296
5453
  };
5454
+ const mismatchDump = process.env.CLODEX_MISMATCH_DUMP === "1";
5297
5455
  const resolvedOptions = {
5298
5456
  hardTtlMs: options.hardTtlMs ?? RESPONSES_WS_HARD_TTL_MS,
5299
5457
  idleTtlMs: options.idleTtlMs ?? RESPONSES_WS_IDLE_TTL_MS,
@@ -5349,6 +5507,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
5349
5507
  let persistent = Boolean(partitionKey);
5350
5508
  let promotedConnectionId;
5351
5509
  let decision;
5510
+ let candidateMismatchDetails;
5352
5511
  if (selected && selectedDelta) {
5353
5512
  sendPayload = { ...payload, input: selectedDelta, previous_response_id: selected.responseId };
5354
5513
  continued = true;
@@ -5371,8 +5530,23 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
5371
5530
  decision = "parallel_isolated";
5372
5531
  debug("parallel request using an isolated socket");
5373
5532
  } else if (diagnosticEntry) {
5533
+ const diagnosticMismatch = continuationMismatchDetails(diagnosticEntry, payload, debug, true);
5534
+ candidateMismatchDetails = /* @__PURE__ */ new Map([[diagnosticEntry, diagnosticMismatch]]);
5535
+ for (const candidate of candidates) {
5536
+ if (candidate === diagnosticEntry) continue;
5537
+ candidateMismatchDetails.set(
5538
+ candidate,
5539
+ continuationMismatchDetails(candidate, payload, debug, true)
5540
+ );
5541
+ }
5374
5542
  debug(
5375
- `history mismatch starting an additional chain; retained ${candidates.length} existing head(s) (${continuationMismatchSummary(diagnosticEntry, payload, debug)})`
5543
+ `history mismatch starting an additional chain; retained ${candidates.length} existing head(s) (${continuationMismatchSummary(
5544
+ diagnosticEntry,
5545
+ payload,
5546
+ debug,
5547
+ mismatchDump,
5548
+ diagnosticMismatch
5549
+ )})`
5376
5550
  );
5377
5551
  decision = "history_mismatch_new_head";
5378
5552
  } else if (partitionKey) {
@@ -5432,7 +5606,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
5432
5606
  ttlPausedMs: entry.ttlPausedMs,
5433
5607
  idleMs: Math.max(0, now - entry.lastUsedAt),
5434
5608
  promptChanges: changedPromptFields(entry.promptFieldHashes, promptFieldHashes),
5435
- mismatch: continuationMismatchDetails(entry, payload, debug)
5609
+ mismatch: candidateMismatchDetails?.get(entry) ?? continuationMismatchDetails(entry, payload, debug)
5436
5610
  })),
5437
5611
  evictions
5438
5612
  }, diagnosticCorrelation);
@@ -5452,6 +5626,7 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
5452
5626
  frameCount: 0,
5453
5627
  pendingEvents: [],
5454
5628
  emittedModelData: false,
5629
+ emittedDownstreamData: false,
5455
5630
  transportRetryPending: false,
5456
5631
  outputByIndex: /* @__PURE__ */ new Map(),
5457
5632
  outputIndexByItemId: /* @__PURE__ */ new Map(),
@@ -9814,6 +9989,41 @@ function resolveUpstreamTools(tools, messages) {
9814
9989
  return upstream;
9815
9990
  }
9816
9991
 
9992
+ // src/upstream-retry.ts
9993
+ var UPSTREAM_MAX_RETRIES_ENV = "CLODEX_UPSTREAM_MAX_RETRIES";
9994
+ var MAX_UPSTREAM_MAX_RETRIES = 5;
9995
+ var reportedValues = /* @__PURE__ */ new Set();
9996
+ function reportOnce(raw, message, warn) {
9997
+ if (reportedValues.has(raw)) return;
9998
+ reportedValues.add(raw);
9999
+ try {
10000
+ warn(message);
10001
+ } catch {
10002
+ }
10003
+ }
10004
+ function upstreamMaxRetries(env = process.env, warn = (message) => console.error(`clodex: ${message}`)) {
10005
+ const raw = env[UPSTREAM_MAX_RETRIES_ENV]?.trim();
10006
+ if (raw === void 0 || raw === "") return void 0;
10007
+ const value = Number(raw);
10008
+ if (!Number.isInteger(value) || value < 0) {
10009
+ reportOnce(
10010
+ raw,
10011
+ `ignoring ${UPSTREAM_MAX_RETRIES_ENV}=${raw} (expected a non-negative integer)`,
10012
+ warn
10013
+ );
10014
+ return void 0;
10015
+ }
10016
+ if (value > MAX_UPSTREAM_MAX_RETRIES) {
10017
+ reportOnce(
10018
+ raw,
10019
+ `clamping ${UPSTREAM_MAX_RETRIES_ENV}=${raw} to ${MAX_UPSTREAM_MAX_RETRIES} (higher values exceed the 120s streaming idle budget)`,
10020
+ warn
10021
+ );
10022
+ return MAX_UPSTREAM_MAX_RETRIES;
10023
+ }
10024
+ return value;
10025
+ }
10026
+
9817
10027
  // src/sdk-adapter.ts
9818
10028
  function sdkTranslationErrorSignature(error) {
9819
10029
  const message = error instanceof Error ? error.message : typeof error === "string" ? error : void 0;
@@ -9884,10 +10094,12 @@ function openAiCacheBreakpoint(block, enabled) {
9884
10094
  function translateTopLevelSystemForOpenAi(system) {
9885
10095
  if (!system) return [];
9886
10096
  if (typeof system === "string") {
9887
- return system.trim() ? [{ role: "system", content: system }] : [];
10097
+ const stripped = stripClaudeCodeBillingHeader(system);
10098
+ return stripped?.trim() ? [{ role: "system", content: stripped }] : [];
9888
10099
  }
9889
10100
  return system.flatMap((block) => {
9890
- const text4 = typeof block === "string" ? block : block.text ?? "";
10101
+ const raw = typeof block === "string" ? block : block.text ?? "";
10102
+ const text4 = stripClaudeCodeBillingHeader(raw) ?? "";
9891
10103
  if (!text4.trim()) return [];
9892
10104
  const cacheControl = typeof block === "string" ? void 0 : block.cache_control;
9893
10105
  return [{
@@ -10035,15 +10247,6 @@ function translateMessages(messages, npm, openAiPromptCacheBreakpoints = false)
10035
10247
  }
10036
10248
  return out;
10037
10249
  }
10038
- function sanitizeToolInput(input, requiredProps) {
10039
- const out = {};
10040
- for (const [k, v] of Object.entries(input)) {
10041
- if (v === null) continue;
10042
- if (Array.isArray(v) && v.length === 0 && !requiredProps?.has(k)) continue;
10043
- out[k] = v;
10044
- }
10045
- return out;
10046
- }
10047
10250
  function toolRequiredProps(tools) {
10048
10251
  const map = /* @__PURE__ */ new Map();
10049
10252
  for (const [name, t] of Object.entries(tools ?? {})) {
@@ -10082,7 +10285,7 @@ function isClaudeCodeStructuredOutputCompactRequest(body) {
10082
10285
  function translateRequest(body, npm, options) {
10083
10286
  const messages = body.messages ?? [];
10084
10287
  annotateToolNames(messages);
10085
- const baseSystem = systemToString(body.system, options?.openAiOAuth === true);
10288
+ const baseSystem = systemToString(body.system, true);
10086
10289
  const systemText = baseSystem?.trim() || (options?.openAiOAuth ? "You are a coding assistant." : void 0);
10087
10290
  const compactRequest = isClaudeCodeStructuredOutputCompactRequest(body);
10088
10291
  let upstreamTools = resolveUpstreamTools(
@@ -10373,6 +10576,7 @@ async function streamAnthropicResponse(model, params, modelId, write, log12, obs
10373
10576
  const result = streamText({
10374
10577
  model,
10375
10578
  ...params,
10579
+ maxRetries: upstreamMaxRetries(),
10376
10580
  abortSignal,
10377
10581
  onError: () => {
10378
10582
  }
@@ -10421,6 +10625,7 @@ async function generateAnthropicResponse(model, params, modelId, options) {
10421
10625
  const r = streamText({
10422
10626
  model,
10423
10627
  ...params,
10628
+ maxRetries: upstreamMaxRetries(),
10424
10629
  abortSignal,
10425
10630
  onError: () => {
10426
10631
  }
@@ -10477,6 +10682,7 @@ async function generateAnthropicResponse(model, params, modelId, options) {
10477
10682
  const r = await generateText({
10478
10683
  model,
10479
10684
  ...params,
10685
+ maxRetries: upstreamMaxRetries(),
10480
10686
  abortSignal: generateAbort.signal
10481
10687
  });
10482
10688
  ({ text: text4, toolCalls, finishReason, usage } = r);
@@ -11431,11 +11637,20 @@ async function collectOpenAiStream(stream) {
11431
11637
  async function generateOpenAiResponse(model, params, responseModelId, options) {
11432
11638
  let result;
11433
11639
  if (options?.forceStream) {
11434
- const { stream } = streamText2({ model, ...params, onError: () => {
11435
- } });
11640
+ const { stream } = streamText2({
11641
+ model,
11642
+ ...params,
11643
+ maxRetries: upstreamMaxRetries(),
11644
+ onError: () => {
11645
+ }
11646
+ });
11436
11647
  result = await collectOpenAiStream(stream);
11437
11648
  } else {
11438
- result = await generateText2({ model, ...params });
11649
+ result = await generateText2({
11650
+ model,
11651
+ ...params,
11652
+ maxRetries: upstreamMaxRetries()
11653
+ });
11439
11654
  }
11440
11655
  const message = { role: "assistant", content: result.text || null };
11441
11656
  if (result.toolCalls?.length) {
@@ -11459,7 +11674,11 @@ async function generateOpenAiResponse(model, params, responseModelId, options) {
11459
11674
  };
11460
11675
  }
11461
11676
  async function streamOpenAiResponse(model, params, responseModelId, onChunk) {
11462
- const { stream } = streamText2({ model, ...params });
11677
+ const { stream } = streamText2({
11678
+ model,
11679
+ ...params,
11680
+ maxRetries: upstreamMaxRetries()
11681
+ });
11463
11682
  const baseData = {
11464
11683
  id: `chatcmpl-${Date.now()}`,
11465
11684
  object: "chat.completion.chunk",