@dan-ai-studio/dshopencodego 0.1.88 → 0.1.90

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
@@ -342,11 +342,45 @@ var init_resolve = __esm({
342
342
  }
343
343
  });
344
344
 
345
+ // node_modules/@earendil-works/pi-ai/dist/utils/text.js
346
+ function contentText(content, separator = "\n") {
347
+ if (typeof content === "string")
348
+ return content;
349
+ return content.filter((block) => block.type === "text").map((block) => block.text).join(separator);
350
+ }
351
+ function getSystemMessageText(message) {
352
+ const parts = [contentText(message.content)];
353
+ for (const text2 of Object.values(message.sections ?? {})) {
354
+ if (text2 !== null)
355
+ parts.push(text2);
356
+ }
357
+ return parts.filter((part) => part.length > 0).join("\n\n");
358
+ }
359
+ function renderSystemMessageUpdate(message) {
360
+ const parts = [];
361
+ const text2 = contentText(message.content);
362
+ if (text2.length > 0)
363
+ parts.push(text2);
364
+ for (const [name2, value] of Object.entries(message.sections ?? {})) {
365
+ parts.push(value === null ? `Removed system prompt section "${name2}".` : `Updated system prompt section "${name2}":
366
+
367
+ ${value}`);
368
+ }
369
+ return parts.join("\n\n");
370
+ }
371
+ function ownedSlice(text2, start, end = text2.length) {
372
+ return `${text2.slice(start, end)} `.slice(0, -1);
373
+ }
374
+ var init_text = __esm({
375
+ "node_modules/@earendil-works/pi-ai/dist/utils/text.js"() {
376
+ }
377
+ });
378
+
345
379
  // node_modules/@earendil-works/pi-ai/dist/utils/version.js
346
380
  var PI_AI_VERSION;
347
381
  var init_version = __esm({
348
382
  "node_modules/@earendil-works/pi-ai/dist/utils/version.js"() {
349
- PI_AI_VERSION = "1.4.0";
383
+ PI_AI_VERSION = "1.5.0";
350
384
  }
351
385
  });
352
386
 
@@ -454,37 +488,6 @@ var init_model_operations = __esm({
454
488
  }
455
489
  });
456
490
 
457
- // node_modules/@earendil-works/pi-ai/dist/utils/text.js
458
- function contentText(content, separator = "\n") {
459
- if (typeof content === "string")
460
- return content;
461
- return content.filter((block) => block.type === "text").map((block) => block.text).join(separator);
462
- }
463
- function getSystemMessageText(message) {
464
- const parts = [contentText(message.content)];
465
- for (const text2 of Object.values(message.sections ?? {})) {
466
- if (text2 !== null)
467
- parts.push(text2);
468
- }
469
- return parts.filter((part) => part.length > 0).join("\n\n");
470
- }
471
- function renderSystemMessageUpdate(message) {
472
- const parts = [];
473
- const text2 = contentText(message.content);
474
- if (text2.length > 0)
475
- parts.push(text2);
476
- for (const [name2, value] of Object.entries(message.sections ?? {})) {
477
- parts.push(value === null ? `Removed system prompt section "${name2}".` : `Updated system prompt section "${name2}":
478
-
479
- ${value}`);
480
- }
481
- return parts.join("\n\n");
482
- }
483
- var init_text = __esm({
484
- "node_modules/@earendil-works/pi-ai/dist/utils/text.js"() {
485
- }
486
- });
487
-
488
491
  // node_modules/@earendil-works/pi-ai/dist/utils/transcript.js
