@ai-sdk-tool/parser 2.1.3 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -20,11 +20,30 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ RJSON: () => robust_json_exports,
24
+ coerceBySchema: () => coerceBySchema,
25
+ coerceToolCallInput: () => coerceToolCallInput,
26
+ createDynamicIfThenElseSchema: () => createDynamicIfThenElseSchema,
23
27
  createToolMiddleware: () => createToolMiddleware,
28
+ escapeRegExp: () => escapeRegExp,
29
+ extractOnErrorOption: () => extractOnErrorOption,
30
+ fixToolCallWithSchema: () => fixToolCallWithSchema,
24
31
  gemmaToolMiddleware: () => gemmaToolMiddleware,
32
+ getDebugLevel: () => getDebugLevel,
33
+ getFunctionTools: () => getFunctionTools,
34
+ getPotentialStartIndex: () => getPotentialStartIndex,
35
+ getSchemaType: () => getSchemaType,
36
+ hasInputProperty: () => hasInputProperty,
25
37
  hermesToolMiddleware: () => hermesToolMiddleware,
38
+ isToolCallContent: () => isToolCallContent,
39
+ isToolChoiceActive: () => isToolChoiceActive,
40
+ isToolResultPart: () => isToolResultPart,
26
41
  jsonMixProtocol: () => jsonMixProtocol,
42
+ logParsedChunk: () => logParsedChunk,
43
+ logParsedSummary: () => logParsedSummary,
44
+ logRawChunk: () => logRawChunk,
27
45
  morphXmlProtocol: () => morphXmlProtocol,
46
+ unwrapJsonSchema: () => unwrapJsonSchema,
28
47
  xmlToolMiddleware: () => xmlToolMiddleware
29
48
  });
30
49
  module.exports = __toCommonJS(index_exports);
@@ -114,9 +133,9 @@ function escapeRegExp(literal) {
114
133
  return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
115
134
  }
116
135
 
