@ai-sdk-tool/parser 3.0.0-canary.2 → 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,557 +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
- for (const toolCall of toolCalls) {
2272
- currentIndex = processTextBeforeToolCall(
2273
- text,
2274
- currentIndex,
2275
- toolCall.startIndex,
2276
- processedElements
2277
- );
2278
- if (pipelineConfig) {
2279
- processToolCallWithPipeline({
2280
- toolCall,
2281
- tools,
2282
- options,
2283
- text,
2284
- processedElements,
2285
- pipelineConfig,
2286
- maxReparses
2287
- });
2288
- } else {
2289
- processToolCall({
2290
- toolCall,
2291
- tools,
2292
- options,
2293
- text,
2294
- 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)
2295
2224
  });
2296
2225
  }
2297
- 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
+ });
2298
2242
  }
2299
- addRemainingText(text, currentIndex, processedElements);
2300
2243
  return processedElements;
2301
2244
  },
2302
2245
  createStreamParser({ tools, options }) {
2303
- const toolNames = tools.map((t) => t.name).filter((name) => name != null);
2304
- const maxStartTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n}>`.length)) : 0;
2246
+ const toolNames = tools.map((t) => t.name).filter(Boolean);
2305
2247
  let buffer = "";
2306
2248
  let currentToolCall = null;
2307
2249
  let currentTextId = null;
2250
+ let hasEmittedTextStart = false;
2308
2251
  const flushText = createFlushTextHandler(
2309
- () => buffer,
2310
- (newBuffer) => {
2311
- buffer = newBuffer;
2312
- },
2313
2252
  () => currentTextId,
2314
2253
  (newId) => {
2315
2254
  currentTextId = newId;
2255
+ },
2256
+ () => hasEmittedTextStart,
2257
+ (value) => {
2258
+ hasEmittedTextStart = value;
2316
2259
  }
2317
2260
  );
2318
- const processChunk = (chunk, controller) => {
2319
- if (chunk.type !== "text-delta") {
2320
- if (buffer) {
2321
- flushText(controller);
2322
- }
2323
- controller.enqueue(chunk);
2324
- return;
2325
- }
2326
- buffer += chunk.delta;
2327
- processBuffer(controller);
2328
- };
2329
- const processBuffer = createProcessBufferHandler({
2330
- getBuffer: () => buffer,
2331
- setBuffer: (newBuffer) => {
2261
+ const processBuffer = createProcessBufferHandler(
2262
+ () => buffer,
2263
+ (newBuffer) => {
2332
2264
  buffer = newBuffer;
2333
2265
  },
2334
- getCurrentToolCall: () => currentToolCall,
2335
- setCurrentToolCall: (newToolCall) => {
2266
+ () => currentToolCall,
2267
+ (newToolCall) => {
2336
2268
  currentToolCall = newToolCall;
2337
2269
  },
2338
2270
  tools,
2339
2271
  options,
2340
2272
  toolNames,
2341
- maxStartTagLen,
2342
2273
  flushText,
2343
2274
  pipelineConfig,
2344
2275
  maxReparses
2345
- });
2346
- const flushBuffer2 = (controller) => {
2347
- if (currentToolCall) {
2348
- const unfinishedCall = `<${currentToolCall.name}>${buffer}`;
2349
- flushText(controller, unfinishedCall);
2350
- } else if (buffer) {
2351
- flushText(controller);
2352
- }
2353
- if (currentTextId) {
2354
- controller.enqueue({ type: "text-end", id: currentTextId });
2355
- }
2356
- };
2276
+ );
2357
2277
  return new TransformStream({
2358
2278
  transform(chunk, controller) {
2359
- 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);
2360
2291
  },
2361
2292
  flush(controller) {
2362
- 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
+ }
2363
2310
  }
2364
2311
  });
2365
2312
  },
@@ -2372,237 +2319,516 @@ var morphXmlProtocol = (protocolOptions) => {
2372
2319
  }
2373
2320
  };
2374
2321
  };
2375
- function getToolSchema(tools, toolName) {
2376
- var _a;
2377
- return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
2378
- }
2379
- 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) {
2380
2330
  let pos = contentStart;
2381
2331
  let depth = 1;
2382
2332
  while (pos < text.length) {
2383
- const tok = nextTagToken(text, pos);
2384
- if (tok.kind === "eof") {
2333
+ const ltIdx = text.indexOf("<", pos);
2334
+ if (ltIdx === -1) {
2385
2335
  break;
2386
2336
  }
2387
- const result = updateDepthWithToken(tok, toolName, depth);
2388
- depth = result.depth;
2389
- if (result.closedAt !== void 0) {
2390
- 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;
2391
2385
  }
2392
- pos = tok.nextPos;
2393
2386
  }
2394
2387
  return -1;
2395
2388
  }
2396
- function skipSpecialSegment(text, lt) {
2397
- const next = text[lt + 1];
2398
- if (next !== "!" && next !== "?") {
2399
- return null;
2400
- }
2401
- const gt = text.indexOf(">", lt + 1);
2402
- if (gt === -1) {
2403
- 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 };
2404
2394
  }
2405
- return gt + 1;
2395
+ return { tagStart: openIdx, isSelfClosing: false };
2406
2396
  }
2407
- function consumeClosingTag(text, lt, _toolName) {
2408
- let p = lt + 2;
2409
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
2410
- 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
+ }
2411
2442
  }
2412
- const gt = text.indexOf(">", lt + 1);
2413
- const endPos = gt === -1 ? text.length : gt + 1;
2414
- return { matched: false, endPos };
2443
+ return toolCalls;
2415
2444
  }
2416
- function consumeOpenTag(text, lt) {
2417
- let p = lt + 1;
2418
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
2419
- 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);
2420
2456
  }
2421
- const nameStart = p;
2422
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
2423
- 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 {};
2424
2461
  }
2425
- const name = text.slice(nameStart, p);
2426
- const q = text.indexOf(">", p);
2427
- if (q === -1) {
2428
- 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");
2429
2470
  }
2430
- let r = q - 1;
2431
- while (r >= nameStart && WHITESPACE_REGEX3.test(text[r])) {
2432
- 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;
2433
2493
  }
2434
- const selfClosing = text[r] === "/";
2435
- return { name, selfClosing, nextPos: q + 1 };
2436
2494
  }
2437
- function updateDepthWithToken(tok, toolName, depth) {
2438
- if (tok.kind === "close" && tok.name === toolName) {
2439
- const newDepth = depth - 1;
2440
- return newDepth === 0 ? { depth: newDepth, closedAt: tok.nextPos } : { depth: newDepth };
2441
- }
2442
- if (tok.kind === "open" && tok.name === toolName && !tok.selfClosing) {
2443
- return { depth: depth + 1 };
2495
+ function appendTextPart(processedElements, textPart) {
2496
+ if (textPart.trim()) {
2497
+ processedElements.push({
2498
+ type: "text",
2499
+ text: textPart
2500
+ });
2444
2501
  }
2445
- return { depth };
2446
2502
  }
2447
- function nextTagToken(text, fromPos) {
2448
- const lt = text.indexOf("<", fromPos);
2449
- if (lt === -1 || lt + 1 >= text.length) {
2450
- 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;
2451
2507
  }
2452
- const next = text[lt + 1];
2453
- const specialEnd = skipSpecialSegment(text, lt);
2454
- if (specialEnd !== null) {
2455
- 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 });
2456
2526
  }
2457
- if (next === "/") {
2458
- const closing = consumeClosingTag(text, lt, "");
2459
- let p = lt + 2;
2460
- while (p < text.length && WHITESPACE_REGEX3.test(text[p])) {
2461
- 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
+ });
2462
2548
  }
2463
- const nameStart = p;
2464
- while (p < text.length && NAME_CHAR_RE2.test(text.charAt(p))) {
2465
- 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;
2466
2584
  }
2467
- const name = text.slice(nameStart, p);
2468
- return { kind: "close", name, nextPos: closing.endPos };
2469
- }
2470
- const open = consumeOpenTag(text, lt);
2471
- if (open === null) {
2472
- return { kind: "eof", nextPos: text.length };
2473
2585
  }
2474
2586
  return {
2475
- kind: "open",
2476
- name: open.name,
2477
- selfClosing: open.selfClosing,
2478
- nextPos: open.nextPos
2587
+ index: bestIndex,
2588
+ name: bestName,
2589
+ selfClosing: bestSelfClosing,
2590
+ tagLength: bestTagLength
2479
2591
  };
2480
2592
  }
2481
- function collectToolCallsFromNormalizedText(text, toolNames) {
2482
- var _a;
2483
- const normalizedText = normalizeCloseTags(text);
2484
- const collected = [];
2485
- for (const toolName of toolNames) {
2486
- const startTag = `<${toolName}>`;
2487
- let idx = 0;
2488
- let lastOrigIdx = 0;
2489
- while (idx < normalizedText.length) {
2490
- const tagStartNorm = normalizedText.indexOf(startTag, idx);
2491
- if (tagStartNorm === -1) {
2492
- 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;
2493
2618
  }
2494
- const contentStartNorm = tagStartNorm + startTag.length;
2495
- const endNorm = findClosingTagEndFlexible(
2496
- normalizedText,
2497
- contentStartNorm,
2498
- toolName
2619
+ const xml = (0, import_rxml3.stringify)(
2620
+ "tool_response",
2621
+ {
2622
+ tool_name: toolResult.toolName,
2623
+ result
2624
+ },
2625
+ { declaration: false }
2499
2626
  );
2500
- if (endNorm > contentStartNorm) {
2501
- const tagStartOrig = text.indexOf(startTag, lastOrigIdx);
2502
- const contentStartOrig = tagStartOrig + startTag.length;
2503
- 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(
2504
2639
  text,
2505
- contentStartOrig,
2506
- toolName
2640
+ tc,
2641
+ currentIndex,
2642
+ processedElements,
2643
+ options
2507
2644
  );
2508
- if (endOrig === -1) {
2509
- const approxLen = endNorm - tagStartNorm;
2510
- endOrig = Math.min(text.length, tagStartOrig + approxLen);
2511
- }
2512
- const segment = text.substring(tagStartOrig, endOrig);
2513
- const inner = (_a = extractRawInner(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
2514
- collected.push({
2515
- toolName,
2516
- startIndex: tagStartOrig,
2517
- endIndex: endOrig,
2518
- content: inner,
2519
- segment
2520
- });
2521
- lastOrigIdx = endOrig;
2522
- idx = endNorm;
2523
- } else {
2524
- idx = contentStartNorm;
2525
2645
  }
2526
- }
2527
- }
2528
- return collected.sort((a, b) => a.startIndex - b.startIndex);
2529
- }
2530
- function getNextTagInfo(text, toolName, fromIndex) {
2531
- const startTag = `<${toolName}>`;
2532
- const selfTag = `<${toolName}/>`;
2533
- const openIdx = text.indexOf(startTag, fromIndex);
2534
- const selfIdx = text.indexOf(selfTag, fromIndex);
2535
- const hasOpen = openIdx !== -1;
2536
- const hasSelf = selfIdx !== -1;
2537
- if (!(hasOpen || hasSelf)) {
2538
- return {
2539
- found: false,
2540
- tagStart: -1,
2541
- selfClosing: false,
2542
- startTag,
2543
- selfTag
2544
- };
2545
- }
2546
- const pickSelf = hasSelf && (!hasOpen || selfIdx < openIdx);
2547
- const tagStart = pickSelf ? selfIdx : openIdx;
2548
- return { found: true, tagStart, selfClosing: pickSelf, startTag, selfTag };
2549
- }
2550
- function findToolCallsForName(text, toolName) {
2551
- var _a;
2552
- const toolCalls = [];
2553
- let searchIndex = 0;
2554
- while (searchIndex < text.length) {
2555
- const info = getNextTagInfo(text, toolName, searchIndex);
2556
- if (!info.found) {
2557
- break;
2558
- }
2559
- const { tagStart, selfClosing, startTag, selfTag } = info;
2560
- if (selfClosing) {
2561
- const endIndex = tagStart + selfTag.length;
2562
- const segment = text.substring(tagStart, endIndex);
2563
- toolCalls.push({
2564
- toolName,
2565
- startIndex: tagStart,
2566
- endIndex,
2567
- content: "",
2568
- segment
2569
- });
2570
- searchIndex = endIndex;
2571
- continue;
2572
- }
2573
- const contentStart = tagStart + startTag.length;
2574
- const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
2575
- if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
2576
- const segment = text.substring(tagStart, fullTagEnd);
2577
- const inner = (_a = extractRawInner(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
2578
- toolCalls.push({
2579
- toolName,
2580
- startIndex: tagStart,
2581
- endIndex: fullTagEnd,
2582
- content: inner,
2583
- 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
+ }
2584
2774
  });
2585
- searchIndex = fullTagEnd;
2586
- } else {
2587
- 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
+ );
2588
2784
  }
2589
- }
2590
- return toolCalls;
2591
- }
2592
- function findToolCalls(text, toolNames) {
2593
- const toolCalls = [];
2594
- for (const toolName of toolNames) {
2595
- const calls = findToolCallsForName(text, toolName);
2596
- toolCalls.push(...calls);
2597
- }
2598
- 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.`;
2599
2824
  }
