@ai-sdk-tool/parser 4.0.1 → 4.1.1

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.
@@ -1,16 +1,19 @@
1
1
  import {
2
2
  escapeRegExp,
3
+ escapeXmlMinimalAttr,
4
+ escapeXmlMinimalText,
3
5
  parse as parse2,
4
- stringify
5
- } from "./chunk-76E6H46R.js";
6
+ stringify,
7
+ unescapeXml
8
+ } from "./chunk-D4YULTAO.js";
6
9
  import {
7
10
  parse
8
- } from "./chunk-IX4FJELL.js";
11
+ } from "./chunk-QBZNMO5C.js";
9
12
  import {
10
13
  coerceBySchema,
11
14
  getSchemaType,
12
15
  unwrapJsonSchema
13
- } from "./chunk-DJB4DAZO.js";
16
+ } from "./chunk-GMTE7BY5.js";
14
17
 
15
18
  // src/core/utils/debug.ts
16
19
  var LINE_SPLIT_REGEX = /\r?\n/;
@@ -219,6 +222,12 @@ function generateToolCallId() {
219
222
  }
220
223
 
221
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
+ }
222
231
  function addTextSegment(text, processedElements) {
223
232
  if (text.trim()) {
224
233
  processedElements.push({ type: "text", text });
@@ -257,10 +266,222 @@ function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmitte
257
266
  };
258
267
  }
259
268
 
260
- // src/core/protocols/json-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
+ }
261
480
  function shouldEmitRawToolCallTextOnError(options) {
262
481
  return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
263
482
  }
483
+
484
+ // src/core/protocols/hermes-protocol.ts
264
485
  function canonicalizeToolInput(argumentsValue) {
265
486
  return JSON.stringify(argumentsValue != null ? argumentsValue : {});
266
487
  }
