@ai-sdk-tool/parser 3.0.0-canary.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,44 @@
1
- // src/protocols/json-mix-protocol.ts
2
- import { generateId } from "@ai-sdk/provider-utils";
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/v6/index.ts
31
+ var v6_exports = {};
32
+ __export(v6_exports, {
33
+ createToolMiddleware: () => createToolMiddleware,
34
+ gemmaToolMiddleware: () => gemmaToolMiddleware,
35
+ hermesToolMiddleware: () => hermesToolMiddleware,
36
+ morphXmlToolMiddleware: () => morphXmlToolMiddleware,
37
+ orchestratorToolMiddleware: () => orchestratorToolMiddleware
38
+ });
39
+ module.exports = __toCommonJS(v6_exports);
3
40
 
4
- // src/utils/debug.ts
41
+ // src/core/utils/debug.ts
5
42
  var LINE_SPLIT_REGEX = /\r?\n/;
6
43
  function normalizeBooleanString(value) {
7
44
  const normalized = value.trim().toLowerCase();
@@ -156,7 +193,7 @@ ${rendered}`);
156
193
  }
157
194
  }
158
195
 
159
- // src/utils/get-potential-start-index.ts
196
+ // src/core/utils/get-potential-start-index.ts
160
197
  function getPotentialStartIndex(text, searchedText) {
161
198
  if (searchedText.length === 0) {
162
199
  return null;
@@ -174,12 +211,17 @@ function getPotentialStartIndex(text, searchedText) {
174
211
  return null;
175
212
  }
176
213
 
177
- // src/utils/regex.ts
214
+ // src/core/utils/id.ts
215
+ function generateId() {
216
+ return Math.random().toString(36).substring(2, 15);
217
+ }
218
+
219
+ // src/core/utils/regex.ts
178
220
  function escapeRegExp(literal) {
179
221
  return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
180
222
  }
181
223
 
182
- // src/utils/robust-json.ts
224
+ // src/core/utils/robust-json.ts
183
225
  var WHITESPACE_TEST_REGEX = /\s/;
184
226
  var WHITESPACE_REGEX = /^\s+/;
185
227
  var OBJECT_START_REGEX = /^\{/;
@@ -420,11 +462,6 @@ function stripTrailingComma(tokens) {
420
462
  });
421
463
  return res;
422
464
  }
423
- function transform(text) {
424
- let tokens = lexer(text);
425
- tokens = stripTrailingComma(tokens);
426
- return tokens.reduce((str, token) => str + token.match, "");
427
- }
428
465
  function popToken(tokens, state) {
429
466
  var _a, _b;
430
467
  const token = tokens[state.pos];
@@ -820,33 +857,10 @@ function parse(text, optsOrReviver) {
820
857
  }
821
858
  return parseWithTransform(text, options);
822
859
  }
823
- function stringifyPair(obj, key) {
824
- return `${JSON.stringify(key)}:${stringify(obj[key])}`;
825
- }
826
- function stringify(obj) {
827
- const type = typeof obj;
828
- if (type === "string" || type === "number" || type === "boolean" || obj === null) {
829
- return JSON.stringify(obj);
830
- }
831
- if (type === "undefined") {
832
- return "null";
833
- }
834
- if (Array.isArray(obj)) {
835
- const elements = obj.map(stringify).join(",");
836
- return `[${elements}]`;
837
- }
838
- if (type === "object") {
839
- const keys = Object.keys(obj);
840
- keys.sort();
841
- const pairs = keys.map((key) => stringifyPair(obj, key)).join(",");
842
- return `{${pairs}}`;
843
- }
844
- return "null";
845
- }
846
860
 
847
- // src/protocols/json-mix-protocol.ts
861
+ // src/core/protocols/json-mix-protocol.ts
848
862
  function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
849
- var _a;
863
+ var _a, _b;
850
864
  try {
851
865
  const parsedToolCall = parse(toolCallJson);
852
866
  processedElements.push({
@@ -862,12 +876,11 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
862
876
  snippet: fullMatch,
863
877
  error
864
878
  });
865
- if (options == null ? void 0 : options.onError) {
866
- options.onError(
867
- "Could not process JSON tool call, keeping original text.",
868
- { toolCall: fullMatch, error }
869
- );
870
- }
879
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
880
+ options,
881
+ "Could not process JSON tool call, keeping original text.",
882
+ { toolCall: fullMatch, error }
883
+ );
871
884
  processedElements.push({ type: "text", text: fullMatch });
872
885
  }
873
886
  }
@@ -895,20 +908,27 @@ function flushBuffer(state, controller, toolCallStart) {
895
908
  }
896
909
  if (!state.currentTextId) {
897
910
  state.currentTextId = generateId();
898
- controller.enqueue({ type: "text-start", id: state.currentTextId });
911
+ controller.enqueue({
912
+ type: "text-start",
913
+ id: state.currentTextId
914
+ });
899
915
  state.hasEmittedTextStart = true;
900
916
  }
901
- const delta = state.isInsideToolCall ? `${toolCallStart}${state.buffer}` : state.buffer;
917
+ const deltaContent = state.isInsideToolCall ? `${toolCallStart}${state.buffer}` : state.buffer;
902
918
  controller.enqueue({
903
919
  type: "text-delta",
904
920
  id: state.currentTextId,
905
- delta
921
+ textDelta: deltaContent,
922
+ delta: deltaContent
906
923
  });
907
924
  state.buffer = "";
908
925
  }
909
926
  function closeTextBlock(state, controller) {
910
927
  if (state.currentTextId && state.hasEmittedTextStart) {
911
- controller.enqueue({ type: "text-end", id: state.currentTextId });
928
+ controller.enqueue({
929
+ type: "text-end",
930
+ id: state.currentTextId
931
+ });
912
932
  state.currentTextId = null;
913
933
  state.hasEmittedTextStart = false;
914
934
  }
@@ -923,13 +943,21 @@ function emitIncompleteToolCall(state, controller, toolCallStart) {
923
943
  snippet: `${toolCallStart}${state.currentToolCallJson}`
924
944
  });
925
945
  const errorId = generateId();
926
- controller.enqueue({ type: "text-start", id: errorId });
946
+ const errorContent = `${toolCallStart}${state.currentToolCallJson}`;
947
+ controller.enqueue({
948
+ type: "text-start",
949
+ id: errorId
950
+ });
927
951
  controller.enqueue({
928
952
  type: "text-delta",
929
953
  id: errorId,
930
- delta: `${toolCallStart}${state.currentToolCallJson}`
954
+ textDelta: errorContent,
955
+ delta: errorContent
956
+ });
957
+ controller.enqueue({
958
+ type: "text-end",
959
+ id: errorId
931
960
  });
932
- controller.enqueue({ type: "text-end", id: errorId });
933
961
  state.currentToolCallJson = "";
934
962
  }
935
963
  function handleFinishChunk(state, controller, toolCallStart, chunk) {
@@ -947,18 +975,22 @@ function publishText(text, state, controller) {
947
975
  } else if (text.length > 0) {
948
976
  if (!state.currentTextId) {
949
977
  state.currentTextId = generateId();
950
- controller.enqueue({ type: "text-start", id: state.currentTextId });
978
+ controller.enqueue({
979
+ type: "text-start",
980
+ id: state.currentTextId
981
+ });
951
982
  state.hasEmittedTextStart = true;
952
983
  }
953
984
  controller.enqueue({
954
985
  type: "text-delta",
955
986
  id: state.currentTextId,
987
+ textDelta: text,
956
988
  delta: text
957
989
  });
958
990
  }
959
991
  }
960
992
  function emitToolCall(context) {
961
- var _a;
993
+ var _a, _b;
962
994
  const { state, controller, toolCallStart, toolCallEnd, options } = context;
963
995
  try {
964
996
  const parsedToolCall = parse(state.currentToolCallJson);
@@ -977,21 +1009,28 @@ function emitToolCall(context) {
977
1009
  error
978
1010
  });
979
1011
  const errorId = generateId();
980
- controller.enqueue({ type: "text-start", id: errorId });
1012
+ const errorContent = `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`;
1013
+ controller.enqueue({
1014
+ type: "text-start",
1015
+ id: errorId
1016
+ });
981
1017
  controller.enqueue({
982
1018
  type: "text-delta",
983
1019
  id: errorId,
984
- delta: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`
1020
+ textDelta: errorContent,
1021
+ delta: errorContent
985
1022
  });