2600
2825
 
2601
- // src/generate-handler.ts
2602
- import { generateId as generateId3 } from "@ai-sdk/provider-utils";
2603
- 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
+ }
2604
2830
 
2605
- // src/utils/on-error.ts
2831
+ // src/core/utils/on-error.ts
2606
2832
  function extractOnErrorOption(providerOptions) {
2607
2833
  var _a;
2608
2834
  if (providerOptions && typeof providerOptions === "object") {
@@ -2612,7 +2838,7 @@ function extractOnErrorOption(providerOptions) {
2612
2838
  return;
2613
2839
  }
2614
2840
 
2615
- // src/utils/provider-options.ts
2841
+ // src/core/utils/provider-options.ts
2616
2842
  var originalToolsSchema = {
2617
2843
  encode: encodeOriginalTools,
2618
2844
  decode: decodeOriginalTools
@@ -2635,16 +2861,15 @@ function decodeOriginalTools(originalTools) {
2635
2861
  })
2636
2862
  );
2637
2863
  }
2638
- function extractToolNamesFromOriginalTools(originalTools) {
2639
- return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
2640
- }
2641
2864
  function isToolChoiceActive(params) {
2642
2865
  var _a, _b, _c;
2643
2866
  const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
2644
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"));
2645
2868
  }
