@eddyskywalker/dsh-chatgpt-subscription 0.12.4 → 0.12.6

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/lib/index.js CHANGED
@@ -791,7 +791,7 @@ function parseListing(payload) {
791
791
  function parseListingEntry$1(value) {
792
792
  const record = asRecord$10(value);
793
793
  if (record === void 0) return [];
794
- const id = asString$17(record.slug) ?? asString$17(record.id);
794
+ const id = asString$18(record.slug) ?? asString$18(record.id);
795
795
  if (id === void 0) return [];
796
796
  const contextWindow = asNumber$4(record.context_window) ?? asNumber$4(record.contextWindow);
797
797
  const modalities = parseModalities(record.input_modalities);
@@ -799,18 +799,18 @@ function parseListingEntry$1(value) {
799
799
  const fallback = CODEX_MODEL_CATALOG.find((entry) => entry.id === id);
800
800
  return [{
801
801
  id,
802
- name: asString$17(record.display_name) ?? asString$17(record.displayName) ?? fallback?.name ?? id,
802
+ name: asString$18(record.display_name) ?? asString$18(record.displayName) ?? fallback?.name ?? id,
803
803
  contextWindow: contextWindow !== void 0 && contextWindow > 0 ? contextWindow : null,
804
804
  inputModalities: modalities ?? (fallback ? [...fallback.inputModalities] : ["text"]),
805
805
  ...efforts !== null ? { reasoningEfforts: efforts } : {},
806
- defaultReasoningEffort: asString$17(record.default_reasoning_level) ?? fallback?.defaultReasoningEffort ?? null
806
+ defaultReasoningEffort: asString$18(record.default_reasoning_level) ?? fallback?.defaultReasoningEffort ?? null
807
807
  }];
808
808
  }
809
809
  function parseModalities(value) {
810
810
  if (!Array.isArray(value)) return null;
811
811
  const out = [];
812
812
  for (const item of value) {
813
- const name = asString$17(item);
813
+ const name = asString$18(item);
814
814
  if (name === "text" || name === "image") out.push(name);
815
815
  }
816
816
  return out.length > 0 ? out : null;
@@ -825,7 +825,7 @@ function parseEfforts(value) {
825
825
  if (!Array.isArray(value)) return null;
826
826
  const out = [];
827
827
  for (const item of value) {
828
- const effort = asString$17(item) ?? asString$17(asRecord$10(item)?.effort);
828
+ const effort = asString$18(item) ?? asString$18(asRecord$10(item)?.effort);
829
829
  if (effort !== void 0 && !out.includes(effort)) out.push(effort);
830
830
  }
831
831
  return out.length > 0 ? out : null;
@@ -843,7 +843,7 @@ function accountKeyFor$1(credentials) {
843
843
  function asRecord$10(value) {
844
844
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
845
845
  }
846
- function asString$17(value) {
846
+ function asString$18(value) {
847
847
  return typeof value === "string" && value !== "" ? value : void 0;
848
848
  }
849
849
  function asNumber$4(value) {
@@ -1085,6 +1085,22 @@ var WindowsDpapiTokenStore = class extends WindowsDpapiCredentialStore {
1085
1085
  super(path, parseStoredCredentials);
1086
1086
  }
1087
1087
  };
1088
+ /**
1089
+ * How long a helper may run before it is killed and the read fails.
1090
+ *
1091
+ * A healthy spawn costs ~200 ms (see the cache note on this class), so the guard
1092
+ * exists only for a child that never exits, and it was set at 10 s - fifty times
1093
+ * the healthy cost. That turned out to be too tight for one real environment: a
1094
+ * cold Windows runner whose freshly-installed dependency tree is being scanned
1095
+ * on first spawn, where the helper legitimately took longer than 10 s and the
1096
+ * kill turned a working credential read into `DPAPI helper timed out`.
1097
+ *
1098
+ * The guard is kept, and only its headroom widened: 30 s is still bounded, still
1099
+ * far above anything a warm machine needs, and a hung helper now blocks one
1100
+ * credential read for 30 s rather than 10 - a worse wait in a case that is already
1101
+ * a failure, in exchange for not failing a machine that is merely cold.
1102
+ */
1103
+ const POWERSHELL_HELPER_TIMEOUT_MS = 3e4;
1088
1104
  function runPowerShell(script, path, stdin) {
1089
1105
  return new Promise((resolve, reject) => {
1090
1106
  const child = spawn("powershell.exe", [
@@ -1110,7 +1126,7 @@ function runPowerShell(script, path, stdin) {
1110
1126
  const timer = setTimeout(() => {
1111
1127
  child.kill();
1112
1128
  reject(/* @__PURE__ */ new Error("DPAPI helper timed out"));
1113
- }, 1e4);
1129
+ }, POWERSHELL_HELPER_TIMEOUT_MS);
1114
1130
  child.stdout.setEncoding("utf8");
1115
1131
  child.stdout.on("data", (chunk) => {
1116
1132
  stdout += chunk;
@@ -3309,13 +3325,13 @@ function createCodexFetchProvider(options = {}) {
3309
3325
  //#region src/host/common/llm-compat.ts
3310
3326
  /** This package's kind in the harness message-source map. */
3311
3327
  const PLUGIN_MESSAGE_SOURCE_KIND = "dsh-chatgpt-subscription";
3312
- function isRecord$29(value) {
3328
+ function isRecord$30(value) {
3313
3329
  return typeof value === "object" && value !== null && !Array.isArray(value);
3314
3330
  }
3315
3331
  /** Read a message body's blocks, keeping every entry that carries a block tag. */
3316
3332
  function readBlocks(raw) {
3317
3333
  if (!Array.isArray(raw)) return [];
3318
- return raw.filter((block) => isRecord$29(block) && typeof block.type === "string");
3334
+ return raw.filter((block) => isRecord$30(block) && typeof block.type === "string");
3319
3335
  }
3320
3336
  /**
3321
3337
  * Normalize one harness message list into {@link Message}.
@@ -3330,10 +3346,10 @@ function readBlocks(raw) {
3330
3346
  function normalizeMessages(messages) {
3331
3347
  const normalized = [];
3332
3348
  for (const raw of messages ?? []) {
3333
- if (!isRecord$29(raw)) continue;
3349
+ if (!isRecord$30(raw)) continue;
3334
3350
  const content = readBlocks(raw.content);
3335
3351
  if (raw.role === "tool") {
3336
- const source = isRecord$29(raw.source) ? raw.source : void 0;
3352
+ const source = isRecord$30(raw.source) ? raw.source : void 0;
3337
3353
  const callId = String(raw.toolCallId ?? source?.callId ?? "");
3338
3354
  normalized.push({
3339
3355
  id: raw.id,
@@ -3355,7 +3371,7 @@ function normalizeMessages(messages) {
3355
3371
  id: raw.id,
3356
3372
  role: typeof raw.role === "string" ? raw.role : "user",
3357
3373
  content,
3358
- ...isRecord$29(raw.source) ? { source: raw.source } : {}
3374
+ ...isRecord$30(raw.source) ? { source: raw.source } : {}
3359
3375
  });
3360
3376
  }
3361
3377
  return normalized;
@@ -7055,7 +7071,7 @@ function field(value, name) {
7055
7071
  const candidate = value[name];
7056
7072
  return typeof candidate === "string" && candidate !== "" ? candidate : null;
7057
7073
  }
7058
- function isRecord$28(value) {
7074
+ function isRecord$29(value) {
7059
7075
  return typeof value === "object" && value !== null && !Array.isArray(value);
7060
7076
  }
7061
7077
  function readPreferencesUpdate(value, current) {
@@ -7089,7 +7105,7 @@ function readPreferencesUpdate(value, current) {
7089
7105
  patch.searchProvider = value.searchProvider;
7090
7106
  }
7091
7107
  if ("contextWindowOverrides" in value) {
7092
- if (!isRecord$28(value.contextWindowOverrides)) throw new PreferenceError("contextWindowOverrides must be an object.");
7108
+ if (!isRecord$29(value.contextWindowOverrides)) throw new PreferenceError("contextWindowOverrides must be an object.");
7093
7109
  const overrides = {};
7094
7110
  for (const [model, contextWindow] of Object.entries(value.contextWindowOverrides)) {
7095
7111
  if (!isCodexModelId(model)) throw new PreferenceError("Unknown Codex model for a context window override.");
@@ -8589,7 +8605,7 @@ const schemaFields = /* @__PURE__ */ new Set([
8589
8605
  "required",
8590
8606
  "propertyOrdering"
8591
8607
  ]);
8592
- function isRecord$27(value) {
8608
+ function isRecord$28(value) {
8593
8609
  return typeof value === "object" && value !== null && !Array.isArray(value);
8594
8610
  }
8595
8611
  function mergeSchemas(left, right) {
@@ -8597,7 +8613,7 @@ function mergeSchemas(left, right) {
8597
8613
  ...left,
8598
8614
  ...right
8599
8615
  };
8600
- if (isRecord$27(left.properties) && isRecord$27(right.properties)) merged.properties = {
8616
+ if (isRecord$28(left.properties) && isRecord$28(right.properties)) merged.properties = {
8601
8617
  ...left.properties,
8602
8618
  ...right.properties
8603
8619
  };
@@ -8633,9 +8649,9 @@ const mergedTypeKeys = /* @__PURE__ */ new Set([
8633
8649
  * model with strictly less than the schema it started from.
8634
8650
  */
8635
8651
  function describeBranch(branch) {
8636
- const type = typeof branch.type === "string" ? branch.type : isRecord$27(branch.properties) ? "object" : isRecord$27(branch.items) ? "array" : "value";
8652
+ const type = typeof branch.type === "string" ? branch.type : isRecord$28(branch.properties) ? "object" : isRecord$28(branch.items) ? "array" : "value";
8637
8653
  const details = [];
8638
- if (isRecord$27(branch.properties)) {
8654
+ if (isRecord$28(branch.properties)) {
8639
8655
  const names = Object.keys(branch.properties);
8640
8656
  if (names.length > 0) details.push(`{${names.join(",")}}`);
8641
8657
  }
@@ -8649,7 +8665,7 @@ function describeBranch(branch) {
8649
8665
  }
8650
8666
  /** How well one branch can stand in for a whole union; a named object shape wins. */
8651
8667
  function branchRank(branch) {
8652
- if (isRecord$27(branch.properties)) return 3;
8668
+ if (isRecord$28(branch.properties)) return 3;
8653
8669
  if (branch.type === "object") return 2;
8654
8670
  if (branch.type === "array") return 1;
8655
8671
  return 0;
@@ -8678,7 +8694,7 @@ function unionShape(branches) {
8678
8694
  shape: branches[0],
8679
8695
  folded: false
8680
8696
  };
8681
- if (new Set(branches.map((branch) => branch.type)).size === 1 && branches.every((branch) => !isRecord$27(branch.properties) && !isRecord$27(branch.items))) {
8697
+ if (new Set(branches.map((branch) => branch.type)).size === 1 && branches.every((branch) => !isRecord$28(branch.properties) && !isRecord$28(branch.items))) {
8682
8698
  const shape = { type: branches[0].type };
8683
8699
  if (branches.every((branch) => Array.isArray(branch.enum))) {
8684
8700
  const values = [...new Set(branches.flatMap((branch) => branch.enum))];
@@ -8715,7 +8731,7 @@ function foldOwnFields(node) {
8715
8731
  const out = {};
8716
8732
  for (const [key, value] of Object.entries(node)) {
8717
8733
  if (key === "anyOf" || key === "oneOf" || key === "allOf") continue;
8718
- if (key === "properties" && isRecord$27(value)) {
8734
+ if (key === "properties" && isRecord$28(value)) {
8719
8735
  out.properties = Object.fromEntries(Object.entries(value).map(([name, child]) => [name, foldSchemaUnions(child)]));
8720
8736
  continue;
8721
8737
  }
@@ -8744,15 +8760,15 @@ function foldOwnFields(node) {
8744
8760
  * argument the model sends anyway fails there, naming the actual problem.
8745
8761
  */
8746
8762
  function foldSchemaUnions(node) {
8747
- if (!isRecord$27(node)) return node;
8763
+ if (!isRecord$28(node)) return node;
8748
8764
  let own = foldOwnFields(node);
8749
8765
  if (Array.isArray(node.allOf)) for (const branch of node.allOf) {
8750
8766
  const folded = foldSchemaUnions(branch);
8751
- if (isRecord$27(folded)) own = mergeSchemas(own, folded);
8767
+ if (isRecord$28(folded)) own = mergeSchemas(own, folded);
8752
8768
  }
8753
8769
  const alternatives = Array.isArray(node.anyOf) ? node.anyOf : Array.isArray(node.oneOf) ? node.oneOf : [];
8754
8770
  if (alternatives.length === 0) return own;
8755
- const branches = alternatives.map((branch) => foldSchemaUnions(branch)).filter(isRecord$27);
8771
+ const branches = alternatives.map((branch) => foldSchemaUnions(branch)).filter(isRecord$28);
8756
8772
  if (branches.length === 0) return own;
8757
8773
  const shapes = branches.filter((branch) => branch.type !== "null");
8758
8774
  const acceptsNull = branches.some((branch) => branch.type === "null");
@@ -8768,7 +8784,7 @@ function foldSchemaUnions(node) {
8768
8784
  return merged;
8769
8785
  }
8770
8786
  function toAntigravityToolSchema(schema, options = {}) {
8771
- if (!isRecord$27(schema)) return schema;
8787
+ if (!isRecord$28(schema)) return schema;
8772
8788
  const root = schema;
8773
8789
  function resolveReference(reference) {
8774
8790
  let target = root;
@@ -8776,13 +8792,13 @@ function toAntigravityToolSchema(schema, options = {}) {
8776
8792
  const path = reference === "#" ? [] : reference.slice(2).split("/");
8777
8793
  for (const segment of path) {
8778
8794
  const key = segment.replace(/~1/g, "/").replace(/~0/g, "~");
8779
- target = isRecord$27(target) && Object.hasOwn(target, key) ? target[key] : void 0;
8795
+ target = isRecord$28(target) && Object.hasOwn(target, key) ? target[key] : void 0;
8780
8796
  }
8781
- if (!isRecord$27(target)) throw new LlmError(`Antigravity tool schema reference was not found: ${reference}`, "PROVIDER_ERROR");
8797
+ if (!isRecord$28(target)) throw new LlmError(`Antigravity tool schema reference was not found: ${reference}`, "PROVIDER_ERROR");
8782
8798
  return target;
8783
8799
  }
8784
8800
  function convert(node, references) {
8785
- if (!isRecord$27(node)) return {};
8801
+ if (!isRecord$28(node)) return {};
8786
8802
  let inherited = {};
8787
8803
  if (typeof node.$ref === "string") {
8788
8804
  if (references.has(node.$ref)) throw new LlmError(`Antigravity tool schema contains a recursive reference: ${node.$ref}`, "PROVIDER_ERROR");
@@ -8791,8 +8807,8 @@ function toAntigravityToolSchema(schema, options = {}) {
8791
8807
  if (Array.isArray(node.allOf)) for (const branch of node.allOf) inherited = mergeSchemas(inherited, convert(branch, references));
8792
8808
  const out = {};
8793
8809
  for (const [key, value] of Object.entries(node)) if (schemaFields.has(key)) out[key] = value;
8794
- if (isRecord$27(node.properties)) out.properties = Object.fromEntries(Object.entries(node.properties).map(([name, child]) => [name, convert(child, references)]));
8795
- if (isRecord$27(node.items)) out.items = convert(node.items, references);
8810
+ if (isRecord$28(node.properties)) out.properties = Object.fromEntries(Object.entries(node.properties).map(([name, child]) => [name, convert(child, references)]));
8811
+ if (isRecord$28(node.items)) out.items = convert(node.items, references);
8796
8812
  const alternatives = Array.isArray(node.anyOf) ? node.anyOf : node.oneOf;
8797
8813
  if (Array.isArray(alternatives)) out.anyOf = alternatives.map((child) => convert(child, references));
8798
8814
  if (Array.isArray(node.type)) {
@@ -8828,10 +8844,10 @@ let toolCallCounter = 0;
8828
8844
  function sanitizeText$5(text) {
8829
8845
  return text.replace(/\0/g, "");
8830
8846
  }
8831
- function isRecord$26(value) {
8847
+ function isRecord$27(value) {
8832
8848
  return typeof value === "object" && value !== null && !Array.isArray(value);
8833
8849
  }
8834
- function asString$16(value) {
8850
+ function asString$17(value) {
8835
8851
  return typeof value === "string" ? value : void 0;
8836
8852
  }
8837
8853
  function safeJsonParse$5(text) {
@@ -8848,25 +8864,25 @@ function toolCallIdNeeded(modelId, runtimeModel) {
8848
8864
  return modelId.startsWith("claude-") || modelId.startsWith("gpt-oss-") || runtimeModel.startsWith("claude-") || runtimeModel.startsWith("gpt-oss-");
8849
8865
  }
8850
8866
  function parseArguments$1(raw) {
8851
- if (isRecord$26(raw)) return raw;
8867
+ if (isRecord$27(raw)) return raw;
8852
8868
  if (raw === void 0 || raw === null || raw === "") return {};
8853
8869
  const parsed = typeof raw === "string" ? safeJsonParse$5(raw) : raw;
8854
- return isRecord$26(parsed) ? parsed : {};
8870
+ return isRecord$27(parsed) ? parsed : {};
8855
8871
  }
8856
8872
  const NO_RESOLVED_IMAGES$5 = /* @__PURE__ */ new Map();
8857
8873
  function attachmentOf$5(block) {
8858
8874
  const attachment = block.attachment;
8859
- if (!isRecord$26(attachment)) return void 0;
8875
+ if (!isRecord$27(attachment)) return void 0;
8860
8876
  return typeof attachment.attachmentId === "string" ? attachment : void 0;
8861
8877
  }
8862
8878
  function attachmentLabel$6(block) {
8863
- const attachment = isRecord$26(block.attachment) ? block.attachment : void 0;
8864
- return asString$16(attachment?.name) || asString$16(attachment?.attachmentId);
8879
+ const attachment = isRecord$27(block.attachment) ? block.attachment : void 0;
8880
+ return asString$17(attachment?.name) || asString$17(attachment?.attachmentId);
8865
8881
  }
8866
8882
  function collectImageRefs$4(content, refs) {
8867
8883
  if (!Array.isArray(content)) return;
8868
8884
  for (const block of content) {
8869
- if (!isRecord$26(block)) continue;
8885
+ if (!isRecord$27(block)) continue;
8870
8886
  if (block.type === "image") {
8871
8887
  const attachment = attachmentOf$5(block);
8872
8888
  if (attachment) refs.set(attachment.attachmentId, attachment);
@@ -8904,13 +8920,13 @@ function base64Length$4(bytes) {
8904
8920
  function requestImageBytes$4(block) {
8905
8921
  const attachment = attachmentOf$5(block);
8906
8922
  if (attachment) return base64Length$4(attachment.bytes);
8907
- const inline = asString$16(block.data) || asString$16(block.base64);
8923
+ const inline = asString$17(block.data) || asString$17(block.base64);
8908
8924
  return inline ? inline.length : void 0;
8909
8925
  }
8910
8926
  function collectRequestImageBytes$4(content, lengths) {
8911
8927
  if (!Array.isArray(content)) return;
8912
8928
  for (const block of content) {
8913
- if (!isRecord$26(block) || block.type !== "image") continue;
8929
+ if (!isRecord$27(block) || block.type !== "image") continue;
8914
8930
  const bytes = requestImageBytes$4(block);
8915
8931
  if (bytes !== void 0) lengths.push(bytes);
8916
8932
  }
@@ -8945,7 +8961,7 @@ function offloadOldestRequestImages$4(options) {
8945
8961
  if (remaining.count === 0 || !Array.isArray(message.content)) return message;
8946
8962
  let replaced = false;
8947
8963
  const content = message.content.map((block) => {
8948
- if (remaining.count === 0 || !isRecord$26(block) || block.type !== "image") return block;
8964
+ if (remaining.count === 0 || !isRecord$27(block) || block.type !== "image") return block;
8949
8965
  if (requestImageBytes$4(block) === void 0) return block;
8950
8966
  remaining.count -= 1;
8951
8967
  replaced = true;
@@ -9008,10 +9024,10 @@ function unavailableImageText$6(block) {
9008
9024
  return `[image unavailable: ${label ? `${label} could not be read` : "the image could not be read"}; ask the user to attach it again if the image is needed]`;
9009
9025
  }
9010
9026
  function imageBlockToPart(block, images) {
9011
- let data = asString$16(block.data) || asString$16(block.base64);
9012
- const source = isRecord$26(block.source) ? block.source : void 0;
9013
- if (!data && source) data = asString$16(source.data) || asString$16(source.base64);
9014
- let mimeType = asString$16(block.mimeType) || asString$16(block.mediaType) || (source ? asString$16(source.mimeType) || asString$16(source.mediaType) : void 0) || "image/png";
9027
+ let data = asString$17(block.data) || asString$17(block.base64);
9028
+ const source = isRecord$27(block.source) ? block.source : void 0;
9029
+ if (!data && source) data = asString$17(source.data) || asString$17(source.base64);
9030
+ let mimeType = asString$17(block.mimeType) || asString$17(block.mediaType) || (source ? asString$17(source.mimeType) || asString$17(source.mediaType) : void 0) || "image/png";
9015
9031
  if (data?.startsWith("data:")) {
9016
9032
  const match = data.match(/^data:([^;,]+);base64,(.*)$/s);
9017
9033
  if (match) {
@@ -9034,8 +9050,8 @@ function contentToUserParts(content, images) {
9034
9050
  if (typeof content === "string") return [{ text: sanitizeText$5(content) }];
9035
9051
  if (!Array.isArray(content)) return [];
9036
9052
  const parts = [];
9037
- for (const block of content) if (isRecord$26(block) && block.type === "text" && typeof block.text === "string") parts.push({ text: sanitizeText$5(block.text) });
9038
- else if (isRecord$26(block) && block.type === "image") {
9053
+ for (const block of content) if (isRecord$27(block) && block.type === "text" && typeof block.text === "string") parts.push({ text: sanitizeText$5(block.text) });
9054
+ else if (isRecord$27(block) && block.type === "image") {
9039
9055
  const img = imageBlockToPart(block, images);
9040
9056
  parts.push(img ?? { text: unavailableImageText$6(block) });
9041
9057
  }
@@ -9050,7 +9066,7 @@ function toolResultImageParts(blocks, images) {
9050
9066
  if (!Array.isArray(blocks)) return [];
9051
9067
  const parts = [];
9052
9068
  for (const block of blocks) {
9053
- if (!isRecord$26(block)) continue;
9069
+ if (!isRecord$27(block)) continue;
9054
9070
  if (block.type === "image") {
9055
9071
  parts.push(imageBlockToPart(block, images) ?? { text: unavailableImageText$6(block) });
9056
9072
  continue;
@@ -9062,7 +9078,7 @@ function toolResultImageParts(blocks, images) {
9062
9078
  function toolResultText$5(blocks) {
9063
9079
  if (!Array.isArray(blocks)) return "";
9064
9080
  return blocks.map((block) => {
9065
- if (!isRecord$26(block)) return "";
9081
+ if (!isRecord$27(block)) return "";
9066
9082
  if (block.type === "text" && typeof block.text === "string") return sanitizeText$5(block.text);
9067
9083
  if (block.type === "tool-result") return toolResultText$5(block.content);
9068
9084
  if (block.type === "image") {
@@ -9076,16 +9092,16 @@ function replayBlockFor$1(message, index) {
9076
9092
  const source = message.source;
9077
9093
  if (!source || source.kind !== "model" || source.provider !== "antigravity") return void 0;
9078
9094
  const state = source.replayState;
9079
- if (!isRecord$26(state)) return void 0;
9095
+ if (!isRecord$27(state)) return void 0;
9080
9096
  if (Array.isArray(state.blocks)) return state.blocks[index];
9081
- const resp = isRecord$26(state.response) ? state.response : void 0;
9097
+ const resp = isRecord$27(state.response) ? state.response : void 0;
9082
9098
  if (resp) {
9083
9099
  if (Array.isArray(resp.outputItems)) return resp.outputItems[index];
9084
9100
  if (Array.isArray(resp.blocks)) return resp.blocks[index];
9085
9101
  }
9086
9102
  }
9087
9103
  function thoughtSignature(part) {
9088
- return asString$16(part?.thoughtSignature) || asString$16(part?.thought_signature) || asString$16(part?.thinkingSignature) || asString$16(part?.textSignature);
9104
+ return asString$17(part?.thoughtSignature) || asString$17(part?.thought_signature) || asString$17(part?.thinkingSignature) || asString$17(part?.textSignature);
9089
9105
  }
9090
9106
  function replayPart(part) {
9091
9107
  const copy = { ...part };
@@ -9138,11 +9154,11 @@ function assistantParts(message, model, runtimeModel, toolCalls) {
9138
9154
  if (!Array.isArray(message.content)) return parts;
9139
9155
  for (let index = 0; index < message.content.length; index++) {
9140
9156
  const block = message.content[index];
9141
- if (!isRecord$26(block)) continue;
9157
+ if (!isRecord$27(block)) continue;
9142
9158
  if (block.type === "reasoning" && runtimeModel.startsWith("claude-") && (message.source?.kind !== "model" || message.source.provider !== "antigravity" || !("model" in message.source) || message.source.model !== model.id)) continue;
9143
9159
  const replay = replayBlockFor$1(message, index);
9144
- const originalParts = Array.isArray(replay?.parts) ? replay.parts.filter(isRecord$26) : [];
9145
- if ((block.type === "text" || block.type === "reasoning") && originalParts.length > 0 && originalParts.every((part) => !part.functionCall) && originalParts.map((part) => asString$16(part.text) || "").join("") === sanitizeText$5(String(block.text || ""))) {
9160
+ const originalParts = Array.isArray(replay?.parts) ? replay.parts.filter(isRecord$27) : [];
9161
+ if ((block.type === "text" || block.type === "reasoning") && originalParts.length > 0 && originalParts.every((part) => !part.functionCall) && originalParts.map((part) => asString$17(part.text) || "").join("") === sanitizeText$5(String(block.text || ""))) {
9146
9162
  parts.push(...originalParts.map(replayPart));
9147
9163
  continue;
9148
9164
  }
@@ -9162,8 +9178,8 @@ function assistantParts(message, model, runtimeModel, toolCalls) {
9162
9178
  } else if (block.type === "tool-call") {
9163
9179
  const toolId = String(block.id || "");
9164
9180
  const toolName = String(block.name || "");
9165
- const originalCall = originalParts.find((part) => isRecord$26(part.functionCall));
9166
- const wireId = asString$16((isRecord$26(originalCall?.functionCall) ? originalCall.functionCall : void 0)?.id) || (toolCallIdNeeded(model.id, runtimeModel) ? sanitizeToolCallId(toolId, toolName) : originalCall ? void 0 : toolId || void 0);
9181
+ const originalCall = originalParts.find((part) => isRecord$27(part.functionCall));
9182
+ const wireId = asString$17((isRecord$27(originalCall?.functionCall) ? originalCall.functionCall : void 0)?.id) || (toolCallIdNeeded(model.id, runtimeModel) ? sanitizeToolCallId(toolId, toolName) : originalCall ? void 0 : toolId || void 0);
9167
9183
  toolCalls.set(toolId, {
9168
9184
  name: toolName,
9169
9185
  id: wireId
@@ -9215,7 +9231,7 @@ function convertMessages(options, model, runtimeModel, images = NO_RESOLVED_IMAG
9215
9231
  continue;
9216
9232
  }
9217
9233
  const content = Array.isArray(message.content) ? message.content : [];
9218
- const userParts = contentToUserParts(content.filter((b) => !isRecord$26(b) || b.type !== "tool-result"), images);
9234
+ const userParts = contentToUserParts(content.filter((b) => !isRecord$27(b) || b.type !== "tool-result"), images);
9219
9235
  if (role === "system") {
9220
9236
  if (userParts.length) contents.push({
9221
9237
  role: GEMINI_ROLE.user,
@@ -9227,7 +9243,7 @@ function convertMessages(options, model, runtimeModel, images = NO_RESOLVED_IMAG
9227
9243
  role: GEMINI_ROLE.user,
9228
9244
  parts: userParts
9229
9245
  });
9230
- for (const b of content) if (isRecord$26(b) && b.type === "tool-result") pushToolResult(contents, b, toolCalls, model, runtimeModel, images);
9246
+ for (const b of content) if (isRecord$27(b) && b.type === "tool-result") pushToolResult(contents, b, toolCalls, model, runtimeModel, images);
9231
9247
  }
9232
9248
  return contents;
9233
9249
  }
@@ -9362,7 +9378,7 @@ const USAGE_FIELDS = [
9362
9378
  "totalTokenCount"
9363
9379
  ];
9364
9380
  function collectUsage(value, state) {
9365
- if (!isRecord$26(value)) return;
9381
+ if (!isRecord$27(value)) return;
9366
9382
  for (const key of USAGE_FIELDS) {
9367
9383
  const count = value[key];
9368
9384
  if (typeof count !== "number" || !Number.isSafeInteger(count) || count < 0) continue;
@@ -9392,17 +9408,17 @@ function processStreamLine$2(line, state) {
9392
9408
  }
9393
9409
  if (!json) return [];
9394
9410
  const chunk = safeJsonParse$5(json);
9395
- if (!isRecord$26(chunk)) return [];
9396
- const responseData = isRecord$26(chunk.response) ? chunk.response : chunk;
9397
- const error = isRecord$26(chunk.error) ? chunk.error : isRecord$26(responseData.error) ? responseData.error : void 0;
9398
- if (error !== void 0) throw new LlmError$1(`Antigravity stream error: ${asString$16(error.message) ?? "unknown error"}`, isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
9411
+ if (!isRecord$27(chunk)) return [];
9412
+ const responseData = isRecord$27(chunk.response) ? chunk.response : chunk;
9413
+ const error = isRecord$27(chunk.error) ? chunk.error : isRecord$27(responseData.error) ? responseData.error : void 0;
9414
+ if (error !== void 0) throw new LlmError$1(`Antigravity stream error: ${asString$17(error.message) ?? "unknown error"}`, isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
9399
9415
  const candidates = Array.isArray(responseData.candidates) ? responseData.candidates : [];
9400
- const candidate = isRecord$26(candidates[0]) ? candidates[0] : void 0;
9401
- const content = isRecord$26(candidate?.content) ? candidate.content : void 0;
9416
+ const candidate = isRecord$27(candidates[0]) ? candidates[0] : void 0;
9417
+ const content = isRecord$27(candidate?.content) ? candidate.content : void 0;
9402
9418
  const parts = Array.isArray(content?.parts) ? content.parts : [];
9403
9419
  const out = [];
9404
9420
  for (const part of parts) {
9405
- if (!isRecord$26(part)) continue;
9421
+ if (!isRecord$27(part)) continue;
9406
9422
  if (typeof part.text === "string" && part.text !== "") {
9407
9423
  const isThinking = Boolean(part.thought);
9408
9424
  const blockType = isThinking ? "reasoning" : "text";
@@ -9434,7 +9450,7 @@ function processStreamLine$2(line, state) {
9434
9450
  index: state.currentBlock.index,
9435
9451
  text: delta
9436
9452
  });
9437
- } else if (!isRecord$26(part.functionCall) && thoughtSignature(part)) {
9453
+ } else if (!isRecord$27(part.functionCall) && thoughtSignature(part)) {
9438
9454
  if (state.replayBlocks.length === 0) {
9439
9455
  const type = part.thought ? "reasoning" : "text";
9440
9456
  state.blocks.push({
@@ -9458,12 +9474,12 @@ function processStreamLine$2(line, state) {
9458
9474
  }
9459
9475
  state.replayBlocks[state.replayBlocks.length - 1].parts.push(replayPart(part));
9460
9476
  }
9461
- if (isRecord$26(part.functionCall)) {
9477
+ if (isRecord$27(part.functionCall)) {
9462
9478
  out.push(...closeCurrentBlock(state));
9463
9479
  const fc = part.functionCall;
9464
- const toolName = asString$16(fc.name) || "";
9465
- const toolId = asString$16(fc.id) || sanitizeToolCallId("", toolName);
9466
- const argsText = JSON.stringify(isRecord$26(fc.args) ? fc.args : {});
9480
+ const toolName = asString$17(fc.name) || "";
9481
+ const toolId = asString$17(fc.id) || sanitizeToolCallId("", toolName);
9482
+ const argsText = JSON.stringify(isRecord$27(fc.args) ? fc.args : {});
9467
9483
  const index = state.blocks.length;
9468
9484
  const block = {
9469
9485
  type: "tool-call",
@@ -9500,7 +9516,7 @@ function processStreamLine$2(line, state) {
9500
9516
  }
9501
9517
  collectUsage(chunk.usageMetadata, state);
9502
9518
  if (responseData !== chunk) collectUsage(responseData.usageMetadata, state);
9503
- const finishReason = asString$16(candidate?.finishReason) || asString$16(responseData.finishReason);
9519
+ const finishReason = asString$17(candidate?.finishReason) || asString$17(responseData.finishReason);
9504
9520
  if (finishReason) {
9505
9521
  state.finishReason = finishReason;
9506
9522
  out.push(...closeCurrentBlock(state));
@@ -11859,13 +11875,13 @@ function commandCodeHeaders(apiKey, extra = {}) {
11859
11875
  function timeoutSignal$3(signal, ms) {
11860
11876
  return signal ? AbortSignal.any([signal, AbortSignal.timeout(ms)]) : AbortSignal.timeout(ms);
11861
11877
  }
11862
- function isRecord$25(value) {
11878
+ function isRecord$26(value) {
11863
11879
  return typeof value === "object" && value !== null && !Array.isArray(value);
11864
11880
  }
11865
11881
  function asRecord$9(value) {
11866
- return isRecord$25(value) ? value : void 0;
11882
+ return isRecord$26(value) ? value : void 0;
11867
11883
  }
11868
- function asString$15(value) {
11884
+ function asString$16(value) {
11869
11885
  if (typeof value === "string" && value.trim() !== "") return value;
11870
11886
  if (typeof value === "number" && Number.isFinite(value)) return String(value);
11871
11887
  }
@@ -11878,7 +11894,7 @@ function asNumber$3(value) {
11878
11894
  }
11879
11895
  function firstString$1(record, keys) {
11880
11896
  for (const key of keys) {
11881
- const value = asString$15(record[key]);
11897
+ const value = asString$16(record[key]);
11882
11898
  if (value !== void 0) return value;
11883
11899
  }
11884
11900
  }
@@ -11907,7 +11923,7 @@ function deepValue(value, keys, depth = 0) {
11907
11923
  }
11908
11924
  return;
11909
11925
  }
11910
- if (!isRecord$25(value)) return void 0;
11926
+ if (!isRecord$26(value)) return void 0;
11911
11927
  for (const key of keys) if (value[key] !== void 0 && value[key] !== null) return value[key];
11912
11928
  for (const nested of Object.values(value)) {
11913
11929
  const hit = deepValue(nested, keys, depth + 1);
@@ -11921,7 +11937,7 @@ function collectRecords(value, keys, depth = 0, out = []) {
11921
11937
  for (const entry of value) collectRecords(entry, keys, depth + 1, out);
11922
11938
  return out;
11923
11939
  }
11924
- if (!isRecord$25(value)) return out;
11940
+ if (!isRecord$26(value)) return out;
11925
11941
  if (keys.some((key) => value[key] !== void 0)) out.push(value);
11926
11942
  for (const nested of Object.values(value)) collectRecords(nested, keys, depth + 1, out);
11927
11943
  return out;
@@ -12125,7 +12141,7 @@ function parseCreditBalances(payload, consumed = []) {
12125
12141
  /** Resolve the plan id the subscription or credits payload reports, when either does. */
12126
12142
  function parsePlanId(payloads) {
12127
12143
  for (const payload of payloads) {
12128
- const id = asString$15(deepValue(payload, [
12144
+ const id = asString$16(deepValue(payload, [
12129
12145
  "planId",
12130
12146
  "plan_id",
12131
12147
  "priceId",
@@ -12144,7 +12160,7 @@ function parsePlanId(payloads) {
12144
12160
  */
12145
12161
  function parseSubscriptionStatus(payload) {
12146
12162
  const root = asRecord$9(payload) ?? {};
12147
- return asString$15(deepValue(asRecord$9(root.data) ?? root, ["status"])) ?? null;
12163
+ return asString$16(deepValue(asRecord$9(root.data) ?? root, ["status"])) ?? null;
12148
12164
  }
12149
12165
  /** End of the current billing period, in Unix milliseconds. */
12150
12166
  function parseSubscriptionPeriodEnd(payload) {
@@ -12696,10 +12712,10 @@ function buildModelOptions$2(catalog, enabledModelIds, overrides) {
12696
12712
  *
12697
12713
  * https://commandcode.ai/blog/command-code-provider-api
12698
12714
  */
12699
- function isRecord$24(value) {
12715
+ function isRecord$25(value) {
12700
12716
  return typeof value === "object" && value !== null && !Array.isArray(value);
12701
12717
  }
12702
- function asString$14(value) {
12718
+ function asString$15(value) {
12703
12719
  return typeof value === "string" ? value : void 0;
12704
12720
  }
12705
12721
  function safeJsonParse$4(text) {
@@ -12736,17 +12752,17 @@ const SUPPORTED_IMAGE_MEDIA_TYPES$4 = /* @__PURE__ */ new Set([
12736
12752
  ]);
12737
12753
  function attachmentOf$4(block) {
12738
12754
  const attachment = block.attachment;
12739
- if (!isRecord$24(attachment)) return void 0;
12755
+ if (!isRecord$25(attachment)) return void 0;
12740
12756
  return typeof attachment.attachmentId === "string" ? attachment : void 0;
12741
12757
  }
12742
12758
  function attachmentLabel$5(block) {
12743
- const attachment = isRecord$24(block.attachment) ? block.attachment : void 0;
12744
- return asString$14(attachment?.name) || asString$14(attachment?.attachmentId);
12759
+ const attachment = isRecord$25(block.attachment) ? block.attachment : void 0;
12760
+ return asString$15(attachment?.name) || asString$15(attachment?.attachmentId);
12745
12761
  }
12746
12762
  function collectImageRefs$3(content, refs) {
12747
12763
  if (!Array.isArray(content)) return;
12748
12764
  for (const block of content) {
12749
- if (!isRecord$24(block)) continue;
12765
+ if (!isRecord$25(block)) continue;
12750
12766
  if (block.type === "image") {
12751
12767
  const attachment = attachmentOf$4(block);
12752
12768
  if (attachment) refs.set(attachment.attachmentId, attachment);
@@ -12761,13 +12777,13 @@ function base64Length$3(bytes) {
12761
12777
  function requestImageBytes$3(block) {
12762
12778
  const attachment = attachmentOf$4(block);
12763
12779
  if (attachment) return base64Length$3(attachment.bytes);
12764
- const inline = asString$14(block.data) || asString$14(block.base64);
12780
+ const inline = asString$15(block.data) || asString$15(block.base64);
12765
12781
  return inline ? inline.length : void 0;
12766
12782
  }
12767
12783
  function collectRequestImageBytes$3(content, lengths) {
12768
12784
  if (!Array.isArray(content)) return;
12769
12785
  for (const block of content) {
12770
- if (!isRecord$24(block) || block.type !== "image") continue;
12786
+ if (!isRecord$25(block) || block.type !== "image") continue;
12771
12787
  const bytes = requestImageBytes$3(block);
12772
12788
  if (bytes !== void 0) lengths.push(bytes);
12773
12789
  }
@@ -12794,7 +12810,7 @@ function offloadOldestRequestImages$3(options) {
12794
12810
  if (remaining.count === 0 || !Array.isArray(message.content)) return message;
12795
12811
  let replaced = false;
12796
12812
  const content = message.content.map((block) => {
12797
- if (remaining.count === 0 || !isRecord$24(block) || block.type !== "image") return block;
12813
+ if (remaining.count === 0 || !isRecord$25(block) || block.type !== "image") return block;
12798
12814
  if (requestImageBytes$3(block) === void 0) return block;
12799
12815
  remaining.count -= 1;
12800
12816
  replaced = true;
@@ -12847,10 +12863,10 @@ function unavailableImageText$5(block) {
12847
12863
  return `[image unavailable: ${label ? `${label} could not be read` : "the image could not be read"}; ask the user to attach it again if the image is needed]`;
12848
12864
  }
12849
12865
  function imageBlockToInline$3(block, images) {
12850
- let data = asString$14(block.data) || asString$14(block.base64);
12851
- const source = isRecord$24(block.source) ? block.source : void 0;
12852
- if (!data && source) data = asString$14(source.data) || asString$14(source.base64);
12853
- let mediaType = asString$14(block.mimeType) || asString$14(block.mediaType) || (source ? asString$14(source.mimeType) || asString$14(source.mediaType) : void 0) || "image/png";
12866
+ let data = asString$15(block.data) || asString$15(block.base64);
12867
+ const source = isRecord$25(block.source) ? block.source : void 0;
12868
+ if (!data && source) data = asString$15(source.data) || asString$15(source.base64);
12869
+ let mediaType = asString$15(block.mimeType) || asString$15(block.mediaType) || (source ? asString$15(source.mimeType) || asString$15(source.mediaType) : void 0) || "image/png";
12854
12870
  if (data?.startsWith("data:")) {
12855
12871
  const matched = data.match(/^data:([^;,]+);base64,(.*)$/s);
12856
12872
  if (matched) {
@@ -12874,7 +12890,7 @@ function textOf$5(content) {
12874
12890
  if (!Array.isArray(content)) return "";
12875
12891
  const parts = [];
12876
12892
  for (const block of content) {
12877
- if (!isRecord$24(block)) continue;
12893
+ if (!isRecord$25(block)) continue;
12878
12894
  if (block.type === "text" && typeof block.text === "string") parts.push(sanitizeText$4(block.text));
12879
12895
  else if (block.type === "tool-result") parts.push(textOf$5(block.content));
12880
12896
  }
@@ -12883,7 +12899,7 @@ function textOf$5(content) {
12883
12899
  function toolResultText$4(blocks) {
12884
12900
  if (!Array.isArray(blocks)) return "";
12885
12901
  return blocks.map((block) => {
12886
- if (!isRecord$24(block)) return "";
12902
+ if (!isRecord$25(block)) return "";
12887
12903
  if (block.type === "text" && typeof block.text === "string") return sanitizeText$4(block.text);
12888
12904
  if (block.type === "tool-result") return toolResultText$4(block.content);
12889
12905
  if (block.type === "image") return `[image: ${attachmentLabel$5(block) ?? "attached image"}]`;
@@ -12901,7 +12917,7 @@ function toolResultBlocks$2(blocks, images) {
12901
12917
  const out = [];
12902
12918
  let hasImage = false;
12903
12919
  for (const block of blocks) {
12904
- if (!isRecord$24(block)) continue;
12920
+ if (!isRecord$25(block)) continue;
12905
12921
  if (block.type === "text" && typeof block.text === "string") {
12906
12922
  out.push({
12907
12923
  type: "text",
@@ -12950,7 +12966,7 @@ function toolResultImageBlocks$2(blocks, images) {
12950
12966
  if (!Array.isArray(blocks)) return [];
12951
12967
  const out = [];
12952
12968
  for (const block of blocks) {
12953
- if (!isRecord$24(block)) continue;
12969
+ if (!isRecord$25(block)) continue;
12954
12970
  if (block.type === "image") {
12955
12971
  const inline = imageBlockToInline$3(block, images);
12956
12972
  if (inline && SUPPORTED_IMAGE_MEDIA_TYPES$4.has(inline.mediaType)) out.push({
@@ -12994,7 +13010,7 @@ function nonSystemMessages$4(options) {
12994
13010
  }
12995
13011
  /** Drop the JSON-Schema keywords provider gateways reject or ignore. */
12996
13012
  function stripMetaSchema$2(schema) {
12997
- if (!isRecord$24(schema)) return {
13013
+ if (!isRecord$25(schema)) return {
12998
13014
  type: "object",
12999
13015
  properties: {}
13000
13016
  };
@@ -13011,7 +13027,7 @@ function openAIUserContent$2(message, images) {
13011
13027
  const parts = [];
13012
13028
  let hasImage = false;
13013
13029
  for (const block of message.content) {
13014
- if (!isRecord$24(block)) continue;
13030
+ if (!isRecord$25(block)) continue;
13015
13031
  if (block.type === "text" && typeof block.text === "string") {
13016
13032
  const text = sanitizeText$4(block.text);
13017
13033
  if (text !== "") parts.push({
@@ -13039,7 +13055,7 @@ function openAIAssistantContent$2(message) {
13039
13055
  const textParts = [];
13040
13056
  const toolCalls = [];
13041
13057
  for (const block of message.content) {
13042
- if (!isRecord$24(block)) continue;
13058
+ if (!isRecord$25(block)) continue;
13043
13059
  if (block.type === "text" && typeof block.text === "string") textParts.push(sanitizeText$4(block.text));
13044
13060
  else if (block.type === "tool-call" && typeof block.name === "string") toolCalls.push({
13045
13061
  id: typeof block.id === "string" && block.id !== "" ? block.id : `call_${toolCalls.length}`,
@@ -13071,7 +13087,7 @@ function buildOpenAIRequest$1(options, images = NO_RESOLVED_IMAGES$4) {
13071
13087
  while (index < conversation.length && isToolResultMessage$4(conversation[index])) {
13072
13088
  const current = conversation[index];
13073
13089
  const block = current.content[0];
13074
- const callId = isRecord$24(block) && typeof block.toolCallId === "string" ? block.toolCallId : "";
13090
+ const callId = isRecord$25(block) && typeof block.toolCallId === "string" ? block.toolCallId : "";
13075
13091
  messages.push({
13076
13092
  role: "tool",
13077
13093
  tool_call_id: callId,
@@ -13132,7 +13148,7 @@ function anthropicUserContent$2(message, images) {
13132
13148
  if (!Array.isArray(message.content)) return [];
13133
13149
  const blocks = [];
13134
13150
  for (const block of message.content) {
13135
- if (!isRecord$24(block)) continue;
13151
+ if (!isRecord$25(block)) continue;
13136
13152
  if (block.type === "text" && typeof block.text === "string") {
13137
13153
  const text = sanitizeText$4(block.text);
13138
13154
  if (text !== "") blocks.push({
@@ -13169,7 +13185,7 @@ function anthropicUserContent$2(message, images) {
13169
13185
  function anthropicAssistantContent$2(message) {
13170
13186
  const blocks = [];
13171
13187
  for (const block of message.content) {
13172
- if (!isRecord$24(block)) continue;
13188
+ if (!isRecord$25(block)) continue;
13173
13189
  if (block.type === "text" && typeof block.text === "string") {
13174
13190
  const text = sanitizeText$4(block.text);
13175
13191
  if (text !== "") blocks.push({
@@ -13182,7 +13198,7 @@ function anthropicAssistantContent$2(message) {
13182
13198
  type: "tool_use",
13183
13199
  id: typeof block.id === "string" && block.id !== "" ? block.id : `toolu_${blocks.length}`,
13184
13200
  name: block.name,
13185
- input: isRecord$24(parsed) ? parsed : {}
13201
+ input: isRecord$25(parsed) ? parsed : {}
13186
13202
  });
13187
13203
  }
13188
13204
  }
@@ -13276,7 +13292,7 @@ function responsesUserContent(message, images) {
13276
13292
  if (!Array.isArray(message.content)) return [];
13277
13293
  const parts = [];
13278
13294
  for (const block of message.content) {
13279
- if (!isRecord$24(block)) continue;
13295
+ if (!isRecord$25(block)) continue;
13280
13296
  if (block.type === "text" && typeof block.text === "string") {
13281
13297
  const text = sanitizeText$4(block.text);
13282
13298
  if (text !== "") parts.push({
@@ -13301,7 +13317,7 @@ function responsesToolResultImageBlocks(blocks, images) {
13301
13317
  if (!Array.isArray(blocks)) return [];
13302
13318
  const out = [];
13303
13319
  for (const block of blocks) {
13304
- if (!isRecord$24(block)) continue;
13320
+ if (!isRecord$25(block)) continue;
13305
13321
  if (block.type === "image") {
13306
13322
  const inline = imageBlockToInline$3(block, images);
13307
13323
  if (inline && SUPPORTED_IMAGE_MEDIA_TYPES$4.has(inline.mediaType)) out.push({
@@ -13328,8 +13344,8 @@ function buildResponsesRequest(options, images = NO_RESOLVED_IMAGES$4) {
13328
13344
  const imageBlocks = [];
13329
13345
  while (index < conversation.length && isToolResultMessage$4(conversation[index])) {
13330
13346
  const current = conversation[index];
13331
- const toolResult = Array.isArray(current.content) ? current.content.find((b) => isRecord$24(b) && b.type === "tool-result") : void 0;
13332
- const callId = (isRecord$24(toolResult) && typeof toolResult.toolCallId === "string" ? toolResult.toolCallId : "") || (typeof current.source?.callId === "string" ? current.source.callId : "");
13347
+ const toolResult = Array.isArray(current.content) ? current.content.find((b) => isRecord$25(b) && b.type === "tool-result") : void 0;
13348
+ const callId = (isRecord$25(toolResult) && typeof toolResult.toolCallId === "string" ? toolResult.toolCallId : "") || (typeof current.source?.callId === "string" ? current.source.callId : "");
13333
13349
  input.push({
13334
13350
  type: "function_call_output",
13335
13351
  call_id: callId,
@@ -13352,7 +13368,7 @@ function buildResponsesRequest(options, images = NO_RESOLVED_IMAGES$4) {
13352
13368
  content
13353
13369
  });
13354
13370
  for (const call of toolCalls) {
13355
- const fn = isRecord$24(call.function) ? call.function : void 0;
13371
+ const fn = isRecord$25(call.function) ? call.function : void 0;
13356
13372
  input.push({
13357
13373
  type: "function_call",
13358
13374
  call_id: call.id,
@@ -13475,25 +13491,33 @@ function processOpenAIStreamLine$1(line, state) {
13475
13491
  }
13476
13492
  if (payload === "") return [];
13477
13493
  const chunk = safeJsonParse$4(payload);
13478
- if (!isRecord$24(chunk)) return [];
13494
+ if (!isRecord$25(chunk)) return [];
13479
13495
  const out = [];
13480
- if (isRecord$24(chunk.error)) throw new LlmError$1(`Command Code stream error: ${asString$14(chunk.error.message) ?? "unknown error"}`, isContextOverflow(chunk.error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
13481
- const usage = isRecord$24(chunk.usage) ? chunk.usage : void 0;
13496
+ if (isRecord$25(chunk.error)) {
13497
+ const message = asString$15(chunk.error.message) ?? "unknown error";
13498
+ state.streamError = {
13499
+ vocabulary: "openai",
13500
+ error: chunk.error,
13501
+ message
13502
+ };
13503
+ throw new LlmError$1(`Command Code stream error: ${message}`, isContextOverflow(chunk.error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
13504
+ }
13505
+ const usage = isRecord$25(chunk.usage) ? chunk.usage : void 0;
13482
13506
  if (usage) {
13483
13507
  state.sawUsage = true;
13484
13508
  const prompt = numberOr$5(usage.prompt_tokens, 0);
13485
- const details = isRecord$24(usage.prompt_tokens_details) ? usage.prompt_tokens_details : void 0;
13509
+ const details = isRecord$25(usage.prompt_tokens_details) ? usage.prompt_tokens_details : void 0;
13486
13510
  const cached = details ? numberOr$5(details.cached_tokens, 0) : 0;
13487
13511
  state.inputTokens = Math.max(0, prompt - cached);
13488
13512
  state.cacheReadTokens = cached;
13489
13513
  state.outputTokens = numberOr$5(usage.completion_tokens, state.outputTokens);
13490
- if (isRecord$24(usage.completion_tokens_details)) state.reasoningTokens = numberOr$5(usage.completion_tokens_details.reasoning_tokens, state.reasoningTokens);
13514
+ if (isRecord$25(usage.completion_tokens_details)) state.reasoningTokens = numberOr$5(usage.completion_tokens_details.reasoning_tokens, state.reasoningTokens);
13491
13515
  }
13492
13516
  const choices = Array.isArray(chunk.choices) ? chunk.choices : [];
13493
- const choice = isRecord$24(choices[0]) ? choices[0] : void 0;
13494
- const delta = isRecord$24(choice?.delta) ? choice.delta : void 0;
13517
+ const choice = isRecord$25(choices[0]) ? choices[0] : void 0;
13518
+ const delta = isRecord$25(choice?.delta) ? choice.delta : void 0;
13495
13519
  if (delta) {
13496
- const reasoning = asString$14(delta.reasoning_content) ?? asString$14(delta.reasoning);
13520
+ const reasoning = asString$15(delta.reasoning_content) ?? asString$15(delta.reasoning);
13497
13521
  if (reasoning !== void 0 && reasoning !== "") {
13498
13522
  out.push(...closeToolCalls$4(state));
13499
13523
  if (state.current === null || state.current.type !== "reasoning") out.push(...openTextBlock$3(state, "reasoning"));
@@ -13505,7 +13529,7 @@ function processOpenAIStreamLine$1(line, state) {
13505
13529
  text: sanitizeText$4(reasoning)
13506
13530
  });
13507
13531
  }
13508
- const content = asString$14(delta.content);
13532
+ const content = asString$15(delta.content);
13509
13533
  if (content !== void 0 && content !== "") {
13510
13534
  out.push(...closeToolCalls$4(state));
13511
13535
  if (state.current === null || state.current.type !== "text") out.push(...openTextBlock$3(state, "text"));
@@ -13519,11 +13543,11 @@ function processOpenAIStreamLine$1(line, state) {
13519
13543
  }
13520
13544
  const toolDeltas = Array.isArray(delta.tool_calls) ? delta.tool_calls : [];
13521
13545
  for (const entry of toolDeltas) {
13522
- if (!isRecord$24(entry)) continue;
13546
+ if (!isRecord$25(entry)) continue;
13523
13547
  out.push(...applyOpenAIToolDelta$1(entry, state));
13524
13548
  }
13525
13549
  }
13526
- const finish = asString$14(choice?.finish_reason);
13550
+ const finish = asString$15(choice?.finish_reason);
13527
13551
  if (finish !== void 0 && finish !== "") {
13528
13552
  state.finishReason = finish;
13529
13553
  out.push(...closeCurrent$3(state));
@@ -13533,15 +13557,15 @@ function processOpenAIStreamLine$1(line, state) {
13533
13557
  }
13534
13558
  function applyOpenAIToolDelta$1(entry, state) {
13535
13559
  const wireIndex = typeof entry.index === "number" ? entry.index : 0;
13536
- const fn = isRecord$24(entry.function) ? entry.function : {};
13560
+ const fn = isRecord$25(entry.function) ? entry.function : {};
13537
13561
  const out = [];
13538
13562
  let call = state.toolCalls.get(wireIndex);
13539
13563
  if (call === void 0) {
13540
13564
  out.push(...closeCurrent$3(state));
13541
13565
  call = {
13542
13566
  blockIndex: state.blocks.length,
13543
- id: asString$14(entry.id) ?? `call_${wireIndex}`,
13544
- name: asString$14(fn.name) ?? "",
13567
+ id: asString$15(entry.id) ?? `call_${wireIndex}`,
13568
+ name: asString$15(fn.name) ?? "",
13545
13569
  arguments: "",
13546
13570
  started: false
13547
13571
  };
@@ -13554,13 +13578,13 @@ function applyOpenAIToolDelta$1(entry, state) {
13554
13578
  state.toolCalls.set(wireIndex, call);
13555
13579
  } else {
13556
13580
  if (call.id === `call_${wireIndex}`) {
13557
- const id = asString$14(entry.id);
13581
+ const id = asString$15(entry.id);
13558
13582
  if (id !== void 0) call.id = id;
13559
13583
  }
13560
- const name = asString$14(fn.name);
13584
+ const name = asString$15(fn.name);
13561
13585
  if (name !== void 0 && name !== "") call.name = name;
13562
13586
  }
13563
- const argsDelta = asString$14(fn.arguments) ?? "";
13587
+ const argsDelta = asString$15(fn.arguments) ?? "";
13564
13588
  if (argsDelta !== "") call.arguments += argsDelta;
13565
13589
  if (!call.started) {
13566
13590
  call.started = true;
@@ -13591,12 +13615,12 @@ function processAnthropicStreamLine$1(line, state) {
13591
13615
  const payload = trimmed.slice(5).trim();
13592
13616
  if (payload === "" || payload === "[DONE]") return [];
13593
13617
  const event = safeJsonParse$4(payload);
13594
- if (!isRecord$24(event)) return [];
13595
- const type = asString$14(event.type);
13618
+ if (!isRecord$25(event)) return [];
13619
+ const type = asString$15(event.type);
13596
13620
  const out = [];
13597
13621
  if (type === "message_start") {
13598
- const message = isRecord$24(event.message) ? event.message : void 0;
13599
- const usage = message && isRecord$24(message.usage) ? message.usage : void 0;
13622
+ const message = isRecord$25(event.message) ? event.message : void 0;
13623
+ const usage = message && isRecord$25(message.usage) ? message.usage : void 0;
13600
13624
  if (usage) {
13601
13625
  state.sawUsage = true;
13602
13626
  state.inputTokens = numberOr$5(usage.input_tokens, 0);
@@ -13604,21 +13628,21 @@ function processAnthropicStreamLine$1(line, state) {
13604
13628
  state.cacheWriteTokens = numberOr$5(usage.cache_creation_input_tokens, 0);
13605
13629
  state.outputTokens = numberOr$5(usage.output_tokens, 0);
13606
13630
  }
13607
- const stop = message ? asString$14(message.stop_reason) : void 0;
13631
+ const stop = message ? asString$15(message.stop_reason) : void 0;
13608
13632
  if (stop !== void 0 && stop !== null) state.finishReason = stop;
13609
13633
  return out;
13610
13634
  }
13611
13635
  if (type === "content_block_start") {
13612
13636
  const contentIndex = numberOr$5(event.index, 0);
13613
- const block = isRecord$24(event.content_block) ? event.content_block : {};
13614
- const blockType = asString$14(block.type);
13637
+ const block = isRecord$25(event.content_block) ? event.content_block : {};
13638
+ const blockType = asString$15(block.type);
13615
13639
  out.push(...closeCurrent$3(state));
13616
13640
  if (blockType === "tool_use") {
13617
13641
  const index = state.blocks.length;
13618
13642
  const pending = {
13619
13643
  blockIndex: index,
13620
- id: asString$14(block.id) ?? `toolu_${contentIndex}`,
13621
- name: asString$14(block.name) ?? "",
13644
+ id: asString$15(block.id) ?? `toolu_${contentIndex}`,
13645
+ name: asString$15(block.name) ?? "",
13622
13646
  arguments: "",
13623
13647
  started: true
13624
13648
  };
@@ -13660,11 +13684,11 @@ function processAnthropicStreamLine$1(line, state) {
13660
13684
  }
13661
13685
  if (type === "content_block_delta") {
13662
13686
  const contentIndex = numberOr$5(event.index, 0);
13663
- const delta = isRecord$24(event.delta) ? event.delta : {};
13664
- const deltaType = asString$14(delta.type);
13687
+ const delta = isRecord$25(event.delta) ? event.delta : {};
13688
+ const deltaType = asString$15(delta.type);
13665
13689
  if (deltaType === "input_json_delta") {
13666
13690
  const pending = state.toolCalls.get(contentIndex);
13667
- const partial = asString$14(delta.partial_json) ?? "";
13691
+ const partial = asString$15(delta.partial_json) ?? "";
13668
13692
  if (pending !== void 0) {
13669
13693
  pending.arguments += partial;
13670
13694
  out.push({
@@ -13677,7 +13701,7 @@ function processAnthropicStreamLine$1(line, state) {
13677
13701
  }
13678
13702
  return out;
13679
13703
  }
13680
- const text = deltaType === "thinking_delta" ? asString$14(delta.thinking) : asString$14(delta.text);
13704
+ const text = deltaType === "thinking_delta" ? asString$15(delta.thinking) : asString$15(delta.text);
13681
13705
  if (text !== void 0 && text !== "") {
13682
13706
  const index = state.contentIndexes.get(contentIndex) ?? state.current?.index;
13683
13707
  const kind = deltaType === "thinking_delta" ? "reasoning" : "text";
@@ -13733,10 +13757,10 @@ function processAnthropicStreamLine$1(line, state) {
13733
13757
  return out;
13734
13758
  }
13735
13759
  if (type === "message_delta") {
13736
- const delta = isRecord$24(event.delta) ? event.delta : void 0;
13737
- const stop = delta ? asString$14(delta.stop_reason) : void 0;
13760
+ const delta = isRecord$25(event.delta) ? event.delta : void 0;
13761
+ const stop = delta ? asString$15(delta.stop_reason) : void 0;
13738
13762
  if (stop !== void 0 && stop !== "") state.finishReason = stop;
13739
- const usage = isRecord$24(event.usage) ? event.usage : void 0;
13763
+ const usage = isRecord$25(event.usage) ? event.usage : void 0;
13740
13764
  if (usage) {
13741
13765
  state.sawUsage = true;
13742
13766
  state.outputTokens = numberOr$5(usage.output_tokens, state.outputTokens);
@@ -13748,8 +13772,14 @@ function processAnthropicStreamLine$1(line, state) {
13748
13772
  return closeStream$4(state);
13749
13773
  }
13750
13774
  if (type === "error") {
13751
- const error = isRecord$24(event.error) ? event.error : {};
13752
- throw new LlmError$1(`Command Code stream error: ${asString$14(error.message) ?? "unknown error"}`, isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
13775
+ const error = isRecord$25(event.error) ? event.error : {};
13776
+ const message = asString$15(error.message) ?? "unknown error";
13777
+ state.streamError = {
13778
+ vocabulary: "anthropic",
13779
+ error,
13780
+ message
13781
+ };
13782
+ throw new LlmError$1(`Command Code stream error: ${message}`, isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
13753
13783
  }
13754
13784
  return out;
13755
13785
  }
@@ -13788,7 +13818,7 @@ function processResponsesStreamLine(line, state) {
13788
13818
  } catch {
13789
13819
  return [];
13790
13820
  }
13791
- if (!isRecord$24(parsed)) return [];
13821
+ if (!isRecord$25(parsed)) return [];
13792
13822
  const type = typeof parsed.type === "string" ? parsed.type : "";
13793
13823
  if (type === "response.output_text.delta") {
13794
13824
  const delta = typeof parsed.delta === "string" ? parsed.delta : "";
@@ -13815,7 +13845,7 @@ function processResponsesStreamLine(line, state) {
13815
13845
  }];
13816
13846
  }
13817
13847
  if (type === "response.output_item.added") {
13818
- const item = isRecord$24(parsed.item) ? parsed.item : null;
13848
+ const item = isRecord$25(parsed.item) ? parsed.item : null;
13819
13849
  if (item === null || item.type !== "function_call") return [];
13820
13850
  return startResponsesToolCall(state, parsed, item);
13821
13851
  }
@@ -13839,19 +13869,24 @@ function processResponsesStreamLine(line, state) {
13839
13869
  return [];
13840
13870
  }
13841
13871
  if (type === "response.completed" || type === "response.incomplete") {
13842
- const response = isRecord$24(parsed.response) ? parsed.response : null;
13872
+ const response = isRecord$25(parsed.response) ? parsed.response : null;
13843
13873
  if (response !== null) {
13844
13874
  if (response.status === "failed") {
13845
13875
  state.done = true;
13846
- const errorObj = isRecord$24(response.error) ? response.error : null;
13876
+ const errorObj = isRecord$25(response.error) ? response.error : null;
13847
13877
  const detail = errorObj && typeof errorObj.message === "string" ? errorObj.message : typeof response.error === "string" ? response.error : "";
13878
+ state.streamError = {
13879
+ vocabulary: "responses",
13880
+ error: errorObj,
13881
+ message: detail
13882
+ };
13848
13883
  throw new LlmError$1(detail === "" ? "Command Code responses stream failed" : `Command Code responses stream failed: ${detail}`, "PROVIDER_ERROR");
13849
13884
  }
13850
13885
  readResponsesUsage(response, state);
13851
13886
  }
13852
13887
  state.done = true;
13853
13888
  if (type === "response.incomplete") {
13854
- const details = response && isRecord$24(response.incomplete_details) ? response.incomplete_details : null;
13889
+ const details = response && isRecord$25(response.incomplete_details) ? response.incomplete_details : null;
13855
13890
  const reason = details && typeof details.reason === "string" ? details.reason : "";
13856
13891
  state.finishReason = reason === "max_output_tokens" || reason === "length" || reason === "max_tokens" ? "length" : reason || "length";
13857
13892
  } else state.finishReason = "stop";
@@ -13859,8 +13894,13 @@ function processResponsesStreamLine(line, state) {
13859
13894
  }
13860
13895
  if (type === "response.failed" || type === "error") {
13861
13896
  state.done = true;
13862
- const errorObj = isRecord$24(parsed.error) ? parsed.error : isRecord$24(parsed.response) && isRecord$24(parsed.response.error) ? parsed.response.error : null;
13863
- const detail = (typeof parsed.message === "string" ? parsed.message : "") || (errorObj && typeof errorObj.message === "string" ? errorObj.message : "") || (isRecord$24(parsed.response) && typeof parsed.response.error === "string" ? parsed.response.error : typeof parsed.error === "string" ? parsed.error : "");
13897
+ const errorObj = isRecord$25(parsed.error) ? parsed.error : isRecord$25(parsed.response) && isRecord$25(parsed.response.error) ? parsed.response.error : null;
13898
+ const detail = (typeof parsed.message === "string" ? parsed.message : "") || (errorObj && typeof errorObj.message === "string" ? errorObj.message : "") || (isRecord$25(parsed.response) && typeof parsed.response.error === "string" ? parsed.response.error : typeof parsed.error === "string" ? parsed.error : "");
13899
+ state.streamError = {
13900
+ vocabulary: "responses",
13901
+ error: errorObj,
13902
+ message: detail
13903
+ };
13864
13904
  throw new LlmError$1(detail === "" ? "Command Code responses stream failed" : `Command Code responses stream failed: ${detail}`, isContextOverflow(errorObj ?? detail) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
13865
13905
  }
13866
13906
  return [];
@@ -13943,15 +13983,15 @@ function responsesToolCall(state, key) {
13943
13983
  for (const call of state.toolCalls.values()) if (call.id === toToolCallId(key)) return call;
13944
13984
  }
13945
13985
  function readResponsesUsage(response, state) {
13946
- const usage = isRecord$24(response.usage) ? response.usage : null;
13986
+ const usage = isRecord$25(response.usage) ? response.usage : null;
13947
13987
  if (usage === null) return;
13948
- const cached = isRecord$24(usage.input_tokens_details) ? numberOrZero(usage.input_tokens_details.cached_tokens) : 0;
13949
- const written = isRecord$24(usage.input_tokens_details) ? numberOrZero(usage.input_tokens_details.cache_write_tokens) : 0;
13988
+ const cached = isRecord$25(usage.input_tokens_details) ? numberOrZero(usage.input_tokens_details.cached_tokens) : 0;
13989
+ const written = isRecord$25(usage.input_tokens_details) ? numberOrZero(usage.input_tokens_details.cache_write_tokens) : 0;
13950
13990
  state.inputTokens = Math.max(0, numberOrZero(usage.input_tokens) - cached - written);
13951
13991
  state.cacheReadTokens = cached;
13952
13992
  state.cacheWriteTokens = written;
13953
13993
  state.outputTokens = numberOrZero(usage.output_tokens);
13954
- const outputDetails = isRecord$24(usage.output_tokens_details) ? usage.output_tokens_details : null;
13994
+ const outputDetails = isRecord$25(usage.output_tokens_details) ? usage.output_tokens_details : null;
13955
13995
  if (outputDetails !== null) state.reasoningTokens = numberOrZero(outputDetails.reasoning_tokens);
13956
13996
  state.sawUsage = true;
13957
13997
  }
@@ -13978,6 +14018,136 @@ function assertStreamComplete$4(state) {
13978
14018
  if (!state.done && state.finishReason === null) throw new LlmError$1("Command Code stream ended before its terminal event", "PROVIDER_ERROR");
13979
14019
  }
13980
14020
  //#endregion
14021
+ //#region src/host/common/stream-error.ts
14022
+ /**
14023
+ * A failure the provider reported INSIDE a 200 stream.
14024
+ *
14025
+ * A service can answer 200 and then report the failure in the stream, in the
14026
+ * same `{ error: { type, message } }` envelope a non-2xx body carries. A mapper
14027
+ * has to type that event with one code, and the code that is right in general is
14028
+ * PROVIDER_ERROR - it cannot know whether output has started - which is outside
14029
+ * every retry set. So a transient failure delivered this way ends the turn on
14030
+ * the first try while the identical failure delivered as a status is retried.
14031
+ *
14032
+ * The reclassification itself is per line, because only the adapter knows
14033
+ * whether anything has reached the caller yet, and because every line owns rules
14034
+ * its own HTTP path already owns. What is shared is the question each line asks
14035
+ * its own classifier: what status WOULD this failure have carried?
14036
+ */
14037
+ /**
14038
+ * The status an in-band `error` event stands for, or null for a type this
14039
+ * vocabulary does not name.
14040
+ *
14041
+ * The Anthropic-compatible shims (MiniMax Code, Kimi Code, and Command Code's
14042
+ * messages stream) speak one vocabulary, and each of these types already has a
14043
+ * status: 529 is Anthropic's documented overload, 429 the rate limit, and a 5xx
14044
+ * the server-side failure. Naming the STATUS rather than the verdict is what lets
14045
+ * each line hand the answer to its own classifier, so a rule that line already
14046
+ * owns - a 429 that names an exhausted plan, a credential refusal reported as
14047
+ * 403 - keeps owning it here.
14048
+ *
14049
+ * Null for everything else: a request the provider rejected, a context
14050
+ * overflow, a credential refusal, a type from the future. Null is what keeps
14051
+ * the mapper's own verdict, and that is the safe direction to fail in - a
14052
+ * fallback to some made-up status would file an unknown type as a retryable
14053
+ * server error, which is worse than not retrying at all.
14054
+ */
14055
+ function inBandAnthropicStatus(error) {
14056
+ const type = readErrorType(error);
14057
+ if (type === null) return null;
14058
+ return ANTHROPIC_IN_BAND_STATUS[type] ?? null;
14059
+ }
14060
+ /** The status each transient Anthropic-compatible in-band type stands for. */
14061
+ const ANTHROPIC_IN_BAND_STATUS = {
14062
+ overloaded_error: 529,
14063
+ rate_limit_error: 429,
14064
+ api_error: 500
14065
+ };
14066
+ /**
14067
+ * The DSH code an in-band Responses-vocabulary failure becomes, or null when it
14068
+ * names nothing transient.
14069
+ *
14070
+ * The Responses stream reports failure as `response.failed` or `error`, whose
14071
+ * message is free text and whose structured evidence is split across TWO fields:
14072
+ * this plugin's own routes document `{"error":{"message":"Upstream model
14073
+ * provider is temporarily unavailable. Please try again in a moment.","type":
14074
+ * "server_error"}}` - `type`, not `code` - so reading only `code` would miss
14075
+ * the exact body this exists for, and its message names nothing the heuristic
14076
+ * would catch. Both fields are read, and the message is read too, because a
14077
+ * deployment that says "overloaded" in prose is the whole signal there.
14078
+ *
14079
+ * Anything not recognized keeps the mapper's verdict.
14080
+ */
14081
+ function inBandResponsesCode(error, message) {
14082
+ const fields = isRecord$24(error) ? error : {};
14083
+ const rawCode = (asString$14(fields.code) ?? asString$14(fields.type) ?? "").toLowerCase();
14084
+ const text = message.toLowerCase();
14085
+ if (text.includes("rate limit") || rawCode === "rate_limit" || rawCode === "rate_limit_exceeded") return "RATE_LIMIT";
14086
+ if (text.includes("overload") || text.includes("server error") || rawCode === "server_error" || rawCode === "service_unavailable" || rawCode === "internal_error") return "SERVER";
14087
+ return null;
14088
+ }
14089
+ /**
14090
+ * The error one in-band stream failure becomes, or `thrown` itself when the
14091
+ * line's own verdict stands.
14092
+ *
14093
+ * Call this only while nothing has reached the caller: the whole reason a fresh
14094
+ * request is still free is what makes the retry safe (see module note 1 in the
14095
+ * Claude adapter, which this generalizes). After the first chunk the mapper's
14096
+ * verdict stands and this must not be called at all.
14097
+ *
14098
+ * Only the CODE changes. The message stays the mapper's, which names the wire
14099
+ * type the user saw, and no `status` is attached: the response really was a
14100
+ * 200, and a synthetic one would misreport what the provider said.
14101
+ *
14102
+ * @param thrown - the mapper's own verdict, passed through when it stands.
14103
+ * @param rawError - the event's wire `error` object, from the stream state.
14104
+ * @param classify - this line's own failure classifier, so every rule its HTTP
14105
+ * path owns still owns the verdict reached here.
14106
+ * @param statusFor - the vocabulary's status table; Responses lines pass
14107
+ * {@link inBandResponsesCode} through {@link reclassifyInBandResponsesError}.
14108
+ */
14109
+ function reclassifyInBandError(thrown, rawError, classify, statusFor = inBandAnthropicStatus) {
14110
+ const status = statusFor(rawError);
14111
+ if (status === null) return thrown;
14112
+ const failure = classify(status, JSON.stringify({ error: rawError }));
14113
+ if (!failure.retryable) return thrown;
14114
+ return new LlmError(thrown.message, failure.code, { cause: thrown });
14115
+ }
14116
+ /**
14117
+ * {@link reclassifyInBandError} for a line whose classifier reads a status, fed
14118
+ * by the Responses vocabulary instead of the Anthropic one.
14119
+ *
14120
+ * The transient verdict found here is a QUESTION, not the answer: a
14121
+ * `rate_limit` code says only that the failure is worth retrying, and whether
14122
+ * it actually is - a 429 naming a spent balance is this route's PROVIDER_ERROR,
14123
+ * not a RATE_LIMIT - is a rule the line's own classifier owns. So the answer is
14124
+ * asked of `classify` at the status the verdict stands for, exactly as the
14125
+ * Anthropic sibling does, and the CODE that comes back is the one the HTTP path
14126
+ * would have produced for the same body. That agreement is the whole point: the
14127
+ * in-band delivery must not be the one delivery with its own opinion.
14128
+ */
14129
+ function reclassifyInBandResponsesError(thrown, rawError, message, classify) {
14130
+ const code = inBandResponsesCode(rawError, message);
14131
+ if (code === null) return thrown;
14132
+ const failure = classify(code === "RATE_LIMIT" ? 429 : 500, JSON.stringify({
14133
+ error: rawError,
14134
+ message
14135
+ }));
14136
+ if (!failure.retryable) return thrown;
14137
+ return new LlmError(thrown.message, failure.code, { cause: thrown });
14138
+ }
14139
+ /** The wire `error` object of an in-band event, read defensively. */
14140
+ function readErrorType(error) {
14141
+ if (!isRecord$24(error)) return null;
14142
+ return typeof error.type === "string" ? error.type : null;
14143
+ }
14144
+ function asString$14(value) {
14145
+ return typeof value === "string" ? value : void 0;
14146
+ }
14147
+ function isRecord$24(value) {
14148
+ return typeof value === "object" && value !== null && !Array.isArray(value);
14149
+ }
14150
+ //#endregion
13981
14151
  //#region src/host/common/capabilities.ts
13982
14152
  /** Error thrown by requireCapability when a capability contract fails. */
13983
14153
  var CapabilityError = class extends Error {
@@ -14253,6 +14423,35 @@ function isCommandCodeCredentialInvalid(status, detail) {
14253
14423
  }
14254
14424
  return false;
14255
14425
  }
14426
+ /**
14427
+ * The verdict one failed response becomes on this route.
14428
+ *
14429
+ * An in-band `error` event is a status the provider chose not to send as a
14430
+ * status, so the chain that answers a non-2xx body has to answer it too rather
14431
+ * than a second, looser one: every rule this route already owns - a model the
14432
+ * plan does not include, a rejected key, a spent quota - keeps owning the
14433
+ * answer, and the codes below are the ONLY place the HTTP path reads them from.
14434
+ *
14435
+ * `retryable` is membership of this route's own policy rather than a second
14436
+ * judgement, because a code is worth repeating exactly when RETRY_POLICY repeats
14437
+ * it; a verdict the policy would not act on must not be filed as transient.
14438
+ *
14439
+ * @param status - the response status, or the status an in-band type stands for.
14440
+ * @param detail - the response body, or the serialized in-band error envelope.
14441
+ */
14442
+ function classifyCommandCodeFailure(status, detail) {
14443
+ let code;
14444
+ if (status === 422) code = "PROVIDER_ERROR";
14445
+ else if (isCommandCodeModelAccessDenied(status, detail)) code = "PROVIDER_ERROR";
14446
+ else if (isCommandCodeCredentialInvalid(status, detail) || status === 401) code = "INVALID_CREDENTIAL";
14447
+ else if (status === 429) code = "RATE_LIMIT";
14448
+ else if (status >= 500) code = "SERVER";
14449
+ else code = isHttpContextOverflow(status, detail) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR";
14450
+ return {
14451
+ code,
14452
+ retryable: RETRY_POLICY$5.mode === "normal" && RETRY_POLICY$5.retryableCodes.includes(code)
14453
+ };
14454
+ }
14256
14455
  /** Cooldown one rate-limited key takes when the provider states no delay. */
14257
14456
  const POOL_COOLDOWN_MS$4 = 15 * 6e4;
14258
14457
  var CommandCodeAdapter = class extends LlmAdapter {
@@ -14447,49 +14646,105 @@ var CommandCodeAdapter = class extends LlmAdapter {
14447
14646
  }
14448
14647
  if (response === void 0 || !response.ok) {
14449
14648
  const status = response?.status ?? 500;
14649
+ const { code } = classifyCommandCodeFailure(status, detail);
14450
14650
  if (status === 422) {
14451
- if (detail.includes("cmd_zdr_no_providers")) throw new LlmError(`${PROVIDER_NAME$5} rejected request under Zero Data Retention: no ZDR-capable upstream is available for this model (${detail || "cmd_zdr_no_providers"}).`, "PROVIDER_ERROR", { status: 422 });
14452
- throw new LlmError(`${PROVIDER_NAME$5} validation error (422): ${detail || "Unprocessable Entity"}`, "PROVIDER_ERROR", { status: 422 });
14651
+ if (detail.includes("cmd_zdr_no_providers")) throw new LlmError(`${PROVIDER_NAME$5} rejected request under Zero Data Retention: no ZDR-capable upstream is available for this model (${detail || "cmd_zdr_no_providers"}).`, code, { status: 422 });
14652
+ throw new LlmError(`${PROVIDER_NAME$5} validation error (422): ${detail || "Unprocessable Entity"}`, code, { status: 422 });
14453
14653
  }
14454
- if (isCommandCodeModelAccessDenied(status, detail)) throw new LlmError(`${PROVIDER_NAME$5} access denied for model ${options.model}: this model is not included in the plan or requires higher entitlement (${status}).${detail ? ` ${detail}` : ""}`, "PROVIDER_ERROR", { status });
14455
- if (isCommandCodeCredentialInvalid(status, detail) || status === 401) throw new LlmError(`${PROVIDER_NAME$5} rejected the stored API key (${status}). Sign in again from Settings > Command Code.${detail ? ` ${detail}` : ""}`, "INVALID_CREDENTIAL", { status });
14654
+ if (isCommandCodeModelAccessDenied(status, detail)) throw new LlmError(`${PROVIDER_NAME$5} access denied for model ${options.model}: this model is not included in the plan or requires higher entitlement (${status}).${detail ? ` ${detail}` : ""}`, code, { status });
14655
+ if (isCommandCodeCredentialInvalid(status, detail) || status === 401) throw new LlmError(`${PROVIDER_NAME$5} rejected the stored API key (${status}). Sign in again from Settings > Command Code.${detail ? ` ${detail}` : ""}`, code, { status });
14456
14656
  if (status === 429) {
14457
14657
  const after = response === void 0 ? void 0 : retryAfterMs$1(response.headers);
14458
- throw new LlmError(`${PROVIDER_NAME$5} rate limit or plan quota reached (429). Check the quota card in Settings > Command Code.${detail ? ` ${detail}` : ""}`, "RATE_LIMIT", {
14658
+ throw new LlmError(`${PROVIDER_NAME$5} rate limit or plan quota reached (429). Check the quota card in Settings > Command Code.${detail ? ` ${detail}` : ""}`, code, {
14459
14659
  status: 429,
14460
14660
  ...after === void 0 ? {} : { providerRetryAfterMs: after }
14461
14661
  });
14462
14662
  }
14463
- if (status >= 500) throw new LlmError(`${PROVIDER_NAME$5} upstream server error (${status}): ${detail || "No response"}`, "SERVER", { status });
14464
- throw new LlmError(`${PROVIDER_NAME$5} API error (${status}): ${detail || "No response"}`, isHttpContextOverflow(status, detail) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR", { status });
14663
+ if (status >= 500) throw new LlmError(`${PROVIDER_NAME$5} upstream server error (${status}): ${detail || "No response"}`, code, { status });
14664
+ throw new LlmError(`${PROVIDER_NAME$5} API error (${status}): ${detail || "No response"}`, code, { status });
14465
14665
  }
14466
14666
  if (response.body === null) throw new LlmError("Command Code returned an empty response body", "PROVIDER_ERROR");
14467
14667
  const reader = response.body.getReader();
14468
14668
  const decoder = new TextDecoder();
14469
14669
  const state = createStreamState$5(wire);
14470
14670
  let buffer = "";
14671
+ /**
14672
+ * Set the moment ANY chunk reaches the caller, and never cleared.
14673
+ *
14674
+ * Deliberately broader than `a text delta or a tool call`: a retry would repeat
14675
+ * a block-start the caller has already seen just as surely, and could re-issue
14676
+ * a tool call the agent has already run, so the conservative reading is the
14677
+ * one that cannot be wrong. It is what keeps the in-band reclassification
14678
+ * below pre-output only, and before that point a fresh request is still free.
14679
+ */
14680
+ let outputStarted = false;
14471
14681
  try {
14472
- while (true) {
14473
- const { done, value } = await reader.read();
14474
- if (done) break;
14475
- buffer += decoder.decode(value, { stream: true });
14476
- const lines = buffer.split("\n");
14477
- buffer = lines.pop() ?? "";
14478
- for (const line of lines) {
14479
- for (const chunk of processLine$1(line, state, wire)) yield chunk;
14480
- if (state.finished) return;
14682
+ try {
14683
+ while (true) {
14684
+ const { done, value } = await reader.read();
14685
+ if (done) break;
14686
+ buffer += decoder.decode(value, { stream: true });
14687
+ const lines = buffer.split("\n");
14688
+ buffer = lines.pop() ?? "";
14689
+ for (const line of lines) {
14690
+ for (const chunk of processLine$1(line, state, wire)) {
14691
+ outputStarted = true;
14692
+ yield chunk;
14693
+ }
14694
+ if (state.finished) return;
14695
+ }
14696
+ }
14697
+ buffer += decoder.decode();
14698
+ if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processLine$1(line, state, wire)) {
14699
+ outputStarted = true;
14700
+ yield chunk;
14701
+ }
14702
+ if (state.finished) return;
14703
+ assertStreamComplete$4(state);
14704
+ for (const chunk of closeStream$4(state)) {
14705
+ outputStarted = true;
14706
+ yield chunk;
14707
+ }
14708
+ } catch (error) {
14709
+ const inBand = state.streamError;
14710
+ if (error instanceof LlmError && !outputStarted && inBand !== void 0 && error.code === "PROVIDER_ERROR") {
14711
+ const reclassified = reclassifyInBandStreamError(error, inBand);
14712
+ if (reclassified.code === "RATE_LIMIT" && pool !== null && accountId !== void 0) {
14713
+ const after = retryAfterMs$1(response.headers);
14714
+ await pool.markCooldown(accountId, after ?? POOL_COOLDOWN_MS$4, `${PROVIDER_NAME$5} in-stream 429`).catch(() => void 0);
14715
+ }
14716
+ throw reclassified;
14481
14717
  }
14718
+ throw error;
14482
14719
  }
14483
- buffer += decoder.decode();
14484
- if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processLine$1(line, state, wire)) yield chunk;
14485
- if (state.finished) return;
14486
- assertStreamComplete$4(state);
14487
- for (const chunk of closeStream$4(state)) yield chunk;
14488
14720
  } finally {
14489
14721
  reader.cancel().catch(() => void 0);
14490
14722
  }
14491
14723
  }
14492
14724
  };
14725
+ /**
14726
+ * The error one recorded in-band failure becomes, or the mapper's own verdict.
14727
+ *
14728
+ * Two rules, because this line speaks three in-band vocabularies and they do
14729
+ * not carry the same evidence. The messages wire names a transient failure with
14730
+ * a `type` that STANDS FOR A STATUS - an `overloaded_error` is the 529 it would
14731
+ * have sent - so its envelope is answered by the status table. The
14732
+ * chat-completions and Responses wires have no such type: their evidence is a
14733
+ * `code`, a `type` in the looser `server_error` sense, or plain prose, and the
14734
+ * status-reading helper is what turns that into the question this line's own
14735
+ * classifier answers.
14736
+ *
14737
+ * The switch is exhaustive on purpose. A fourth vocabulary must be a compile
14738
+ * error here rather than a silent fall into the rule above, which is the one
14739
+ * shape of this bug that cannot be caught by a test.
14740
+ */
14741
+ function reclassifyInBandStreamError(thrown, inBand) {
14742
+ switch (inBand.vocabulary) {
14743
+ case "anthropic": return reclassifyInBandError(thrown, inBand.error, classifyCommandCodeFailure);
14744
+ case "openai":
14745
+ case "responses": return reclassifyInBandResponsesError(thrown, inBand.error, inBand.message, classifyCommandCodeFailure);
14746
+ }
14747
+ }
14493
14748
  /** Path suffix the chosen route answers on. */
14494
14749
  function endpointPathFor(wire) {
14495
14750
  if (wire === "anthropic") return "/messages";
@@ -15541,6 +15796,24 @@ const DEFAULT_CONTEXT_WINDOW$4 = 128e3;
15541
15796
  * ceiling rather than a claim about what the model can do.
15542
15797
  */
15543
15798
  const DEFAULT_MAX_OUTPUT_TOKENS = 8192;
15799
+ /**
15800
+ * Raise a cap that is too small for this model's forced thinking.
15801
+ *
15802
+ * Left alone: a model whose thinking CAN be disabled - its caller may have asked
15803
+ * for thinking off on purpose, and raising the cap would not enable it while the
15804
+ * number read back would be misleading - and an absent cap, which
15805
+ * `DEFAULT_MAX_OUTPUT_TOKENS` already owns at a size nothing is short of.
15806
+ *
15807
+ * @param modelId - the routed model id.
15808
+ * @param requested - the caller's cap, undefined when it stated none.
15809
+ * @returns the cap to request, raised only when that is the difference between an
15810
+ * empty truncated answer and a usable one.
15811
+ */
15812
+ function floorForcedThinkingTokens$1(modelId, requested) {
15813
+ if (requested === void 0) return void 0;
15814
+ if (thinkingModeForModel(modelId) !== "levels") return requested;
15815
+ return Math.max(requested, 512);
15816
+ }
15544
15817
  /** How long a catalog sync may take before the cached list is used instead. */
15545
15818
  const CATALOG_TIMEOUT_MS = 15e3;
15546
15819
  /**
@@ -16586,6 +16859,23 @@ var OllamaAdapter = class extends LlmAdapter {
16586
16859
  let lastStatus;
16587
16860
  let lastDetail = "";
16588
16861
  let accountId;
16862
+ /**
16863
+ * Set the moment ANY chunk reaches the caller, and never cleared.
16864
+ *
16865
+ * Deliberately broader than "some text arrived": a block start or a tool
16866
+ * call the caller has already seen is exactly as visible as the text, so the
16867
+ * conservative reading is the one that cannot be wrong. It also survives the
16868
+ * pool rotation below, because output an account produced before failing is
16869
+ * still output.
16870
+ */
16871
+ let outputStarted = false;
16872
+ /**
16873
+ * The code a transient in-band failure becomes, or null for this attempt.
16874
+ *
16875
+ * Assigned per failure rather than accumulated, so a later attempt that
16876
+ * failed for a reason of its own is never judged by an earlier one's wording.
16877
+ */
16878
+ let lastInBandCode = null;
16589
16879
  for (;;) {
16590
16880
  let credentials;
16591
16881
  if (pool === null) {
@@ -16613,6 +16903,7 @@ var OllamaAdapter = class extends LlmAdapter {
16613
16903
  if (event.type === "error") {
16614
16904
  lastStatus = openedStatus;
16615
16905
  lastDetail = event.message;
16906
+ lastInBandCode = outputStarted || !(openedStatus !== void 0 && openedStatus >= 200 && openedStatus < 300) ? null : inBandTransientCode(event.message);
16616
16907
  failed = true;
16617
16908
  break;
16618
16909
  }
@@ -16621,12 +16912,18 @@ var OllamaAdapter = class extends LlmAdapter {
16621
16912
  continue;
16622
16913
  }
16623
16914
  if (event.type === "text" || event.type === "thinking" || event.type === "tool_call") {
16624
- for (const chunk of applyEvent(state, event)) yield chunk;
16915
+ for (const chunk of applyEvent(state, event)) {
16916
+ outputStarted = true;
16917
+ yield chunk;
16918
+ }
16625
16919
  continue;
16626
16920
  }
16627
16921
  }
16628
16922
  if (!failed) {
16629
- for (const chunk of closeStream$3(state)) yield chunk;
16923
+ for (const chunk of closeStream$3(state)) {
16924
+ outputStarted = true;
16925
+ yield chunk;
16926
+ }
16630
16927
  if (pool !== null && accountId !== void 0 && spent !== null) await pool.recordUsage(accountId, spent.inputTokens, spent.outputTokens);
16631
16928
  return;
16632
16929
  }
@@ -16646,9 +16943,76 @@ var OllamaAdapter = class extends LlmAdapter {
16646
16943
  const status = lastStatus;
16647
16944
  if (status === 401 || status === 403) throw new LlmError(`${PROVIDER_NAME$4} rejected the API key (${status}). Replace it from Settings > ${PROVIDER_NAME$4}.${lastDetail ? ` ${lastDetail}` : ""}`, "INVALID_CREDENTIAL", { status });
16648
16945
  if (status === 429) throw new LlmError(`${PROVIDER_NAME$4} rate limit or plan quota reached (429). Add another key, or wait for the cooldown shown in Settings > ${PROVIDER_NAME$4}.${lastDetail ? ` ${lastDetail}` : ""}`, "RATE_LIMIT", { status: 429 });
16649
- throw new LlmError(`${PROVIDER_NAME$4} request failed${status === void 0 ? "" : ` (${status})`}.${lastDetail}`, status !== void 0 && status >= 500 ? "SERVER" : "INVALID_REQUEST", status === void 0 ? {} : { status });
16946
+ throw new LlmError(`${PROVIDER_NAME$4} request failed${status === void 0 ? "" : ` (${status})`}.${lastDetail}`, lastInBandCode ?? (status !== void 0 && status >= 500 ? "SERVER" : "INVALID_REQUEST"), status === void 0 ? {} : { status });
16650
16947
  }
16651
16948
  };
16949
+ /**
16950
+ * The DSH code an in-band Ollama failure becomes, or null when the message names
16951
+ * nothing transient.
16952
+ *
16953
+ * Ollama reports a failure inside a 200 as `{"error": "<message>"}` - one string,
16954
+ * no type - so the shared helper's Anthropic table cannot apply and there is no
16955
+ * status to name either. The wording is the whole signal, which is the same
16956
+ * message heuristic the Codex line already reads on `response.failed` in
16957
+ * `responses-client.ts` (generalized for the Responses vocabulary by
16958
+ * `inBandResponsesCode` in `common/stream-error.ts`); it is kept local here
16959
+ * because these are Ollama's own phrasings, not a vocabulary lines share.
16960
+ *
16961
+ * Every phrase below names a condition Ollama reports that clears on its own: a
16962
+ * model still being pulled into memory, a runner that would not start, a server
16963
+ * with no slot for this request, an overloaded or throttled front door. That is
16964
+ * what makes a retry worth taking - the request did not change, so a later one
16965
+ * is genuinely a different bet.
16966
+ *
16967
+ * Deliberately narrow, because the cost of guessing is paid by the user in
16968
+ * backoff. A refusal the wording does not name is usually the service objecting
16969
+ * to the caller's message, and retrying repeats it verbatim: three identical
16970
+ * requests ending in the same verdict, with the real fault unreported. Falling
16971
+ * back to some invented status instead would be worse on both counts, filing an
16972
+ * unrecognized refusal as a retryable server error and inviting the pool chain
16973
+ * to cool an account down for something nothing observed.
16974
+ */
16975
+ function inBandTransientCode(message) {
16976
+ const text = message.toLowerCase();
16977
+ if (IN_BAND_RATE_LIMIT.some((phrase) => text.includes(phrase))) return "RATE_LIMIT";
16978
+ if (IN_BAND_SERVER.some((phrase) => text.includes(phrase))) return "SERVER";
16979
+ return null;
16980
+ }
16981
+ /**
16982
+ * Throttling wording, read first because it is the narrower of the two verdicts.
16983
+ *
16984
+ * The same conditions this line already types RATE_LIMIT for when they arrive as
16985
+ * a 429; a gateway that reports one inside the stream is describing the same
16986
+ * state, and the harness backoff that 429 earns is what the turn should get.
16987
+ */
16988
+ const IN_BAND_RATE_LIMIT = [
16989
+ "rate limit",
16990
+ "rate-limit",
16991
+ "rate_limit",
16992
+ "too many requests",
16993
+ "quota"
16994
+ ];
16995
+ /**
16996
+ * Server-side conditions, in no particular order.
16997
+ *
16998
+ * The model-loading and runner wording covers the two failures Ollama raises while
16999
+ * it is still getting ready to serve - the request was well formed and the
17000
+ * service was not ready for it - and the rest is what its front door says when it
17001
+ * is saturated.
17002
+ */
17003
+ const IN_BAND_SERVER = [
17004
+ "overload",
17005
+ "server busy",
17006
+ "model is loading",
17007
+ "loading model",
17008
+ "couldn't load",
17009
+ "could not load",
17010
+ "unable to load",
17011
+ "failed to load",
17012
+ "runner",
17013
+ "service unavailable",
17014
+ "internal server error"
17015
+ ];
16652
17016
  function isAbort$3(error, signal) {
16653
17017
  return signal?.aborted === true || error instanceof Error && error.name === "AbortError";
16654
17018
  }
@@ -16812,7 +17176,8 @@ async function toOllamaRequest(options, attachments, signal) {
16812
17176
  model: options.model,
16813
17177
  messages
16814
17178
  };
16815
- if (options.maxTokens !== void 0) request.maxOutputTokens = options.maxTokens;
17179
+ const flooredMax = floorForcedThinkingTokens$1(options.model, options.maxTokens);
17180
+ if (flooredMax !== void 0) request.maxOutputTokens = flooredMax;
16816
17181
  if (options.temperature !== void 0) request.temperature = options.temperature;
16817
17182
  const think = thinkForModel(options.model, options.reasoningEffort);
16818
17183
  if (think !== void 0) request.think = think;
@@ -21104,7 +21469,15 @@ function processOpenAIStreamLine(line, state) {
21104
21469
  if (!isRecord$17(chunk)) return [];
21105
21470
  const out = [];
21106
21471
  const errorPayload = isRecord$17(chunk.error) ? chunk.error : void 0;
21107
- if (errorPayload !== void 0) throw new LlmError$1(`Kimi Code stream error: ${asString$9(errorPayload.message) ?? "unknown error"}`, isContextOverflow(errorPayload) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
21472
+ if (errorPayload !== void 0) {
21473
+ const message = asString$9(errorPayload.message) ?? "unknown error";
21474
+ state.streamError = {
21475
+ vocabulary: "openai",
21476
+ error: errorPayload,
21477
+ message
21478
+ };
21479
+ throw new LlmError$1(`Kimi Code stream error: ${message}`, isContextOverflow(errorPayload) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
21480
+ }
21108
21481
  const usage = isRecord$17(chunk.usage) ? chunk.usage : void 0;
21109
21482
  if (usage) {
21110
21483
  state.sawUsage = true;
@@ -21373,7 +21746,13 @@ function processAnthropicStreamLine(line, state) {
21373
21746
  }
21374
21747
  if (type === "error") {
21375
21748
  const error = isRecord$17(event.error) ? event.error : {};
21376
- throw new LlmError$1(`Kimi Code stream error: ${asString$9(error.message) ?? "unknown error"}`, isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
21749
+ const message = asString$9(error.message) ?? "unknown error";
21750
+ state.streamError = {
21751
+ vocabulary: "anthropic",
21752
+ error,
21753
+ message
21754
+ };
21755
+ throw new LlmError$1(`Kimi Code stream error: ${message}`, isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
21377
21756
  }
21378
21757
  return out;
21379
21758
  }
@@ -22014,27 +22393,98 @@ var KimiCodeAdapter = class extends LlmAdapter {
22014
22393
  const state = createStreamState$3(wire, requestOptions.sessionId);
22015
22394
  markSessionActive(requestOptions.sessionId);
22016
22395
  let buffer = "";
22396
+ /**
22397
+ * Set the moment ANY chunk reaches the caller, and never cleared.
22398
+ *
22399
+ * Deliberately broader than "text arrived": a block-start the caller has
22400
+ * already seen repeats just as badly as text it has already read, so the
22401
+ * conservative reading is the one that cannot be wrong. It is what keeps the
22402
+ * in-band reclassification below pre-output only.
22403
+ */
22404
+ let outputStarted = false;
22017
22405
  try {
22018
- while (true) {
22019
- const { done, value } = await reader.read();
22020
- if (done) break;
22021
- buffer += decoder.decode(value, { stream: true });
22022
- const lines = buffer.split("\n");
22023
- buffer = lines.pop() ?? "";
22024
- for (const line of lines) {
22025
- for (const chunk of processLine(line, state, wire)) yield chunk;
22026
- if (state.finished) return;
22406
+ try {
22407
+ while (true) {
22408
+ const { done, value } = await reader.read();
22409
+ if (done) break;
22410
+ buffer += decoder.decode(value, { stream: true });
22411
+ const lines = buffer.split("\n");
22412
+ buffer = lines.pop() ?? "";
22413
+ for (const line of lines) {
22414
+ for (const chunk of processLine(line, state, wire)) {
22415
+ outputStarted = true;
22416
+ yield chunk;
22417
+ }
22418
+ if (state.finished) return;
22419
+ }
22420
+ }
22421
+ buffer += decoder.decode();
22422
+ if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processLine(line, state, wire)) {
22423
+ outputStarted = true;
22424
+ yield chunk;
22027
22425
  }
22426
+ if (state.finished) return;
22427
+ assertStreamComplete$3(state);
22428
+ for (const chunk of closeStream$2(state, servedByAccountId)) {
22429
+ outputStarted = true;
22430
+ yield chunk;
22431
+ }
22432
+ } catch (error) {
22433
+ const inBand = state.streamError;
22434
+ if (error instanceof LlmError && !outputStarted && error.code === "PROVIDER_ERROR" && inBand !== void 0) throw await this.inBandStreamFailure(error, inBand, servedByAccountId);
22435
+ throw error;
22028
22436
  }
22029
- buffer += decoder.decode();
22030
- if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processLine(line, state, wire)) yield chunk;
22031
- if (state.finished) return;
22032
- assertStreamComplete$3(state);
22033
- for (const chunk of closeStream$2(state, servedByAccountId)) yield chunk;
22034
22437
  } finally {
22035
22438
  reader.cancel().catch(() => void 0);
22036
22439
  }
22037
22440
  }
22441
+ /**
22442
+ * What one in-band failure becomes once the pool has been told what the
22443
+ * verdict means for it.
22444
+ *
22445
+ * Reclassification and the pool reaction are separate because they answer
22446
+ * different questions about the same classification: the code decides whether
22447
+ * the harness retries, `accountScoped` decides whether a retry could land
22448
+ * somewhere that can answer. The mapper can supply only the first, which is
22449
+ * why the wire object is recorded there and read here.
22450
+ *
22451
+ * The body is the one a non-2xx response would have carried, so every pattern
22452
+ * below reads exactly what the HTTP branch reads and a limit cannot mean one
22453
+ * thing as a status and another as an event. The request itself is NOT
22454
+ * re-issued: its body is already open and part-read, and the harness retry
22455
+ * policy owns the repeat.
22456
+ */
22457
+ async inBandStreamFailure(thrown, inBand, accountId) {
22458
+ const bodyText = JSON.stringify({ error: inBand.error });
22459
+ const reclassified = inBand.vocabulary === "anthropic" ? reclassifyInBandError(thrown, inBand.error, classifyKimiFailure) : reclassifyInBandResponsesError(thrown, inBand.error, inBand.message, classifyKimiFailure);
22460
+ const pool = this.accountPool;
22461
+ if (pool === null || accountId === void 0) return reclassified;
22462
+ if (inBand.vocabulary === "anthropic") {
22463
+ const status = inBandAnthropicStatus(inBand.error);
22464
+ if (status === null) return reclassified;
22465
+ const failure = classifyKimiFailure(status, bodyText);
22466
+ const planScoped = status === 429 && matchesAny$1(bodyText, ENTITLEMENT_PATTERNS);
22467
+ if (status === 429 && !planScoped) await this.coolInBandRateLimit(pool, accountId, failure.accountScoped, bodyText);
22468
+ else if (failure.code === "INVALID_CREDENTIAL") await pool.markAuthFailed(accountId, failure.message).catch(() => void 0);
22469
+ else if (failure.accountScoped) await pool.markCooldown(accountId, accountLimitCooldownMs(bodyText), `${PROVIDER_NAME$3} in-stream 403`).catch(() => void 0);
22470
+ return reclassified;
22471
+ }
22472
+ if (reclassified.code === "RATE_LIMIT" && !matchesAny$1(bodyText, ENTITLEMENT_PATTERNS)) await this.coolInBandRateLimit(pool, accountId, classifyKimiFailure(429, bodyText).accountScoped, bodyText);
22473
+ return reclassified;
22474
+ }
22475
+ /**
22476
+ * Cool the account whose own rate limit the stream reported.
22477
+ *
22478
+ * The window this route already defaults to, never a Retry-After: there is no
22479
+ * 429 response to read one from, and a delay stated on the 200 belongs to a
22480
+ * different message. An account-scoped verdict takes its own window instead,
22481
+ * because a spent balance is not back-pressure and 15 minutes would put the
22482
+ * account back into rotation four times inside the window that refused it.
22483
+ */
22484
+ async coolInBandRateLimit(pool, accountId, accountScoped, bodyText) {
22485
+ const cooldownMs = accountScoped ? accountLimitCooldownMs(bodyText) : POOL_COOLDOWN_MS$2;
22486
+ await pool.markCooldown(accountId, cooldownMs, `${PROVIDER_NAME$3} in-stream 429`).catch(() => void 0);
22487
+ }
22038
22488
  };
22039
22489
  function processLine(line, state, wire) {
22040
22490
  return wire === "anthropic" ? processAnthropicStreamLine(line, state) : processOpenAIStreamLine(line, state);
@@ -23997,6 +24447,26 @@ function outputConfigFor(modelId, requestedEffort) {
23997
24447
  const effort = effortForModel(modelId, requestedEffort ?? null);
23998
24448
  return effort === "default" ? void 0 : { effort };
23999
24449
  }
24450
+ /**
24451
+ * Raise a cap that is too small for this line's forced thinking.
24452
+ *
24453
+ * Left alone: a model that can disable thinking (its caller may have asked for
24454
+ * thinking off on purpose, and raising the cap would not enable it but a caller
24455
+ * reading the number back would be misled), and an absent cap (the caller stated
24456
+ * none, so \`maxOutputTokensFor\` owns the ceiling).
24457
+ *
24458
+ * @param modelId - the routed model id.
24459
+ * @param requested - the caller's cap, undefined when it stated none.
24460
+ * @returns the cap to request, raised only when that is the difference between an
24461
+ * empty truncated answer and a usable one.
24462
+ */
24463
+ function floorForcedThinkingTokens(modelId, requested) {
24464
+ if (requested === void 0) return void 0;
24465
+ const model = catalogEntry(modelId);
24466
+ const thinking = model?.thinking;
24467
+ if (thinking !== "always-on" && thinking !== "forced-effort") return requested;
24468
+ return Math.min(Math.max(requested, 512), Math.max(requested, model?.maxTokens ?? requested));
24469
+ }
24000
24470
  /** Output cap one request asks for, tracked against the model's declared ceiling. */
24001
24471
  function maxOutputTokensFor$1(modelId, contextWindow) {
24002
24472
  const model = catalogEntry(modelId);
@@ -24515,6 +24985,7 @@ function processMinimaxStreamLine(line, state) {
24515
24985
  }
24516
24986
  if (type === "error") {
24517
24987
  const error = isRecord$16(event.error) ? event.error : {};
24988
+ state.streamError = error;
24518
24989
  throw new LlmError$1("MiniMax Code(编程订阅) stream error: " + (asString$8(error.message) ?? "unknown error"), isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
24519
24990
  }
24520
24991
  return out;
@@ -27175,7 +27646,7 @@ var MinimaxCodeAdapter = class extends LlmAdapter {
27175
27646
  }
27176
27647
  let authOwner = computeMinimaxAuthOwner(credentials, accountId);
27177
27648
  const withUploads = await uploadOversizedMedia(requestOptions, images, videos, credentials, accountId, this.options.fetchFn ?? fetch, signal);
27178
- const effectiveMax = clampOutputToContext(requestOptions.maxTokens ?? maxOutputTokensFor$1(options.model, contextWindow), contextWindow, estimatedInputTokens(requestOptions));
27649
+ const effectiveMax = clampOutputToContext(floorForcedThinkingTokens(options.model, requestOptions.maxTokens) ?? maxOutputTokensFor$1(options.model, contextWindow), contextWindow, estimatedInputTokens(requestOptions));
27179
27650
  const buildBodyForOwner = (owner) => {
27180
27651
  return assertRequestBodyFits(buildMinimaxRequest({
27181
27652
  ...withUploads,
@@ -27235,23 +27706,46 @@ var MinimaxCodeAdapter = class extends LlmAdapter {
27235
27706
  provider: PROVIDER_ID$2
27236
27707
  });
27237
27708
  let buffer = "";
27709
+ /**
27710
+ * Set the moment ANY chunk reaches the caller, and never cleared.
27711
+ *
27712
+ * Deliberately broader than "a content delta or a tool block": a retry would
27713
+ * duplicate a block-start the caller has already seen just as surely, so the
27714
+ * conservative reading is the one that cannot be wrong. It is what keeps the
27715
+ * in-band reclassification below pre-output only.
27716
+ */
27717
+ let outputStarted = false;
27238
27718
  try {
27239
- while (true) {
27240
- const { done, value } = await reader.read();
27241
- if (done) break;
27242
- buffer += decoder.decode(value, { stream: true });
27243
- const lines = buffer.split("\n");
27244
- buffer = lines.pop() ?? "";
27245
- for (const line of lines) {
27246
- for (const chunk of processMinimaxStreamLine(line, state)) yield chunk;
27247
- if (state.finished) return;
27719
+ try {
27720
+ while (true) {
27721
+ const { done, value } = await reader.read();
27722
+ if (done) break;
27723
+ buffer += decoder.decode(value, { stream: true });
27724
+ const lines = buffer.split("\n");
27725
+ buffer = lines.pop() ?? "";
27726
+ for (const line of lines) {
27727
+ for (const chunk of processMinimaxStreamLine(line, state)) {
27728
+ outputStarted = true;
27729
+ yield chunk;
27730
+ }
27731
+ if (state.finished) return;
27732
+ }
27248
27733
  }
27734
+ buffer += decoder.decode();
27735
+ if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processMinimaxStreamLine(line, state)) {
27736
+ outputStarted = true;
27737
+ yield chunk;
27738
+ }
27739
+ if (state.finished) return;
27740
+ assertStreamComplete(state);
27741
+ for (const chunk of closeMinimaxStream(state)) {
27742
+ outputStarted = true;
27743
+ yield chunk;
27744
+ }
27745
+ } catch (error) {
27746
+ if (error instanceof LlmError && !outputStarted && error.code === "PROVIDER_ERROR" && state.streamError !== void 0) throw reclassifyInBandError(error, state.streamError, classifyMinimaxFailure);
27747
+ throw error;
27249
27748
  }
27250
- buffer += decoder.decode();
27251
- if (buffer.trim() !== "") for (const line of buffer.split("\n")) for (const chunk of processMinimaxStreamLine(line, state)) yield chunk;
27252
- if (state.finished) return;
27253
- assertStreamComplete(state);
27254
- for (const chunk of closeMinimaxStream(state)) yield chunk;
27255
27749
  } finally {
27256
27750
  reader.cancel().catch(() => void 0);
27257
27751
  }
@@ -36641,6 +37135,7 @@ function processStreamLine(line, state) {
36641
37135
  const error = isRecord$5(event.error) ? event.error : {};
36642
37136
  const message = asString$2(error.message) ?? "unknown error";
36643
37137
  const kind = asString$2(error.type);
37138
+ state.streamError = error;
36644
37139
  throw new LlmError$1("Claude stream error" + (kind === void 0 ? "" : " (" + kind + ")") + ": " + message, isContextOverflow(error) ? CONTEXT_OVERFLOW_CODE : "PROVIDER_ERROR");
36645
37140
  }
36646
37141
  return out;
@@ -37814,6 +38309,13 @@ function cancelLogin() {
37814
38309
  * - `request` -> PROVIDER_ERROR;
37815
38310
  * - `network` -> TRANSPORT.
37816
38311
  *
38312
+ * An in-band `error` event inside a 200 stream carries the same envelope and is
38313
+ * classified the same way while nothing has reached the caller; after the first
38314
+ * chunk it is surfaced as PROVIDER_ERROR, for the reason in note 1
38315
+ * ({@link inBandStreamVerdict}). A reclassified in-band failure is weighed by
38316
+ * {@link shouldRotateAccount} exactly as a non-2xx one is, so an account-scoped
38317
+ * limit reported inside the stream still takes that account out of rotation.
38318
+ *
37817
38319
  * A reported-client-version rejection is a REQUEST problem even though it
37818
38320
  * arrives as a 400 that mentions the client: it must NOT sign the user out, and
37819
38321
  * it has a real remedy (raise the reported version), so it is handled
@@ -38213,8 +38715,19 @@ var ClaudeAdapter = class ClaudeAdapter extends LlmAdapter {
38213
38715
  * a later reordering of this method cannot silently drop it.
38214
38716
  */
38215
38717
  let outputStarted = false;
38718
+ /**
38719
+ * The account the response now being streamed was issued with.
38720
+ *
38721
+ * Hoisted out of the loop because the in-stream failure path needs it: a
38722
+ * rate limit reported inside a 200 stream belongs to the account that was
38723
+ * asked, and that account is what the failure takes out of rotation — the
38724
+ * harness is about to repeat this request, and repeating it against the same
38725
+ * exhausted account fails identically.
38726
+ */
38727
+ let usedAccountId;
38216
38728
  while (true) {
38217
38729
  const { credentials, accountId } = await this.resolveCredential(pool, tried, fetchFn, signal);
38730
+ usedAccountId = accountId;
38218
38731
  response = await this.attemptRequest(credentials, requestOptions, images, toolNames, thinking, settings, signal, fetchFn);
38219
38732
  if (response.ok) break;
38220
38733
  const detail = (await response.text().catch(() => "")).slice(0, 2e3);
@@ -38260,7 +38773,12 @@ var ClaudeAdapter = class ClaudeAdapter extends LlmAdapter {
38260
38773
  yield chunk;
38261
38774
  }
38262
38775
  } catch (error) {
38263
- if (error instanceof LlmError) throw error;
38776
+ if (error instanceof LlmError) {
38777
+ if (outputStarted || error.code !== "PROVIDER_ERROR" || state.streamError === void 0) throw error;
38778
+ const verdict = inBandStreamVerdict(error, state.streamError, response.headers);
38779
+ if (verdict.failure !== null && shouldRotateAccount(verdict.failure, outputStarted) && usedAccountId !== void 0) await pool?.markCooldown(usedAccountId, cooldownMsFor(verdict.failure), "Claude(订阅) in-stream 429").catch(() => void 0);
38780
+ throw verdict.error;
38781
+ }
38264
38782
  if (signal.aborted) throw new LlmError("Claude request aborted", "ABORTED", { cause: error });
38265
38783
  throw new LlmError("Claude stream failed: " + (error instanceof Error ? error.message : String(error)), outputStarted ? "PROVIDER_ERROR" : "TRANSPORT", { cause: error });
38266
38784
  }
@@ -38350,6 +38868,49 @@ function codeForFailure(failure) {
38350
38868
  return "PROVIDER_ERROR";
38351
38869
  }
38352
38870
  /**
38871
+ * The DSH error an in-band `error` event becomes when it arrived BEFORE any
38872
+ * chunk reached the caller.
38873
+ *
38874
+ * Anthropic can answer 200 and then report the failure inside the stream, in
38875
+ * the same `{ error: { type, message } }` envelope a non-2xx body carries. The
38876
+ * mapper types every such event PROVIDER_ERROR, because it cannot know whether
38877
+ * output has started — and PROVIDER_ERROR is outside the retry set, so an
38878
+ * `overloaded_error` delivered this way ended the turn on the first try while
38879
+ * the identical overload delivered as a 529 is retried. Before any output a
38880
+ * fresh request is still free (module note 1), so the envelope is classified
38881
+ * exactly as a response body would be, and a transient verdict (overloaded,
38882
+ * server, rate limit) takes its retryable code.
38883
+ *
38884
+ * Everything else keeps the mapper's verdict: a request problem, a context
38885
+ * overflow, a credential refusal, and a type this line does not recognize. The
38886
+ * last matters: classifyFailure falls back to the status line for an unknown
38887
+ * type, and no status here describes the failure — the response itself was a
38888
+ * 200 — so the status passed is 0 and never consulted for a recognized type.
38889
+ *
38890
+ * The message stays the mapper's, which names the wire type the user saw.
38891
+ *
38892
+ * The classified failure rides along beside the error so the caller can weigh it
38893
+ * with {@link shouldRotateAccount} instead of re-deriving what it says. It is
38894
+ * null whenever the mapper's verdict stands, so a caller never has to guess
38895
+ * whether `accountScoped` is meaningful.
38896
+ *
38897
+ * @param thrown - the mapper's PROVIDER_ERROR (or context-overflow) verdict.
38898
+ * @param streamError - the event's wire `error` object, from the stream state.
38899
+ * @param headers - the 200 response's headers, read for the rate-limit verdict.
38900
+ */
38901
+ function inBandStreamVerdict(thrown, streamError, headers) {
38902
+ const failure = classifyFailure(0, JSON.stringify({ error: streamError }), headers);
38903
+ if (failure.type === null || !failure.retryable) return {
38904
+ error: thrown,
38905
+ failure: null
38906
+ };
38907
+ const retryAfter = failure.retryAfterMs !== null && failure.retryAfterMs > 0 ? failure.retryAfterMs : void 0;
38908
+ return {
38909
+ error: new LlmError(thrown.message, codeForFailure(failure), retryAfter === void 0 ? {} : { providerRetryAfterMs: retryAfter }),
38910
+ failure
38911
+ };
38912
+ }
38913
+ /**
38353
38914
  * Turn one classified failure into the DSH error the caller sees.
38354
38915
  *
38355
38916
  * The facts the harness needs ride along: the HTTP status, and the delay the