117
- // src/utils/relaxed-json.ts
118
- var relaxed_json_exports = {};
119
- __export(relaxed_json_exports, {
136
+ // src/utils/robust-json.ts
137
+ var robust_json_exports = {};
138
+ __export(robust_json_exports, {
120
139
  parse: () => parse,
121
140
  stringify: () => stringify,
122
141
  transform: () => transform
@@ -1038,11 +1057,6 @@ function extractOnErrorOption(providerOptions) {
1038
1057
  return void 0;
1039
1058
  }
1040
1059
 
1041
- // src/utils/protocol.ts
1042
- function isProtocolFactory(protocol) {
1043
- return typeof protocol === "function";
1044
- }
1045
-
1046
1060
  // src/utils/tools.ts
1047
1061
  function isToolChoiceActive(params) {
1048
1062
  var _a, _b, _c;
@@ -1139,7 +1153,7 @@ var jsonMixProtocol = ({
1139
1153
  }
1140
1154
  if (toolCallJson) {
1141
1155
  try {
1142
- const parsedToolCall = relaxed_json_exports.parse(toolCallJson);
1156
+ const parsedToolCall = robust_json_exports.parse(toolCallJson);
1143
1157
  processedElements.push({
1144
1158
  type: "tool-call",
1145
1159
  toolCallId: (0, import_provider_utils2.generateId)(),
@@ -1262,7 +1276,7 @@ var jsonMixProtocol = ({
1262
1276
  isInsideToolCall = true;
1263
1277
  } else {
1264
1278
  try {
1265
- const parsedToolCall = relaxed_json_exports.parse(currentToolCallJson);
1279
+ const parsedToolCall = robust_json_exports.parse(currentToolCallJson);
1266
1280
  if (currentTextId && hasEmittedTextStart) {
1267
1281
  controller.enqueue({ type: "text-end", id: currentTextId });
1268
1282
  currentTextId = null;
@@ -1324,8 +1338,7 @@ var jsonMixProtocol = ({
1324
1338
 
1325
1339
  // src/protocols/morph-xml-protocol.ts
1326
1340
  var import_provider_utils3 = require("@ai-sdk/provider-utils");
1327
- var import_fast_xml_parser = require("fast-xml-parser");
1328
- var WARN_ON_DUPLICATE_STRING_TAGS = true;
1341
+ var import_rxml = require("@ai-sdk-tool/rxml");
1329
1342
  function getToolSchema(tools, originalSchemas, toolName) {
1330
1343
  var _a;
1331
1344
  const original = originalSchemas[toolName];
@@ -1333,598 +1346,42 @@ function getToolSchema(tools, originalSchemas, toolName) {
1333
1346
  const fallback = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
1334
1347
  return fallback;
1335
1348
  }
1336
- function getPropertySchema(toolSchema, key) {
1337
- const unwrapped = unwrapJsonSchema(toolSchema);
1338
- if (!unwrapped || typeof unwrapped !== "object") return void 0;
1339
- const u = unwrapped;
1340
- const props = u.properties;
1341
- if (props && Object.prototype.hasOwnProperty.call(props, key)) {
1342
- return props[key];
1343
- }
1344
- return void 0;
1345
- }
1346
- function extractRawInner(xmlContent, tagName) {
1347
- const isNameStartChar = (ch) => /[A-Za-z_:]/.test(ch);
1348
- const isNameChar = (ch) => /[A-Za-z0-9_.:-]/.test(ch);
1349
- const len = xmlContent.length;
1350
- const target = tagName;
1351
- let bestStart = -1;
1352
- let bestEnd = -1;
1353
- let bestDepth = Number.POSITIVE_INFINITY;
1354
- const skipQuoted = (s, i2) => {
1355
- const quote = s[i2];
1356
- i2++;
1357
- while (i2 < s.length) {
1358
- const ch = s[i2];
1359
- if (ch === "\\") {
1360
- i2 += 2;
1361
- continue;
1362
- }
1363
- if (ch === quote) {
1364
- return i2 + 1;
1365
- }
1366
- i2++;
1367
- }
1368
- return i2;
1369
- };
1370
- let i = 0;
1371
- let depth = 0;
1372
- while (i < len) {
1373
- const lt = xmlContent.indexOf("<", i);
1374
- if (lt === -1) return void 0;
1375
- i = lt + 1;
1376
- if (i >= len) return void 0;
1377
- const ch = xmlContent[i];
1378
- if (ch === "!") {
1379
- if (xmlContent.startsWith("!--", i + 1)) {
1380
- const close = xmlContent.indexOf("-->", i + 4);
1381
- i = close === -1 ? len : close + 3;
1382
- continue;
1383
- }
1384
- if (xmlContent.startsWith("![CDATA[", i + 1)) {
1385
- const close = xmlContent.indexOf("]]>", i + 9);
1386
- i = close === -1 ? len : close + 3;
1387
- continue;
1388
- }
1389
- const gt = xmlContent.indexOf(">", i + 1);
1390
- i = gt === -1 ? len : gt + 1;
1391
- continue;
1392
- } else if (ch === "?") {
1393
- const close = xmlContent.indexOf("?>", i + 1);
1394
- i = close === -1 ? len : close + 2;
1395
- continue;
1396
- } else if (ch === "/") {
1397
- let j = i + 1;
1398
- if (j < len && isNameStartChar(xmlContent[j])) {
1399
- j++;
1400
- while (j < len && isNameChar(xmlContent[j])) j++;
1401
- }
1402
- const gt = xmlContent.indexOf(">", j);
1403
- i = gt === -1 ? len : gt + 1;
1404
- depth = Math.max(0, depth - 1);
1405
- continue;
1406
- } else {
1407
- let j = i;
1408
- if (j < len && isNameStartChar(xmlContent[j])) {
1409
- j++;
1410
- while (j < len && isNameChar(xmlContent[j])) j++;
1411
- }
1412
- const name = xmlContent.slice(i, j);
1413
- let k = j;
1414
- let isSelfClosing = false;
1415
- while (k < len) {
1416
- const c = xmlContent[k];
1417
- if (c === '"' || c === "'") {
1418
- k = skipQuoted(xmlContent, k);
1419
- continue;
1420
- }
1421
- if (c === ">") {
1422
- break;
1423
- }
1424
- if (c === "/" && xmlContent[k + 1] === ">") {
1425
- isSelfClosing = true;
1426
- k++;
1427
- break;
1428
- }
1429
- k++;
1430
- }
1431
- const tagEnd = k;
1432
- if (name === target) {
1433
- const contentStart = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
1434
- if (isSelfClosing) {
1435
- if (depth < bestDepth) {
1436
- bestStart = contentStart;
1437
- bestEnd = contentStart;
1438
- bestDepth = depth;
1439
- if (bestDepth === 0) {
1440
- }
1441
- }
1442
- } else {
1443
- let pos = contentStart;
1444
- let sameDepth = 1;
1445
- while (pos < len) {
1446
- const nextLt = xmlContent.indexOf("<", pos);
1447
- if (nextLt === -1) break;
1448
- const nx = nextLt + 1;
1449
- if (nx >= len) break;
1450
- const h = xmlContent[nx];
1451
- if (h === "!") {
1452
- if (xmlContent.startsWith("!--", nx + 1)) {
1453
- const close = xmlContent.indexOf("-->", nx + 4);
1454
- pos = close === -1 ? len : close + 3;
1455
- continue;
1456
- }
1457
- if (xmlContent.startsWith("![CDATA[", nx + 1)) {
1458
- const close = xmlContent.indexOf("]]>", nx + 9);
1459
- pos = close === -1 ? len : close + 3;
1460
- continue;
1461
- }
1462
- const gt2 = xmlContent.indexOf(">", nx + 1);
1463
- pos = gt2 === -1 ? len : gt2 + 1;
1464
- continue;
1465
- } else if (h === "?") {
1466
- const close = xmlContent.indexOf("?>", nx + 1);
1467
- pos = close === -1 ? len : close + 2;
1468
- continue;
1469
- } else if (h === "/") {
1470
- let t = nx + 1;
1471
- if (t < len && isNameStartChar(xmlContent[t])) {
1472
- t++;
1473
- while (t < len && isNameChar(xmlContent[t])) t++;
1474
- }
1475
- const endName = xmlContent.slice(nx + 1, t);
1476
- const gt2 = xmlContent.indexOf(">", t);
1477
- if (endName === target) {
1478
- sameDepth--;
1479
- if (sameDepth === 0) {
1480
- if (depth < bestDepth) {
1481
- bestStart = contentStart;
1482
- bestEnd = nextLt;
1483
- bestDepth = depth;
1484
- if (bestDepth === 0) {
1485
- }
1486
- }
1487
- break;
1488
- }
1489
- }
1490
- pos = gt2 === -1 ? len : gt2 + 1;
1491
- continue;
1492
- } else {
1493
- let t = nx;
1494
- if (t < len && isNameStartChar(xmlContent[t])) {
1495
- t++;
1496
- while (t < len && isNameChar(xmlContent[t])) t++;
1497
- }
1498
- const startName = xmlContent.slice(nx, t);
1499
- let u = t;
1500
- let selfClose = false;
1501
- while (u < len) {
1502
- const cu = xmlContent[u];
1503
- if (cu === '"' || cu === "'") {
1504
- u = skipQuoted(xmlContent, u);
1505
- continue;
1506
- }
1507
- if (cu === ">") break;
1508
- if (cu === "/" && xmlContent[u + 1] === ">") {
1509
- selfClose = true;
1510
- u++;
1511
- break;
1512
- }
1513
- u++;
1514
- }
1515
- if (startName === target && !selfClose) {
1516
- sameDepth++;
1517
- }
1518
- pos = xmlContent[u] === ">" ? u + 1 : u + 1;
1519
- continue;
1520
- }
1521
- }
1349
+ function findToolCalls(text, toolNames) {
1350
+ const toolCalls = [];
1351
+ for (const toolName of toolNames) {
1352
+ let searchIndex = 0;
1353
+ while (searchIndex < text.length) {
1354
+ const startTag = `<${toolName}>`;
1355
+ const tagStart = text.indexOf(startTag, searchIndex);
1356
+ if (tagStart === -1) break;
1357
+ const remainingText = text.substring(tagStart);
1358
+ const range = (0, import_rxml.findFirstTopLevelRange)(remainingText, toolName);
1359
+ if (range) {
1360
+ const contentStart = tagStart + startTag.length;
1361
+ const contentEnd = contentStart + (range.end - range.start);
1362
+ let fullTagEnd = contentEnd + `</${toolName}>`.length;
1363
+ const closeHead = text.indexOf(`</${toolName}`, contentEnd);
1364
+ if (closeHead === contentEnd) {
1365
+ let p = closeHead + 2 + toolName.length;
1366
+ while (p < text.length && /\s/.test(text[p])) p++;
1367
+ if (text[p] === ">") fullTagEnd = p + 1;
1522
1368
  }
1523
- }
1524
- i = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
1525
- depth += isSelfClosing ? 0 : 1;
1526
- continue;
1527
- }
1528
- }
1529
- if (bestStart !== -1) {
1530
- return xmlContent.slice(bestStart, bestEnd);
1531
- }
1532
- return void 0;
1533
- }
1534
- function findFirstTopLevelRange(xmlContent, tagName) {
1535
- const isNameStartChar = (ch) => /[A-Za-z_:]/.test(ch);
1536
- const isNameChar = (ch) => /[A-Za-z0-9_.:-]/.test(ch);
1537
- const len = xmlContent.length;
1538
- const target = tagName;
1539
- const skipQuoted = (s, i2) => {
1540
- const quote = s[i2];
1541
- i2++;
1542
- while (i2 < s.length) {
1543
- const ch = s[i2];
1544
- if (ch === "\\") {
1545
- i2 += 2;
1546
- continue;
1547
- }
1548
- if (ch === quote) return i2 + 1;
1549
- i2++;
1550
- }
1551
- return i2;
1552
- };
1553
- let i = 0;
1554
- let depth = 0;
1555
- while (i < len) {
1556
- const lt = xmlContent.indexOf("<", i);
1557
- if (lt === -1) return void 0;
1558
- i = lt + 1;
1559
- if (i >= len) return void 0;
1560
- const ch = xmlContent[i];
1561
- if (ch === "!") {
1562
- if (xmlContent.startsWith("!--", i + 1)) {
1563
- const close = xmlContent.indexOf("-->", i + 4);
1564
- i = close === -1 ? len : close + 3;
1565
- continue;
1566
- }
1567
- if (xmlContent.startsWith("![CDATA[", i + 1)) {
1568
- const close = xmlContent.indexOf("]]>", i + 9);
1569
- i = close === -1 ? len : close + 3;
1570
- continue;
1571
- }
1572
- const gt = xmlContent.indexOf(">", i + 1);
1573
- i = gt === -1 ? len : gt + 1;
1574
- continue;
1575
- } else if (ch === "?") {
1576
- const close = xmlContent.indexOf("?>", i + 1);
1577
- i = close === -1 ? len : close + 2;
1578
- continue;
1579
- } else if (ch === "/") {
1580
- const gt = xmlContent.indexOf(">", i + 1);
1581
- i = gt === -1 ? len : gt + 1;
1582
- depth = Math.max(0, depth - 1);
1583
- continue;
1584
- } else {
1585
- let j = i;
1586
- if (j < len && isNameStartChar(xmlContent[j])) {
1587
- j++;
1588
- while (j < len && isNameChar(xmlContent[j])) j++;
1589
- }
1590
- const name = xmlContent.slice(i, j);
1591
- let k = j;
1592
- let isSelfClosing = false;
1593
- while (k < len) {
1594
- const c = xmlContent[k];
1595
- if (c === '"' || c === "'") {
1596
- k = skipQuoted(xmlContent, k);
1597
- continue;
1598
- }
1599
- if (c === ">") break;
1600
- if (c === "/" && xmlContent[k + 1] === ">") {
1601
- isSelfClosing = true;
1602
- k++;
1603
- break;
1604
- }
1605
- k++;
1606
- }
1607
- const tagEnd = k;
1608
- if (depth === 0 && name === target) {
1609
- const contentStart = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
1610
- if (isSelfClosing) return { start: contentStart, end: contentStart };
1611
- let pos = contentStart;
1612
- let sameDepth = 1;
1613
- while (pos < len) {
1614
- const nextLt = xmlContent.indexOf("<", pos);
1615
- if (nextLt === -1) break;
1616
- const nx = nextLt + 1;
1617
- if (nx >= len) break;
1618
- const h = xmlContent[nx];
1619
- if (h === "!") {
1620
- if (xmlContent.startsWith("!--", nx + 1)) {
1621
- const close = xmlContent.indexOf("-->", nx + 4);
1622
- pos = close === -1 ? len : close + 3;
1623
- continue;
1624
- }
1625
- if (xmlContent.startsWith("![CDATA[", nx + 1)) {
1626
- const close = xmlContent.indexOf("]]>", nx + 9);
1627
- pos = close === -1 ? len : close + 3;
1628
- continue;
1629
- }
1630
- const gt2 = xmlContent.indexOf(">", nx + 1);
1631
- pos = gt2 === -1 ? len : gt2 + 1;
1632
- continue;
1633
- } else if (h === "?") {
1634
- const close = xmlContent.indexOf("?>", nx + 1);
1635
- pos = close === -1 ? len : close + 2;
1636
- continue;
1637
- } else if (h === "/") {
1638
- let t = nx + 1;
1639
- if (t < len && isNameStartChar(xmlContent[t])) {
1640
- t++;
1641
- while (t < len && isNameChar(xmlContent[t])) t++;
1642
- }
1643
- const endName = xmlContent.slice(nx + 1, t);
1644
- const gt2 = xmlContent.indexOf(">", t);
1645
- if (endName === target) {
1646
- sameDepth--;
1647
- if (sameDepth === 0) {
1648
- return { start: contentStart, end: nextLt };
1649
- }
1650
- }
1651
- pos = gt2 === -1 ? len : gt2 + 1;
1652
- continue;
1653
- } else {
1654
- let t = nx;
1655
- if (t < len && isNameStartChar(xmlContent[t])) {
1656
- t++;
1657
- while (t < len && isNameChar(xmlContent[t])) t++;
1658
- }
1659
- let u = t;
1660
- let selfClose = false;
1661
- while (u < len) {
1662
- const cu = xmlContent[u];
1663
- if (cu === '"' || cu === "'") {
1664
- u = skipQuoted(xmlContent, u);
1665
- continue;
1666
- }
1667
- if (cu === ">") break;
1668
- if (cu === "/" && xmlContent[u + 1] === ">") {
1669
- selfClose = true;
1670
- u++;
1671
- break;
1672
- }
1673
- u++;
1674
- }
1675
- if (!selfClose) {
1676
- }
1677
- pos = xmlContent[u] === ">" ? u + 1 : u + 1;
1678
- continue;
1679
- }
1680
- }
1681
- return void 0;
1682
- }
1683
- i = xmlContent[tagEnd] === ">" ? tagEnd + 1 : tagEnd + 1;
1684
- depth += isSelfClosing ? 0 : 1;
1685
- continue;
1686
- }
1687
- }
1688
- return void 0;
1689
- }
1690
- function countTagOccurrences(xmlContent, tagName, excludeRanges, skipFirst = true) {
1691
- const isNameStartChar = (ch) => /[A-Za-z_:]/.test(ch);
1692
- const isNameChar = (ch) => /[A-Za-z0-9_.:-]/.test(ch);
1693
- const len = xmlContent.length;
1694
- const target = tagName;
1695
- const skipQuoted = (s, i2) => {
1696
- const quote = s[i2];
1697
- i2++;
1698
- while (i2 < s.length) {
1699
- const ch = s[i2];
1700
- if (ch === "\\") {
1701
- i2 += 2;
1702
- continue;
1703
- }
1704
- if (ch === quote) return i2 + 1;
1705
- i2++;
1706
- }
1707
- return i2;
1708
- };
1709
- let i = 0;
1710
- let count = 0;
1711
- const isExcluded = (pos) => {
1712
- if (!excludeRanges || excludeRanges.length === 0) return false;
1713
- for (const r of excludeRanges) {
1714
- if (pos >= r.start && pos < r.end) return true;
1715
- }
1716
- return false;
1717
- };
1718
- while (i < len) {
1719
- const lt = xmlContent.indexOf("<", i);
1720
- if (lt === -1) break;
1721
- i = lt + 1;
1722
- if (i >= len) break;
1723
- const ch = xmlContent[i];
1724
- if (ch === "!") {
1725
- if (xmlContent.startsWith("!--", i + 1)) {
1726
- const close = xmlContent.indexOf("-->", i + 4);
1727
- i = close === -1 ? len : close + 3;
1728
- continue;
1729
- }
1730
- if (xmlContent.startsWith("![CDATA[", i + 1)) {
1731
- const close = xmlContent.indexOf("]]>", i + 9);
1732
- i = close === -1 ? len : close + 3;
1733
- continue;
1734
- }
1735
- const gt = xmlContent.indexOf(">", i + 1);
1736
- i = gt === -1 ? len : gt + 1;
1737
- continue;
1738
- } else if (ch === "?") {
1739
- const close = xmlContent.indexOf("?>", i + 1);
1740
- i = close === -1 ? len : close + 2;
1741
- continue;
1742
- } else if (ch === "/") {
1743
- const gt = xmlContent.indexOf(">", i + 1);
1744
- i = gt === -1 ? len : gt + 1;
1745
- continue;
1746
- } else {
1747
- let j = i;
1748
- if (j < len && isNameStartChar(xmlContent[j])) {
1749
- j++;
1750
- while (j < len && isNameChar(xmlContent[j])) j++;
1751
- }
1752
- const name = xmlContent.slice(i, j);
1753
- let k = j;
1754
- while (k < len) {
1755
- const c = xmlContent[k];
1756
- if (c === '"' || c === "'") {
1757
- k = skipQuoted(xmlContent, k);
1758
- continue;
1759
- }
1760
- if (c === ">") break;
1761
- if (c === "/" && xmlContent[k + 1] === ">") {
1762
- k++;
1763
- break;
1764
- }
1765
- k++;
1766
- }
1767
- if (name === target && !isExcluded(lt)) {
1768
- if (skipFirst) {
1769
- skipFirst = false;
1770
- } else {
1771
- count++;
1772
- }
1773
- }
1774
- i = k + 1;
1775
- continue;
1776
- }
1777
- }
1778
- return count;
1779
- }
1780
- function processParsedArgs(parsedArgs, toolSchema, toolContent, toolName, options) {
1781
- var _a, _b, _c;
1782
- const args = {};
1783
- let cancelToolCall = false;
1784
- const stringTypedProps = (() => {
1785
- const set = /* @__PURE__ */ new Set();
1786
- const unwrapped = unwrapJsonSchema(toolSchema);
1787
- if (unwrapped && typeof unwrapped === "object") {
1788
- const u = unwrapped;
1789
- const props = u.properties;
1790
- if (props && typeof props === "object") {
1791
- for (const key of Object.keys(props)) {
1792
- const t = getSchemaType(props[key]);
1793
- if (t === "string") set.add(key);
1794
- }
1795
- }
1796
- }
1797
- return set;
1798
- })();
1799
- for (const k of Object.keys(parsedArgs || {})) {
1800
- const v = parsedArgs[k];
1801
- let val = v;
1802
- const propSchema = getPropertySchema(toolSchema, k);
1803
- const propType = getSchemaType(propSchema);
1804
- if (propType === "string" && !Array.isArray(v)) {
1805
- const excludeRanges = [];
1806
- for (const other of stringTypedProps) {
1807
- if (other === k) continue;
1808
- const range = findFirstTopLevelRange(toolContent, other);
1809
- if (range) excludeRanges.push(range);
1810
- }
1811
- const occurrences = countTagOccurrences(
1812
- toolContent,
1813
- k,
1814
- excludeRanges,
1815
- true
1816
- );
1817
- if (occurrences > 0) {
1818
- if (WARN_ON_DUPLICATE_STRING_TAGS) {
1819
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
1820
- options,
1821
- `Duplicate string tags for <${k}> detected; cancelling tool call`,
1822
- {
1823
- toolName,
1824
- toolCall: `<${toolName}>${toolContent}</${toolName}>`
1825
- }
1826
- );
1827
- }
1828
- cancelToolCall = true;
1829
- break;
1830
- }
1831
- const raw = extractRawInner(toolContent, k);
1832
- if (typeof raw === "string") {
1833
- args[k] = raw;
1834
- continue;
1835
- }
1836
- }
1837
- if (v && typeof v === "object" && Object.prototype.hasOwnProperty.call(v, "#text")) {
1838
- val = v == null ? void 0 : v["#text"];
1839
- }
1840
- if (Array.isArray(v)) {
1841
- if (propType === "string") {
1842
- const mapped = v.map((item) => {
1843
- if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
1844
- const textVal = item == null ? void 0 : item["#text"];
1845
- return typeof textVal === "string" ? textVal : String(textVal);
1846
- }
1847
- return typeof item === "string" ? item : String(item);
1848
- });
1849
- if (mapped.length > 1 && WARN_ON_DUPLICATE_STRING_TAGS) {
1850
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
1851
- options,
1852
- `Duplicate string tags for <${k}> detected; cancelling tool call`,
1853
- {
1854
- toolName,
1855
- toolCall: `<${toolName}>${toolContent}</${toolName}>`
1856
- }
1857
- );
1858
- }
1859
- if (mapped.length > 1) {
1860
- cancelToolCall = true;
1861
- break;
1862
- } else {
1863
- args[k] = (_c = mapped[0]) != null ? _c : "";
1864
- continue;
1865
- }
1866
- } else {
1867
- val = v.map((item) => {
1868
- if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
1869
- const textVal = item == null ? void 0 : item["#text"];
1870
- return typeof textVal === "string" ? textVal.trim() : textVal;
1871
- }
1872
- return typeof item === "string" ? item.trim() : item;
1369
+ const toolContent = text.substring(contentStart, contentEnd);
1370
+ const fullSegment = text.substring(tagStart, fullTagEnd);
1371
+ toolCalls.push({
1372
+ toolName,
1373
+ startIndex: tagStart,
1374
+ endIndex: fullTagEnd,
1375
+ content: toolContent,
1376
+ segment: fullSegment
1873
1377
  });
1874
- }
1875
- } else if (v && typeof v === "object" && !Object.prototype.hasOwnProperty.call(v, "#text")) {
1876
- const obj = v;
1877
- const keys = Object.keys(obj);
1878
- if (keys.length === 1 && keys[0] === "item") {
1879
- const itemValue = obj.item;
1880
- if (Array.isArray(itemValue)) {
1881
- val = itemValue.map((item) => {
1882
- let currentVal = item;
1883
- if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
1884
- currentVal = item == null ? void 0 : item["#text"];
1885
- }
1886
- const trimmed = typeof currentVal === "string" ? currentVal.trim() : currentVal;
1887
- if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
1888
- const num = Number(trimmed);
1889
- if (Number.isFinite(num)) return num;
1890
- }
1891
- return trimmed;
1892
- });
1893
- } else {
1894
- const trimmed = typeof itemValue === "string" ? itemValue.trim() : itemValue;
1895
- if (typeof trimmed === "string" && /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(trimmed)) {
1896
- const num = Number(trimmed);
1897
- val = Number.isFinite(num) ? num : trimmed;
1898
- } else {
1899
- val = trimmed;
1900
- }
1901
- }
1378
+ searchIndex = fullTagEnd;
1902
1379
  } else {
1903
- let isIndexedTuple = false;
1904
- if (keys.length > 0 && keys.every((key) => /^\d+$/.test(key))) {
1905
- const indices = keys.map((k2) => parseInt(k2, 10)).sort((a, b) => a - b);
1906
- isIndexedTuple = indices[0] === 0 && indices.every((val2, idx) => val2 === idx);
1907
- }
1908
- if (isIndexedTuple) {
1909
- const sortedKeys = keys.sort(
1910
- (a, b) => parseInt(a, 10) - parseInt(b, 10)
1911
- );
1912
- val = sortedKeys.map((key) => {
1913
- const item = obj[key];
1914
- if (item && typeof item === "object" && Object.prototype.hasOwnProperty.call(item, "#text")) {
1915
- const textVal = item == null ? void 0 : item["#text"];
1916
- return typeof textVal === "string" ? textVal.trim() : textVal;
1917
- }
1918
- return typeof item === "string" ? item.trim() : item;
1919
- });
1920
- } else {
1921
- val = v;
1922
- }
1380
+ searchIndex = tagStart + startTag.length;
1923
1381
  }
1924
1382
  }
1925
- args[k] = typeof val === "string" ? val.trim() : val;
1926
1383
  }
1927
- return { args, cancelToolCall };
1384
+ return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
1928
1385
  }
1929
1386
  var morphXmlProtocol = () => ({
1930
1387
  formatTools({ tools, toolSystemPromptTemplate }) {
@@ -1936,7 +1393,6 @@ var morphXmlProtocol = () => ({
1936
1393
  return toolSystemPromptTemplate(JSON.stringify(toolsForPrompt));
1937
1394
  },
1938
1395
  formatToolCall(toolCall) {
1939
- const builder = new import_fast_xml_parser.XMLBuilder({ format: true, suppressEmptyNode: true });
1940
1396
  let args = {};
1941
1397
  const inputValue = hasInputProperty(toolCall) ? toolCall.input : void 0;
1942
1398
  if (typeof inputValue === "string") {
@@ -1948,85 +1404,63 @@ var morphXmlProtocol = () => ({
1948
1404
  } else {
1949
1405
  args = inputValue;
1950
1406
  }
1951
- const xmlContent = builder.build({
1952
- [toolCall.toolName]: args
1407
+ return (0, import_rxml.stringify)(toolCall.toolName, args, {
1408
+ suppressEmptyNode: false,
1409
+ format: false
1953
1410
  });
1954
- return xmlContent;
1955
1411
  },
1956
1412
  formatToolResponse(toolResult) {
1957
- const builder = new import_fast_xml_parser.XMLBuilder({ format: true });
1958
- const xmlContent = builder.build({
1959
- tool_response: {
1960
- tool_name: toolResult.toolName,
1961
- result: toolResult.output
1962
- }
1413
+ return (0, import_rxml.stringify)("tool_response", {
1414
+ tool_name: toolResult.toolName,
1415
+ result: toolResult.output
1963
1416
  });
1964
- return xmlContent;
1965
1417
  },
1966
1418
  parseGeneratedText({ text, tools, options }) {
1967
- var _a, _b, _c;
1419
+ var _a;
1968
1420
  const originalSchemas = (options == null ? void 0 : options.originalToolSchemas) || {};
1969
1421
  const toolNames = tools.map((t) => t.name).filter((name) => name != null);
1970
1422
  if (toolNames.length === 0) {
1971
1423
  return [{ type: "text", text }];
1972
1424
  }
1973
- const toolNamesPattern = toolNames.map((n) => escapeRegExp(n)).join("|");
1974
- const toolCallRegex = new RegExp(
1975
- String.raw`<(${toolNamesPattern})>([\s\S]*?)<\/\1>`,
1976
- "g"
1977
- );
1978
1425
  const processedElements = [];
1979
1426
  let currentIndex = 0;
1980
- let match;
1981
- while ((match = toolCallRegex.exec(text)) !== null) {
1982
- const startIndex = match.index;
1983
- const toolName = match[1];
1984
- const toolContent = match[2].trim();
1985
- if (startIndex > currentIndex) {
1986
- const textSegment = text.substring(currentIndex, startIndex);
1427
+ const toolCalls = findToolCalls(text, toolNames);
1428
+ for (const toolCall of toolCalls) {
1429
+ if (toolCall.startIndex > currentIndex) {
1430
+ const textSegment = text.substring(currentIndex, toolCall.startIndex);
1987
1431
  if (textSegment.trim()) {
1988
1432
  processedElements.push({ type: "text", text: textSegment });
1989
1433
  }
1990
1434
  }
1991
1435
  try {
1992
- const parser = new import_fast_xml_parser.XMLParser({
1993
- ignoreAttributes: false,
1994
- parseTagValue: false,
1995
- ignoreDeclaration: true,
1996
- textNodeName: "#text"
1997
- });
1998
- const parsedArgs = ((_a = parser.parse(`<root>${toolContent}</root>`)) == null ? void 0 : _a.root) || {};
1999
- const toolSchema = getToolSchema(tools, originalSchemas, toolName);
2000
- const { args, cancelToolCall } = processParsedArgs(
2001
- parsedArgs,
2002
- toolSchema,
2003
- toolContent,
2004
- toolName,
2005
- options
1436
+ const toolSchema = getToolSchema(
1437
+ tools,
1438
+ originalSchemas,
1439
+ toolCall.toolName
2006
1440
  );
2007
- if (cancelToolCall) {
2008
- const originalCallText = match[0];
2009
- (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
2010
- options,
2011
- `Duplicate string tags detected; cancelling tool call`,
2012
- { toolCall: originalCallText, toolName }
2013
- );
2014
- processedElements.push({ type: "text", text: originalCallText });
2015
- } else {
2016
- const coercedArgs = coerceBySchema(args, toolSchema);
2017
- processedElements.push({
2018
- type: "tool-call",
2019
- toolCallId: (0, import_provider_utils3.generateId)(),
2020
- toolName,
2021
- input: JSON.stringify(coercedArgs)
2022
- });
2023
- }
1441
+ const parsed = (0, import_rxml.parse)(toolCall.content, toolSchema, {
1442
+ onError: options == null ? void 0 : options.onError
1443
+ });
1444
+ processedElements.push({
1445
+ type: "tool-call",
1446
+ toolCallId: (0, import_provider_utils3.generateId)(),
1447
+ toolName: toolCall.toolName,
1448
+ input: JSON.stringify(parsed)
1449
+ });
2024
1450
  } catch (error) {
2025
- const message = `Could not process XML tool call, keeping original text: ${match[0]}`;
2026
- (_c = options == null ? void 0 : options.onError) == null ? void 0 : _c.call(options, message, { toolCall: match[0], toolName, error });
2027
- processedElements.push({ type: "text", text: match[0] });
1451
+ const originalCallText = text.substring(
1452
+ toolCall.startIndex,
1453
+ toolCall.endIndex
1454
+ );
1455
+ const message = `Could not process XML tool call, keeping original text: ${originalCallText}`;
1456
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1457
+ toolCall: originalCallText,
1458
+ toolName: toolCall.toolName,
1459
+ error
1460
+ });
1461
+ processedElements.push({ type: "text", text: originalCallText });
2028
1462
  }
2029
- currentIndex = startIndex + match[0].length;
1463
+ currentIndex = toolCall.endIndex;
2030
1464
  }
2031
1465
  if (currentIndex < text.length) {
2032
1466
  const remainingText = text.substring(currentIndex);
@@ -2080,61 +1514,36 @@ var morphXmlProtocol = () => ({
2080
1514
  const toolContent = buffer.substring(0, endTagIndex);
2081
1515
  buffer = buffer.substring(endTagIndex + endTag.length);
2082
1516
  try {
2083
- const parser = new import_fast_xml_parser.XMLParser({
2084
- ignoreAttributes: false,
2085
- parseTagValue: false,
2086
- ignoreDeclaration: true,
2087
- textNodeName: "#text"
2088
- });
2089
- const parsedArgs = ((_a = parser.parse(`<root>${toolContent}</root>`)) == null ? void 0 : _a.root) || {};
2090
1517
  const toolSchema = getToolSchema(
2091
1518
  tools,
2092
1519
  originalSchemas,
2093
1520
  currentToolCall.name
2094
1521
  );
2095
- const { args, cancelToolCall } = processParsedArgs(
2096
- parsedArgs,
2097
- toolSchema,
2098
- toolContent,
2099
- currentToolCall.name,
2100
- options
2101
- );
2102
- if (cancelToolCall) {
2103
- const originalCallText = `<${currentToolCall.name}>${toolContent}</${currentToolCall.name}>`;
2104
- if (options == null ? void 0 : options.onError) {
2105
- options.onError(
2106
- "Duplicate string tags detected; cancelling tool call",
2107
- {
2108
- toolCall: originalCallText,
2109
- toolName: currentToolCall.name
2110
- }
2111
- );
2112
- }
2113
- flushText(controller, originalCallText);
2114
- } else {
2115
- const coercedArgs = coerceBySchema(
2116
- args,
2117
- toolSchema
2118
- );
2119
- flushText(controller);
2120
- controller.enqueue({
2121
- type: "tool-call",
2122
- toolCallId: (0, import_provider_utils3.generateId)(),
2123
- toolName: currentToolCall.name,
2124
- input: JSON.stringify(coercedArgs)
2125
- });
2126
- }
2127
- } catch (e) {
1522
+ const parsed = (0, import_rxml.parse)(toolContent, toolSchema, {
1523
+ onError: options == null ? void 0 : options.onError
1524
+ });
1525
+ flushText(controller);
1526
+ controller.enqueue({
1527
+ type: "tool-call",
1528
+ toolCallId: (0, import_provider_utils3.generateId)(),
1529
+ toolName: currentToolCall.name,
1530
+ input: JSON.stringify(parsed)
1531
+ });
1532
+ } catch (error) {
2128
1533
  const originalCallText = `<${currentToolCall.name}>${toolContent}${endTag}`;
2129
- if (options == null ? void 0 : options.onError) {
2130
- options.onError(
2131
- "Could not process streaming XML tool call; emitting original text.",
2132
- {
2133
- toolCall: originalCallText,
2134
- toolName: currentToolCall.name
2135
- }
2136
- );
1534
+ let message = "Could not process streaming XML tool call; emitting original text.";
1535
+ if (error instanceof import_rxml.RXMLDuplicateStringTagError) {
1536
+ message = `Duplicate string tags detected in streaming tool call '${currentToolCall.name}'; emitting original text.`;
1537
+ } else if (error instanceof import_rxml.RXMLCoercionError) {
1538
+ message = `Failed to coerce arguments for streaming tool call '${currentToolCall.name}'; emitting original text.`;
1539
+ } else if (error instanceof import_rxml.RXMLParseError) {
1540
+ message = `Failed to parse XML for streaming tool call '${currentToolCall.name}'; emitting original text.`;
2137
1541
  }
1542
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, message, {
1543
+ toolCall: originalCallText,
1544
+ toolName: currentToolCall.name,
1545
+ error
1546
+ });
2138
1547
  flushText(controller, originalCallText);
2139
1548
  }
2140
1549
  currentToolCall = null;
@@ -2184,18 +1593,15 @@ var morphXmlProtocol = () => ({
2184
1593
  extractToolCallSegments({ text, tools }) {
2185
1594
  const toolNames = tools.map((t) => t.name).filter(Boolean);
2186
1595
  if (toolNames.length === 0) return [];
2187
- const names = toolNames.map((n) => escapeRegExp(String(n))).join("|");
2188
- if (!names) return [];
2189
- const regex = new RegExp(`<(${names})>[\\s\\S]*?<\\/\\1>`, "g");
2190
- const segments = [];
2191
- let m;
2192
- while ((m = regex.exec(text)) != null) {
2193
- segments.push(m[0]);
2194
- }
2195
- return segments;
1596
+ return findToolCalls(text, toolNames).map((tc) => tc.segment);
2196
1597
  }
2197
1598
  });
2198
1599
 
1600
+ // src/protocols/tool-call-protocol.ts
1601
+ function isProtocolFactory(protocol) {
1602
+ return typeof protocol === "function";
1603
+ }
1604
+
2199
1605
  // src/generate-handler.ts
2200
1606
  var import_provider_utils4 = require("@ai-sdk/provider-utils");
2201
1607
  async function wrapGenerate({
@@ -2811,11 +2217,30 @@ San Fransisco
2811
2217
  });
2812
2218
  // Annotate the CommonJS export names for ESM import in node:
2813
2219
  0 && (module.exports = {
2220
+ RJSON,
2221
+ coerceBySchema,
2222
+ coerceToolCallInput,
2223
+ createDynamicIfThenElseSchema,
2814
2224
  createToolMiddleware,
2225
+ escapeRegExp,
2226
+ extractOnErrorOption,
2227
+ fixToolCallWithSchema,
2815
2228
  gemmaToolMiddleware,
2229
+ getDebugLevel,
2230
+ getFunctionTools,
2231
+ getPotentialStartIndex,
2232
+ getSchemaType,
2233
+ hasInputProperty,
2816
2234
  hermesToolMiddleware,
2235
+ isToolCallContent,
2236
+ isToolChoiceActive,
2237
+ isToolResultPart,
2817
2238
  jsonMixProtocol,
2239
+ logParsedChunk,
2240
+ logParsedSummary,
2241
+ logRawChunk,
2818
2242
  morphXmlProtocol,
2243
+ unwrapJsonSchema,
2819
2244
  xmlToolMiddleware
2820
2245
  });
2821
2246
  //# sourceMappingURL=index.cjs.map