@ai-sdk-tool/parser 4.1.0 → 4.1.2

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.
@@ -5,7 +5,7 @@ import {
5
5
  parse as parse2,
6
6
  stringify,
7
7
  unescapeXml
8
- } from "./chunk-MHZC45AC.js";
8
+ } from "./chunk-D4YULTAO.js";
9
9
  import {
10
10
  parse
11
11
  } from "./chunk-QBZNMO5C.js";
@@ -222,6 +222,12 @@ function generateToolCallId() {
222
222
  }
223
223
 
224
224
  // src/core/utils/protocol-utils.ts
225
+ function formatToolsWithPromptTemplate(options) {
226
+ return options.toolSystemPromptTemplate(options.tools || []);
227
+ }
228
+ function extractToolNames(tools) {
229
+ return tools.map((tool) => tool.name).filter(Boolean);
230
+ }
225
231
  function addTextSegment(text, processedElements) {
226
232
  if (text.trim()) {
227
233
  processedElements.push({ type: "text", text });
@@ -260,10 +266,222 @@ function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmitte
260
266
  };
261
267
  }
262
268
 
263
- // src/core/protocols/hermes-protocol.ts
269
+ // src/core/utils/streamed-tool-input-delta.ts
270
+ function emitDelta({
271
+ controller,
272
+ id,
273
+ state,
274
+ nextInput
275
+ }) {
276
+ if (!nextInput.startsWith(state.emittedInput)) {
277
+ return false;
278
+ }
279
+ const delta = nextInput.slice(state.emittedInput.length);
280
+ if (delta.length === 0) {
281
+ return false;
282
+ }
283
+ controller.enqueue({
284
+ type: "tool-input-delta",
285
+ id,
286
+ delta
287
+ });
288
+ state.emittedInput = nextInput;
289
+ return true;
290
+ }
291
+ function toIncompleteJsonPrefix(fullJson) {
292
+ const trimmed = fullJson.trim();
293
+ let prefix = trimmed;
294
+ while (prefix.endsWith("}") || prefix.endsWith("]")) {
295
+ prefix = prefix.slice(0, -1);
296
+ }
297
+ prefix = prefix.trimEnd();
298
+ if (prefix.endsWith('"')) {
299
+ prefix = prefix.slice(0, -1);
300
+ }
301
+ if (prefix.length === 0) {
302
+ if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
303
+ return trimmed.startsWith("{") ? "{" : "[";
304
+ }
305
+ if (trimmed.startsWith("]")) {
306
+ return "[";
307
+ }
308
+ if (trimmed.startsWith("}")) {
309
+ return "{";
310
+ }
311
+ if (trimmed.startsWith('"')) {
312
+ return '"';
313
+ }
314
+ return "{";
315
+ }
316
+ return prefix;
317
+ }
318
+ function emitPrefixDelta(params) {
319
+ return emitDelta({
320
+ ...params,
321
+ nextInput: params.candidate
322
+ });
323
+ }
324
+ var DEFAULT_TOOL_INPUT_DELTA_CHUNK_CHARS = 512;
325
+ function emitChunkedPrefixDelta(params) {
326
+ const { maxChunkChars = DEFAULT_TOOL_INPUT_DELTA_CHUNK_CHARS } = params;
327
+ if (maxChunkChars <= 0) {
328
+ return emitPrefixDelta(params);
329
+ }
330
+ const growth = params.candidate.length - params.state.emittedInput.length;
331
+ if (growth <= 0) {
332
+ return false;
333
+ }
334
+ if (growth <= maxChunkChars) {
335
+ return emitPrefixDelta(params);
336
+ }
337
+ let emittedAny = false;
338
+ let cursor = params.state.emittedInput.length + maxChunkChars;
339
+ while (cursor < params.candidate.length) {
340
+ const didEmit = emitPrefixDelta({
341
+ controller: params.controller,
342
+ id: params.id,
343
+ state: params.state,
344
+ candidate: params.candidate.slice(0, cursor)
345
+ });
346
+ if (!didEmit) {
347
+ return emittedAny;
348
+ }
349
+ emittedAny = true;
350
+ cursor += maxChunkChars;
351
+ }
352
+ return emitPrefixDelta({
353
+ controller: params.controller,
354
+ id: params.id,
355
+ state: params.state,
356
+ candidate: params.candidate
357
+ }) || emittedAny;
358
+ }
359
+ function emitFinalRemainder(params) {
360
+ var _a;
361
+ const result = emitDelta({
362
+ ...params,
363
+ nextInput: params.finalFullJson
364
+ });
365
+ if (!result && params.state.emittedInput.length > 0) {
366
+ (_a = params.onMismatch) == null ? void 0 : _a.call(
367
+ params,
368
+ "Final JSON does not extend emitted tool-input prefix",
369
+ {
370
+ emittedLength: params.state.emittedInput.length,
371
+ finalLength: params.finalFullJson.length
372
+ }
373
+ );
374
+ }
375
+ return result;
376
+ }
377
+
378
+ // src/core/utils/tool-call-coercion.ts
379
+ function coerceToolCallInput(toolName, input, tools) {
380
+ var _a;
381
+ let args = {};
382
+ if (typeof input === "string") {
383
+ try {
384
+ args = JSON.parse(input);
385
+ } catch (e) {
386
+ return;
387
+ }
388
+ } else if (input && typeof input === "object") {
389
+ args = input;
390
+ } else {
391
+ return;
392
+ }
393
+ const schema = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
394
+ const coerced = coerceBySchema(args, schema);
395
+ return JSON.stringify(coerced != null ? coerced : {});
396
+ }
397
+ function coerceToolCallPart(part, tools) {
398
+ const coercedInput = coerceToolCallInput(part.toolName, part.input, tools);
399
+ if (coercedInput === void 0) {
400
+ return part;
401
+ }
402
+ return {
403
+ ...part,
404
+ input: coercedInput
405
+ };
406
+ }
407
+
408
+ // src/core/utils/tool-input-streaming.ts
409
+ function stringifyToolInputWithSchema(options) {
410
+ var _a;
411
+ const coerced = coerceToolCallInput(
412
+ options.toolName,
413
+ options.args,
414
+ options.tools
415
+ );
416
+ if (coerced !== void 0) {
417
+ return coerced;
418
+ }
419
+ if (options.fallback) {
420
+ return options.fallback(options.args);
421
+ }
422
+ return JSON.stringify((_a = options.args) != null ? _a : {});
423
+ }
424
+ function emitToolInputProgressDelta(options) {
425
+ var _a;
426
+ const mode = (_a = options.mode) != null ? _a : "incomplete-json-prefix";
427
+ const candidate = mode === "full-json" ? options.fullInput : toIncompleteJsonPrefix(options.fullInput);
428
+ return emitChunkedPrefixDelta({
429
+ controller: options.controller,
430
+ id: options.id,
431
+ state: options.state,
432
+ candidate
433
+ });
434
+ }
435
+ function enqueueToolInputEndAndCall(options) {
436
+ enqueueToolInputEnd({
437
+ controller: options.controller,
438
+ id: options.id
439
+ });
440
+ options.controller.enqueue({
441
+ type: "tool-call",
442
+ toolCallId: options.id,
443
+ toolName: options.toolName,
444
+ input: options.input
445
+ });
446
+ }
447
+ function enqueueToolInputEnd(options) {
448
+ options.controller.enqueue({
449
+ type: "tool-input-end",
450
+ id: options.id
451
+ });
452
+ }
453
+ function emitFailedToolInputLifecycle(options) {
454
+ var _a;
455
+ if (options.endInput !== false) {
456
+ enqueueToolInputEnd({
457
+ controller: options.controller,
458
+ id: options.id
459
+ });
460
+ }
461
+ if (options.emitRawToolCallTextOnError && typeof options.rawToolCallText === "string" && options.rawToolCallText.length > 0) {
462
+ (_a = options.emitRawText) == null ? void 0 : _a.call(options, options.rawToolCallText);
463
+ }
464
+ }
465
+ function emitFinalizedToolInputLifecycle(options) {
466
+ emitFinalRemainder({
467
+ controller: options.controller,
468
+ id: options.id,
469
+ state: options.state,
470
+ finalFullJson: options.finalInput,
471
+ onMismatch: options.onMismatch
472
+ });
473
+ enqueueToolInputEndAndCall({
474
+ controller: options.controller,
475
+ id: options.id,
476
+ toolName: options.toolName,
477
+ input: options.finalInput
478
+ });
479
+ }
264
480
  function shouldEmitRawToolCallTextOnError(options) {
265
481
  return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
266
482
  }
483
+
484
+ // src/core/protocols/hermes-protocol.ts
267
485
  function canonicalizeToolInput(argumentsValue) {
268
486
  return JSON.stringify(argumentsValue != null ? argumentsValue : {});
269
487
  }