986
- controller.enqueue({ type: "text-end", id: errorId });
987
- if (options == null ? void 0 : options.onError) {
988
- options.onError(
989
- "Could not process streaming JSON tool call; emitting original text.",
990
- {
991
- toolCall: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`
992
- }
993
- );
994
- }
1023
+ controller.enqueue({
1024
+ type: "text-end",
1025
+ id: errorId
1026
+ });
1027
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1028
+ options,
1029
+ "Could not process streaming JSON tool call; emitting original text.",
1030
+ {
1031
+ toolCall: errorContent
1032
+ }
1033
+ );
995
1034
  }
996
1035
  }
997
1036
  function processTagMatch(context) {
@@ -1067,7 +1106,7 @@ var jsonMixProtocol = ({
1067
1106
  formatToolResponse(toolResult) {
1068
1107
  return `${toolResponseStart}${JSON.stringify({
1069
1108
  toolName: toolResult.toolName,
1070
- result: toolResult.output
1109
+ result: toolResult.result
1071
1110
  })}${toolResponseEnd}`;
1072
1111
  },
1073
1112
  parseGeneratedText({ text, options }) {
@@ -1096,7 +1135,7 @@ var jsonMixProtocol = ({
1096
1135
  }
1097
1136
  return processedElements;
1098
1137
  },
1099
- createStreamParser({ tools: _tools, options } = { tools: [] }) {
1138
+ createStreamParser({ options }) {
1100
1139
  const state = {
1101
1140
  isInsideToolCall: false,
1102
1141
  buffer: "",
@@ -1106,6 +1145,7 @@ var jsonMixProtocol = ({
1106
1145
  };
1107
1146
  return new TransformStream({
1108
1147
  transform(chunk, controller) {
1148
+ var _a, _b;
1109
1149
  if (chunk.type === "finish") {
1110
1150
  handleFinishChunk(state, controller, toolCallStart, chunk);
1111
1151
  return;
@@ -1114,7 +1154,8 @@ var jsonMixProtocol = ({
1114
1154
  controller.enqueue(chunk);
1115
1155
  return;
1116
1156
  }
1117
- state.buffer += chunk.delta;
1157
+ const textContent = (_b = (_a = chunk.textDelta) != null ? _a : chunk.delta) != null ? _b : "";
1158
+ state.buffer += textContent;
1118
1159
  processBufferTags({
1119
1160
  state,
1120
1161
  controller,
@@ -1140,19 +1181,10 @@ var jsonMixProtocol = ({
1140
1181
  }
1141
1182
  });
1142
1183
 
1143
- // src/protocols/morph-xml-protocol.ts
1144
- import { generateId as generateId2 } from "@ai-sdk/provider-utils";
1145
- import {
1146
- extractRawInner,
1147
- parse as parse3,
1148
- RXMLCoercionError,
1149
- RXMLDuplicateStringTagError,
1150
- RXMLParseError,
1151
- stringify as stringify2,
1152
- unwrapJsonSchema as unwrapJsonSchema2
1153
- } from "@ai-sdk-tool/rxml";
1184
+ // src/core/protocols/morph-xml-protocol.ts
1185
+ var import_rxml2 = require("@ai-sdk-tool/rxml");
1154
1186
 
1155
- // src/heuristics/engine.ts
1187
+ // src/core/heuristics/engine.ts
1156
1188
  function applyRawSegmentUpdate(current, result) {
1157
1189
  if (result.rawSegment !== void 0) {
1158
1190
  return { ...current, rawSegment: result.rawSegment };
@@ -1253,32 +1285,9 @@ function createIntermediateCall(toolName, rawSegment, schema) {
1253
1285
  meta: { originalContent: rawSegment }
1254
1286
  };
1255
1287
  }
1256
- function mergePipelineConfigs(...configs) {
1257
- var _a, _b, _c;
1258
- const result = {
1259
- preParse: [],
1260
- fallbackReparse: [],
1261
- postParse: []
1262
- };
1263
- for (const config of configs) {
1264
- if (config.preParse) {
1265
- result.preParse = [...(_a = result.preParse) != null ? _a : [], ...config.preParse];
1266
- }
1267
- if (config.fallbackReparse) {
1268
- result.fallbackReparse = [
1269
- ...(_b = result.fallbackReparse) != null ? _b : [],
1270
- ...config.fallbackReparse
1271
- ];
1272
- }
1273
- if (config.postParse) {
1274
- result.postParse = [...(_c = result.postParse) != null ? _c : [], ...config.postParse];
1275
- }
1276
- }
1277
- return result;
1278
- }
1279
1288
 
1280
- // src/heuristics/xml-defaults.ts
1281
- import { parse as parse2, unwrapJsonSchema } from "@ai-sdk-tool/rxml";
1289
+ // src/core/heuristics/xml-defaults.ts
1290
+ var import_rxml = require("@ai-sdk-tool/rxml");
1282
1291
  var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
1283
1292
  var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
1284
1293
  var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
@@ -1487,7 +1496,7 @@ function handleOpeningTagSegment(src, lt, out, stack) {
1487
1496
  return q + 1;
1488
1497
  }
1489
1498
  function shouldDeduplicateStringTags(schema) {
1490
- const unwrapped = unwrapJsonSchema(schema);
1499
+ const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
1491
1500
  if (!unwrapped || typeof unwrapped !== "object") {
1492
1501
  return false;
1493
1502
  }
@@ -1499,11 +1508,11 @@ function shouldDeduplicateStringTags(schema) {
1499
1508
  if (!commandRaw) {
1500
1509
  return false;
1501
1510
  }
1502
- const command = unwrapJsonSchema(commandRaw);
1511
+ const command = (0, import_rxml.unwrapJsonSchema)(commandRaw);
1503
1512
  return (command == null ? void 0 : command.type) === "array";
1504
1513
  }
1505
1514
  function getStringPropertyNames(schema) {
1506
- const unwrapped = unwrapJsonSchema(schema);
1515
+ const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
1507
1516
  if (!unwrapped || typeof unwrapped !== "object") {
1508
1517
  return [];
1509
1518
  }
@@ -1513,7 +1522,7 @@ function getStringPropertyNames(schema) {
1513
1522
  }
1514
1523
  const names = [];
1515
1524
  for (const key of Object.keys(props)) {
1516
- const prop = unwrapJsonSchema(
1525
+ const prop = (0, import_rxml.unwrapJsonSchema)(
1517
1526
  props[key]
1518
1527
  );
1519
1528
  const type = prop.type;
@@ -1552,7 +1561,7 @@ function repairParsedAgainstSchema(input, schema) {
1552
1561
  if (!input || typeof input !== "object") {
1553
1562
  return input;
1554
1563
  }
1555
- const unwrapped = unwrapJsonSchema(schema);
1564
+ const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
1556
1565
  if (!unwrapped || typeof unwrapped !== "object") {
1557
1566
  return input;
1558
1567
  }
@@ -1569,11 +1578,11 @@ function applySchemaProps(obj, properties) {
1569
1578
  if (!propSchema) {
1570
1579
  continue;
1571
1580
  }
1572
- const prop = unwrapJsonSchema(propSchema);
1581
+ const prop = (0, import_rxml.unwrapJsonSchema)(propSchema);
1573
1582
  const propType = prop.type;
1574
1583
  if (propType === "array" && prop.items) {
1575
1584
  const itemSchemaRaw = prop.items;
1576
- const itemSchema = unwrapJsonSchema(itemSchemaRaw);
1585
+ const itemSchema = (0, import_rxml.unwrapJsonSchema)(itemSchemaRaw);
1577
1586
  obj[key] = coerceArrayItems(obj[key], itemSchema);
1578
1587
  continue;
1579
1588
  }
@@ -1614,7 +1623,7 @@ function coerceArrayItem(v, itemSchema) {
1614
1623
  function tryParseStringToSchemaObject(xml, itemSchema) {
1615
1624
  try {
1616
1625
  const normalized = xml.replace(MALFORMED_CLOSE_RE_G, "</$1>");
1617
- const fixed = parse2(normalized, itemSchema, { noChildNodes: [] });
1626
+ const fixed = (0, import_rxml.parse)(normalized, itemSchema, { noChildNodes: [] });
1618
1627
  return typeof fixed === "string" ? null : fixed;
1619
1628
  } catch (e) {
1620
1629
  return null;
@@ -1629,40 +1638,21 @@ function extractStepStatusFromString(normXml) {
1629
1638
  return null;
1630
1639
  }
1631
1640
 
1632
- // src/utils/type-guards.ts
1633
- function isToolCallContent(content) {
1634
- return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
1635
- (typeof content.input === "string" || typeof content.input === "object");
1636
- }
1637
- function isToolResultPart(content) {
1638
- const c = content;
1639
- return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
1640
- }
1641
- function hasInputProperty(obj) {
1642
- return typeof obj === "object" && obj !== null && "input" in obj;
1643
- }
1644
-
1645
- // src/protocols/morph-xml-protocol.ts
1641
+ // src/core/protocols/morph-xml-protocol.ts
1646
1642
  var defaultPipelineConfig2 = defaultPipelineConfig;
1647
- var applyHeuristicPipeline2 = applyHeuristicPipeline;
1648
- var createIntermediateCall2 = createIntermediateCall;
1649
- var mergePipelineConfigs2 = mergePipelineConfigs;
1650
- var WHITESPACE_REGEX3 = /\s/;
1651
- var MALFORMED_CLOSE_RE2 = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
1652
- var MALFORMED_CLOSE_RE_G2 = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
1653
1643
  var NAME_CHAR_RE2 = /[A-Za-z0-9_:-]/;
1644
+ var WHITESPACE_REGEX3 = /\s/;
1645
+ function getToolSchema(tools, toolName) {
1646
+ var _a;
1647
+ return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
1648
+ }
1654
1649
  function normalizeCloseTags(xml) {
1655
- return xml.replace(MALFORMED_CLOSE_RE_G2, "</$1>");
1650
+ return xml.replace(/<\/\s+([A-Za-z0-9_:-]+)\s*>/g, "</$1>");
1656
1651
  }
1657
1652
  function tryParseSecondaryXml(content, toolSchema, options) {
1658
- const normalized = normalizeCloseTags(content);
1659
1653
  const balanced = balanceTags(content);
1660
- const hasMalformedClose = MALFORMED_CLOSE_RE2.test(content);
1661
- if (!hasMalformedClose && balanced.length > normalized.length) {
1662
- return null;
1663
- }
1664
1654
  try {
1665
- let parsed = parse3(balanced, toolSchema, {
1655
+ let parsed = (0, import_rxml2.parse)(balanced, toolSchema, {
1666
1656
  onError: options == null ? void 0 : options.onError,
1667
1657
  noChildNodes: []
1668
1658
  });
@@ -1670,10 +1660,14 @@ function tryParseSecondaryXml(content, toolSchema, options) {
1670
1660
  return parsed;
1671
1661
  } catch (e) {
1672
1662
  if (shouldDeduplicateStringTags(toolSchema)) {
1673
- const deduped = dedupeStringTagsAgainstSchema(balanced, toolSchema);
1663
+ const names = getStringPropertyNames(toolSchema);
1664
+ let deduped = balanced;
1665
+ for (const key of names) {
1666
+ deduped = dedupeSingleTag(deduped, key);
1667
+ }
1674
1668
  if (deduped !== balanced) {
1675
1669
  try {
1676
- let reparsed = parse3(deduped, toolSchema, {
1670
+ let reparsed = (0, import_rxml2.parse)(deduped, toolSchema, {
1677
1671
  onError: options == null ? void 0 : options.onError,
1678
1672
  noChildNodes: []
1679
1673
  });
@@ -1687,23 +1681,6 @@ function tryParseSecondaryXml(content, toolSchema, options) {
1687
1681
  return null;
1688
1682
  }
1689
1683
  }
1690
- function dedupeStringTagsAgainstSchema(xml, schema) {
1691
- const names = getStringPropertyNames(schema);
1692
- let out = xml;
1693
- for (const key of names) {
1694
- out = dedupeSingleTag(out, key);
1695
- }
1696
- return out;
1697
- }
1698
- function processTextBeforeToolCall(text, currentIndex, toolCallStartIndex, processedElements) {
1699
- if (toolCallStartIndex > currentIndex) {
1700
- const textSegment = text.substring(currentIndex, toolCallStartIndex);
1701
- if (textSegment.trim()) {
1702
- processedElements.push({ type: "text", text: textSegment });
1703
- }
1704
- }
1705
- return currentIndex;
1706
- }
1707
1684
  function processToolCallWithPipeline(params) {
1708
1685
  var _a;
1709
1686
  const {
@@ -1716,20 +1693,20 @@ function processToolCallWithPipeline(params) {
1716
1693
  maxReparses
1717
1694
  } = params;
1718
1695
  const toolSchema = getToolSchema(tools, toolCall.toolName);
1719
- const ctx = createIntermediateCall2(
1696
+ const ctx = createIntermediateCall(
1720
1697
  toolCall.toolName,
1721
1698
  toolCall.content,
1722
1699
  toolSchema
1723
1700
  );
1724
- const result = applyHeuristicPipeline2(ctx, pipelineConfig, {
1725
- parse: (xml, schema) => parse3(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
1701
+ const result = applyHeuristicPipeline(ctx, pipelineConfig, {
1702
+ parse: (xml, schema) => (0, import_rxml2.parse)(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
1726
1703
  onError: options == null ? void 0 : options.onError,
1727
1704
  maxReparses
1728
1705
  });
1729
1706
  if (result.parsed !== null) {
1730
1707
  processedElements.push({
1731
1708
  type: "tool-call",
1732
- toolCallId: generateId2(),
1709
+ toolCallId: generateId(),
1733
1710
  toolName: toolCall.toolName,
1734
1711
  input: JSON.stringify(result.parsed)
1735
1712
  });
@@ -1738,69 +1715,15 @@ function processToolCallWithPipeline(params) {
1738
1715
  toolCall.startIndex,
1739
1716
  toolCall.endIndex
1740
1717
  );
1741
- const message = `Could not process XML tool call, keeping original text: ${originalCallText}`;
1742
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1743
- toolCall: originalCallText,
1744
- toolName: toolCall.toolName,
1745
- error: result.errors[0]
1746
- });
1747
- processedElements.push({ type: "text", text: originalCallText });
1748
- }
1749
- }
1750
- function processToolCall(params) {
1751
- var _a;
1752
- const { toolCall, tools, options, text, processedElements } = params;
1753
- const toolSchema = getToolSchema(tools, toolCall.toolName);
1754
- try {
1755
- const primary = escapeInvalidLt(normalizeCloseTags(toolCall.content));
1756
- let parsed = parse3(primary, toolSchema, {
1757
- onError: options == null ? void 0 : options.onError,
1758
- noChildNodes: []
1759
- });
1760
- parsed = repairParsedAgainstSchema(parsed, toolSchema);
1761
- processedElements.push({
1762
- type: "tool-call",
1763
- toolCallId: generateId2(),
1764
- toolName: toolCall.toolName,
1765
- input: JSON.stringify(parsed)
1766
- });
1767
- } catch (error) {
1768
- const reparsed = tryParseSecondaryXml(
1769
- toolCall.content,
1770
- toolSchema,
1771
- options
1772
- );
1773
- if (reparsed !== null) {
1774
- processedElements.push({
1775
- type: "tool-call",
1776
- toolCallId: generateId2(),
1777
- toolName: toolCall.toolName,
1778
- input: JSON.stringify(reparsed)
1779
- });
1780
- return;
1781
- }
1782
- const originalCallText = text.substring(
1783
- toolCall.startIndex,
1784
- toolCall.endIndex
1718
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
1719
+ options,
1720
+ `Could not process XML tool call: ${toolCall.toolName}`,
1721
+ { toolCall: originalCallText, error: result.errors[0] }
1785
1722
  );
1786
- const message = `Could not process XML tool call, keeping original text: ${originalCallText}`;
1787
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1788
- toolCall: originalCallText,
1789
- toolName: toolCall.toolName,
1790
- error
1791
- });
1792
1723
  processedElements.push({ type: "text", text: originalCallText });
1793
1724
  }
1794
1725
  }
1795
- function addRemainingText(text, currentIndex, processedElements) {
1796
- if (currentIndex < text.length) {
1797
- const remainingText = text.substring(currentIndex);
1798
- if (remainingText.trim()) {
1799
- processedElements.push({ type: "text", text: remainingText });
1800
- }
1801
- }
1802
- }
1803
- function handleStreamingToolCallEndWithPipeline(params) {
1726
+ function handleStreamingToolCallEnd(params) {
1804
1727
  var _a;
1805
1728
  const {
1806
1729
  toolContent,
@@ -1809,577 +1732,581 @@ function handleStreamingToolCallEndWithPipeline(params) {
1809
1732
  options,
1810
1733
  ctrl,
1811
1734
  flushText,
1812
- pipelineConfig = defaultPipelineConfig2,
1735
+ pipelineConfig,
1813
1736
  maxReparses
1814
1737
  } = params;
1815
1738
  const toolSchema = getToolSchema(tools, currentToolCall.name);
1816
- const ctx = createIntermediateCall2(
1817
- currentToolCall.name,
1818
- toolContent,
1819
- toolSchema
1820
- );
1821
- const result = applyHeuristicPipeline2(ctx, pipelineConfig, {
1822
- parse: (xml, schema) => parse3(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
1823
- onError: options == null ? void 0 : options.onError,
1824
- maxReparses
1825
- });
1739
+ let parsedResult = null;
1740
+ if (pipelineConfig) {
1741
+ const ctx = createIntermediateCall(
1742
+ currentToolCall.name,
1743
+ toolContent,
1744
+ toolSchema
1745
+ );
1746
+ const result = applyHeuristicPipeline(ctx, pipelineConfig, {
1747
+ parse: (xml, schema) => (0, import_rxml2.parse)(xml, schema, { onError: options == null ? void 0 : options.onError, noChildNodes: [] }),
1748
+ onError: options == null ? void 0 : options.onError,
1749
+ maxReparses
1750
+ });
1751
+ parsedResult = result.parsed;
1752
+ } else {
1753
+ try {
1754
+ const primary = escapeInvalidLt(normalizeCloseTags(toolContent));
1755
+ const parsed = (0, import_rxml2.parse)(primary, toolSchema, {
1756
+ onError: options == null ? void 0 : options.onError,
1757
+ noChildNodes: []
1758
+ });
1759
+ parsedResult = repairParsedAgainstSchema(parsed, toolSchema);
1760
+ } catch (e) {
1761
+ parsedResult = tryParseSecondaryXml(
1762
+ toolContent,
1763
+ toolSchema,
1764
+ options != null ? options : {}
1765
+ );
1766
+ }
1767
+ }
1826
1768
  flushText(ctrl);
1827
- if (result.parsed !== null) {
1769
+ if (parsedResult !== null) {
1828
1770
  ctrl.enqueue({
1829
1771
  type: "tool-call",
1830
- toolCallId: generateId2(),
1772
+ toolCallId: generateId(),
1831
1773
  toolName: currentToolCall.name,
1832
- input: JSON.stringify(result.parsed)
1774
+ input: JSON.stringify(parsedResult)
1833
1775
  });
1834
1776
  } else {
1835
- const endTag = `</${currentToolCall.name}>`;
1836
- const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
1837
- const error = result.errors[0];
1838
- let message = "Could not process streaming XML tool call; emitting original text.";
1839
- if (error instanceof RXMLDuplicateStringTagError) {
1840
- message = `Duplicate string tags detected in streaming tool call '${currentToolCall.name}'; emitting original text.`;
1841
- } else if (error instanceof RXMLCoercionError) {
1842
- message = `Failed to coerce arguments for streaming tool call '${currentToolCall.name}'; emitting original text.`;
1843
- } else if (error instanceof RXMLParseError) {
1844
- message = `Failed to parse XML for streaming tool call '${currentToolCall.name}'; emitting original text.`;
1845
- }
1846
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1847
- toolCall: originalCallText,
1848
- toolName: currentToolCall.name,
1849
- error
1777
+ const original = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
1778
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not process streaming XML tool call", {
1779
+ toolCall: original
1850
1780
  });
1851
- flushText(ctrl, originalCallText);
1781
+ flushText(ctrl, original);
1852
1782
  }
1853
1783
  }
1854
- function handleStreamingToolCallEnd(params) {
1855
- const { toolContent, currentToolCall, tools, options, ctrl, flushText } = params;
1856
- const toolSchema = getToolSchema(tools, currentToolCall.name);
1857
- try {
1858
- const primary = escapeInvalidLt(normalizeCloseTags(toolContent));
1859
- let parsed = parse3(primary, toolSchema, {
1860
- onError: options == null ? void 0 : options.onError,
1861
- noChildNodes: []
1862
- });
1863
- parsed = repairParsedAgainstSchema(parsed, toolSchema);
1864
- flushText(ctrl);
1865
- ctrl.enqueue({
1866
- type: "tool-call",
1867
- toolCallId: generateId2(),
1868
- toolName: currentToolCall.name,
1869
- input: JSON.stringify(parsed)
1870
- });
1871
- } catch (error) {
1872
- const parsed = tryParseSecondaryXml(toolContent, toolSchema, options);
1873
- if (parsed !== null) {
1874
- flushText(ctrl);
1875
- ctrl.enqueue({
1876
- type: "tool-call",
1877
- toolCallId: generateId2(),
1878
- toolName: currentToolCall.name,
1879
- input: JSON.stringify(parsed)
1880
- });
1881
- return;
1784
+ function findClosingTagEndFlexible(text, contentStart, toolName) {
1785
+ let pos = contentStart;
1786
+ let depth = 1;
1787
+ while (pos < text.length) {
1788
+ const tok = nextTagToken(text, pos);
1789
+ if (tok.kind === "eof") {
1790
+ break;
1882
1791
  }
1883
- handleStreamingToolCallError({
1884
- error,
1885
- currentToolCall,
1886
- toolContent,
1887
- options,
1888
- ctrl,
1889
- flushText
1890
- });
1792
+ const result = updateDepthWithToken(tok, toolName, depth);
1793
+ depth = result.depth;
1794
+ if (result.closedAt !== void 0) {
1795
+ return result.closedAt;
1796
+ }
1797
+ pos = tok.nextPos;
1891
1798
  }
1799
+ return -1;
1892
1800
  }
1893
- function handleStreamingToolCallError(params) {
1894
- var _a;
1895
- const { error, currentToolCall, toolContent, options, ctrl, flushText } = params;
1896
- const endTag = `</${currentToolCall.name}>`;
1897
- const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
1898
- let message = "Could not process streaming XML tool call; emitting original text.";
1899
- if (error instanceof RXMLDuplicateStringTagError) {
1900
- message = `Duplicate string tags detected in streaming tool call '${currentToolCall.name}'; emitting original text.`;
1901
- } else if (error instanceof RXMLCoercionError) {
1902
- message = `Failed to coerce arguments for streaming tool call '${currentToolCall.name}'; emitting original text.`;
1903
- } else if (error instanceof RXMLParseError) {
1904
- message = `Failed to parse XML for streaming tool call '${currentToolCall.name}'; emitting original text.`;
1905
- }
1906
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1907
- toolCall: originalCallText,
1908
- toolName: currentToolCall.name,
1909
- error
1910
- });
1911
- flushText(ctrl, originalCallText);
1912
- }
1913
- function findEarliestToolTag(buffer, toolNames) {
1914
- let bestIndex = -1;
1915
- let bestName = "";
1916
- let bestSelfClosing = false;
1917
- if (toolNames.length > 0) {
1918
- for (const name of toolNames) {
1919
- const openTag = `<${name}>`;
1920
- const selfTag = `<${name}/>`;
1921
- const idxOpen = buffer.indexOf(openTag);
1922
- const idxSelf = buffer.indexOf(selfTag);
1923
- if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
1924
- bestIndex = idxOpen;
1925
- bestName = name;
1926
- bestSelfClosing = false;
1927
- }
1928
- if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
1929
- bestIndex = idxSelf;
1930
- bestName = name;
1931
- bestSelfClosing = true;
1932
- }
1801
+ function skipSpecialSegment(text, lt) {
1802
+ const next = text[lt + 1];
1803
+ if (next === "!" || next === "?") {
1804
+ const gt = text.indexOf(">", lt + 1);
1805
+ if (gt !== -1) {
1806
+ return gt + 1;
1933
1807
  }
1934
1808
  }
1935
- return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
1809
+ return null;
1810
+ }
1811
+ function consumeClosingTag(text, lt) {
1812
+ const gt = text.indexOf(">", lt + 1);
1813
+ const endPos = gt === -1 ? text.length : gt + 1;
1814
+ return { matched: false, endPos };
1936
1815
  }
1937
- function handleNoToolTagInBuffer(buffer, maxStartTagLen, controller, flushText) {
1938
- const tail = Math.max(0, maxStartTagLen - 1);
1939
- const safeLen = Math.max(0, buffer.length - tail);
1940
- if (safeLen > 0) {
1941
- const textToFlush = buffer.slice(0, safeLen);
1942
- flushText(controller, textToFlush);
1943
- return { buffer: buffer.slice(safeLen), shouldContinue: true };
1816
+ function consumeOpenTag(text, lt) {
1817
+ let p = lt + 1;
1818
+ while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
1819
+ p += 1;
1820
+ }
1821
+ const nameStart = p;
1822
+ while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
1823
+ p += 1;
1824
+ }
1825
+ const name = text.slice(nameStart, p);
1826
+ const q = text.indexOf(">", p);
1827
+ if (q === -1) {
1828
+ return null;
1829
+ }
1830
+ let r = q - 1;
1831
+ while (r >= nameStart && WHITESPACE_REGEX3.test(text[r])) {
1832
+ r -= 1;
1944
1833
  }
1945
- return { buffer, shouldContinue: false };
1834
+ const selfClosing = text[r] === "/";
1835
+ return { name, selfClosing, nextPos: q + 1 };
1946
1836
  }
1947
- function processToolCallInBuffer(params) {
1948
- const {
1949
- buffer,
1950
- currentToolCall,
1951
- tools,
1952
- options,
1953
- controller,
1954
- flushText,
1955
- setBuffer,
1956
- pipelineConfig,
1957
- maxReparses
1958
- } = params;
1959
- const endTag = `</${currentToolCall.name}>`;
1960
- const normalized = normalizeCloseTags(buffer);
1961
- const effectiveBuffer = normalized;
1962
- const endTagIndex = effectiveBuffer.indexOf(endTag);
1963
- if (endTagIndex !== -1) {
1964
- const toolContent = effectiveBuffer.substring(0, endTagIndex);
1965
- const newBuffer = effectiveBuffer.substring(endTagIndex + endTag.length);
1966
- setBuffer("");
1967
- if (pipelineConfig) {
1968
- handleStreamingToolCallEndWithPipeline({
1969
- toolContent,
1970
- currentToolCall,
1971
- tools,
1972
- options,
1973
- ctrl: controller,
1974
- flushText,
1975
- pipelineConfig,
1976
- maxReparses
1977
- });
1978
- } else {
1979
- handleStreamingToolCallEnd({
1980
- toolContent,
1981
- currentToolCall,
1982
- tools,
1983
- options,
1984
- ctrl: controller,
1985
- flushText
1986
- });
1987
- }
1988
- setBuffer(newBuffer);
1989
- return { buffer: newBuffer, currentToolCall: null, shouldBreak: false };
1837
+ function updateDepthWithToken(tok, toolName, depth) {
1838
+ if (tok.kind === "close" && tok.name === toolName) {
1839
+ const newDepth = depth - 1;
1840
+ return newDepth === 0 ? { depth: newDepth, closedAt: tok.nextPos } : { depth: newDepth };
1990
1841
  }
1991
- return { buffer: effectiveBuffer, currentToolCall, shouldBreak: true };
1842
+ if (tok.kind === "open" && tok.name === toolName && !tok.selfClosing) {
1843
+ return { depth: depth + 1 };
1844
+ }
1845
+ return { depth };
1992
1846
  }
1993
- function processNoToolCallInBuffer(params) {
1994
- const {
1995
- buffer,
1996
- toolNames,
1997
- maxStartTagLen,
1998
- controller,
1999
- flushText,
2000
- tools,
2001
- options,
2002
- pipelineConfig,
2003
- maxReparses
2004
- } = params;
2005
- const {
2006
- index: earliestStartTagIndex,
2007
- name: earliestToolName,
2008
- selfClosing
2009
- } = findEarliestToolTag(buffer, toolNames);
2010
- if (earliestStartTagIndex !== -1) {
2011
- const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
2012
- flushText(controller, textBeforeTag);
2013
- if (selfClosing) {
2014
- const selfTag = `<${earliestToolName}/>`;
2015
- const newBuffer2 = buffer.substring(
2016
- earliestStartTagIndex + selfTag.length
2017
- );
2018
- if (pipelineConfig) {
2019
- handleStreamingToolCallEndWithPipeline({
2020
- toolContent: "",
2021
- currentToolCall: { name: earliestToolName, content: "" },
2022
- tools,
2023
- options,
2024
- ctrl: controller,
2025
- flushText,
2026
- pipelineConfig,
2027
- maxReparses
2028
- });
2029
- } else {
2030
- handleStreamingToolCallEnd({
2031
- toolContent: "",
2032
- currentToolCall: { name: earliestToolName, content: "" },
2033
- tools,
2034
- options,
2035
- ctrl: controller,
2036
- flushText
2037
- });
2038
- }
2039
- return {
2040
- buffer: newBuffer2,
2041
- currentToolCall: null,
2042
- shouldBreak: false,
2043
- shouldContinue: false
2044
- };
1847
+ function nextTagToken(text, fromPos) {
1848
+ const lt = text.indexOf("<", fromPos);
1849
+ if (lt === -1 || lt + 1 >= text.length) {
1850
+ return { kind: "eof", nextPos: text.length };
1851
+ }
1852
+ const next = text[lt + 1];
1853
+ const specialEnd = skipSpecialSegment(text, lt);
1854
+ if (specialEnd !== null) {
1855
+ return { kind: "special", nextPos: specialEnd };
1856
+ }
1857
+ if (next === "/") {
1858
+ const closing = consumeClosingTag(text, lt);
1859
+ let p = lt + 2;
1860
+ while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
1861
+ p += 1;
2045
1862
  }
2046
- const startTag = `<${earliestToolName}>`;
2047
- const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
2048
- return {
2049
- buffer: newBuffer,
2050
- currentToolCall: { name: earliestToolName, content: "" },
2051
- shouldBreak: false,
2052
- shouldContinue: false
2053
- };
1863
+ const nameStart = p;
1864
+ while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
1865
+ p += 1;
1866
+ }
1867
+ const name = text.slice(nameStart, p);
1868
+ return { kind: "close", name, nextPos: closing.endPos };
1869
+ }
1870
+ const open = consumeOpenTag(text, lt);
1871
+ if (open === null) {
1872
+ return { kind: "eof", nextPos: text.length };
2054
1873
  }
2055
- const result = handleNoToolTagInBuffer(
2056
- buffer,
2057
- maxStartTagLen,
2058
- controller,
2059
- flushText
2060
- );
2061
1874
  return {
2062
- buffer: result.buffer,
2063
- currentToolCall: null,
2064
- shouldBreak: !result.shouldContinue,
2065
- shouldContinue: result.shouldContinue
1875
+ kind: "open",
1876
+ name: open.name,
1877
+ selfClosing: open.selfClosing,
1878
+ nextPos: open.nextPos
2066
1879
  };
2067
1880
  }
2068
- function createFlushTextHandler(getBuffer, setBuffer, getCurrentTextId, setCurrentTextId) {
1881
+ function findToolCallsForName(text, toolName) {
1882
+ var _a;
1883
+ const toolCalls = [];
1884
+ let searchIndex = 0;
1885
+ while (searchIndex < text.length) {
1886
+ const startTag = `<${toolName}>`;
1887
+ const selfTag = `<${toolName}/>`;
1888
+ const openIdx = text.indexOf(startTag, searchIndex);
1889
+ const selfIdx = text.indexOf(selfTag, searchIndex);
1890
+ if (openIdx === -1 && selfIdx === -1) {
1891
+ break;
1892
+ }
1893
+ const tagStart = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx) ? selfIdx : openIdx;
1894
+ const isSelfClosing = tagStart === selfIdx;
1895
+ if (isSelfClosing) {
1896
+ const endIndex = tagStart + selfTag.length;
1897
+ const segment = text.substring(tagStart, endIndex);
1898
+ toolCalls.push({
1899
+ toolName,
1900
+ startIndex: tagStart,
1901
+ endIndex,
1902
+ content: "",
1903
+ segment
1904
+ });
1905
+ searchIndex = endIndex;
1906
+ continue;
1907
+ }
1908
+ const contentStart = tagStart + startTag.length;
1909
+ const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
1910
+ if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
1911
+ const segment = text.substring(tagStart, fullTagEnd);
1912
+ const inner = (_a = (0, import_rxml2.extractRawInner)(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
1913
+ toolCalls.push({
1914
+ toolName,
1915
+ startIndex: tagStart,
1916
+ endIndex: fullTagEnd,
1917
+ content: inner,
1918
+ segment
1919
+ });
1920
+ searchIndex = fullTagEnd;
1921
+ } else {
1922
+ searchIndex = contentStart;
1923
+ }
1924
+ }
1925
+ return toolCalls;
1926
+ }
1927
+ function findToolCalls(text, toolNames) {
1928
+ const toolCalls = [];
1929
+ for (const toolName of toolNames) {
1930
+ const calls = findToolCallsForName(text, toolName);
1931
+ toolCalls.push(...calls);
1932
+ }
1933
+ return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
1934
+ }
1935
+ function findEarliestToolTag(buffer, toolNames) {
1936
+ let bestIndex = -1;
1937
+ let bestName = "";
1938
+ let bestSelfClosing = false;
1939
+ if (toolNames.length > 0) {
1940
+ for (const name of toolNames) {
1941
+ const openTag = `<${name}>`;
1942
+ const selfTag = `<${name}/>`;
1943
+ const idxOpen = buffer.indexOf(openTag);
1944
+ const idxSelf = buffer.indexOf(selfTag);
1945
+ if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
1946
+ bestIndex = idxOpen;
1947
+ bestName = name;
1948
+ bestSelfClosing = false;
1949
+ }
1950
+ if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
1951
+ bestIndex = idxSelf;
1952
+ bestName = name;
1953
+ bestSelfClosing = true;
1954
+ }
1955
+ }
1956
+ }
1957
+ return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
1958
+ }
1959
+ function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
2069
1960
  return (controller, text) => {
2070
- const content = text != null ? text : getBuffer();
1961
+ const content = text;
2071
1962
  if (content) {
2072
- const currentTextId2 = getCurrentTextId();
2073
- if (!currentTextId2) {
2074
- const newId = generateId2();
1963
+ if (!getCurrentTextId()) {
1964
+ const newId = generateId();
2075
1965
  setCurrentTextId(newId);
2076
- controller.enqueue({ type: "text-start", id: newId });
1966
+ controller.enqueue({
1967
+ type: "text-start",
1968
+ id: newId
1969
+ });
1970
+ setHasEmittedTextStart(true);
2077
1971
  }
2078
1972
  controller.enqueue({
2079
1973
  type: "text-delta",
2080
1974
  id: getCurrentTextId(),
1975
+ textDelta: content,
2081
1976
  delta: content
2082
1977
  });
2083
- if (text === void 0) {
2084
- setBuffer("");
2085
- }
2086
1978
  }
2087
1979
  const currentTextId = getCurrentTextId();
2088
1980
  if (currentTextId && !text) {
2089
- controller.enqueue({ type: "text-end", id: currentTextId });
1981
+ if (getHasEmittedTextStart()) {
1982
+ controller.enqueue({
1983
+ type: "text-end",
1984
+ id: currentTextId
1985
+ });
1986
+ setHasEmittedTextStart(false);
1987
+ }
2090
1988
  setCurrentTextId(null);
2091
1989
  }
2092
1990
  };
2093
1991
  }
2094
- function processBufferWithToolCall(params, controller) {
1992
+ function processToolCallInBuffer(params) {
2095
1993
  const {
2096
- getBuffer,
2097
- setBuffer,
2098
- getCurrentToolCall,
2099
- setCurrentToolCall,
1994
+ buffer,
1995
+ currentToolCall,
2100
1996
  tools,
2101
1997
  options,
1998
+ controller,
2102
1999
  flushText,
2000
+ setBuffer,
2103
2001
  pipelineConfig,
2104
2002
  maxReparses
2105
2003
  } = params;
2106
- const currentToolCall = getCurrentToolCall();
2107
- if (!currentToolCall) {
2108
- return true;
2109
- }
2110
- const result = processToolCallInBuffer({
2111
- buffer: getBuffer(),
2004
+ const endTag = `</${currentToolCall.name}>`;
2005
+ const endIdx = buffer.indexOf(endTag);
2006
+ if (endIdx === -1) {
2007
+ return { buffer, currentToolCall, shouldBreak: true };
2008
+ }
2009
+ const content = buffer.substring(0, endIdx);
2010
+ setBuffer(buffer.substring(endIdx + endTag.length));
2011
+ handleStreamingToolCallEnd({
2012
+ toolContent: content,
2112
2013
  currentToolCall,
2113
2014
  tools,
2114
2015
  options,
2115
- controller,
2016
+ ctrl: controller,
2116
2017
  flushText,
2117
- setBuffer,
2118
2018
  pipelineConfig,
2119
2019
  maxReparses
2120
2020
  });
2121
- setBuffer(result.buffer);
2122
- setCurrentToolCall(result.currentToolCall);
2123
- return result.shouldBreak;
2021
+ return {
2022
+ buffer: buffer.substring(endIdx + endTag.length),
2023
+ currentToolCall: null,
2024
+ shouldBreak: false
2025
+ };
2124
2026
  }
2125
- function processBufferWithoutToolCall(params, controller) {
2027
+ function processNoToolCallInBuffer(params) {
2126
2028
  const {
2127
- getBuffer,
2128
- setBuffer,
2129
- setCurrentToolCall,
2130
- tools,
2131
- options,
2132
- toolNames,
2133
- maxStartTagLen,
2134
- flushText,
2135
- pipelineConfig,
2136
- maxReparses
2137
- } = params;
2138
- const result = processNoToolCallInBuffer({
2139
- buffer: getBuffer(),
2029
+ buffer,
2140
2030
  toolNames,
2141
- maxStartTagLen,
2142
2031
  controller,
2143
2032
  flushText,
2144
2033
  tools,
2145
2034
  options,
2146
2035
  pipelineConfig,
2147
- maxReparses
2148
- });
2149
- setBuffer(result.buffer);
2150
- setCurrentToolCall(result.currentToolCall);
2036
+ maxReparses,
2037
+ setBuffer
2038
+ } = params;
2039
+ const {
2040
+ index: earliestStartTagIndex,
2041
+ name: earliestToolName,
2042
+ selfClosing
2043
+ } = findEarliestToolTag(buffer, toolNames);
2044
+ if (earliestStartTagIndex === -1) {
2045
+ const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n}>`.length)) : 0;
2046
+ const tail = Math.max(0, maxTagLen - 1);
2047
+ const safeLen = Math.max(0, buffer.length - tail);
2048
+ if (safeLen > 0) {
2049
+ flushText(controller, buffer.slice(0, safeLen));
2050
+ setBuffer(buffer.slice(safeLen));
2051
+ }
2052
+ return {
2053
+ buffer: buffer.slice(safeLen),
2054
+ currentToolCall: null,
2055
+ shouldBreak: true,
2056
+ shouldContinue: false
2057
+ };
2058
+ }
2059
+ flushText(controller, buffer.substring(0, earliestStartTagIndex));
2060
+ if (selfClosing) {
2061
+ const selfTag = `<${earliestToolName}/>`;
2062
+ const newBuffer2 = buffer.substring(earliestStartTagIndex + selfTag.length);
2063
+ setBuffer(newBuffer2);
2064
+ handleStreamingToolCallEnd({
2065
+ toolContent: "",
2066
+ currentToolCall: { name: earliestToolName, content: "" },
2067
+ tools,
2068
+ options,
2069
+ ctrl: controller,
2070
+ flushText,
2071
+ pipelineConfig,
2072
+ maxReparses
2073
+ });
2074
+ return {
2075
+ buffer: newBuffer2,
2076
+ currentToolCall: null,
2077
+ shouldBreak: false,
2078
+ shouldContinue: false
2079
+ };
2080
+ }
2081
+ const startTag = `<${earliestToolName}>`;
2082
+ const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
2083
+ setBuffer(newBuffer);
2151
2084
  return {
2152
- shouldBreak: result.shouldBreak,
2153
- shouldContinue: result.shouldContinue
2085
+ buffer: newBuffer,
2086
+ currentToolCall: { name: earliestToolName, content: "" },
2087
+ shouldBreak: false,
2088
+ shouldContinue: true
2154
2089
  };