@@ -524,19 +745,13 @@ function emitToolInputDelta(state, controller, fullInput) {
524
745
  if (!active) {
525
746
  return;
526
747
  }
527
- if (!fullInput.startsWith(active.emittedInput)) {
528
- return;
529
- }
530
- const delta = fullInput.slice(active.emittedInput.length);
531
- if (delta.length === 0) {
532
- return;
533
- }
534
- controller.enqueue({
535
- type: "tool-input-delta",
748
+ emitToolInputProgressDelta({
749
+ controller,
536
750
  id: active.id,
537
- delta
751
+ state: active,
752
+ fullInput,
753
+ mode: "full-json"
538
754
  });
539
- active.emittedInput = fullInput;
540
755
  }
541
756
  function closeToolInput(state, controller) {
542
757
  if (!state.activeToolInput) {
@@ -548,11 +763,16 @@ function closeToolInput(state, controller) {
548
763
  });
549
764
  state.activeToolInput = null;
550
765
  }
551
- function emitToolCallFromParsed(state, controller, parsedToolCall) {
766
+ function emitToolCallFromParsed(state, controller, parsedToolCall, tools) {
552
767
  var _a, _b, _c, _d;
553
768
  closeTextBlock(state, controller);
554
769
  const toolName = typeof parsedToolCall.name === "string" ? parsedToolCall.name : (_b = (_a = state.activeToolInput) == null ? void 0 : _a.toolName) != null ? _b : "unknown";
555
- const input = canonicalizeToolInput(parsedToolCall.arguments);
770
+ const input = stringifyToolInputWithSchema({
771
+ toolName,
772
+ args: parsedToolCall.arguments,
773
+ tools,
774
+ fallback: canonicalizeToolInput
775
+ });
556
776
  ensureToolInputStart(state, controller, toolName);
557
777
  emitToolInputDelta(state, controller, input);
558
778
  const toolCallId = (_d = (_c = state.activeToolInput) == null ? void 0 : _c.id) != null ? _d : generateToolCallId();
@@ -564,18 +784,23 @@ function emitToolCallFromParsed(state, controller, parsedToolCall) {
564
784
  input
565
785
  });
566
786
  }
567
- function canonicalizeArgumentsProgressInput(progress) {
787
+ function canonicalizeArgumentsProgressInput(progress, toolName, tools) {
568
788
  if (progress.argumentsText === void 0 || !progress.argumentsComplete) {
569
789
  return void 0;
570
790
  }
571
791
  try {
572
792
  const parsedArguments = parse(progress.argumentsText);
573
- return canonicalizeToolInput(parsedArguments);
793
+ return stringifyToolInputWithSchema({
794
+ toolName,
795
+ args: parsedArguments,
796
+ tools,
797
+ fallback: canonicalizeToolInput
798
+ });
574
799
  } catch (e) {
575
800
  return void 0;
576
801
  }
577
802
  }
578
- function emitToolInputProgress(state, controller) {
803
+ function emitToolInputProgress(state, controller, tools) {
579
804
  if (!(state.isInsideToolCall && state.currentToolCallJson)) {
580
805
  return;
581
806
  }
@@ -584,7 +809,11 @@ function emitToolInputProgress(state, controller) {
584
809
  return;
585
810
  }
586
811
  ensureToolInputStart(state, controller, progress.toolName);
587
- const canonicalProgressInput = canonicalizeArgumentsProgressInput(progress);
812
+ const canonicalProgressInput = canonicalizeArgumentsProgressInput(
813
+ progress,
814
+ progress.toolName,
815
+ tools
816
+ );
588
817
  if (canonicalProgressInput !== void 0) {
589
818
  emitToolInputDelta(state, controller, canonicalProgressInput);
590
819
  }
@@ -619,7 +848,7 @@ function closeTextBlock(state, controller) {
619
848
  state.hasEmittedTextStart = false;
620
849
  }
621
850
  }
622
- function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, options) {
851
+ function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer, tools, options) {
623
852
  var _a;
624
853
  if (!state.currentToolCallJson && trailingBuffer.length === 0) {
625
854
  state.isInsideToolCall = false;
@@ -628,7 +857,7 @@ function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer
628
857
  if (state.currentToolCallJson) {
629
858
  try {
630
859
  const parsedToolCall = parse(state.currentToolCallJson);
631
- emitToolCallFromParsed(state, controller, parsedToolCall);
860
+ emitToolCallFromParsed(state, controller, parsedToolCall, tools);
632
861
  state.currentToolCallJson = "";
633
862
  state.isInsideToolCall = false;
634
863
  return;
@@ -668,7 +897,7 @@ function emitIncompleteToolCall(state, controller, toolCallStart, trailingBuffer
668
897
  state.currentToolCallJson = "";
669
898
  state.isInsideToolCall = false;
670
899
  }
671
- function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
900
+ function handleFinishChunk(state, controller, toolCallStart, tools, options, chunk) {
672
901
  if (state.isInsideToolCall) {
673
902
  const trailingBuffer = state.buffer;
674
903
  state.buffer = "";
@@ -677,6 +906,7 @@ function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
677
906
  controller,
678
907
  toolCallStart,
679
908
  trailingBuffer,
909
+ tools,
680
910
  options
681
911
  );
682
912
  } else if (state.buffer.length > 0) {
@@ -685,11 +915,11 @@ function handleFinishChunk(state, controller, toolCallStart, options, chunk) {
685
915
  closeTextBlock(state, controller);
686
916
  controller.enqueue(chunk);
687
917
  }
688
- function publishText(text, state, controller) {
918
+ function publishText(text, state, controller, tools) {
689
919
  if (state.isInsideToolCall) {
690
920
  closeTextBlock(state, controller);
691
921
  state.currentToolCallJson += text;
692
- emitToolInputProgress(state, controller);
922
+ emitToolInputProgress(state, controller, tools);
693
923
  } else if (text.length > 0) {
694
924
  if (!state.currentTextId) {
695
925
  state.currentTextId = generateId();
@@ -708,10 +938,10 @@ function publishText(text, state, controller) {
708
938
  }
709
939
  function emitToolCall(context) {
710
940
  var _a;
711
- const { state, controller, toolCallStart, toolCallEnd, options } = context;
941
+ const { state, controller, toolCallStart, toolCallEnd, options, tools } = context;
712
942
  try {
713
943
  const parsedToolCall = parse(state.currentToolCallJson);
714
- emitToolCallFromParsed(state, controller, parsedToolCall);
944
+ emitToolCallFromParsed(state, controller, parsedToolCall, tools);
715
945
  } catch (error) {
716
946
  const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
717
947
  const shouldEmitRawFallback = shouldEmitRawToolCallTextOnError(options);
@@ -760,7 +990,7 @@ function processTagMatch(context) {
760
990
  }
761
991
  }
762
992
  function processBufferTags(context) {
763
- const { state, controller, toolCallStart, toolCallEnd } = context;
993
+ const { state, controller, toolCallStart, toolCallEnd, tools } = context;
764
994
  let startIndex = getPotentialStartIndex(
765
995
  state.buffer,
766
996
  state.isInsideToolCall ? toolCallEnd : toolCallStart
@@ -770,7 +1000,7 @@ function processBufferTags(context) {
770
1000
  if (startIndex + tag.length > state.buffer.length) {
771
1001
  break;
772
1002
  }
773
- publishText(state.buffer.slice(0, startIndex), state, controller);
1003
+ publishText(state.buffer.slice(0, startIndex), state, controller, tools);
774
1004
  state.buffer = state.buffer.slice(startIndex + tag.length);
775
1005
  processTagMatch(context);
776
1006
  startIndex = getPotentialStartIndex(
@@ -779,28 +1009,38 @@ function processBufferTags(context) {
779
1009
  );
780
1010
  }
781
1011
  }
782
- function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
1012
+ function handlePartialTag(state, controller, toolCallStart, toolCallEnd, tools) {
783
1013
  if (state.isInsideToolCall) {
784
1014
  const potentialEndIndex = getPotentialStartIndex(state.buffer, toolCallEnd);
785
1015
  if (potentialEndIndex != null && potentialEndIndex + toolCallEnd.length > state.buffer.length) {
786
- publishText(state.buffer.slice(0, potentialEndIndex), state, controller);
1016
+ publishText(
1017
+ state.buffer.slice(0, potentialEndIndex),
1018
+ state,
1019
+ controller,
1020
+ tools
1021
+ );
787
1022
  state.buffer = state.buffer.slice(potentialEndIndex);
788
1023
  } else {
789
- publishText(state.buffer, state, controller);
1024
+ publishText(state.buffer, state, controller, tools);
790
1025
  state.buffer = "";
791
1026
  }
792
1027
  return;
793
1028
  }
794
1029
  const potentialIndex = getPotentialStartIndex(state.buffer, toolCallStart);
795
1030
  if (potentialIndex != null && potentialIndex + toolCallStart.length > state.buffer.length) {
796
- publishText(state.buffer.slice(0, potentialIndex), state, controller);
1031
+ publishText(
1032
+ state.buffer.slice(0, potentialIndex),
1033
+ state,
1034
+ controller,
1035
+ tools
1036
+ );
797
1037
  state.buffer = state.buffer.slice(potentialIndex);
798
1038
  } else {
799
- publishText(state.buffer, state, controller);
1039
+ publishText(state.buffer, state, controller, tools);
800
1040
  state.buffer = "";
801
1041
  }
802
1042
  }
803
- var jsonProtocol = ({
1043
+ var hermesProtocol = ({
804
1044
  toolCallStart = "<tool_call>",
805
1045
  toolCallEnd = "</tool_call>"
806
1046
  } = {}) => ({
@@ -808,7 +1048,7 @@ var jsonProtocol = ({
808
1048
  tools,
809
1049
  toolSystemPromptTemplate
810
1050
  }) {
811
- return toolSystemPromptTemplate(tools || []);
1051
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
812
1052
  },
813
1053
  formatToolCall(toolCall) {
814
1054
  let args = {};
@@ -854,6 +1094,7 @@ var jsonProtocol = ({
854
1094
  return processedElements;
855
1095
  },
856
1096
  createStreamParser({
1097
+ tools,
857
1098
  options
858
1099
  }) {
859
1100
  const state = {
@@ -868,7 +1109,14 @@ var jsonProtocol = ({
868
1109
  transform(chunk, controller) {
869
1110
  var _a;
870
1111
  if (chunk.type === "finish") {
871
- handleFinishChunk(state, controller, toolCallStart, options, chunk);
1112
+ handleFinishChunk(
1113
+ state,
1114
+ controller,
1115
+ toolCallStart,
1116
+ tools,
1117
+ options,
1118
+ chunk
1119
+ );
872
1120
  return;
873
1121
  }
874
1122
  if (chunk.type !== "text-delta") {
@@ -882,9 +1130,10 @@ var jsonProtocol = ({
882
1130
  controller,
883
1131
  toolCallStart,
884
1132
  toolCallEnd,
885
- options
1133
+ options,
1134
+ tools
886
1135
  });
887
- handlePartialTag(state, controller, toolCallStart, toolCallEnd);
1136
+ handlePartialTag(state, controller, toolCallStart, toolCallEnd, tools);
888
1137
  }
889
1138
  });
890
1139
  },
@@ -902,92 +1151,10 @@ var jsonProtocol = ({
902
1151
  }
903
1152
  });
904
1153
 
905
- // src/core/protocols/protocol-interface.ts
906
- function isProtocolFactory(protocol) {
907
- return typeof protocol === "function";
908
- }
909
- function isTCMProtocolFactory(protocol) {
910
- return typeof protocol === "function";
911
- }
912
-
913
1154
  // src/core/utils/regex-constants.ts
914
1155
  var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
915
1156
  var WHITESPACE_REGEX = /\s/;
916
1157
 
917
- // src/core/utils/streamed-tool-input-delta.ts
918
- function emitDelta({
919
- controller,
920
- id,
921
- state,
922
- nextInput
923
- }) {
924
- if (!nextInput.startsWith(state.emittedInput)) {
925
- return false;
926
- }
927
- const delta = nextInput.slice(state.emittedInput.length);
928
- if (delta.length === 0) {
929
- return false;
930
- }
931
- controller.enqueue({
932
- type: "tool-input-delta",
933
- id,
934
- delta
935
- });
936
- state.emittedInput = nextInput;
937
- return true;
938
- }
939
- function toIncompleteJsonPrefix(fullJson) {
940
- const trimmed = fullJson.trim();
941
- let prefix = trimmed;
942
- while (prefix.endsWith("}") || prefix.endsWith("]")) {
943
- prefix = prefix.slice(0, -1);
944
- }
945
- prefix = prefix.trimEnd();
946
- if (prefix.endsWith('"')) {
947
- prefix = prefix.slice(0, -1);
948
- }
949
- if (prefix.length === 0) {
950
- if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
951
- return trimmed.startsWith("{") ? "{" : "[";
952
- }
953
- if (trimmed.startsWith("]")) {
954
- return "[";
955
- }
956
- if (trimmed.startsWith("}")) {
957
- return "{";
958
- }
959
- if (trimmed.startsWith('"')) {
960
- return '"';
961
- }
962
- return "{";
963
- }
964
- return prefix;
965
- }
966
- function emitPrefixDelta(params) {
967
- return emitDelta({
968
- ...params,
969
- nextInput: params.candidate
970
- });
971
- }
972
- function emitFinalRemainder(params) {
973
- var _a;
974
- const result = emitDelta({
975
- ...params,
976
- nextInput: params.finalFullJson
977
- });
978
- if (!result && params.state.emittedInput.length > 0) {
979
- (_a = params.onMismatch) == null ? void 0 : _a.call(
980
- params,
981
- "Final JSON does not extend emitted tool-input prefix",
982
- {
983
- emittedLength: params.state.emittedInput.length,
984
- finalLength: params.finalFullJson.length
985
- }
986
- );
987
- }
988
- return result;
989
- }
990
-
991
1158
  // src/core/utils/xml-root-repair.ts
992
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*$/;
993
1160
  function tryRepairXmlSelfClosingRootWithBody(rawText, toolNames) {
@@ -1012,18 +1179,244 @@ ${body}
1012
1179
  </${rootTag}>`;
1013
1180
  }
1014
1181
 
1015
- // src/core/protocols/xml-protocol.ts
1016
- function getToolSchema(tools, toolName) {
1017
- var _a;
1018
- return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
1019
- }
1020
- function shouldEmitRawToolCallTextOnError2(options) {
1021
- return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
1022
- }
1023
- function processToolCall(params) {
1024
- var _a, _b;
1025
- const { toolCall, tools, options, text, processedElements, parseOptions } = params;
1026
- const toolSchema = getToolSchema(tools, toolCall.toolName);
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) {
1417
+ var _a, _b;
1418
+ const { toolCall, tools, options, text, processedElements, parseOptions } = params;
1419
+ const toolSchema = getToolSchema(tools, toolCall.toolName);
1027
1420
  const parseConfig = {
1028
1421
  ...parseOptions != null ? parseOptions : {},
1029
1422
  onError: (_a = options == null ? void 0 : options.onError) != null ? _a : parseOptions == null ? void 0 : parseOptions.onError
@@ -1248,6 +1641,76 @@ function schemaAllowsArrayType(schema) {
1248
1641
  }
1249
1642
  return false;
1250
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
+ }
1251
1714
  function getSchemaObjectProperty(schema, propertyName) {
1252
1715
  if (!schema || typeof schema !== "object") {
1253
1716
  return null;
@@ -1297,8 +1760,10 @@ function isStableXmlProgressCandidate(options) {
1297
1760
  }
1298
1761
  function parseXmlContentForStreamProgress({
1299
1762
  toolContent,
1763
+ toolName,
1300
1764
  toolSchema,
1301
- parseOptions
1765
+ parseOptions,
1766
+ tools
1302
1767
  }) {
1303
1768
  const tryParse = (content) => {
1304
1769
  try {
@@ -1317,7 +1782,29 @@ function parseXmlContentForStreamProgress({
1317
1782
  parsed: strictFull,
1318
1783
  toolSchema
1319
1784
  })) {
1320
- 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
+ }
1321
1808
  }
1322
1809
  let searchEnd = toolContent.length;
1323
1810
  while (searchEnd > 0) {
@@ -1336,7 +1823,11 @@ function parseXmlContentForStreamProgress({
1336
1823
  parsed: parsedCandidate,
1337
1824
  toolSchema
1338
1825
  })) {
1339
- return JSON.stringify(parsedCandidate);
1826
+ return stringifyToolInputWithSchema({
1827
+ toolName,
1828
+ args: parsedCandidate,
1829
+ tools
1830
+ });
1340
1831
  }
1341
1832
  searchEnd = gtIndex;
1342
1833
  }
@@ -1361,37 +1852,35 @@ function handleStreamingToolCallEnd(params) {
1361
1852
  flushText(ctrl);
1362
1853
  try {
1363
1854
  const parsedResult = parse2(toolContent, toolSchema, parseConfig);
1364
- const finalInput = JSON.stringify(parsedResult);
1365
- emitFinalRemainder({
1855
+ const finalInput = stringifyToolInputWithSchema({
1856
+ toolName: currentToolCall.name,
1857
+ args: parsedResult,
1858
+ tools
1859
+ });
1860
+ emitFinalizedToolInputLifecycle({
1366
1861
  controller: ctrl,
1367
1862
  id: currentToolCall.toolCallId,
1368
1863
  state: currentToolCall,
1369
- finalFullJson: finalInput,
1370
- onMismatch: options == null ? void 0 : options.onError
1371
- });
1372
- ctrl.enqueue({
1373
- type: "tool-input-end",
1374
- id: currentToolCall.toolCallId
1375
- });
1376
- ctrl.enqueue({
1377
- type: "tool-call",
1378
- toolCallId: currentToolCall.toolCallId,
1379
1864
  toolName: currentToolCall.name,
1380
- input: finalInput
1865
+ finalInput,
1866
+ onMismatch: options == null ? void 0 : options.onError
1381
1867
  });
1382
1868
  } catch (error) {
1383
- ctrl.enqueue({
1384
- type: "tool-input-end",
1385
- id: currentToolCall.toolCallId
1386
- });
1387
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
+ });
1388
1880
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "Could not process streaming XML tool call", {
1389
1881
  toolCall: original,
1390
1882
  error
1391
1883
  });
1392
- if (shouldEmitRawToolCallTextOnError2(options)) {
1393
- flushText(ctrl, original);
1394
- }
1395
1884
  }
1396
1885
  }
1397
1886
  function findClosingTagEndFlexible(text, contentStart, toolName) {
@@ -1491,22 +1980,6 @@ function nextTagToken(text, fromPos) {
1491
1980
  nextPos: open.nextPos
1492
1981
  };
1493
1982
  }
1494
- function findNextToolTag(text, searchIndex, toolName) {
1495
- var _a, _b;
1496
- const startTag = `<${toolName}>`;
1497
- const openIdx = text.indexOf(startTag, searchIndex);
1498
- const selfMatch = findSelfClosingTag(text, toolName, searchIndex);
1499
- const selfIdx = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
1500
- if (openIdx === -1 && selfIdx === -1) {
1501
- return null;
1502
- }
1503
- const isSelfClosing = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx);
1504
- return {
1505
- tagStart: isSelfClosing ? selfIdx : openIdx,
1506
- isSelfClosing,
1507
- tagLength: isSelfClosing ? (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0 : startTag.length
1508
- };
1509
- }
1510
1983
  function findLastCloseTagStart(segment, toolName) {
1511
1984
  const closeTagPattern = new RegExp(
1512
1985
  `</\\s*${escapeRegExp(toolName)}\\s*>`,
@@ -1534,24 +2007,6 @@ function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, tagLength)
1534
2007
  });
1535
2008
  return endIndex;
1536
2009
  }
1537
- var selfClosingTagCache = /* @__PURE__ */ new Map();
1538
- function getSelfClosingTagPattern(toolName) {
1539
- let pattern = selfClosingTagCache.get(toolName);
1540
- if (!pattern) {
1541
- pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
1542
- selfClosingTagCache.set(toolName, pattern);
1543
- }
1544
- return pattern;
1545
- }
1546
- function findSelfClosingTag(text, toolName, fromIndex) {
1547
- const pattern = getSelfClosingTagPattern(toolName);
1548
- pattern.lastIndex = fromIndex;
1549
- const match = pattern.exec(text);
1550
- if (!match || match.index === void 0) {
1551
- return null;
1552
- }
1553
- return { index: match.index, length: match[0].length };
1554
- }
1555
2010
  function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, startTag) {
1556
2011
  const contentStart = tagStart + startTag.length;
1557
2012
  const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
@@ -1703,39 +2158,6 @@ function findLinePrefixedToolCall(text, toolNames) {
1703
2158
  }
1704
2159
  return best;
1705
2160
  }
1706
- function findEarliestToolTag(buffer, toolNames) {
1707
- var _a, _b;
1708
- let bestIndex = -1;
1709
- let bestName = "";
1710
- let bestSelfClosing = false;
1711
- let bestTagLength = 0;
1712
- if (toolNames.length > 0) {
1713
- for (const name of toolNames) {
1714
- const openTag = `<${name}>`;
1715
- const idxOpen = buffer.indexOf(openTag);
1716
- const selfMatch = findSelfClosingTag(buffer, name, 0);
1717
- const idxSelf = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
1718
- if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
1719
- bestIndex = idxOpen;
1720
- bestName = name;
1721
- bestSelfClosing = false;
1722
- bestTagLength = openTag.length;
1723
- }
1724
- if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
1725
- bestIndex = idxSelf;
1726
- bestName = name;
1727
- bestSelfClosing = true;
1728
- bestTagLength = (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0;
1729
- }
1730
- }
1731
- }
1732
- return {
1733
- index: bestIndex,
1734
- name: bestName,
1735
- selfClosing: bestSelfClosing,
1736
- tagLength: bestTagLength
1737
- };
1738
- }
1739
2161
  function isOpenTagPrefix(suffix, toolName) {
1740
2162
  return `${toolName}>`.startsWith(suffix);
1741
2163
  }
@@ -1813,160 +2235,6 @@ function findPotentialToolTagStart(buffer, toolNames) {
1813
2235
  }
1814
2236
  return -1;
1815
2237
  }
1816
- function processToolCallInBuffer(params) {
1817
- const {
1818
- buffer,
1819
- currentToolCall,
1820
- tools,
1821
- options,
1822
- controller,
1823
- flushText,
1824
- setBuffer,
1825
- parseOptions,
1826
- emitToolInputProgress: emitToolInputProgress2
1827
- } = params;
1828
- const endTagPattern = new RegExp(
1829
- `</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
1830
- );
1831
- const endMatch = endTagPattern.exec(buffer);
1832
- if (!endMatch || endMatch.index === void 0) {
1833
- emitToolInputProgress2(controller, currentToolCall, buffer);
1834
- return { buffer, currentToolCall, shouldBreak: true };
1835
- }
1836
- const endIdx = endMatch.index;
1837
- const endPos = endIdx + endMatch[0].length;
1838
- const content = buffer.substring(0, endIdx);
1839
- emitToolInputProgress2(controller, currentToolCall, content);
1840
- const remainder = buffer.substring(endPos);
1841
- setBuffer(remainder);
1842
- handleStreamingToolCallEnd({
1843
- toolContent: content,
1844
- currentToolCall,
1845
- tools,
1846
- options,
1847
- ctrl: controller,
1848
- flushText,
1849
- parseOptions
1850
- });
1851
- return {
1852
- buffer: remainder,
1853
- currentToolCall: null,
1854
- shouldBreak: false
1855
- };
1856
- }
1857
- function processNoToolCallInBuffer(params) {
1858
- const {
1859
- buffer,
1860
- toolNames,
1861
- controller,
1862
- flushText,
1863
- tools,
1864
- options,
1865
- parseOptions,
1866
- setBuffer,
1867
- emitToolInputStart
1868
- } = params;
1869
- const {
1870
- index: earliestStartTagIndex,
1871
- name: earliestToolName,
1872
- selfClosing,
1873
- tagLength
1874
- } = findEarliestToolTag(buffer, toolNames);
1875
- if (earliestStartTagIndex === -1) {
1876
- const potentialStart = findPotentialToolTagStart(buffer, toolNames);
1877
- const safeLen = Math.max(
1878
- 0,
1879
- potentialStart === -1 ? buffer.length : potentialStart
1880
- );
1881
- const remaining = buffer.slice(safeLen);
1882
- if (safeLen > 0) {
1883
- flushText(controller, buffer.slice(0, safeLen));
1884
- setBuffer(remaining);
1885
- }
1886
- return {
1887
- buffer: remaining,
1888
- currentToolCall: null,
1889
- shouldBreak: true,
1890
- shouldContinue: false
1891
- };
1892
- }
1893
- flushText(controller, buffer.substring(0, earliestStartTagIndex));
1894
- if (selfClosing) {
1895
- const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
1896
- setBuffer(newBuffer2);
1897
- const currentToolCall = emitToolInputStart(controller, earliestToolName);
1898
- handleStreamingToolCallEnd({
1899
- toolContent: "",
1900
- currentToolCall,
1901
- tools,
1902
- options,
1903
- ctrl: controller,
1904
- flushText,
1905
- parseOptions
1906
- });
1907
- return {
1908
- buffer: newBuffer2,
1909
- currentToolCall: null,
1910
- shouldBreak: false,
1911
- shouldContinue: false
1912
- };
1913
- }
1914
- const startTag = `<${earliestToolName}>`;
1915
- const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
1916
- setBuffer(newBuffer);
1917
- return {
1918
- buffer: newBuffer,
1919
- currentToolCall: emitToolInputStart(controller, earliestToolName),
1920
- shouldBreak: false,
1921
- shouldContinue: true
1922
- };
1923
- }
1924
- function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, parseOptions, emitToolInputProgress2, emitToolInputStart) {
1925
- return (controller) => {
1926
- while (true) {
1927
- const currentToolCall = getCurrentToolCall();
1928
- if (currentToolCall) {
1929
- const result = processToolCallInBuffer({
1930
- buffer: getBuffer(),
1931
- currentToolCall,
1932
- tools,
1933
- options,
1934
- controller,
1935
- flushText,
1936
- setBuffer,
1937
- parseOptions,
1938
- emitToolInputProgress: emitToolInputProgress2
1939
- });
1940
- setBuffer(result.buffer);
1941
- setCurrentToolCall(result.currentToolCall);
1942
- if (result.shouldBreak) {
1943
- break;
1944
- }
1945
- } else {
1946
- const result = processNoToolCallInBuffer({
1947
- buffer: getBuffer(),
1948
- toolNames,
1949
- controller,
1950
- flushText,
1951
- tools,
1952
- options,
1953
- parseOptions,
1954
- setBuffer,
1955
- emitToolInputStart
1956
- });
1957
- setBuffer(result.buffer);
1958
- setCurrentToolCall(result.currentToolCall);
1959
- if (result.shouldBreak) {
1960
- break;
1961
- }
1962
- if (result.shouldContinue) {
1963
- continue;
1964
- }
1965
- break;
1966
- }
1967
- }
1968
- };
1969
- }
1970
2238
  function findToolCallsWithFallbacks(text, toolNames) {
1971
2239
  let parseText = text;
1972
2240
  let toolCalls = findToolCalls(parseText, toolNames);
@@ -1988,7 +2256,7 @@ function findToolCallsWithFallbacks(text, toolNames) {
1988
2256
  }
1989
2257
  return { parseText, toolCalls };
1990
2258
  }
1991
- var xmlProtocol = (protocolOptions) => {
2259
+ var morphXmlProtocol = (protocolOptions) => {
1992
2260
  var _a;
1993
2261
  const parseOptions = {
1994
2262
  repair: true,
@@ -1997,7 +2265,7 @@ var xmlProtocol = (protocolOptions) => {
1997
2265
  };
1998
2266
  return {
1999
2267
  formatTools({ tools, toolSystemPromptTemplate }) {
2000
- return toolSystemPromptTemplate(tools || []);
2268
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
2001
2269
  },
2002
2270
  formatToolCall(toolCall) {
2003
2271
  let args = {};
@@ -2015,7 +2283,7 @@ var xmlProtocol = (protocolOptions) => {
2015
2283
  });
2016
2284
  },
2017
2285
  parseGeneratedText({ text, tools, options }) {
2018
- const toolNames = tools.map((t) => t.name).filter(Boolean);
2286
+ const toolNames = extractToolNames(tools);
2019
2287
  if (toolNames.length === 0) {
2020
2288
  return [{ type: "text", text }];
2021
2289
  }
@@ -2051,7 +2319,7 @@ var xmlProtocol = (protocolOptions) => {
2051
2319
  return processedElements;
2052
2320
  },
2053
2321
  createStreamParser({ tools, options }) {
2054
- const toolNames = tools.map((t) => t.name).filter(Boolean);
2322
+ const toolNames = extractToolNames(tools);
2055
2323
  let buffer = "";
2056
2324
  let currentToolCall = null;
2057
2325
  let currentTextId = null;
@@ -2072,6 +2340,7 @@ var xmlProtocol = (protocolOptions) => {
2072
2340
  name: toolName,
2073
2341
  toolCallId: generateToolCallId(),
2074
2342
  emittedInput: "",
2343
+ lastProgressContentLength: null,
2075
2344
  lastProgressGtIndex: null,
2076
2345
  lastProgressFullInput: null
2077
2346
  };
@@ -2084,7 +2353,8 @@ var xmlProtocol = (protocolOptions) => {
2084
2353
  };
2085
2354
  const emitToolInputProgress2 = (controller, toolCall, toolContent) => {
2086
2355
  const progressGtIndex = toolContent.lastIndexOf(">");
2087
- if (toolCall.lastProgressGtIndex === progressGtIndex) {
2356
+ const progressContentLength = toolContent.length;
2357
+ if (toolCall.lastProgressGtIndex === progressGtIndex && toolCall.lastProgressContentLength === progressContentLength) {
2088
2358
  const cached = toolCall.lastProgressFullInput;
2089
2359
  if (cached == null) {
2090
2360
  return;
@@ -2092,22 +2362,24 @@ var xmlProtocol = (protocolOptions) => {
2092
2362
  if (cached === "{}" && toolContent.trim().length === 0) {
2093
2363
  return;
2094
2364
  }
2095
- const prefixCandidate2 = toIncompleteJsonPrefix(cached);
2096
- emitPrefixDelta({
2365
+ emitToolInputProgressDelta({
2097
2366
  controller,
2098
2367
  id: toolCall.toolCallId,
2099
2368
  state: toolCall,
2100
- candidate: prefixCandidate2
2369
+ fullInput: cached
2101
2370
  });
2102
2371
  return;
2103
2372
  }
2104
2373
  const toolSchema = getToolSchema(tools, toolCall.name);
2105
2374
  const fullInput = parseXmlContentForStreamProgress({
2106
2375
  toolContent,
2376
+ toolName: toolCall.name,
2107
2377
  toolSchema,
2108
- parseOptions
2378
+ parseOptions,
2379
+ tools
2109
2380
  });
2110
2381
  toolCall.lastProgressGtIndex = progressGtIndex;
2382
+ toolCall.lastProgressContentLength = progressContentLength;
2111
2383
  toolCall.lastProgressFullInput = fullInput;
2112
2384
  if (fullInput == null) {
2113
2385
  return;
@@ -2115,12 +2387,11 @@ var xmlProtocol = (protocolOptions) => {
2115
2387
  if (fullInput === "{}" && toolContent.trim().length === 0) {
2116
2388
  return;
2117
2389
  }
2118
- const prefixCandidate = toIncompleteJsonPrefix(fullInput);
2119
- emitPrefixDelta({
2390
+ emitToolInputProgressDelta({
2120
2391
  controller,
2121
2392
  id: toolCall.toolCallId,
2122
2393
  state: toolCall,
2123
- candidate: prefixCandidate
2394
+ fullInput
2124
2395
  });
2125
2396
  };
2126
2397
  const finalizeUnclosedToolCall = (controller) => {
@@ -2142,59 +2413,59 @@ var xmlProtocol = (protocolOptions) => {
2142
2413
  );
2143
2414
  }
2144
2415
  const parsedResult = parse2(buffer, toolSchema, parseConfig);
2145
- const finalInput = JSON.stringify(parsedResult);
2146
- emitFinalRemainder({
2416
+ const finalInput = stringifyToolInputWithSchema({
2417
+ toolName: currentToolCall.name,
2418
+ args: parsedResult,
2419
+ tools
2420
+ });
2421
+ emitFinalizedToolInputLifecycle({
2147
2422
  controller,
2148
2423
  id: currentToolCall.toolCallId,
2149
2424
  state: currentToolCall,
2150
- finalFullJson: finalInput,
2151
- onMismatch: options == null ? void 0 : options.onError
2152
- });
2153
- controller.enqueue({
2154
- type: "tool-input-end",
2155
- id: currentToolCall.toolCallId
2156
- });
2157
- controller.enqueue({
2158
- type: "tool-call",
2159
- toolCallId: currentToolCall.toolCallId,
2160
2425
  toolName: currentToolCall.name,
2161
- input: finalInput
2426
+ finalInput,
2427
+ onMismatch: options == null ? void 0 : options.onError
2162
2428
  });
2163
2429
  } catch (error) {
2164
- controller.enqueue({
2165
- type: "tool-input-end",
2166
- id: currentToolCall.toolCallId
2167
- });
2168
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
+ });
2169
2441
  (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
2170
2442
  options,
2171
2443
  "Could not complete streaming XML tool call at finish.",
2172
2444
  { toolCall: unfinishedContent, error }
2173
2445
  );
2174
- if (shouldEmitRawToolCallTextOnError2(options)) {
2175
- flushText(controller, unfinishedContent);
2176
- }
2177
2446
  }
2178
2447
  buffer = "";
2179
2448
  currentToolCall = null;
2180
2449
  };
2181
- const processBuffer = createProcessBufferHandler(
2182
- () => buffer,
2183
- (newBuffer) => {
2450
+ const processBuffer = createProcessBufferHandler({
2451
+ getBuffer: () => buffer,
2452
+ setBuffer: (newBuffer) => {
2184
2453
  buffer = newBuffer;
2185
2454
  },
2186
- () => currentToolCall,
2187
- (newToolCall) => {
2455
+ getCurrentToolCall: () => currentToolCall,
2456
+ setCurrentToolCall: (newToolCall) => {
2188
2457
  currentToolCall = newToolCall;
2189
2458
  },
2190
2459
  tools,
2191
- options,
2460
+ parserOptions: options,
2192
2461
  toolNames,
2193
2462
  flushText,
2194
2463
  parseOptions,
2195
- emitToolInputProgress2,
2196
- emitToolInputStart
2197
- );
2464
+ emitToolInputProgress: emitToolInputProgress2,
2465
+ emitToolInputStart,
2466
+ findPotentialToolTagStart,
2467
+ handleStreamingToolCallEnd
2468
+ });
2198
2469
  return new TransformStream({
2199
2470
  // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Stateful stream parsing requires branching over chunk lifecycle and parser states.
2200
2471
  transform(chunk, controller) {
@@ -2230,41 +2501,1950 @@ var xmlProtocol = (protocolOptions) => {
2230
2501
  flushText(controller, buffer);
2231
2502
  buffer = "";
2232
2503
  }
2233
- if (currentTextId && hasEmittedTextStart) {
2234
- controller.enqueue({
2235
- type: "text-end",
2236
- id: currentTextId
2237
- });
2238
- hasEmittedTextStart = false;
2239
- currentTextId = null;
2504
+ if (currentTextId && hasEmittedTextStart) {
2505
+ controller.enqueue({
2506
+ type: "text-end",
2507
+ id: currentTextId
2508
+ });
2509
+ hasEmittedTextStart = false;
2510
+ currentTextId = null;
2511
+ }
2512
+ }
2513
+ });
2514
+ },
2515
+ extractToolCallSegments({ text, tools }) {
2516
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
2517
+ if (toolNames.length === 0) {
2518
+ return [];
2519
+ }
2520
+ return findToolCalls(text, toolNames).map((tc) => tc.segment);
2521
+ }
2522
+ };
2523
+ };
2524
+
2525
+ // src/core/protocols/protocol-interface.ts
2526
+ function isProtocolFactory(protocol) {
2527
+ return typeof protocol === "function";
2528
+ }
2529
+ var isTCMProtocolFactory = isProtocolFactory;
2530
+
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) {
2552
+ var _a;
2553
+ const parsed = options.parseParamTagAt(
2554
+ options.work,
2555
+ options.lower,
2556
+ options.lt,
2557
+ {
2558
+ allowEndOfString: options.allowEndOfString,
2559
+ callEndTagNameLower: options.callState.endTagName
2560
+ }
2561
+ );
2562
+ if (!parsed) {
2563
+ return {
2564
+ nextIndex: options.lt + 1,
2565
+ nextLastKept: options.lastKept,
2566
+ shouldStop: false
2567
+ };
2568
+ }
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
+ };
2581
+ }
2582
+ options.callState.partialParam = null;
2583
+ options.mergeParamValue(options.callState.args, parsed.name, parsed.value);
2584
+ return {
2585
+ keepSlice: options.work.slice(options.lastKept, parsed.start),
2586
+ nextIndex: parsed.end,
2587
+ nextLastKept: parsed.end,
2588
+ shouldStop: false
2589
+ };
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
+ }
2649
+
2650
+ // src/core/protocols/qwen3coder-protocol.ts
2651
+ var TOOL_CALL_OPEN_RE = /<tool_call\b[^>]*>/i;
2652
+ var TOOL_CALL_CLOSE_RE = /<\/tool_call\s*>/i;
2653
+ var TOOL_CALL_CLOSE_TRAILING_RE = /<\/tool_call\s*>\s*$/i;
2654
+ var TOOL_CALL_BLOCK_RE = /<tool_call\b[^>]*>[\s\S]*?<\/tool_call\s*>/gi;
2655
+ var LEADING_CALL_CLOSE_TAG_RE = /^\s*<\s*\/\s*(?:tool_call|function|call|tool|invoke)\s*>/i;
2656
+ var CALL_BLOCK_RE = /<(call|function|tool|invoke)\b[^>]*>[\s\S]*?<\/\1\s*>/gi;
2657
+ var QWEN3CODER_TOOL_PARSER_PARAM_TAG_NAMES = /* @__PURE__ */ new Set([
2658
+ "parameter",
2659
+ "param",
2660
+ "argument",
2661
+ "arg"
2662
+ ]);
2663
+ var QWEN3CODER_TOOL_PARSER_CALL_TAG_NAMES = /* @__PURE__ */ new Set([
2664
+ "function",
2665
+ "call",
2666
+ "tool",
2667
+ "invoke",
2668
+ "tool_call"
2669
+ ]);
2670
+ var CALL_SHORTHAND_VALUE_RE = /^<\s*(call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/]+))/i;
2671
+ var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_START_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b/i;
2672
+ var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b[^>]*>/i;
2673
+ var QWEN3CODER_TOOL_PARSER_STREAM_TOOL_CALL_CLOSE_TAG_RE = /<\s*\/\s*tool_call\s*>/i;
2674
+ var QWEN3CODER_TOOL_PARSER_STREAM_NAME_OR_PARAM_SIGNAL_RE = /<\s*(?!\/)\s*(name|tool_name|parameter|param|argument|arg)\b/i;
2675
+ var QWEN3CODER_TOOL_PARSER_STREAM_NAME_TAG_RE = /<\s*(name|tool_name)\b[^>]*>([\s\S]*?)<\s*\/\s*\1\s*>/i;
2676
+ var QWEN3CODER_TOOL_PARSER_STREAM_SELF_CLOSING_TAG_RE = /\/\s*>$/;
2677
+ function isAsciiWhitespace(ch) {
2678
+ return ch === " " || ch === "\n" || ch === "\r" || ch === " " || ch === "\f";
2679
+ }
2680
+ function skipAsciiWhitespace(text, index) {
2681
+ var _a;
2682
+ let i = index;
2683
+ while (i < text.length && isAsciiWhitespace((_a = text[i]) != null ? _a : "")) {
2684
+ i += 1;
2685
+ }
2686
+ return i;
2687
+ }
2688
+ function stripLeadingToolCallCloseTags(text) {
2689
+ let out = text;
2690
+ while (true) {
2691
+ const start = skipAsciiWhitespace(out, 0);
2692
+ const trimmed = out.slice(start);
2693
+ const match = TOOL_CALL_CLOSE_RE.exec(trimmed);
2694
+ if (!match || match.index !== 0 || !match[0]) {
2695
+ return out;
2696
+ }
2697
+ out = out.slice(start + match[0].length);
2698
+ }
2699
+ }
2700
+ function stripTrailingToolCallCloseTags(text) {
2701
+ let out = text;
2702
+ while (true) {
2703
+ const next = out.replace(TOOL_CALL_CLOSE_TRAILING_RE, "");
2704
+ if (next === out) {
2705
+ return out;
2706
+ }
2707
+ out = next;
2708
+ }
2709
+ }
2710
+ function isTagBoundaryChar(ch) {
2711
+ return ch === "" || isAsciiWhitespace(ch) || ch === ">" || ch === "/";
2712
+ }
2713
+ function findTagEndIndex(text, startIndex) {
2714
+ var _a;
2715
+ let quote = null;
2716
+ for (let i = startIndex; i < text.length; i += 1) {
2717
+ const ch = (_a = text[i]) != null ? _a : "";
2718
+ if (quote) {
2719
+ if (ch === quote) {
2720
+ quote = null;
2721
+ }
2722
+ continue;
2723
+ }
2724
+ if (ch === '"' || ch === "'") {
2725
+ quote = ch;
2726
+ continue;
2727
+ }
2728
+ if (ch === ">") {
2729
+ return i;
2730
+ }
2731
+ }
2732
+ return null;
2733
+ }
2734
+ function parseShorthandValue(openTag, tagNameLower) {
2735
+ var _a, _b;
2736
+ let i = 1;
2737
+ i = skipAsciiWhitespace(openTag, i);
2738
+ if (!openTag.toLowerCase().startsWith(tagNameLower, i)) {
2739
+ return null;
2740
+ }
2741
+ i += tagNameLower.length;
2742
+ i = skipAsciiWhitespace(openTag, i);
2743
+ if (openTag[i] !== "=") {
2744
+ return null;
2745
+ }
2746
+ i += 1;
2747
+ i = skipAsciiWhitespace(openTag, i);
2748
+ const quote = (_a = openTag[i]) != null ? _a : "";
2749
+ if (quote === '"' || quote === "'") {
2750
+ const end = openTag.indexOf(quote, i + 1);
2751
+ if (end === -1) {
2752
+ return null;
2753
+ }
2754
+ return openTag.slice(i + 1, end);
2755
+ }
2756
+ const start = i;
2757
+ while (i < openTag.length) {
2758
+ const ch = (_b = openTag[i]) != null ? _b : "";
2759
+ if (isAsciiWhitespace(ch) || ch === ">" || ch === "/") {
2760
+ break;
2761
+ }
2762
+ i += 1;
2763
+ }
2764
+ const value = openTag.slice(start, i);
2765
+ return value.length > 0 ? value : null;
2766
+ }
2767
+ function parseQwen3CoderToolParserParamName(openTag, tagNameLower) {
2768
+ const shorthand = parseShorthandValue(openTag, tagNameLower);
2769
+ if (shorthand != null) {
2770
+ return unescapeXml(shorthand);
2771
+ }
2772
+ return getAttributeValue(openTag, "name");
2773
+ }
2774
+ function getCdataSectionNextIndex(textLower, startIndex) {
2775
+ if (!textLower.startsWith("<![cdata[", startIndex)) {
2776
+ return startIndex;
2777
+ }
2778
+ const cdataEnd = textLower.indexOf("]]>", startIndex + "<![cdata[".length);
2779
+ if (cdataEnd === -1) {
2780
+ return null;
2781
+ }
2782
+ return cdataEnd + 3;
2783
+ }
2784
+ function parseMatchingTagHeader(textLower, lt, tagNameLower) {
2785
+ var _a;
2786
+ let i = skipAsciiWhitespace(textLower, lt + 1);
2787
+ const isClosing = textLower[i] === "/";
2788
+ if (isClosing) {
2789
+ i += 1;
2790
+ i = skipAsciiWhitespace(textLower, i);
2791
+ }
2792
+ if (!textLower.startsWith(tagNameLower, i)) {
2793
+ return null;
2794
+ }
2795
+ const afterName = i + tagNameLower.length;
2796
+ const boundary = (_a = textLower[afterName]) != null ? _a : "";
2797
+ const validBoundary = isClosing ? isTagBoundaryChar(boundary) : isTagBoundaryChar(boundary) || boundary === "=";
2798
+ if (boundary && !validBoundary) {
2799
+ return null;
2800
+ }
2801
+ return { isClosing, afterName };
2802
+ }
2803
+ function isSelfClosingXmlTag(textLower, lt, gt) {
2804
+ return textLower.slice(lt, gt + 1).trimEnd().endsWith("/>");
2805
+ }
2806
+ function findClosingTagEnd(textLower, startIndex, tagNameLower) {
2807
+ let depth = 1;
2808
+ let index = startIndex;
2809
+ while (true) {
2810
+ const lt = textLower.indexOf("<", index);
2811
+ if (lt === -1) {
2812
+ return null;
2813
+ }
2814
+ const cdataNextIndex = getCdataSectionNextIndex(textLower, lt);
2815
+ if (cdataNextIndex == null) {
2816
+ return null;
2817
+ }
2818
+ if (cdataNextIndex !== lt) {
2819
+ index = cdataNextIndex;
2820
+ continue;
2821
+ }
2822
+ const header = parseMatchingTagHeader(textLower, lt, tagNameLower);
2823
+ if (!header) {
2824
+ index = lt + 1;
2825
+ continue;
2826
+ }
2827
+ const gt = textLower.indexOf(">", header.afterName);
2828
+ if (gt === -1) {
2829
+ return null;
2830
+ }
2831
+ if (header.isClosing) {
2832
+ depth -= 1;
2833
+ if (depth === 0) {
2834
+ return { start: lt, end: gt + 1 };
2835
+ }
2836
+ index = gt + 1;
2837
+ continue;
2838
+ }
2839
+ const isSelfClosing = isSelfClosingXmlTag(textLower, lt, gt);
2840
+ if (!isSelfClosing) {
2841
+ depth += 1;
2842
+ }
2843
+ index = gt + 1;
2844
+ }
2845
+ }
2846
+ function findClosingTagStartWithBoundary(lowerText, valueStart, tagNameLower, allowEndOfStringBoundary) {
2847
+ var _a;
2848
+ const needle = `</${tagNameLower}`;
2849
+ let searchIndex = valueStart;
2850
+ while (searchIndex < lowerText.length) {
2851
+ const found = lowerText.indexOf(needle, searchIndex);
2852
+ if (found === -1) {
2853
+ return -1;
2854
+ }
2855
+ const nextChar = (_a = lowerText[found + needle.length]) != null ? _a : "";
2856
+ if (nextChar === "" && !allowEndOfStringBoundary) {
2857
+ searchIndex = found + needle.length;
2858
+ continue;
2859
+ }
2860
+ if (isTagBoundaryChar(nextChar)) {
2861
+ return found;
2862
+ }
2863
+ searchIndex = found + needle.length;
2864
+ }
2865
+ return -1;
2866
+ }
2867
+ function toSupportedCallEndTagName(tagNameLower) {
2868
+ var _a;
2869
+ const normalized = (_a = tagNameLower == null ? void 0 : tagNameLower.trim().toLowerCase()) != null ? _a : "";
2870
+ if (!normalized) {
2871
+ return null;
2872
+ }
2873
+ return QWEN3CODER_TOOL_PARSER_CALL_TAG_NAMES.has(normalized) ? normalized : null;
2874
+ }
2875
+ function findUnclosedParamBoundaryIndex(lowerText, valueStart, callEndTagNameLower, allowEndOfString) {
2876
+ const normalizedCallEndTag = toSupportedCallEndTagName(callEndTagNameLower);
2877
+ const callCloseIndex = normalizedCallEndTag ? findClosingTagStartWithBoundary(
2878
+ lowerText,
2879
+ valueStart,
2880
+ normalizedCallEndTag,
2881
+ allowEndOfString
2882
+ ) : findClosingTagStartWithBoundary(
2883
+ lowerText,
2884
+ valueStart,
2885
+ "function",
2886
+ allowEndOfString
2887
+ );
2888
+ const indices = [
2889
+ lowerText.indexOf("<parameter", valueStart),
2890
+ lowerText.indexOf("<param", valueStart),
2891
+ lowerText.indexOf("<argument", valueStart),
2892
+ lowerText.indexOf("<arg", valueStart),
2893
+ callCloseIndex,
2894
+ findClosingTagStartWithBoundary(
2895
+ lowerText,
2896
+ valueStart,
2897
+ "tool_call",
2898
+ allowEndOfString
2899
+ ),
2900
+ lowerText.indexOf("<function", valueStart)
2901
+ ].filter((index) => index !== -1);
2902
+ if (indices.length === 0) {
2903
+ return null;
2904
+ }
2905
+ return Math.min(...indices);
2906
+ }
2907
+ function parseQwen3CoderToolParserParamTagNameLower(lowerText, startIndex) {
2908
+ var _a;
2909
+ let i = skipAsciiWhitespace(lowerText, startIndex + 1);
2910
+ if (i >= lowerText.length) {
2911
+ return { kind: "partial" };
2912
+ }
2913
+ if (lowerText[i] === "/") {
2914
+ return null;
2915
+ }
2916
+ const nameStart = i;
2917
+ while (i < lowerText.length) {
2918
+ const ch = (_a = lowerText[i]) != null ? _a : "";
2919
+ if (isAsciiWhitespace(ch) || ch === ">" || ch === "/" || ch === "=") {
2920
+ break;
2921
+ }
2922
+ i += 1;
2923
+ }
2924
+ const tagNameLower = lowerText.slice(nameStart, i);
2925
+ if (!QWEN3CODER_TOOL_PARSER_PARAM_TAG_NAMES.has(tagNameLower)) {
2926
+ return null;
2927
+ }
2928
+ return { kind: "match", tagNameLower };
2929
+ }
2930
+ function parseQwen3CoderToolParserUnclosedParamValue(options) {
2931
+ var _a;
2932
+ const valueStart = options.openEnd + 1;
2933
+ const boundaryIndex = findUnclosedParamBoundaryIndex(
2934
+ options.lowerText,
2935
+ valueStart,
2936
+ (_a = options.callEndTagNameLower) != null ? _a : null,
2937
+ options.allowEndOfString
2938
+ );
2939
+ if (boundaryIndex == null) {
2940
+ if (!options.allowEndOfString) {
2941
+ const rawProgressValue = options.text.slice(valueStart);
2942
+ return {
2943
+ kind: "partial",
2944
+ start: options.startIndex,
2945
+ openEnd: options.openEnd,
2946
+ name: options.paramName,
2947
+ value: rawProgressValue ? normalizeXmlTextValue(rawProgressValue) : ""
2948
+ };
2949
+ }
2950
+ const rawValue2 = options.text.slice(valueStart);
2951
+ return {
2952
+ kind: "match",
2953
+ start: options.startIndex,
2954
+ end: options.text.length,
2955
+ name: options.paramName,
2956
+ value: rawValue2 ? normalizeXmlTextValue(rawValue2) : ""
2957
+ };
2958
+ }
2959
+ const rawValue = options.text.slice(valueStart, boundaryIndex);
2960
+ return {
2961
+ kind: "match",
2962
+ start: options.startIndex,
2963
+ end: boundaryIndex,
2964
+ name: options.paramName,
2965
+ value: rawValue ? normalizeXmlTextValue(rawValue) : ""
2966
+ };
2967
+ }
2968
+ function parseQwen3CoderToolParserParamTagAt(text, lowerText, startIndex, options) {
2969
+ var _a;
2970
+ const tagNameParse = parseQwen3CoderToolParserParamTagNameLower(
2971
+ lowerText,
2972
+ startIndex
2973
+ );
2974
+ if (!tagNameParse) {
2975
+ return null;
2976
+ }
2977
+ if (tagNameParse.kind === "partial") {
2978
+ return { kind: "partial", start: startIndex, openEnd: null };
2979
+ }
2980
+ const tagNameLower = tagNameParse.tagNameLower;
2981
+ const openEnd = findTagEndIndex(text, startIndex);
2982
+ if (openEnd == null) {
2983
+ return { kind: "partial", start: startIndex, openEnd: null };
2984
+ }
2985
+ const openTag = text.slice(startIndex, openEnd + 1);
2986
+ const paramNameRaw = parseQwen3CoderToolParserParamName(
2987
+ openTag,
2988
+ tagNameLower
2989
+ );
2990
+ const paramName = (_a = paramNameRaw == null ? void 0 : paramNameRaw.trim()) != null ? _a : "";
2991
+ if (paramName.length === 0) {
2992
+ return null;
2993
+ }
2994
+ const selfClosing = openTag.trimEnd().endsWith("/>");
2995
+ if (selfClosing) {
2996
+ return {
2997
+ kind: "match",
2998
+ start: startIndex,
2999
+ end: openEnd + 1,
3000
+ name: paramName,
3001
+ value: ""
3002
+ };
3003
+ }
3004
+ const valueStart = openEnd + 1;
3005
+ const close = findClosingTagEnd(lowerText, valueStart, tagNameLower);
3006
+ if (!close) {
3007
+ return parseQwen3CoderToolParserUnclosedParamValue({
3008
+ text,
3009
+ lowerText,
3010
+ startIndex,
3011
+ openEnd,
3012
+ paramName,
3013
+ allowEndOfString: (options == null ? void 0 : options.allowEndOfString) === true,
3014
+ callEndTagNameLower: options == null ? void 0 : options.callEndTagNameLower
3015
+ });
3016
+ }
3017
+ const rawValue = text.slice(openEnd + 1, close.start);
3018
+ return {
3019
+ kind: "match",
3020
+ start: startIndex,
3021
+ end: close.end,
3022
+ name: paramName,
3023
+ value: rawValue ? normalizeXmlTextValue(rawValue) : ""
3024
+ };
3025
+ }
3026
+ function normalizeXmlTextValue(raw) {
3027
+ let out = raw.trim();
3028
+ if (out.startsWith("<![CDATA[") && out.endsWith("]]>")) {
3029
+ out = out.slice("<![CDATA[".length, -"]]>".length).trim();
3030
+ }
3031
+ return unescapeXml(out);
3032
+ }
3033
+ function getOpeningTag(xml) {
3034
+ const gt = xml.indexOf(">");
3035
+ if (gt === -1) {
3036
+ return null;
3037
+ }
3038
+ return xml.slice(0, gt + 1);
3039
+ }
3040
+ var attrValueRegExpCache = /* @__PURE__ */ new Map();
3041
+ function getAttributeValue(openTag, attrName) {
3042
+ var _a;
3043
+ let re = attrValueRegExpCache.get(attrName);
3044
+ if (!re) {
3045
+ re = new RegExp(
3046
+ `\\b${escapeRegExp(attrName)}\\s*=\\s*(["'])([\\s\\S]*?)\\1`,
3047
+ "i"
3048
+ );
3049
+ attrValueRegExpCache.set(attrName, re);
3050
+ }
3051
+ const match = re.exec(openTag);
3052
+ if (!match) {
3053
+ return null;
3054
+ }
3055
+ return unescapeXml((_a = match[2]) != null ? _a : "");
3056
+ }
3057
+ function getShorthandValue(openTag) {
3058
+ var _a, _b;
3059
+ const match = CALL_SHORTHAND_VALUE_RE.exec(openTag);
3060
+ if (!match) {
3061
+ return null;
3062
+ }
3063
+ const value = (_b = (_a = match[2]) != null ? _a : match[3]) != null ? _b : match[4];
3064
+ if (!value) {
3065
+ return null;
3066
+ }
3067
+ return unescapeXml(value);
3068
+ }
3069
+ function extractFirstTagText(xml, tagName) {
3070
+ var _a;
3071
+ const lower = xml.toLowerCase();
3072
+ const tagLower = tagName.toLowerCase();
3073
+ let index = 0;
3074
+ while (true) {
3075
+ const lt = lower.indexOf("<", index);
3076
+ if (lt === -1) {
3077
+ return null;
3078
+ }
3079
+ const i = skipAsciiWhitespace(lower, lt + 1);
3080
+ if (i >= lower.length || lower[i] === "/") {
3081
+ index = lt + 1;
3082
+ continue;
3083
+ }
3084
+ if (!lower.startsWith(tagLower, i)) {
3085
+ index = lt + 1;
3086
+ continue;
3087
+ }
3088
+ const afterName = i + tagLower.length;
3089
+ const boundary = (_a = lower[afterName]) != null ? _a : "";
3090
+ if (boundary && !isTagBoundaryChar(boundary)) {
3091
+ index = lt + 1;
3092
+ continue;
3093
+ }
3094
+ const openEnd = findTagEndIndex(xml, lt);
3095
+ if (openEnd == null) {
3096
+ return null;
3097
+ }
3098
+ const contentStart = openEnd + 1;
3099
+ const close = findClosingTagEnd(lower, contentStart, tagLower);
3100
+ if (!close) {
3101
+ return null;
3102
+ }
3103
+ return normalizeXmlTextValue(xml.slice(contentStart, close.start));
3104
+ }
3105
+ }
3106
+ function extractToolCallInnerXml(segment) {
3107
+ const openMatch = TOOL_CALL_OPEN_RE.exec(segment);
3108
+ const closeMatch = TOOL_CALL_CLOSE_RE.exec(segment);
3109
+ if (!(openMatch && closeMatch)) {
3110
+ return null;
3111
+ }
3112
+ const openIndex = openMatch.index;
3113
+ const openTag = openMatch[0];
3114
+ const openEnd = openIndex + openTag.length;
3115
+ const closeIndex = segment.toLowerCase().lastIndexOf("</tool_call");
3116
+ if (closeIndex === -1) {
3117
+ return null;
3118
+ }
3119
+ const closeGt = segment.indexOf(">", closeIndex);
3120
+ if (closeGt === -1) {
3121
+ return null;
3122
+ }
3123
+ return {
3124
+ outerOpenTag: openTag,
3125
+ inner: segment.slice(openEnd, closeIndex)
3126
+ };
3127
+ }
3128
+ function mergeParamValue(args, key, value) {
3129
+ const existing = args[key];
3130
+ if (existing === void 0) {
3131
+ args[key] = value;
3132
+ return;
3133
+ }
3134
+ if (Array.isArray(existing)) {
3135
+ existing.push(value);
3136
+ return;
3137
+ }
3138
+ args[key] = [existing, value];
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
+ }
3162
+ function extractParameters(xml, options) {
3163
+ var _a;
3164
+ const args = {};
3165
+ const lower = xml.toLowerCase();
3166
+ let index = 0;
3167
+ while (true) {
3168
+ const lt = lower.indexOf("<", index);
3169
+ if (lt === -1) {
3170
+ break;
3171
+ }
3172
+ const parsed = parseQwen3CoderToolParserParamTagAt(xml, lower, lt, {
3173
+ allowEndOfString: true,
3174
+ callEndTagNameLower: options == null ? void 0 : options.callEndTagNameLower
3175
+ });
3176
+ if (!parsed) {
3177
+ index = lt + 1;
3178
+ continue;
3179
+ }
3180
+ if (parsed.kind === "match") {
3181
+ mergeParamValue(args, parsed.name, parsed.value);
3182
+ index = parsed.end;
3183
+ continue;
3184
+ }
3185
+ index = ((_a = parsed.openEnd) != null ? _a : lt) + 1;
3186
+ }
3187
+ return args;
3188
+ }
3189
+ function parseSingleFunctionCallXml(xml, fallbackToolName) {
3190
+ var _a, _b, _c;
3191
+ const openingTag = getOpeningTag(xml);
3192
+ const toolNameAttr = openingTag ? getAttributeValue(openingTag, "name") : null;
3193
+ const shorthandName = openingTag ? getShorthandValue(openingTag) : null;
3194
+ const toolName = (_c = (_b = (_a = toolNameAttr != null ? toolNameAttr : shorthandName) != null ? _a : extractFirstTagText(xml, "name")) != null ? _b : extractFirstTagText(xml, "tool_name")) != null ? _c : fallbackToolName;
3195
+ const callEndTagNameLower = toSupportedCallEndTagName(
3196
+ openingTag ? getOpenTagNameLower(openingTag) : null
3197
+ );
3198
+ if (!toolName || toolName.trim().length === 0) {
3199
+ return null;
3200
+ }
3201
+ return {
3202
+ toolName,
3203
+ args: extractParameters(xml, { callEndTagNameLower })
3204
+ };
3205
+ }
3206
+ function findImplicitCallOpenIndices(lowerText) {
3207
+ var _a;
3208
+ const indices = [];
3209
+ let index = 0;
3210
+ while (true) {
3211
+ const lt = lowerText.indexOf("<", index);
3212
+ if (lt === -1) {
3213
+ break;
3214
+ }
3215
+ const i = skipAsciiWhitespace(lowerText, lt + 1);
3216
+ if (i >= lowerText.length) {
3217
+ break;
3218
+ }
3219
+ if (lowerText[i] === "/") {
3220
+ index = lt + 1;
3221
+ continue;
3222
+ }
3223
+ const tagNames = ["call", "function", "tool", "invoke"];
3224
+ for (const tagName of tagNames) {
3225
+ if (!lowerText.startsWith(tagName, i)) {
3226
+ continue;
3227
+ }
3228
+ const after = i + tagName.length;
3229
+ const boundary = (_a = lowerText[after]) != null ? _a : "";
3230
+ if (boundary && !isTagBoundaryChar(boundary) && boundary !== "=") {
3231
+ continue;
3232
+ }
3233
+ indices.push(lt);
3234
+ break;
3235
+ }
3236
+ index = lt + 1;
3237
+ }
3238
+ return indices;
3239
+ }
3240
+ function splitImplicitCallBlocks(xml) {
3241
+ var _a, _b;
3242
+ const lower = xml.toLowerCase();
3243
+ const starts = findImplicitCallOpenIndices(lower);
3244
+ if (starts.length === 0) {
3245
+ return [];
3246
+ }
3247
+ const blocks = [];
3248
+ for (let i = 0; i < starts.length; i += 1) {
3249
+ const start = (_a = starts[i]) != null ? _a : 0;
3250
+ const end = (_b = starts[i + 1]) != null ? _b : xml.length;
3251
+ blocks.push(xml.slice(start, end));
3252
+ }
3253
+ return blocks;
3254
+ }
3255
+ function stripLeadingCallCloseTags(text) {
3256
+ let out = text;
3257
+ while (true) {
3258
+ const match = LEADING_CALL_CLOSE_TAG_RE.exec(out);
3259
+ if (!match) {
3260
+ return out;
3261
+ }
3262
+ out = out.slice(match[0].length);
3263
+ }
3264
+ }
3265
+ function getOpenTagNameLower(openTag) {
3266
+ var _a;
3267
+ const lowerOpenTag = openTag.toLowerCase();
3268
+ const lt = lowerOpenTag.indexOf("<");
3269
+ if (lt === -1) {
3270
+ return null;
3271
+ }
3272
+ let i = skipAsciiWhitespace(lowerOpenTag, lt + 1);
3273
+ if (i >= lowerOpenTag.length || lowerOpenTag[i] === "/") {
3274
+ return null;
3275
+ }
3276
+ const start = i;
3277
+ while (i < lowerOpenTag.length) {
3278
+ const ch = (_a = lowerOpenTag[i]) != null ? _a : "";
3279
+ if (isAsciiWhitespace(ch) || ch === ">" || ch === "/" || ch === "=") {
3280
+ break;
3281
+ }
3282
+ i += 1;
3283
+ }
3284
+ const tagName = lowerOpenTag.slice(start, i);
3285
+ return tagName.length > 0 ? tagName : null;
3286
+ }
3287
+ function splitImplicitCallAndTail(callBlock) {
3288
+ var _a;
3289
+ const openingTag = getOpeningTag(callBlock);
3290
+ const openingTagName = toSupportedCallEndTagName(
3291
+ openingTag ? getOpenTagNameLower(openingTag) : null
3292
+ );
3293
+ const lowerCallBlock = callBlock.toLowerCase();
3294
+ let consumed = 0;
3295
+ if (openingTag) {
3296
+ consumed = openingTag.length;
3297
+ if (openingTagName) {
3298
+ const close = findClosingTagEnd(lowerCallBlock, consumed, openingTagName);
3299
+ if (close) {
3300
+ consumed = Math.max(consumed, close.end);
3301
+ }
3302
+ }
3303
+ }
3304
+ let index = 0;
3305
+ while (true) {
3306
+ const lt = lowerCallBlock.indexOf("<", index);
3307
+ if (lt === -1) {
3308
+ break;
3309
+ }
3310
+ const parsed = parseQwen3CoderToolParserParamTagAt(
3311
+ callBlock,
3312
+ lowerCallBlock,
3313
+ lt,
3314
+ {
3315
+ allowEndOfString: true,
3316
+ callEndTagNameLower: openingTagName
3317
+ }
3318
+ );
3319
+ if (!parsed) {
3320
+ index = lt + 1;
3321
+ continue;
3322
+ }
3323
+ if (parsed.kind === "partial") {
3324
+ index = ((_a = parsed.openEnd) != null ? _a : lt) + 1;
3325
+ continue;
3326
+ }
3327
+ consumed = Math.max(consumed, parsed.end);
3328
+ index = parsed.end;
3329
+ }
3330
+ const clamped = Math.max(0, Math.min(consumed, callBlock.length));
3331
+ return {
3332
+ callContent: callBlock.slice(0, clamped),
3333
+ trailingText: callBlock.slice(clamped)
3334
+ };
3335
+ }
3336
+ function parseQwen3CoderToolParserCallBlocks(blocks, outerNameAttr) {
3337
+ const calls = [];
3338
+ for (const block of blocks) {
3339
+ const parsed = parseSingleFunctionCallXml(block, outerNameAttr);
3340
+ if (!parsed) {
3341
+ return null;
3342
+ }
3343
+ calls.push(parsed);
3344
+ }
3345
+ return calls;
3346
+ }
3347
+ function parseQwen3CoderToolParserClosedMatches(inner, outerNameAttr) {
3348
+ var _a, _b;
3349
+ const callBlockMatches = Array.from(inner.matchAll(CALL_BLOCK_RE));
3350
+ if (callBlockMatches.length === 0) {
3351
+ return void 0;
3352
+ }
3353
+ const closedBlocks = [];
3354
+ let lastClosedEnd = 0;
3355
+ for (const match of callBlockMatches) {
3356
+ const callBlock = (_a = match[0]) != null ? _a : "";
3357
+ const startIndex = (_b = match.index) != null ? _b : -1;
3358
+ if (!callBlock || startIndex < 0) {
3359
+ continue;
3360
+ }
3361
+ closedBlocks.push(callBlock);
3362
+ lastClosedEnd = startIndex + callBlock.length;
3363
+ }
3364
+ const closedCalls = parseQwen3CoderToolParserCallBlocks(
3365
+ closedBlocks,
3366
+ outerNameAttr
3367
+ );
3368
+ if (!closedCalls) {
3369
+ return null;
3370
+ }
3371
+ const trailingInner = inner.slice(lastClosedEnd);
3372
+ if (trailingInner.trim().length === 0) {
3373
+ return closedCalls;
3374
+ }
3375
+ const trailingBlocks = splitImplicitCallBlocks(trailingInner).filter(
3376
+ (b) => b.trim().length > 0
3377
+ );
3378
+ if (trailingBlocks.length === 0) {
3379
+ return closedCalls;
3380
+ }
3381
+ const trailingCalls = parseQwen3CoderToolParserCallBlocks(
3382
+ trailingBlocks,
3383
+ outerNameAttr
3384
+ );
3385
+ if (!trailingCalls) {
3386
+ return closedCalls;
3387
+ }
3388
+ return closedCalls.concat(trailingCalls);
3389
+ }
3390
+ function parseQwen3CoderToolParserToolCallSegment(segment) {
3391
+ var _a;
3392
+ const extracted = extractToolCallInnerXml(segment);
3393
+ if (!extracted) {
3394
+ return null;
3395
+ }
3396
+ const { inner, outerOpenTag } = extracted;
3397
+ const outerNameAttr = getAttributeValue(outerOpenTag, "name");
3398
+ const closedCalls = parseQwen3CoderToolParserClosedMatches(
3399
+ inner,
3400
+ outerNameAttr
3401
+ );
3402
+ if (closedCalls) {
3403
+ return closedCalls;
3404
+ }
3405
+ if (closedCalls === null) {
3406
+ return null;
3407
+ }
3408
+ const implicitBlocks = splitImplicitCallBlocks(inner).filter(
3409
+ (b) => b.trim().length > 0
3410
+ );
3411
+ if (implicitBlocks.length > 0) {
3412
+ return parseQwen3CoderToolParserCallBlocks(implicitBlocks, outerNameAttr);
3413
+ }
3414
+ const single = (_a = parseSingleFunctionCallXml(inner, outerNameAttr)) != null ? _a : parseSingleFunctionCallXml(segment, outerNameAttr);
3415
+ if (!single) {
3416
+ return null;
3417
+ }
3418
+ return [single];
3419
+ }
3420
+ function parseToolCallInput(input) {
3421
+ if (input == null) {
3422
+ return {};
3423
+ }
3424
+ try {
3425
+ return JSON.parse(input);
3426
+ } catch (e) {
3427
+ return input;
3428
+ }
3429
+ }
3430
+ function toQwen3CoderToolParserParamText(value) {
3431
+ if (typeof value === "string") {
3432
+ return value;
3433
+ }
3434
+ if (value === null) {
3435
+ return "None";
3436
+ }
3437
+ if (typeof value === "boolean") {
3438
+ return value ? "True" : "False";
3439
+ }
3440
+ if (value === void 0) {
3441
+ return "";
3442
+ }
3443
+ if (typeof value === "object") {
3444
+ return JSON.stringify(value);
3445
+ }
3446
+ return String(value);
3447
+ }
3448
+ function appendQwen3CoderToolParserParameter(lines, key, value) {
3449
+ const nameAttr = escapeXmlMinimalAttr(key, '"');
3450
+ const text = escapeXmlMinimalText(toQwen3CoderToolParserParamText(value));
3451
+ lines.push(` <parameter="${nameAttr}">${text}</parameter>`);
3452
+ }
3453
+ function appendQwen3CoderToolParserArgs(lines, args) {
3454
+ if (args && typeof args === "object" && !Array.isArray(args)) {
3455
+ for (const [key, value] of Object.entries(args)) {
3456
+ if (Array.isArray(value)) {
3457
+ for (const item of value) {
3458
+ appendQwen3CoderToolParserParameter(lines, key, item);
3459
+ }
3460
+ } else {
3461
+ appendQwen3CoderToolParserParameter(lines, key, value);
3462
+ }
3463
+ }
3464
+ return;
3465
+ }
3466
+ if (args !== void 0 && args !== null && args !== "") {
3467
+ appendQwen3CoderToolParserParameter(lines, "input", args);
3468
+ }
3469
+ }
3470
+ var qwen3CoderProtocol = () => ({
3471
+ formatTools({ tools, toolSystemPromptTemplate }) {
3472
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
3473
+ },
3474
+ formatToolCall(toolCall) {
3475
+ const args = parseToolCallInput(toolCall.input);
3476
+ const lines = ["<tool_call>"];
3477
+ lines.push(
3478
+ ` <function="${escapeXmlMinimalAttr(toolCall.toolName, '"')}">`
3479
+ );
3480
+ appendQwen3CoderToolParserArgs(lines, args);
3481
+ lines.push(" </function>");
3482
+ lines.push("</tool_call>");
3483
+ return lines.join("\n");
3484
+ },
3485
+ parseGeneratedText({ text, tools, options }) {
3486
+ const processedElements = [];
3487
+ const emitToolCalls = (calls) => {
3488
+ for (const call of calls) {
3489
+ processedElements.push({
3490
+ type: "tool-call",
3491
+ toolCallId: generateToolCallId(),
3492
+ toolName: call.toolName,
3493
+ input: stringifyToolInputWithSchema({
3494
+ tools,
3495
+ toolName: call.toolName,
3496
+ args: call.args
3497
+ })
3498
+ });
3499
+ }
3500
+ };
3501
+ const pushText = (value) => {
3502
+ if (value.length === 0) {
3503
+ return;
3504
+ }
3505
+ processedElements.push({ type: "text", text: value });
3506
+ };
3507
+ const tryEmitToolCallSegment = (segment, fallbackText = segment) => {
3508
+ var _a;
3509
+ const parsedCalls = parseQwen3CoderToolParserToolCallSegment(segment);
3510
+ if (!parsedCalls) {
3511
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3512
+ options,
3513
+ "Could not process Qwen3CoderToolParser XML tool call; keeping original text.",
3514
+ { toolCall: fallbackText }
3515
+ );
3516
+ processedElements.push({ type: "text", text: fallbackText });
3517
+ return false;
3518
+ }
3519
+ emitToolCalls(parsedCalls);
3520
+ return true;
3521
+ };
3522
+ const emitWrapperlessCallParseFailureAsText = (raw) => {
3523
+ var _a;
3524
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3525
+ options,
3526
+ "Could not process Qwen3CoderToolParser <function> call; keeping original text.",
3527
+ { toolCall: raw }
3528
+ );
3529
+ processedElements.push({ type: "text", text: raw });
3530
+ };
3531
+ const tryParseCallBlocksWithoutWrapperByImplicitStarts = (sourceText, starts) => {
3532
+ var _a, _b;
3533
+ let index = 0;
3534
+ for (let i = 0; i < starts.length; i += 1) {
3535
+ const startIndex = (_a = starts[i]) != null ? _a : -1;
3536
+ if (startIndex < 0) {
3537
+ continue;
3538
+ }
3539
+ const endIndex = (_b = starts[i + 1]) != null ? _b : sourceText.length;
3540
+ pushText(
3541
+ stripTrailingToolCallCloseTags(
3542
+ stripLeadingToolCallCloseTags(sourceText.slice(index, startIndex))
3543
+ )
3544
+ );
3545
+ const full = sourceText.slice(startIndex, endIndex);
3546
+ const { callContent, trailingText } = splitImplicitCallAndTail(full);
3547
+ const parsed = parseSingleFunctionCallXml(callContent, null);
3548
+ if (parsed) {
3549
+ emitToolCalls([parsed]);
3550
+ pushText(
3551
+ stripTrailingToolCallCloseTags(
3552
+ stripLeadingToolCallCloseTags(trailingText)
3553
+ )
3554
+ );
3555
+ } else {
3556
+ emitWrapperlessCallParseFailureAsText(full);
3557
+ }
3558
+ index = endIndex;
3559
+ }
3560
+ pushText(
3561
+ stripTrailingToolCallCloseTags(
3562
+ stripLeadingToolCallCloseTags(sourceText.slice(index))
3563
+ )
3564
+ );
3565
+ return true;
3566
+ };
3567
+ const tryParseCallBlocksWithoutWrapperByMatches = (sourceText, matches) => {
3568
+ var _a;
3569
+ let index = 0;
3570
+ for (const match of matches) {
3571
+ const full = match[0];
3572
+ const startIndex = (_a = match.index) != null ? _a : -1;
3573
+ if (!full || startIndex < 0) {
3574
+ continue;
3575
+ }
3576
+ pushText(
3577
+ stripTrailingToolCallCloseTags(
3578
+ stripLeadingToolCallCloseTags(sourceText.slice(index, startIndex))
3579
+ )
3580
+ );
3581
+ const parsed = parseSingleFunctionCallXml(full, null);
3582
+ if (parsed) {
3583
+ emitToolCalls([parsed]);
3584
+ } else {
3585
+ emitWrapperlessCallParseFailureAsText(full);
3586
+ }
3587
+ index = startIndex + full.length;
3588
+ }
3589
+ const trailing = sourceText.slice(index);
3590
+ const trailingStarts = findImplicitCallOpenIndices(
3591
+ trailing.toLowerCase()
3592
+ );
3593
+ if (trailingStarts.length > 0) {
3594
+ return tryParseCallBlocksWithoutWrapperByImplicitStarts(
3595
+ trailing,
3596
+ trailingStarts
3597
+ );
3598
+ }
3599
+ pushText(
3600
+ stripTrailingToolCallCloseTags(stripLeadingToolCallCloseTags(trailing))
3601
+ );
3602
+ return true;
3603
+ };
3604
+ const tryParseCallBlocksWithoutWrapperText = (sourceText) => {
3605
+ const matches = Array.from(sourceText.matchAll(CALL_BLOCK_RE));
3606
+ if (matches.length > 0) {
3607
+ return tryParseCallBlocksWithoutWrapperByMatches(sourceText, matches);
3608
+ }
3609
+ const starts = findImplicitCallOpenIndices(sourceText.toLowerCase());
3610
+ if (starts.length === 0) {
3611
+ return false;
3612
+ }
3613
+ return tryParseCallBlocksWithoutWrapperByImplicitStarts(
3614
+ sourceText,
3615
+ starts
3616
+ );
3617
+ };
3618
+ const pushTextOrParseWrapperlessCalls = (segment) => {
3619
+ if (segment.length === 0) {
3620
+ return;
3621
+ }
3622
+ if (!tryParseCallBlocksWithoutWrapperText(segment)) {
3623
+ pushText(segment);
3624
+ }
3625
+ };
3626
+ const handleCompleteToolCallRemainder = (remainder) => {
3627
+ if (!remainder) {
3628
+ return;
3629
+ }
3630
+ const lowerRemainder = remainder.toLowerCase();
3631
+ const trailingIndex = lowerRemainder.indexOf("<tool_call");
3632
+ if (trailingIndex === -1) {
3633
+ pushTextOrParseWrapperlessCalls(remainder);
3634
+ return;
3635
+ }
3636
+ pushTextOrParseWrapperlessCalls(remainder.slice(0, trailingIndex));
3637
+ const trailing = remainder.slice(trailingIndex);
3638
+ const synthetic = TOOL_CALL_CLOSE_RE.test(trailing) ? trailing : `${trailing}</tool_call>`;
3639
+ tryEmitToolCallSegment(synthetic, trailing);
3640
+ };
3641
+ const tryParseCompleteToolCallBlocks = () => {
3642
+ var _a;
3643
+ const matches = Array.from(text.matchAll(TOOL_CALL_BLOCK_RE));
3644
+ if (matches.length === 0) {
3645
+ return false;
3646
+ }
3647
+ let index = 0;
3648
+ for (const match of matches) {
3649
+ const full = match[0];
3650
+ const startIndex = (_a = match.index) != null ? _a : -1;
3651
+ if (!full || startIndex < 0) {
3652
+ continue;
3653
+ }
3654
+ pushTextOrParseWrapperlessCalls(text.slice(index, startIndex));
3655
+ tryEmitToolCallSegment(full);
3656
+ index = startIndex + full.length;
3657
+ }
3658
+ handleCompleteToolCallRemainder(text.slice(index));
3659
+ return true;
3660
+ };
3661
+ const tryParseIncompleteToolCall = () => {
3662
+ const lowerText = text.toLowerCase();
3663
+ const startIndex = lowerText.indexOf("<tool_call");
3664
+ if (startIndex === -1) {
3665
+ return false;
3666
+ }
3667
+ pushTextOrParseWrapperlessCalls(text.slice(0, startIndex));
3668
+ const trailing = text.slice(startIndex);
3669
+ const synthetic = TOOL_CALL_CLOSE_RE.test(trailing) ? trailing : `${trailing}</tool_call>`;
3670
+ tryEmitToolCallSegment(synthetic, trailing);
3671
+ return true;
3672
+ };
3673
+ const tryParseCallBlocksWithoutWrapper = () => {
3674
+ return tryParseCallBlocksWithoutWrapperText(text);
3675
+ };
3676
+ const tryParseSingleFunctionCall = () => {
3677
+ const lowerText = text.toLowerCase();
3678
+ const startIndex = lowerText.indexOf("<function");
3679
+ if (startIndex === -1) {
3680
+ return false;
3681
+ }
3682
+ pushText(stripTrailingToolCallCloseTags(text.slice(0, startIndex)));
3683
+ const trailing = stripLeadingToolCallCloseTags(text.slice(startIndex));
3684
+ const parsed = parseSingleFunctionCallXml(trailing, null);
3685
+ if (!parsed) {
3686
+ processedElements.push({ type: "text", text: trailing });
3687
+ return true;
3688
+ }
3689
+ emitToolCalls([parsed]);
3690
+ return true;
3691
+ };
3692
+ if (tryParseCompleteToolCallBlocks()) {
3693
+ return processedElements;
3694
+ }
3695
+ if (tryParseIncompleteToolCall()) {
3696
+ return processedElements;
3697
+ }
3698
+ if (tryParseCallBlocksWithoutWrapper()) {
3699
+ return processedElements;
3700
+ }
3701
+ if (tryParseSingleFunctionCall()) {
3702
+ return processedElements;
3703
+ }
3704
+ return [{ type: "text", text }];
3705
+ },
3706
+ extractToolCallSegments({ text }) {
3707
+ return Array.from(text.matchAll(TOOL_CALL_BLOCK_RE)).map((m) => m[0]).filter((s) => Boolean(s));
3708
+ },
3709
+ createStreamParser({ tools, options }) {
3710
+ const toolCallStartPrefixLower = "<tool_call";
3711
+ const implicitCallPrefixesLower = [
3712
+ "<function",
3713
+ "<call",
3714
+ "<tool",
3715
+ "<invoke"
3716
+ ];
3717
+ let buffer = "";
3718
+ let toolCall = null;
3719
+ let implicitCall = null;
3720
+ let implicitCallOpenTag = null;
3721
+ let currentTextId = null;
3722
+ let hasEmittedTextStart = false;
3723
+ const flushText = createFlushTextHandler(
3724
+ () => currentTextId,
3725
+ (id) => {
3726
+ currentTextId = id;
3727
+ },
3728
+ () => hasEmittedTextStart,
3729
+ (value) => {
3730
+ hasEmittedTextStart = value;
3731
+ }
3732
+ );
3733
+ const maybeEmitToolInputStart = (controller, callState) => {
3734
+ if (callState.hasEmittedStart) {
3735
+ return;
3736
+ }
3737
+ const toolName = callState.toolName;
3738
+ if (!toolName || toolName.trim().length === 0) {
3739
+ return;
3740
+ }
3741
+ flushText(controller);
3742
+ controller.enqueue({
3743
+ type: "tool-input-start",
3744
+ id: callState.toolCallId,
3745
+ toolName
3746
+ });
3747
+ callState.hasEmittedStart = true;
3748
+ };
3749
+ const maybeEmitToolInputProgress = (controller, callState) => {
3750
+ if (!callState.hasEmittedStart) {
3751
+ return;
3752
+ }
3753
+ const toolName = callState.toolName;
3754
+ if (!toolName) {
3755
+ return;
3756
+ }
3757
+ const argsForProgress = mergeArgsWithPartialParam(
3758
+ callState.args,
3759
+ callState.partialParam
3760
+ );
3761
+ const fullInput = stringifyToolInputWithSchema({
3762
+ tools,
3763
+ toolName,
3764
+ args: argsForProgress
3765
+ });
3766
+ if (fullInput === "{}") {
3767
+ return;
3768
+ }
3769
+ emitToolInputProgressDelta({
3770
+ controller,
3771
+ id: callState.toolCallId,
3772
+ state: callState,
3773
+ fullInput
3774
+ });
3775
+ };
3776
+ const finalizeCall = (controller, callState, fallbackToolName, rawToolCallText = null) => {
3777
+ var _a, _b;
3778
+ const resolvedToolName = (_a = callState.toolName) != null ? _a : fallbackToolName;
3779
+ if (!resolvedToolName || resolvedToolName.trim().length === 0) {
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
+ });
3791
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
3792
+ options,
3793
+ shouldEmitRaw && rawToolCallText ? "Could not resolve Qwen3CoderToolParser tool name for tool call; emitting original text." : "Could not resolve Qwen3CoderToolParser tool name for tool call",
3794
+ {
3795
+ toolCallId: callState.toolCallId,
3796
+ toolCall: rawToolCallText
3797
+ }
3798
+ );
3799
+ return false;
3800
+ }
3801
+ callState.toolName = resolvedToolName;
3802
+ maybeEmitToolInputStart(controller, callState);
3803
+ maybeEmitToolInputProgress(controller, callState);
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;
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
+ });
3834
+ const closeTagCache = /* @__PURE__ */ new Map();
3835
+ const getCloseTagPattern = (endTagName) => {
3836
+ const cached = closeTagCache.get(endTagName);
3837
+ if (cached) {
3838
+ return cached;
3839
+ }
3840
+ const created = new RegExp(
3841
+ `<\\s*\\/\\s*${escapeRegExp(endTagName)}\\s*>`,
3842
+ "i"
3843
+ );
3844
+ closeTagCache.set(endTagName, created);
3845
+ return created;
3846
+ };
3847
+ const getNextCallStartInBuffer = (callState) => {
3848
+ var _a;
3849
+ if (callState.endTagName === "tool_call") {
3850
+ return -1;
3851
+ }
3852
+ const match = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE.exec(
3853
+ callState.buffer
3854
+ );
3855
+ return (_a = match == null ? void 0 : match.index) != null ? _a : -1;
3856
+ };
3857
+ const finalizeStreamingCall = (controller, callState, fallbackToolName, remainder) => {
3858
+ const rawToolCallText = remainder.length > 0 && callState.raw.endsWith(remainder) ? callState.raw.slice(0, -remainder.length) : callState.raw;
3859
+ const ok = finalizeCall(
3860
+ controller,
3861
+ callState,
3862
+ fallbackToolName,
3863
+ rawToolCallText
3864
+ );
3865
+ if (ok && toolCall) {
3866
+ toolCall.emittedToolCallCount += 1;
3867
+ }
3868
+ };
3869
+ const consumeCallAtNextBoundary = (controller, callState, fallbackToolName, nextCallStart) => {
3870
+ const beforeNextCall = callState.buffer.slice(0, nextCallStart);
3871
+ const afterNextCall = callState.buffer.slice(nextCallStart);
3872
+ callState.buffer = parseStreamingCallContent(
3873
+ controller,
3874
+ callState,
3875
+ beforeNextCall,
3876
+ true
3877
+ );
3878
+ finalizeStreamingCall(
3879
+ controller,
3880
+ callState,
3881
+ fallbackToolName,
3882
+ afterNextCall
3883
+ );
3884
+ return { done: true, remainder: afterNextCall };
3885
+ };
3886
+ const consumeCall = (controller, callState, incoming, fallbackToolName) => {
3887
+ var _a, _b, _c;
3888
+ callState.buffer += incoming;
3889
+ callState.raw += incoming;
3890
+ const closeMatch = getCloseTagPattern(callState.endTagName).exec(
3891
+ callState.buffer
3892
+ );
3893
+ const closeStart = (_a = closeMatch == null ? void 0 : closeMatch.index) != null ? _a : -1;
3894
+ const nextCallStart = getNextCallStartInBuffer(callState);
3895
+ const shouldCloseAtNextBoundary = nextCallStart !== -1 && (closeStart === -1 || nextCallStart < closeStart);
3896
+ if (shouldCloseAtNextBoundary) {
3897
+ return consumeCallAtNextBoundary(
3898
+ controller,
3899
+ callState,
3900
+ fallbackToolName,
3901
+ nextCallStart
3902
+ );
3903
+ }
3904
+ if (!closeMatch) {
3905
+ callState.buffer = parseStreamingCallContent(
3906
+ controller,
3907
+ callState,
3908
+ callState.buffer,
3909
+ false
3910
+ );
3911
+ return { done: false, remainder: "" };
3912
+ }
3913
+ const closeEnd = closeStart + ((_c = (_b = closeMatch[0]) == null ? void 0 : _b.length) != null ? _c : 0);
3914
+ const beforeClose = callState.buffer.slice(0, closeStart);
3915
+ const afterClose = callState.buffer.slice(closeEnd);
3916
+ parseStreamingCallContent(controller, callState, beforeClose, true);
3917
+ callState.buffer = "";
3918
+ finalizeStreamingCall(
3919
+ controller,
3920
+ callState,
3921
+ fallbackToolName,
3922
+ afterClose
3923
+ );
3924
+ return { done: true, remainder: afterClose };
3925
+ };
3926
+ const finalizeCallAtFinish = (controller, callState, fallbackToolName) => {
3927
+ callState.buffer = parseStreamingCallContent(
3928
+ controller,
3929
+ callState,
3930
+ callState.buffer,
3931
+ true
3932
+ );
3933
+ const trailingText = stripLeadingCallCloseTags(callState.buffer);
3934
+ callState.buffer = "";
3935
+ const ok = finalizeCall(controller, callState, fallbackToolName, null);
3936
+ return {
3937
+ ok,
3938
+ trailingText
3939
+ };
3940
+ };
3941
+ const flushSafeTextPrefix = (controller) => {
3942
+ const lower = buffer.toLowerCase();
3943
+ const potentialIndices = [
3944
+ getPotentialStartIndex(lower, toolCallStartPrefixLower),
3945
+ ...implicitCallPrefixesLower.map(
3946
+ (prefix) => getPotentialStartIndex(lower, prefix)
3947
+ )
3948
+ ].filter((value) => value != null);
3949
+ const potentialIndex = potentialIndices.length > 0 ? Math.min(...potentialIndices) : null;
3950
+ if (potentialIndex == null) {
3951
+ if (buffer.length > 0) {
3952
+ flushText(controller, buffer);
3953
+ buffer = "";
3954
+ }
3955
+ return;
3956
+ }
3957
+ if (potentialIndex > 0) {
3958
+ flushText(controller, buffer.slice(0, potentialIndex));
3959
+ buffer = buffer.slice(potentialIndex);
3960
+ }
3961
+ };
3962
+ const stripLeadingToolCallCloseTagsFromBuffer = () => {
3963
+ if (!buffer) {
3964
+ return;
3965
+ }
3966
+ const stripped = stripLeadingToolCallCloseTags(buffer);
3967
+ if (stripped !== buffer) {
3968
+ buffer = stripped;
3969
+ }
3970
+ };
3971
+ const startToolCallIfPresent = (_controller) => {
3972
+ if (toolCall) {
3973
+ return;
3974
+ }
3975
+ if (implicitCall) {
3976
+ return;
3977
+ }
3978
+ const lower = buffer.toLowerCase();
3979
+ const startIndex = getPotentialStartIndex(
3980
+ lower,
3981
+ toolCallStartPrefixLower
3982
+ );
3983
+ if (startIndex == null || startIndex !== 0) {
3984
+ return;
3985
+ }
3986
+ const gtIndex = buffer.indexOf(">");
3987
+ if (gtIndex === -1) {
3988
+ return;
3989
+ }
3990
+ const openTag = buffer.slice(0, gtIndex + 1);
3991
+ if (!TOOL_CALL_OPEN_RE.test(openTag)) {
3992
+ return;
3993
+ }
3994
+ toolCall = {
3995
+ outerOpenTag: openTag,
3996
+ outerNameAttr: getAttributeValue(openTag, "name"),
3997
+ raw: openTag,
3998
+ mode: "unknown",
3999
+ innerBuffer: "",
4000
+ activeCall: null,
4001
+ emittedToolCallCount: 0
4002
+ };
4003
+ const remainder = buffer.slice(gtIndex + 1);
4004
+ buffer = "";
4005
+ if (remainder.length > 0) {
4006
+ toolCall.raw += remainder;
4007
+ toolCall.innerBuffer += remainder;
4008
+ }
4009
+ };
4010
+ const startImplicitCallIfPresent = (controller) => {
4011
+ var _a, _b, _c, _d;
4012
+ if (toolCall || implicitCall) {
4013
+ return;
4014
+ }
4015
+ const match = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE.exec(buffer);
4016
+ const startIndex = (_a = match == null ? void 0 : match.index) != null ? _a : -1;
4017
+ const openTag = (_b = match == null ? void 0 : match[0]) != null ? _b : "";
4018
+ const callTagName = ((_c = match == null ? void 0 : match[1]) != null ? _c : "").toLowerCase();
4019
+ if (!match || startIndex !== 0 || !openTag || !callTagName) {
4020
+ return;
4021
+ }
4022
+ const inlineToolName = (_d = getAttributeValue(openTag, "name")) != null ? _d : getShorthandValue(openTag);
4023
+ if (!inlineToolName || inlineToolName.trim().length === 0) {
4024
+ return;
4025
+ }
4026
+ const selfClosing = QWEN3CODER_TOOL_PARSER_STREAM_SELF_CLOSING_TAG_RE.test(openTag);
4027
+ buffer = buffer.slice(openTag.length);
4028
+ const newCall = {
4029
+ endTagName: callTagName,
4030
+ toolCallId: generateToolCallId(),
4031
+ toolName: inlineToolName,
4032
+ hasEmittedStart: false,
4033
+ partialParam: null,
4034
+ emittedInput: "",
4035
+ raw: openTag,
4036
+ args: {},
4037
+ buffer: ""
4038
+ };
4039
+ maybeEmitToolInputStart(controller, newCall);
4040
+ if (selfClosing) {
4041
+ finalizeCall(controller, newCall, inlineToolName, newCall.raw);
4042
+ return;
4043
+ }
4044
+ implicitCall = newCall;
4045
+ implicitCallOpenTag = openTag;
4046
+ };
4047
+ const processImplicitCall = (controller) => {
4048
+ while (implicitCall) {
4049
+ const callState = implicitCall;
4050
+ const { done, remainder } = consumeCall(
4051
+ controller,
4052
+ callState,
4053
+ buffer,
4054
+ null
4055
+ );
4056
+ buffer = "";
4057
+ if (!done) {
4058
+ return;
4059
+ }
4060
+ implicitCall = null;
4061
+ implicitCallOpenTag = null;
4062
+ if (remainder.length > 0) {
4063
+ buffer = remainder;
4064
+ }
4065
+ stripLeadingToolCallCloseTagsFromBuffer();
4066
+ flushSafeTextPrefix(controller);
4067
+ startToolCallIfPresent(controller);
4068
+ if (toolCall) {
4069
+ processToolCall2(controller);
4070
+ return;
4071
+ }
4072
+ startImplicitCallIfPresent(controller);
4073
+ }
4074
+ };
4075
+ const drainStarts = (controller) => {
4076
+ while (true) {
4077
+ if (toolCall || implicitCall) {
4078
+ return;
4079
+ }
4080
+ const before = buffer;
4081
+ startToolCallIfPresent(controller);
4082
+ if (toolCall) {
4083
+ processToolCall2(controller);
4084
+ return;
4085
+ }
4086
+ startImplicitCallIfPresent(controller);
4087
+ if (implicitCall) {
4088
+ processImplicitCall(controller);
4089
+ return;
4090
+ }
4091
+ if (buffer === before) {
4092
+ return;
4093
+ }
4094
+ stripLeadingToolCallCloseTagsFromBuffer();
4095
+ flushSafeTextPrefix(controller);
4096
+ }
4097
+ };
4098
+ const processToolCall2 = (controller) => {
4099
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
4100
+ while (toolCall) {
4101
+ if (toolCall.mode === "unknown") {
4102
+ const callMatch = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_START_RE.exec(
4103
+ toolCall.innerBuffer
4104
+ );
4105
+ const signalMatch = QWEN3CODER_TOOL_PARSER_STREAM_NAME_OR_PARAM_SIGNAL_RE.exec(
4106
+ toolCall.innerBuffer
4107
+ );
4108
+ if (callMatch && (!signalMatch || ((_a = callMatch.index) != null ? _a : 0) < ((_b = signalMatch.index) != null ? _b : 0))) {
4109
+ toolCall.mode = "multi";
4110
+ } else if (signalMatch) {
4111
+ toolCall.mode = "single";
4112
+ const activeCall = {
4113
+ endTagName: "tool_call",
4114
+ toolCallId: generateToolCallId(),
4115
+ toolName: toolCall.outerNameAttr,
4116
+ hasEmittedStart: false,
4117
+ partialParam: null,
4118
+ emittedInput: "",
4119
+ raw: toolCall.outerOpenTag,
4120
+ args: {},
4121
+ buffer: ""
4122
+ };
4123
+ toolCall.activeCall = activeCall;
4124
+ if (toolCall.outerNameAttr) {
4125
+ maybeEmitToolInputStart(controller, activeCall);
4126
+ }
4127
+ } else {
4128
+ return;
4129
+ }
4130
+ }
4131
+ if (toolCall.mode === "single") {
4132
+ const callState = toolCall.activeCall;
4133
+ if (!callState) {
4134
+ return;
4135
+ }
4136
+ const { done, remainder } = consumeCall(
4137
+ controller,
4138
+ callState,
4139
+ toolCall.innerBuffer,
4140
+ toolCall.outerNameAttr
4141
+ );
4142
+ toolCall.innerBuffer = "";
4143
+ if (!done) {
4144
+ return;
4145
+ }
4146
+ toolCall = null;
4147
+ if (remainder.length > 0) {
4148
+ buffer = remainder + buffer;
4149
+ }
4150
+ flushSafeTextPrefix(controller);
4151
+ startToolCallIfPresent(controller);
4152
+ continue;
4153
+ }
4154
+ if (toolCall.mode === "multi") {
4155
+ if (toolCall.activeCall) {
4156
+ const callState = toolCall.activeCall;
4157
+ const { done, remainder } = consumeCall(
4158
+ controller,
4159
+ callState,
4160
+ toolCall.innerBuffer,
4161
+ toolCall.outerNameAttr
4162
+ );
4163
+ toolCall.innerBuffer = "";
4164
+ if (!done) {
4165
+ return;
4166
+ }
4167
+ toolCall.activeCall = null;
4168
+ toolCall.innerBuffer = remainder;
4169
+ continue;
4170
+ }
4171
+ const closeMatch = QWEN3CODER_TOOL_PARSER_STREAM_TOOL_CALL_CLOSE_TAG_RE.exec(
4172
+ toolCall.innerBuffer
4173
+ );
4174
+ const callOpenMatch = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE.exec(
4175
+ toolCall.innerBuffer
4176
+ );
4177
+ if (!(closeMatch || callOpenMatch)) {
4178
+ return;
4179
+ }
4180
+ const closeIndex = (_c = closeMatch == null ? void 0 : closeMatch.index) != null ? _c : -1;
4181
+ const callIndex = (_d = callOpenMatch == null ? void 0 : callOpenMatch.index) != null ? _d : -1;
4182
+ const hasClose = closeIndex !== -1;
4183
+ const hasCall = callIndex !== -1;
4184
+ const chooseClose = hasClose && (!hasCall || closeIndex < callIndex);
4185
+ const nextIndex = chooseClose ? closeIndex : callIndex;
4186
+ if (nextIndex > 0) {
4187
+ toolCall.innerBuffer = toolCall.innerBuffer.slice(nextIndex);
4188
+ }
4189
+ if (chooseClose) {
4190
+ const matchLen = (_f = (_e = closeMatch == null ? void 0 : closeMatch[0]) == null ? void 0 : _e.length) != null ? _f : 0;
4191
+ const remainder = toolCall.innerBuffer.slice(matchLen);
4192
+ toolCall = null;
4193
+ if (remainder.length > 0) {
4194
+ buffer = remainder + buffer;
4195
+ }
4196
+ flushSafeTextPrefix(controller);
4197
+ startToolCallIfPresent(controller);
4198
+ continue;
4199
+ }
4200
+ if (!callOpenMatch) {
4201
+ return;
4202
+ }
4203
+ const openTag = (_g = callOpenMatch[0]) != null ? _g : "";
4204
+ const callTagName = ((_h = callOpenMatch[1]) != null ? _h : "").toLowerCase();
4205
+ const rest = toolCall.innerBuffer.slice(openTag.length);
4206
+ const selfClosing = QWEN3CODER_TOOL_PARSER_STREAM_SELF_CLOSING_TAG_RE.test(openTag);
4207
+ if (selfClosing) {
4208
+ const toolNameAttr2 = (_j = (_i = getAttributeValue(openTag, "name")) != null ? _i : getShorthandValue(openTag)) != null ? _j : toolCall.outerNameAttr;
4209
+ const immediateCall = {
4210
+ endTagName: callTagName,
4211
+ toolCallId: generateToolCallId(),
4212
+ toolName: toolNameAttr2,
4213
+ hasEmittedStart: false,
4214
+ partialParam: null,
4215
+ emittedInput: "",
4216
+ raw: openTag,
4217
+ args: {},
4218
+ buffer: ""
4219
+ };
4220
+ const ok = finalizeCall(
4221
+ controller,
4222
+ immediateCall,
4223
+ toolNameAttr2,
4224
+ immediateCall.raw
4225
+ );
4226
+ if (ok) {
4227
+ toolCall.emittedToolCallCount += 1;
4228
+ }
4229
+ toolCall.innerBuffer = rest;
4230
+ continue;
4231
+ }
4232
+ const toolNameAttr = (_k = getAttributeValue(openTag, "name")) != null ? _k : getShorthandValue(openTag);
4233
+ const newCall = {
4234
+ endTagName: callTagName,
4235
+ toolCallId: generateToolCallId(),
4236
+ toolName: toolNameAttr,
4237
+ hasEmittedStart: false,
4238
+ partialParam: null,
4239
+ emittedInput: "",
4240
+ raw: openTag,
4241
+ args: {},
4242
+ buffer: ""
4243
+ };
4244
+ if (toolNameAttr) {
4245
+ maybeEmitToolInputStart(controller, newCall);
4246
+ }
4247
+ toolCall.activeCall = newCall;
4248
+ toolCall.innerBuffer = rest;
4249
+ }
4250
+ }
4251
+ };
4252
+ const reportUnfinishedToolCallAtFinish = (controller, rawToolCall) => {
4253
+ var _a;
4254
+ const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
4255
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4256
+ options,
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.",
4258
+ { toolCall: rawToolCall }
4259
+ );
4260
+ if (shouldEmitRaw) {
4261
+ flushText(controller, rawToolCall);
4262
+ }
4263
+ };
4264
+ const reportUnfinishedImplicitCallAtFinish = (controller, rawCallText) => {
4265
+ var _a;
4266
+ const shouldEmitRaw = shouldEmitRawToolCallTextOnError(options);
4267
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4268
+ options,
4269
+ shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser call block at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser call block at finish.",
4270
+ { toolCall: rawCallText }
4271
+ );
4272
+ if (shouldEmitRaw) {
4273
+ flushText(controller, rawCallText);
4274
+ }
4275
+ };
4276
+ const handleFinish = (controller) => {
4277
+ var _a, _b;
4278
+ if (toolCall) {
4279
+ processToolCall2(controller);
4280
+ if (toolCall) {
4281
+ if (toolCall.mode === "unknown") {
4282
+ const callMatch = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_START_RE.exec(
4283
+ toolCall.innerBuffer
4284
+ );
4285
+ const signalMatch = QWEN3CODER_TOOL_PARSER_STREAM_NAME_OR_PARAM_SIGNAL_RE.exec(
4286
+ toolCall.innerBuffer
4287
+ );
4288
+ if (callMatch && (!signalMatch || ((_a = callMatch.index) != null ? _a : 0) < ((_b = signalMatch.index) != null ? _b : 0))) {
4289
+ toolCall.mode = "multi";
4290
+ } else if (signalMatch) {
4291
+ toolCall.mode = "single";
4292
+ toolCall.activeCall = {
4293
+ endTagName: "tool_call",
4294
+ toolCallId: generateToolCallId(),
4295
+ toolName: toolCall.outerNameAttr,
4296
+ hasEmittedStart: false,
4297
+ partialParam: null,
4298
+ emittedInput: "",
4299
+ raw: toolCall.outerOpenTag,
4300
+ args: {},
4301
+ buffer: ""
4302
+ };
4303
+ }
4304
+ }
4305
+ if (toolCall.mode === "single" && toolCall.activeCall) {
4306
+ toolCall.activeCall.buffer += toolCall.innerBuffer;
4307
+ toolCall.innerBuffer = "";
4308
+ const result = finalizeCallAtFinish(
4309
+ controller,
4310
+ toolCall.activeCall,
4311
+ toolCall.outerNameAttr
4312
+ );
4313
+ if (result.ok) {
4314
+ toolCall.emittedToolCallCount += 1;
4315
+ }
4316
+ const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError(options);
4317
+ if (shouldFlushTrailingText && result.trailingText.length > 0) {
4318
+ flushText(controller, result.trailingText);
4319
+ }
4320
+ if (!result.ok && toolCall.emittedToolCallCount === 0) {
4321
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4322
+ }
4323
+ } else if (toolCall.mode === "multi") {
4324
+ if (toolCall.activeCall) {
4325
+ const result = finalizeCallAtFinish(
4326
+ controller,
4327
+ toolCall.activeCall,
4328
+ toolCall.outerNameAttr
4329
+ );
4330
+ if (result.ok) {
4331
+ toolCall.emittedToolCallCount += 1;
4332
+ }
4333
+ const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError(options);
4334
+ if (shouldFlushTrailingText && result.trailingText.length > 0) {
4335
+ flushText(controller, result.trailingText);
4336
+ }
4337
+ if (!result.ok && toolCall.emittedToolCallCount === 0) {
4338
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4339
+ }
4340
+ toolCall.activeCall = null;
4341
+ } else if (toolCall.emittedToolCallCount === 0) {
4342
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4343
+ }
4344
+ } else {
4345
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
2240
4346
  }
4347
+ toolCall = null;
2241
4348
  }
2242
- });
2243
- },
2244
- extractToolCallSegments({ text, tools }) {
2245
- const toolNames = tools.map((t) => t.name).filter(Boolean);
2246
- if (toolNames.length === 0) {
2247
- return [];
2248
4349
  }
2249
- return findToolCalls(text, toolNames).map((tc) => tc.segment);
2250
- }
2251
- };
2252
- };
4350
+ if (implicitCall) {
4351
+ const callState = implicitCall;
4352
+ const openTag = implicitCallOpenTag;
4353
+ implicitCall = null;
4354
+ implicitCallOpenTag = null;
4355
+ const result = finalizeCallAtFinish(controller, callState, null);
4356
+ const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError(options);
4357
+ if (shouldFlushTrailingText && result.trailingText.length > 0) {
4358
+ flushText(controller, result.trailingText);
4359
+ }
4360
+ if (!result.ok && openTag) {
4361
+ reportUnfinishedImplicitCallAtFinish(
4362
+ controller,
4363
+ callState.raw || openTag + callState.buffer
4364
+ );
4365
+ }
4366
+ } else {
4367
+ stripLeadingToolCallCloseTagsFromBuffer();
4368
+ flushSafeTextPrefix(controller);
4369
+ drainStarts(controller);
4370
+ }
4371
+ if (buffer.length > 0) {
4372
+ flushText(controller, buffer);
4373
+ buffer = "";
4374
+ }
4375
+ flushText(controller);
4376
+ };
4377
+ const handlePassthroughChunk = (controller, chunk) => {
4378
+ if (!toolCall && buffer) {
4379
+ flushText(controller, buffer);
4380
+ buffer = "";
4381
+ }
4382
+ controller.enqueue(chunk);
4383
+ };
4384
+ const handleTextDeltaChunk = (controller, delta) => {
4385
+ if (toolCall) {
4386
+ toolCall.raw += delta;
4387
+ toolCall.innerBuffer += delta;
4388
+ processToolCall2(controller);
4389
+ return;
4390
+ }
4391
+ if (implicitCall) {
4392
+ const callState = implicitCall;
4393
+ const { done, remainder } = consumeCall(
4394
+ controller,
4395
+ callState,
4396
+ delta,
4397
+ null
4398
+ );
4399
+ if (!done) {
4400
+ return;
4401
+ }
4402
+ implicitCall = null;
4403
+ implicitCallOpenTag = null;
4404
+ if (remainder.length > 0) {
4405
+ buffer = remainder + buffer;
4406
+ }
4407
+ stripLeadingToolCallCloseTagsFromBuffer();
4408
+ flushSafeTextPrefix(controller);
4409
+ drainStarts(controller);
4410
+ return;
4411
+ }
4412
+ buffer += delta;
4413
+ stripLeadingToolCallCloseTagsFromBuffer();
4414
+ flushSafeTextPrefix(controller);
4415
+ drainStarts(controller);
4416
+ };
4417
+ const handleTransformChunk = (controller, chunk) => {
4418
+ if (chunk.type === "finish") {
4419
+ handleFinish(controller);
4420
+ controller.enqueue(chunk);
4421
+ return;
4422
+ }
4423
+ if (chunk.type !== "text-delta") {
4424
+ handlePassthroughChunk(controller, chunk);
4425
+ return;
4426
+ }
4427
+ const delta = chunk.delta;
4428
+ if (!delta) {
4429
+ return;
4430
+ }
4431
+ handleTextDeltaChunk(controller, delta);
4432
+ };
4433
+ return new TransformStream({
4434
+ transform(chunk, controller) {
4435
+ handleTransformChunk(controller, chunk);
4436
+ },
4437
+ flush(controller) {
4438
+ handleFinish(controller);
4439
+ }
4440
+ });
4441
+ }
4442
+ });
4443
+ var uiTarsXmlProtocol = qwen3CoderProtocol;
4444
+ var Qwen3CoderToolParser = qwen3CoderProtocol;
2253
4445
 
2254
- // src/core/protocols/yaml-protocol.ts
4446
+ // src/core/protocols/yaml-xml-protocol.ts
2255
4447
  import YAML from "yaml";
2256
- function shouldEmitRawToolCallTextOnError3(options) {
2257
- return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
2258
- }
2259
- var selfClosingTagCache2 = /* @__PURE__ */ new Map();
2260
- function getSelfClosingTagPattern2(toolName) {
2261
- let pattern = selfClosingTagCache2.get(toolName);
2262
- if (!pattern) {
2263
- pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
2264
- selfClosingTagCache2.set(toolName, pattern);
2265
- }
2266
- return pattern;
2267
- }
2268
4448
  var LEADING_WHITESPACE_RE = /^(\s*)/;
2269
4449
  var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
2270
4450
  var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
@@ -2452,7 +4632,7 @@ function stabilizeParsedValueForStreamProgress(value, source) {
2452
4632
  }
2453
4633
  return trimTrailingNewlineInUnknown(value);
2454
4634
  }
2455
- function findClosingTagEnd(text, contentStart, toolName) {
4635
+ function findClosingTagEnd2(text, contentStart, toolName) {
2456
4636
  let pos = contentStart;
2457
4637
  let depth = 1;
2458
4638
  while (pos < text.length) {
@@ -2512,34 +4692,19 @@ function findClosingTagEnd(text, contentStart, toolName) {
2512
4692
  }
2513
4693
  return -1;
2514
4694
  }
2515
- function findEarliestTagPosition(openIdx, selfIdx) {
2516
- const hasSelf = selfIdx !== -1;
2517
- const hasOpen = openIdx !== -1;
2518
- if (hasSelf && (!hasOpen || selfIdx < openIdx)) {
2519
- return { tagStart: selfIdx, isSelfClosing: true };
2520
- }
2521
- return { tagStart: openIdx, isSelfClosing: false };
2522
- }
2523
4695
  function collectToolCallsForName(text, toolName) {
2524
4696
  const toolCalls = [];
2525
4697
  let searchIndex = 0;
2526
4698
  const startTag = `<${toolName}>`;
2527
- const selfTagRegex = getSelfClosingTagPattern2(toolName);
2528
4699
  while (searchIndex < text.length) {
2529
- const openIdx = text.indexOf(startTag, searchIndex);
2530
- selfTagRegex.lastIndex = searchIndex;
2531
- const selfMatch = selfTagRegex.exec(text);
2532
- const selfIdx = selfMatch ? selfMatch.index : -1;
2533
- const selfTagLength = selfMatch ? selfMatch[0].length : 0;
2534
- if (openIdx === -1 && selfIdx === -1) {
4700
+ const match = findNextToolTag(text, searchIndex, toolName);
4701
+ if (match === null) {
2535
4702
  break;
2536
4703
  }
2537
- const { tagStart, isSelfClosing } = findEarliestTagPosition(
2538
- openIdx,
2539
- selfIdx
2540
- );
4704
+ const tagStart = match.tagStart;
4705
+ const isSelfClosing = match.isSelfClosing;
2541
4706
  if (isSelfClosing) {
2542
- const endIndex = tagStart + selfTagLength;
4707
+ const endIndex = tagStart + match.tagLength;
2543
4708
  toolCalls.push({
2544
4709
  toolName,
2545
4710
  startIndex: tagStart,
@@ -2550,7 +4715,7 @@ function collectToolCallsForName(text, toolName) {
2550
4715
  continue;
2551
4716
  }
2552
4717
  const contentStart = tagStart + startTag.length;
2553
- const fullTagEnd = findClosingTagEnd(text, contentStart, toolName);
4718
+ const fullTagEnd = findClosingTagEnd2(text, contentStart, toolName);
2554
4719
  if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
2555
4720
  const endTag = `</${toolName}>`;
2556
4721
  const endTagStart = fullTagEnd - endTag.length;
@@ -2645,38 +4810,6 @@ function processToolCallMatch(text, tc, currentIndex, processedElements, options
2645
4810
  }
2646
4811
  return tc.endIndex;
2647
4812
  }
2648
- function findEarliestToolTag2(buffer, toolNames) {
2649
- let bestIndex = -1;
2650
- let bestName = "";
2651
- let bestSelfClosing = false;
2652
- let bestTagLength = 0;
2653
- for (const name of toolNames) {
2654
- const openTag = `<${name}>`;
2655
- const selfTagRegex = getSelfClosingTagPattern2(name);
2656
- const idxOpen = buffer.indexOf(openTag);
2657
- selfTagRegex.lastIndex = 0;
2658
- const selfMatch = selfTagRegex.exec(buffer);
2659
- const idxSelf = selfMatch ? selfMatch.index : -1;
2660
- if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
2661
- bestIndex = idxOpen;
2662
- bestName = name;
2663
- bestSelfClosing = false;
2664
- bestTagLength = openTag.length;
2665
- }
2666
- if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
2667
- bestIndex = idxSelf;
2668
- bestName = name;
2669
- bestSelfClosing = true;
2670
- bestTagLength = selfMatch ? selfMatch[0].length : 0;
2671
- }
2672
- }
2673
- return {
2674
- index: bestIndex,
2675
- name: bestName,
2676
- selfClosing: bestSelfClosing,
2677
- tagLength: bestTagLength
2678
- };
2679
- }
2680
4813
  function stripTrailingPartialCloseTag(content, toolName) {
2681
4814
  const closeTag = `</${toolName}>`;
2682
4815
  const lastLineBreakIndex = Math.max(
@@ -2700,10 +4833,10 @@ function stripTrailingPartialCloseTag(content, toolName) {
2700
4833
  )}${preservedLeadingWhitespace}`;
2701
4834
  return contentWithoutPartial.trimEnd();
2702
4835
  }
2703
- var yamlProtocol = (_protocolOptions) => {
4836
+ var yamlXmlProtocol = (_protocolOptions) => {
2704
4837
  return {
2705
4838
  formatTools({ tools, toolSystemPromptTemplate }) {
2706
- return toolSystemPromptTemplate(tools || []);
4839
+ return formatToolsWithPromptTemplate({ tools, toolSystemPromptTemplate });
2707
4840
  },
2708
4841
  formatToolCall(toolCall) {
2709
4842
  let args = {};
@@ -2719,7 +4852,7 @@ var yamlProtocol = (_protocolOptions) => {
2719
4852
  ${yamlContent}</${toolCall.toolName}>`;
2720
4853
  },
2721
4854
  parseGeneratedText({ text, tools, options }) {
2722
- const toolNames = tools.map((t) => t.name).filter(Boolean);
4855
+ const toolNames = extractToolNames(tools);
2723
4856
  if (toolNames.length === 0) {
2724
4857
  return [{ type: "text", text }];
2725
4858
  }
@@ -2755,7 +4888,7 @@ ${yamlContent}</${toolCall.toolName}>`;
2755
4888
  return processedElements;
2756
4889
  },
2757
4890
  createStreamParser({ tools, options }) {
2758
- const toolNames = tools.map((t) => t.name).filter(Boolean);
4891
+ const toolNames = extractToolNames(tools);
2759
4892
  let buffer = "";
2760
4893
  let currentToolCall = null;
2761
4894
  let currentTextId = null;
@@ -2778,16 +4911,19 @@ ${yamlContent}</${toolCall.toolName}>`;
2778
4911
  if (parsedArgs === null) {
2779
4912
  return;
2780
4913
  }
2781
- const fullInput = JSON.stringify(parsedArgs);
4914
+ const fullInput = stringifyToolInputWithSchema({
4915
+ toolName: currentToolCall.name,
4916
+ args: parsedArgs,
4917
+ tools
4918
+ });
2782
4919
  if (fullInput === "{}" && toolContent.trim().length === 0) {
2783
4920
  return;
2784
4921
  }
2785
- const prefixCandidate = toIncompleteJsonPrefix(fullInput);
2786
- emitPrefixDelta({
4922
+ emitToolInputProgressDelta({
2787
4923
  controller,
2788
4924
  id: currentToolCall.toolCallId,
2789
4925
  state: currentToolCall,
2790
- candidate: prefixCandidate
4926
+ fullInput
2791
4927
  });
2792
4928
  };
2793
4929
  const processToolCallEnd = (controller, toolContent, toolName, toolCallId) => {
@@ -2795,38 +4931,43 @@ ${yamlContent}</${toolCall.toolName}>`;
2795
4931
  const parsedArgs = parseYamlContent(toolContent, options);
2796
4932
  flushText(controller);
2797
4933
  if (parsedArgs !== null) {
2798
- const finalInput = JSON.stringify(parsedArgs);
4934
+ const finalInput = stringifyToolInputWithSchema({
4935
+ toolName,
4936
+ args: parsedArgs,
4937
+ tools
4938
+ });
2799
4939
  if (currentToolCall && currentToolCall.toolCallId === toolCallId) {
2800
- emitFinalRemainder({
4940
+ emitFinalizedToolInputLifecycle({
2801
4941
  controller,
2802
4942
  id: toolCallId,
2803
4943
  state: currentToolCall,
2804
- finalFullJson: finalInput,
4944
+ toolName,
4945
+ finalInput,
2805
4946
  onMismatch: options == null ? void 0 : options.onError
2806
4947
  });
4948
+ } else {
4949
+ enqueueToolInputEndAndCall({
4950
+ controller,
4951
+ id: toolCallId,
4952
+ toolName,
4953
+ input: finalInput
4954
+ });
2807
4955
  }
2808
- controller.enqueue({
2809
- type: "tool-input-end",
2810
- id: toolCallId
2811
- });
2812
- controller.enqueue({
2813
- type: "tool-call",
2814
- toolCallId,
2815
- toolName,
2816
- input: finalInput
2817
- });
2818
4956
  } else {
2819
- controller.enqueue({
2820
- type: "tool-input-end",
2821
- id: toolCallId
2822
- });
2823
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
+ });
2824
4968
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
2825
4969
  toolCall: original
2826
4970
  });
2827
- if (shouldEmitRawToolCallTextOnError3(options)) {
2828
- flushText(controller, original);
2829
- }
2830
4971
  }
2831
4972
  };
2832
4973
  const finalizeUnclosedToolCall = (controller) => {
@@ -2840,38 +4981,36 @@ ${yamlContent}</${toolCall.toolName}>`;
2840
4981
  const parsedArgs = parseYamlContent(reconciledBuffer, options);
2841
4982
  flushText(controller);
2842
4983
  if (parsedArgs !== null) {
2843
- const finalInput = JSON.stringify(parsedArgs);
2844
- emitFinalRemainder({
4984
+ const finalInput = stringifyToolInputWithSchema({
4985
+ toolName,
4986
+ args: parsedArgs,
4987
+ tools
4988
+ });
4989
+ emitFinalizedToolInputLifecycle({
2845
4990
  controller,
2846
4991
  id: toolCallId,
2847
4992
  state: currentToolCall,
2848
- finalFullJson: finalInput,
2849
- onMismatch: options == null ? void 0 : options.onError
2850
- });
2851
- controller.enqueue({
2852
- type: "tool-input-end",
2853
- id: toolCallId
2854
- });
2855
- controller.enqueue({
2856
- type: "tool-call",
2857
- toolCallId,
2858
4993
  toolName,
2859
- input: finalInput
4994
+ finalInput,
4995
+ onMismatch: options == null ? void 0 : options.onError
2860
4996
  });
2861
4997
  } else {
2862
- controller.enqueue({
2863
- type: "tool-input-end",
2864
- id: toolCallId
2865
- });
2866
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
+ });
2867
5009
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
2868
5010
  options,
2869
5011
  "Could not complete streaming YAML tool call at finish.",
2870
5012
  { toolCall: unfinishedContent }
2871
5013
  );
2872
- if (shouldEmitRawToolCallTextOnError3(options)) {
2873
- flushText(controller, unfinishedContent);
2874
- }
2875
5014
  }
2876
5015
  buffer = "";
2877
5016
  currentToolCall = null;
@@ -2948,7 +5087,7 @@ ${yamlContent}</${toolCall.toolName}>`;
2948
5087
  break;
2949
5088
  }
2950
5089
  } else {
2951
- const { index, name, selfClosing, tagLength } = findEarliestToolTag2(
5090
+ const { index, name, selfClosing, tagLength } = findEarliestToolTag(
2952
5091
  buffer,
2953
5092
  toolNames
2954
5093
  );
@@ -3145,9 +5284,38 @@ function decodeOriginalTools(originalTools, options) {
3145
5284
  }
3146
5285
  return decodedTools;
3147
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
+ }
3148
5294
  function extractToolNamesFromOriginalTools(originalTools) {
3149
5295
  return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
3150
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
+ }
3151
5319
  function isToolChoiceActive(params) {
3152
5320
  var _a, _b, _c;
3153
5321
  const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
@@ -3167,7 +5335,7 @@ function hasInputProperty(obj) {
3167
5335
  }
3168
5336
 
3169
5337
  // src/core/utils/generated-text-json-recovery.ts
3170
- function isRecord(value) {
5338
+ function isRecord2(value) {
3171
5339
  return typeof value === "object" && value !== null && !Array.isArray(value);
3172
5340
  }
3173
5341
  function safeStringify2(value) {
@@ -3323,7 +5491,7 @@ function toRecoveredParts(text, candidate, toolCallPart) {
3323
5491
  return out;
3324
5492
  }
3325
5493
  function parseAsToolPayload(payload, tools) {
3326
- if (!isRecord(payload)) {
5494
+ if (!isRecord2(payload)) {
3327
5495
  return null;
3328
5496
  }
3329
5497
  const toolName = typeof payload.name === "string" && payload.name.trim().length > 0 ? payload.name.trim() : null;
@@ -3334,7 +5502,7 @@ function parseAsToolPayload(payload, tools) {
3334
5502
  return null;
3335
5503
  }
3336
5504
  const rawArgs = Object.hasOwn(payload, "arguments") ? payload.arguments : {};
3337
- if (!isRecord(rawArgs)) {
5505
+ if (!isRecord2(rawArgs)) {
3338
5506
  return null;
3339
5507
  }
3340
5508
  return {
@@ -3344,14 +5512,14 @@ function parseAsToolPayload(payload, tools) {
3344
5512
  }
3345
5513
  function isLikelyArgumentsShapeForTool(args, tool) {
3346
5514
  const unwrapped = unwrapJsonSchema(tool.inputSchema);
3347
- if (!isRecord(unwrapped)) {
5515
+ if (!isRecord2(unwrapped)) {
3348
5516
  return false;
3349
5517
  }
3350
5518
  if (getSchemaType(unwrapped) !== "object") {
3351
5519
  return false;
3352
5520
  }
3353
5521
  const properties = unwrapped.properties;
3354
- if (!isRecord(properties)) {
5522
+ if (!isRecord2(properties)) {
3355
5523
  return false;
3356
5524
  }
3357
5525
  const keys = Object.keys(args);
@@ -3371,11 +5539,11 @@ function parseAsArgumentsOnly(payload, tools) {
3371
5539
  if (tools.length !== 1) {
3372
5540
  return null;
3373
5541
  }
3374
- if (!isRecord(payload)) {
5542
+ if (!isRecord2(payload)) {
3375
5543
  return null;
3376
5544
  }
3377
5545
  const hasNameEnvelope = Object.hasOwn(payload, "name") && typeof payload.name === "string" && payload.name.length > 0;
3378
- 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));
3379
5547
  if (hasNameEnvelope || hasArgumentsEnvelope) {
3380
5548
  return null;
3381
5549
  }
@@ -3410,36 +5578,6 @@ function recoverToolCallFromJsonCandidates(text, tools) {
3410
5578
  return null;
3411
5579
  }
3412
5580
 
3413
- // src/core/utils/tool-call-coercion.ts
3414
- function coerceToolCallInput(toolName, input, tools) {
3415
- var _a;
3416
- let args = {};
3417
- if (typeof input === "string") {
3418
- try {
3419
- args = JSON.parse(input);
3420
- } catch (e) {
3421
- return;
3422
- }
3423
- } else if (input && typeof input === "object") {
3424
- args = input;
3425
- } else {
3426
- return;
3427
- }
3428
- const schema = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
3429
- const coerced = coerceBySchema(args, schema);
3430
- return JSON.stringify(coerced != null ? coerced : {});
3431
- }
3432
- function coerceToolCallPart(part, tools) {
3433
- const coercedInput = coerceToolCallInput(part.toolName, part.input, tools);
3434
- if (coercedInput === void 0) {
3435
- return part;
3436
- }
3437
- return {
3438
- ...part,
3439
- input: coercedInput
3440
- };
3441
- }
3442
-
3443
5581
  // src/core/utils/tool-choice.ts
3444
5582
  function ensureNonEmptyToolName(name) {
3445
5583
  if (typeof name !== "string") {
@@ -3494,6 +5632,30 @@ function parseToolChoicePayload({
3494
5632
  input: coercedInput != null ? coercedInput : safeStringify3(rawArgs)
3495
5633
  };
3496
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
+ }
3497
5659
 
3498
5660
  // src/generate-handler.ts
3499
5661
  function logDebugSummary(debugSummary, toolCall, originText) {
@@ -3513,29 +5675,23 @@ async function handleToolChoice(doGenerate, params, tools) {
3513
5675
  var _a, _b, _c, _d;
3514
5676
  const result = await doGenerate();
3515
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;
3516
5679
  const onError = (_b = extractOnErrorOption(params.providerOptions)) == null ? void 0 : _b.onError;
3517
- let toolName = "unknown";
3518
- let input = "{}";
3519
- if (first && first.type === "text") {
3520
- if (getDebugLevel() === "parse") {
3521
- logRawChunk(first.text);
3522
- }
3523
- const parsed = parseToolChoicePayload({
3524
- text: first.text,
3525
- tools,
3526
- onError,
3527
- errorMessage: "Failed to parse toolChoice JSON from generated model output"
3528
- });
3529
- toolName = parsed.toolName;
3530
- input = parsed.input;
5680
+ if (typeof firstText === "string" && getDebugLevel() === "parse") {
5681
+ logRawChunk(firstText);
3531
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
+ });
3532
5689
  const toolCall = {
3533
5690
  type: "tool-call",
3534
5691
  toolCallId: generateToolCallId(),
3535
5692
  toolName,
3536
5693
  input
3537
5694
  };
3538
- const originText = first && first.type === "text" ? first.text : "";
3539
5695
  const debugSummary = (_d = (_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) == null ? void 0 : _d.debugSummary;
3540
5696
  logDebugSummary(debugSummary, toolCall, originText);
3541
5697
  return {
@@ -3556,7 +5712,7 @@ function parseContent(content, protocol, tools, providerOptions) {
3556
5712
  tools,
3557
5713
  options: {
3558
5714
  ...extractOnErrorOption(providerOptions),
3559
- ...providerOptions == null ? void 0 : providerOptions.toolCallMiddleware
5715
+ ...getToolCallMiddlewareOptions(providerOptions)
3560
5716
  }
3561
5717
  });
3562
5718
  const hasToolCall = parsedByProtocol.some(
@@ -3614,10 +5770,9 @@ async function wrapGenerate({
3614
5770
  doGenerate,
3615
5771
  params
3616
5772
  }) {
3617
- var _a, _b;
3618
5773
  const onError = extractOnErrorOption(params.providerOptions);
3619
- const tools = originalToolsSchema.decode(
3620
- (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
5774
+ const tools = decodeOriginalToolsFromProviderOptions(
5775
+ params.providerOptions,
3621
5776
  onError
3622
5777
  );
3623
5778
  if (isToolChoiceActive(params)) {
@@ -3647,23 +5802,147 @@ async function wrapGenerate({
3647
5802
  };
3648
5803
  }
3649
5804
 
3650
- // src/core/prompts/hermes-system-prompt.ts
3651
- function hermesSystemPromptTemplate(tools) {
3652
- const toolsJson = JSON.stringify(tools);
3653
- return `You are a function calling AI model.
3654
- You are provided with function signatures within <tools></tools> XML tags.
3655
- You may call one or more functions to assist with the user query.
3656
- Don't make assumptions about what values to plug into functions.
3657
- Here are the available tools: <tools>${toolsJson}</tools>
3658
- Use the following pydantic model json schema for each tool call you will make: {"title": "FunctionCall", "type": "object", "properties": {"arguments": {"title": "Arguments", "type": "object"}, "name": {"title": "Name", "type": "string"}}, "required": ["arguments", "name"]}
3659
- For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
3660
- <tool_call>
3661
- {"name": "<function-name>", "arguments": <args-dict>}
3662
- </tool_call>`;
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
+ };
3663
5818
  }
3664
5819
 
3665
- // src/core/prompts/tool-response.ts
3666
- function unwrapToolResult(result) {
5820
+ // src/core/prompts/shared/tool-result-normalizer.ts
5821
+ function isMapping(value) {
5822
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5823
+ }
5824
+ function getMediaKindFromMediaType(mediaType) {
5825
+ if (mediaType.startsWith("image/")) {
5826
+ return "image";
5827
+ }
5828
+ if (mediaType.startsWith("audio/")) {
5829
+ return "audio";
5830
+ }
5831
+ if (mediaType.startsWith("video/")) {
5832
+ return "video";
5833
+ }
5834
+ return "file";
5835
+ }
5836
+ function getContentPartMediaKind(part) {
5837
+ const contentPart = isMapping(part) ? part : void 0;
5838
+ const type = contentPart == null ? void 0 : contentPart.type;
5839
+ switch (type) {
5840
+ case "image-data":
5841
+ case "image-url":
5842
+ case "image-file-id":
5843
+ return "image";
5844
+ case "file-data":
5845
+ case "file-url":
5846
+ case "file-id": {
5847
+ const mediaType = contentPart == null ? void 0 : contentPart.mediaType;
5848
+ if (typeof mediaType === "string") {
5849
+ return getMediaKindFromMediaType(mediaType);
5850
+ }
5851
+ return "file";
5852
+ }
5853
+ case "media": {
5854
+ const mediaType = contentPart == null ? void 0 : contentPart.mediaType;
5855
+ if (typeof mediaType === "string") {
5856
+ return getMediaKindFromMediaType(mediaType);
5857
+ }
5858
+ return "file";
5859
+ }
5860
+ default:
5861
+ return null;
5862
+ }
5863
+ }
5864
+ function shouldPassRawByStrategy(mediaKind, strategy) {
5865
+ var _a;
5866
+ const mode = getMediaMode(strategy);
5867
+ if (mode === "raw") {
5868
+ return true;
5869
+ }
5870
+ if (mode === "placeholder") {
5871
+ return false;
5872
+ }
5873
+ if (mode === "model") {
5874
+ return false;
5875
+ }
5876
+ return ((_a = strategy == null ? void 0 : strategy.capabilities) == null ? void 0 : _a[mediaKind]) === true;
5877
+ }
5878
+ function getMediaMode(strategy) {
5879
+ var _a;
5880
+ return (_a = strategy == null ? void 0 : strategy.mode) != null ? _a : "placeholder";
5881
+ }
5882
+ function shouldPassRawContent(contentParts, strategy) {
5883
+ const mode = getMediaMode(strategy);
5884
+ if (mode === "raw") {
5885
+ return true;
5886
+ }
5887
+ if (mode === "placeholder") {
5888
+ return false;
5889
+ }
5890
+ if (mode === "model") {
5891
+ return false;
5892
+ }
5893
+ let hasSupportedMediaContent = false;
5894
+ for (const part of contentParts) {
5895
+ const mediaKind = getContentPartMediaKind(part);
5896
+ if (!mediaKind) {
5897
+ continue;
5898
+ }
5899
+ hasSupportedMediaContent = true;
5900
+ if (!shouldPassRawByStrategy(mediaKind, strategy)) {
5901
+ return false;
5902
+ }
5903
+ }
5904
+ return hasSupportedMediaContent;
5905
+ }
5906
+ function formatIdPlaceholder(label, fileId) {
5907
+ const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
5908
+ return `[${label}: ${displayId}]`;
5909
+ }
5910
+ function formatContentPartPlaceholder(part) {
5911
+ var _a;
5912
+ const contentPart = part;
5913
+ switch (contentPart.type) {
5914
+ case "text":
5915
+ return (_a = contentPart.text) != null ? _a : "";
5916
+ case "image-data":
5917
+ return `[Image: ${contentPart.mediaType}]`;
5918
+ case "image-url":
5919
+ return `[Image URL: ${contentPart.url}]`;
5920
+ case "image-file-id": {
5921
+ const fileId = contentPart.fileId;
5922
+ return formatIdPlaceholder("Image ID", fileId);
5923
+ }
5924
+ case "file-data": {
5925
+ const filePart = contentPart;
5926
+ if (filePart.filename) {
5927
+ return `[File: ${filePart.filename} (${filePart.mediaType})]`;
5928
+ }
5929
+ return `[File: ${filePart.mediaType}]`;
5930
+ }
5931
+ case "file-url":
5932
+ return `[File URL: ${contentPart.url}]`;
5933
+ case "file-id": {
5934
+ const fileId = contentPart.fileId;
5935
+ return formatIdPlaceholder("File ID", fileId);
5936
+ }
5937
+ case "media":
5938
+ return `[Media: ${contentPart.mediaType}]`;
5939
+ case "custom":
5940
+ return "[Custom content]";
5941
+ default:
5942
+ return "[Unknown content]";
5943
+ }
5944
+ }
5945
+ function unwrapToolResult(result, mediaStrategy) {
3667
5946
  var _a, _b;
3668
5947
  switch (result.type) {
3669
5948
  case "text":
@@ -3679,43 +5958,11 @@ function unwrapToolResult(result) {
3679
5958
  case "error-json":
3680
5959
  return `[Error: ${JSON.stringify(result.value)}]`;
3681
5960
  case "content": {
3682
- return result.value.map((part) => {
3683
- var _a2;
3684
- const contentPart = part;
3685
- switch (contentPart.type) {
3686
- case "text":
3687
- return (_a2 = contentPart.text) != null ? _a2 : "";
3688
- case "image-data":
3689
- return `[Image: ${contentPart.mediaType}]`;
3690
- case "image-url":
3691
- return `[Image URL: ${contentPart.url}]`;
3692
- case "image-file-id": {
3693
- const fileId = contentPart.fileId;
3694
- const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
3695
- return `[Image ID: ${displayId}]`;
3696
- }
3697
- case "file-data": {
3698
- const filePart = contentPart;
3699
- if (filePart.filename) {
3700
- return `[File: ${filePart.filename} (${filePart.mediaType})]`;
3701
- }
3702
- return `[File: ${filePart.mediaType}]`;
3703
- }
3704
- case "file-url":
3705
- return `[File URL: ${contentPart.url}]`;
3706
- case "file-id": {
3707
- const fileId = contentPart.fileId;
3708
- const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
3709
- return `[File ID: ${displayId}]`;
3710
- }
3711
- case "media":
3712
- return `[Media: ${contentPart.mediaType}]`;
3713
- case "custom":
3714
- return "[Custom content]";
3715
- default:
3716
- return "[Unknown content]";
3717
- }
3718
- }).join("\n");
5961
+ const parts = result.value;
5962
+ if (shouldPassRawContent(parts, mediaStrategy)) {
5963
+ return parts;
5964
+ }
5965
+ return parts.map(formatContentPartPlaceholder).join("\n");
3719
5966
  }
3720
5967
  default: {
3721
5968
  const _exhaustive = result;
@@ -3723,58 +5970,89 @@ function unwrapToolResult(result) {
3723
5970
  }
3724
5971
  }
3725
5972
  }
3726
- function formatToolResponseAsJsonInXml(toolResult) {
3727
- const unwrappedResult = unwrapToolResult(toolResult.output);
5973
+
5974
+ // src/core/prompts/hermes-prompt.ts
5975
+ function formatToolResponseAsHermesWithOptions(toolResult, options) {
5976
+ const unwrappedResult = unwrapToolResult(
5977
+ toolResult.output,
5978
+ options == null ? void 0 : options.mediaStrategy
5979
+ );
3728
5980
  return `<tool_response>${JSON.stringify({
3729
- toolName: toolResult.toolName,
3730
- result: unwrappedResult
5981
+ name: toolResult.toolName,
5982
+ content: unwrappedResult
3731
5983
  })}</tool_response>`;
3732
5984
  }
3733
- function formatToolResponseAsXml(toolResult) {
3734
- const unwrappedResult = unwrapToolResult(toolResult.output);
3735
- const toolNameXml = `<tool_name>${toolResult.toolName}</tool_name>`;
3736
- const resultLines = formatXmlNode("result", unwrappedResult, 1);
3737
- return [
3738
- "<tool_response>",
3739
- ` ${toolNameXml}`,
3740
- ...resultLines,
3741
- "</tool_response>"
3742
- ].join("\n");
5985
+ function formatToolResponseAsHermes(toolResult) {
5986
+ return formatToolResponseAsHermesWithOptions(toolResult);
3743
5987
  }
3744
- function formatXmlNode(tagName, value, depth) {
3745
- const indent = " ".repeat(depth);
3746
- if (value === null || value === void 0) {
3747
- return [`${indent}<${tagName}></${tagName}>`];
5988
+ function jsonSchemaToPythonType(schema) {
5989
+ const type = schema.type;
5990
+ if (type === "string") {
5991
+ return "str";
3748
5992
  }
3749
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3750
- return [`${indent}<${tagName}>${String(value)}</${tagName}>`];
5993
+ if (type === "number") {
5994
+ return "float";
3751
5995
  }
3752
- if (Array.isArray(value)) {
3753
- if (value.length === 0) {
3754
- return [`${indent}<${tagName}></${tagName}>`];
5996
+ if (type === "integer") {
5997
+ return "int";
5998
+ }
5999
+ if (type === "boolean") {
6000
+ return "bool";
6001
+ }
6002
+ if (type === "array") {
6003
+ const items = schema.items;
6004
+ if (items) {
6005
+ return `list[${jsonSchemaToPythonType(items)}]`;
3755
6006
  }
3756
- const lines2 = [`${indent}<${tagName}>`];
3757
- for (const item of value) {
3758
- lines2.push(...formatXmlNode("item", item, depth + 1));
6007
+ return "list[Any]";
6008
+ }
6009
+ if (type === "object") {
6010
+ const additionalProperties = schema.additionalProperties;
6011
+ if (additionalProperties) {
6012
+ return `dict[str, ${jsonSchemaToPythonType(additionalProperties)}]`;
3759
6013
  }
3760
- lines2.push(`${indent}</${tagName}>`);
3761
- return lines2;
6014
+ return "dict";
3762
6015
  }
3763
- const entries = Object.entries(value);
3764
- if (entries.length === 0) {
3765
- return [`${indent}<${tagName}></${tagName}>`];
6016
+ if (Array.isArray(type)) {
6017
+ return `Union[${type.map((t) => jsonSchemaToPythonType({ type: t })).join(",")}]`;
3766
6018
  }
3767
- const lines = [`${indent}<${tagName}>`];
3768
- for (const [key, entryValue] of entries) {
3769
- lines.push(...formatXmlNode(key, entryValue, depth + 1));
6019
+ return "Any";
6020
+ }
6021
+ function renderToolDefinition(tool) {
6022
+ var _a, _b;
6023
+ const schema = tool.inputSchema;
6024
+ const properties = schema.properties;
6025
+ const paramSignature = properties ? Object.entries(properties).map(([name, field]) => `${name}: ${jsonSchemaToPythonType(field)}`).join(", ") : "";
6026
+ const desc = (_a = tool.description) != null ? _a : "";
6027
+ let description = `${tool.name}(${paramSignature}) - ${desc}
6028
+
6029
+ `;
6030
+ if (properties && Object.keys(properties).length > 0) {
6031
+ description += " Args:\n";
6032
+ for (const [paramName, paramFields] of Object.entries(properties)) {
6033
+ const paramDesc = (_b = paramFields.description) != null ? _b : "";
6034
+ description += ` ${paramName}(${jsonSchemaToPythonType(paramFields)}): ${paramDesc.trim()}
6035
+ `;
6036
+ }
3770
6037
  }
3771
- lines.push(`${indent}</${tagName}>`);
3772
- return lines;
6038
+ const parametersJson = JSON.stringify(schema);
6039
+ const descJson = JSON.stringify(description);
6040
+ const nameJson = JSON.stringify(tool.name);
6041
+ return `{"type": "function", "function": {"name": ${nameJson}, "description": ${descJson}, "parameters": ${parametersJson}}}`;
6042
+ }
6043
+ function hermesSystemPromptTemplate(tools) {
6044
+ const toolsRendered = tools.map(renderToolDefinition).join("\n");
6045
+ return `You are a function calling AI model. You are provided with function signatures within <tools></tools> XML tags. You may call one or more functions to assist with the user query. Don't make assumptions about what values to plug into functions. Here are the available tools: <tools> ${toolsRendered} </tools>
6046
+ Use the following pydantic model json schema for each tool call you will make: {"properties": {"name": {"title": "Name", "type": "string"}, "arguments": {"title": "Arguments", "type": "object"}}, "required": ["name", "arguments"], "title": "FunctionCall", "type": "object"}
6047
+ For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
6048
+ <tool_call>
6049
+ {"name": "<function-name>", "arguments": <args-dict>}
6050
+ </tool_call>`;
3773
6051
  }
3774
6052
 
3775
- // src/core/prompts/xml-system-prompt.ts
6053
+ // src/core/prompts/morph-xml-prompt.ts
3776
6054
  import dedent from "dedent";
3777
- function xmlSystemPromptTemplate(tools) {
6055
+ function morphXmlSystemPromptTemplate(tools) {
3778
6056
  const toolsText = renderToolsForXmlPrompt(tools);
3779
6057
  const header = dedent`
3780
6058
  # Tools
@@ -3998,9 +6276,202 @@ function stripSchemaKeys(value) {
3998
6276
  }
3999
6277
  return value;
4000
6278
  }
6279
+ function formatXmlNode(tagName, value, depth) {
6280
+ const indent = " ".repeat(depth);
6281
+ if (value === null || value === void 0) {
6282
+ return [`${indent}<${tagName}></${tagName}>`];
6283
+ }
6284
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
6285
+ return [`${indent}<${tagName}>${String(value)}</${tagName}>`];
6286
+ }
6287
+ if (Array.isArray(value)) {
6288
+ if (value.length === 0) {
6289
+ return [`${indent}<${tagName}></${tagName}>`];
6290
+ }
6291
+ const lines2 = [`${indent}<${tagName}>`];
6292
+ for (const item of value) {
6293
+ lines2.push(...formatXmlNode("item", item, depth + 1));
6294
+ }
6295
+ lines2.push(`${indent}</${tagName}>`);
6296
+ return lines2;
6297
+ }
6298
+ const entries = Object.entries(value);
6299
+ if (entries.length === 0) {
6300
+ return [`${indent}<${tagName}></${tagName}>`];
6301
+ }
6302
+ const lines = [`${indent}<${tagName}>`];
6303
+ for (const [key, entryValue] of entries) {
6304
+ lines.push(...formatXmlNode(key, entryValue, depth + 1));
6305
+ }
6306
+ lines.push(`${indent}</${tagName}>`);
6307
+ return lines;
6308
+ }
6309
+ function morphFormatToolResponseAsXmlWithOptions(toolResult, options) {
6310
+ const unwrappedResult = unwrapToolResult(
6311
+ toolResult.output,
6312
+ options == null ? void 0 : options.mediaStrategy
6313
+ );
6314
+ const toolNameXml = `<tool_name>${toolResult.toolName}</tool_name>`;
6315
+ const resultLines = formatXmlNode("result", unwrappedResult, 1);
6316
+ return [
6317
+ "<tool_response>",
6318
+ ` ${toolNameXml}`,
6319
+ ...resultLines,
6320
+ "</tool_response>"
6321
+ ].join("\n");
6322
+ }
6323
+ function morphFormatToolResponseAsXml(toolResult) {
6324
+ return morphFormatToolResponseAsXmlWithOptions(toolResult);
6325
+ }
6326
+
6327
+ // src/core/prompts/qwen3coder-prompt.ts
6328
+ var QWEN3CODER_TOOL_HEADER = "# Tools\n\nYou have access to the following functions:\n\n";
6329
+ 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>";
6330
+ var XML_PROMPT_TAG_NAME_RE = /^[A-Za-z_][A-Za-z0-9_.-]*$/;
6331
+ function isMapping2(value) {
6332
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6333
+ }
6334
+ function isSequence(value) {
6335
+ return Array.isArray(value);
6336
+ }
6337
+ function toJinjaString(value) {
6338
+ if (value === void 0) {
6339
+ return "";
6340
+ }
6341
+ if (value === null) {
6342
+ return "None";
6343
+ }
6344
+ if (typeof value === "boolean") {
6345
+ return value ? "True" : "False";
6346
+ }
6347
+ return String(value);
6348
+ }
6349
+ function toJinjaTrimmedString(value) {
6350
+ return toJinjaString(value).trim();
6351
+ }
6352
+ function toEscapedXmlText(value) {
6353
+ return escapeXmlMinimalText(toJinjaString(value));
6354
+ }
6355
+ function toEscapedTrimmedXmlText(value) {
6356
+ return escapeXmlMinimalText(toJinjaTrimmedString(value));
6357
+ }
6358
+ function renderXmlPromptField(key, escapedValue) {
6359
+ if (XML_PROMPT_TAG_NAME_RE.test(key)) {
6360
+ return `
6361
+ <${key}>${escapedValue}</${key}>`;
6362
+ }
6363
+ return `
6364
+ <property name="${escapeXmlMinimalAttr(
6365
+ key,
6366
+ '"'
6367
+ )}">${escapedValue}</property>`;
6368
+ }
6369
+ function renderExtraKeys(jsonDict, handledKeys) {
6370
+ if (!isMapping2(jsonDict)) {
6371
+ return "";
6372
+ }
6373
+ const handled = new Set(handledKeys);
6374
+ let out = "";
6375
+ for (const [jsonKey, jsonValue] of Object.entries(jsonDict)) {
6376
+ if (handled.has(jsonKey)) {
6377
+ continue;
6378
+ }
6379
+ const renderedValue = isMapping2(jsonValue) || isSequence(jsonValue) ? JSON.stringify(jsonValue) : toJinjaString(jsonValue);
6380
+ out += renderXmlPromptField(jsonKey, escapeXmlMinimalText(renderedValue));
6381
+ }
6382
+ return out;
6383
+ }
6384
+ function normalizeInputSchema(inputSchema) {
6385
+ if (typeof inputSchema !== "string") {
6386
+ return inputSchema;
6387
+ }
6388
+ try {
6389
+ return JSON.parse(inputSchema);
6390
+ } catch (e) {
6391
+ return inputSchema;
6392
+ }
6393
+ }
6394
+ function normalizeTool(rawTool) {
6395
+ return {
6396
+ name: rawTool.name,
6397
+ description: rawTool.description,
6398
+ parameters: normalizeInputSchema(rawTool.inputSchema)
6399
+ };
6400
+ }
6401
+ function renderParameter(paramName, paramFieldsRaw) {
6402
+ const paramFields = isMapping2(paramFieldsRaw) ? paramFieldsRaw : void 0;
6403
+ let out = "\n<parameter>";
6404
+ out += `
6405
+ <name>${toEscapedXmlText(paramName)}</name>`;
6406
+ if ((paramFields == null ? void 0 : paramFields.type) !== void 0) {
6407
+ out += `
6408
+ <type>${toEscapedXmlText(paramFields.type)}</type>`;
6409
+ }
6410
+ if ((paramFields == null ? void 0 : paramFields.description) !== void 0) {
6411
+ out += `
6412
+ <description>${toEscapedTrimmedXmlText(paramFields.description)}</description>`;
6413
+ }
6414
+ out += renderExtraKeys(paramFieldsRaw, ["name", "type", "description"]);
6415
+ out += "\n</parameter>";
6416
+ return out;
6417
+ }
6418
+ function renderTool(tool) {
6419
+ let out = `
6420
+ <function>
6421
+ <name>${toEscapedXmlText(tool.name)}</name>`;
6422
+ if (tool.description !== void 0) {
6423
+ out += `
6424
+ <description>${toEscapedTrimmedXmlText(tool.description)}</description>`;
6425
+ }
6426
+ out += "\n<parameters>";
6427
+ const parameters = tool.parameters;
6428
+ if (isMapping2(parameters) && isMapping2(parameters.properties)) {
6429
+ for (const [paramName, paramFieldsRaw] of Object.entries(
6430
+ parameters.properties
6431
+ )) {
6432
+ out += renderParameter(paramName, paramFieldsRaw);
6433
+ }
6434
+ }
6435
+ out += renderExtraKeys(parameters, ["type", "properties"]);
6436
+ out += "\n</parameters>";
6437
+ out += renderExtraKeys(tool, ["type", "name", "description", "parameters"]);
6438
+ out += "\n</function>";
6439
+ return out;
6440
+ }
6441
+ function qwen3coderSystemPromptTemplate(tools) {
6442
+ if (!tools.length) {
6443
+ return "";
6444
+ }
6445
+ let out = `${QWEN3CODER_TOOL_HEADER}<tools>`;
6446
+ for (const tool of tools) {
6447
+ out += renderTool(normalizeTool(tool));
6448
+ }
6449
+ out += "\n</tools>";
6450
+ out += QWEN3CODER_TOOL_CALL_INSTRUCTIONS;
6451
+ return out;
6452
+ }
6453
+ function stringifyToolResponseContent(value) {
6454
+ if (typeof value === "string") {
6455
+ return value;
6456
+ }
6457
+ return JSON.stringify(value);
6458
+ }
6459
+ function formatToolResponseAsQwen3CoderXmlWithOptions(toolResult, options) {
6460
+ const unwrappedResult = unwrapToolResult(
6461
+ toolResult.output,
6462
+ options == null ? void 0 : options.mediaStrategy
6463
+ );
6464
+ const content = stringifyToolResponseContent(unwrappedResult);
6465
+ return `<tool_response>
6466
+ ${content}
6467
+ </tool_response>`;
6468
+ }
6469
+ function formatToolResponseAsQwen3CoderXml(toolResult) {
6470
+ return formatToolResponseAsQwen3CoderXmlWithOptions(toolResult);
6471
+ }
4001
6472
 
4002
- // src/core/prompts/yaml-system-prompt.ts
4003
- function yamlSystemPromptTemplate(tools, includeMultilineExample = true) {
6473
+ // src/core/prompts/yaml-xml-prompt.ts
6474
+ function yamlXmlSystemPromptTemplate(tools, includeMultilineExample = true) {
4004
6475
  const toolsJson = JSON.stringify(tools);
4005
6476
  const multilineExample = includeMultilineExample ? `
4006
6477
 
@@ -4039,6 +6510,9 @@ unit: celsius
4039
6510
  - Do NOT ask clarifying questions. Use reasonable defaults for optional parameters.
4040
6511
  - If a task requires multiple function calls, make ALL of them at once.`;
4041
6512
  }
6513
+ function formatToolResponseAsYaml(toolResult) {
6514
+ return morphFormatToolResponseAsXml(toolResult);
6515
+ }
4042
6516
 
4043
6517
  // src/stream-handler.ts
4044
6518
  async function wrapStream({
@@ -4047,10 +6521,9 @@ async function wrapStream({
4047
6521
  doGenerate,
4048
6522
  params
4049
6523
  }) {
4050
- var _a, _b, _c;
4051
6524
  const onErrorOptions = extractOnErrorOption(params.providerOptions);
4052
- const tools = originalToolsSchema.decode(
4053
- (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.originalTools,
6525
+ const tools = decodeOriginalToolsFromProviderOptions(
6526
+ params.providerOptions,
4054
6527
  onErrorOptions
4055
6528
  );
4056
6529
  if (isToolChoiceActive(params)) {
@@ -4064,7 +6537,7 @@ async function wrapStream({
4064
6537
  const debugLevel = getDebugLevel();
4065
6538
  const options = {
4066
6539
  ...onErrorOptions,
4067
- ...((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) || {}
6540
+ ...getToolCallMiddlewareOptions(params.providerOptions)
4068
6541
  };
4069
6542
  const coreStream = stream.pipeThrough(
4070
6543
  new TransformStream(
@@ -4114,18 +6587,14 @@ async function toolChoiceStream({
4114
6587
  var _a;
4115
6588
  const normalizedTools = Array.isArray(tools) ? tools : [];
4116
6589
  const result = await doGenerate();
4117
- let toolName = "unknown";
4118
- let input = "{}";
4119
- if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
4120
- const parsed = parseToolChoicePayload({
4121
- text: result.content[0].text,
4122
- tools: normalizedTools,
4123
- onError: options == null ? void 0 : options.onError,
4124
- errorMessage: "Failed to parse toolChoice JSON from streamed model output"
4125
- });
4126
- toolName = parsed.toolName;
4127
- input = parsed.input;
4128
- }
6590
+ const first = (_a = result == null ? void 0 : result.content) == null ? void 0 : _a[0];
6591
+ const firstText = (first == null ? void 0 : first.type) === "text" ? first.text : void 0;
6592
+ const { toolName, input } = resolveToolChoiceSelection({
6593
+ text: firstText,
6594
+ tools: normalizedTools,
6595
+ onError: options == null ? void 0 : options.onError,
6596
+ errorMessage: "Failed to parse toolChoice JSON from streamed model output"
6597
+ });
4129
6598
  const stream = new ReadableStream({
4130
6599
  start(controller) {
4131
6600
  controller.enqueue({
@@ -4203,8 +6672,108 @@ function normalizeUsage(usage) {
4203
6672
  return ZERO_USAGE;
4204
6673
  }
4205
6674
 
6675
+ // src/core/prompts/shared/assistant-tool-calls-to-text.ts
6676
+ function assistantToolCallsToTextContent(options) {
6677
+ var _a, _b;
6678
+ const newContent = [];
6679
+ for (const item of options.content) {
6680
+ switch (item.type) {
6681
+ case "tool-call":
6682
+ newContent.push({
6683
+ type: "text",
6684
+ text: options.protocol.formatToolCall(item)
6685
+ });
6686
+ break;
6687
+ case "text":
6688
+ case "reasoning":
6689
+ newContent.push(item);
6690
+ break;
6691
+ default:
6692
+ (_b = (_a = options.conversionOptions) == null ? void 0 : _a.onError) == null ? void 0 : _b.call(
6693
+ _a,
6694
+ "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
6695
+ { content: item }
6696
+ );
6697
+ newContent.push({
6698
+ type: "text",
6699
+ text: JSON.stringify(item)
6700
+ });
6701
+ }
6702
+ }
6703
+ if (!newContent.every((entry) => entry.type === "text")) {
6704
+ return newContent;
6705
+ }
6706
+ return [
6707
+ {
6708
+ type: "text",
6709
+ text: newContent.map((entry) => entry.text).join("\n")
6710
+ }
6711
+ ];
6712
+ }
6713
+
6714
+ // src/core/prompts/shared/tool-role-to-user-message.ts
6715
+ function formatApprovalResponse(part) {
6716
+ const status = part.approved ? "Approved" : "Denied";
6717
+ const reason = part.reason ? `: ${part.reason}` : "";
6718
+ return `[Tool Approval ${status}${reason}]`;
6719
+ }
6720
+ function normalizeTemplateResult(result) {
6721
+ if (typeof result === "string") {
6722
+ return [toTextPart(result)];
6723
+ }
6724
+ return result;
6725
+ }
6726
+ function appendSection(target, section) {
6727
+ if (section.length === 0) {
6728
+ return;
6729
+ }
6730
+ if (target.length > 0) {
6731
+ target.push(toTextPart("\n"));
6732
+ }
6733
+ target.push(...section);
6734
+ }
6735
+ function mergeAdjacentTextParts(parts) {
6736
+ const merged = [];
6737
+ for (const part of parts) {
6738
+ const last = merged.at(-1);
6739
+ const canMergeTextParts = part.type === "text" && (last == null ? void 0 : last.type) === "text" && part.providerOptions === void 0 && last.providerOptions === void 0;
6740
+ if (canMergeTextParts) {
6741
+ last.text += part.text;
6742
+ continue;
6743
+ }
6744
+ merged.push(part);
6745
+ }
6746
+ return merged;
6747
+ }
6748
+ function toolRoleContentToUserTextMessage(options) {
6749
+ const toolResultParts = options.toolContent.filter(
6750
+ (part) => part.type === "tool-result"
6751
+ );
6752
+ const approvalResponseParts = options.toolContent.filter(
6753
+ (part) => part.type === "tool-approval-response"
6754
+ );
6755
+ const sections = [];
6756
+ for (const toolResult of toolResultParts) {
6757
+ const result = options.toolResponsePromptTemplate(toolResult);
6758
+ appendSection(sections, normalizeTemplateResult(result));
6759
+ }
6760
+ for (const approvalResponse of approvalResponseParts) {
6761
+ appendSection(sections, [
6762
+ toTextPart(formatApprovalResponse(approvalResponse))
6763
+ ]);
6764
+ }
6765
+ const normalizedSections = sections.length > 0 ? sections : [toTextPart("")];
6766
+ return {
6767
+ role: "user",
6768
+ content: mergeAdjacentTextParts(normalizedSections)
6769
+ };
6770
+ }
6771
+
4206
6772
  // src/transform-handler.ts
4207
6773
  function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
6774
+ if (systemPrompt.trim().length === 0) {
6775
+ return processedPrompt;
6776
+ }
4208
6777
  const systemIndex = processedPrompt.findIndex((m) => m.role === "system");
4209
6778
  if (systemIndex !== -1) {
4210
6779
  const existing = processedPrompt[systemIndex].content;
@@ -4254,13 +6823,9 @@ function buildBaseReturnParams(params, finalPrompt, functionTools) {
4254
6823
  prompt: finalPrompt,
4255
6824
  tools: [],
4256
6825
  toolChoice: void 0,
4257
- providerOptions: {
4258
- ...params.providerOptions || {},
4259
- toolCallMiddleware: {
4260
- ...params.providerOptions && typeof params.providerOptions === "object" && params.providerOptions.toolCallMiddleware || {},
4261
- originalTools: originalToolsSchema.encode(functionTools)
4262
- }
4263
- }
6826
+ providerOptions: mergeToolCallMiddlewareOptions(params.providerOptions, {
6827
+ originalTools: originalToolsSchema.encode(functionTools)
6828
+ })
4264
6829
  };
4265
6830
  }
4266
6831
  function findProviderDefinedTool(tools, selectedToolName) {
@@ -4312,13 +6877,10 @@ function handleToolChoiceTool(params, baseReturnParams) {
4312
6877
  name: selectedTool.name,
4313
6878
  description: typeof selectedTool.description === "string" ? selectedTool.description : void 0
4314
6879
  },
4315
- providerOptions: {
4316
- ...baseReturnParams.providerOptions || {},
4317
- toolCallMiddleware: {
4318
- ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
4319
- ...params.toolChoice ? { toolChoice: params.toolChoice } : {}
4320
- }
4321
- }
6880
+ providerOptions: mergeToolCallMiddlewareOptions(
6881
+ baseReturnParams.providerOptions,
6882
+ params.toolChoice ? { toolChoice: params.toolChoice } : {}
6883
+ )
4322
6884
  };
4323
6885
  }
4324
6886
  function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
@@ -4338,13 +6900,12 @@ function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
4338
6900
  type: "json",
4339
6901
  schema: createDynamicIfThenElseSchema(functionTools)
4340
6902
  },
4341
- providerOptions: {
4342
- ...baseReturnParams.providerOptions || {},
4343
- toolCallMiddleware: {
4344
- ...baseReturnParams.providerOptions && typeof baseReturnParams.providerOptions === "object" && baseReturnParams.providerOptions.toolCallMiddleware || {},
6903
+ providerOptions: mergeToolCallMiddlewareOptions(
6904
+ baseReturnParams.providerOptions,
6905
+ {
4345
6906
  toolChoice: { type: "required" }
4346
6907
  }
4347
- }
6908
+ )
4348
6909
  };
4349
6910
  }
4350
6911
  function transformParams({
@@ -4400,94 +6961,30 @@ function transformParams({
4400
6961
  }
4401
6962
  return baseReturnParams;
4402
6963
  }
4403
- function processAssistantContent(content, resolvedProtocol, providerOptions) {
4404
- var _a;
4405
- const newContent = [];
4406
- for (const item of content) {
4407
- switch (item.type) {
4408
- case "tool-call":
4409
- newContent.push({
4410
- type: "text",
4411
- text: resolvedProtocol.formatToolCall(item)
4412
- });
4413
- break;
4414
- case "text":
4415
- case "reasoning":
4416
- newContent.push(item);
4417
- break;
4418
- default: {
4419
- const options = extractOnErrorOption(providerOptions);
4420
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4421
- options,
4422
- "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
4423
- { content: item }
4424
- );
4425
- newContent.push({
4426
- type: "text",
4427
- text: JSON.stringify(item)
4428
- });
4429
- }
4430
- }
4431
- }
4432
- const onlyText = newContent.every((c) => c.type === "text");
4433
- return onlyText ? [
4434
- {
4435
- type: "text",
4436
- text: newContent.map((c) => c.text).join("\n")
4437
- }
4438
- ] : newContent;
4439
- }
4440
- function formatApprovalResponse(part) {
4441
- const status = part.approved ? "Approved" : "Denied";
4442
- const reason = part.reason ? `: ${part.reason}` : "";
4443
- return `[Tool Approval ${status}${reason}]`;
4444
- }
4445
- function processToolMessage(toolResults, approvalResponses, toolResponsePromptTemplate) {
4446
- const resultTexts = toolResults.map((toolResult) => {
4447
- return toolResponsePromptTemplate(toolResult);
4448
- });
4449
- const approvalTexts = approvalResponses.map(formatApprovalResponse);
4450
- const allTexts = [...resultTexts, ...approvalTexts];
4451
- return {
4452
- role: "user",
4453
- content: [
4454
- {
4455
- type: "text",
4456
- text: allTexts.join("\n")
4457
- }
4458
- ]
4459
- };
4460
- }
4461
6964
  function processMessage(message, resolvedProtocol, providerOptions, toolResponsePromptTemplate) {
4462
6965
  if (message.role === "assistant") {
4463
- const condensedContent = processAssistantContent(
4464
- message.content,
4465
- resolvedProtocol,
4466
- providerOptions
4467
- );
6966
+ const condensedContent = assistantToolCallsToTextContent({
6967
+ content: message.content,
6968
+ protocol: resolvedProtocol,
6969
+ conversionOptions: {
6970
+ onError: providerOptions == null ? void 0 : providerOptions.onError
6971
+ }
6972
+ });
4468
6973
  return {
4469
6974
  role: "assistant",
4470
6975
  content: condensedContent
4471
6976
  };
4472
6977
  }
4473
6978
  if (message.role === "tool") {
4474
- const toolContent = message.content;
4475
- const toolResultParts = toolContent.filter(
4476
- (part) => part.type === "tool-result"
4477
- );
4478
- const approvalResponseParts = toolContent.filter(
4479
- (part) => part.type === "tool-approval-response"
4480
- );
4481
6979
  if (!toolResponsePromptTemplate) {
4482
6980
  throw new Error(
4483
6981
  'toolResponsePromptTemplate is required when processing messages with role "tool". This parameter is optional for other roles but is required here so tool-result content can be converted into a prompt. Ensure your middleware or transform configuration passes a toolResponsePromptTemplate when tool message processing is enabled.'
4484
6982
  );
4485
6983
  }
4486
- return processToolMessage(
4487
- toolResultParts,
4488
- approvalResponseParts,
6984
+ return toolRoleContentToUserTextMessage({
6985
+ toolContent: message.content,
4489
6986
  toolResponsePromptTemplate
4490
- );
6987
+ });
4491
6988
  }
4492
6989
  return message;
4493
6990
  }
@@ -4538,6 +7035,9 @@ function mergeConsecutiveUserMessages(processedPrompt) {
4538
7035
  const current = processedPrompt[i];
4539
7036
  const prev = processedPrompt[i - 1];
4540
7037
  if (current.role === "user" && prev.role === "user") {
7038
+ if (!(isAllTextContent(prev.content) && isAllTextContent(current.content))) {
7039
+ continue;
7040
+ }
4541
7041
  const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
4542
7042
  const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
4543
7043
  processedPrompt[i - 1] = {
@@ -4597,19 +7097,24 @@ function createToolMiddleware({
4597
7097
 
4598
7098
  // src/preconfigured-middleware.ts
4599
7099
  var hermesToolMiddleware = createToolMiddleware({
4600
- protocol: jsonProtocol({}),
7100
+ protocol: hermesProtocol(),
4601
7101
  toolSystemPromptTemplate: hermesSystemPromptTemplate,
4602
- toolResponsePromptTemplate: formatToolResponseAsJsonInXml
7102
+ toolResponsePromptTemplate: formatToolResponseAsHermes
7103
+ });
7104
+ var qwen3CoderToolMiddleware = createToolMiddleware({
7105
+ protocol: qwen3CoderProtocol,
7106
+ toolSystemPromptTemplate: qwen3coderSystemPromptTemplate,
7107
+ toolResponsePromptTemplate: formatToolResponseAsQwen3CoderXml
4603
7108
  });
4604
- var xmlToolMiddleware = createToolMiddleware({
4605
- protocol: xmlProtocol({}),
4606
- toolSystemPromptTemplate: xmlSystemPromptTemplate,
4607
- toolResponsePromptTemplate: formatToolResponseAsXml
7109
+ var morphXmlToolMiddleware = createToolMiddleware({
7110
+ protocol: morphXmlProtocol({}),
7111
+ toolSystemPromptTemplate: morphXmlSystemPromptTemplate,
7112
+ toolResponsePromptTemplate: morphFormatToolResponseAsXml
4608
7113
  });
4609
- var yamlToolMiddleware = createToolMiddleware({
4610
- protocol: yamlProtocol({}),
4611
- toolSystemPromptTemplate: yamlSystemPromptTemplate,
4612
- toolResponsePromptTemplate: formatToolResponseAsXml
7114
+ var yamlXmlToolMiddleware = createToolMiddleware({
7115
+ protocol: yamlXmlProtocol({}),
7116
+ toolSystemPromptTemplate: yamlXmlSystemPromptTemplate,
7117
+ toolResponsePromptTemplate: formatToolResponseAsYaml
4613
7118
  });
4614
7119
 
4615
7120
  export {
@@ -4619,27 +7124,35 @@ export {
4619
7124
  logParsedChunk,
4620
7125
  logParsedSummary,
4621
7126
  getPotentialStartIndex,
4622
- jsonProtocol,
7127
+ hermesProtocol,
7128
+ morphXmlProtocol,
4623
7129
  isProtocolFactory,
4624
7130
  isTCMProtocolFactory,
4625
- xmlProtocol,
4626
- yamlProtocol,
7131
+ qwen3CoderProtocol,
7132
+ uiTarsXmlProtocol,
7133
+ Qwen3CoderToolParser,
7134
+ yamlXmlProtocol,
4627
7135
  createDynamicIfThenElseSchema,
4628
7136
  extractOnErrorOption,
4629
7137
  originalToolsSchema,
4630
7138
  encodeOriginalTools,
4631
7139
  decodeOriginalTools,
7140
+ decodeOriginalToolsFromProviderOptions,
4632
7141
  extractToolNamesFromOriginalTools,
7142
+ getToolCallMiddlewareOptions,
7143
+ mergeToolCallMiddlewareOptions,
4633
7144
  isToolChoiceActive,
4634
7145
  isToolResultPart,
4635
7146
  hasInputProperty,
4636
7147
  wrapGenerate,
7148
+ morphFormatToolResponseAsXml,
4637
7149
  wrapStream,
4638
7150
  toolChoiceStream,
4639
7151
  transformParams,
4640
7152
  createToolMiddleware,
4641
7153
  hermesToolMiddleware,
4642
- xmlToolMiddleware,
4643
- yamlToolMiddleware
7154
+ qwen3CoderToolMiddleware,
7155
+ morphXmlToolMiddleware,
7156
+ yamlXmlToolMiddleware
4644
7157
  };
4645
- //# sourceMappingURL=chunk-DPGORNPB.js.map
7158
+ //# sourceMappingURL=chunk-722D5BGD.js.map