2646
2869
 
2647
- // 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");
2648
2873
  function parseToolChoiceJson(text, providerOptions) {
2649
2874
  var _a;
2650
2875
  try {
@@ -2688,7 +2913,7 @@ async function handleToolChoice(doGenerate, params) {
2688
2913
  }
2689
2914
  const toolCall = {
2690
2915
  type: "tool-call",
2691
- toolCallId: generateId3(),
2916
+ toolCallId: (0, import_provider_utils.generateId)(),
2692
2917
  toolName: parsed.name || "unknown",
2693
2918
  input: JSON.stringify(parsed.arguments || {})
2694
2919
  };
@@ -2807,80 +3032,79 @@ function fixToolCallWithSchema(part, tools) {
2807
3032
  args = tc.input;
2808
3033
  }
2809
3034
  const schema = (_a = tools.find((t) => t.name === tc.toolName)) == null ? void 0 : _a.inputSchema;
2810
- const coerced = coerceBySchema(args, schema);
3035
+ const coerced = (0, import_rxml4.coerceBySchema)(args, schema);
2811
3036
  return {
2812
3037
  ...part,
2813
3038
  input: JSON.stringify(coerced != null ? coerced : {})
2814
3039
  };
2815
3040
  }
2816
3041
 
2817
- // src/protocols/tool-call-protocol.ts
2818
- function isProtocolFactory(protocol) {
2819
- return typeof protocol === "function";
2820
- }
2821
-
2822
- // src/stream-handler.ts
2823
- import { generateId as generateId4 } from "@ai-sdk/provider-utils";
2824
- function extractToolCallSegments(protocol, fullRawText, tools) {
2825
- const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
2826
- text: fullRawText,
2827
- tools
2828
- }) : [];
2829
- return segments.join("\n\n");
2830
- }
2831
- function serializeToolCalls(parsedToolCalls) {
2832
- const toolCallParts = parsedToolCalls.filter(
2833
- (p) => p.type === "tool-call"
2834
- );
2835
- return JSON.stringify(
2836
- toolCallParts.map((tc) => ({
2837
- toolName: tc.toolName,
2838
- input: tc.input
2839
- }))
2840
- );
2841
- }
2842
- function handleDebugSummary(parsedToolCalls, origin, params) {
2843
- var _a, _b;
2844
- const dbg = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.debugSummary;
2845
- if (dbg) {
2846
- dbg.originalText = origin;
2847
- try {
2848
- dbg.toolCalls = serializeToolCalls(parsedToolCalls);
2849
- } catch (e) {
2850
- }
2851
- } else {
2852
- logParsedSummary({
2853
- toolCalls: parsedToolCalls,
2854
- originalText: origin
2855
- });
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;
2856
3079
  }
2857
3080
  }
