@ai-sdk-tool/parser 3.2.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/community.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createToolMiddleware,
3
3
  xmlProtocol
4
- } from "./chunk-PIUBQRFC.js";
4
+ } from "./chunk-DCK5APVO.js";
5
5
 
6
6
  // src/community/sijawara.ts
7
7
  var sijawaraDetailedXmlToolMiddleware = createToolMiddleware({
package/dist/index.cjs CHANGED
@@ -578,10 +578,6 @@ function isTCMProtocolFactory(protocol) {
578
578
  var import_rxml = require("@ai-sdk-tool/rxml");
579
579
  var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
580
580
  var WHITESPACE_REGEX = /\s/;
581
- var REGEX_ESCAPE_RE = /[.*+?^${}()|[\]\\]/g;
582
- function escapeRegExp2(value) {
583
- return value.replace(REGEX_ESCAPE_RE, "\\$&");
584
- }
585
581
  function getToolSchema(tools, toolName) {
586
582
  var _a;
587
583
  return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
@@ -746,21 +742,25 @@ function nextTagToken(text, fromPos) {
746
742
  nextPos: open.nextPos
747
743
  };
748
744
  }
749
- function findNextToolTag(text, searchIndex, startTag, selfTag) {
745
+ function findNextToolTag(text, searchIndex, toolName) {
746
+ var _a, _b;
747
+ const startTag = `<${toolName}>`;
750
748
  const openIdx = text.indexOf(startTag, searchIndex);
751
- const selfIdx = text.indexOf(selfTag, searchIndex);
749
+ const selfMatch = findSelfClosingTag(text, toolName, searchIndex);
750
+ const selfIdx = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
752
751
  if (openIdx === -1 && selfIdx === -1) {
753
752
  return null;
754
753
  }
755
754
  const isSelfClosing = selfIdx !== -1 && (openIdx === -1 || selfIdx < openIdx);
756
755
  return {
757
756
  tagStart: isSelfClosing ? selfIdx : openIdx,
758
- isSelfClosing
757
+ isSelfClosing,
758
+ tagLength: isSelfClosing ? (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0 : startTag.length
759
759
  };
760
760
  }
761
761
  function findLastCloseTagStart(segment, toolName) {
762
762
  const closeTagPattern = new RegExp(
763
- `</\\s*${escapeRegExp2(toolName)}\\s*>`,
763
+ `</\\s*${escapeRegExp(toolName)}\\s*>`,
764
764
  "g"
765
765
  );
766
766
  let closeTagStart = -1;
@@ -774,8 +774,8 @@ function findLastCloseTagStart(segment, toolName) {
774
774
  }
775
775
  return closeTagStart;
776
776
  }
777
- function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, selfTag) {
778
- const endIndex = tagStart + selfTag.length;
777
+ function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, tagLength) {
778
+ const endIndex = tagStart + tagLength;
779
779
  toolCalls.push({
780
780
  toolName,
781
781
  startIndex: tagStart,
@@ -785,6 +785,24 @@ function pushSelfClosingToolCall(toolCalls, toolName, text, tagStart, selfTag) {
785
785
  });
786
786
  return endIndex;
787
787
  }
788
+ var selfClosingTagCache = /* @__PURE__ */ new Map();
789
+ function getSelfClosingTagPattern(toolName) {
790
+ let pattern = selfClosingTagCache.get(toolName);
791
+ if (!pattern) {
792
+ pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
793
+ selfClosingTagCache.set(toolName, pattern);
794
+ }
795
+ return pattern;
796
+ }
797
+ function findSelfClosingTag(text, toolName, fromIndex) {
798
+ const pattern = getSelfClosingTagPattern(toolName);
799
+ pattern.lastIndex = fromIndex;
800
+ const match = pattern.exec(text);
801
+ if (!match || match.index === void 0) {
802
+ return null;
803
+ }
804
+ return { index: match.index, length: match[0].length };
805
+ }
788
806
  function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, startTag) {
789
807
  const contentStart = tagStart + startTag.length;
790
808
  const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
@@ -806,10 +824,9 @@ function appendOpenToolCallIfComplete(toolCalls, text, toolName, tagStart, start
806
824
  function findToolCallsForName(text, toolName) {
807
825
  const toolCalls = [];
808
826
  const startTag = `<${toolName}>`;
809
- const selfTag = `<${toolName}/>`;
810
827
  let searchIndex = 0;
811
828
  while (searchIndex < text.length) {
812
- const match = findNextToolTag(text, searchIndex, startTag, selfTag);
829
+ const match = findNextToolTag(text, searchIndex, toolName);
813
830
  if (match === null) {
814
831
  break;
815
832
  }
@@ -819,7 +836,7 @@ function findToolCallsForName(text, toolName) {
819
836
  toolName,
820
837
  text,
821
838
  match.tagStart,
822
- selfTag
839
+ match.tagLength
823
840
  );
824
841
  continue;
825
842
  }
@@ -842,28 +859,114 @@ function findToolCalls(text, toolNames) {
842
859
  return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
843
860
  }
844
861
  function findEarliestToolTag(buffer, toolNames) {
862
+ var _a, _b;
845
863
  let bestIndex = -1;
846
864
  let bestName = "";
847
865
  let bestSelfClosing = false;
866
+ let bestTagLength = 0;
848
867
  if (toolNames.length > 0) {
849
868
  for (const name of toolNames) {
850
869
  const openTag = `<${name}>`;
851
- const selfTag = `<${name}/>`;
852
870
  const idxOpen = buffer.indexOf(openTag);
853
- const idxSelf = buffer.indexOf(selfTag);
871
+ const selfMatch = findSelfClosingTag(buffer, name, 0);
872
+ const idxSelf = (_a = selfMatch == null ? void 0 : selfMatch.index) != null ? _a : -1;
854
873
  if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
855
874
  bestIndex = idxOpen;
856
875
  bestName = name;
857
876
  bestSelfClosing = false;
877
+ bestTagLength = openTag.length;
858
878
  }
859
879
  if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
860
880
  bestIndex = idxSelf;
861
881
  bestName = name;
862
882
  bestSelfClosing = true;
883
+ bestTagLength = (_b = selfMatch == null ? void 0 : selfMatch.length) != null ? _b : 0;
863
884
  }
864
885
  }
865
886
  }
866
- return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
887
+ return {
888
+ index: bestIndex,
889
+ name: bestName,
890
+ selfClosing: bestSelfClosing,
891
+ tagLength: bestTagLength
892
+ };
893
+ }
894
+ function isOpenTagPrefix(suffix, toolName) {
895
+ return `${toolName}>`.startsWith(suffix);
896
+ }
897
+ function consumeWhitespace(text, index) {
898
+ let i = index;
899
+ while (i < text.length && WHITESPACE_REGEX.test(text.charAt(i))) {
900
+ i += 1;
901
+ }
902
+ return i;
903
+ }
904
+ function consumeToolNamePrefix(text, index, toolName) {
905
+ let i = index;
906
+ let nameIndex = 0;
907
+ while (i < text.length && nameIndex < toolName.length) {
908
+ if (text.charAt(i) !== toolName.charAt(nameIndex)) {
909
+ return { index: i, done: false, valid: false };
910
+ }
911
+ i += 1;
912
+ nameIndex += 1;
913
+ }
914
+ return { index: i, done: nameIndex === toolName.length, valid: true };
915
+ }
916
+ function isSelfClosingSuffixRemainder(text, index) {
917
+ if (text.charAt(index) !== "/") {
918
+ return false;
919
+ }
920
+ if (index + 1 >= text.length) {
921
+ return true;
922
+ }
923
+ return index + 1 === text.length - 1 && text.charAt(index + 1) === ">";
924
+ }
925
+ function isSelfClosingTagPrefix(suffix, toolName) {
926
+ let i = consumeWhitespace(suffix, 0);
927
+ if (i >= suffix.length) {
928
+ return true;
929
+ }
930
+ const nameRemainder = suffix.slice(i);
931
+ if (toolName.startsWith(nameRemainder)) {
932
+ return true;
933
+ }
934
+ const nameResult = consumeToolNamePrefix(suffix, i, toolName);
935
+ if (!nameResult.valid) {
936
+ return false;
937
+ }
938
+ i = nameResult.index;
939
+ if (i >= suffix.length) {
940
+ return true;
941
+ }
942
+ if (!nameResult.done) {
943
+ return false;
944
+ }
945
+ i = consumeWhitespace(suffix, i);
946
+ if (i >= suffix.length) {
947
+ return true;
948
+ }
949
+ return isSelfClosingSuffixRemainder(suffix, i);
950
+ }
951
+ function findPotentialToolTagStart(buffer, toolNames) {
952
+ if (toolNames.length === 0 || buffer.length === 0) {
953
+ return -1;
954
+ }
955
+ const lastGt = buffer.lastIndexOf(">");
956
+ const offset = lastGt === -1 ? 0 : lastGt + 1;
957
+ const trailing = buffer.slice(offset);
958
+ for (let i = trailing.length - 1; i >= 0; i -= 1) {
959
+ if (trailing.charAt(i) !== "<") {
960
+ continue;
961
+ }
962
+ const suffix = trailing.slice(i + 1);
963
+ for (const name of toolNames) {
964
+ if (isOpenTagPrefix(suffix, name) || isSelfClosingTagPrefix(suffix, name)) {
965
+ return offset + i;
966
+ }
967
+ }
968
+ }
969
+ return -1;
867
970
  }
868
971
  function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmittedTextStart, setHasEmittedTextStart) {
869
972
  return (controller, text) => {
@@ -909,7 +1012,7 @@ function processToolCallInBuffer(params) {
909
1012
  parseOptions
910
1013
  } = params;
911
1014
  const endTagPattern = new RegExp(
912
- `</\\s*${escapeRegExp2(currentToolCall.name)}\\s*>`
1015
+ `</\\s*${escapeRegExp(currentToolCall.name)}\\s*>`
913
1016
  );
914
1017
  const endMatch = endTagPattern.exec(buffer);
915
1018
  if (!endMatch || endMatch.index === void 0) {
@@ -949,18 +1052,22 @@ function processNoToolCallInBuffer(params) {
949
1052
  const {
950
1053
  index: earliestStartTagIndex,
951
1054
  name: earliestToolName,
952
- selfClosing
1055
+ selfClosing,
1056
+ tagLength
953
1057
  } = findEarliestToolTag(buffer, toolNames);
954
1058
  if (earliestStartTagIndex === -1) {
955
- const maxTagLen = toolNames.length ? Math.max(...toolNames.map((n) => `<${n}>`.length)) : 0;
956
- const tail = Math.max(0, maxTagLen - 1);
957
- const safeLen = Math.max(0, buffer.length - tail);
1059
+ const potentialStart = findPotentialToolTagStart(buffer, toolNames);
1060
+ const safeLen = Math.max(
1061
+ 0,
1062
+ potentialStart === -1 ? buffer.length : potentialStart
1063
+ );
1064
+ const remaining = buffer.slice(safeLen);
958
1065
  if (safeLen > 0) {
959
1066
  flushText(controller, buffer.slice(0, safeLen));
960
- setBuffer(buffer.slice(safeLen));
1067
+ setBuffer(remaining);
961
1068
  }
962
1069
  return {
963
- buffer: buffer.slice(safeLen),
1070
+ buffer: remaining,
964
1071
  currentToolCall: null,
965
1072
  shouldBreak: true,
966
1073
  shouldContinue: false
@@ -968,8 +1075,7 @@ function processNoToolCallInBuffer(params) {
968
1075
  }
969
1076
  flushText(controller, buffer.substring(0, earliestStartTagIndex));
970
1077
  if (selfClosing) {
971
- const selfTag = `<${earliestToolName}/>`;
972
- const newBuffer2 = buffer.substring(earliestStartTagIndex + selfTag.length);
1078
+ const newBuffer2 = buffer.substring(earliestStartTagIndex + tagLength);
973
1079
  setBuffer(newBuffer2);
974
1080
  handleStreamingToolCallEnd({
975
1081
  toolContent: "",
@@ -2030,29 +2136,230 @@ function formatXmlNode(tagName, value, depth) {
2030
2136
  }
2031
2137
 
2032
2138
  // src/core/prompts/xml-system-prompt.ts
2139
+ var import_dedent = __toESM(require("dedent"), 1);
2033
2140
  function xmlSystemPromptTemplate(tools) {
2034
- const toolsJson = JSON.stringify(tools);
2035
- return `# Tools
2036
-
2037
- You may call one or more functions to assist with the user query.
2038
-
2039
- You are provided with function signatures within <tools></tools> XML tags:
2040
- <tools>${toolsJson}</tools>
2041
-
2042
- # Rules
2043
- - Use exactly one XML element whose tag name is the function name.
2044
- - Put each parameter as a child element.
2045
- - Values must follow the schema exactly (numbers, arrays, objects, enums \u2192 copy as-is).
2046
- - Do not add or remove functions or parameters.
2047
- - Each required parameter must appear once.
2048
- - Output nothing before or after the function call.
2049
- - 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.
2050
-
2051
- # Example
2052
- <get_weather>
2053
- <location>New York</location>
2054
- <unit>celsius</unit>
2055
- </get_weather>`;
2141
+ const toolsText = renderToolsForXmlPrompt(tools);
2142
+ const header = import_dedent.default`
2143
+ # Tools
2144
+ You may call one or more functions to assist with the user query.
2145
+ `;
2146
+ const definitions = [
2147
+ "You have access to the following functions:",
2148
+ "<tools>",
2149
+ toolsText,
2150
+ "</tools>"
2151
+ ].join("\n");
2152
+ const rules = import_dedent.default`
2153
+ <rules>
2154
+ - Use exactly one XML element whose tag name is the function name.
2155
+ - Put each parameter as a child element.
2156
+ - Values must follow the schema exactly (numbers, arrays, objects, enums copy as-is).
2157
+ - Do not add or remove functions or parameters.
2158
+ - Each required parameter must appear once.
2159
+ - Output nothing before or after the function call.
2160
+ - It is also possible to call multiple types of functions in one turn or to call a single function multiple times.
2161
+ </rules>
2162
+ `;
2163
+ const examples = import_dedent.default`
2164
+ For each function call, output the function name and parameter in the following format:
2165
+ <example_function_name>
2166
+ <example_parameter_1>value_1</example_parameter_1>
2167
+ <example_parameter_2>This is the value for the second parameter
2168
+ that can span
2169
+ multiple lines</example_parameter_2>
2170
+ </example_function_name>
2171
+ `;
2172
+ return [header, definitions, rules, examples].join("\n\n");
2173
+ }
2174
+ var INDENT = " ";
2175
+ function renderToolsForXmlPrompt(tools) {
2176
+ if (!tools.length) {
2177
+ return "none";
2178
+ }
2179
+ return tools.map(renderToolForXmlPrompt).join("\n\n");
2180
+ }
2181
+ function renderToolForXmlPrompt(tool) {
2182
+ const lines = [`name: ${tool.name}`];
2183
+ if (tool.description) {
2184
+ lines.push(`description: ${tool.description}`);
2185
+ }
2186
+ lines.push("parameters:");
2187
+ const normalizedSchema = normalizeSchema(tool.inputSchema);
2188
+ lines.push(...renderParametersSummary(normalizedSchema, 1));
2189
+ lines.push(`schema: ${stringifySchema(normalizedSchema)}`);
2190
+ return lines.join("\n");
2191
+ }
2192
+ function normalizeSchema(schema) {
2193
+ if (typeof schema === "string") {
2194
+ try {
2195
+ return JSON.parse(schema);
2196
+ } catch (e) {
2197
+ return { type: "string", const: schema };
2198
+ }
2199
+ }
2200
+ return schema;
2201
+ }
2202
+ function renderParametersSummary(schema, indentLevel) {
2203
+ var _a, _b;
2204
+ const indent = INDENT.repeat(indentLevel);
2205
+ if (schema === void 0 || schema === null) {
2206
+ return [`${indent}(none)`];
2207
+ }
2208
+ if (schema === true) {
2209
+ return [`${indent}(any)`];
2210
+ }
2211
+ if (schema === false) {
2212
+ return [`${indent}(no valid parameters)`];
2213
+ }
2214
+ if (typeof schema !== "object") {
2215
+ return [`${indent}- value (${String(schema)})`];
2216
+ }
2217
+ const schemaType = [];
2218
+ if (Array.isArray(schema.type)) {
2219
+ schemaType.push(...schema.type);
2220
+ } else if (schema.type) {
2221
+ schemaType.push(schema.type);
2222
+ }
2223
+ const isObjectLike = schemaType.includes("object") || !!schema.properties;
2224
+ if (isObjectLike) {
2225
+ const properties = (_a = schema.properties) != null ? _a : {};
2226
+ const requiredSet = new Set((_b = schema.required) != null ? _b : []);
2227
+ const propertyNames = Object.keys(properties).sort();
2228
+ if (propertyNames.length === 0) {
2229
+ return [`${indent}(no named parameters)`];
2230
+ }
2231
+ const lines = [];
2232
+ for (const propName of propertyNames) {
2233
+ const propSchema = properties[propName];
2234
+ lines.push(
2235
+ renderPropertySummaryLine({
2236
+ indent,
2237
+ propName,
2238
+ propSchema,
2239
+ required: requiredSet.has(propName)
2240
+ })
2241
+ );
2242
+ }
2243
+ return lines.length ? lines : [`${indent}(no parameters)`];
2244
+ }
2245
+ return [`${indent}- value (${summarizeType(schema)})`];
2246
+ }
2247
+ function renderPropertySummaryLine({
2248
+ indent,
2249
+ propName,
2250
+ propSchema,
2251
+ required
2252
+ }) {
2253
+ const typeLabel = summarizeType(propSchema);
2254
+ const requiredLabel = required ? "required" : "optional";
2255
+ const extras = collectPropertyExtras(propSchema);
2256
+ const extraText = extras.length ? ` - ${extras.join("; ")}` : "";
2257
+ return `${indent}- ${propName} (${typeLabel}, ${requiredLabel})${extraText}`;
2258
+ }
2259
+ function collectPropertyExtras(propSchema) {
2260
+ if (!propSchema || typeof propSchema !== "object") {
2261
+ return [];
2262
+ }
2263
+ const extras = [];
2264
+ if (propSchema.enum) {
2265
+ extras.push(`enum: ${formatEnumForSummary(propSchema.enum)}`);
2266
+ }
2267
+ if (propSchema.default !== void 0) {
2268
+ extras.push(`default: ${formatValue(propSchema.default)}`);
2269
+ }
2270
+ if (propSchema.description) {
2271
+ extras.push(propSchema.description);
2272
+ }
2273
+ return extras;
2274
+ }
2275
+ function summarizeType(schema) {
2276
+ var _a;
2277
+ if (schema === void 0 || schema === null) {
2278
+ return "unknown";
2279
+ }
2280
+ if (schema === true) {
2281
+ return "any";
2282
+ }
2283
+ if (schema === false) {
2284
+ return "never";
2285
+ }
2286
+ if (typeof schema !== "object") {
2287
+ return String(schema);
2288
+ }
2289
+ const schemaType = schema.type;
2290
+ let baseType = "";
2291
+ if (Array.isArray(schemaType) && schemaType.length) {
2292
+ baseType = schemaType.join(" | ");
2293
+ } else if (typeof schemaType === "string") {
2294
+ baseType = schemaType;
2295
+ } else if (schema.enum) {
2296
+ const inferred = Array.from(
2297
+ new Set(schema.enum.map((value) => typeof value))
2298
+ );
2299
+ if (inferred.length === 1) {
2300
+ baseType = (_a = inferred[0]) != null ? _a : "";
2301
+ }
2302
+ } else if (schema.const !== void 0) {
2303
+ baseType = typeof schema.const;
2304
+ }
2305
+ if (!baseType) {
2306
+ baseType = "any";
2307
+ }
2308
+ if (baseType === "array" && schema.items) {
2309
+ const itemType = Array.isArray(schema.items) ? schema.items.map((item) => summarizeType(item)).join(" | ") : summarizeType(schema.items);
2310
+ return `array<${itemType}>`;
2311
+ }
2312
+ if (baseType === "string" && schema.format) {
2313
+ return `string (${schema.format})`;
2314
+ }
2315
+ return baseType;
2316
+ }
2317
+ var ENUM_MAX_INLINE = 6;
2318
+ var ENUM_PREVIEW_LIMIT = 5;
2319
+ function formatEnumForSummary(values) {
2320
+ if (values.length <= ENUM_MAX_INLINE) {
2321
+ return formatValue(values);
2322
+ }
2323
+ const preview = values.slice(0, ENUM_PREVIEW_LIMIT).map((value) => formatValue(value));
2324
+ return `[${preview.join(", ")}, ... (${values.length} total)]`;
2325
+ }
2326
+ function formatValue(value) {
2327
+ if (typeof value === "string") {
2328
+ return JSON.stringify(value);
2329
+ }
2330
+ if (typeof value === "number" || typeof value === "boolean") {
2331
+ return String(value);
2332
+ }
2333
+ if (value === null) {
2334
+ return "null";
2335
+ }
2336
+ if (Array.isArray(value)) {
2337
+ return `[${value.map(formatValue).join(", ")}]`;
2338
+ }
2339
+ return JSON.stringify(value);
2340
+ }
2341
+ function stringifySchema(schema) {
2342
+ if (schema === void 0) {
2343
+ return "null";
2344
+ }
2345
+ return JSON.stringify(stripSchemaKeys(schema));
2346
+ }
2347
+ function stripSchemaKeys(value) {
2348
+ if (Array.isArray(value)) {
2349
+ return value.map((entry) => stripSchemaKeys(entry));
2350
+ }
2351
+ if (value && typeof value === "object") {
2352
+ const record = value;
2353
+ const cleaned = {};
2354
+ for (const [key, entry] of Object.entries(record)) {
2355
+ if (key === "$schema") {
2356
+ continue;
2357
+ }
2358
+ cleaned[key] = stripSchemaKeys(entry);
2359
+ }
2360
+ return cleaned;
2361
+ }
2362
+ return value;
2056
2363
  }
2057
2364
 
2058
2365
  // src/core/prompts/yaml-system-prompt.ts