2155
2090
  }
2156
- function processBufferLoop(params, controller) {
2157
- while (true) {
2158
- const currentToolCall = params.getCurrentToolCall();
2159
- if (currentToolCall) {
2160
- const shouldBreak = processBufferWithToolCall(params, controller);
2161
- if (shouldBreak) {
2162
- break;
2163
- }
2164
- } else {
2165
- const { shouldBreak, shouldContinue } = processBufferWithoutToolCall(
2166
- params,
2167
- controller
2168
- );
2169
- if (shouldContinue) {
2170
- continue;
2171
- }
2172
- if (shouldBreak) {
2091
+ function createProcessBufferHandler(getBuffer, setBuffer, getCurrentToolCall, setCurrentToolCall, tools, options, toolNames, flushText, pipelineConfig, maxReparses) {
2092
+ return (controller) => {
2093
+ while (true) {
2094
+ const currentToolCall = getCurrentToolCall();
2095
+ if (currentToolCall) {
2096
+ const result = processToolCallInBuffer({
2097
+ buffer: getBuffer(),
2098
+ currentToolCall,
2099
+ tools,
2100
+ options,
2101
+ controller,
2102
+ flushText,
2103
+ setBuffer,
2104
+ pipelineConfig,
2105
+ maxReparses
2106
+ });
2107
+ setBuffer(result.buffer);
2108
+ setCurrentToolCall(result.currentToolCall);
2109
+ if (result.shouldBreak) {
2110
+ break;
2111
+ }
2112
+ } else {
2113
+ const result = processNoToolCallInBuffer({
2114
+ buffer: getBuffer(),
2115
+ toolNames,
2116
+ controller,
2117
+ flushText,
2118
+ tools,
2119
+ options,
2120
+ pipelineConfig,
2121
+ maxReparses,
2122
+ setBuffer
2123
+ });
2124
+ setBuffer(result.buffer);
2125
+ setCurrentToolCall(result.currentToolCall);
2126
+ if (result.shouldBreak) {
2127
+ break;
2128
+ }
2129
+ if (result.shouldContinue) {
2130
+ continue;
2131
+ }
2173
2132
  break;
2174
2133
  }
2175
2134
  }
2176
- }
2177
- }
2178
- function createProcessBufferHandler(params) {
2179
- return (controller) => {
2180
- processBufferLoop(params, controller);
2181
2135
  };
2182
2136
  }
2183
- function buildPipelineOptions(protocolOptions) {
2184
- var _a, _b, _c;
2137
+ var morphXmlProtocol = (protocolOptions) => {
2138
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2139
+ let pipelineConfig = protocolOptions == null ? void 0 : protocolOptions.pipeline;
2185
2140
  const maxReparses = protocolOptions == null ? void 0 : protocolOptions.maxReparses;
2186
- if (protocolOptions == null ? void 0 : protocolOptions.pipeline) {
2187
- return {
2188
- pipelineConfig: mergePipelineConfigs2(
2189
- defaultPipelineConfig2,
2190
- protocolOptions.pipeline
2191
- ),
2192
- maxReparses
2141
+ if ((protocolOptions == null ? void 0 : protocolOptions.heuristics) && protocolOptions.heuristics.length > 0) {
2142
+ const heuristicsConfig = {
2143
+ preParse: [],
2144
+ fallbackReparse: [],
2145
+ postParse: []
2193
2146
  };
2194
- }
2195
- if (protocolOptions == null ? void 0 : protocolOptions.heuristics) {
2196
- return {
2197
- pipelineConfig: {
2198
- ...defaultPipelineConfig2,
2147
+ for (const h of protocolOptions.heuristics) {
2148
+ if (h.phase === "pre-parse") {
2149
+ (_a = heuristicsConfig.preParse) == null ? void 0 : _a.push(h);
2150
+ } else if (h.phase === "fallback-reparse") {
2151
+ (_b = heuristicsConfig.fallbackReparse) == null ? void 0 : _b.push(h);
2152
+ } else if (h.phase === "post-parse") {
2153
+ (_c = heuristicsConfig.postParse) == null ? void 0 : _c.push(h);
2154
+ }
2155
+ }
2156
+ if (pipelineConfig) {
2157
+ pipelineConfig = {
2199
2158
  preParse: [
2200
- ...(_a = defaultPipelineConfig2.preParse) != null ? _a : [],
2201
- ...protocolOptions.heuristics.filter((h) => h.phase === "pre-parse")
2159
+ ...(_d = pipelineConfig.preParse) != null ? _d : [],
2160
+ ...(_e = heuristicsConfig.preParse) != null ? _e : []
2202
2161
  ],
2203
2162
  fallbackReparse: [
2204
- ...(_b = defaultPipelineConfig2.fallbackReparse) != null ? _b : [],
2205
- ...protocolOptions.heuristics.filter(
2206
- (h) => h.phase === "fallback-reparse"
2207
- )
2163
+ ...(_f = pipelineConfig.fallbackReparse) != null ? _f : [],
2164
+ ...(_g = heuristicsConfig.fallbackReparse) != null ? _g : []
2208
2165
  ],
2209
2166
  postParse: [
2210
- ...(_c = defaultPipelineConfig2.postParse) != null ? _c : [],
2211
- ...protocolOptions.heuristics.filter((h) => h.phase === "post-parse")
2167
+ ...(_h = pipelineConfig.postParse) != null ? _h : [],
2168
+ ...(_i = heuristicsConfig.postParse) != null ? _i : []
2212
2169
  ]
2213
- },
2214
- maxReparses
2215
- };
2170
+ };
2171
+ } else {
2172
+ pipelineConfig = heuristicsConfig;
2173
+ }
2216
2174
  }
2217
- return { pipelineConfig: void 0, maxReparses };
2218
- }
2219
- var morphXmlProtocol = (protocolOptions) => {
2220
- const { pipelineConfig, maxReparses } = buildPipelineOptions(protocolOptions);
2221
2175
  return {
2222
2176
  formatTools({ tools, toolSystemPromptTemplate }) {
2223
2177
  const toolsForPrompt = (tools || []).map((tool) => ({
2224
2178
  name: tool.name,
2225
2179
  description: tool.description,
2226
- parameters: unwrapJsonSchema2(tool.inputSchema)
2180
+ parameters: (0, import_rxml2.unwrapJsonSchema)(tool.inputSchema)
2227
2181
  }));
2228
2182
  return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
2229
2183
  },
2230
2184
  formatToolCall(toolCall) {
2231
2185
  let args = {};
2232
- const inputValue = hasInputProperty(toolCall) ? toolCall.input : void 0;
2233
- if (typeof inputValue === "string") {
2234
- try {
2235
- args = JSON.parse(inputValue);
2236
- } catch (e) {
2237
- args = inputValue;
2238
- }
2239
- } else {
2240
- args = inputValue;
2186
+ try {
2187
+ args = JSON.parse(toolCall.input);
2188
+ } catch (e) {
2189
+ args = toolCall.input;
2241
2190
  }
2242
- return stringify2(toolCall.toolName, args, {
2191
+ return (0, import_rxml2.stringify)(toolCall.toolName, args, {
2243
2192
  suppressEmptyNode: false,
2244
2193
  format: false
2245
2194
  });
2246
2195
  },
2247
2196
  formatToolResponse(toolResult) {
2248
- return stringify2("tool_response", {
2249
- tool_name: toolResult.toolName,
2250
- result: toolResult.output
2251
- });
2197
+ let result = toolResult.result;
2198
+ if (result && typeof result === "object" && "type" in result && result.type === "json" && "value" in result) {
2199
+ result = result.value;
2200
+ }
2201
+ const xml = (0, import_rxml2.stringify)(
2202
+ "tool_response",
2203
+ {
2204
+ tool_name: toolResult.toolName,
2205
+ result
2206
+ },
2207
+ { declaration: false }
2208
+ );
2209
+ return xml;
2252
2210
  },
2253
2211
  parseGeneratedText({ text, tools, options }) {
2254
- const toolNames = tools.map((t) => t.name).filter((name) => name != null);
2212
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
2255
2213
  if (toolNames.length === 0) {
2256
2214
  return [{ type: "text", text }];
2257
2215
  }
2258
2216
  const processedElements = [];
2259
2217
  let currentIndex = 0;
2260
- const toolCallsRaw = findToolCalls(text, toolNames);
2261
- const toolCallsNorm = collectToolCallsFromNormalizedText(text, toolNames);
2262
- const seen = /* @__PURE__ */ new Set();
2263
- const toolCalls = [...toolCallsRaw, ...toolCallsNorm].filter((tc) => {
2264
- const key = `${tc.toolName}:${tc.startIndex}:${tc.endIndex}`;
2265
- if (seen.has(key)) {
2266
- return false;
2267
- }
2268
- seen.add(key);
2269
- return true;
2270
- }).sort((a, b) => a.startIndex - b.startIndex);
2271
- if (process.env.DEBUG_PARSER_OUTPUT === "true") {
2272
- console.log("\n=== PARSER DEBUG ===");
2273
- console.log(`Available tools: ${toolNames.join(", ")}`);
2274
- console.log(`Full text length: ${text.length}`);
2275
- console.log(`Full text:
2276
- ${text}
2277
- `);
2278
- console.log(`Tool calls found: ${toolCalls.length}`);
2279
- for (let i = 0; i < toolCalls.length; i++) {
2280
- const tc = toolCalls[i];
2281
- console.log(`
2282
- [Tool Call ${i + 1}] ${tc.toolName}`);
2283
- console.log(`Position: ${tc.startIndex} - ${tc.endIndex}`);
2284
- console.log(`Segment:
2285
- ${tc.segment}`);
2286
- console.log(`Content:
2287
- ${tc.content}`);
2288
- }
2289
- console.log("===================\n");
2290
- }
2291
- for (const toolCall of toolCalls) {
2292
- currentIndex = processTextBeforeToolCall(
2293
- text,
2294
- currentIndex,
2295
- toolCall.startIndex,
2296
- processedElements
2297
- );
2298
- if (pipelineConfig) {
2299
- processToolCallWithPipeline({
2300
- toolCall,
2301
- tools,
2302
- options,
2303
- text,
2304
- processedElements,
2305
- pipelineConfig,
2306
- maxReparses
2307
- });
2308
- } else {
2309
- processToolCall({
2310
- toolCall,
2311
- tools,
2312
- options,
2313
- text,
2314
- processedElements
2218
+ const toolCalls = findToolCalls(text, toolNames);
2219
+ for (const tc of toolCalls) {
2220
+ if (tc.startIndex > currentIndex) {
2221
+ processedElements.push({
2222
+ type: "text",
2223
+ text: text.substring(currentIndex, tc.startIndex)
2315
2224
  });
2316
2225
  }
2317
- currentIndex = toolCall.endIndex;
2226
+ processToolCallWithPipeline({
2227
+ toolCall: tc,
2228
+ tools,
2229
+ options,
2230
+ text,
2231
+ processedElements,
2232
+ pipelineConfig,
2233
+ maxReparses
2234
+ });
2235
+ currentIndex = tc.endIndex;
2236
+ }
2237
+ if (currentIndex < text.length) {
2238
+ processedElements.push({
2239
+ type: "text",
2240
+ text: text.substring(currentIndex)
2241
+ });
2318
2242
  }
2319
- addRemainingText(text, currentIndex, processedElements);
2320
2243
  return processedElements;
2321
2244
  },
2322
2245
  createStreamParser({ tools, options }) {
2323
- const toolNames = tools.map((t) => t.name).filter((name) => name != null);
2324
- const maxStartTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n}>`.length)) : 0;
2246
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
2325
2247
  let buffer = "";
2326
2248
  let currentToolCall = null;
2327
2249
  let currentTextId = null;
2250
+ let hasEmittedTextStart = false;
2328
2251
  const flushText = createFlushTextHandler(
2329
- () => buffer,
2330
- (newBuffer) => {
2331
- buffer = newBuffer;
2332
- },
2333
2252
  () => currentTextId,
2334
2253
  (newId) => {
2335
2254
  currentTextId = newId;
2255
+ },
2256
+ () => hasEmittedTextStart,
2257
+ (value) => {
2258
+ hasEmittedTextStart = value;
2336
2259
  }
2337
2260
  );
2338
- const processChunk = (chunk, controller) => {
2339
- if (chunk.type !== "text-delta") {
2340
- if (buffer) {
2341
- flushText(controller);
2342
- }
2343
- controller.enqueue(chunk);
2344
- return;
2345
- }
2346
- buffer += chunk.delta;
2347
- processBuffer(controller);
2348
- };
2349
- const processBuffer = createProcessBufferHandler({
2350
- getBuffer: () => buffer,
2351
- setBuffer: (newBuffer) => {
2261
+ const processBuffer = createProcessBufferHandler(
2262
+ () => buffer,
2263
+ (newBuffer) => {
2352
2264
  buffer = newBuffer;
2353
2265
  },
2354
- getCurrentToolCall: () => currentToolCall,
2355
- setCurrentToolCall: (newToolCall) => {
2266
+ () => currentToolCall,
2267
+ (newToolCall) => {
2356
2268
  currentToolCall = newToolCall;
2357
2269
  },
2358
2270
  tools,
2359
2271
  options,
2360
2272
  toolNames,
2361
- maxStartTagLen,
2362
2273
  flushText,
2363
2274
  pipelineConfig,
2364
2275
  maxReparses
2365
- });
2366
- const flushBuffer2 = (controller) => {
2367
- if (currentToolCall) {
2368
- const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
2369
- flushText(controller, unfinishedCall);
2370
- } else if (buffer) {
2371
- flushText(controller);
2372
- }
2373
- if (currentTextId) {
2374
- controller.enqueue({ type: "text-end", id: currentTextId });
2375
- }
2376
- };
2276
+ );
2377
2277
  return new TransformStream({
2378
2278
  transform(chunk, controller) {
2379
- processChunk(chunk, controller);
2279
+ var _a2, _b2;
2280
+ if (chunk.type !== "text-delta") {
2281
+ if (buffer) {
2282
+ flushText(controller, buffer);
2283
+ buffer = "";
2284
+ }
2285
+ controller.enqueue(chunk);
2286
+ return;
2287
+ }
2288
+ const textContent = (_b2 = (_a2 = chunk.textDelta) != null ? _a2 : chunk.delta) != null ? _b2 : "";
2289
+ buffer += textContent;
2290
+ processBuffer(controller);
2380
2291
  },
2381
2292
  flush(controller) {
2382
- flushBuffer2(controller);
2293
+ if (currentToolCall) {
2294
+ const unfinishedContent = `<${currentToolCall.name}>${currentToolCall.content || ""}${buffer}`;
2295
+ flushText(controller, unfinishedContent);
2296
+ buffer = "";
2297
+ currentToolCall = null;
2298
+ } else if (buffer) {
2299
+ flushText(controller, buffer);
2300
+ buffer = "";
2301
+ }
2302
+ if (currentTextId && hasEmittedTextStart) {
2303
+ controller.enqueue({
2304
+ type: "text-end",
2305
+ id: currentTextId
2306
+ });
2307
+ hasEmittedTextStart = false;
2308
+ currentTextId = null;
2309
+ }
2383
2310
  }
2384
2311
  });
2385
2312
  },
@@ -2392,237 +2319,516 @@ ${tc.content}`);
2392
2319
  }
2393
2320
  };
2394
2321
  };
2395
- function getToolSchema(tools, toolName) {
2396
- var _a;
2397
- return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
2398
- }
2399
- function findClosingTagEndFlexible(text, contentStart, toolName) {
2322
+
2323
+ // src/core/protocols/yaml-xml-protocol.ts
2324
+ var import_rxml3 = require("@ai-sdk-tool/rxml");
2325
+ var import_yaml = __toESM(require("yaml"), 1);
2326
+ var NAME_CHAR_RE3 = /[A-Za-z0-9_:-]/;
2327
+ var WHITESPACE_REGEX4 = /\s/;
2328
+ var LEADING_WHITESPACE_RE = /^(\s*)/;
2329
+ function findClosingTagEnd(text, contentStart, toolName) {
2400
2330
  let pos = contentStart;
2401
2331
  let depth = 1;
2402
2332
  while (pos < text.length) {
2403
- const tok = nextTagToken(text, pos);
2404
- if (tok.kind === "eof") {
2333
+ const ltIdx = text.indexOf("<", pos);
2334
+ if (ltIdx === -1) {
2405
2335
  break;
2406
2336
  }
2407
- const result = updateDepthWithToken(tok, toolName, depth);
2408
- depth = result.depth;
2409
- if (result.closedAt !== void 0) {
2410
- return result.closedAt;
2337
+ const next = text[ltIdx + 1];
2338
+ if (next === "/") {
2339
+ const gtIdx = text.indexOf(">", ltIdx);
2340
+ if (gtIdx === -1) {
2341
+ break;
2342
+ }
2343
+ let p = ltIdx + 2;
2344
+ while (p < gtIdx && WHITESPACE_REGEX4.test(text[p])) {
2345
+ p++;
2346
+ }
2347
+ const nameStart = p;
2348
+ while (p < gtIdx && NAME_CHAR_RE3.test(text.charAt(p))) {
2349
+ p++;
2350
+ }
2351
+ const name = text.slice(nameStart, p);
2352
+ if (name === toolName) {
2353
+ depth--;
2354
+ if (depth === 0) {
2355
+ return gtIdx + 1;
2356
+ }
2357
+ }
2358
+ pos = gtIdx + 1;
2359
+ } else if (next === "!" || next === "?") {
2360
+ const gtIdx = text.indexOf(">", ltIdx);
2361
+ pos = gtIdx === -1 ? text.length : gtIdx + 1;
2362
+ } else {
2363
+ let p = ltIdx + 1;
2364
+ while (p < text.length && WHITESPACE_REGEX4.test(text[p])) {
2365
+ p++;
2366
+ }
2367
+ const nameStart = p;
2368
+ while (p < text.length && NAME_CHAR_RE3.test(text.charAt(p))) {
2369
+ p++;
2370
+ }
2371
+ const name = text.slice(nameStart, p);
2372
+ const gtIdx = text.indexOf(">", p);
2373
+ if (gtIdx === -1) {
2374
+ break;
2375
+ }
2376
+ let r = gtIdx - 1;
2377
+ while (r >= nameStart && WHITESPACE_REGEX4.test(text[r])) {
2378
+ r--;
2379
+ }
2380
+ const selfClosing = text[r] === "/";
2381
+ if (name === toolName && !selfClosing) {
2382
+ depth++;
2383
+ }
2384
+ pos = gtIdx + 1;
2411
2385
  }
2412
- pos = tok.nextPos;
2413
2386
  }
2414
2387
  return -1;
2415
2388
  }
2416
- function skipSpecialSegment(text, lt) {
2417
- const next = text[lt + 1];
2418
- if (next !== "!" && next !== "?") {
2419
- return null;
2420
- }
2421
- const gt = text.indexOf(">", lt + 1);
2422
- if (gt === -1) {
2423
- return null;
2389
+ function findEarliestTagPosition(openIdx, selfIdx) {
2390
+ const hasSelf = selfIdx !== -1;
2391
+ const hasOpen = openIdx !== -1;
2392
+ if (hasSelf && (!hasOpen || selfIdx < openIdx)) {
2393
+ return { tagStart: selfIdx, isSelfClosing: true };
2424
2394
  }
2425
- return gt + 1;
2395
+ return { tagStart: openIdx, isSelfClosing: false };
2426
2396
  }
2427
- function consumeClosingTag(text, lt, _toolName) {
2428
- let p = lt + 2;
2429
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
2430
- p += 1;
2397
+ function collectToolCallsForName(text, toolName) {
2398
+ const toolCalls = [];
2399
+ let searchIndex = 0;
2400
+ const selfTagRegex = new RegExp(`<${toolName}\\s*/>`, "g");
2401
+ while (searchIndex < text.length) {
2402
+ const startTag = `<${toolName}>`;
2403
+ const openIdx = text.indexOf(startTag, searchIndex);
2404
+ selfTagRegex.lastIndex = searchIndex;
2405
+ const selfMatch = selfTagRegex.exec(text);
2406
+ const selfIdx = selfMatch ? selfMatch.index : -1;
2407
+ const selfTagLength = selfMatch ? selfMatch[0].length : 0;
2408
+ if (openIdx === -1 && selfIdx === -1) {
2409
+ break;
2410
+ }
2411
+ const { tagStart, isSelfClosing } = findEarliestTagPosition(
2412
+ openIdx,
2413
+ selfIdx
2414
+ );
2415
+ if (isSelfClosing) {
2416
+ const endIndex = tagStart + selfTagLength;
2417
+ toolCalls.push({
2418
+ toolName,
2419
+ startIndex: tagStart,
2420
+ endIndex,
2421
+ content: ""
2422
+ });
2423
+ searchIndex = endIndex;
2424
+ continue;
2425
+ }
2426
+ const contentStart = tagStart + startTag.length;
2427
+ const fullTagEnd = findClosingTagEnd(text, contentStart, toolName);
2428
+ if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
2429
+ const endTag = `</${toolName}>`;
2430
+ const endTagStart = fullTagEnd - endTag.length;
2431
+ const content = text.substring(contentStart, endTagStart);
2432
+ toolCalls.push({
2433
+ toolName,
2434
+ startIndex: tagStart,
2435
+ endIndex: fullTagEnd,
2436
+ content
2437
+ });
2438
+ searchIndex = fullTagEnd;
2439
+ } else {
2440
+ searchIndex = contentStart;
2441
+ }
2431
2442
  }
2432
- const gt = text.indexOf(">", lt + 1);
2433
- const endPos = gt === -1 ? text.length : gt + 1;
2434
- return { matched: false, endPos };
2443
+ return toolCalls;
2435
2444
  }
2436
- function consumeOpenTag(text, lt) {
2437
- let p = lt + 1;
2438
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
2439
- p += 1;
2445
+ function findToolCalls2(text, toolNames) {
2446
+ const toolCalls = toolNames.flatMap(
2447
+ (toolName) => collectToolCallsForName(text, toolName)
2448
+ );
2449
+ return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
2450
+ }
2451
+ function parseYamlContent(yamlContent, options) {
2452
+ var _a, _b, _c;
2453
+ let normalized = yamlContent;
2454
+ if (normalized.startsWith("\n")) {
2455
+ normalized = normalized.slice(1);
2440
2456
  }
2441
- const nameStart = p;
2442
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
2443
- p += 1;
2457
+ const lines = normalized.split("\n");
2458
+ const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
2459
+ if (nonEmptyLines.length === 0) {
2460
+ return {};
2444
2461
  }
2445
- const name = text.slice(nameStart, p);
2446
- const q = text.indexOf(">", p);
2447
- if (q === -1) {
2448
- return null;
2462
+ const minIndent = Math.min(
2463
+ ...nonEmptyLines.map((line) => {
2464
+ const match = line.match(LEADING_WHITESPACE_RE);
2465
+ return match ? match[1].length : 0;
2466
+ })
2467
+ );
2468
+ if (minIndent > 0) {
2469
+ normalized = lines.map((line) => line.slice(minIndent)).join("\n");
2449
2470
  }
2450
- let r = q - 1;
2451
- while (r >= nameStart && WHITESPACE_REGEX3.test(text[r])) {
2452
- r -= 1;
2471
+ try {
2472
+ const doc = import_yaml.default.parseDocument(normalized);
2473
+ if (doc.errors && doc.errors.length > 0) {
2474
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "YAML parse error", {
2475
+ errors: doc.errors.map((e) => e.message)
2476
+ });
2477
+ return null;
2478
+ }
2479
+ const result = doc.toJSON();
2480
+ if (result === null) {
2481
+ return {};
2482
+ }
2483
+ if (typeof result !== "object" || Array.isArray(result)) {
2484
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(options, "YAML content must be a key-value mapping", {
2485
+ got: typeof result
2486
+ });
2487
+ return null;
2488
+ }
2489
+ return result;
2490
+ } catch (error) {
2491
+ (_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, "Failed to parse YAML content", { error });
2492
+ return null;
2453
2493
  }
2454
- const selfClosing = text[r] === "/";
2455
- return { name, selfClosing, nextPos: q + 1 };
2456
2494
  }
2457
- function updateDepthWithToken(tok, toolName, depth) {
2458
- if (tok.kind === "close" && tok.name === toolName) {
2459
- const newDepth = depth - 1;
2460
- return newDepth === 0 ? { depth: newDepth, closedAt: tok.nextPos } : { depth: newDepth };
2461
- }
2462
- if (tok.kind === "open" && tok.name === toolName && !tok.selfClosing) {
2463
- return { depth: depth + 1 };
2495
+ function appendTextPart(processedElements, textPart) {
2496
+ if (textPart.trim()) {
2497
+ processedElements.push({
2498
+ type: "text",
2499
+ text: textPart
2500
+ });
2464
2501
  }
2465
- return { depth };
2466
2502
  }
2467
- function nextTagToken(text, fromPos) {
2468
- const lt = text.indexOf("<", fromPos);
2469
- if (lt === -1 || lt + 1 >= text.length) {
2470
- return { kind: "eof", nextPos: text.length };
2503
+ function processToolCallMatch(text, tc, currentIndex, processedElements, options) {
2504
+ var _a;
2505
+ if (tc.startIndex < currentIndex) {
2506
+ return currentIndex;
2471
2507
  }
2472
- const next = text[lt + 1];
2473
- const specialEnd = skipSpecialSegment(text, lt);
2474
- if (specialEnd !== null) {
2475
- return { kind: "special", nextPos: specialEnd };
2508
+ appendTextPart(
2509
+ processedElements,
2510
+ text.substring(currentIndex, tc.startIndex)
2511
+ );
2512
+ const parsedArgs = parseYamlContent(tc.content, options);
2513
+ if (parsedArgs !== null) {
2514
+ processedElements.push({
2515
+ type: "tool-call",
2516
+ toolCallId: generateId(),
2517
+ toolName: tc.toolName,
2518
+ input: JSON.stringify(parsedArgs)
2519
+ });
2520
+ } else {
2521
+ const originalText = text.substring(tc.startIndex, tc.endIndex);
2522
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse YAML tool call", {
2523
+ toolCall: originalText
2524
+ });
2525
+ processedElements.push({ type: "text", text: originalText });
2476
2526
  }
2477
- if (next === "/") {
2478
- const closing = consumeClosingTag(text, lt, "");
2479
- let p = lt + 2;
2480
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
2481
- p += 1;
2527
+ return tc.endIndex;
2528
+ }
2529
+ function createFlushTextHandler2(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
2530
+ return (controller, text) => {
2531
+ const content = text;
2532
+ if (content) {
2533
+ if (!getCurrentTextId()) {
2534
+ const newId = generateId();
2535
+ setCurrentTextId(newId);
2536
+ controller.enqueue({
2537
+ type: "text-start",
2538
+ id: newId
2539
+ });
2540
+ setHasEmittedTextStart(true);
2541
+ }
2542
+ controller.enqueue({
2543
+ type: "text-delta",
2544
+ id: getCurrentTextId(),
2545
+ textDelta: content,
2546
+ delta: content
2547
+ });
2482
2548
  }
2483
- const nameStart = p;
2484
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
2485
- p += 1;
2549
+ const currentTextId = getCurrentTextId();
2550
+ if (currentTextId && !text) {
2551
+ if (getHasEmittedTextStart()) {
2552
+ controller.enqueue({
2553
+ type: "text-end",
2554
+ id: currentTextId
2555
+ });
2556
+ setHasEmittedTextStart(false);
2557
+ }
2558
+ setCurrentTextId(null);
2559
+ }
2560
+ };
2561
+ }
2562
+ function findEarliestToolTag2(buffer, toolNames) {
2563
+ let bestIndex = -1;
2564
+ let bestName = "";
2565
+ let bestSelfClosing = false;
2566
+ let bestTagLength = 0;
2567
+ for (const name of toolNames) {
2568
+ const openTag = `<${name}>`;
2569
+ const selfTagRegex = new RegExp(`<${name}\\s*/>`);
2570
+ const idxOpen = buffer.indexOf(openTag);
2571
+ const selfMatch = selfTagRegex.exec(buffer);
2572
+ const idxSelf = selfMatch ? selfMatch.index : -1;
2573
+ if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
2574
+ bestIndex = idxOpen;
2575
+ bestName = name;
2576
+ bestSelfClosing = false;
2577
+ bestTagLength = openTag.length;
2578
+ }
2579
+ if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
2580
+ bestIndex = idxSelf;
2581
+ bestName = name;
2582
+ bestSelfClosing = true;
2583
+ bestTagLength = selfMatch ? selfMatch[0].length : 0;
2486
2584
  }
2487
- const name = text.slice(nameStart, p);
2488
- return { kind: "close", name, nextPos: closing.endPos };
2489
- }
2490
- const open = consumeOpenTag(text, lt);
2491
- if (open === null) {
2492
- return { kind: "eof", nextPos: text.length };
2493
2585
  }
2494
2586
  return {
2495
- kind: "open",
2496
- name: open.name,
2497
- selfClosing: open.selfClosing,
2498
- nextPos: open.nextPos
2587
+ index: bestIndex,
2588
+ name: bestName,
2589
+ selfClosing: bestSelfClosing,
2590
+ tagLength: bestTagLength
2499
2591
  };
2500
2592
  }
2501
- function collectToolCallsFromNormalizedText(text, toolNames) {
2502
- var _a;
2503
- const normalizedText = normalizeCloseTags(text);
2504
- const collected = [];
2505
- for (const toolName of toolNames) {
2506
- const startTag = `<${toolName}>`;
2507
- let idx = 0;
2508
- let lastOrigIdx = 0;
2509
- while (idx < normalizedText.length) {
2510
- const tagStartNorm = normalizedText.indexOf(startTag, idx);
2511
- if (tagStartNorm === -1) {
2512
- break;
2593
+ var yamlXmlProtocol = (_protocolOptions) => {
2594
+ return {
2595
+ formatTools({ tools, toolSystemPromptTemplate }) {
2596
+ const toolsForPrompt = (tools || []).map((tool) => ({
2597
+ name: tool.name,
2598
+ description: tool.description,
2599
+ parameters: (0, import_rxml3.unwrapJsonSchema)(tool.inputSchema)
2600
+ }));
2601
+ return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
2602
+ },
2603
+ formatToolCall(toolCall) {
2604
+ let args = {};
2605
+ try {
2606
+ args = JSON.parse(toolCall.input);
2607
+ } catch (e) {
2608
+ args = { value: toolCall.input };
2609
+ }
2610
+ const yamlContent = import_yaml.default.stringify(args);
2611
+ return `<${toolCall.toolName}>
2612
+ ${yamlContent}</${toolCall.toolName}>`;
2613
+ },
2614
+ formatToolResponse(toolResult) {
2615
+ let result = toolResult.result;
2616
+ if (result && typeof result === "object" && "type" in result && result.type === "json" && "value" in result) {
2617
+ result = result.value;
2513
2618
  }
2514
- const contentStartNorm = tagStartNorm + startTag.length;
2515
- const endNorm = findClosingTagEndFlexible(
2516
- normalizedText,
2517
- contentStartNorm,
2518
- toolName
2619
+ const xml = (0, import_rxml3.stringify)(
2620
+ "tool_response",
2621
+ {
2622
+ tool_name: toolResult.toolName,
2623
+ result
2624
+ },
2625
+ { declaration: false }
2519
2626
  );
2520
- if (endNorm > contentStartNorm) {
2521
- const tagStartOrig = text.indexOf(startTag, lastOrigIdx);
2522
- const contentStartOrig = tagStartOrig + startTag.length;
2523
- let endOrig = findClosingTagEndFlexible(
2627
+ return xml;
2628
+ },
2629
+ parseGeneratedText({ text, tools, options }) {
2630
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
2631
+ if (toolNames.length === 0) {
2632
+ return [{ type: "text", text }];
2633
+ }
2634
+ const processedElements = [];
2635
+ let currentIndex = 0;
2636
+ const toolCalls = findToolCalls2(text, toolNames);
2637
+ for (const tc of toolCalls) {
2638
+ currentIndex = processToolCallMatch(
2524
2639
  text,
2525
- contentStartOrig,
2526
- toolName
2640
+ tc,
2641
+ currentIndex,
2642
+ processedElements,
2643
+ options
2527
2644
  );
2528
- if (endOrig === -1) {
2529
- const approxLen = endNorm - tagStartNorm;
2530
- endOrig = Math.min(text.length, tagStartOrig + approxLen);
2531
- }
2532
- const segment = text.substring(tagStartOrig, endOrig);
2533
- const inner = (_a = extractRawInner(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
2534
- collected.push({
2535
- toolName,
2536
- startIndex: tagStartOrig,
2537
- endIndex: endOrig,
2538
- content: inner,
2539
- segment
2540
- });
2541
- lastOrigIdx = endOrig;
2542
- idx = endNorm;
2543
- } else {
2544
- idx = contentStartNorm;
2545
2645
  }
2546
- }
2547
- }
2548
- return collected.sort((a, b) => a.startIndex - b.startIndex);
2549
- }
2550
- function getNextTagInfo(text, toolName, fromIndex) {
2551
- const startTag = `<${toolName}>`;
2552
- const selfTag = `<${toolName}/>`;
2553
- const openIdx = text.indexOf(startTag, fromIndex);
2554
- const selfIdx = text.indexOf(selfTag, fromIndex);
2555
- const hasOpen = openIdx !== -1;
2556
- const hasSelf = selfIdx !== -1;
2557
- if (!(hasOpen || hasSelf)) {
2558
- return {
2559
- found: false,
2560
- tagStart: -1,
2561
- selfClosing: false,
2562
- startTag,
2563
- selfTag
2564
- };
2565
- }
2566
- const pickSelf = hasSelf && (!hasOpen || selfIdx < openIdx);
2567
- const tagStart = pickSelf ? selfIdx : openIdx;
2568
- return { found: true, tagStart, selfClosing: pickSelf, startTag, selfTag };
2569
- }
2570
- function findToolCallsForName(text, toolName) {
2571
- var _a;
2572
- const toolCalls = [];
2573
- let searchIndex = 0;
2574
- while (searchIndex < text.length) {
2575
- const info = getNextTagInfo(text, toolName, searchIndex);
2576
- if (!info.found) {
2577
- break;
2578
- }
2579
- const { tagStart, selfClosing, startTag, selfTag } = info;
2580
- if (selfClosing) {
2581
- const endIndex = tagStart + selfTag.length;
2582
- const segment = text.substring(tagStart, endIndex);
2583
- toolCalls.push({
2584
- toolName,
2585
- startIndex: tagStart,
2586
- endIndex,
2587
- content: "",
2588
- segment
2589
- });
2590
- searchIndex = endIndex;
2591
- continue;
2592
- }
2593
- const contentStart = tagStart + startTag.length;
2594
- const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
2595
- if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
2596
- const segment = text.substring(tagStart, fullTagEnd);
2597
- const inner = (_a = extractRawInner(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
2598
- toolCalls.push({
2599
- toolName,
2600
- startIndex: tagStart,
2601
- endIndex: fullTagEnd,
2602
- content: inner,
2603
- segment
2646
+ if (currentIndex < text.length) {
2647
+ appendTextPart(processedElements, text.substring(currentIndex));
2648
+ }
2649
+ return processedElements;
2650
+ },
2651
+ createStreamParser({ tools, options }) {
2652
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
2653
+ let buffer = "";
2654
+ let currentToolCall = null;
2655
+ let currentTextId = null;
2656
+ let hasEmittedTextStart = false;
2657
+ const flushText = createFlushTextHandler2(
2658
+ () => currentTextId,
2659
+ (newId) => {
2660
+ currentTextId = newId;
2661
+ },
2662
+ () => hasEmittedTextStart,
2663
+ (value) => {
2664
+ hasEmittedTextStart = value;
2665
+ }
2666
+ );
2667
+ const processToolCallEnd = (controller, toolContent, toolName) => {
2668
+ var _a;
2669
+ const parsedArgs = parseYamlContent(toolContent, options);
2670
+ flushText(controller);
2671
+ if (parsedArgs !== null) {
2672
+ controller.enqueue({
2673
+ type: "tool-call",
2674
+ toolCallId: generateId(),
2675
+ toolName,
2676
+ input: JSON.stringify(parsedArgs)
2677
+ });
2678
+ } else {
2679
+ const original = `<${toolName}>${toolContent}</${toolName}>`;
2680
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
2681
+ toolCall: original
2682
+ });
2683
+ flushText(controller, original);
2684
+ }
2685
+ };
2686
+ const handlePendingToolCall = (controller, endTag, toolName) => {
2687
+ const endIdx = buffer.indexOf(endTag);
2688
+ if (endIdx === -1) {
2689
+ return false;
2690
+ }
2691
+ const content = buffer.substring(0, endIdx);
2692
+ buffer = buffer.substring(endIdx + endTag.length);
2693
+ processToolCallEnd(controller, content, toolName);
2694
+ currentToolCall = null;
2695
+ return true;
2696
+ };
2697
+ const flushSafeText = (controller) => {
2698
+ const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n} />`.length)) : 0;
2699
+ const tail = Math.max(0, maxTagLen - 1);
2700
+ const safeLen = Math.max(0, buffer.length - tail);
2701
+ if (safeLen > 0) {
2702
+ flushText(controller, buffer.slice(0, safeLen));
2703
+ buffer = buffer.slice(safeLen);
2704
+ }
2705
+ };
2706
+ const handleNewToolTag = (controller, tagIndex, tagName, selfClosing, tagLength) => {
2707
+ if (tagIndex > 0) {
2708
+ flushText(controller, buffer.substring(0, tagIndex));
2709
+ }
2710
+ if (selfClosing) {
2711
+ buffer = buffer.substring(tagIndex + tagLength);
2712
+ processToolCallEnd(controller, "", tagName);
2713
+ } else {
2714
+ const startTag = `<${tagName}>`;
2715
+ buffer = buffer.substring(tagIndex + startTag.length);
2716
+ currentToolCall = { name: tagName, content: "" };
2717
+ }
2718
+ };
2719
+ const processBuffer = (controller) => {
2720
+ while (true) {
2721
+ if (currentToolCall) {
2722
+ const toolName = currentToolCall.name;
2723
+ const endTag = `</${toolName}>`;
2724
+ if (!handlePendingToolCall(controller, endTag, toolName)) {
2725
+ break;
2726
+ }
2727
+ } else {
2728
+ const { index, name, selfClosing, tagLength } = findEarliestToolTag2(
2729
+ buffer,
2730
+ toolNames
2731
+ );
2732
+ if (index === -1) {
2733
+ flushSafeText(controller);
2734
+ break;
2735
+ }
2736
+ handleNewToolTag(controller, index, name, selfClosing, tagLength);
2737
+ }
2738
+ }
2739
+ };
2740
+ return new TransformStream({
2741
+ transform(chunk, controller) {
2742
+ var _a, _b;
2743
+ if (chunk.type !== "text-delta") {
2744
+ if (buffer) {
2745
+ flushText(controller, buffer);
2746
+ buffer = "";
2747
+ }
2748
+ controller.enqueue(chunk);
2749
+ return;
2750
+ }
2751
+ const textContent = (_b = (_a = chunk.textDelta) != null ? _a : chunk.delta) != null ? _b : "";
2752
+ buffer += textContent;
2753
+ processBuffer(controller);
2754
+ },
2755
+ flush(controller) {
2756
+ if (currentToolCall) {
2757
+ const unfinishedContent = `<${currentToolCall.name}>${buffer}`;
2758
+ flushText(controller, unfinishedContent);
2759
+ buffer = "";
2760
+ currentToolCall = null;
2761
+ } else if (buffer) {
2762
+ flushText(controller, buffer);
2763
+ buffer = "";
2764
+ }
2765
+ if (currentTextId && hasEmittedTextStart) {
2766
+ controller.enqueue({
2767
+ type: "text-end",
2768
+ id: currentTextId
2769
+ });
2770
+ hasEmittedTextStart = false;
2771
+ currentTextId = null;
2772
+ }
2773
+ }
2604
2774
  });
2605
- searchIndex = fullTagEnd;
2606
- } else {
2607
- searchIndex = contentStart;
2775
+ },
2776
+ extractToolCallSegments({ text, tools }) {
2777
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
2778
+ if (toolNames.length === 0) {
2779
+ return [];
2780
+ }
2781
+ return findToolCalls2(text, toolNames).map(
2782
+ (tc) => `<${tc.toolName}>${tc.content}</${tc.toolName}>`
2783
+ );
2608
2784
  }
2609
- }
2610
- return toolCalls;
2611
- }
2612
- function findToolCalls(text, toolNames) {
2613
- const toolCalls = [];
2614
- for (const toolName of toolNames) {
2615
- const calls = findToolCallsForName(text, toolName);
2616
- toolCalls.push(...calls);
2617
- }
2618
- return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
2785
+ };
2786
+ };
2787
+ function orchestratorSystemPromptTemplate(tools, includeMultilineExample = true) {
2788
+ const multilineExample = includeMultilineExample ? `
2789
+
2790
+ For multiline values, use YAML's literal block syntax:
2791
+ <write_file>
2792
+ file_path: /tmp/example.txt
2793
+ contents: |
2794
+ First line
2795
+ Second line
2796
+ Third line
2797
+ </write_file>` : "";
2798
+ return `# Tools
2799
+
2800
+ You may call one or more functions to assist with the user query.
2801
+
2802
+ You are provided with function signatures within <tools></tools> XML tags:
2803
+ <tools>${tools}</tools>
2804
+
2805
+ # Format
2806
+
2807
+ Use exactly one XML element whose tag name is the function name.
2808
+ Inside the XML element, specify parameters using YAML syntax (key: value pairs).
2809
+
2810
+ # Example
2811
+ <get_weather>
2812
+ location: New York
2813
+ unit: celsius
2814
+ </get_weather>${multilineExample}
2815
+
2816
+ # Rules
2817
+ - Parameter names and values must follow the schema exactly.
2818
+ - Use proper YAML syntax for values (strings, numbers, booleans, arrays, objects).
2819
+ - Each required parameter must appear once.
2820
+ - Do not add functions or parameters not in the schema.
2821
+ - After calling a tool, you will receive a response. Use this result to answer the user.
2822
+ - Do NOT ask clarifying questions. Use reasonable defaults for optional parameters.
2823
+ - If a task requires multiple function calls, make ALL of them at once.`;
2619
2824
  }
2620
2825
 
2621
- // src/generate-handler.ts
2622
- import { generateId as generateId3 } from "@ai-sdk/provider-utils";
2623
- import { coerceBySchema } from "@ai-sdk-tool/rxml";
2826
+ // src/core/protocols/tool-call-protocol.ts
2827
+ function isProtocolFactory(protocol) {
2828
+ return typeof protocol === "function";
2829
+ }
2624
2830
 
2625
- // src/utils/on-error.ts
2831
+ // src/core/utils/on-error.ts
2626
2832
  function extractOnErrorOption(providerOptions) {
2627
2833
  var _a;
2628
2834
  if (providerOptions && typeof providerOptions === "object") {
@@ -2632,7 +2838,7 @@ function extractOnErrorOption(providerOptions) {
2632
2838
  return;
2633
2839
  }
2634
2840
 
2635
- // src/utils/provider-options.ts
2841
+ // src/core/utils/provider-options.ts
2636
2842
  var originalToolsSchema = {
2637
2843
  encode: encodeOriginalTools,
2638
2844
  decode: decodeOriginalTools
@@ -2655,16 +2861,15 @@ function decodeOriginalTools(originalTools) {
2655
2861
  })
2656
2862
  );
2657
2863
  }
2658
- function extractToolNamesFromOriginalTools(originalTools) {
2659
- return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
2660
- }
2661
2864
  function isToolChoiceActive(params) {
2662
2865
  var _a, _b, _c;
2663
2866
  const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
2664
2867
  return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
2665
2868
  }
2666
2869
 
2667
- // src/generate-handler.ts
2870
+ // src/v6/generate-handler.ts
2871
+ var import_provider_utils = require("@ai-sdk/provider-utils");
2872
+ var import_rxml4 = require("@ai-sdk-tool/rxml");
2668
2873
  function parseToolChoiceJson(text, providerOptions) {
2669
2874
  var _a;
2670
2875
  try {
@@ -2708,7 +2913,7 @@ async function handleToolChoice(doGenerate, params) {
2708
2913
  }
2709
2914
  const toolCall = {
2710
2915
  type: "tool-call",
2711
- toolCallId: generateId3(),
2916
+ toolCallId: (0, import_provider_utils.generateId)(),
2712
2917
  toolName: parsed.name || "unknown",
2713
2918
  input: JSON.stringify(parsed.arguments || {})
2714
2919
  };
@@ -2827,80 +3032,79 @@ function fixToolCallWithSchema(part, tools) {
2827
3032
  args = tc.input;
2828
3033
  }
2829
3034
  const schema = (_a = tools.find((t) => t.name === tc.toolName)) == null ? void 0 : _a.inputSchema;
2830
- const coerced = coerceBySchema(args, schema);
3035
+ const coerced = (0, import_rxml4.coerceBySchema)(args, schema);
2831
3036
  return {
2832
3037
  ...part,
2833
3038
  input: JSON.stringify(coerced != null ? coerced : {})
2834
3039
  };
2835
3040
  }
2836
3041
 
2837
- // src/protocols/tool-call-protocol.ts
2838
- function isProtocolFactory(protocol) {
2839
- return typeof protocol === "function";
2840
- }
2841
-
2842
- // src/stream-handler.ts
2843
- import { generateId as generateId4 } from "@ai-sdk/provider-utils";
2844
- function extractToolCallSegments(protocol, fullRawText, tools) {
2845
- const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
2846
- text: fullRawText,
2847
- tools
2848
- }) : [];
2849
- return segments.join("\n\n");
2850
- }
2851
- function serializeToolCalls(parsedToolCalls) {
2852
- const toolCallParts = parsedToolCalls.filter(
2853
- (p) => p.type === "tool-call"
2854
- );
2855
- return JSON.stringify(
2856
- toolCallParts.map((tc) => ({
2857
- toolName: tc.toolName,
2858
- input: tc.input
2859
- }))
2860
- );
2861
- }
2862
- function handleDebugSummary(parsedToolCalls, origin, params) {
2863
- var _a, _b;
2864
- const dbg = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.debugSummary;
2865
- if (dbg) {
2866
- dbg.originalText = origin;
2867
- try {
2868
- dbg.toolCalls = serializeToolCalls(parsedToolCalls);
2869
- } catch (e) {
2870
- }
2871
- } else {
2872
- logParsedSummary({
2873
- toolCalls: parsedToolCalls,
2874
- originalText: origin
2875
- });
3042
+ // src/v6/stream-handler.ts
3043
+ var import_provider_utils2 = require("@ai-sdk/provider-utils");
3044
+ function mapCorePartToV3(part) {
3045
+ switch (part.type) {
3046
+ case "text-delta":
3047
+ return {
3048
+ type: "text-delta",
3049
+ id: part.id || (0, import_provider_utils2.generateId)(),
3050
+ delta: part.textDelta
3051
+ };
3052
+ case "tool-call":
3053
+ return {
3054
+ type: "tool-call",
3055
+ toolCallId: part.toolCallId,
3056
+ toolName: part.toolName,
3057
+ input: part.input
3058
+ };
3059
+ case "tool-call-delta":
3060
+ return {
3061
+ type: "tool-call-delta",
3062
+ toolCallId: part.toolCallId,
3063
+ toolName: part.toolName,
3064
+ argsTextDelta: part.argsTextDelta
3065
+ };
3066
+ case "finish":
3067
+ return {
3068
+ type: "finish",
3069
+ finishReason: part.finishReason,
3070
+ usage: part.usage
3071
+ };
3072
+ case "error":
3073
+ return {
3074
+ type: "error",
3075
+ error: part.error
3076
+ };
3077
+ default:
3078
+ return part;
2876
3079
  }
2877
3080
  }
2878
- function createDebugSummaryTransform({
2879
- protocol,
2880
- getFullRawText,
2881
- tools,
2882
- params
2883
- }) {
2884
- return new TransformStream({
2885
- transform: /* @__PURE__ */ (() => {
2886
- const parsedToolCalls = [];
2887
- return (part, controller) => {
2888
- if (part.type === "tool-call") {
2889
- parsedToolCalls.push(part);
2890
- }
2891
- if (part.type === "finish") {
2892
- try {
2893
- const raw = getFullRawText();
2894
- logRawChunk(raw);
2895
- const origin = extractToolCallSegments(protocol, raw, tools);
2896
- handleDebugSummary(parsedToolCalls, origin, params);
2897
- } catch (e) {
2898
- }
2899
- }
2900
- controller.enqueue(part);
3081
+ function mapV3PartToCore(part) {
3082
+ const p = part;
3083
+ switch (p.type) {
3084
+ case "text-delta":
3085
+ return {
3086
+ type: "text-delta",
3087
+ id: p.id,
3088
+ textDelta: p.delta || p.textDelta || ""
2901
3089
  };
2902
- })()
2903
- });
3090
+ case "tool-call":
3091
+ return {
3092
+ type: "tool-call",
3093
+ toolCallId: p.toolCallId,
3094
+ toolName: p.toolName,
3095
+ input: p.input
3096
+ };
3097
+ case "finish": {
3098
+ const finishReason = p.finishReason;
3099
+ return {
3100
+ type: "finish",
3101
+ finishReason: (typeof finishReason === "object" ? finishReason == null ? void 0 : finishReason.unified : finishReason) || "stop",
3102
+ usage: p.usage
3103
+ };
3104
+ }
3105
+ default:
3106
+ return p;
3107
+ }
2904
3108
  }
2905
3109
  async function wrapStream({
2906
3110
  protocol,
@@ -2922,89 +3126,39 @@ async function wrapStream({
2922
3126
  );
2923
3127
  const options = {
2924
3128
  ...extractOnErrorOption(params.providerOptions),
2925
- ...(_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware
3129
+ ...((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) || {}
2926
3130
  };
2927
- if (debugLevel === "off") {
2928
- return {
2929
- stream: stream.pipeThrough(
2930
- protocol.createStreamParser({
2931
- tools,
2932
- options
2933
- })
2934
- ),
2935
- ...rest
2936
- };
2937
- }
2938
- if (debugLevel === "stream") {
2939
- const withRawTap2 = stream.pipeThrough(
2940
- new TransformStream(
2941
- {
2942
- transform(part, controller) {
2943
- logRawChunk(part);
2944
- controller.enqueue(part);
2945
- }
2946
- }
2947
- )
2948
- );
2949
- const parsed2 = withRawTap2.pipeThrough(
2950
- protocol.createStreamParser({
2951
- tools,
2952
- options
2953
- })
2954
- );
2955
- const withParsedTap = parsed2.pipeThrough(
2956
- new TransformStream(
2957
- {
2958
- transform(part, controller) {
2959
- logParsedChunk(part);
2960
- controller.enqueue(part);
2961
- }
2962
- }
2963
- )
2964
- );
2965
- return {
2966
- stream: withParsedTap,
2967
- ...rest
2968
- };
2969
- }
2970
- let fullRawText = "";
2971
- const withRawTap = stream.pipeThrough(
3131
+ const coreStream = stream.pipeThrough(
2972
3132
  new TransformStream({
2973
3133
  transform(part, controller) {
2974
- if (part.type === "text-delta") {
2975
- const delta = part.delta;
2976
- if (typeof delta === "string" && delta.length > 0) {
2977
- fullRawText += delta;
2978
- }
3134
+ if (debugLevel === "stream") {
3135
+ logRawChunk(part);
2979
3136
  }
2980
- controller.enqueue(part);
3137
+ controller.enqueue(mapV3PartToCore(part));
2981
3138
  }
2982
3139
  })
2983
- );
2984
- const parsed = withRawTap.pipeThrough(
2985
- protocol.createStreamParser({
2986
- tools,
2987
- options
2988
- })
2989
- );
2990
- const withSummary = parsed.pipeThrough(
2991
- createDebugSummaryTransform({
2992
- protocol,
2993
- getFullRawText: () => fullRawText,
2994
- tools,
2995
- params
3140
+ ).pipeThrough(protocol.createStreamParser({ tools, options }));
3141
+ const v3Stream = coreStream.pipeThrough(
3142
+ new TransformStream({
3143
+ transform(part, controller) {
3144
+ const v3Part = mapCorePartToV3(part);
3145
+ if (debugLevel === "stream") {
3146
+ logParsedChunk(v3Part);
3147
+ }
3148
+ controller.enqueue(v3Part);
3149
+ }
2996
3150
  })
2997
3151
  );
2998
3152
  return {
2999
- stream: withSummary,
3000
- ...rest
3153
+ ...rest,
3154
+ stream: v3Stream
3001
3155
  };
3002
3156
  }
3003
3157
  async function toolChoiceStream({
3004
3158
  doGenerate,
3005
3159
  options
3006
3160
  }) {
3007
- var _a, _b, _c;
3161
+ var _a, _b;
3008
3162
  const result = await doGenerate();
3009
3163
  let toolJson = {};
3010
3164
  if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
@@ -3022,62 +3176,33 @@ async function toolChoiceStream({
3022
3176
  toolJson = {};
3023
3177
  }
3024
3178
  }
3025
- const toolCallChunk = {
3026
- type: "tool-call",
3027
- toolCallId: generateId4(),
3028
- toolName: toolJson.name || "unknown",
3029
- input: JSON.stringify(toolJson.arguments || {})
3030
- };
3031
- const finishChunk = {
3032
- type: "finish",
3033
- usage: (result == null ? void 0 : result.usage) || {
3034
- inputTokens: {
3035
- total: 0,
3036
- noCache: void 0,
3037
- cacheRead: void 0,
3038
- cacheWrite: void 0
3039
- },
3040
- outputTokens: {
3041
- total: 0,
3042
- text: void 0,
3043
- reasoning: void 0
3044
- }
3045
- },
3046
- finishReason: { unified: "tool-calls", raw: void 0 }
3047
- };
3048
3179
  const stream = new ReadableStream({
3049
3180
  start(controller) {
3050
- controller.enqueue(toolCallChunk);
3051
- controller.enqueue(finishChunk);
3181
+ controller.enqueue({
3182
+ type: "tool-call",
3183
+ toolCallId: (0, import_provider_utils2.generateId)(),
3184
+ toolName: toolJson.name || "unknown",
3185
+ input: JSON.stringify(toolJson.arguments || {})
3186
+ });
3187
+ controller.enqueue({
3188
+ type: "finish",
3189
+ usage: (result == null ? void 0 : result.usage) || {
3190
+ inputTokens: 0,
3191
+ outputTokens: 0
3192
+ },
3193
+ finishReason: "tool-calls"
3194
+ });
3052
3195
  controller.close();
3053
3196
  }
3054
3197
  });
3055
- const debugLevel = getDebugLevel();
3056
- const firstText = ((_c = result == null ? void 0 : result.content) == null ? void 0 : _c[0]) && result.content[0].type === "text" && result.content[0].text || "";
3057
- const streamWithSummary = debugLevel === "parse" ? stream.pipeThrough(
3058
- new TransformStream({
3059
- transform(part, controller) {
3060
- if (part.type === "finish") {
3061
- try {
3062
- logParsedSummary({
3063
- toolCalls: [toolCallChunk],
3064
- originalText: typeof firstText === "string" ? firstText : ""
3065
- });
3066
- } catch (e) {
3067
- }
3068
- }
3069
- controller.enqueue(part);
3070
- }
3071
- })
3072
- ) : stream;
3073
3198
  return {
3074
3199
  request: (result == null ? void 0 : result.request) || {},
3075
3200
  response: (result == null ? void 0 : result.response) || {},
3076
- stream: streamWithSummary
3201
+ stream
3077
3202
  };
3078
3203
  }
3079
3204
 
3080
- // src/utils/dynamic-tool-schema.ts
3205
+ // src/core/utils/dynamic-tool-schema.ts
3081
3206
  function createDynamicIfThenElseSchema(tools) {
3082
3207
  let currentSchema = {};
3083
3208
  const toolNames = [];
@@ -3134,7 +3259,13 @@ function createDynamicIfThenElseSchema(tools) {
3134
3259
  };
3135
3260
  }
3136
3261
 
3137
- // src/transform-handler.ts
3262
+ // src/core/utils/type-guards.ts
3263
+ function isToolCallContent(content) {
3264
+ return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
3265
+ (typeof content.input === "string" || typeof content.input === "object");
3266
+ }
3267
+
3268
+ // src/v6/transform-handler.ts
3138
3269
  function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
3139
3270
  const systemIndex = processedPrompt.findIndex((m) => m.role === "system");
3140
3271
  if (systemIndex !== -1) {
@@ -3356,7 +3487,14 @@ function processToolMessage(content, resolvedProtocol) {
3356
3487
  content: [
3357
3488
  {
3358
3489
  type: "text",
3359
- text: content.map((toolResult) => resolvedProtocol.formatToolResponse(toolResult)).join("\n")
3490
+ text: content.map((toolResult) => {
3491
+ var _a, _b;
3492
+ const tr = toolResult;
3493
+ return resolvedProtocol.formatToolResponse({
3494
+ ...toolResult,
3495
+ result: (_b = (_a = tr.result) != null ? _a : tr.content) != null ? _b : tr.output
3496
+ });
3497
+ }).join("\n")
3360
3498
  }
3361
3499
  ]
3362
3500
  };
@@ -3449,7 +3587,7 @@ function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
3449
3587
  return processedPrompt;
3450
3588
  }
3451
3589
 
3452
- // src/tool-call-middleware.ts
3590
+ // src/v6/tool-call-middleware.ts
3453
3591
  function createToolMiddleware({
3454
3592
  protocol,
3455
3593
  toolSystemPromptTemplate,
@@ -3486,19 +3624,14 @@ function createToolMiddleware({
3486
3624
  };
3487
3625
  }
3488
3626
 
3489
- // src/index.ts
3627
+ // src/v6/index.ts
3490
3628
  var gemmaToolMiddleware = createToolMiddleware({
3491
- protocol: jsonMixProtocol(
3492
- // Customize the tool call delimiters to use markdown code fences
3493
- {
3494
- toolCallStart: "```tool_call\n",
3495
- // TODO: Support specifying multiple possible tags,
3496
- // e.g., for gemma, it would be nice to be able to set both `` and ``` at the same time.
3497
- toolCallEnd: "\n```",
3498
- toolResponseStart: "```tool_response\n",
3499
- toolResponseEnd: "\n```"
3500
- }
3501
- ),
3629
+ protocol: jsonMixProtocol({
3630
+ toolCallStart: "```tool_call\n",
3631
+ toolCallEnd: "\n```",
3632
+ toolResponseStart: "```tool_response\n",
3633
+ toolResponseEnd: "\n```"
3634
+ }),
3502
3635
  toolSystemPromptTemplate(tools) {
3503
3636
  return `You have access to functions. If you decide to invoke any of the function(s),
3504
3637
  you MUST put it in the format of markdown code fence block with the language name of tool_call , e.g.
@@ -3526,11 +3659,13 @@ For each function call return a json object with function name and arguments wit
3526
3659
  });
3527
3660
  var morphXmlToolMiddleware = createToolMiddleware({
3528
3661
  protocol: morphXmlProtocol,
3529
- placement: "last",
3662
+ placement: "first",
3530
3663
  toolSystemPromptTemplate(tools) {
3531
- return `You are a function calling AI model.
3664
+ return `# Tools
3665
+
3666
+ You may call one or more functions to assist with the user query.
3532
3667
 
3533
- Available functions are listed inside <tools></tools>.
3668
+ You are provided with function signatures within <tools></tools> XML tags:
3534
3669
  <tools>${tools}</tools>
3535
3670
 
3536
3671
  # Rules
@@ -3540,6 +3675,7 @@ Available functions are listed inside <tools></tools>.
3540
3675
  - Do not add or remove functions or parameters.
3541
3676
  - Each required parameter must appear once.
3542
3677
  - Output nothing before or after the function call.
3678
+ - After calling a tool, you will receive a response in the format: <tool_response><tool_name>NAME</tool_name><result>RESULT</result></tool_response>. Use this result to answer the user.
3543
3679
 
3544
3680
  # Example
3545
3681
  <get_weather>
@@ -3548,42 +3684,17 @@ Available functions are listed inside <tools></tools>.
3548
3684
  </get_weather>`;
3549
3685
  }
3550
3686
  });
3551
-
3552
- export {
3553
- getDebugLevel,
3554
- logParseFailure,
3555
- logRawChunk,
3556
- logParsedChunk,
3557
- logParsedSummary,
3558
- getPotentialStartIndex,
3559
- escapeRegExp,
3560
- transform,
3561
- parse,
3562
- stringify,
3563
- jsonMixProtocol,
3564
- applyHeuristicPipeline,
3565
- createIntermediateCall,
3566
- mergePipelineConfigs,
3567
- normalizeCloseTagsHeuristic,
3568
- escapeInvalidLtHeuristic,
3569
- balanceTagsHeuristic,
3570
- dedupeShellStringTagsHeuristic,
3571
- repairAgainstSchemaHeuristic,
3572
- defaultPipelineConfig,
3573
- isToolCallContent,
3574
- isToolResultPart,
3575
- hasInputProperty,
3576
- morphXmlProtocol,
3577
- extractOnErrorOption,
3578
- originalToolsSchema,
3579
- encodeOriginalTools,
3580
- decodeOriginalTools,
3581
- extractToolNamesFromOriginalTools,
3582
- isToolChoiceActive,
3583
- createDynamicIfThenElseSchema,
3687
+ var orchestratorToolMiddleware = createToolMiddleware({
3688
+ protocol: yamlXmlProtocol(),
3689
+ placement: "first",
3690
+ toolSystemPromptTemplate: orchestratorSystemPromptTemplate
3691
+ });
3692
+ // Annotate the CommonJS export names for ESM import in node:
3693
+ 0 && (module.exports = {
3584
3694
  createToolMiddleware,
3585
3695
  gemmaToolMiddleware,
3586
3696
  hermesToolMiddleware,
3587
- morphXmlToolMiddleware
3588
- };
3589
- //# sourceMappingURL=chunk-2B2YNKXY.js.map
3697
+ morphXmlToolMiddleware,
3698
+ orchestratorToolMiddleware
3699
+ });
3700
+ //# sourceMappingURL=v6.cjs.map