@@ -527,19 +745,13 @@ function emitToolInputDelta(state, controller, fullInput) {
527
745
  if (!active) {
528
746
  return;
529
747
  }
530
- if (!fullInput.startsWith(active.emittedInput)) {
531
- return;
532
- }
533
- const delta = fullInput.slice(active.emittedInput.length);
534
- if (delta.length === 0) {
535
- return;
536
- }
537
- controller.enqueue({
538
- type: "tool-input-delta",
748
+ emitToolInputProgressDelta({
749
+ controller,
539
750
  id: active.id,
540
- delta
751
+ state: active,
752
+ fullInput,
753
+ mode: "full-json"
541
754
  });
542
- active.emittedInput = fullInput;
543
755
  }
544
756
  function closeToolInput(state, controller) {
545
757
  if (!state.activeToolInput) {
@@ -551,11 +763,16 @@ function closeToolInput(state, controller) {
551
763
  });
552
764
  state.activeToolInput = null;
553
765
  }
554
- function emitToolCallFromParsed(state, controller, parsedToolCall) {
766
+ function emitToolCallFromParsed(state, controller, parsedToolCall, tools) {
555
767
  var _a, _b, _c, _d;
556
768
  closeTextBlock(state, controller);
557
769
  const toolName = typeof parsedToolCall.name === "string" ? parsedToolCall.name : (_b = (_a = state.activeToolInput) == null ? void 0 : _a.toolName) != null ? _b : "unknown";
558
- const input = canonicalizeToolInput(parsedToolCall.arguments);
770
+ const input = stringifyToolInputWithSchema({
771
+ toolName,
772
+ args: parsedToolCall.arguments,
773
+ tools,
774
+ fallback: canonicalizeToolInput
775
+ });
559
776
  ensureToolInputStart(state, controller, toolName);
560
777
  emitToolInputDelta(state, controller, input);
561
778
  const toolCallId = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.id) != null ? _d : generateToolCallId();
@@ -567,18 +784,23 @@ function emitToolCallFromParsed(state, controller, parsedToolCall) {
567
784
  input
568
785
  });
569
786
  }
570
- function canonicalizeArgumentsProgressInput(progress) {
787
+ function canonicalizeArgumentsProgressInput(progress, toolName, tools) {
571
788
  if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
572
789
  return void 0;
573
790
  }
574
791
  try {
575
792
  const parsedArguments = parse(progress.argumentsText);
576
- return canonicalizeToolInput(parsedArguments);
793
+ return stringifyToolInputWithSchema({
794
+ toolName,
795
+ args: parsedArguments,
796
+ tools,
797
+ fallback: canonicalizeToolInput
798
+ });
577
799
  } catch (e) {
578
800
  return void 0;
579
801
  }
580
802
  }
581
- function emitToolInputProgress(state, controller) {
803
+ function emitToolInputProgress(state, controller, tools) {
582
804
  if (!(state.isInsideToolCall && state.currentToolCallJson)) {
583
805
  return;
584
806
  }
@@ -587,7 +809,11 @@ function emitToolInputProgress(state, controller) {
587
809
  return;
588
810
  }
589
811
  ensureToolInputStart(state, controller, progress.toolName);
590
- const canonicalProgressInput = canonicalizeArgumentsProgressInput(progress);
812
+ const canonicalProgressInput = canonicalizeArgumentsProgressInput(
813
+ progress,
814
+ progress.toolName,
815
+ tools
816
+ );
591
817
  if (canonicalProgressInput !== void 0) {
592
818
  emitToolInputDelta(state, controller, canonicalProgressInput);
593
819
  }
@@ -622,7 +848,7 @@ function closeTextBlock(state, controller) {
622
848
  state.hasEmittedTextStart = false;
623
849
  }
624
850
  }
625
- function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, options) {
851
+ function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, tools, options) {
626
852
  var _a;
627
853
  if (!state.currentToolCallJson && trailingBuffer.length === 0) {
628
854
  state.isInsideToolCall = false;
@@ -631,7 +857,7 @@ function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer
631
857
  if (state.currentToolCallJson) {
632
858
  try {
633
859
  const parsedToolCall = parse(state.currentToolCallJson);
634
- emitToolCallFromParsed(state, controller, parsedToolCall);
860
+ emitToolCallFromParsed(state, controller, parsedToolCall, tools);
635
861
  state.currentToolCallJson = "";
636
862
  state.isInsideToolCall = false;
637
863
  return;
@@ -671,7 +897,7 @@ function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer
671
897
  state.currentToolCallJson = "";
672
898
  state.isInsideToolCall = false;
673
899
  }
674
- function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
900
+ function handleFinishChunk(state, controller, toolCallStart, tools, options, chunk) {
675
901
  if (state.isInsideToolCall) {
676
902
  const trailingBuffer = state.buffer;
677
903
  state.buffer = "";
@@ -680,6 +906,7 @@ function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
680
906
  controller,
681
907
  toolCallStart,
682
908
  trailingBuffer,
909
+ tools,
683
910
  options
684
911
  );
685
912
  } else if (state.buffer.length > 0) {
@@ -688,11 +915,11 @@ function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
688
915
  closeTextBlock(state, controller);
689
916
  controller.enqueue(chunk);
690
917
  }
691
- function publishText(text, state, controller) {
918
+ function publishText(text, state, controller, tools) {
692
919
  if (state.isInsideToolCall) {
693
920
  closeTextBlock(state, controller);
694
921
  state.currentToolCallJson += text;
695
- emitToolInputProgress(state, controller);
922
+ emitToolInputProgress(state, controller, tools);
696
923
  } else if (text.length > 0) {
697
924
  if (!state.currentTextId) {
698
925
  state.currentTextId = generateId();
@@ -711,10 +938,10 @@ function publishText(text, state, controller) {
711
938
  }
712
939
  function emitToolCall(context) {
713
940
  var _a;
714
- const { state, controller, toolCallStart, toolCallEnd, options } = context;
941
+ const { state, controller, toolCallStart, toolCallEnd, options, tools } = context;
715
942
  try {
716
943
  const parsedToolCall = parse(state.currentToolCallJson);
717
- emitToolCallFromParsed(state, controller, parsedToolCall);
944
+ emitToolCallFromParsed(state, controller, parsedToolCall, tools);
718
945
  } catch (error) {
719
946
  const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
720
947
  const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
@@ -763,7 +990,7 @@ function processTagMatch(context) {
763
990
  }
764
991
  }
765
992
  function processBufferTags(context) {
766
- const { state, controller, toolCallStart, toolCallEnd } = context;
993
+ const { state, controller, toolCallStart, toolCallEnd, tools } = context;
767
994
  let startIndex = getPotentialStartIndex(
768
995
  state.buffer,
769
996
  state.isInsideToolCall ? toolCallEnd : toolCallStart
@@ -773,7 +1000,7 @@ function processBufferTags(context) {
773
1000
  if (startIndex + tag.length > state.buffer.length) {
774
1001
  break;
775
1002
  }
776
- publishText(state.buffer.slice(0, startIndex), state, controller);
1003
+ publishText(state.buffer.slice(0, startIndex), state, controller, tools);
777
1004
  state.buffer = state.buffer.slice(startIndex + tag.length);
778
1005
  processTagMatch(context);
779
1006
  startIndex = getPotentialStartIndex(
@@ -782,24 +1009,34 @@ function processBufferTags(context) {
782
1009
  );
783
1010
  }
784
1011
  }
785
- function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
1012
+ function handlePartialTag(state, controller, toolCallStart, toolCallEnd, tools) {
786
1013
  if (state.isInsideToolCall) {
787
1014
  const potentialEndIndex = getPotentialStartIndex(state.buffer, toolCallEnd);
788
1015
  if (potentialEndIndex != null && potentialEndIndex + toolCallEnd.length > state.buffer.length) {
789
- publishText(state.buffer.slice(0, potentialEndIndex), state, controller);
1016
+ publishText(
1017
+ state.buffer.slice(0, potentialEndIndex),
1018
+ state,
1019
+ controller,
1020
+ tools
1021
+ );
790
1022
  state.buffer = state.buffer.slice(potentialEndIndex);
791
1023
  } else {
792
- publishText(state.buffer, state, controller);
1024
+ publishText(state.buffer, state, controller, tools);
793
1025
  state.buffer = "";
794
1026
  }
795
1027
  return;
796
1028
  }
797
1029
  const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
798
1030
  if (potentialIndex != null && potentialIndex + toolCallStart.length > state.buffer.length) {
799
- publishText(state.buffer.slice(0, potentialIndex), state, controller);
1031
+ publishText(
1032
+ state.buffer.slice(0, potentialIndex),
1033
+ state,
1034
+ controller,
1035
+ tools
1036
+ );
800
1037
  state.buffer = state.buffer.slice(potentialIndex);
801
1038
  } else {
802
- publishText(state.buffer, state, controller);
1039
+ publishText(state.buffer, state, controller, tools);
803
1040
  state.buffer = "";
804
1041
  }
805
1042
  }
@@ -811,7 +1048,7 @@ var hermesProtocol = ({
811
1048
  tools,
812
1049
  toolSystemPromptTemplate
813
1050
  }) {
814
- return toolSystemPromptTemplate(tools || []);
1051
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
815
1052
  },
816
1053
  formatToolCall(toolCall) {
817
1054
  let args = {};
@@ -857,6 +1094,7 @@ var hermesProtocol = ({
857
1094
  return processedElements;
858
1095
  },
859
1096
  createStreamParser({
1097
+ tools,
860
1098
  options
861
1099
  }) {
862
1100
  const state = {
@@ -871,7 +1109,14 @@ var hermesProtocol = ({
871
1109
  transform(chunk, controller) {
872
1110
  var _a;
873
1111
  if (chunk.type === "finish") {
874
- handleFinishChunk(state, controller, toolCallStart, options, chunk);
1112
+ handleFinishChunk(
1113
+ state,
1114
+ controller,
1115
+ toolCallStart,
1116
+ tools,
1117
+ options,
1118
+ chunk
1119
+ );
875
1120
  return;
876
1121
  }
877
1122
  if (chunk.type !== "text-delta") {
@@ -885,9 +1130,10 @@ var hermesProtocol = ({
885
1130
  controller,
886
1131
  toolCallStart,
887
1132
  toolCallEnd,
888
- options
1133
+ options,
1134
+ tools
889
1135
  });
890
- handlePartialTag(state, controller, toolCallStart, toolCallEnd);
1136
+ handlePartialTag(state, controller, toolCallStart, toolCallEnd, tools);
891
1137
  }
892
1138
  });
893
1139
  },
@@ -909,80 +1155,6 @@ var hermesProtocol = ({
909
1155
  var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
910
1156
  var WHITESPACE_REGEX = /\s/;
911
1157
 
912
- // src/core/utils/streamed-tool-input-delta.ts
913
- function emitDelta({
914
- controller,
915
- id,
916
- state,
917
- nextInput
918
- }) {
919
- if (!nextInput.startsWith(state.emittedInput)) {
920
- return false;
921
- }
922
- const delta = nextInput.slice(state.emittedInput.length);
923
- if (delta.length === 0) {
924
- return false;
925
- }
926
- controller.enqueue({
927
- type: "tool-input-delta",
928
- id,
929
- delta
930
- });
931
- state.emittedInput = nextInput;
932
- return true;
933
- }
934
- function toIncompleteJsonPrefix(fullJson) {
935
- const trimmed = fullJson.trim();
936
- let prefix = trimmed;
937
- while (prefix.endsWith("}") || prefix.endsWith("]")) {
938
- prefix = prefix.slice(0, -1);
939
- }
940
- prefix = prefix.trimEnd();
941
- if (prefix.endsWith('"')) {
942
- prefix = prefix.slice(0, -1);
943
- }
944
- if (prefix.length === 0) {
945
- if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
946
- return trimmed.startsWith("{") ? "{" : "[";
947
- }
948
- if (trimmed.startsWith("]")) {
949
- return "[";
950
- }
951
- if (trimmed.startsWith("}")) {
952
- return "{";
953
- }
954
- if (trimmed.startsWith('"')) {
955
- return '"';
956
- }
957
- return "{";
958
- }
959
- return prefix;
960
- }
961
- function emitPrefixDelta(params) {
962
- return emitDelta({
963
- ...params,
964
- nextInput: params.candidate
965
- });
966
- }
967
- function emitFinalRemainder(params) {
968
- var _a;
969
- const result = emitDelta({
970
- ...params,
971
- nextInput: params.finalFullJson
972
- });
973
- if (!result && params.state.emittedInput.length > 0) {
974
- (_a = params.onMismatch) == null ? void 0 : _a.call(
975
- params,
976
- "Final JSON does not extend emitted tool-input prefix",
977
- {
978
- emittedLength: params.state.emittedInput.length,
979
- finalLength: params.finalFullJson.length
980
- }
981
- );
982
- }
983
- return result;
984
- }
985
-
986
1158
  // src/core/utils/xml-root-repair.ts
987
1159
  var XML_SELF_CLOSING_ROOT_WITH_BODY_REGEX = /^<([A-Za-z_][A-Za-z0-9_-]*)\s*\r?\n([\s\S]+?)\r?\n\s*\/>\s*$/;
988
1160
  function tryRepairXmlSelfClosingRootWithBody(rawText, toolNames) {
@@ -1007,15 +1179,241 @@ ${body}
1007
1179
  </${rootTag}>`;
1008
1180
  }
1009
1181
 
1010
- // src/core/protocols/morph-xml-protocol.ts
1011
- function getToolSchema(tools, toolName) {
1012
- var _a;
1013
- return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
1014
- }
1015
- function shouldEmitRawToolCallTextOnError2(options) {
1016
- return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
1017
- }
1018
- function processToolCall(params) {
1182
+ // src/core/utils/xml-tool-tag-scanner.ts
1183
+ var selfClosingTagCache = /* @__PURE__ */ new Map();
1184
+ function getSelfClosingTagPattern(toolName) {
1185
+ let pattern = selfClosingTagCache.get(toolName);
1186
+ if (!pattern) {
1187
+ pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
1188
+ selfClosingTagCache.set(toolName, pattern);
1189
+ }
1190
+ return pattern;
1191
+ }
1192
+ function findSelfClosingTag(text, toolName, fromIndex) {
1193
+ const pattern = getSelfClosingTagPattern(toolName);
1194
+ pattern.lastIndex = fromIndex;
1195
+ const match = pattern.exec(text);
1196
+ if (!match || match.index === void 0) {
1197
+ return null;
1198
+ }
1199
+ return { index: match.index, length: match[0].length };
1200
+ }
1201
+ function findNextToolTag(text, searchIndex, toolName) {
1202
+ var _a, _b;
1203
+ const startTag = `<${toolName}>`;
1204
+ const openIdx = text.indexOf(startTag, searchIndex);
1205
+ const selfMatch = findSelfClosingTag(text, toolName, searchIndex);
1206
+ const selfIdx = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
1207
+ if (openIdx === -1 && selfIdx === -1) {
1208
+ return null;
1209
+ }
1210
+ const isSelfClosing = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx);
1211
+ return {
1212
+ tagStart: isSelfClosing ? selfIdx : openIdx,
1213
+ isSelfClosing,
1214
+ tagLength: isSelfClosing ? (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0 : startTag.length
1215
+ };
1216
+ }
1217
+ function findEarliestToolTag(buffer, toolNames) {
1218
+ var _a, _b;
1219
+ let bestIndex = -1;
1220
+ let bestName = "";
1221
+ let bestSelfClosing = false;
1222
+ let bestTagLength = 0;
1223
+ for (const name of toolNames) {
1224
+ const openTag = `<${name}>`;
1225
+ const idxOpen = buffer.indexOf(openTag);
1226
+ const selfMatch = findSelfClosingTag(buffer, name, 0);
1227
+ const idxSelf = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
1228
+ if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
1229
+ bestIndex = idxOpen;
1230
+ bestName = name;
1231
+ bestSelfClosing = false;
1232
+ bestTagLength = openTag.length;
1233
+ }
1234
+ if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
1235
+ bestIndex = idxSelf;
1236
+ bestName = name;
1237
+ bestSelfClosing = true;
1238
+ bestTagLength = (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0;
1239
+ }
1240
+ }
1241
+ return {
1242
+ index: bestIndex,
1243
+ name: bestName,
1244
+ selfClosing: bestSelfClosing,
1245
+ tagLength: bestTagLength
1246
+ };
1247
+ }
1248
+
1249
+ // src/core/protocols/morph-xml-stream-state-machine.ts
1250
+ function processToolCallInBuffer(params) {
1251
+ const {
1252
+ buffer,
1253
+ currentToolCall,
1254
+ tools,
1255
+ options,
1256
+ controller,
1257
+ flushText,
1258
+ setBuffer,
1259
+ parseOptions,
1260
+ emitToolInputProgress: emitToolInputProgress2,
1261
+ handleStreamingToolCallEnd: handleStreamingToolCallEnd2
1262
+ } = params;
1263
+ const endTagPattern = new RegExp(
1264
+ `</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
1265
+ );
1266
+ const endMatch = endTagPattern.exec(buffer);
1267
+ if (!endMatch || endMatch.index === void 0) {
1268
+ emitToolInputProgress2(controller, currentToolCall, buffer);
1269
+ return { buffer, currentToolCall, shouldBreak: true };
1270
+ }
1271
+ const endIdx = endMatch.index;
1272
+ const endPos = endIdx + endMatch[0].length;
1273
+ const content = buffer.substring(0, endIdx);
1274
+ emitToolInputProgress2(controller, currentToolCall, content);
1275
+ const remainder = buffer.substring(endPos);
1276
+ setBuffer(remainder);
1277
+ handleStreamingToolCallEnd2({
1278
+ toolContent: content,
1279
+ currentToolCall,
1280
+ tools,
1281
+ options,
1282
+ ctrl: controller,
1283
+ flushText,
1284
+ parseOptions
1285
+ });
1286
+ return {
1287
+ buffer: remainder,
1288
+ currentToolCall: null,
1289
+ shouldBreak: false
1290
+ };
1291
+ }
1292
+ function processNoToolCallInBuffer(params) {
1293
+ const {
1294
+ buffer,
1295
+ toolNames,
1296
+ controller,
1297
+ flushText,
1298
+ tools,
1299
+ options,
1300
+ parseOptions,
1301
+ setBuffer,
1302
+ emitToolInputStart,
1303
+ findPotentialToolTagStart: findPotentialToolTagStart2,
1304
+ handleStreamingToolCallEnd: handleStreamingToolCallEnd2
1305
+ } = params;
1306
+ const {
1307
+ index: earliestStartTagIndex,
1308
+ name: earliestToolName,
1309
+ selfClosing,
1310
+ tagLength
1311
+ } = findEarliestToolTag(buffer, toolNames);
1312
+ if (earliestStartTagIndex === -1) {
1313
+ const potentialStart = findPotentialToolTagStart2(buffer, toolNames);
1314
+ const safeLen = Math.max(
1315
+ 0,
1316
+ potentialStart === -1 ? buffer.length : potentialStart
1317
+ );
1318
+ const remaining = buffer.slice(safeLen);
1319
+ if (safeLen > 0) {
1320
+ flushText(controller, buffer.slice(0, safeLen));
1321
+ setBuffer(remaining);
1322
+ }
1323
+ return {
1324
+ buffer: remaining,
1325
+ currentToolCall: null,
1326
+ shouldBreak: true,
1327
+ shouldContinue: false
1328
+ };
1329
+ }
1330
+ flushText(controller, buffer.substring(0, earliestStartTagIndex));
1331
+ if (selfClosing) {
1332
+ const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
1333
+ setBuffer(newBuffer2);
1334
+ const currentToolCall = emitToolInputStart(controller, earliestToolName);
1335
+ handleStreamingToolCallEnd2({
1336
+ toolContent: "",
1337
+ currentToolCall,
1338
+ tools,
1339
+ options,
1340
+ ctrl: controller,
1341
+ flushText,
1342
+ parseOptions
1343
+ });
1344
+ return {
1345
+ buffer: newBuffer2,
1346
+ currentToolCall: null,
1347
+ shouldBreak: false,
1348
+ shouldContinue: false
1349
+ };
1350
+ }
1351
+ const startTag = `<${earliestToolName}>`;
1352
+ const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
1353
+ setBuffer(newBuffer);
1354
+ return {
1355
+ buffer: newBuffer,
1356
+ currentToolCall: emitToolInputStart(controller, earliestToolName),
1357
+ shouldBreak: false,
1358
+ shouldContinue: true
1359
+ };
1360
+ }
1361
+ function createProcessBufferHandler(options) {
1362
+ return (controller) => {
1363
+ while (true) {
1364
+ const currentToolCall = options.getCurrentToolCall();
1365
+ if (currentToolCall) {
1366
+ const result = processToolCallInBuffer({
1367
+ buffer: options.getBuffer(),
1368
+ currentToolCall,
1369
+ tools: options.tools,
1370
+ options: options.parserOptions,
1371
+ controller,
1372
+ flushText: options.flushText,
1373
+ setBuffer: options.setBuffer,
1374
+ parseOptions: options.parseOptions,
1375
+ emitToolInputProgress: options.emitToolInputProgress,
1376
+ handleStreamingToolCallEnd: options.handleStreamingToolCallEnd
1377
+ });
1378
+ options.setBuffer(result.buffer);
1379
+ options.setCurrentToolCall(result.currentToolCall);
1380
+ if (result.shouldBreak) {
1381
+ break;
1382
+ }
1383
+ } else {
1384
+ const result = processNoToolCallInBuffer({
1385
+ buffer: options.getBuffer(),
1386
+ toolNames: options.toolNames,
1387
+ controller,
1388
+ flushText: options.flushText,
1389
+ tools: options.tools,
1390
+ options: options.parserOptions,
1391
+ parseOptions: options.parseOptions,
1392
+ setBuffer: options.setBuffer,
1393
+ emitToolInputStart: options.emitToolInputStart,
1394
+ findPotentialToolTagStart: options.findPotentialToolTagStart,
1395
+ handleStreamingToolCallEnd: options.handleStreamingToolCallEnd
1396
+ });
1397
+ options.setBuffer(result.buffer);
1398
+ options.setCurrentToolCall(result.currentToolCall);
1399
+ if (result.shouldBreak) {
1400
+ break;
1401
+ }
1402
+ if (result.shouldContinue) {
1403
+ continue;
1404
+ }
1405
+ break;
1406
+ }
1407
+ }
1408
+ };
1409
+ }
1410
+
1411
+ // src/core/protocols/morph-xml-protocol.ts
1412
+ function getToolSchema(tools, toolName) {
1413
+ var _a;
1414
+ return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
1415
+ }
1416
+ function processToolCall(params) {
1019
1417
  var _a, _b;
1020
1418
  const { toolCall, tools, options, text, processedElements, parseOptions } = params;
1021
1419
  const toolSchema = getToolSchema(tools, toolCall.toolName);
@@ -1243,6 +1641,76 @@ function schemaAllowsArrayType(schema) {
1243
1641
  }
1244
1642
  return false;
1245
1643
  }
1644
+ function schemaAllowsStringType(schema) {
1645
+ if (!schema || typeof schema !== "object") {
1646
+ return false;
1647
+ }
1648
+ const schemaRecord = schema;
1649
+ const typeValue = schemaRecord.type;
1650
+ if (typeValue === "string") {
1651
+ return true;
1652
+ }
1653
+ if (Array.isArray(typeValue) && typeValue.includes("string")) {
1654
+ return true;
1655
+ }
1656
+ const unions = [schemaRecord.anyOf, schemaRecord.oneOf, schemaRecord.allOf];
1657
+ for (const union of unions) {
1658
+ if (!Array.isArray(union)) {
1659
+ continue;
1660
+ }
1661
+ if (union.some((entry) => schemaAllowsStringType(entry))) {
1662
+ return true;
1663
+ }
1664
+ }
1665
+ return false;
1666
+ }
1667
+ function getObjectSchemaStringPropertyNames(schema) {
1668
+ const propertyNames = getObjectSchemaPropertyNames(schema);
1669
+ if (!propertyNames) {
1670
+ return null;
1671
+ }
1672
+ const out = /* @__PURE__ */ new Set();
1673
+ for (const name of propertyNames) {
1674
+ const property = getSchemaObjectProperty(schema, name);
1675
+ if (schemaAllowsStringType(property)) {
1676
+ out.add(name);
1677
+ }
1678
+ }
1679
+ return out;
1680
+ }
1681
+ function findTrailingUnclosedStringTag(options) {
1682
+ let bestName = null;
1683
+ let bestOpenIndex = -1;
1684
+ for (const name of options.stringPropertyNames) {
1685
+ const openPattern = new RegExp(
1686
+ `<${escapeRegExp(name)}(?:\\s[^>]*)?>`,
1687
+ "gi"
1688
+ );
1689
+ const closePattern = new RegExp(`</\\s*${escapeRegExp(name)}\\s*>`, "gi");
1690
+ let lastOpen = -1;
1691
+ for (const match of options.toolContent.matchAll(openPattern)) {
1692
+ const index = match.index;
1693
+ if (index !== void 0) {
1694
+ lastOpen = index;
1695
+ }
1696
+ }
1697
+ if (lastOpen === -1) {
1698
+ continue;
1699
+ }
1700
+ let lastClose = -1;
1701
+ for (const match of options.toolContent.matchAll(closePattern)) {
1702
+ const index = match.index;
1703
+ if (index !== void 0) {
1704
+ lastClose = index;
1705
+ }
1706
+ }
1707
+ if (lastOpen > lastClose && lastOpen > bestOpenIndex) {
1708
+ bestOpenIndex = lastOpen;
1709
+ bestName = name;
1710
+ }
1711
+ }
1712
+ return bestName;
1713
+ }
1246
1714
  function getSchemaObjectProperty(schema, propertyName) {
1247
1715
  if (!schema || typeof schema !== "object") {
1248
1716
  return null;
@@ -1292,8 +1760,10 @@ function isStableXmlProgressCandidate(options) {
1292
1760
  }
1293
1761
  function parseXmlContentForStreamProgress({
1294
1762
  toolContent,
1763
+ toolName,
1295
1764
  toolSchema,
1296
- parseOptions
1765
+ parseOptions,
1766
+ tools
1297
1767
  }) {
1298
1768
  const tryParse = (content) => {
1299
1769
  try {
@@ -1312,7 +1782,29 @@ function parseXmlContentForStreamProgress({
1312
1782
  parsed: strictFull,
1313
1783
  toolSchema
1314
1784
  })) {
1315
- return JSON.stringify(strictFull);
1785
+ return stringifyToolInputWithSchema({
1786
+ toolName,
1787
+ args: strictFull,
1788
+ tools
1789
+ });
1790
+ }
1791
+ const stringPropertyNames = getObjectSchemaStringPropertyNames(toolSchema);
1792
+ if (stringPropertyNames && stringPropertyNames.size > 0) {
1793
+ const trailingStringTag = findTrailingUnclosedStringTag({
1794
+ toolContent,
1795
+ stringPropertyNames
1796
+ });
1797
+ if (trailingStringTag) {
1798
+ const repaired = `${toolContent}</${trailingStringTag}>`;
1799
+ const parsedRepaired = tryParse(repaired);
1800
+ if (parsedRepaired !== null) {
1801
+ return stringifyToolInputWithSchema({
1802
+ toolName,
1803
+ args: parsedRepaired,
1804
+ tools
1805
+ });
1806
+ }
1807
+ }
1316
1808
  }
1317
1809
  let searchEnd = toolContent.length;
1318
1810
  while (searchEnd > 0) {
@@ -1331,7 +1823,11 @@ function parseXmlContentForStreamProgress({
1331
1823
  parsed: parsedCandidate,
1332
1824
  toolSchema
1333
1825
  })) {
1334
- return JSON.stringify(parsedCandidate);
1826
+ return stringifyToolInputWithSchema({
1827
+ toolName,
1828
+ args: parsedCandidate,
1829
+ tools
1830
+ });
1335
1831
  }
1336
1832
  searchEnd = gtIndex;
1337
1833
  }
@@ -1356,37 +1852,35 @@ function handleStreamingToolCallEnd(params) {
1356
1852
  flushText(ctrl);
1357
1853
  try {
1358
1854
  const parsedResult = parse2(toolContent, toolSchema, parseConfig);
1359
- const finalInput = JSON.stringify(parsedResult);
1360
- emitFinalRemainder({
1855
+ const finalInput = stringifyToolInputWithSchema({
1856
+ toolName: currentToolCall.name,
1857
+ args: parsedResult,
1858
+ tools
1859
+ });
1860
+ emitFinalizedToolInputLifecycle({
1361
1861
  controller: ctrl,
1362
1862
  id: currentToolCall.toolCallId,
1363
1863
  state: currentToolCall,
1364
- finalFullJson: finalInput,
1365
- onMismatch: options == null ? void 0 : options.onError
1366
- });
1367
- ctrl.enqueue({
1368
- type: "tool-input-end",
1369
- id: currentToolCall.toolCallId
1370
- });
1371
- ctrl.enqueue({
1372
- type: "tool-call",
1373
- toolCallId: currentToolCall.toolCallId,
1374
1864
  toolName: currentToolCall.name,
1375
- input: finalInput
1865
+ finalInput,
1866
+ onMismatch: options == null ? void 0 : options.onError
1376
1867
  });
1377
1868
  } catch (error) {
1378
- ctrl.enqueue({
1379
- type: "tool-input-end",
1380
- id: currentToolCall.toolCallId
1381
- });
1382
1869
  const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
1870
+ const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
1871
+ emitFailedToolInputLifecycle({
1872
+ controller: ctrl,
1873
+ id: currentToolCall.toolCallId,
1874
+ emitRawToolCallTextOnError: emitRawFallback,
1875
+ rawToolCallText: original,
1876
+ emitRawText: (rawText) => {
1877
+ flushText(ctrl, rawText);
1878
+ }
1879
+ });
1383
1880
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
1384
1881
  toolCall: original,
1385
1882
  error
1386
1883
  });
1387
- if (shouldEmitRawToolCallTextOnError2(options)) {
1388
- flushText(ctrl, original);
1389
- }
1390
1884
  }
1391
1885
  }
1392
1886
  function findClosingTagEndFlexible(text, contentStart, toolName) {
@@ -1486,22 +1980,6 @@ function nextTagToken(text, fromPos) {
1486
1980
  nextPos: open.nextPos
1487
1981
  };
1488
1982
  }
1489
- function findNextToolTag(text, searchIndex, toolName) {
1490
- var _a, _b;
1491
- const startTag = `<${toolName}>`;
1492
- const openIdx = text.indexOf(startTag, searchIndex);
1493
- const selfMatch = findSelfClosingTag(text, toolName, searchIndex);
1494
- const selfIdx = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
1495
- if (openIdx === -1 && selfIdx === -1) {
1496
- return null;
1497
- }
1498
- const isSelfClosing = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx);
1499
- return {
1500
- tagStart: isSelfClosing ? selfIdx : openIdx,
1501
- isSelfClosing,
1502
- tagLength: isSelfClosing ? (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0 : startTag.length
1503
- };
1504
- }
1505
1983
  function findLastCloseTagStart(segment, toolName) {
1506
1984
  const closeTagPattern = new RegExp(
1507
1985
  `</\\s*${escapeRegExp(toolName)}\\s*>`,
@@ -1529,24 +2007,6 @@ function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, tagLength)
1529
2007
  });
1530
2008
  return endIndex;
1531
2009
  }
1532
- var selfClosingTagCache = /* @__PURE__ */ new Map();
1533
- function getSelfClosingTagPattern(toolName) {
1534
- let pattern = selfClosingTagCache.get(toolName);
1535
- if (!pattern) {
1536
- pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
1537
- selfClosingTagCache.set(toolName, pattern);
1538
- }
1539
- return pattern;
1540
- }
1541
- function findSelfClosingTag(text, toolName, fromIndex) {
1542
- const pattern = getSelfClosingTagPattern(toolName);
1543
- pattern.lastIndex = fromIndex;
1544
- const match = pattern.exec(text);
1545
- if (!match || match.index === void 0) {
1546
- return null;
1547
- }
1548
- return { index: match.index, length: match[0].length };
1549
- }
1550
2010
  function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, startTag) {
1551
2011
  const contentStart = tagStart + startTag.length;
1552
2012
  const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
@@ -1698,39 +2158,6 @@ function findLinePrefixedToolCall(text, toolNames) {
1698
2158
  }
1699
2159
  return best;
1700
2160
  }
1701
- function findEarliestToolTag(buffer, toolNames) {
1702
- var _a, _b;
1703
- let bestIndex = -1;
1704
- let bestName = "";
1705
- let bestSelfClosing = false;
1706
- let bestTagLength = 0;
1707
- if (toolNames.length > 0) {
1708
- for (const name of toolNames) {
1709
- const openTag = `<${name}>`;
1710
- const idxOpen = buffer.indexOf(openTag);
1711
- const selfMatch = findSelfClosingTag(buffer, name, 0);
1712
- const idxSelf = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
1713
- if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
1714
- bestIndex = idxOpen;
1715
- bestName = name;
1716
- bestSelfClosing = false;
1717
- bestTagLength = openTag.length;
1718
- }
1719
- if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
1720
- bestIndex = idxSelf;
1721
- bestName = name;
1722
- bestSelfClosing = true;
1723
- bestTagLength = (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0;
1724
- }
1725
- }
1726
- }
1727
- return {
1728
- index: bestIndex,
1729
- name: bestName,
1730
- selfClosing: bestSelfClosing,
1731
- tagLength: bestTagLength
1732
- };
1733
- }
1734
2161
  function isOpenTagPrefix(suffix, toolName) {
1735
2162
  return `${toolName}>`.startsWith(suffix);
1736
2163
  }
@@ -1748,219 +2175,65 @@ function consumeToolNamePrefix(text, index, toolName) {
1748
2175
  if (text.charAt(i) !== toolName.charAt(nameIndex)) {
1749
2176
  return { index: i, done: false, valid: false };
1750
2177
  }
1751
- i += 1;
1752
- nameIndex += 1;
1753
- }
1754
- return { index: i, done: nameIndex === toolName.length, valid: true };
1755
- }
1756
- function isSelfClosingSuffixRemainder(text, index) {
1757
- if (text.charAt(index) !== "/") {
1758
- return false;
1759
- }
1760
- if (index + 1 >= text.length) {
1761
- return true;
1762
- }
1763
- return index + 1 === text.length - 1 && text.charAt(index + 1) === ">";
1764
- }
1765
- function isSelfClosingTagPrefix(suffix, toolName) {
1766
- let i = consumeWhitespace(suffix, 0);
1767
- if (i >= suffix.length) {
1768
- return true;
1769
- }
1770
- const nameRemainder = suffix.slice(i);
1771
- if (toolName.startsWith(nameRemainder)) {
1772
- return true;
1773
- }
1774
- const nameResult = consumeToolNamePrefix(suffix, i, toolName);
1775
- if (!nameResult.valid) {
1776
- return false;
1777
- }
1778
- i = nameResult.index;
1779
- if (i >= suffix.length) {
1780
- return true;
1781
- }
1782
- if (!nameResult.done) {
1783
- return false;
1784
- }
1785
- i = consumeWhitespace(suffix, i);
1786
- if (i >= suffix.length) {
1787
- return true;
1788
- }
1789
- return isSelfClosingSuffixRemainder(suffix, i);
1790
- }
1791
- function findPotentialToolTagStart(buffer, toolNames) {
1792
- if (toolNames.length === 0 || buffer.length === 0) {
1793
- return -1;
1794
- }
1795
- const lastGt = buffer.lastIndexOf(">");
1796
- const offset = lastGt === -1 ? 0 : lastGt + 1;
1797
- const trailing = buffer.slice(offset);
1798
- for (let i = trailing.length - 1; i >= 0; i -= 1) {
1799
- if (trailing.charAt(i) !== "<") {
1800
- continue;
1801
- }
1802
- const suffix = trailing.slice(i + 1);
1803
- for (const name of toolNames) {
1804
- if (isOpenTagPrefix(suffix, name) || isSelfClosingTagPrefix(suffix, name)) {
1805
- return offset + i;
1806
- }
1807
- }
1808
- }
1809
- return -1;
1810
- }
1811
- function processToolCallInBuffer(params) {
1812
- const {
1813
- buffer,
1814
- currentToolCall,
1815
- tools,
1816
- options,
1817
- controller,
1818
- flushText,
1819
- setBuffer,
1820
- parseOptions,
1821
- emitToolInputProgress: emitToolInputProgress2
1822
- } = params;
1823
- const endTagPattern = new RegExp(
1824
- `</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
1825
- );
1826
- const endMatch = endTagPattern.exec(buffer);
1827
- if (!endMatch || endMatch.index === void 0) {
1828
- emitToolInputProgress2(controller, currentToolCall, buffer);
1829
- return { buffer, currentToolCall, shouldBreak: true };
1830
- }
1831
- const endIdx = endMatch.index;
1832
- const endPos = endIdx + endMatch[0].length;
1833
- const content = buffer.substring(0, endIdx);
1834
- emitToolInputProgress2(controller, currentToolCall, content);
1835
- const remainder = buffer.substring(endPos);
1836
- setBuffer(remainder);
1837
- handleStreamingToolCallEnd({
1838
- toolContent: content,
1839
- currentToolCall,
1840
- tools,
1841
- options,
1842
- ctrl: controller,
1843
- flushText,
1844
- parseOptions
1845
- });
1846
- return {
1847
- buffer: remainder,
1848
- currentToolCall: null,
1849
- shouldBreak: false
1850
- };
1851
- }
1852
- function processNoToolCallInBuffer(params) {
1853
- const {
1854
- buffer,
1855
- toolNames,
1856
- controller,
1857
- flushText,
1858
- tools,
1859
- options,
1860
- parseOptions,
1861
- setBuffer,
1862
- emitToolInputStart
1863
- } = params;
1864
- const {
1865
- index: earliestStartTagIndex,
1866
- name: earliestToolName,
1867
- selfClosing,
1868
- tagLength
1869
- } = findEarliestToolTag(buffer, toolNames);
1870
- if (earliestStartTagIndex === -1) {
1871
- const potentialStart = findPotentialToolTagStart(buffer, toolNames);
1872
- const safeLen = Math.max(
1873
- 0,
1874
- potentialStart === -1 ? buffer.length : potentialStart
1875
- );
1876
- const remaining = buffer.slice(safeLen);
1877
- if (safeLen > 0) {
1878
- flushText(controller, buffer.slice(0, safeLen));
1879
- setBuffer(remaining);
1880
- }
1881
- return {
1882
- buffer: remaining,
1883
- currentToolCall: null,
1884
- shouldBreak: true,
1885
- shouldContinue: false
1886
- };
2178
+ i += 1;
2179
+ nameIndex += 1;
1887
2180
  }
1888
- flushText(controller, buffer.substring(0, earliestStartTagIndex));
1889
- if (selfClosing) {
1890
- const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
1891
- setBuffer(newBuffer2);
1892
- const currentToolCall = emitToolInputStart(controller, earliestToolName);
1893
- handleStreamingToolCallEnd({
1894
- toolContent: "",
1895
- currentToolCall,
1896
- tools,
1897
- options,
1898
- ctrl: controller,
1899
- flushText,
1900
- parseOptions
1901
- });
1902
- return {
1903
- buffer: newBuffer2,
1904
- currentToolCall: null,
1905
- shouldBreak: false,
1906
- shouldContinue: false
1907
- };
2181
+ return { index: i, done: nameIndex === toolName.length, valid: true };
2182
+ }
2183
+ function isSelfClosingSuffixRemainder(text, index) {
2184
+ if (text.charAt(index) !== "/") {
2185
+ return false;
1908
2186
  }
1909
- const startTag = `<${earliestToolName}>`;
1910
- const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
1911
- setBuffer(newBuffer);
1912
- return {
1913
- buffer: newBuffer,
1914
- currentToolCall: emitToolInputStart(controller, earliestToolName),
1915
- shouldBreak: false,
1916
- shouldContinue: true
1917
- };
2187
+ if (index + 1 >= text.length) {
2188
+ return true;
2189
+ }
2190
+ return index + 1 === text.length - 1 && text.charAt(index + 1) === ">";
1918
2191
  }
1919
- function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions, emitToolInputProgress2, emitToolInputStart) {
1920
- return (controller) => {
1921
- while (true) {
1922
- const currentToolCall = getCurrentToolCall();
1923
- if (currentToolCall) {
1924
- const result = processToolCallInBuffer({
1925
- buffer: getBuffer(),
1926
- currentToolCall,
1927
- tools,
1928
- options,
1929
- controller,
1930
- flushText,
1931
- setBuffer,
1932
- parseOptions,
1933
- emitToolInputProgress: emitToolInputProgress2
1934
- });
1935
- setBuffer(result.buffer);
1936
- setCurrentToolCall(result.currentToolCall);
1937
- if (result.shouldBreak) {
1938
- break;
1939
- }
1940
- } else {
1941
- const result = processNoToolCallInBuffer({
1942
- buffer: getBuffer(),
1943
- toolNames,
1944
- controller,
1945
- flushText,
1946
- tools,
1947
- options,
1948
- parseOptions,
1949
- setBuffer,
1950
- emitToolInputStart
1951
- });
1952
- setBuffer(result.buffer);
1953
- setCurrentToolCall(result.currentToolCall);
1954
- if (result.shouldBreak) {
1955
- break;
1956
- }
1957
- if (result.shouldContinue) {
1958
- continue;
1959
- }
1960
- break;
2192
+ function isSelfClosingTagPrefix(suffix, toolName) {
2193
+ let i = consumeWhitespace(suffix, 0);
2194
+ if (i >= suffix.length) {
2195
+ return true;
2196
+ }
2197
+ const nameRemainder = suffix.slice(i);
2198
+ if (toolName.startsWith(nameRemainder)) {
2199
+ return true;
2200
+ }
2201
+ const nameResult = consumeToolNamePrefix(suffix, i, toolName);
2202
+ if (!nameResult.valid) {
2203
+ return false;
2204
+ }
2205
+ i = nameResult.index;
2206
+ if (i >= suffix.length) {
2207
+ return true;
2208
+ }
2209
+ if (!nameResult.done) {
2210
+ return false;
2211
+ }
2212
+ i = consumeWhitespace(suffix, i);
2213
+ if (i >= suffix.length) {
2214
+ return true;
2215
+ }
2216
+ return isSelfClosingSuffixRemainder(suffix, i);
2217
+ }
2218
+ function findPotentialToolTagStart(buffer, toolNames) {
2219
+ if (toolNames.length === 0 || buffer.length === 0) {
2220
+ return -1;
2221
+ }
2222
+ const lastGt = buffer.lastIndexOf(">");
2223
+ const offset = lastGt === -1 ? 0 : lastGt + 1;
2224
+ const trailing = buffer.slice(offset);
2225
+ for (let i = trailing.length - 1; i >= 0; i -= 1) {
2226
+ if (trailing.charAt(i) !== "<") {
2227
+ continue;
2228
+ }
2229
+ const suffix = trailing.slice(i + 1);
2230
+ for (const name of toolNames) {
2231
+ if (isOpenTagPrefix(suffix, name) || isSelfClosingTagPrefix(suffix, name)) {
2232
+ return offset + i;
1961
2233
  }
1962
2234
  }
1963
- };
2235
+ }
2236
+ return -1;
1964
2237
  }
1965
2238
  function findToolCallsWithFallbacks(text, toolNames) {
1966
2239
  let parseText = text;
@@ -1992,7 +2265,7 @@ var morphXmlProtocol = (protocolOptions) => {
1992
2265
  };
1993
2266
  return {
1994
2267
  formatTools({ tools, toolSystemPromptTemplate }) {
1995
- return toolSystemPromptTemplate(tools || []);
2268
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
1996
2269
  },
1997
2270
  formatToolCall(toolCall) {
1998
2271
  let args = {};
@@ -2010,7 +2283,7 @@ var morphXmlProtocol = (protocolOptions) => {
2010
2283
  });
2011
2284
  },
2012
2285
  parseGeneratedText({ text, tools, options }) {
2013
- const toolNames = tools.map((t) => t.name).filter(Boolean);
2286
+ const toolNames = extractToolNames(tools);
2014
2287
  if (toolNames.length === 0) {
2015
2288
  return [{ type: "text", text }];
2016
2289
  }
@@ -2046,7 +2319,7 @@ var morphXmlProtocol = (protocolOptions) => {
2046
2319
  return processedElements;
2047
2320
  },
2048
2321
  createStreamParser({ tools, options }) {
2049
- const toolNames = tools.map((t) => t.name).filter(Boolean);
2322
+ const toolNames = extractToolNames(tools);
2050
2323
  let buffer = "";
2051
2324
  let currentToolCall = null;
2052
2325
  let currentTextId = null;
@@ -2067,6 +2340,7 @@ var morphXmlProtocol = (protocolOptions) => {
2067
2340
  name: toolName,
2068
2341
  toolCallId: generateToolCallId(),
2069
2342
  emittedInput: "",
2343
+ lastProgressContentLength: null,
2070
2344
  lastProgressGtIndex: null,
2071
2345
  lastProgressFullInput: null
2072
2346
  };
@@ -2079,7 +2353,8 @@ var morphXmlProtocol = (protocolOptions) => {
2079
2353
  };
2080
2354
  const emitToolInputProgress2 = (controller, toolCall, toolContent) => {
2081
2355
  const progressGtIndex = toolContent.lastIndexOf(">");
2082
- if (toolCall.lastProgressGtIndex === progressGtIndex) {
2356
+ const progressContentLength = toolContent.length;
2357
+ if (toolCall.lastProgressGtIndex === progressGtIndex && toolCall.lastProgressContentLength === progressContentLength) {
2083
2358
  const cached = toolCall.lastProgressFullInput;
2084
2359
  if (cached == null) {
2085
2360
  return;
@@ -2087,22 +2362,24 @@ var morphXmlProtocol = (protocolOptions) => {
2087
2362
  if (cached === "{}" && toolContent.trim().length === 0) {
2088
2363
  return;
2089
2364
  }
2090
- const prefixCandidate2 = toIncompleteJsonPrefix(cached);
2091
- emitPrefixDelta({
2365
+ emitToolInputProgressDelta({
2092
2366
  controller,
2093
2367
  id: toolCall.toolCallId,
2094
2368
  state: toolCall,
2095
- candidate: prefixCandidate2
2369
+ fullInput: cached
2096
2370
  });
2097
2371
  return;
2098
2372
  }
2099
2373
  const toolSchema = getToolSchema(tools, toolCall.name);
2100
2374
  const fullInput = parseXmlContentForStreamProgress({
2101
2375
  toolContent,
2376
+ toolName: toolCall.name,
2102
2377
  toolSchema,
2103
- parseOptions
2378
+ parseOptions,
2379
+ tools
2104
2380
  });
2105
2381
  toolCall.lastProgressGtIndex = progressGtIndex;
2382
+ toolCall.lastProgressContentLength = progressContentLength;
2106
2383
  toolCall.lastProgressFullInput = fullInput;
2107
2384
  if (fullInput == null) {
2108
2385
  return;
@@ -2110,12 +2387,11 @@ var morphXmlProtocol = (protocolOptions) => {
2110
2387
  if (fullInput === "{}" && toolContent.trim().length === 0) {
2111
2388
  return;
2112
2389
  }
2113
- const prefixCandidate = toIncompleteJsonPrefix(fullInput);
2114
- emitPrefixDelta({
2390
+ emitToolInputProgressDelta({
2115
2391
  controller,
2116
2392
  id: toolCall.toolCallId,
2117
2393
  state: toolCall,
2118
- candidate: prefixCandidate
2394
+ fullInput
2119
2395
  });
2120
2396
  };
2121
2397
  const finalizeUnclosedToolCall = (controller) => {
@@ -2137,59 +2413,59 @@ var morphXmlProtocol = (protocolOptions) => {
2137
2413
  );
2138
2414
  }
2139
2415
  const parsedResult = parse2(buffer, toolSchema, parseConfig);
2140
- const finalInput = JSON.stringify(parsedResult);
2141
- emitFinalRemainder({
2416
+ const finalInput = stringifyToolInputWithSchema({
2417
+ toolName: currentToolCall.name,
2418
+ args: parsedResult,
2419
+ tools
2420
+ });
2421
+ emitFinalizedToolInputLifecycle({
2142
2422
  controller,
2143
2423
  id: currentToolCall.toolCallId,
2144
2424
  state: currentToolCall,
2145
- finalFullJson: finalInput,
2146
- onMismatch: options == null ? void 0 : options.onError
2147
- });
2148
- controller.enqueue({
2149
- type: "tool-input-end",
2150
- id: currentToolCall.toolCallId
2151
- });
2152
- controller.enqueue({
2153
- type: "tool-call",
2154
- toolCallId: currentToolCall.toolCallId,
2155
2425
  toolName: currentToolCall.name,
2156
- input: finalInput
2426
+ finalInput,
2427
+ onMismatch: options == null ? void 0 : options.onError
2157
2428
  });
2158
2429
  } catch (error) {
2159
- controller.enqueue({
2160
- type: "tool-input-end",
2161
- id: currentToolCall.toolCallId
2162
- });
2163
2430
  const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
2431
+ const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
2432
+ emitFailedToolInputLifecycle({
2433
+ controller,
2434
+ id: currentToolCall.toolCallId,
2435
+ emitRawToolCallTextOnError: emitRawFallback,
2436
+ rawToolCallText: unfinishedContent,
2437
+ emitRawText: (rawText) => {
2438
+ flushText(controller, rawText);
2439
+ }
2440
+ });
2164
2441
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
2165
2442
  options,
2166
2443
  "Could not complete streaming XML tool call at finish.",
2167
2444
  { toolCall: unfinishedContent, error }
2168
2445
  );
2169
- if (shouldEmitRawToolCallTextOnError2(options)) {
2170
- flushText(controller, unfinishedContent);
2171
- }
2172
2446
  }
2173
2447
  buffer = "";
2174
2448
  currentToolCall = null;
2175
2449
  };
2176
- const processBuffer = createProcessBufferHandler(
2177
- () => buffer,
2178
- (newBuffer) => {
2450
+ const processBuffer = createProcessBufferHandler({
2451
+ getBuffer: () => buffer,
2452
+ setBuffer: (newBuffer) => {
2179
2453
  buffer = newBuffer;
2180
2454
  },
2181
- () => currentToolCall,
2182
- (newToolCall) => {
2455
+ getCurrentToolCall: () => currentToolCall,
2456
+ setCurrentToolCall: (newToolCall) => {
2183
2457
  currentToolCall = newToolCall;
2184
2458
  },
2185
2459
  tools,
2186
- options,
2460
+ parserOptions: options,
2187
2461
  toolNames,
2188
2462
  flushText,
2189
2463
  parseOptions,
2190
- emitToolInputProgress2,
2191
- emitToolInputStart
2192
- );
2464
+ emitToolInputProgress: emitToolInputProgress2,
2465
+ emitToolInputStart,
2466
+ findPotentialToolTagStart,
2467
+ handleStreamingToolCallEnd
2468
+ });
2193
2469
  return new TransformStream({
2194
2470
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stateful stream parsing requires branching over chunk lifecycle and parser states.
2195
2471
  transform(chunk, controller) {
@@ -2250,44 +2526,128 @@ var morphXmlProtocol = (protocolOptions) => {
2250
2526
  function isProtocolFactory(protocol) {
2251
2527
  return typeof protocol === "function";
2252
2528
  }
2253
- function isTCMProtocolFactory(protocol) {
2254
- return typeof protocol === "function";
2255
- }
2529
+ var isTCMProtocolFactory = isProtocolFactory;
2256
2530
 
2257
- // src/core/utils/tool-call-coercion.ts
2258
- function coerceToolCallInput(toolName, input, tools) {
2531
+ // src/core/protocols/qwen3coder-stream-call-content.ts
2532
+ function consumeToolNameTag(options) {
2533
+ var _a, _b, _c, _d;
2534
+ if (options.callState.toolName) {
2535
+ return options.work;
2536
+ }
2537
+ const match = options.nameTagRe.exec(options.work);
2538
+ if (!match) {
2539
+ return options.work;
2540
+ }
2541
+ const value = options.normalizeXmlTextValue((_a = match[2]) != null ? _a : "");
2542
+ if (value.trim().length > 0) {
2543
+ options.callState.toolName = value;
2544
+ }
2545
+ const start = (_b = match.index) != null ? _b : 0;
2546
+ const consumedLength = (_d = (_c = match[0]) == null ? void 0 : _c.length) != null ? _d : 0;
2547
+ const nextWork = options.work.slice(0, start) + options.work.slice(start + consumedLength);
2548
+ options.maybeEmitToolInputStart();
2549
+ return nextWork;
2550
+ }
2551
+ function consumeSingleParamTag(options) {
2259
2552
  var _a;
2260
- let args = {};
2261
- if (typeof input === "string") {
2262
- try {
2263
- args = JSON.parse(input);
2264
- } catch (e) {
2265
- return;
2553
+ const parsed = options.parseParamTagAt(
2554
+ options.work,
2555
+ options.lower,
2556
+ options.lt,
2557
+ {
2558
+ allowEndOfString: options.allowEndOfString,
2559
+ callEndTagNameLower: options.callState.endTagName
2266
2560
  }
2267
- } else if (input && typeof input === "object") {
2268
- args = input;
2269
- } else {
2270
- return;
2561
+ );
2562
+ if (!parsed) {
2563
+ return {
2564
+ nextIndex: options.lt + 1,
2565
+ nextLastKept: options.lastKept,
2566
+ shouldStop: false
2567
+ };
2271
2568
  }
2272
- const schema = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
2273
- const coerced = coerceBySchema(args, schema);
2274
- return JSON.stringify(coerced != null ? coerced : {});
2275
- }
2276
- function coerceToolCallPart(part, tools) {
2277
- const coercedInput = coerceToolCallInput(part.toolName, part.input, tools);
2278
- if (coercedInput === void 0) {
2279
- return part;
2569
+ if (parsed.kind === "partial") {
2570
+ if (parsed.name !== void 0) {
2571
+ options.callState.partialParam = {
2572
+ name: parsed.name,
2573
+ value: (_a = parsed.value) != null ? _a : ""
2574
+ };
2575
+ }
2576
+ return {
2577
+ nextIndex: options.lt + 1,
2578
+ nextLastKept: options.lastKept,
2579
+ shouldStop: true
2580
+ };
2280
2581
  }
2582
+ options.callState.partialParam = null;
2583
+ options.mergeParamValue(options.callState.args, parsed.name, parsed.value);
2281
2584
  return {
2282
- ...part,
2283
- input: coercedInput
2585
+ keepSlice: options.work.slice(options.lastKept, parsed.start),
2586
+ nextIndex: parsed.end,
2587
+ nextLastKept: parsed.end,
2588
+ shouldStop: false
2284
2589
  };
2285
2590
  }
2591
+ function consumeParamTags(options) {
2592
+ const lower = options.work.toLowerCase();
2593
+ let index = 0;
2594
+ let lastKept = 0;
2595
+ let pieces = null;
2596
+ while (true) {
2597
+ const lt = lower.indexOf("<", index);
2598
+ if (lt === -1) {
2599
+ break;
2600
+ }
2601
+ const step = consumeSingleParamTag({
2602
+ allowEndOfString: options.allowEndOfString,
2603
+ callState: options.callState,
2604
+ lower,
2605
+ lt,
2606
+ work: options.work,
2607
+ lastKept,
2608
+ parseParamTagAt: options.parseParamTagAt,
2609
+ mergeParamValue: options.mergeParamValue
2610
+ });
2611
+ if (step.keepSlice !== void 0) {
2612
+ pieces != null ? pieces : pieces = [];
2613
+ pieces.push(step.keepSlice);
2614
+ }
2615
+ index = step.nextIndex;
2616
+ lastKept = step.nextLastKept;
2617
+ if (step.shouldStop) {
2618
+ break;
2619
+ }
2620
+ }
2621
+ options.maybeEmitToolInputStart();
2622
+ if (!pieces) {
2623
+ return options.work;
2624
+ }
2625
+ pieces.push(options.work.slice(lastKept));
2626
+ return pieces.join("");
2627
+ }
2628
+ function parseCallContent(options) {
2629
+ let work = options.content;
2630
+ work = consumeToolNameTag({
2631
+ callState: options.callState,
2632
+ work,
2633
+ nameTagRe: options.nameTagRe,
2634
+ normalizeXmlTextValue: options.normalizeXmlTextValue,
2635
+ maybeEmitToolInputStart: options.maybeEmitToolInputStart
2636
+ });
2637
+ work = consumeParamTags({
2638
+ callState: options.callState,
2639
+ work,
2640
+ allowEndOfString: options.allowEndOfString,
2641
+ parseParamTagAt: options.parseParamTagAt,
2642
+ mergeParamValue: options.mergeParamValue,
2643
+ maybeEmitToolInputStart: options.maybeEmitToolInputStart
2644
+ });
2645
+ options.maybeEmitToolInputStart();
2646
+ options.maybeEmitToolInputProgress();
2647
+ return work;
2648
+ }
2286
2649
 
2287
2650
  // src/core/protocols/qwen3coder-protocol.ts
2288
- function shouldEmitRawToolCallTextOnError3(options) {
2289
- return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
2290
- }
2291
2651
  var TOOL_CALL_OPEN_RE = /<tool_call\b[^>]*>/i;
2292
2652
  var TOOL_CALL_CLOSE_RE = /<\/tool_call\s*>/i;
2293
2653
  var TOOL_CALL_CLOSE_TRAILING_RE = /<\/tool_call\s*>\s*$/i;
@@ -2578,10 +2938,13 @@ function parseQwen3CoderToolParserUnclosedParamValue(options) {
2578
2938
  );
2579
2939
  if (boundaryIndex == null) {
2580
2940
  if (!options.allowEndOfString) {
2941
+ const rawProgressValue = options.text.slice(valueStart);
2581
2942
  return {
2582
2943
  kind: "partial",
2583
2944
  start: options.startIndex,
2584
- openEnd: options.openEnd
2945
+ openEnd: options.openEnd,
2946
+ name: options.paramName,
2947
+ value: rawProgressValue ? normalizeXmlTextValue(rawProgressValue) : ""
2585
2948
  };
2586
2949
  }
2587
2950
  const rawValue2 = options.text.slice(valueStart);
@@ -2774,6 +3137,28 @@ function mergeParamValue(args, key, value) {
2774
3137
  }
2775
3138
  args[key] = [existing, value];
2776
3139
  }
3140
+ function mergeArgsWithPartialParam(args, partialParam) {
3141
+ if (!partialParam) {
3142
+ return args;
3143
+ }
3144
+ const existing = args[partialParam.name];
3145
+ if (existing === void 0) {
3146
+ return {
3147
+ ...args,
3148
+ [partialParam.name]: partialParam.value
3149
+ };
3150
+ }
3151
+ if (Array.isArray(existing)) {
3152
+ return {
3153
+ ...args,
3154
+ [partialParam.name]: [...existing, partialParam.value]
3155
+ };
3156
+ }
3157
+ return {
3158
+ ...args,
3159
+ [partialParam.name]: [existing, partialParam.value]
3160
+ };
3161
+ }
2777
3162
  function extractParameters(xml, options) {
2778
3163
  var _a;
2779
3164
  const args = {};
@@ -3042,14 +3427,6 @@ function parseToolCallInput(input) {
3042
3427
  return input;
3043
3428
  }
3044
3429
  }
3045
- function stringifyToolInputWithSchema(options) {
3046
- const coerced = coerceToolCallInput(
3047
- options.toolName,
3048
- options.args,
3049
- options.tools
3050
- );
3051
- return coerced != null ? coerced : JSON.stringify(options.args);
3052
- }
3053
3430
  function toQwen3CoderToolParserParamText(value) {
3054
3431
  if (typeof value === "string") {
3055
3432
  return value;
@@ -3092,7 +3469,7 @@ function appendQwen3CoderToolParserArgs(lines, args) {
3092
3469
  }
3093
3470
  var qwen3CoderProtocol = () => ({
3094
3471
  formatTools({ tools, toolSystemPromptTemplate }) {
3095
- return toolSystemPromptTemplate(tools || []);
3472
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
3096
3473
  },
3097
3474
  formatToolCall(toolCall) {
3098
3475
  const args = parseToolCallInput(toolCall.input);
@@ -3353,7 +3730,6 @@ var qwen3CoderProtocol = () => ({
3353
3730
  hasEmittedTextStart = value;
3354
3731
  }
3355
3732
  );
3356
- const removeSlice = (text, start, end) => text.slice(0, start) + text.slice(end);
3357
3733
  const maybeEmitToolInputStart = (controller, callState) => {
3358
3734
  if (callState.hasEmittedStart) {
3359
3735
  return;
@@ -3378,27 +3754,40 @@ var qwen3CoderProtocol = () => ({
3378
3754
  if (!toolName) {
3379
3755
  return;
3380
3756
  }
3757
+ const argsForProgress = mergeArgsWithPartialParam(
3758
+ callState.args,
3759
+ callState.partialParam
3760
+ );
3381
3761
  const fullInput = stringifyToolInputWithSchema({
3382
3762
  tools,
3383
3763
  toolName,
3384
- args: callState.args
3764
+ args: argsForProgress
3385
3765
  });
3386
3766
  if (fullInput === "{}") {
3387
3767
  return;
3388
3768
  }
3389
- const prefixCandidate = toIncompleteJsonPrefix(fullInput);
3390
- emitPrefixDelta({
3769
+ emitToolInputProgressDelta({
3391
3770
  controller,
3392
3771
  id: callState.toolCallId,
3393
3772
  state: callState,
3394
- candidate: prefixCandidate
3773
+ fullInput
3395
3774
  });
3396
3775
  };
3397
3776
  const finalizeCall = (controller, callState, fallbackToolName, rawToolCallText = null) => {
3398
3777
  var _a, _b;
3399
3778
  const resolvedToolName = (_a = callState.toolName) != null ? _a : fallbackToolName;
3400
3779
  if (!resolvedToolName || resolvedToolName.trim().length === 0) {
3401
- const shouldEmitRaw = shouldEmitRawToolCallTextOnError3(options);
3780
+ const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
3781
+ emitFailedToolInputLifecycle({
3782
+ controller,
3783
+ id: callState.toolCallId,
3784
+ endInput: callState.hasEmittedStart,
3785
+ emitRawToolCallTextOnError: shouldEmitRaw,
3786
+ rawToolCallText,
3787
+ emitRawText: (rawText) => {
3788
+ flushText(controller, rawText);
3789
+ }
3790
+ });
3402
3791
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
3403
3792
  options,
3404
3793
  shouldEmitRaw && rawToolCallText ? "Could not resolve Qwen3CoderToolParser tool name for tool call; emitting original text." : "Could not resolve Qwen3CoderToolParser tool name for tool call",
@@ -3406,109 +3795,42 @@ var qwen3CoderProtocol = () => ({
3406
3795
  toolCallId: callState.toolCallId,
3407
3796
  toolCall: rawToolCallText
3408
3797
  }
3409
- );
3410
- if (callState.hasEmittedStart) {
3411
- controller.enqueue({
3412
- type: "tool-input-end",
3413
- id: callState.toolCallId
3414
- });
3415
- }
3416
- if (shouldEmitRaw && rawToolCallText) {
3417
- flushText(controller, rawToolCallText);
3418
- }
3419
- return false;
3420
- }
3421
- callState.toolName = resolvedToolName;
3422
- maybeEmitToolInputStart(controller, callState);
3423
- maybeEmitToolInputProgress(controller, callState);
3424
- const finalInput = stringifyToolInputWithSchema({
3425
- tools,
3426
- toolName: resolvedToolName,
3427
- args: callState.args
3428
- });
3429
- emitFinalRemainder({
3430
- controller,
3431
- id: callState.toolCallId,
3432
- state: callState,
3433
- finalFullJson: finalInput,
3434
- onMismatch: options == null ? void 0 : options.onError
3435
- });
3436
- controller.enqueue({
3437
- type: "tool-input-end",
3438
- id: callState.toolCallId
3439
- });
3440
- controller.enqueue({
3441
- type: "tool-call",
3442
- toolCallId: callState.toolCallId,
3443
- toolName: resolvedToolName,
3444
- input: finalInput
3445
- });
3446
- return true;
3447
- };
3448
- const consumeToolNameTag = (controller, callState, work) => {
3449
- var _a, _b, _c, _d;
3450
- if (callState.toolName) {
3451
- return work;
3452
- }
3453
- const match = QWEN3CODER_TOOL_PARSER_STREAM_NAME_TAG_RE.exec(work);
3454
- if (!match) {
3455
- return work;
3456
- }
3457
- const value = normalizeXmlTextValue((_a = match[2]) != null ? _a : "");
3458
- if (value.trim().length > 0) {
3459
- callState.toolName = value;
3460
- }
3461
- const start = (_b = match.index) != null ? _b : 0;
3462
- const nextWork = removeSlice(
3463
- work,
3464
- start,
3465
- start + ((_d = (_c = match[0]) == null ? void 0 : _c.length) != null ? _d : 0)
3466
- );
3467
- maybeEmitToolInputStart(controller, callState);
3468
- return nextWork;
3469
- };
3470
- const consumeParamTags = (controller, callState, work, allowEndOfString) => {
3471
- const lower = work.toLowerCase();
3472
- let index = 0;
3473
- let lastKept = 0;
3474
- let pieces = null;
3475
- while (true) {
3476
- const lt = lower.indexOf("<", index);
3477
- if (lt === -1) {
3478
- break;
3479
- }
3480
- const parsed = parseQwen3CoderToolParserParamTagAt(work, lower, lt, {
3481
- allowEndOfString,
3482
- callEndTagNameLower: callState.endTagName
3483
- });
3484
- if (!parsed) {
3485
- index = lt + 1;
3486
- continue;
3487
- }
3488
- if (parsed.kind === "partial") {
3489
- break;
3490
- }
3491
- mergeParamValue(callState.args, parsed.name, parsed.value);
3492
- pieces != null ? pieces : pieces = [];
3493
- pieces.push(work.slice(lastKept, parsed.start));
3494
- lastKept = parsed.end;
3495
- index = parsed.end;
3496
- }
3497
- maybeEmitToolInputStart(controller, callState);
3498
- if (!pieces) {
3499
- return work;
3798
+ );
3799
+ return false;
3500
3800
  }
3501
- pieces.push(work.slice(lastKept));
3502
- return pieces.join("");
3503
- };
3504
- const parseCallContent = (controller, callState, content, allowEndOfString) => {
3505
- let work = content;
3506
- work = consumeToolNameTag(controller, callState, work);
3507
- work = consumeParamTags(controller, callState, work, allowEndOfString);
3801
+ callState.toolName = resolvedToolName;
3508
3802
  maybeEmitToolInputStart(controller, callState);
3509
3803
  maybeEmitToolInputProgress(controller, callState);
3510
- return work;
3804
+ const finalInput = stringifyToolInputWithSchema({
3805
+ tools,
3806
+ toolName: resolvedToolName,
3807
+ args: callState.args
3808
+ });
3809
+ emitFinalizedToolInputLifecycle({
3810
+ controller,
3811
+ id: callState.toolCallId,
3812
+ state: callState,
3813
+ toolName: resolvedToolName,
3814
+ finalInput,
3815
+ onMismatch: options == null ? void 0 : options.onError
3816
+ });
3817
+ return true;
3511
3818
  };
3819
+ const parseStreamingCallContent = (controller, callState, content, allowEndOfString) => parseCallContent({
3820
+ callState,
3821
+ content,
3822
+ allowEndOfString,
3823
+ nameTagRe: QWEN3CODER_TOOL_PARSER_STREAM_NAME_TAG_RE,
3824
+ normalizeXmlTextValue,
3825
+ parseParamTagAt: parseQwen3CoderToolParserParamTagAt,
3826
+ mergeParamValue,
3827
+ maybeEmitToolInputStart: () => {
3828
+ maybeEmitToolInputStart(controller, callState);
3829
+ },
3830
+ maybeEmitToolInputProgress: () => {
3831
+ maybeEmitToolInputProgress(controller, callState);
3832
+ }
3833
+ });
3512
3834
  const closeTagCache = /* @__PURE__ */ new Map();
3513
3835
  const getCloseTagPattern = (endTagName) => {
3514
3836
  const cached = closeTagCache.get(endTagName);
@@ -3547,7 +3869,7 @@ var qwen3CoderProtocol = () => ({
3547
3869
  const consumeCallAtNextBoundary = (controller, callState, fallbackToolName, nextCallStart) => {
3548
3870
  const beforeNextCall = callState.buffer.slice(0, nextCallStart);
3549
3871
  const afterNextCall = callState.buffer.slice(nextCallStart);
3550
- callState.buffer = parseCallContent(
3872
+ callState.buffer = parseStreamingCallContent(
3551
3873
  controller,
3552
3874
  callState,
3553
3875
  beforeNextCall,
@@ -3580,7 +3902,7 @@ var qwen3CoderProtocol = () => ({
3580
3902
  );
3581
3903
  }
3582
3904
  if (!closeMatch) {
3583
- callState.buffer = parseCallContent(
3905
+ callState.buffer = parseStreamingCallContent(
3584
3906
  controller,
3585
3907
  callState,
3586
3908
  callState.buffer,
@@ -3591,7 +3913,7 @@ var qwen3CoderProtocol = () => ({
3591
3913
  const closeEnd = closeStart + ((_c = (_b = closeMatch[0]) == null ? void 0 : _b.length) != null ? _c : 0);
3592
3914
  const beforeClose = callState.buffer.slice(0, closeStart);
3593
3915
  const afterClose = callState.buffer.slice(closeEnd);
3594
- parseCallContent(controller, callState, beforeClose, true);
3916
+ parseStreamingCallContent(controller, callState, beforeClose, true);
3595
3917
  callState.buffer = "";
3596
3918
  finalizeStreamingCall(
3597
3919
  controller,
@@ -3602,7 +3924,7 @@ var qwen3CoderProtocol = () => ({
3602
3924
  return { done: true, remainder: afterClose };
3603
3925
  };
3604
3926
  const finalizeCallAtFinish = (controller, callState, fallbackToolName) => {
3605
- callState.buffer = parseCallContent(
3927
+ callState.buffer = parseStreamingCallContent(
3606
3928
  controller,
3607
3929
  callState,
3608
3930
  callState.buffer,
@@ -3708,6 +4030,7 @@ var qwen3CoderProtocol = () => ({
3708
4030
  toolCallId: generateToolCallId(),
3709
4031
  toolName: inlineToolName,
3710
4032
  hasEmittedStart: false,
4033
+ partialParam: null,
3711
4034
  emittedInput: "",
3712
4035
  raw: openTag,
3713
4036
  args: {},
@@ -3791,6 +4114,7 @@ var qwen3CoderProtocol = () => ({
3791
4114
  toolCallId: generateToolCallId(),
3792
4115
  toolName: toolCall.outerNameAttr,
3793
4116
  hasEmittedStart: false,
4117
+ partialParam: null,
3794
4118
  emittedInput: "",
3795
4119
  raw: toolCall.outerOpenTag,
3796
4120
  args: {},
@@ -3887,6 +4211,7 @@ var qwen3CoderProtocol = () => ({
3887
4211
  toolCallId: generateToolCallId(),
3888
4212
  toolName: toolNameAttr2,
3889
4213
  hasEmittedStart: false,
4214
+ partialParam: null,
3890
4215
  emittedInput: "",
3891
4216
  raw: openTag,
3892
4217
  args: {},
@@ -3910,6 +4235,7 @@ var qwen3CoderProtocol = () => ({
3910
4235
  toolCallId: generateToolCallId(),
3911
4236
  toolName: toolNameAttr,
3912
4237
  hasEmittedStart: false,
4238
+ partialParam: null,
3913
4239
  emittedInput: "",
3914
4240
  raw: openTag,
3915
4241
  args: {},
@@ -3925,7 +4251,7 @@ var qwen3CoderProtocol = () => ({
3925
4251
  };
3926
4252
  const reportUnfinishedToolCallAtFinish = (controller, rawToolCall) => {
3927
4253
  var _a;
3928
- const shouldEmitRaw = shouldEmitRawToolCallTextOnError3(options);
4254
+ const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
3929
4255
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3930
4256
  options,
3931
4257
  shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser XML tool call at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser XML tool call at finish.",
@@ -3937,7 +4263,7 @@ var qwen3CoderProtocol = () => ({
3937
4263
  };
3938
4264
  const reportUnfinishedImplicitCallAtFinish = (controller, rawCallText) => {
3939
4265
  var _a;
3940
- const shouldEmitRaw = shouldEmitRawToolCallTextOnError3(options);
4266
+ const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
3941
4267
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3942
4268
  options,
3943
4269
  shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser call block at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser call block at finish.",
@@ -3968,6 +4294,7 @@ var qwen3CoderProtocol = () => ({
3968
4294
  toolCallId: generateToolCallId(),
3969
4295
  toolName: toolCall.outerNameAttr,
3970
4296
  hasEmittedStart: false,
4297
+ partialParam: null,
3971
4298
  emittedInput: "",
3972
4299
  raw: toolCall.outerOpenTag,
3973
4300
  args: {},
@@ -3986,7 +4313,7 @@ var qwen3CoderProtocol = () => ({
3986
4313
  if (result.ok) {
3987
4314
  toolCall.emittedToolCallCount += 1;
3988
4315
  }
3989
- const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError3(options);
4316
+ const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError(options);
3990
4317
  if (shouldFlushTrailingText && result.trailingText.length > 0) {
3991
4318
  flushText(controller, result.trailingText);
3992
4319
  }
@@ -4003,7 +4330,7 @@ var qwen3CoderProtocol = () => ({
4003
4330
  if (result.ok) {
4004
4331
  toolCall.emittedToolCallCount += 1;
4005
4332
  }
4006
- const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError3(options);
4333
+ const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError(options);
4007
4334
  if (shouldFlushTrailingText && result.trailingText.length > 0) {
4008
4335
  flushText(controller, result.trailingText);
4009
4336
  }
@@ -4026,7 +4353,7 @@ var qwen3CoderProtocol = () => ({
4026
4353
  implicitCall = null;
4027
4354
  implicitCallOpenTag = null;
4028
4355
  const result = finalizeCallAtFinish(controller, callState, null);
4029
- const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError3(options);
4356
+ const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError(options);
4030
4357
  if (shouldFlushTrailingText && result.trailingText.length > 0) {
4031
4358
  flushText(controller, result.trailingText);
4032
4359
  }
@@ -4118,18 +4445,6 @@ var Qwen3CoderToolParser = qwen3CoderProtocol;
4118
4445
 
4119
4446
  // src/core/protocols/yaml-xml-protocol.ts
4120
4447
  import YAML from "yaml";
4121
- function shouldEmitRawToolCallTextOnError4(options) {
4122
- return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
4123
- }
4124
- var selfClosingTagCache2 = /* @__PURE__ */ new Map();
4125
- function getSelfClosingTagPattern2(toolName) {
4126
- let pattern = selfClosingTagCache2.get(toolName);
4127
- if (!pattern) {
4128
- pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
4129
- selfClosingTagCache2.set(toolName, pattern);
4130
- }
4131
- return pattern;
4132
- }
4133
4448
  var LEADING_WHITESPACE_RE = /^(\s*)/;
4134
4449
  var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
4135
4450
  var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
@@ -4377,34 +4692,19 @@ function findClosingTagEnd2(text, contentStart, toolName) {
4377
4692
  }
4378
4693
  return -1;
4379
4694
  }
4380
- function findEarliestTagPosition(openIdx, selfIdx) {
4381
- const hasSelf = selfIdx !== -1;
4382
- const hasOpen = openIdx !== -1;
4383
- if (hasSelf && (!hasOpen || selfIdx < openIdx)) {
4384
- return { tagStart: selfIdx, isSelfClosing: true };
4385
- }
4386
- return { tagStart: openIdx, isSelfClosing: false };
4387
- }
4388
4695
  function collectToolCallsForName(text, toolName) {
4389
4696
  const toolCalls = [];
4390
4697
  let searchIndex = 0;
4391
4698
  const startTag = `<${toolName}>`;
4392
- const selfTagRegex = getSelfClosingTagPattern2(toolName);
4393
4699
  while (searchIndex < text.length) {
4394
- const openIdx = text.indexOf(startTag, searchIndex);
4395
- selfTagRegex.lastIndex = searchIndex;
4396
- const selfMatch = selfTagRegex.exec(text);
4397
- const selfIdx = selfMatch ? selfMatch.index : -1;
4398
- const selfTagLength = selfMatch ? selfMatch[0].length : 0;
4399
- if (openIdx === -1 && selfIdx === -1) {
4700
+ const match = findNextToolTag(text, searchIndex, toolName);
4701
+ if (match === null) {
4400
4702
  break;
4401
4703
  }
4402
- const { tagStart, isSelfClosing } = findEarliestTagPosition(
4403
- openIdx,
4404
- selfIdx
4405
- );
4704
+ const tagStart = match.tagStart;
4705
+ const isSelfClosing = match.isSelfClosing;
4406
4706
  if (isSelfClosing) {
4407
- const endIndex = tagStart + selfTagLength;
4707
+ const endIndex = tagStart + match.tagLength;
4408
4708
  toolCalls.push({
4409
4709
  toolName,
4410
4710
  startIndex: tagStart,
@@ -4510,38 +4810,6 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
4510
4810
  }
4511
4811
  return tc.endIndex;
4512
4812
  }
4513
- function findEarliestToolTag2(buffer, toolNames) {
4514
- let bestIndex = -1;
4515
- let bestName = "";
4516
- let bestSelfClosing = false;
4517
- let bestTagLength = 0;
4518
- for (const name of toolNames) {
4519
- const openTag = `<${name}>`;
4520
- const selfTagRegex = getSelfClosingTagPattern2(name);
4521
- const idxOpen = buffer.indexOf(openTag);
4522
- selfTagRegex.lastIndex = 0;
4523
- const selfMatch = selfTagRegex.exec(buffer);
4524
- const idxSelf = selfMatch ? selfMatch.index : -1;
4525
- if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
4526
- bestIndex = idxOpen;
4527
- bestName = name;
4528
- bestSelfClosing = false;
4529
- bestTagLength = openTag.length;
4530
- }
4531
- if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
4532
- bestIndex = idxSelf;
4533
- bestName = name;
4534
- bestSelfClosing = true;
4535
- bestTagLength = selfMatch ? selfMatch[0].length : 0;
4536
- }
4537
- }
4538
- return {
4539
- index: bestIndex,
4540
- name: bestName,
4541
- selfClosing: bestSelfClosing,
4542
- tagLength: bestTagLength
4543
- };
4544
- }
4545
4813
  function stripTrailingPartialCloseTag(content, toolName) {
4546
4814
  const closeTag = `</${toolName}>`;
4547
4815
  const lastLineBreakIndex = Math.max(
@@ -4568,7 +4836,7 @@ function stripTrailingPartialCloseTag(content, toolName) {
4568
4836
  var yamlXmlProtocol = (_protocolOptions) => {
4569
4837
  return {
4570
4838
  formatTools({ tools, toolSystemPromptTemplate }) {
4571
- return toolSystemPromptTemplate(tools || []);
4839
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
4572
4840
  },
4573
4841
  formatToolCall(toolCall) {
4574
4842
  let args = {};
@@ -4584,7 +4852,7 @@ var yamlXmlProtocol = (_protocolOptions) => {
4584
4852
  ${yamlContent}</${toolCall.toolName}>`;
4585
4853
  },
4586
4854
  parseGeneratedText({ text, tools, options }) {
4587
- const toolNames = tools.map((t) => t.name).filter(Boolean);
4855
+ const toolNames = extractToolNames(tools);
4588
4856
  if (toolNames.length === 0) {
4589
4857
  return [{ type: "text", text }];
4590
4858
  }
@@ -4620,7 +4888,7 @@ ${yamlContent}</${toolCall.toolName}>`;
4620
4888
  return processedElements;
4621
4889
  },
4622
4890
  createStreamParser({ tools, options }) {
4623
- const toolNames = tools.map((t) => t.name).filter(Boolean);
4891
+ const toolNames = extractToolNames(tools);
4624
4892
  let buffer = "";
4625
4893
  let currentToolCall = null;
4626
4894
  let currentTextId = null;
@@ -4643,16 +4911,19 @@ ${yamlContent}</${toolCall.toolName}>`;
4643
4911
  if (parsedArgs === null) {
4644
4912
  return;
4645
4913
  }
4646
- const fullInput = JSON.stringify(parsedArgs);
4914
+ const fullInput = stringifyToolInputWithSchema({
4915
+ toolName: currentToolCall.name,
4916
+ args: parsedArgs,
4917
+ tools
4918
+ });
4647
4919
  if (fullInput === "{}" && toolContent.trim().length === 0) {
4648
4920
  return;
4649
4921
  }
4650
- const prefixCandidate = toIncompleteJsonPrefix(fullInput);
4651
- emitPrefixDelta({
4922
+ emitToolInputProgressDelta({
4652
4923
  controller,
4653
4924
  id: currentToolCall.toolCallId,
4654
4925
  state: currentToolCall,
4655
- candidate: prefixCandidate
4926
+ fullInput
4656
4927
  });
4657
4928
  };
4658
4929
  const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
@@ -4660,38 +4931,43 @@ ${yamlContent}</${toolCall.toolName}>`;
4660
4931
  const parsedArgs = parseYamlContent(toolContent, options);
4661
4932
  flushText(controller);
4662
4933
  if (parsedArgs !== null) {
4663
- const finalInput = JSON.stringify(parsedArgs);
4934
+ const finalInput = stringifyToolInputWithSchema({
4935
+ toolName,
4936
+ args: parsedArgs,
4937
+ tools
4938
+ });
4664
4939
  if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
4665
- emitFinalRemainder({
4940
+ emitFinalizedToolInputLifecycle({
4666
4941
  controller,
4667
4942
  id: toolCallId,
4668
4943
  state: currentToolCall,
4669
- finalFullJson: finalInput,
4944
+ toolName,
4945
+ finalInput,
4670
4946
  onMismatch: options == null ? void 0 : options.onError
4671
4947
  });
4948
+ } else {
4949
+ enqueueToolInputEndAndCall({
4950
+ controller,
4951
+ id: toolCallId,
4952
+ toolName,
4953
+ input: finalInput
4954
+ });
4672
4955
  }
4673
- controller.enqueue({
4674
- type: "tool-input-end",
4675
- id: toolCallId
4676
- });
4677
- controller.enqueue({
4678
- type: "tool-call",
4679
- toolCallId,
4680
- toolName,
4681
- input: finalInput
4682
- });
4683
4956
  } else {
4684
- controller.enqueue({
4685
- type: "tool-input-end",
4686
- id: toolCallId
4687
- });
4688
4957
  const original = `<${toolName}>${toolContent}</${toolName}>`;
4958
+ const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
4959
+ emitFailedToolInputLifecycle({
4960
+ controller,
4961
+ id: toolCallId,
4962
+ emitRawToolCallTextOnError: emitRawFallback,
4963
+ rawToolCallText: original,
4964
+ emitRawText: (rawText) => {
4965
+ flushText(controller, rawText);
4966
+ }
4967
+ });
4689
4968
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
4690
4969
  toolCall: original
4691
4970
  });
4692
- if (shouldEmitRawToolCallTextOnError4(options)) {
4693
- flushText(controller, original);
4694
- }
4695
4971
  }
4696
4972
  };
4697
4973
  const finalizeUnclosedToolCall = (controller) => {
@@ -4705,38 +4981,36 @@ ${yamlContent}</${toolCall.toolName}>`;
4705
4981
  const parsedArgs = parseYamlContent(reconciledBuffer, options);
4706
4982
  flushText(controller);
4707
4983
  if (parsedArgs !== null) {
4708
- const finalInput = JSON.stringify(parsedArgs);
4709
- emitFinalRemainder({
4984
+ const finalInput = stringifyToolInputWithSchema({
4985
+ toolName,
4986
+ args: parsedArgs,
4987
+ tools
4988
+ });
4989
+ emitFinalizedToolInputLifecycle({
4710
4990
  controller,
4711
4991
  id: toolCallId,
4712
4992
  state: currentToolCall,
4713
- finalFullJson: finalInput,
4714
- onMismatch: options == null ? void 0 : options.onError
4715
- });
4716
- controller.enqueue({
4717
- type: "tool-input-end",
4718
- id: toolCallId
4719
- });
4720
- controller.enqueue({
4721
- type: "tool-call",
4722
- toolCallId,
4723
4993
  toolName,
4724
- input: finalInput
4994
+ finalInput,
4995
+ onMismatch: options == null ? void 0 : options.onError
4725
4996
  });
4726
4997
  } else {
4727
- controller.enqueue({
4728
- type: "tool-input-end",
4729
- id: toolCallId
4730
- });
4731
4998
  const unfinishedContent = `<${toolName}>${buffer}`;
4999
+ const emitRawFallback = shouldEmitRawToolCallTextOnError(options);
5000
+ emitFailedToolInputLifecycle({
5001
+ controller,
5002
+ id: toolCallId,
5003
+ emitRawToolCallTextOnError: emitRawFallback,
5004
+ rawToolCallText: unfinishedContent,
5005
+ emitRawText: (rawText) => {
5006
+ flushText(controller, rawText);
5007
+ }
5008
+ });
4732
5009
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4733
5010
  options,
4734
5011
  "Could not complete streaming YAML tool call at finish.",
4735
5012
  { toolCall: unfinishedContent }
4736
5013
  );
4737
- if (shouldEmitRawToolCallTextOnError4(options)) {
4738
- flushText(controller, unfinishedContent);
4739
- }
4740
5014
  }
4741
5015
  buffer = "";
4742
5016
  currentToolCall = null;
@@ -4813,7 +5087,7 @@ ${yamlContent}</${toolCall.toolName}>`;
4813
5087
  break;
4814
5088
  }
4815
5089
  } else {
4816
- const { index, name, selfClosing, tagLength } = findEarliestToolTag2(
5090
+ const { index, name, selfClosing, tagLength } = findEarliestToolTag(
4817
5091
  buffer,
4818
5092
  toolNames
4819
5093
  );
@@ -5010,9 +5284,38 @@ function decodeOriginalTools(originalTools, options) {
5010
5284
  }
5011
5285
  return decodedTools;
5012
5286
  }
5287
+ function decodeOriginalToolsFromProviderOptions(providerOptions, options) {
5288
+ var _a;
5289
+ return decodeOriginalTools(
5290
+ (_a = providerOptions == null ? void 0 : providerOptions.toolCallMiddleware) == null ? void 0 : _a.originalTools,
5291
+ options
5292
+ );
5293
+ }
5013
5294
  function extractToolNamesFromOriginalTools(originalTools) {
5014
5295
  return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
5015
5296
  }
5297
+ function isRecord(value) {
5298
+ return typeof value === "object" && value !== null;
5299
+ }
5300
+ function getToolCallMiddlewareOptions(providerOptions) {
5301
+ if (!isRecord(providerOptions)) {
5302
+ return {};
5303
+ }
5304
+ const toolCallMiddleware = providerOptions.toolCallMiddleware;
5305
+ if (!isRecord(toolCallMiddleware)) {
5306
+ return {};
5307
+ }
5308
+ return toolCallMiddleware;
5309
+ }
5310
+ function mergeToolCallMiddlewareOptions(providerOptions, overrides) {
5311
+ return {
5312
+ ...isRecord(providerOptions) ? providerOptions : {},
5313
+ toolCallMiddleware: {
5314
+ ...getToolCallMiddlewareOptions(providerOptions),
5315
+ ...overrides
5316
+ }
5317
+ };
5318
+ }
5016
5319
  function isToolChoiceActive(params) {
5017
5320
  var _a, _b, _c;
5018
5321
  const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
@@ -5032,7 +5335,7 @@ function hasInputProperty(obj) {
5032
5335
  }
5033
5336
 
5034
5337
  // src/core/utils/generated-text-json-recovery.ts
5035
- function isRecord(value) {
5338
+ function isRecord2(value) {
5036
5339
  return typeof value === "object" && value !== null && !Array.isArray(value);
5037
5340
  }
5038
5341
  function safeStringify2(value) {
@@ -5188,7 +5491,7 @@ function toRecoveredParts(text, candidate, toolCallPart) {
5188
5491
  return out;
5189
5492
  }
5190
5493
  function parseAsToolPayload(payload, tools) {
5191
- if (!isRecord(payload)) {
5494
+ if (!isRecord2(payload)) {
5192
5495
  return null;
5193
5496
  }
5194
5497
  const toolName = typeof payload.name === "string" && payload.name.trim().length > 0 ? payload.name.trim() : null;
@@ -5199,7 +5502,7 @@ function parseAsToolPayload(payload, tools) {
5199
5502
  return null;
5200
5503
  }
5201
5504
  const rawArgs = Object.hasOwn(payload, "arguments") ? payload.arguments : {};
5202
- if (!isRecord(rawArgs)) {
5505
+ if (!isRecord2(rawArgs)) {
5203
5506
  return null;
5204
5507
  }
5205
5508
  return {
@@ -5209,14 +5512,14 @@ function parseAsToolPayload(payload, tools) {
5209
5512
  }
5210
5513
  function isLikelyArgumentsShapeForTool(args, tool) {
5211
5514
  const unwrapped = unwrapJsonSchema(tool.inputSchema);
5212
- if (!isRecord(unwrapped)) {
5515
+ if (!isRecord2(unwrapped)) {
5213
5516
  return false;
5214
5517
  }
5215
5518
  if (getSchemaType(unwrapped) !== "object") {
5216
5519
  return false;
5217
5520
  }
5218
5521
  const properties = unwrapped.properties;
5219
- if (!isRecord(properties)) {
5522
+ if (!isRecord2(properties)) {
5220
5523
  return false;
5221
5524
  }
5222
5525
  const keys = Object.keys(args);
@@ -5236,11 +5539,11 @@ function parseAsArgumentsOnly(payload, tools) {
5236
5539
  if (tools.length !== 1) {
5237
5540
  return null;
5238
5541
  }
5239
- if (!isRecord(payload)) {
5542
+ if (!isRecord2(payload)) {
5240
5543
  return null;
5241
5544
  }
5242
5545
  const hasNameEnvelope = Object.hasOwn(payload, "name") && typeof payload.name === "string" && payload.name.length > 0;
5243
- const hasArgumentsEnvelope = Object.hasOwn(payload, "arguments") && (typeof payload.arguments === "string" || isRecord(payload.arguments));
5546
+ const hasArgumentsEnvelope = Object.hasOwn(payload, "arguments") && (typeof payload.arguments === "string" || isRecord2(payload.arguments));
5244
5547
  if (hasNameEnvelope || hasArgumentsEnvelope) {
5245
5548
  return null;
5246
5549
  }
@@ -5329,6 +5632,30 @@ function parseToolChoicePayload({
5329
5632
  input: coercedInput != null ? coercedInput : safeStringify3(rawArgs)
5330
5633
  };
5331
5634
  }
5635
+ function resolveToolChoiceSelection({
5636
+ text,
5637
+ tools,
5638
+ onError,
5639
+ errorMessage
5640
+ }) {
5641
+ if (typeof text !== "string") {
5642
+ return {
5643
+ toolName: "unknown",
5644
+ input: "{}",
5645
+ originText: ""
5646
+ };
5647
+ }
5648
+ const parsed = parseToolChoicePayload({
5649
+ text,
5650
+ tools,
5651
+ onError,
5652
+ errorMessage
5653
+ });
5654
+ return {
5655
+ ...parsed,
5656
+ originText: text
5657
+ };
5658
+ }
5332
5659
 
5333
5660
  // src/generate-handler.ts
5334
5661
  function logDebugSummary(debugSummary, toolCall, originText) {
@@ -5348,29 +5675,23 @@ async function handleToolChoice(doGenerate, params, tools) {
5348
5675
  var _a, _b, _c, _d;
5349
5676
  const result = await doGenerate();
5350
5677
  const first = (_a = result.content) == null ? void 0 : _a[0];
5678
+ const firstText = (first == null ? void 0 : first.type) === "text" ? first.text : void 0;
5351
5679
  const onError = (_b = extractOnErrorOption(params.providerOptions)) == null ? void 0 : _b.onError;
5352
- let toolName = "unknown";
5353
- let input = "{}";
5354
- if (first && first.type === "text") {
5355
- if (getDebugLevel() === "parse") {
5356
- logRawChunk(first.text);
5357
- }
5358
- const parsed = parseToolChoicePayload({
5359
- text: first.text,
5360
- tools,
5361
- onError,
5362
- errorMessage: "Failed to parse toolChoice JSON from generated model output"
5363
- });
5364
- toolName = parsed.toolName;
5365
- input = parsed.input;
5680
+ if (typeof firstText === "string" && getDebugLevel() === "parse") {
5681
+ logRawChunk(firstText);
5366
5682
  }
5683
+ const { toolName, input, originText } = resolveToolChoiceSelection({
5684
+ text: firstText,
5685
+ tools,
5686
+ onError,
5687
+ errorMessage: "Failed to parse toolChoice JSON from generated model output"
5688
+ });
5367
5689
  const toolCall = {
5368
5690
  type: "tool-call",
5369
5691
  toolCallId: generateToolCallId(),
5370
5692
  toolName,
5371
5693
  input
5372
5694
  };
5373
- const originText = first && first.type === "text" ? first.text : "";
5374
5695
  const debugSummary = (_d = (_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) == null ? void 0 : _d.debugSummary;
5375
5696
  logDebugSummary(debugSummary, toolCall, originText);
5376
5697
  return {
@@ -5391,7 +5712,7 @@ function parseContent(content, protocol, tools, providerOptions) {
5391
5712
  tools,
5392
5713
  options: {
5393
5714
  ...extractOnErrorOption(providerOptions),
5394
- ...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
5715
+ ...getToolCallMiddlewareOptions(providerOptions)
5395
5716
  }
5396
5717
  });
5397
5718
  const hasToolCall = parsedByProtocol.some(
@@ -5449,10 +5770,9 @@ async function wrapGenerate({
5449
5770
  doGenerate,
5450
5771
  params
5451
5772
  }) {
5452
- var _a, _b;
5453
5773
  const onError = extractOnErrorOption(params.providerOptions);
5454
- const tools = originalToolsSchema.decode(
5455
- (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
5774
+ const tools = decodeOriginalToolsFromProviderOptions(
5775
+ params.providerOptions,
5456
5776
  onError
5457
5777
  );
5458
5778
  if (isToolChoiceActive(params)) {
@@ -5482,6 +5802,21 @@ async function wrapGenerate({
5482
5802
  };
5483
5803
  }
5484
5804
 
5805
+ // src/core/prompts/shared/text-part.ts
5806
+ function toTextPart(text, providerOptions) {
5807
+ if (providerOptions === void 0) {
5808
+ return {
5809
+ type: "text",
5810
+ text
5811
+ };
5812
+ }
5813
+ return {
5814
+ type: "text",
5815
+ text,
5816
+ providerOptions
5817
+ };
5818
+ }
5819
+
5485
5820
  // src/core/prompts/shared/tool-result-normalizer.ts
5486
5821
  function isMapping(value) {
5487
5822
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -5527,8 +5862,8 @@ function getContentPartMediaKind(part) {
5527
5862
  }
5528
5863
  }
5529
5864
  function shouldPassRawByStrategy(mediaKind, strategy) {
5530
- var _a, _b;
5531
- const mode = (_a = strategy == null ? void 0 : strategy.mode) != null ? _a : "placeholder";
5865
+ var _a;
5866
+ const mode = getMediaMode(strategy);
5532
5867
  if (mode === "raw") {
5533
5868
  return true;
5534
5869
  }
@@ -5538,11 +5873,14 @@ function shouldPassRawByStrategy(mediaKind, strategy) {
5538
5873
  if (mode === "model") {
5539
5874
  return false;
5540
5875
  }
5541
- return ((_b = strategy == null ? void 0 : strategy.capabilities) == null ? void 0 : _b[mediaKind]) === true;
5876
+ return ((_a = strategy == null ? void 0 : strategy.capabilities) == null ? void 0 : _a[mediaKind]) === true;
5542
5877
  }
5543
- function shouldPassRawContent(contentParts, strategy) {
5878
+ function getMediaMode(strategy) {
5544
5879
  var _a;
5545
- const mode = (_a = strategy == null ? void 0 : strategy.mode) != null ? _a : "placeholder";
5880
+ return (_a = strategy == null ? void 0 : strategy.mode) != null ? _a : "placeholder";
5881
+ }
5882
+ function shouldPassRawContent(contentParts, strategy) {
5883
+ const mode = getMediaMode(strategy);
5546
5884
  if (mode === "raw") {
5547
5885
  return true;
5548
5886
  }
@@ -5565,6 +5903,10 @@ function shouldPassRawContent(contentParts, strategy) {
5565
5903
  }
5566
5904
  return hasSupportedMediaContent;
5567
5905
  }
5906
+ function formatIdPlaceholder(label, fileId) {
5907
+ const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
5908
+ return `[${label}: ${displayId}]`;
5909
+ }
5568
5910
  function formatContentPartPlaceholder(part) {
5569
5911
  var _a;
5570
5912
  const contentPart = part;
@@ -5577,8 +5919,7 @@ function formatContentPartPlaceholder(part) {
5577
5919
  return `[Image URL: ${contentPart.url}]`;
5578
5920
  case "image-file-id": {
5579
5921
  const fileId = contentPart.fileId;
5580
- const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
5581
- return `[Image ID: ${displayId}]`;
5922
+ return formatIdPlaceholder("Image ID", fileId);
5582
5923
  }
5583
5924
  case "file-data": {
5584
5925
  const filePart = contentPart;
@@ -5591,8 +5932,7 @@ function formatContentPartPlaceholder(part) {
5591
5932
  return `[File URL: ${contentPart.url}]`;
5592
5933
  case "file-id": {
5593
5934
  const fileId = contentPart.fileId;
5594
- const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
5595
- return `[File ID: ${displayId}]`;
5935
+ return formatIdPlaceholder("File ID", fileId);
5596
5936
  }
5597
5937
  case "media":
5598
5938
  return `[Media: ${contentPart.mediaType}]`;
@@ -5714,6 +6054,7 @@ For each function call return a json object with function name and arguments wit
5714
6054
  import dedent from "dedent";
5715
6055
  function morphXmlSystemPromptTemplate(tools) {
5716
6056
  const toolsText = renderToolsForXmlPrompt(tools);
6057
+ const inputExamplesText = renderInputExamplesForXmlPrompt(tools);
5717
6058
  const header = dedent`
5718
6059
  # Tools
5719
6060
  You may call one or more functions to assist with the user query.
@@ -5728,7 +6069,7 @@ function morphXmlSystemPromptTemplate(tools) {
5728
6069
  <rules>
5729
6070
  - Use exactly one XML element whose tag name is the function name.
5730
6071
  - Put each parameter as a child element.
5731
- - Values must follow the schema exactly (numbers, arrays, objects, enums copy as-is).
6072
+ - Values must follow the schema exactly (numbers, arrays, objects, enums -> copy as-is).
5732
6073
  - Do not add or remove functions or parameters.
5733
6074
  - Each required parameter must appear once.
5734
6075
  - Output nothing before or after the function call.
@@ -5744,7 +6085,7 @@ function morphXmlSystemPromptTemplate(tools) {
5744
6085
  multiple lines</example_parameter_2>
5745
6086
  </example_function_name>
5746
6087
  `;
5747
- return [header, definitions, rules, examples].join("\n\n");
6088
+ return [header, definitions, rules, examples, inputExamplesText].filter((section) => section.trim().length > 0).join("\n\n");
5748
6089
  }
5749
6090
  var INDENT = " ";
5750
6091
  function renderToolsForXmlPrompt(tools) {
@@ -5764,6 +6105,67 @@ function renderToolForXmlPrompt(tool) {
5764
6105
  lines.push(`schema: ${stringifySchema(normalizedSchema)}`);
5765
6106
  return lines.join("\n");
5766
6107
  }
6108
+ function getToolInputExamples(tool) {
6109
+ const inputExamples = tool.inputExamples;
6110
+ if (!Array.isArray(inputExamples)) {
6111
+ return [];
6112
+ }
6113
+ return inputExamples.filter(
6114
+ (example) => typeof example === "object" && example !== null && "input" in example && example.input !== void 0
6115
+ );
6116
+ }
6117
+ function safeStringifyInputExample(input, sourceError) {
6118
+ try {
6119
+ const serialized = JSON.stringify(input);
6120
+ return serialized != null ? serialized : "null";
6121
+ } catch (stringifyError) {
6122
+ let reason = "";
6123
+ if (sourceError instanceof Error) {
6124
+ reason = sourceError.message;
6125
+ } else if (stringifyError instanceof Error) {
6126
+ reason = stringifyError.message;
6127
+ }
6128
+ return reason.length > 0 ? `[unserializable input: ${reason}]` : "[unserializable input]";
6129
+ }
6130
+ }
6131
+ function renderMorphXmlInputExample(toolName, input) {
6132
+ try {
6133
+ return stringify(toolName, input, {
6134
+ suppressEmptyNode: false,
6135
+ format: true,
6136
+ minimalEscaping: true
6137
+ });
6138
+ } catch (error) {
6139
+ const fallbackContent = safeStringifyInputExample(input, error);
6140
+ const escapedFallback = escapeXmlMinimalText(fallbackContent);
6141
+ return `<${toolName}>${escapedFallback}</${toolName}>`;
6142
+ }
6143
+ }
6144
+ function renderInputExamplesForXmlPrompt(tools) {
6145
+ const renderedTools = tools.map((tool) => {
6146
+ const inputExamples = getToolInputExamples(tool);
6147
+ if (inputExamples.length === 0) {
6148
+ return "";
6149
+ }
6150
+ const renderedExamples = inputExamples.map((example, index) => {
6151
+ const xml = renderMorphXmlInputExample(tool.name, example.input);
6152
+ return `Example ${index + 1}:
6153
+ ${xml}`;
6154
+ }).join("\n\n");
6155
+ return `Tool: ${tool.name}
6156
+ ${renderedExamples}`;
6157
+ }).filter((text) => text.length > 0).join("\n\n");
6158
+ if (renderedTools.length === 0) {
6159
+ return "";
6160
+ }
6161
+ return [
6162
+ "# Input Examples",
6163
+ "Treat these as canonical tool-call patterns.",
6164
+ "Reuse the closest structure and nesting, change only values, and do not invent parameters.",
6165
+ "Do not copy example values unless they match the user's request.",
6166
+ renderedTools
6167
+ ].join("\n\n");
6168
+ }
5767
6169
  function normalizeSchema(schema) {
5768
6170
  if (typeof schema === "string") {
5769
6171
  try {
@@ -5984,45 +6386,6 @@ function morphFormatToolResponseAsXml(toolResult) {
5984
6386
  return morphFormatToolResponseAsXmlWithOptions(toolResult);
5985
6387
  }
5986
6388
 
5987
- // src/core/prompts/shared/assistant-tool-calls-to-text.ts
5988
- function assistantToolCallsToTextContent(options) {
5989
- var _a, _b;
5990
- const newContent = [];
5991
- for (const item of options.content) {
5992
- switch (item.type) {
5993
- case "tool-call":
5994
- newContent.push({
5995
- type: "text",
5996
- text: options.protocol.formatToolCall(item)
5997
- });
5998
- break;
5999
- case "text":
6000
- case "reasoning":
6001
- newContent.push(item);
6002
- break;
6003
- default:
6004
- (_b = (_a = options.conversionOptions) == null ? void 0 : _a.onError) == null ? void 0 : _b.call(
6005
- _a,
6006
- "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
6007
- { content: item }
6008
- );
6009
- newContent.push({
6010
- type: "text",
6011
- text: JSON.stringify(item)
6012
- });
6013
- }
6014
- }
6015
- if (!newContent.every((entry) => entry.type === "text")) {
6016
- return newContent;
6017
- }
6018
- return [
6019
- {
6020
- type: "text",
6021
- text: newContent.map((entry) => entry.text).join("\n")
6022
- }
6023
- ];
6024
- }
6025
-
6026
6389
  // src/core/prompts/qwen3coder-prompt.ts
6027
6390
  var QWEN3CODER_TOOL_HEADER = "# Tools\n\nYou have access to the following functions:\n\n";
6028
6391
  var QWEN3CODER_TOOL_CALL_INSTRUCTIONS = "\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>";
@@ -6220,10 +6583,9 @@ async function wrapStream({
6220
6583
  doGenerate,
6221
6584
  params
6222
6585
  }) {
6223
- var _a, _b, _c;
6224
6586
  const onErrorOptions = extractOnErrorOption(params.providerOptions);
6225
- const tools = originalToolsSchema.decode(
6226
- (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
6587
+ const tools = decodeOriginalToolsFromProviderOptions(
6588
+ params.providerOptions,
6227
6589
  onErrorOptions
6228
6590
  );
6229
6591
  if (isToolChoiceActive(params)) {
@@ -6237,7 +6599,7 @@ async function wrapStream({
6237
6599
  const debugLevel = getDebugLevel();
6238
6600
  const options = {
6239
6601
  ...onErrorOptions,
6240
- ...((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) || {}
6602
+ ...getToolCallMiddlewareOptions(params.providerOptions)
6241
6603
  };
6242
6604
  const coreStream = stream.pipeThrough(
6243
6605
  new TransformStream(
@@ -6287,18 +6649,14 @@ async function toolChoiceStream({
6287
6649
  var _a;
6288
6650
  const normalizedTools = Array.isArray(tools) ? tools : [];
6289
6651
  const result = await doGenerate();
6290
- let toolName = "unknown";
6291
- let input = "{}";
6292
- if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
6293
- const parsed = parseToolChoicePayload({
6294
- text: result.content[0].text,
6295
- tools: normalizedTools,
6296
- onError: options == null ? void 0 : options.onError,
6297
- errorMessage: "Failed to parse toolChoice JSON from streamed model output"
6298
- });
6299
- toolName = parsed.toolName;
6300
- input = parsed.input;
6301
- }
6652
+ const first = (_a = result == null ? void 0 : result.content) == null ? void 0 : _a[0];
6653
+ const firstText = (first == null ? void 0 : first.type) === "text" ? first.text : void 0;
6654
+ const { toolName, input } = resolveToolChoiceSelection({
6655
+ text: firstText,
6656
+ tools: normalizedTools,
6657
+ onError: options == null ? void 0 : options.onError,
6658
+ errorMessage: "Failed to parse toolChoice JSON from streamed model output"
6659
+ });
6302
6660
  const stream = new ReadableStream({
6303
6661
  start(controller) {
6304
6662
  controller.enqueue({
@@ -6376,18 +6734,51 @@ function normalizeUsage(usage) {
6376
6734
  return ZERO_USAGE;
6377
6735
  }
6378
6736
 
6737
+ // src/core/prompts/shared/assistant-tool-calls-to-text.ts
6738
+ function assistantToolCallsToTextContent(options) {
6739
+ var _a, _b;
6740
+ const newContent = [];
6741
+ for (const item of options.content) {
6742
+ switch (item.type) {
6743
+ case "tool-call":
6744
+ newContent.push({
6745
+ type: "text",
6746
+ text: options.protocol.formatToolCall(item)
6747
+ });
6748
+ break;
6749
+ case "text":
6750
+ case "reasoning":
6751
+ newContent.push(item);
6752
+ break;
6753
+ default:
6754
+ (_b = (_a = options.conversionOptions) == null ? void 0 : _a.onError) == null ? void 0 : _b.call(
6755
+ _a,
6756
+ "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
6757
+ { content: item }
6758
+ );
6759
+ newContent.push({
6760
+ type: "text",
6761
+ text: JSON.stringify(item)
6762
+ });
6763
+ }
6764
+ }
6765
+ if (!newContent.every((entry) => entry.type === "text")) {
6766
+ return newContent;
6767
+ }
6768
+ return [
6769
+ {
6770
+ type: "text",
6771
+ text: newContent.map((entry) => entry.text).join("\n")
6772
+ }
6773
+ ];
6774
+ }
6775
+
6379
6776
  // src/core/prompts/shared/tool-role-to-user-message.ts
6380
6777
  function formatApprovalResponse(part) {
6381
6778
  const status = part.approved ? "Approved" : "Denied";
6382
6779
  const reason = part.reason ? `: ${part.reason}` : "";
6383
6780
  return `[Tool Approval ${status}${reason}]`;
6384
6781
  }
6385
- function toTextPart(text) {
6386
- return {
6387
- type: "text",
6388
- text
6389
- };
6390
- }
6391
6782
  function normalizeTemplateResult(result) {
6392
6783
  if (typeof result === "string") {
6393
6784
  return [toTextPart(result)];
@@ -6494,13 +6885,9 @@ function buildBaseReturnParams(params, finalPrompt, functionTools) {
6494
6885
  prompt: finalPrompt,
6495
6886
  tools: [],
6496
6887
  toolChoice: void 0,
6497
- providerOptions: {
6498
- ...params.providerOptions || {},
6499
- toolCallMiddleware: {
6500
- ...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
6501
- originalTools: originalToolsSchema.encode(functionTools)
6502
- }
6503
- }
6888
+ providerOptions: mergeToolCallMiddlewareOptions(params.providerOptions, {
6889
+ originalTools: originalToolsSchema.encode(functionTools)
6890
+ })
6504
6891
  };
6505
6892
  }
6506
6893
  function findProviderDefinedTool(tools, selectedToolName) {
@@ -6552,13 +6939,10 @@ function handleToolChoiceTool(params, baseReturnParams) {
6552
6939
  name: selectedTool.name,
6553
6940
  description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
6554
6941
  },
6555
- providerOptions: {
6556
- ...baseReturnParams.providerOptions || {},
6557
- toolCallMiddleware: {
6558
- ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
6559
- ...params.toolChoice ? { toolChoice: params.toolChoice } : {}
6560
- }
6561
- }
6942
+ providerOptions: mergeToolCallMiddlewareOptions(
6943
+ baseReturnParams.providerOptions,
6944
+ params.toolChoice ? { toolChoice: params.toolChoice } : {}
6945
+ )
6562
6946
  };
6563
6947
  }
6564
6948
  function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
@@ -6578,13 +6962,12 @@ function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
6578
6962
  type: "json",
6579
6963
  schema: createDynamicIfThenElseSchema(functionTools)
6580
6964
  },
6581
- providerOptions: {
6582
- ...baseReturnParams.providerOptions || {},
6583
- toolCallMiddleware: {
6584
- ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
6965
+ providerOptions: mergeToolCallMiddlewareOptions(
6966
+ baseReturnParams.providerOptions,
6967
+ {
6585
6968
  toolChoice: { type: "required" }
6586
6969
  }
6587
- }
6970
+ )
6588
6971
  };
6589
6972
  }
6590
6973
  function transformParams({
@@ -6816,7 +7199,10 @@ export {
6816
7199
  originalToolsSchema,
6817
7200
  encodeOriginalTools,
6818
7201
  decodeOriginalTools,
7202
+ decodeOriginalToolsFromProviderOptions,
6819
7203
  extractToolNamesFromOriginalTools,
7204
+ getToolCallMiddlewareOptions,
7205
+ mergeToolCallMiddlewareOptions,
6820
7206
  isToolChoiceActive,
6821
7207
  isToolResultPart,
6822
7208
  hasInputProperty,
@@ -6831,4 +7217,4 @@ export {
6831
7217
  morphXmlToolMiddleware,
6832
7218
  yamlXmlToolMiddleware
6833
7219
  };
6834
- //# sourceMappingURL=chunk-O6NWVXQD.js.map
7220
+ //# sourceMappingURL=chunk-X3NZ2YHV.js.map