489
492
  function createInitialSystemMessage(systemPrompt, tools) {
490
493
  const hasSystemPrompt = systemPrompt !== void 0 && systemPrompt.length > 0;
@@ -731,6 +734,7 @@ function calculateCost(model, usage) {
731
734
  usage.cost.cacheRead = rates2.cacheRead / 1e6 * usage.cacheRead;
732
735
  usage.cost.cacheWrite = (rates2.cacheWrite * shortWrite + rates2.input * 2 * longWrite) / 1e6;
733
736
  usage.cost.total = usage.cost.input + usage.cost.output + usage.cost.cacheRead + usage.cost.cacheWrite;
737
+ usage.cost.totalFromProvider = false;
734
738
  return usage.cost;
735
739
  }
736
740
  function getSupportedThinkingLevels(model) {
@@ -18293,26 +18297,6 @@ ${json}`
18293
18297
  };
18294
18298
  }
18295
18299
  }
18296
- function parseStreamingJson(partialJson) {
18297
- if (!partialJson || partialJson.trim() === "") {
18298
- return {};
18299
- }
18300
- try {
18301
- return parseJsonWithRepair(partialJson);
18302
- } catch {
18303
- try {
18304
- const result = (0, import_partial_json.parse)(partialJson);
18305
- return result ?? {};
18306
- } catch {
18307
- try {
18308
- const result = (0, import_partial_json.parse)(repairJson(partialJson));
18309
- return result ?? {};
18310
- } catch {
18311
- return {};
18312
- }
18313
- }
18314
- }
18315
- }
18316
18300
  var import_partial_json, VALID_JSON_ESCAPES;
18317
18301
  var init_json_parse = __esm({
18318
18302
  "node_modules/@earendil-works/pi-ai/dist/utils/json-parse.js"() {
@@ -18321,6 +18305,43 @@ var init_json_parse = __esm({
18321
18305
  }
18322
18306
  });
18323
18307
 
18308
+ // node_modules/@earendil-works/pi-ai/dist/utils/openrouter-cost.js
18309
+ function isValidCost(value) {
18310
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
18311
+ }
18312
+ function isOpenRouterModel(model) {
18313
+ return model.provider === "openrouter" || model.baseUrl.includes("openrouter.ai");
18314
+ }
18315
+ function applyOpenRouterReportedCost(usage, reported) {
18316
+ if (!isValidCost(reported.cost))
18317
+ return;
18318
+ if (reported.is_byok === false) {
18319
+ usage.cost.total = reported.cost;
18320
+ usage.cost.totalFromProvider = true;
18321
+ return;
18322
+ }
18323
+ if (reported.is_byok === true) {
18324
+ const details = reported.cost_details;
18325
+ if (!details)
18326
+ return;
18327
+ let upstreamCost = details.upstream_inference_cost;
18328
+ if (upstreamCost === null) {
18329
+ if (!isValidCost(details.upstream_inference_prompt_cost) || !isValidCost(details.upstream_inference_completions_cost)) {
18330
+ return;
18331
+ }
18332
+ upstreamCost = details.upstream_inference_prompt_cost + details.upstream_inference_completions_cost;
18333
+ }
18334
+ if (!isValidCost(upstreamCost))
18335
+ return;
18336
+ usage.cost.total = reported.cost + upstreamCost;
18337
+ usage.cost.totalFromProvider = true;
18338
+ }
18339
+ }
18340
+ var init_openrouter_cost = __esm({
18341
+ "node_modules/@earendil-works/pi-ai/dist/utils/openrouter-cost.js"() {
18342
+ }
18343
+ });
18344
+
18324
18345
  // node_modules/@earendil-works/pi-ai/dist/utils/provider-retry.js
18325
18346
  function isProviderError(error) {
18326
18347
  if (!(error instanceof Error) || !("status" in error) || !("headers" in error))
@@ -18418,6 +18439,451 @@ var init_sanitize_unicode = __esm({
18418
18439
  }
18419
18440
  });
18420
18441
 
18442
+ // node_modules/@earendil-works/pi-ai/dist/utils/streaming-json.js
18443
+ function isDelimiter(char) {
18444
+ return char === " " || char === " " || char === "\n" || char === "\r" || char === "," || char === ":" || char === "{" || char === "}" || char === "[" || char === "]" || char === '"';
18445
+ }
18446
+ function isHexDigit(char) {
18447
+ return char >= "0" && char <= "9" || char >= "a" && char <= "f" || char >= "A" && char <= "F";
18448
+ }
18449
+ function scalarValue(token) {
18450
+ for (const [literal, value] of LITERALS)
18451
+ if (token === literal)
18452
+ return value;
18453
+ return NUMBER.test(token) ? Number(token) : void 0;
18454
+ }
18455
+ function pendingScalarValue(token) {
18456
+ for (const [literal, value] of LITERALS)
18457
+ if (literal.startsWith(token))
18458
+ return value;
18459
+ if (NUMBER.test(token))
18460
+ return Number(token);
18461
+ const mantissa = NUMBER_WITHOUT_EXPONENT_DIGITS.exec(token);
18462
+ return mantissa === null ? void 0 : Number(mantissa[1]);
18463
+ }
18464
+ function setSlot(container, slot, value) {
18465
+ if (slot.kind === "element")
18466
+ container[slot.index] = value;
18467
+ else if (slot.kind === "member")
18468
+ setMember(container, slot.key, value);
18469
+ }
18470
+ function setMember(members, key, value) {
18471
+ if (key === "__proto__") {
18472
+ Object.defineProperty(members, key, { value, writable: true, enumerable: true, configurable: true });
18473
+ } else {
18474
+ members[key] = value;
18475
+ }
18476
+ }
18477
+ var MAX_REPORTED_DEPTH, ROOT_SLOT, CREDIT_PER_APPEND, CREDIT_PER_CHARACTER, MAX_PENDING_SCALAR_LENGTH, NUMBER, NUMBER_WITHOUT_EXPONENT_DIGITS, LITERALS, QUOTE, BACKSLASH, StreamingJsonParser, ToolCallArgumentsStream, SIMPLE_ESCAPES;
18478
+ var init_streaming_json = __esm({
18479
+ "node_modules/@earendil-works/pi-ai/dist/utils/streaming-json.js"() {
18480
+ init_json_parse();
18481
+ MAX_REPORTED_DEPTH = 32;
18482
+ ROOT_SLOT = { kind: "root" };
18483
+ CREDIT_PER_APPEND = 256;
18484
+ CREDIT_PER_CHARACTER = 8;
18485
+ MAX_PENDING_SCALAR_LENGTH = 64;
18486
+ NUMBER = /^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
18487
+ NUMBER_WITHOUT_EXPONENT_DIGITS = /^(-?(?:0|[1-9]\d*)(?:\.\d+)?)[eE][+-]?$/;
18488
+ LITERALS = [
18489
+ ["true", true],
18490
+ ["false", false],
18491
+ ["null", null]
18492
+ ];
18493
+ QUOTE = 34;
18494
+ BACKSLASH = 92;
18495
+ StreamingJsonParser = class {
18496
+ #root = void 0;
18497
+ #done = false;
18498
+ #stack = [];
18499
+ #string = void 0;
18500
+ #scalar = "";
18501
+ #scalarSlot = void 0;
18502
+ /** Sum of `size + 1` over the open path: what a fresh snapshot copies. */
18503
+ #pathCost = 0;
18504
+ #credit = 0;
18505
+ #dirty = false;
18506
+ #snapshot = void 0;
18507
+ /** Changes of the piece being read. */
18508
+ #changes = [];
18509
+ /**
18510
+ * Read the next piece of text; returns the changes it made, in order. Costs time linear in `text.length`.
18511
+ */
18512
+ append(text2) {
18513
+ this.#credit += CREDIT_PER_APPEND + CREDIT_PER_CHARACTER * text2.length;
18514
+ this.#changes = [];
18515
+ if (this.#string !== void 0)
18516
+ this.#string.change = void 0;
18517
+ let index = 0;
18518
+ while (index < text2.length && !this.#done) {
18519
+ const open = this.#string;
18520
+ if (open !== void 0)
18521
+ index = this.#readString(open, text2, index);
18522
+ else if (this.#scalar !== "")
18523
+ index = this.#readScalar(text2, index);
18524
+ else
18525
+ this.#structural(text2[index++]);
18526
+ }
18527
+ return this.#changes;
18528
+ }
18529
+ /**
18530
+ * The value of the text read so far: `undefined` before a value starts, otherwise a plain JSON value that never
18531
+ * changes afterwards. Returns the previous snapshot while the text read since did not change the value, or while a
18532
+ * fresh copy of the open path is not yet paid for (see the module comment).
18533
+ */
18534
+ snapshot() {
18535
+ if (!this.#dirty)
18536
+ return this.#snapshot;
18537
+ const pending = this.#pendingScalar();
18538
+ const cost = this.#pathCost + (pending === void 0 ? 0 : 1);
18539
+ if (cost > this.#credit)
18540
+ return this.#snapshot;
18541
+ this.#credit -= cost;
18542
+ this.#dirty = false;
18543
+ this.#snapshot = this.#copyOpenPath(pending);
18544
+ return this.#snapshot;
18545
+ }
18546
+ /** Read string characters from `start` until the string ends or the text does; returns the next index. */
18547
+ #readString(open, text2, start) {
18548
+ let runStart = start;
18549
+ for (let index = start; index < text2.length; index++) {
18550
+ const code = text2.charCodeAt(index);
18551
+ if (open.escape !== "") {
18552
+ if (this.#continueEscape(open, text2[index])) {
18553
+ runStart = index + 1;
18554
+ continue;
18555
+ }
18556
+ runStart = index;
18557
+ }
18558
+ if (code === QUOTE) {
18559
+ if (index > runStart)
18560
+ this.#appendString(open, text2.slice(runStart, index));
18561
+ this.#endString(open);
18562
+ return index + 1;
18563
+ }
18564
+ if (code === BACKSLASH) {
18565
+ if (index > runStart)
18566
+ this.#appendString(open, text2.slice(runStart, index));
18567
+ open.escape = "\\";
18568
+ runStart = index + 1;
18569
+ }
18570
+ }
18571
+ if (text2.length > runStart)
18572
+ this.#appendString(open, text2.slice(runStart));
18573
+ return text2.length;
18574
+ }
18575
+ /** Read number or literal characters from `start` up to the next delimiter; returns the delimiter's index. */
18576
+ #readScalar(text2, start) {
18577
+ let end = start;
18578
+ while (end < text2.length && !isDelimiter(text2[end]))
18579
+ end++;
18580
+ if (end > start) {
18581
+ this.#scalar += text2.slice(start, end);
18582
+ if (this.#scalarSlot !== void 0)
18583
+ this.#dirty = true;
18584
+ }
18585
+ if (end < text2.length)
18586
+ this.#endScalar();
18587
+ return end;
18588
+ }
18589
+ /** Handle one character outside strings. */
18590
+ #structural(char) {
18591
+ switch (char) {
18592
+ case " ":
18593
+ case " ":
18594
+ case "\n":
18595
+ case "\r":
18596
+ return;
18597
+ case '"':
18598
+ this.#startString();
18599
+ return;
18600
+ case "{":
18601
+ case "[":
18602
+ this.#openContainer(char === "{" ? {} : []);
18603
+ return;
18604
+ case "}":
18605
+ case "]":
18606
+ this.#closeContainer();
18607
+ return;
18608
+ case ":": {
18609
+ const frame = this.#stack.at(-1);
18610
+ if (frame !== void 0 && !Array.isArray(frame.container) && frame.phase === "colon")
18611
+ frame.phase = "value";
18612
+ return;
18613
+ }
18614
+ case ",": {
18615
+ const frame = this.#stack.at(-1);
18616
+ if (frame !== void 0)
18617
+ frame.phase = Array.isArray(frame.container) ? "value" : "key";
18618
+ return;
18619
+ }
18620
+ default:
18621
+ this.#scalar = char;
18622
+ this.#scalarSlot = this.#valueSlot();
18623
+ if (this.#scalarSlot !== void 0)
18624
+ this.#dirty = true;
18625
+ }
18626
+ }
18627
+ /** Where a value starting now goes, or `undefined` when this position takes no value. */
18628
+ #valueSlot() {
18629
+ const frame = this.#stack.at(-1);
18630
+ if (frame === void 0)
18631
+ return this.#root === void 0 ? ROOT_SLOT : void 0;
18632
+ if (Array.isArray(frame.container))
18633
+ return { kind: "element", index: frame.container.length };
18634
+ if ((frame.phase === "value" || frame.phase === "colon") && frame.key !== void 0) {
18635
+ return { kind: "member", key: frame.key };
18636
+ }
18637
+ return void 0;
18638
+ }
18639
+ #startString() {
18640
+ const frame = this.#stack.at(-1);
18641
+ if (frame !== void 0 && !Array.isArray(frame.container) && (frame.phase === "key" || frame.phase === "comma")) {
18642
+ this.#string = { target: "key", slot: void 0, text: "", escape: "", path: void 0, change: void 0 };
18643
+ return;
18644
+ }
18645
+ const slot = this.#valueSlot();
18646
+ const path5 = this.#reportedPath(slot);
18647
+ this.#string = { target: "value", slot, text: "", escape: "", path: path5, change: void 0 };
18648
+ this.#place(slot, "");
18649
+ if (path5 !== void 0)
18650
+ this.#string.change = this.#report({ kind: "set", path: path5, value: "" });
18651
+ }
18652
+ /** The path of a value at `slot` in the innermost open container, when its changes are reported. */
18653
+ #reportedPath(slot) {
18654
+ if (slot === void 0)
18655
+ return void 0;
18656
+ if (slot.kind === "root")
18657
+ return [];
18658
+ const frame = this.#stack.at(-1);
18659
+ if (!frame.reportsInside)
18660
+ return void 0;
18661
+ return [...frame.path, slot.kind === "member" ? slot.key : slot.index];
18662
+ }
18663
+ #report(change) {
18664
+ this.#changes.push(change);
18665
+ return change;
18666
+ }
18667
+ /** Continue an escape with `char`; returns false when `char` is not part of it and must be read normally. */
18668
+ #continueEscape(open, char) {
18669
+ if (open.escape === "\\") {
18670
+ const decoded = SIMPLE_ESCAPES[char];
18671
+ if (decoded !== void 0) {
18672
+ open.escape = "";
18673
+ this.#appendString(open, decoded);
18674
+ return true;
18675
+ }
18676
+ if (char === "u") {
18677
+ open.escape = "\\u";
18678
+ return true;
18679
+ }
18680
+ open.escape = "";
18681
+ this.#appendString(open, "\\");
18682
+ return false;
18683
+ }
18684
+ if (isHexDigit(char)) {
18685
+ open.escape += char;
18686
+ if (open.escape.length < 6)
18687
+ return true;
18688
+ const decoded = String.fromCharCode(Number.parseInt(open.escape.slice(2), 16));
18689
+ open.escape = "";
18690
+ this.#appendString(open, decoded);
18691
+ return true;
18692
+ }
18693
+ const literal = open.escape;
18694
+ open.escape = "";
18695
+ this.#appendString(open, literal);
18696
+ return false;
18697
+ }
18698
+ #appendString(open, text2) {
18699
+ open.text += text2;
18700
+ if (open.target !== "value")
18701
+ return;
18702
+ this.#place(open.slot, open.text);
18703
+ if (open.path === void 0)
18704
+ return;
18705
+ const change = open.change;
18706
+ if (change !== void 0 && this.#changes.at(-1) === change) {
18707
+ if (change.kind === "set")
18708
+ change.value = change.value + text2;
18709
+ else
18710
+ change.text += text2;
18711
+ return;
18712
+ }
18713
+ open.change = this.#report({ kind: "append", path: open.path, text: text2 });
18714
+ }
18715
+ #endString(open) {
18716
+ this.#string = void 0;
18717
+ const frame = this.#stack.at(-1);
18718
+ if (open.target === "key") {
18719
+ if (frame === void 0)
18720
+ return;
18721
+ frame.key = open.text;
18722
+ frame.phase = "colon";
18723
+ return;
18724
+ }
18725
+ this.#valueEnded(frame);
18726
+ }
18727
+ #endScalar() {
18728
+ const token = this.#scalar;
18729
+ const slot = this.#scalarSlot;
18730
+ this.#scalar = "";
18731
+ this.#scalarSlot = void 0;
18732
+ const value = scalarValue(token);
18733
+ if (value !== void 0) {
18734
+ this.#place(slot, value);
18735
+ const path5 = this.#reportedPath(slot);
18736
+ if (path5 !== void 0)
18737
+ this.#report({ kind: "set", path: path5, value });
18738
+ }
18739
+ this.#valueEnded(this.#stack.at(-1));
18740
+ }
18741
+ /** The value of the unterminated scalar at the end of the text, if it shows. */
18742
+ #pendingScalar() {
18743
+ const slot = this.#scalarSlot;
18744
+ const token = this.#scalar;
18745
+ if (slot === void 0 || token === "" || token.length > MAX_PENDING_SCALAR_LENGTH)
18746
+ return void 0;
18747
+ const value = pendingScalarValue(token);
18748
+ return value === void 0 ? void 0 : { slot, value };
18749
+ }
18750
+ #openContainer(container) {
18751
+ const slot = this.#valueSlot();
18752
+ const path5 = this.#reportedPath(slot);
18753
+ this.#place(slot, container);
18754
+ this.#stack.push({
18755
+ container,
18756
+ slot,
18757
+ path: path5,
18758
+ reportsInside: path5 !== void 0 && path5.length < MAX_REPORTED_DEPTH,
18759
+ size: 0,
18760
+ key: void 0,
18761
+ phase: Array.isArray(container) ? "value" : "key"
18762
+ });
18763
+ this.#pathCost += 1;
18764
+ this.#dirty = true;
18765
+ if (path5 !== void 0)
18766
+ this.#report({ kind: "set", path: path5, value: Array.isArray(container) ? [] : {} });
18767
+ }
18768
+ #closeContainer() {
18769
+ const frame = this.#stack.pop();
18770
+ if (frame === void 0)
18771
+ return;
18772
+ this.#pathCost -= frame.size + 1;
18773
+ this.#dirty = true;
18774
+ if (frame.path !== void 0 && !frame.reportsInside) {
18775
+ this.#report({ kind: "set", path: frame.path, value: frame.container });
18776
+ }
18777
+ this.#valueEnded(this.#stack.at(-1));
18778
+ }
18779
+ /** A value in `frame`, or the root value when there is no frame, has ended. */
18780
+ #valueEnded(frame) {
18781
+ if (frame === void 0) {
18782
+ if (this.#root !== void 0)
18783
+ this.#done = true;
18784
+ return;
18785
+ }
18786
+ frame.phase = "comma";
18787
+ }
18788
+ /** Set the value at `slot` in the open path; nothing for a value in an invalid position. */
18789
+ #place(slot, value) {
18790
+ if (slot === void 0)
18791
+ return;
18792
+ this.#dirty = true;
18793
+ if (slot.kind === "root") {
18794
+ this.#root = value;
18795
+ return;
18796
+ }
18797
+ const frame = this.#stack.at(-1);
18798
+ if (slot.kind === "element") {
18799
+ const elements = frame.container;
18800
+ if (slot.index === elements.length) {
18801
+ frame.size++;
18802
+ this.#pathCost++;
18803
+ }
18804
+ elements[slot.index] = value;
18805
+ return;
18806
+ }
18807
+ const members = frame.container;
18808
+ if (!Object.hasOwn(members, slot.key)) {
18809
+ frame.size++;
18810
+ this.#pathCost++;
18811
+ }
18812
+ setMember(members, slot.key, value);
18813
+ }
18814
+ /** A fresh snapshot: copies of the open containers, innermost first, each holding the copy of its open child. */
18815
+ #copyOpenPath(pending) {
18816
+ if (this.#stack.length === 0)
18817
+ return pending?.slot.kind === "root" ? pending.value : this.#root;
18818
+ let child;
18819
+ let childSlot;
18820
+ for (let depth = this.#stack.length - 1; depth >= 0; depth--) {
18821
+ const frame = this.#stack[depth];
18822
+ const copy = Array.isArray(frame.container) ? frame.container.slice() : { ...frame.container };
18823
+ if (depth === this.#stack.length - 1 && pending !== void 0)
18824
+ setSlot(copy, pending.slot, pending.value);
18825
+ if (child !== void 0 && childSlot !== void 0)
18826
+ setSlot(copy, childSlot, child);
18827
+ child = copy;
18828
+ childSlot = frame.slot;
18829
+ }
18830
+ return childSlot?.kind === "root" ? child : this.#root;
18831
+ }
18832
+ };
18833
+ ToolCallArgumentsStream = class {
18834
+ #text = "";
18835
+ #parser = new StreamingJsonParser();
18836
+ #snapshot = void 0;
18837
+ #arguments = {};
18838
+ /** The raw argument text received so far. */
18839
+ get text() {
18840
+ return this.#text;
18841
+ }
18842
+ /** Append a piece of argument text; returns the partial arguments, a new object whenever they changed. */
18843
+ append(delta) {
18844
+ this.#text += delta;
18845
+ this.#parser.append(delta);
18846
+ return this.#partial();
18847
+ }
18848
+ /**
18849
+ * Take the provider's complete argument text. When it continues the text so far, returns the missing piece as
18850
+ * `delta`; otherwise starts over with `text`. Either way returns the partial arguments of `text`.
18851
+ */
18852
+ replace(text2) {
18853
+ if (text2.startsWith(this.#text)) {
18854
+ const delta = text2.slice(this.#text.length);
18855
+ return { delta, arguments: delta === "" ? this.#partial() : this.append(delta) };
18856
+ }
18857
+ this.#text = "";
18858
+ this.#parser = new StreamingJsonParser();
18859
+ return { delta: void 0, arguments: this.append(text2) };
18860
+ }
18861
+ /** The final arguments: one full parse of the complete text, which reports malformed arguments. */
18862
+ finish() {
18863
+ return parseToolCallArguments(this.#text);
18864
+ }
18865
+ #partial() {
18866
+ const snapshot2 = this.#parser.snapshot();
18867
+ if (snapshot2 === this.#snapshot)
18868
+ return this.#arguments;
18869
+ this.#snapshot = snapshot2;
18870
+ this.#arguments = typeof snapshot2 === "object" && snapshot2 !== null && !Array.isArray(snapshot2) ? snapshot2 : {};
18871
+ return this.#arguments;
18872
+ }
18873
+ };
18874
+ SIMPLE_ESCAPES = {
18875
+ '"': '"',
18876
+ "\\": "\\",
18877
+ "/": "/",
18878
+ b: "\b",
18879
+ f: "\f",
18880
+ n: "\n",
18881
+ r: "\r",
18882
+ t: " "
18883
+ };
18884
+ }
18885
+ });
18886
+
18421
18887
  // node_modules/@earendil-works/pi-ai/dist/api/constrained-sampling.js
18422
18888
  function isJsonSchemaObject(value) {
18423
18889
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -18511,6 +18977,13 @@ function makeStrictJsonSchema(schema, isUnsupportedKeyword) {
18511
18977
  }
18512
18978
  return cloned;
18513
18979
  }
18980
+ function prefersJsonSchemaStrictSampling(tool) {
18981
+ const config = tool.constrainedSampling;
18982
+ return !!config && config.type === "json_schema" && config.strict === "prefer";
18983
+ }
18984
+ function isStrictToolLimitErrorMessage(message) {
18985
+ return STRICT_TOOL_LIMIT_ERROR_MESSAGES.some((limitMessage) => message.includes(limitMessage));
18986
+ }
18514
18987
  function getJsonSchemaToolParameters(tool, strict) {
18515
18988
  return strict === true ? makeStrictJsonSchema(tool.parameters) : tool.parameters;
18516
18989
  }
@@ -18521,30 +18994,35 @@ function getGrammarToolInput(toolName2, arguments_, inputProperty) {
18521
18994
  }
18522
18995
  return input;
18523
18996
  }
18524
- function appendGrammarToolInputJsonDelta(buffer, inputProperty, nextInput, close) {
18997
+ function appendGrammarToolInputJsonDelta(buffer, inputProperty, inputDelta) {
18525
18998
  if (buffer.closed) {
18526
- if (close && nextInput === buffer.input)
18527
- return void 0;
18528
18999
  throw new Error(`grammar tool input for property "${inputProperty}" changed after it was closed`);
18529
19000
  }
18530
- if (!nextInput.startsWith(buffer.input)) {
18531
- throw new Error(`grammar tool input for property "${inputProperty}" changed non-monotonically`);
18532
- }
18533
- const inputDelta = nextInput.slice(buffer.input.length);
18534
- if (!close && inputDelta.length === 0)
19001
+ if (inputDelta.length === 0)
18535
19002
  return void 0;
18536
- let delta = "";
18537
- if (!buffer.started) {
18538
- delta += `{${JSON.stringify(inputProperty)}:"`;
18539
- buffer.started = true;
19003
+ buffer.input += inputDelta;
19004
+ return grammarToolInputJsonStart(buffer, inputProperty) + JSON.stringify(inputDelta).slice(1, -1);
19005
+ }
19006
+ function closeGrammarToolInputJson(buffer, inputProperty, finalInput) {
19007
+ if (buffer.closed) {
19008
+ if (finalInput === void 0 || finalInput === buffer.input)
19009
+ return void 0;
19010
+ throw new Error(`grammar tool input for property "${inputProperty}" changed after it was closed`);
18540
19011
  }
18541
- delta += JSON.stringify(inputDelta).slice(1, -1);
18542
- buffer.input = nextInput;
18543
- if (close) {
18544
- delta += '"}';
18545
- buffer.closed = true;
19012
+ if (finalInput !== void 0 && !finalInput.startsWith(buffer.input)) {
19013
+ throw new Error(`grammar tool input for property "${inputProperty}" changed non-monotonically`);
18546
19014
  }
18547
- return delta;
19015
+ const rest = finalInput === void 0 ? "" : finalInput.slice(buffer.input.length);
19016
+ if (finalInput !== void 0)
19017
+ buffer.input = finalInput;
19018
+ buffer.closed = true;
19019
+ return `${grammarToolInputJsonStart(buffer, inputProperty)}${JSON.stringify(rest).slice(1, -1)}"}`;
19020
+ }
19021
+ function grammarToolInputJsonStart(buffer, inputProperty) {
19022
+ if (buffer.started)
19023
+ return "";
19024
+ buffer.started = true;
19025
+ return `{${JSON.stringify(inputProperty)}:"`;
18548
19026
  }
18549
19027
  function inferGrammarInputProperty(tool) {
18550
19028
  const schema = tool.parameters;
@@ -18620,7 +19098,7 @@ function createGrammarToolInputProperties(tools, supportsOpenAIGrammarTools) {
18620
19098
  }
18621
19099
  return properties;
18622
19100
  }
18623
- var UnsupportedStrictJsonSchemaError, UNSUPPORTED_STRICT_SCHEMA_KEYS;
19101
+ var UnsupportedStrictJsonSchemaError, UNSUPPORTED_STRICT_SCHEMA_KEYS, STRICT_TOOL_LIMIT_ERROR_MESSAGES;
18624
19102
  var init_constrained_sampling = __esm({
18625
19103
  "node_modules/@earendil-works/pi-ai/dist/api/constrained-sampling.js"() {
18626
19104
  UnsupportedStrictJsonSchemaError = class extends Error {
@@ -18643,6 +19121,11 @@ var init_constrained_sampling = __esm({
18643
19121
  "then",
18644
19122
  "else"
18645
19123
  ];
19124
+ STRICT_TOOL_LIMIT_ERROR_MESSAGES = [
19125
+ "The compiled grammar is too large",
19126
+ "Too many strict tools (",
19127
+ "Schemas contains too many parameters with union types ("
19128
+ ];
18646
19129
  }
18647
19130
  });
18648
19131
 
@@ -19406,10 +19889,7 @@ function buildParams(model, context, isOAuthToken2, options, disablePreferredStr
19406
19889
  let hasPreferredStrictTools = false;
19407
19890
  const convertToolDefinitions = (tools, toolCacheControl2) => {
19408
19891
  const definitions = convertTools(tools, isOAuthToken2, compat.supportsEagerToolInputStreaming, compat.supportsStrictTools, toolCacheControl2, disablePreferredStrictTools);
19409
- if (definitions.some((definition, index) => {
19410
- const config = tools[index].constrainedSampling;
19411
- return definition.strict === true && config && config.type === "json_schema" && config.strict === "prefer";
19412
- })) {
19892
+ if (definitions.some((definition, index) => definition.strict === true && prefersJsonSchemaStrictSampling(tools[index]))) {
19413
19893
  hasPreferredStrictTools = true;
19414
19894
  }
19415
19895
  return definitions;
@@ -19472,7 +19952,7 @@ function buildParams(model, context, isOAuthToken2, options, disablePreferredStr
19472
19952
  display: options?.thinkingDisplay ?? "summarized",
19473
19953
  block_binding: { prefix_mismatch_behavior: "drop_block" }
19474
19954
  };
19475
- params.output_config = { effort: "high" };
19955
+ params.output_config = { effort: "low" };
19476
19956
  } else if (model.reasoning && options?.thinkingEnabled) {
19477
19957
  const display = options.thinkingDisplay ?? "summarized";
19478
19958
  if (model.compat?.forceAdaptiveThinking === true) {
@@ -19583,7 +20063,6 @@ function convertMessages(transformedMessages, isOAuthToken2, cacheControl, allow
19583
20063
  });
19584
20064
  }
19585
20065
  } else if (msg.role === "assistant") {
19586
- flushPendingSystemMessages();
19587
20066
  const blocks = [];
19588
20067
  for (const block of msg.content) {
19589
20068
  if (block.type === "text") {
@@ -19632,6 +20111,7 @@ function convertMessages(transformedMessages, isOAuthToken2, cacheControl, allow
19632
20111
  }
19633
20112
  if (blocks.length === 0)
19634
20113
  continue;
20114
+ flushPendingSystemMessages();
19635
20115
  const messageIndex = params.length;
19636
20116
  params.push({
19637
20117
  role: "assistant",
@@ -19704,8 +20184,7 @@ function convertTools(tools, isOAuthToken2, supportsEagerToolInputStreaming, sup
19704
20184
  if (!tools)
19705
20185
  return [];
19706
20186
  return tools.map((tool, index) => {
19707
- const config = tool.constrainedSampling;
19708
- const strict = disablePreferredStrictTools && config && config.type === "json_schema" && config.strict === "prefer" ? void 0 : resolveJsonSchemaStrictSampling(tool, supportsStrictTools, isAnthropicStrictUnsupportedKeyword);
20187
+ const strict = disablePreferredStrictTools && prefersJsonSchemaStrictSampling(tool) ? void 0 : resolveJsonSchemaStrictSampling(tool, supportsStrictTools, isAnthropicStrictUnsupportedKeyword);
19709
20188
  const parameters = getJsonSchemaToolParameters(tool, strict);
19710
20189
  const schema = parameters;
19711
20190
  const legacyInputSchema = {
@@ -19762,9 +20241,11 @@ var init_anthropic_messages = __esm({
19762
20241
  init_headers2();
19763
20242
  init_identity();
19764
20243
  init_json_parse();
20244
+ init_openrouter_cost();
19765
20245
  init_provider_env();
19766
20246
  init_provider_retry();
19767
20247
  init_sanitize_unicode();
20248
+ init_streaming_json();
19768
20249
  init_text();
19769
20250
  init_transcript();
19770
20251
  init_constrained_sampling();
@@ -19901,11 +20382,7 @@ var init_anthropic_messages = __esm({
19901
20382
  });
19902
20383
  break;
19903
20384
  } catch (error) {
19904
- if (options?.signal?.aborted || disablePreferredStrictTools || !built.hasPreferredStrictTools || !(error instanceof Anthropic.APIError) || error.status !== 400 || error.type !== "invalid_request_error" || ![
19905
- "The compiled grammar is too large",
19906
- "Too many strict tools (",
19907
- "Schemas contains too many parameters with union types ("
19908
- ].some((message) => error.message.includes(message))) {
20385
+ if (options?.signal?.aborted || disablePreferredStrictTools || !built.hasPreferredStrictTools || !(error instanceof Anthropic.APIError) || error.status !== 400 || error.type !== "invalid_request_error" || !isStrictToolLimitErrorMessage(error.message)) {
19909
20386
  throw error;
19910
20387
  }
19911
20388
  disablePreferredStrictTools = true;
@@ -19919,7 +20396,11 @@ var init_anthropic_messages = __esm({
19919
20396
  }
19920
20397
  await options?.onResponse?.({ status: response.status, headers: headersToRecord(response.headers) }, model);
19921
20398
  stream5.push({ type: "start", partial: output });
19922
- const blocks = output.content;
20399
+ const openBlocks = /* @__PURE__ */ new Map();
20400
+ const openBlock = (anthropicIndex) => {
20401
+ const open = openBlocks.get(anthropicIndex);
20402
+ return open === void 0 ? void 0 : { ...open, block: output.content[open.contentIndex] };
20403
+ };
19923
20404
  for await (const event of iterateAnthropicEvents(response, options?.signal)) {
19924
20405
  await options?.onProviderStreamEvent?.(event, model);
19925
20406
  if (event.type === "message_start") {
@@ -19947,95 +20428,82 @@ var init_anthropic_messages = __esm({
19947
20428
  continue;
19948
20429
  }
19949
20430
  if (event.content_block.type === "text") {
19950
- const block = {
19951
- type: "text",
19952
- text: event.content_block.text ?? "",
19953
- index: event.index
19954
- };
19955
- output.content.push(block);
20431
+ output.content.push({ type: "text", text: event.content_block.text ?? "" });
20432
+ openBlocks.set(event.index, { contentIndex: output.content.length - 1 });
19956
20433
  stream5.push({ type: "text_start", contentIndex: output.content.length - 1, partial: output });
19957
20434
  } else if (event.content_block.type === "thinking") {
19958
- const block = {
20435
+ output.content.push({
19959
20436
  type: "thinking",
19960
20437
  thinking: event.content_block.thinking ?? "",
19961
- thinkingSignature: event.content_block.signature ?? "",
19962
- index: event.index
19963
- };
19964
- output.content.push(block);
20438
+ thinkingSignature: event.content_block.signature ?? ""
20439
+ });
20440
+ openBlocks.set(event.index, { contentIndex: output.content.length - 1 });
19965
20441
  stream5.push({ type: "thinking_start", contentIndex: output.content.length - 1, partial: output });
19966
20442
  } else if (event.content_block.type === "redacted_thinking") {
19967
- const block = {
20443
+ output.content.push({
19968
20444
  type: "thinking",
19969
20445
  thinking: "[Reasoning redacted]",
19970
20446
  thinkingSignature: event.content_block.data,
19971
- redacted: true,
19972
- index: event.index
19973
- };
19974
- output.content.push(block);
20447
+ redacted: true
20448
+ });
20449
+ openBlocks.set(event.index, { contentIndex: output.content.length - 1 });
19975
20450
  stream5.push({ type: "thinking_start", contentIndex: output.content.length - 1, partial: output });
19976
20451
  } else if (event.content_block.type === "tool_use") {
19977
- const block = {
20452
+ output.content.push({
19978
20453
  type: "toolCall",
19979
20454
  id: event.content_block.id,
19980
20455
  name: isOAuth ? fromClaudeCodeName(event.content_block.name, currentTools) : event.content_block.name,
19981
- arguments: event.content_block.input ?? {},
19982
- partialJson: "",
19983
- index: event.index
19984
- };
19985
- output.content.push(block);
20456
+ arguments: event.content_block.input ?? {}
20457
+ });
20458
+ openBlocks.set(event.index, {
20459
+ contentIndex: output.content.length - 1,
20460
+ arguments: new ToolCallArgumentsStream()
20461
+ });
19986
20462
  stream5.push({ type: "toolcall_start", contentIndex: output.content.length - 1, partial: output });
19987
20463
  }
19988
20464
  } else if (event.type === "content_block_delta") {
20465
+ const open = openBlock(event.index);
19989
20466
  if (event.delta.type === "text_delta") {
19990
- const index = blocks.findIndex((b) => b.index === event.index);
19991
- const block = blocks[index];
19992
- if (block && block.type === "text") {
19993
- block.text += event.delta.text;
20467
+ if (open?.block.type === "text") {
20468
+ open.block.text += event.delta.text;
19994
20469
  stream5.push({
19995
20470
  type: "text_delta",
19996
- contentIndex: index,
20471
+ contentIndex: open.contentIndex,
19997
20472
  delta: event.delta.text,
19998
20473
  partial: output
19999
20474
  });
20000
20475
  }
20001
20476
  } else if (event.delta.type === "thinking_delta") {
20002
- const index = blocks.findIndex((b) => b.index === event.index);
20003
- const block = blocks[index];
20004
- if (block && block.type === "thinking") {
20005
- block.thinking += event.delta.thinking;
20477
+ if (open?.block.type === "thinking") {
20478
+ open.block.thinking += event.delta.thinking;
20006
20479
  stream5.push({
20007
20480
  type: "thinking_delta",
20008
- contentIndex: index,
20481
+ contentIndex: open.contentIndex,
20009
20482
  delta: event.delta.thinking,
20010
20483
  partial: output
20011
20484
  });
20012
20485
  }
20013
20486
  } else if (event.delta.type === "input_json_delta") {
20014
- const index = blocks.findIndex((b) => b.index === event.index);
20015
- const block = blocks[index];
20016
- if (block && block.type === "toolCall") {
20017
- block.partialJson += event.delta.partial_json;
20018
- block.arguments = parseStreamingJson(block.partialJson);
20487
+ if (open?.block.type === "toolCall" && open.arguments !== void 0) {
20488
+ open.block.arguments = open.arguments.append(event.delta.partial_json);
20019
20489
  stream5.push({
20020
20490
  type: "toolcall_delta",
20021
- contentIndex: index,
20491
+ contentIndex: open.contentIndex,
20022
20492
  delta: event.delta.partial_json,
20023
20493
  partial: output
20024
20494
  });
20025
20495
  }
20026
20496
  } else if (event.delta.type === "signature_delta") {
20027
- const index = blocks.findIndex((b) => b.index === event.index);
20028
- const block = blocks[index];
20029
- if (block && block.type === "thinking") {
20030
- block.thinkingSignature = block.thinkingSignature || "";
20031
- block.thinkingSignature += event.delta.signature;
20497
+ if (open?.block.type === "thinking") {
20498
+ open.block.thinkingSignature = open.block.thinkingSignature || "";
20499
+ open.block.thinkingSignature += event.delta.signature;
20032
20500
  }
20033
20501
  }
20034
20502
  } else if (event.type === "content_block_stop") {
20035
- const index = blocks.findIndex((b) => b.index === event.index);
20036
- const block = blocks[index];
20037
- if (block) {
20038
- delete block.index;
20503
+ const open = openBlock(event.index);
20504
+ openBlocks.delete(event.index);
20505
+ if (open) {
20506
+ const { block, contentIndex: index } = open;
20039
20507
  if (block.type === "text") {
20040
20508
  stream5.push({
20041
20509
  type: "text_end",
@@ -20050,9 +20518,8 @@ var init_anthropic_messages = __esm({
20050
20518
  content: block.thinking,
20051
20519
  partial: output
20052
20520
  });
20053
- } else if (block.type === "toolCall") {
20054
- Object.assign(block, parseToolCallArguments(block.partialJson));
20055
- delete block.partialJson;
20521
+ } else if (block.type === "toolCall" && open.arguments !== void 0) {
20522
+ Object.assign(block, open.arguments.finish());
20056
20523
  stream5.push({
20057
20524
  type: "toolcall_end",
20058
20525
  contentIndex: index,
@@ -20097,6 +20564,9 @@ var init_anthropic_messages = __esm({
20097
20564
  }
20098
20565
  output.usage.totalTokens = output.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;
20099
20566
  calculateCost(usageModel, output.usage);
20567
+ if (isOpenRouterModel(model) && event.usage) {
20568
+ applyOpenRouterReportedCost(output.usage, event.usage);
20569
+ }
20100
20570
  }
20101
20571
  }
20102
20572
  if (options?.signal?.aborted) {
@@ -20124,10 +20594,6 @@ var init_anthropic_messages = __esm({
20124
20594
  stream5.push({ type: "done", reason: output.stopReason, message: output });
20125
20595
  stream5.end();
20126
20596
  } catch (error) {
20127
- for (const block of output.content) {
20128
- delete block.index;
20129
- delete block.partialJson;
20130
- }
20131
20597
  output.stopReason = options?.signal?.aborted ? "aborted" : "error";
20132
20598
  output.errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
20133
20599
  stream5.push({ type: "error", reason: output.stopReason, error: output });
@@ -40373,7 +40839,7 @@ function formatProviderError(norm, prefix) {
40373
40839
  function truncateErrorText(text2, maxChars) {
40374
40840
  if (text2.length <= maxChars)
40375
40841
  return text2;
40376
- return `${text2.slice(0, maxChars)}... [truncated ${text2.length - maxChars} chars]`;
40842
+ return `${ownedSlice(text2, 0, maxChars)}... [truncated ${text2.length - maxChars} chars]`;
40377
40843
  }
40378
40844
  function safeJsonStringify2(value) {
40379
40845
  try {
@@ -40386,6 +40852,7 @@ function safeJsonStringify2(value) {
40386
40852
  var MAX_PROVIDER_ERROR_BODY_CHARS;
40387
40853
  var init_error_body = __esm({
40388
40854
  "node_modules/@earendil-works/pi-ai/dist/utils/error-body.js"() {
40855
+ init_text();
40389
40856
  MAX_PROVIDER_ERROR_BODY_CHARS = 4e3;
40390
40857
  }
40391
40858
  });
@@ -41104,6 +41571,9 @@ function parseChunkUsage(rawUsage, model) {
41104
41571
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }
41105
41572
  };
41106
41573
  calculateCost(model, usage);
41574
+ if (isOpenRouterModel(model)) {
41575
+ applyOpenRouterReportedCost(usage, rawUsage);
41576
+ }
41107
41577
  return usage;
41108
41578
  }
41109
41579
  function mapStopReason2(reason) {
@@ -41221,10 +41691,11 @@ var init_openai_completions = __esm({
41221
41691
  init_hash();
41222
41692
  init_headers2();
41223
41693
  init_identity();
41224
- init_json_parse();
41694
+ init_openrouter_cost();
41225
41695
  init_provider_env();
41226
41696
  init_provider_retry();
41227
41697
  init_sanitize_unicode();
41698
+ init_streaming_json();
41228
41699
  init_text();
41229
41700
  init_transcript();
41230
41701
  init_constrained_sampling();
@@ -41289,23 +41760,14 @@ var init_openai_completions = __esm({
41289
41760
  let hasFinishReason = false;
41290
41761
  const toolCallBlocksByIndex = /* @__PURE__ */ new Map();
41291
41762
  const toolCallBlocksById = /* @__PURE__ */ new Map();
41763
+ const toolCallStates = /* @__PURE__ */ new Map();
41292
41764
  const blocks = output.content;
41293
41765
  const getContentIndex = (block) => blocks.indexOf(block);
41294
- const getCustomToolCallInput2 = (block) => {
41295
- const property2 = block.customInput?.property;
41296
- if (property2 === void 0)
41297
- return "";
41298
- const value = block.arguments[property2];
41299
- return typeof value === "string" ? value : "";
41300
- };
41301
- const appendCustomToolCallInput2 = (block, nextInput, close) => {
41302
- const customInput = block.customInput;
41303
- if (!customInput)
41304
- return void 0;
41305
- const delta = appendGrammarToolInputJsonDelta(customInput.jsonBuffer, customInput.property, nextInput, close);
41306
- block.arguments = { [customInput.property]: nextInput };
41307
- return delta;
41308
- };
41766
+ const customInput2 = (property2) => ({
41767
+ kind: "custom",
41768
+ property: property2,
41769
+ buffer: { input: "", started: false, closed: false }
41770
+ });
41309
41771
  const finishBlock = (block) => {
41310
41772
  const contentIndex = getContentIndex(block);
41311
41773
  if (contentIndex === -1) {
@@ -41327,8 +41789,10 @@ var init_openai_completions = __esm({
41327
41789
  partial: output
41328
41790
  });
41329
41791
  } else if (block.type === "toolCall") {
41330
- if (block.customInput) {
41331
- const delta = appendCustomToolCallInput2(block, getCustomToolCallInput2(block), true);
41792
+ const input = toolCallStates.get(block).input;
41793
+ toolCallStates.delete(block);
41794
+ if (input.kind === "custom") {
41795
+ const delta = closeGrammarToolInputJson(input.buffer, input.property, void 0);
41332
41796
  if (delta !== void 0) {
41333
41797
  stream5.push({
41334
41798
  type: "toolcall_delta",
@@ -41338,11 +41802,8 @@ var init_openai_completions = __esm({
41338
41802
  });
41339
41803
  }
41340
41804
  } else {
41341
- Object.assign(block, parseToolCallArguments(block.partialArgs));
41805
+ Object.assign(block, input.arguments.finish());
41342
41806
  }
41343
- delete block.partialArgs;
41344
- delete block.customInput;
41345
- delete block.streamIndex;
41346
41807
  stream5.push({
41347
41808
  type: "toolcall_end",
41348
41809
  contentIndex,
@@ -41380,16 +41841,16 @@ var init_openai_completions = __esm({
41380
41841
  }
41381
41842
  if (!block) {
41382
41843
  const customInputProperty = toolCall.custom && !toolCall.function ? grammarToolInputProperties.get(name2) ?? "input" : void 0;
41383
- const hasCustomInput = customInputProperty !== void 0;
41384
41844
  block = {
41385
41845
  type: "toolCall",
41386
41846
  id: toolCall.id || "",
41387
41847
  name: name2,
41388
- arguments: hasCustomInput ? { [customInputProperty]: "" } : {},
41389
- partialArgs: hasCustomInput ? void 0 : "",
41390
- customInput: hasCustomInput ? { property: customInputProperty, jsonBuffer: { input: "", started: false, closed: false } } : void 0,
41391
- streamIndex
41848
+ arguments: customInputProperty !== void 0 ? { [customInputProperty]: "" } : {}
41392
41849
  };
41850
+ toolCallStates.set(block, {
41851
+ streamIndex,
41852
+ input: customInputProperty !== void 0 ? customInput2(customInputProperty) : { kind: "json", arguments: new ToolCallArgumentsStream() }
41853
+ });
41393
41854
  if (streamIndex !== void 0) {
41394
41855
  toolCallBlocksByIndex.set(streamIndex, block);
41395
41856
  }
@@ -41403,8 +41864,9 @@ var init_openai_completions = __esm({
41403
41864
  partial: output
41404
41865
  });
41405
41866
  }
41406
- if (streamIndex !== void 0 && block.streamIndex === void 0) {
41407
- block.streamIndex = streamIndex;
41867
+ const state2 = toolCallStates.get(block);
41868
+ if (streamIndex !== void 0 && state2.streamIndex === void 0) {
41869
+ state2.streamIndex = streamIndex;
41408
41870
  toolCallBlocksByIndex.set(streamIndex, block);
41409
41871
  }
41410
41872
  if (toolCall.id) {
@@ -41413,16 +41875,12 @@ var init_openai_completions = __esm({
41413
41875
  if (!block.name && name2) {
41414
41876
  block.name = name2;
41415
41877
  }
41416
- if (toolCall.custom && !toolCall.function && !block.customInput) {
41878
+ if (toolCall.custom && !toolCall.function && state2.input.kind !== "custom") {
41417
41879
  const customInputProperty = grammarToolInputProperties.get(block.name) ?? "input";
41418
41880
  block.arguments = { [customInputProperty]: "" };
41419
- block.customInput = {
41420
- property: customInputProperty,
41421
- jsonBuffer: { input: "", started: false, closed: false }
41422
- };
41423
- delete block.partialArgs;
41881
+ state2.input = customInput2(customInputProperty);
41424
41882
  }
41425
- return block;
41883
+ return { block, state: state2 };
41426
41884
  };
41427
41885
  for await (const chunk of openaiStream) {
41428
41886
  await options?.onProviderStreamEvent?.(chunk, model);
@@ -41497,7 +41955,7 @@ var init_openai_completions = __esm({
41497
41955
  }
41498
41956
  if (choice?.delta?.tool_calls) {
41499
41957
  for (const toolCall of choice.delta.tool_calls) {
41500
- const block = ensureToolCallBlock(toolCall);
41958
+ const { block, state: state2 } = ensureToolCallBlock(toolCall);
41501
41959
  if (!block.id && toolCall.id) {
41502
41960
  block.id = toolCall.id;
41503
41961
  toolCallBlocksById.set(toolCall.id, block);
@@ -41507,13 +41965,13 @@ var init_openai_completions = __esm({
41507
41965
  block.name = name2;
41508
41966
  }
41509
41967
  let delta = "";
41510
- if (toolCall.function?.arguments) {
41968
+ const input = state2.input;
41969
+ if (toolCall.function?.arguments && input.kind === "json") {
41511
41970
  delta = toolCall.function.arguments;
41512
- block.partialArgs = (block.partialArgs ?? "") + toolCall.function.arguments;
41513
- block.arguments = parseStreamingJson(block.partialArgs);
41514
- } else if (toolCall.custom?.input) {
41515
- const nextInput = getCustomToolCallInput2(block) + toolCall.custom.input;
41516
- delta = appendCustomToolCallInput2(block, nextInput, false) ?? "";
41971
+ block.arguments = input.arguments.append(delta);
41972
+ } else if (toolCall.custom?.input && input.kind === "custom") {
41973
+ delta = appendGrammarToolInputJsonDelta(input.buffer, input.property, toolCall.custom.input) ?? "";
41974
+ block.arguments = { [input.property]: input.buffer.input };
41517
41975
  }
41518
41976
  stream5.push({
41519
41977
  type: "toolcall_delta",
@@ -41550,10 +42008,6 @@ var init_openai_completions = __esm({
41550
42008
  if (block.type === "thinking") {
41551
42009
  applyStreamedReasoningDetails(block);
41552
42010
  }
41553
- delete block.index;
41554
- delete block.partialArgs;
41555
- delete block.customInput;
41556
- delete block.streamIndex;
41557
42011
  }
41558
42012
  output.stopReason = options?.signal?.aborted ? "aborted" : "error";
41559
42013
  output.errorMessage = formatProviderError(normalizeProviderError(error));
@@ -41897,24 +42351,10 @@ function convertResponsesTools(tools, options) {
41897
42351
  return functionTool;
41898
42352
  });
41899
42353
  }
41900
- function getCustomToolCallInput(block) {
41901
- const property2 = block.customInput?.property;
41902
- if (property2 === void 0)
41903
- return "";
41904
- const value = block.arguments[property2];
41905
- return typeof value === "string" ? value : "";
41906
- }
41907
- function appendCustomToolCallInput(block, nextInput, close) {
41908
- const customInput = block.customInput;
41909
- if (!customInput)
41910
- return void 0;
41911
- const delta = appendGrammarToolInputJsonDelta(customInput.jsonBuffer, customInput.property, nextInput, close);
41912
- block.arguments = { [customInput.property]: nextInput };
41913
- return delta;
41914
- }
41915
42354
  async function processResponsesStream(openaiStream, output, stream5, model, options) {
41916
42355
  let sawTerminalResponseEvent = false;
41917
42356
  const outputSlots = /* @__PURE__ */ new Map();
42357
+ const unfinishedToolCalls = /* @__PURE__ */ new Set();
41918
42358
  const reasoningBlocksById = /* @__PURE__ */ new Map();
41919
42359
  const applyMessagePhaseStopReason = (item) => {
41920
42360
  if (item.type === "message" && item.phase === "final_answer") {
@@ -41958,19 +42398,21 @@ async function processResponsesStream(openaiStream, output, stream5, model, opti
41958
42398
  return slot;
41959
42399
  }
41960
42400
  if (item.type === "function_call") {
42401
+ const args = new ToolCallArgumentsStream();
41961
42402
  const block = {
41962
42403
  type: "toolCall",
41963
42404
  id: `${item.call_id}|${item.id}`,
41964
42405
  name: item.name,
41965
- arguments: {},
41966
- ...item.namespace !== void 0 ? { namespace: item.namespace } : {},
41967
- partialJson: item.arguments || ""
42406
+ arguments: item.arguments ? args.append(item.arguments) : {},
42407
+ ...item.namespace !== void 0 ? { namespace: item.namespace } : {}
41968
42408
  };
41969
42409
  output.content.push(block);
42410
+ unfinishedToolCalls.add(block);
41970
42411
  const slot = {
41971
42412
  type: "toolCall",
41972
42413
  block,
41973
- contentIndex: output.content.length - 1
42414
+ contentIndex: output.content.length - 1,
42415
+ input: { kind: "json", arguments: args }
41974
42416
  };
41975
42417
  outputSlots.set(outputIndex, slot);
41976
42418
  stream5.push({ type: "toolcall_start", contentIndex: slot.contentIndex, partial: output });
@@ -41984,17 +42426,15 @@ async function processResponsesStream(openaiStream, output, stream5, model, opti
41984
42426
  id: `${item.call_id}|${item.id}`,
41985
42427
  name: item.name,
41986
42428
  arguments: { [inputProperty]: input },
41987
- ...item.namespace !== void 0 ? { namespace: item.namespace } : {},
41988
- customInput: {
41989
- property: inputProperty,
41990
- jsonBuffer: { input: "", started: false, closed: false }
41991
- }
42429
+ ...item.namespace !== void 0 ? { namespace: item.namespace } : {}
41992
42430
  };
41993
42431
  output.content.push(block);
42432
+ unfinishedToolCalls.add(block);
41994
42433
  const slot = {
41995
42434
  type: "toolCall",
41996
42435
  block,
41997
- contentIndex: output.content.length - 1
42436
+ contentIndex: output.content.length - 1,
42437
+ input: customInput(inputProperty, input)
41998
42438
  };
41999
42439
  outputSlots.set(outputIndex, slot);
42000
42440
  stream5.push({ type: "toolcall_start", contentIndex: slot.contentIndex, partial: output });
@@ -42124,33 +42564,28 @@ async function processResponsesStream(openaiStream, output, stream5, model, opti
42124
42564
  });
42125
42565
  } else if (event.type === "response.function_call_arguments.delta") {
42126
42566
  const slot = getSlot(event.output_index, "toolCall");
42127
- if (!slot || slot.block.partialJson === void 0)
42567
+ if (slot?.input.kind !== "json")
42128
42568
  continue;
42129
- slot.block.partialJson += event.delta;
42130
- slot.block.arguments = parseStreamingJson(slot.block.partialJson);
42569
+ slot.block.arguments = slot.input.arguments.append(event.delta);
42131
42570
  pushToolCallDelta(slot, event.delta);
42132
42571
  } else if (event.type === "response.function_call_arguments.done") {
42133
42572
  const slot = getSlot(event.output_index, "toolCall");
42134
- if (!slot || slot.block.partialJson === void 0)
42573
+ if (slot?.input.kind !== "json")
42135
42574
  continue;
42136
- const previousPartialJson = slot.block.partialJson;
42137
- slot.block.partialJson = event.arguments;
42138
- slot.block.arguments = parseStreamingJson(slot.block.partialJson);
42139
- if (event.arguments.startsWith(previousPartialJson)) {
42140
- const delta = event.arguments.slice(previousPartialJson.length);
42141
- if (delta.length > 0)
42142
- pushToolCallDelta(slot, delta);
42143
- }
42575
+ const replaced = slot.input.arguments.replace(event.arguments);
42576
+ slot.block.arguments = replaced.arguments;
42577
+ if (replaced.delta)
42578
+ pushToolCallDelta(slot, replaced.delta);
42144
42579
  } else if (event.type === "response.custom_tool_call_input.delta") {
42145
42580
  const slot = getSlot(event.output_index, "toolCall");
42146
- if (!slot || !slot.block.customInput)
42581
+ if (slot?.input.kind !== "custom")
42147
42582
  continue;
42148
- pushToolCallDelta(slot, appendCustomToolCallInput(slot.block, getCustomToolCallInput(slot.block) + event.delta, false));
42583
+ pushToolCallDelta(slot, appendCustomInput(slot.block, slot.input, event.delta));
42149
42584
  } else if (event.type === "response.custom_tool_call_input.done") {
42150
42585
  const slot = getSlot(event.output_index, "toolCall");
42151
- if (!slot || !slot.block.customInput)
42586
+ if (slot?.input.kind !== "custom")
42152
42587
  continue;
42153
- pushToolCallDelta(slot, appendCustomToolCallInput(slot.block, event.input, true));
42588
+ pushToolCallDelta(slot, closeCustomInput(slot.block, slot.input, event.input));
42154
42589
  } else if (event.type === "response.output_item.done") {
42155
42590
  const item = event.item;
42156
42591
  applyMessagePhaseStopReason(item);
@@ -42178,11 +42613,13 @@ async function processResponsesStream(openaiStream, output, stream5, model, opti
42178
42613
  partial: output
42179
42614
  });
42180
42615
  outputSlots.delete(event.output_index);
42181
- } else if (item.type === "function_call" && slot?.type === "toolCall" && slot.block.partialJson !== void 0) {
42182
- Object.assign(slot.block, parseToolCallArguments(item.arguments || slot.block.partialJson));
42616
+ } else if (item.type === "function_call" && slot?.type === "toolCall" && slot.input.kind === "json") {
42617
+ if (item.arguments)
42618
+ slot.input.arguments.replace(item.arguments);
42619
+ Object.assign(slot.block, slot.input.arguments.finish());
42183
42620
  if (item.namespace !== void 0)
42184
42621
  slot.block.namespace = item.namespace;
42185
- delete slot.block.partialJson;
42622
+ unfinishedToolCalls.delete(slot.block);
42186
42623
  stream5.push({
42187
42624
  type: "toolcall_end",
42188
42625
  contentIndex: slot.contentIndex,
@@ -42190,11 +42627,11 @@ async function processResponsesStream(openaiStream, output, stream5, model, opti
42190
42627
  partial: output
42191
42628
  });
42192
42629
  outputSlots.delete(event.output_index);
42193
- } else if (item.type === "custom_tool_call" && slot?.type === "toolCall" && slot.block.customInput) {
42194
- pushToolCallDelta(slot, appendCustomToolCallInput(slot.block, item.input ?? getCustomToolCallInput(slot.block), true));
42630
+ } else if (item.type === "custom_tool_call" && slot?.type === "toolCall" && slot.input.kind === "custom") {
42631
+ pushToolCallDelta(slot, closeCustomInput(slot.block, slot.input, item.input));
42195
42632
  if (item.namespace !== void 0)
42196
42633
  slot.block.namespace = item.namespace;
42197
- delete slot.block.customInput;
42634
+ unfinishedToolCalls.delete(slot.block);
42198
42635
  stream5.push({
42199
42636
  type: "toolcall_end",
42200
42637
  contentIndex: slot.contentIndex,
@@ -42220,16 +42657,34 @@ async function processResponsesStream(openaiStream, output, stream5, model, opti
42220
42657
  throw new Error("OpenAI Responses stream ended before a terminal response event");
42221
42658
  }
42222
42659
  if (output.stopReason === "toolUse") {
42223
- for (const block of output.content) {
42224
- if (block.type !== "toolCall")
42225
- continue;
42226
- const toolCall = block;
42227
- if (toolCall.partialJson !== void 0 || toolCall.customInput !== void 0) {
42228
- throw new Error(`OpenAI Responses stream completed with an unfinished tool call: ${toolCall.name} (${toolCall.id})`);
42229
- }
42660
+ for (const toolCall of unfinishedToolCalls) {
42661
+ throw new Error(`OpenAI Responses stream completed with an unfinished tool call: ${toolCall.name} (${toolCall.id})`);
42230
42662
  }
42231
42663
  }
42232
42664
  }
42665
+ function customInput(property2, initialInput) {
42666
+ const buffer = { input: "", started: false, closed: false };
42667
+ return {
42668
+ kind: "custom",
42669
+ property: property2,
42670
+ buffer,
42671
+ unsent: appendGrammarToolInputJsonDelta(buffer, property2, initialInput) ?? ""
42672
+ };
42673
+ }
42674
+ function appendCustomInput(block, input, delta) {
42675
+ return sendCustomInput(block, input, appendGrammarToolInputJsonDelta(input.buffer, input.property, delta));
42676
+ }
42677
+ function closeCustomInput(block, input, finalInput) {
42678
+ return sendCustomInput(block, input, closeGrammarToolInputJson(input.buffer, input.property, finalInput));
42679
+ }
42680
+ function sendCustomInput(block, input, jsonDelta) {
42681
+ block.arguments = { [input.property]: input.buffer.input };
42682
+ if (input.unsent === "")
42683
+ return jsonDelta;
42684
+ const sent = input.unsent + (jsonDelta ?? "");
42685
+ input.unsent = "";
42686
+ return sent;
42687
+ }
42233
42688
  function mapStopReason3(status, incompleteReason) {
42234
42689
  if (!status)
42235
42690
  return { stopReason: "stop" };
@@ -42261,8 +42716,8 @@ var init_openai_responses_shared = __esm({
42261
42716
  "node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js"() {
42262
42717
  init_models();
42263
42718
  init_hash();
42264
- init_json_parse();
42265
42719
  init_sanitize_unicode();
42720
+ init_streaming_json();
42266
42721
  init_text();
42267
42722
  init_transcript();
42268
42723
  init_constrained_sampling();
@@ -42548,11 +43003,6 @@ var init_openai_responses = __esm({
42548
43003
  stream5.push({ type: "done", reason: output.stopReason, message: output });
42549
43004
  stream5.end();
42550
43005
  } catch (error) {
42551
- for (const block of output.content) {
42552
- delete block.index;
42553
- delete block.partialJson;
42554
- delete block.customInput;
42555
- }
42556
43006
  output.stopReason = options?.signal?.aborted ? "aborted" : "error";
42557
43007
  const errorMessage = formatProviderError(normalizeProviderError(error), `${model.provider === "openai" ? "OpenAI" : model.provider} API error`);
42558
43008
  if (errorMessage.includes("subscription_sharing_usage_limit_exceeded")) {
@@ -45404,7 +45854,7 @@ var require_webidl = __commonJS({
45404
45854
  var BOOLEAN = 2;
45405
45855
  var STRING = 3;
45406
45856
  var SYMBOL = 4;
45407
- var NUMBER = 5;
45857
+ var NUMBER2 = 5;
45408
45858
  var BIGINT = 6;
45409
45859
  var NULL2 = 7;
45410
45860
  var OBJECT = 8;
@@ -45467,7 +45917,7 @@ var require_webidl = __commonJS({
45467
45917
  case "symbol":
45468
45918
  return SYMBOL;
45469
45919
  case "number":
45470
- return NUMBER;
45920
+ return NUMBER2;
45471
45921
  case "bigint":
45472
45922
  return BIGINT;
45473
45923
  case "function":
@@ -45484,7 +45934,7 @@ var require_webidl = __commonJS({
45484
45934
  BOOLEAN,
45485
45935
  STRING,
45486
45936
  SYMBOL,
45487
- NUMBER,
45937
+ NUMBER: NUMBER2,
45488
45938
  BIGINT,
45489
45939
  NULL: NULL2,
45490
45940
  OBJECT
@@ -45499,7 +45949,7 @@ var require_webidl = __commonJS({
45499
45949
  return "String";
45500
45950
  case SYMBOL:
45501
45951
  return "Symbol";
45502
- case NUMBER:
45952
+ case NUMBER2:
45503
45953
  return "Number";
45504
45954
  case BIGINT:
45505
45955
  return "BigInt";
@@ -73692,7 +74142,7 @@ import { idleWatchdog, timeoutOf } from "@deepseek-ai/dsh-timeout";
73692
74142
  init_models();
73693
74143
 
73694
74144
  // node_modules/@earendil-works/pi-ai/dist/providers/data/opencode-go.json
73695
- var opencode_go_default = { "anthropic-messages": { "chat:claude-haiku-5-5": { id: "claude-haiku-5-5", name: "Claude Haiku 5.5", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.5, cacheRead: 0.01, cacheWrite: 0.125, tiers: [{ inputTokensAbove: 1e5, input: 0.5, output: 2.5, cacheRead: 0.05, cacheWrite: 0.625 }] }, contextWindow: 1e6, maxTokens: 128e3, thinkingLevelMap: { xhigh: "xhigh", max: "max" }, compat: { forceAdaptiveThinking: true, supportsTemperature: false }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:minimax-m3": { id: "minimax-m3", name: "MiniMax-M3", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0, tiers: [{ inputTokensAbove: 512e3, input: 0.6, output: 2.4, cacheRead: 0.12, cacheWrite: 0 }] }, contextWindow: 1e6, maxTokens: 131072, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:qwen3.7-plus": { id: "qwen3.7-plus", name: "Qwen3.7 Plus", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go", reasoning: true, input: ["text", "image"], cost: { input: 0.4, output: 1.6, cacheRead: 0.04, cacheWrite: 0.5, tiers: [{ inputTokensAbove: 256e3, input: 1.2, output: 4.8, cacheRead: 0.12, cacheWrite: 1.5 }] }, contextWindow: 1e6, maxTokens: 65536, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:qwen3.8-flash": { id: "qwen3.8-flash", name: "Qwen3.8 Flash", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 0.47, cacheRead: 0.016, cacheWrite: 0.2 }, contextWindow: 1e6, maxTokens: 131072, compat: { allowEmptySignature: true }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:qwen3.8-max": { id: "qwen3.8-max", name: "Qwen3.8 Max", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 2.5 }, contextWindow: 1e6, maxTokens: 131072, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" } }, "google-generative-ai": { "chat:gemini-4-argon-contributor": { id: "gemini-4-argon-contributor", name: "Gemini 4 Argon Contributor", api: "google-generative-ai", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, input: ["text", "image"], cost: { input: 4, output: 20, cacheRead: 0.2, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" } }, "openai-completions": { "chat:beam-free": { id: "beam-free", name: "Beam Free", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1048576, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, type: "chat" }, "chat:deepseek-v4-pro": { id: "deepseek-v4-pro", name: "DeepSeek V4 Pro (New)", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text"], cost: { input: 0.66, output: 1.98, cacheRead: 0.022, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, contextWindow: 1e6, maxTokens: 384e3, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: "max" }, type: "chat" }, "chat:deepseek-v4.1-flash": { id: "deepseek-v4.1-flash", name: "DeepSeek V4.1 Flash", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" }, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 3e-3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, contextWindow: 1e6, maxTokens: 384e3, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:glm-5.2": { id: "glm-5.2", name: "GLM-5.2", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: null, medium: null, high: "high", xhigh: null, max: "max" }, type: "chat" }, "chat:glm-5.3": { id: "glm-5.3", name: "GLM-5.3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" }, type: "chat" }, "chat:glm-5.3-flash": { id: "glm-5.3-flash", name: "GLM-5.3-Flash", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 0.5, cacheRead: 0.03, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:hy3": { id: "hy3", name: "Hy3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text"], cost: { input: 0.14, output: 0.58, cacheRead: 0.035, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 256e3, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: null }, type: "chat" }, "chat:hy4-preview": { id: "hy4-preview", name: "Hy4 preview", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text"], cost: { input: 0.834, output: 2.501, cacheRead: 0.042, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1024e3, maxTokens: 64e3, thinkingLevelMap: { off: "none", minimal: null, low: null, medium: null, high: "high", xhigh: null, max: null }, type: "chat" }, "chat:kimi-k2.7-code": { id: "kimi-k2.7-code", name: "Kimi K2.7 Code", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 262144, maxTokens: 262144, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:kimi-k3": { id: "kimi-k3", name: "Kimi K3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens", supportsMidConvoSystemMessages: true, supportsMidConvoToolAdditions: true }, contextWindow: 1048576, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: null, low: null, medium: null, high: null, xhigh: null, max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:longcat-2.0": { id: "longcat-2.0", name: "LongCat-2.0", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 6e-3, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, type: "chat" }, "chat:longcat-2.5-preview-free": { id: "longcat-2.5-preview-free", name: "LongCat 2.5 Preview Free", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 131072, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:mimo-v2.5": { id: "mimo-v2.5", name: "MiMo V2.5", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 0.28, cacheRead: 28e-4, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 128e3, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:mimo-v2.5-pro": { id: "mimo-v2.5-pro", name: "MiMo V2.5 Pro", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text"], cost: { input: 0.435, output: 0.87, cacheRead: 3625e-6, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1048576, maxTokens: 128e3, type: "chat" }, "chat:mimo-v2.6-flash": { id: "mimo-v2.6-flash", name: "MiMo-V2.6-Flash", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 0.28, cacheRead: 28e-4, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1048576, maxTokens: 131072, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:mimo-v2.6-pro": { id: "mimo-v2.6-pro", name: "MiMo-V2.6-Pro", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.435, output: 0.87, cacheRead: 3625e-6, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1048576, maxTokens: 131072, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:minimax-m3.1-flash-free": { id: "minimax-m3.1-flash-free", name: "MiniMax M3.1 Flash Free", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 512e3, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:step-5-preview": { id: "step-5-preview", name: "Step 5 Preview", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 2.7, cacheRead: 0.1, cacheWrite: 0 }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, contextWindow: 1e6, maxTokens: 65536, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" } }, "openai-responses": { "chat:gpt-5.6-luna": { id: "gpt-5.6-luna", name: "GPT-5.6 Luna", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25, tiers: [{ inputTokensAbove: 272e3, input: 0.4, output: 1.8, cacheRead: 0.04, cacheWrite: 0.5 }] }, compat: { sessionAffinityFormat: "openai-nosession", supportsMidConvoSystemMessages: true, supportsAdditionalTools: true }, contextWindow: 105e4, maxTokens: 128e3, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-6-luna": { id: "gpt-6-luna", name: "GPT-6 Luna", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.5, cacheRead: 0.01, cacheWrite: 0.125, tiers: [{ inputTokensAbove: 272e3, input: 0.2, output: 0.75, cacheRead: 0.02, cacheWrite: 0.25 }] }, compat: { sessionAffinityFormat: "openai-nosession", supportsMidConvoSystemMessages: true, supportsAdditionalTools: true }, contextWindow: 105e4, maxTokens: 128e3, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:grok-4.7": { id: "grok-4.7", name: "Grok 4.7", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0, tiers: [{ inputTokensAbove: 2e5, input: 4, output: 12, cacheRead: 1, cacheWrite: 0 }] }, compat: { sessionAffinityFormat: "openai-nosession" }, contextWindow: 5e5, maxTokens: 5e5, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:muse-spark-1.2-contributor": { id: "muse-spark-1.2-contributor", name: "Muse Spark 1.2 Contributor", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.2, cacheRead: 2e-3, cacheWrite: 0 }, compat: { sessionAffinityFormat: "openai-nosession" }, contextWindow: 1048576, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:muse-spark-1.3-contributor": { id: "muse-spark-1.3-contributor", name: "Muse Spark 1.3 Contributor", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.2, cacheRead: 2e-3, cacheWrite: 0 }, compat: { sessionAffinityFormat: "openai-nosession" }, contextWindow: 1048576, maxTokens: 131072, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" } } };
74145
+ var opencode_go_default = { "anthropic-messages": { "chat:claude-haiku-5-5": { id: "claude-haiku-5-5", name: "Claude Haiku 5.5", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/anthropic", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.5, cacheRead: 0.01, cacheWrite: 0.125, tiers: [{ inputTokensAbove: 1e5, input: 0.5, output: 2.5, cacheRead: 0.05, cacheWrite: 0.625 }] }, contextWindow: 1e6, maxTokens: 128e3, thinkingLevelMap: { xhigh: "xhigh", max: "max" }, compat: { forceAdaptiveThinking: true, supportsTemperature: false }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:minimax-m3": { id: "minimax-m3", name: "MiniMax-M3", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/anthropic", reasoning: true, input: ["text", "image"], cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0, tiers: [{ inputTokensAbove: 512e3, input: 0.6, output: 2.4, cacheRead: 0.12, cacheWrite: 0 }] }, contextWindow: 1e6, maxTokens: 131072, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:qwen3.7-plus": { id: "qwen3.7-plus", name: "Qwen3.7 Plus", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/anthropic", reasoning: true, input: ["text", "image"], cost: { input: 0.4, output: 1.6, cacheRead: 0.04, cacheWrite: 0.5, tiers: [{ inputTokensAbove: 256e3, input: 1.2, output: 4.8, cacheRead: 0.12, cacheWrite: 1.5 }] }, contextWindow: 1e6, maxTokens: 65536, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:qwen3.8-flash": { id: "qwen3.8-flash", name: "Qwen3.8 Flash", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/anthropic", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 0.47, cacheRead: 0.016, cacheWrite: 0.2 }, contextWindow: 1e6, maxTokens: 131072, compat: { allowEmptySignature: true }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:qwen3.8-max": { id: "qwen3.8-max", name: "Qwen3.8 Max", api: "anthropic-messages", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/anthropic", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 2.5 }, contextWindow: 1e6, maxTokens: 131072, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" } }, "google-generative-ai": { "chat:gemini-4-argon": { id: "gemini-4-argon", name: "Gemini 4 Argon", api: "google-generative-ai", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/google/v1beta", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 65536, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" } }, "openai-completions": { "chat:beam-free": { id: "beam-free", name: "Beam Free", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, type: "chat" }, "chat:deepseek-v4-pro": { id: "deepseek-v4-pro", name: "DeepSeek V4 Pro (New)", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text"], cost: { input: 0.66, output: 1.98, cacheRead: 0.022, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 384e3, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, thinkingLevelMap: { minimal: null, low: null, medium: null, high: "high", max: "max" }, type: "chat" }, "chat:deepseek-v4.1-flash": { id: "deepseek-v4.1-flash", name: "DeepSeek V4.1 Flash", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 3e-3, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 384e3, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" }, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens", requiresReasoningContentOnAssistantMessages: true, thinkingFormat: "deepseek" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:glm-5.2": { id: "glm-5.2", name: "GLM-5.2", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, thinkingLevelMap: { off: null, minimal: null, low: null, medium: null, high: "high", xhigh: null, max: "max" }, type: "chat" }, "chat:glm-5.3": { id: "glm-5.3", name: "GLM-5.3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text"], cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" }, type: "chat" }, "chat:glm-5.3-flash": { id: "glm-5.3-flash", name: "GLM-5.3-Flash", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 0.5, cacheRead: 0.03, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:hy3": { id: "hy3", name: "Hy3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text"], cost: { input: 0.14, output: 0.58, cacheRead: 0.035, cacheWrite: 0 }, contextWindow: 256e3, maxTokens: 128e3, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: null }, type: "chat" }, "chat:hy4-preview": { id: "hy4-preview", name: "Hy4 preview", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text"], cost: { input: 0.834, output: 2.501, cacheRead: 0.042, cacheWrite: 0 }, contextWindow: 1024e3, maxTokens: 64e3, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, thinkingLevelMap: { off: "none", minimal: null, low: null, medium: null, high: "high", xhigh: null, max: null }, type: "chat" }, "chat:iceman-contributor-free": { id: "iceman-contributor-free", name: "Iceman Contributor Free", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text"], cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, type: "chat" }, "chat:kimi-k2.7-code": { id: "kimi-k2.7-code", name: "Kimi K2.7 Code", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 }, contextWindow: 262144, maxTokens: 262144, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:kimi-k3": { id: "kimi-k3", name: "Kimi K3", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens", supportsMidConvoSystemMessages: true, supportsMidConvoToolAdditions: true }, thinkingLevelMap: { off: null, minimal: null, low: null, medium: null, high: null, xhigh: null, max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:kimi-k3.1-pro": { id: "kimi-k3.1-pro", name: "Kimi K3.1 Pro", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens", supportsMidConvoSystemMessages: true, supportsMidConvoToolAdditions: true }, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: null, high: "high", xhigh: null, max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:longcat-2.0": { id: "longcat-2.0", name: "LongCat-2.0", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text"], cost: { input: 0.3, output: 1.2, cacheRead: 6e-3, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, type: "chat" }, "chat:mimo-v2.5": { id: "mimo-v2.5", name: "MiMo V2.5", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 0.28, cacheRead: 28e-4, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 128e3, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:mimo-v2.5-pro": { id: "mimo-v2.5-pro", name: "MiMo V2.5 Pro", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text"], cost: { input: 0.435, output: 0.87, cacheRead: 3625e-6, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 128e3, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, type: "chat" }, "chat:mimo-v2.6-flash": { id: "mimo-v2.6-flash", name: "MiMo-V2.6-Flash", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.14, output: 0.28, cacheRead: 28e-4, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:mimo-v2.6-pro": { id: "mimo-v2.6-pro", name: "MiMo-V2.6-Pro", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.435, output: 0.87, cacheRead: 3625e-6, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:minimax-m3.1-flash": { id: "minimax-m3.1-flash", name: "MiniMax M3.1 Flash", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.15, output: 0.6, cacheRead: 0.015, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 512e3, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:step-5-preview": { id: "step-5-preview", name: "Step 5 Preview", api: "openai-completions", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 1, output: 2.7, cacheRead: 0.1, cacheWrite: 0 }, contextWindow: 1e6, maxTokens: 65536, compat: { supportsStore: false, supportsDeveloperRole: false, supportsStrictMode: true, maxTokensField: "max_tokens" }, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: null, max: null }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" } }, "openai-responses": { "chat:gpt-5.6-luna": { id: "gpt-5.6-luna", name: "GPT-5.6 Luna", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25, tiers: [{ inputTokensAbove: 272e3, input: 0.4, output: 1.8, cacheRead: 0.04, cacheWrite: 0.5 }] }, contextWindow: 105e4, maxTokens: 128e3, compat: { sessionAffinityFormat: "openai-nosession", supportsMidConvoSystemMessages: true, supportsAdditionalTools: true }, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:gpt-6-luna": { id: "gpt-6-luna", name: "GPT-6 Luna", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.5, cacheRead: 0.01, cacheWrite: 0.125, tiers: [{ inputTokensAbove: 272e3, input: 0.2, output: 0.75, cacheRead: 0.02, cacheWrite: 0.25 }] }, contextWindow: 105e4, maxTokens: 128e3, compat: { sessionAffinityFormat: "openai-nosession", supportsMidConvoSystemMessages: true, supportsAdditionalTools: true }, thinkingLevelMap: { off: "none", minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: "max" }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:grok-4.7": { id: "grok-4.7", name: "Grok 4.7", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0, tiers: [{ inputTokensAbove: 2e5, input: 4, output: 12, cacheRead: 1, cacheWrite: 0 }] }, contextWindow: 5e5, maxTokens: 5e5, compat: { sessionAffinityFormat: "openai-nosession" }, thinkingLevelMap: { off: null, minimal: null, low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:muse-spark-1.2-contributor": { id: "muse-spark-1.2-contributor", name: "Muse Spark 1.2 Contributor", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.2, cacheRead: 2e-3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { sessionAffinityFormat: "openai-nosession" }, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" }, "chat:muse-spark-1.3-contributor": { id: "muse-spark-1.3-contributor", name: "Muse Spark 1.3 Contributor", api: "openai-responses", provider: "opencode-go", baseUrl: "https://opencode.ai/inference/go/openai/v1", reasoning: true, input: ["text", "image"], cost: { input: 0.1, output: 0.2, cacheRead: 2e-3, cacheWrite: 0 }, contextWindow: 1048576, maxTokens: 131072, compat: { sessionAffinityFormat: "openai-nosession" }, thinkingLevelMap: { off: null, minimal: "minimal", low: "low", medium: "medium", high: "high", xhigh: "xhigh", max: null }, inputLimits: { images: { resize: { maxWidth: 2e3, maxHeight: 2e3, maxBytes: 4718592, jpegQuality: 80 } } }, type: "chat" } } };
73696
74146
 
73697
74147
  // node_modules/@earendil-works/pi-ai/dist/model-catalog.js
73698
74148
  function flattenModelCatalog(groups, type) {
@@ -77574,6 +78024,8 @@ var OVERFLOW_PATTERNS = [
77574
78024
  // OpenAI (Completions & Responses API)
77575
78025
  /exceeds (?:the )?(?:model'?s )?maximum context length(?: of [\d,]+ tokens?|\s*\([\d,]+\))/i,
77576
78026
  // OpenAI-compatible proxies (LiteLLM)
78027
+ /context window exceeded/i,
78028
+ // LiteLLM pre-call check (ContextWindowExceededError)
77577
78029
  /input token count.*exceeds the maximum/i,
77578
78030
  // Google (Gemini)
77579
78031
  /maximum prompt length is \d+/i,
@@ -79646,7 +80098,7 @@ function createUpdateChecker(deps) {
79646
80098
  }
79647
80099
 
79648
80100
  // src/update/version.ts
79649
- var PLUGIN_VERSION = true ? "0.1.88" : "0.0.0-dev";
80101
+ var PLUGIN_VERSION = true ? "0.1.90" : "0.0.0-dev";
79650
80102
 
79651
80103
  // src/update/service.ts
79652
80104
  import { TypertRemoteService as TypertRemoteService4 } from "@deepseek-ai/dsh-typert-protocol";
@@ -79968,9 +80420,11 @@ function apply(ctx, raw) {
79968
80420
  undiscover();
79969
80421
  return closeDispatcher();
79970
80422
  });
79971
- ctx.on("internal/config", function(_raw, next) {
79972
- const value = next();
79973
- if (this === ctx.fiber) assertBaseURL(PlainConfig(value).baseURL);
80423
+ ctx.on("internal/config", function(first, second) {
80424
+ const value = second();
80425
+ if (ctx.fiber !== void 0 && (first === ctx.fiber || this === ctx.fiber)) {
80426
+ assertBaseURL(PlainConfig(value).baseURL);
80427
+ }
79974
80428
  return value;
79975
80429
  });
79976
80430
  ctx.on("loader/volatile-update", syncRoute);