2858
- function createDebugSummaryTransform({
2859
- protocol,
2860
- getFullRawText,
2861
- tools,
2862
- params
2863
- }) {
2864
- return new TransformStream({
2865
- transform: /* @__PURE__ */ (() => {
2866
- const parsedToolCalls = [];
2867
- return (part, controller) => {
2868
- if (part.type === "tool-call") {
2869
- parsedToolCalls.push(part);
2870
- }
2871
- if (part.type === "finish") {
2872
- try {
2873
- const raw = getFullRawText();
2874
- logRawChunk(raw);
2875
- const origin = extractToolCallSegments(protocol, raw, tools);
2876
- handleDebugSummary(parsedToolCalls, origin, params);
2877
- } catch (e) {
2878
- }
2879
- }
2880
- 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 || ""
2881
3089
  };
2882
- })()
2883
- });
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
+ }
2884
3108
  }
2885
3109
  async function wrapStream({
2886
3110
  protocol,
@@ -2902,89 +3126,39 @@ async function wrapStream({
2902
3126
  );
2903
3127
  const options = {
2904
3128
  ...extractOnErrorOption(params.providerOptions),
2905
- ...(_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware
3129
+ ...((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) || {}
2906
3130
  };
2907
- if (debugLevel === "off") {
2908
- return {
2909
- stream: stream.pipeThrough(
2910
- protocol.createStreamParser({
2911
- tools,
2912
- options
2913
- })
2914
- ),
2915
- ...rest
2916
- };
2917
- }
2918
- if (debugLevel === "stream") {
2919
- const withRawTap2 = stream.pipeThrough(
2920
- new TransformStream(
2921
- {
2922
- transform(part, controller) {
2923
- logRawChunk(part);
2924
- controller.enqueue(part);
2925
- }
2926
- }
2927
- )
2928
- );
2929
- const parsed2 = withRawTap2.pipeThrough(
2930
- protocol.createStreamParser({
2931
- tools,
2932
- options
2933
- })
2934
- );
2935
- const withParsedTap = parsed2.pipeThrough(
2936
- new TransformStream(
2937
- {
2938
- transform(part, controller) {
2939
- logParsedChunk(part);
2940
- controller.enqueue(part);
2941
- }
2942
- }
2943
- )
2944
- );
2945
- return {
2946
- stream: withParsedTap,
2947
- ...rest
2948
- };
2949
- }
2950
- let fullRawText = "";
2951
- const withRawTap = stream.pipeThrough(
3131
+ const coreStream = stream.pipeThrough(
2952
3132
  new TransformStream({
2953
3133
  transform(part, controller) {
2954
- if (part.type === "text-delta") {
2955
- const delta = part.delta;
2956
- if (typeof delta === "string" && delta.length > 0) {
2957
- fullRawText += delta;
2958
- }
3134
+ if (debugLevel === "stream") {
3135
+ logRawChunk(part);
2959
3136
  }
2960
- controller.enqueue(part);
3137
+ controller.enqueue(mapV3PartToCore(part));
2961
3138
  }
2962
3139
  })
2963
- );
2964
- const parsed = withRawTap.pipeThrough(
2965
- protocol.createStreamParser({
2966
- tools,
2967
- options
2968
- })
2969
- );
2970
- const withSummary = parsed.pipeThrough(
2971
- createDebugSummaryTransform({
2972
- protocol,
2973
- getFullRawText: () => fullRawText,
2974
- tools,
2975
- 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
+ }
2976
3150
  })
2977
3151
  );
2978
3152
  return {
2979
- stream: withSummary,
2980
- ...rest
3153
+ ...rest,
3154
+ stream: v3Stream
2981
3155
  };
2982
3156
  }
2983
3157
  async function toolChoiceStream({
2984
3158
  doGenerate,
2985
3159
  options
2986
3160
  }) {
2987
- var _a, _b, _c;
3161
+ var _a, _b;
2988
3162
  const result = await doGenerate();
2989
3163
  let toolJson = {};
2990
3164
  if ((result == null ? void 0 : result.content) && result.content.length > 0 && ((_a = result.content[0]) == null ? void 0 : _a.type) === "text") {
@@ -3002,62 +3176,33 @@ async function toolChoiceStream({
3002
3176
  toolJson = {};
3003
3177
  }
3004
3178
  }
3005
- const toolCallChunk = {
3006
- type: "tool-call",
3007
- toolCallId: generateId4(),
3008
- toolName: toolJson.name || "unknown",
3009
- input: JSON.stringify(toolJson.arguments || {})
3010
- };
3011
- const finishChunk = {
3012
- type: "finish",
3013
- usage: (result == null ? void 0 : result.usage) || {
3014
- inputTokens: {
3015
- total: 0,
3016
- noCache: void 0,
3017
- cacheRead: void 0,
3018
- cacheWrite: void 0
3019
- },
3020
- outputTokens: {
3021
- total: 0,
3022
- text: void 0,
3023
- reasoning: void 0
3024
- }
3025
- },
3026
- finishReason: { unified: "tool-calls", raw: void 0 }
3027
- };
3028
3179
  const stream = new ReadableStream({
3029
3180
  start(controller) {
3030
- controller.enqueue(toolCallChunk);
3031
- 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
+ });
3032
3195
  controller.close();
3033
3196
  }
3034
3197
  });
3035
- const debugLevel = getDebugLevel();
3036
- const firstText = ((_c = result == null ? void 0 : result.content) == null ? void 0 : _c[0]) && result.content[0].type === "text" && result.content[0].text || "";
3037
- const streamWithSummary = debugLevel === "parse" ? stream.pipeThrough(
3038
- new TransformStream({
3039
- transform(part, controller) {
3040
- if (part.type === "finish") {
3041
- try {
3042
- logParsedSummary({
3043
- toolCalls: [toolCallChunk],
3044
- originalText: typeof firstText === "string" ? firstText : ""
3045
- });
3046
- } catch (e) {
3047
- }
3048
- }
3049
- controller.enqueue(part);
3050
- }
3051
- })
3052
- ) : stream;
3053
3198
  return {
3054
3199
  request: (result == null ? void 0 : result.request) || {},
3055
3200
  response: (result == null ? void 0 : result.response) || {},
3056
- stream: streamWithSummary
3201
+ stream
3057
3202
  };
3058
3203
  }
3059
3204
 
3060
- // src/utils/dynamic-tool-schema.ts
3205
+ // src/core/utils/dynamic-tool-schema.ts
3061
3206
  function createDynamicIfThenElseSchema(tools) {
3062
3207
  let currentSchema = {};
3063
3208
  const toolNames = [];
@@ -3114,7 +3259,13 @@ function createDynamicIfThenElseSchema(tools) {
3114
3259
  };
3115
3260
  }
3116
3261
 
3117
- // 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
3118
3269
  function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
3119
3270
  const systemIndex = processedPrompt.findIndex((m) => m.role === "system");
3120
3271
  if (systemIndex !== -1) {
@@ -3336,7 +3487,14 @@ function processToolMessage(content, resolvedProtocol) {
3336
3487
  content: [
3337
3488
  {
3338
3489
  type: "text",
3339
- 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")
3340
3498
  }
3341
3499
  ]
3342
3500
  };
@@ -3429,7 +3587,7 @@ function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
3429
3587
  return processedPrompt;
3430
3588
  }
3431
3589
 
3432
- // src/tool-call-middleware.ts
3590
+ // src/v6/tool-call-middleware.ts
3433
3591
  function createToolMiddleware({
3434
3592
  protocol,
3435
3593
  toolSystemPromptTemplate,
@@ -3466,19 +3624,14 @@ function createToolMiddleware({
3466
3624
  };
3467
3625
  }
3468
3626
 
3469
- // src/index.ts
3627
+ // src/v6/index.ts
3470
3628
  var gemmaToolMiddleware = createToolMiddleware({
3471
- protocol: jsonMixProtocol(
3472
- // Customize the tool call delimiters to use markdown code fences
3473
- {
3474
- toolCallStart: "```tool_call\n",
3475
- // TODO: Support specifying multiple possible tags,
3476
- // e.g., for gemma, it would be nice to be able to set both `` and ``` at the same time.
3477
- toolCallEnd: "\n```",
3478
- toolResponseStart: "```tool_response\n",
3479
- toolResponseEnd: "\n```"
3480
- }
3481
- ),
3629
+ protocol: jsonMixProtocol({
3630
+ toolCallStart: "```tool_call\n",
3631
+ toolCallEnd: "\n```",
3632
+ toolResponseStart: "```tool_response\n",
3633
+ toolResponseEnd: "\n```"
3634
+ }),
3482
3635
  toolSystemPromptTemplate(tools) {
3483
3636
  return `You have access to functions. If you decide to invoke any of the function(s),
3484
3637
  you MUST put it in the format of markdown code fence block with the language name of tool_call , e.g.
@@ -3506,11 +3659,13 @@ For each function call return a json object with function name and arguments wit
3506
3659
  });
3507
3660
  var morphXmlToolMiddleware = createToolMiddleware({
3508
3661
  protocol: morphXmlProtocol,
3509
- placement: "last",
3662
+ placement: "first",
3510
3663
  toolSystemPromptTemplate(tools) {
3511
- 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.
3512
3667
 
3513
- Available functions are listed inside <tools></tools>.
3668
+ You are provided with function signatures within <tools></tools> XML tags:
3514
3669
  <tools>${tools}</tools>
3515
3670
 
3516
3671
  # Rules
@@ -3520,6 +3675,7 @@ Available functions are listed inside <tools></tools>.
3520
3675
  - Do not add or remove functions or parameters.
3521
3676
  - Each required parameter must appear once.
3522
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.
3523
3679
 
3524
3680
  # Example
3525
3681
  <get_weather>
@@ -3528,42 +3684,17 @@ Available functions are listed inside <tools></tools>.
3528
3684
  </get_weather>`;
3529
3685
  }
3530
3686
  });
3531
-
3532
- export {
3533
- getDebugLevel,
3534
- logParseFailure,
3535
- logRawChunk,
3536
- logParsedChunk,
3537
- logParsedSummary,
3538
- getPotentialStartIndex,
3539
- escapeRegExp,
3540
- transform,
3541
- parse,
3542
- stringify,
3543
- jsonMixProtocol,
3544
- applyHeuristicPipeline,
3545
- createIntermediateCall,
3546
- mergePipelineConfigs,
3547
- normalizeCloseTagsHeuristic,
3548
- escapeInvalidLtHeuristic,
3549
- balanceTagsHeuristic,
3550
- dedupeShellStringTagsHeuristic,
3551
- repairAgainstSchemaHeuristic,
3552
- defaultPipelineConfig,
3553
- isToolCallContent,
3554
- isToolResultPart,
3555
- hasInputProperty,
3556
- morphXmlProtocol,
3557
- extractOnErrorOption,
3558
- originalToolsSchema,
3559
- encodeOriginalTools,
3560
- decodeOriginalTools,
3561
- extractToolNamesFromOriginalTools,
3562
- isToolChoiceActive,
3563
- 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 = {
3564
3694
  createToolMiddleware,
3565
3695
  gemmaToolMiddleware,
3566
3696
  hermesToolMiddleware,
3567
- morphXmlToolMiddleware
3568
- };
3569
- //# sourceMappingURL=chunk-LB5ALTRD.js.map
3697
+ morphXmlToolMiddleware,
3698
+ orchestratorToolMiddleware
3699
+ });
3700
+ //# sourceMappingURL=v6.cjs.map