@ai-sdk-tool/parser 4.0.0 → 4.1.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,16 +1,19 @@
1
1
  import {
2
2
  escapeRegExp,
3
+ escapeXmlMinimalAttr,
4
+ escapeXmlMinimalText,
3
5
  parse as parse2,
4
- stringify
5
- } from "./chunk-CXWS24JX.js";
6
+ stringify,
7
+ unescapeXml
8
+ } from "./chunk-MHZC45AC.js";
6
9
  import {
7
10
  parse
8
- } from "./chunk-IX4FJELL.js";
11
+ } from "./chunk-QBZNMO5C.js";
9
12
  import {
10
13
  coerceBySchema,
11
14
  getSchemaType,
12
15
  unwrapJsonSchema
13
- } from "./chunk-2KK5BDZF.js";
16
+ } from "./chunk-GMTE7BY5.js";
14
17
 
15
18
  // src/core/utils/debug.ts
16
19
  var LINE_SPLIT_REGEX = /\r?\n/;
@@ -176,9 +179,19 @@ function getPotentialStartIndex(text, searchedText) {
176
179
  if (directIndex !== -1) {
177
180
  return directIndex;
178
181
  }
179
- for (let i = text.length - 1; i >= 0; i -= 1) {
180
- const suffix = text.substring(i);
181
- if (searchedText.startsWith(suffix)) {
182
+ const textLength = text.length;
183
+ const searchedTextLength = searchedText.length;
184
+ const startAt = Math.max(0, textLength - searchedTextLength + 1);
185
+ for (let i = startAt; i < textLength; i++) {
186
+ let match = true;
187
+ const currentSuffixLength = textLength - i;
188
+ for (let j = 0; j < currentSuffixLength; j++) {
189
+ if (text[i + j] !== searchedText[j]) {
190
+ match = false;
191
+ break;
192
+ }
193
+ }
194
+ if (match) {
182
195
  return i;
183
196
  }
184
197
  }
@@ -247,7 +260,7 @@ function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmitte
247
260
  };
248
261
  }
249
262
 
250
- // src/core/protocols/json-protocol.ts
263
+ // src/core/protocols/hermes-protocol.ts
251
264
  function shouldEmitRawToolCallTextOnError(options) {
252
265
  return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
253
266
  }
@@ -790,7 +803,7 @@ function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
790
803
  state.buffer = "";
791
804
  }
792
805
  }
793
- var jsonProtocol = ({
806
+ var hermesProtocol = ({
794
807
  toolCallStart = "<tool_call>",
795
808
  toolCallEnd = "</tool_call>"
796
809
  } = {}) => ({
@@ -892,14 +905,6 @@ var jsonProtocol = ({
892
905
  }
893
906
  });
894
907
 
895
- // src/core/protocols/protocol-interface.ts
896
- function isProtocolFactory(protocol) {
897
- return typeof protocol === "function";
898
- }
899
- function isTCMProtocolFactory(protocol) {
900
- return typeof protocol === "function";
901
- }
902
-
903
908
  // src/core/utils/regex-constants.ts
904
909
  var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
905
910
  var WHITESPACE_REGEX = /\s/;
@@ -1002,7 +1007,7 @@ ${body}
1002
1007
  </${rootTag}>`;
1003
1008
  }
1004
1009
 
1005
- // src/core/protocols/xml-protocol.ts
1010
+ // src/core/protocols/morph-xml-protocol.ts
1006
1011
  function getToolSchema(tools, toolName) {
1007
1012
  var _a;
1008
1013
  return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
@@ -1978,7 +1983,7 @@ function findToolCallsWithFallbacks(text, toolNames) {
1978
1983
  }
1979
1984
  return { parseText, toolCalls };
1980
1985
  }
1981
- var xmlProtocol = (protocolOptions) => {
1986
+ var morphXmlProtocol = (protocolOptions) => {
1982
1987
  var _a;
1983
1988
  const parseOptions = {
1984
1989
  repair: true,
@@ -2241,196 +2246,2066 @@ var xmlProtocol = (protocolOptions) => {
2241
2246
  };
2242
2247
  };
2243
2248
 
2244
- // src/core/protocols/yaml-protocol.ts
2245
- import YAML from "yaml";
2246
- function shouldEmitRawToolCallTextOnError3(options) {
2247
- return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
2249
+ // src/core/protocols/protocol-interface.ts
2250
+ function isProtocolFactory(protocol) {
2251
+ return typeof protocol === "function";
2248
2252
  }
2249
- var selfClosingTagCache2 = /* @__PURE__ */ new Map();
2250
- function getSelfClosingTagPattern2(toolName) {
2251
- let pattern = selfClosingTagCache2.get(toolName);
2252
- if (!pattern) {
2253
- pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
2254
- selfClosingTagCache2.set(toolName, pattern);
2255
- }
2256
- return pattern;
2253
+ function isTCMProtocolFactory(protocol) {
2254
+ return typeof protocol === "function";
2257
2255
  }
2258
- var LEADING_WHITESPACE_RE = /^(\s*)/;
2259
- var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
2260
- var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
2261
- var BLOCK_SCALAR_KEY_RE = /:\s*[|>][-+0-9]*\s*$/;
2262
- var PLAIN_MAPPING_VALUE_RE = /^[^:[\]{}-][^:]*:\s*(.+)$/;
2263
- var PLAIN_SEQUENCE_VALUE_RE = /^-\s+(.+)$/;
2264
- function normalizeYamlContent(yamlContent) {
2265
- let normalized = yamlContent;
2266
- if (normalized.startsWith("\n")) {
2267
- normalized = normalized.slice(1);
2256
+
2257
+ // src/core/utils/tool-call-coercion.ts
2258
+ function coerceToolCallInput(toolName, input, tools) {
2259
+ var _a;
2260
+ let args = {};
2261
+ if (typeof input === "string") {
2262
+ try {
2263
+ args = JSON.parse(input);
2264
+ } catch (e) {
2265
+ return;
2266
+ }
2267
+ } else if (input && typeof input === "object") {
2268
+ args = input;
2269
+ } else {
2270
+ return;
2268
2271
  }
2269
- const lines = normalized.split("\n");
2270
- const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
2271
- if (nonEmptyLines.length === 0) {
2272
- return { normalized: "", nonEmptyLines };
2272
+ const schema = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
2273
+ const coerced = coerceBySchema(args, schema);
2274
+ return JSON.stringify(coerced != null ? coerced : {});
2275
+ }
2276
+ function coerceToolCallPart(part, tools) {
2277
+ const coercedInput = coerceToolCallInput(part.toolName, part.input, tools);
2278
+ if (coercedInput === void 0) {
2279
+ return part;
2273
2280
  }
2274
- const minIndent = Math.min(
2275
- ...nonEmptyLines.map((line) => {
2276
- const match = line.match(LEADING_WHITESPACE_RE);
2277
- return match ? match[1].length : 0;
2278
- })
2279
- );
2280
- if (minIndent > 0) {
2281
- normalized = lines.map((line) => line.slice(minIndent)).join("\n");
2281
+ return {
2282
+ ...part,
2283
+ input: coercedInput
2284
+ };
2285
+ }
2286
+
2287
+ // src/core/protocols/qwen3coder-protocol.ts
2288
+ function shouldEmitRawToolCallTextOnError3(options) {
2289
+ return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
2290
+ }
2291
+ var TOOL_CALL_OPEN_RE = /<tool_call\b[^>]*>/i;
2292
+ var TOOL_CALL_CLOSE_RE = /<\/tool_call\s*>/i;
2293
+ var TOOL_CALL_CLOSE_TRAILING_RE = /<\/tool_call\s*>\s*$/i;
2294
+ var TOOL_CALL_BLOCK_RE = /<tool_call\b[^>]*>[\s\S]*?<\/tool_call\s*>/gi;
2295
+ var LEADING_CALL_CLOSE_TAG_RE = /^\s*<\s*\/\s*(?:tool_call|function|call|tool|invoke)\s*>/i;
2296
+ var CALL_BLOCK_RE = /<(call|function|tool|invoke)\b[^>]*>[\s\S]*?<\/\1\s*>/gi;
2297
+ var QWEN3CODER_TOOL_PARSER_PARAM_TAG_NAMES = /* @__PURE__ */ new Set([
2298
+ "parameter",
2299
+ "param",
2300
+ "argument",
2301
+ "arg"
2302
+ ]);
2303
+ var QWEN3CODER_TOOL_PARSER_CALL_TAG_NAMES = /* @__PURE__ */ new Set([
2304
+ "function",
2305
+ "call",
2306
+ "tool",
2307
+ "invoke",
2308
+ "tool_call"
2309
+ ]);
2310
+ var CALL_SHORTHAND_VALUE_RE = /^<\s*(call|function|tool|invoke)\b\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>/]+))/i;
2311
+ var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_START_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b/i;
2312
+ var QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE = /<\s*(?!\/)\s*(call|function|tool|invoke)\b[^>]*>/i;
2313
+ var QWEN3CODER_TOOL_PARSER_STREAM_TOOL_CALL_CLOSE_TAG_RE = /<\s*\/\s*tool_call\s*>/i;
2314
+ var QWEN3CODER_TOOL_PARSER_STREAM_NAME_OR_PARAM_SIGNAL_RE = /<\s*(?!\/)\s*(name|tool_name|parameter|param|argument|arg)\b/i;
2315
+ var QWEN3CODER_TOOL_PARSER_STREAM_NAME_TAG_RE = /<\s*(name|tool_name)\b[^>]*>([\s\S]*?)<\s*\/\s*\1\s*>/i;
2316
+ var QWEN3CODER_TOOL_PARSER_STREAM_SELF_CLOSING_TAG_RE = /\/\s*>$/;
2317
+ function isAsciiWhitespace(ch) {
2318
+ return ch === " " || ch === "\n" || ch === "\r" || ch === " " || ch === "\f";
2319
+ }
2320
+ function skipAsciiWhitespace(text, index) {
2321
+ var _a;
2322
+ let i = index;
2323
+ while (i < text.length && isAsciiWhitespace((_a = text[i]) != null ? _a : "")) {
2324
+ i += 1;
2282
2325
  }
2283
- return { normalized, nonEmptyLines };
2326
+ return i;
2284
2327
  }
2285
- function parseYamlDocumentAsMapping(normalized) {
2286
- try {
2287
- const doc = YAML.parseDocument(normalized);
2288
- const errors = doc.errors.map((e) => e.message);
2289
- const result = doc.toJSON();
2290
- if (result === null) {
2291
- return { value: {}, errors };
2328
+ function stripLeadingToolCallCloseTags(text) {
2329
+ let out = text;
2330
+ while (true) {
2331
+ const start = skipAsciiWhitespace(out, 0);
2332
+ const trimmed = out.slice(start);
2333
+ const match = TOOL_CALL_CLOSE_RE.exec(trimmed);
2334
+ if (!match || match.index !== 0 || !match[0]) {
2335
+ return out;
2292
2336
  }
2293
- if (typeof result !== "object" || Array.isArray(result)) {
2294
- return { value: null, errors };
2337
+ out = out.slice(start + match[0].length);
2338
+ }
2339
+ }
2340
+ function stripTrailingToolCallCloseTags(text) {
2341
+ let out = text;
2342
+ while (true) {
2343
+ const next = out.replace(TOOL_CALL_CLOSE_TRAILING_RE, "");
2344
+ if (next === out) {
2345
+ return out;
2295
2346
  }
2296
- return { value: result, errors };
2297
- } catch (error) {
2298
- return {
2299
- value: null,
2300
- errors: [
2301
- error instanceof Error ? error.message : "Unknown YAML parsing error"
2302
- ]
2303
- };
2347
+ out = next;
2304
2348
  }
2305
2349
  }
2306
- function getLastMeaningfulLineInfo(input) {
2350
+ function isTagBoundaryChar(ch) {
2351
+ return ch === "" || isAsciiWhitespace(ch) || ch === ">" || ch === "/";
2352
+ }
2353
+ function findTagEndIndex(text, startIndex) {
2307
2354
  var _a;
2308
- const lines = input.split("\n");
2309
- let index = lines.length - 1;
2310
- while (index >= 0) {
2311
- const raw = (_a = lines[index]) != null ? _a : "";
2312
- const trimmed = raw.trim();
2313
- if (trimmed.length > 0 && !trimmed.startsWith("#")) {
2314
- return {
2315
- index,
2316
- raw,
2317
- trimmed,
2318
- indent: raw.length - raw.trimStart().length
2319
- };
2355
+ let quote = null;
2356
+ for (let i = startIndex; i < text.length; i += 1) {
2357
+ const ch = (_a = text[i]) != null ? _a : "";
2358
+ if (quote) {
2359
+ if (ch === quote) {
2360
+ quote = null;
2361
+ }
2362
+ continue;
2363
+ }
2364
+ if (ch === '"' || ch === "'") {
2365
+ quote = ch;
2366
+ continue;
2367
+ }
2368
+ if (ch === ">") {
2369
+ return i;
2320
2370
  }
2321
- index -= 1;
2322
2371
  }
2323
2372
  return null;
2324
2373
  }
2325
- function dropLastMeaningfulLine(input) {
2326
- const lineInfo = getLastMeaningfulLineInfo(input);
2327
- if (!lineInfo) {
2374
+ function parseShorthandValue(openTag, tagNameLower) {
2375
+ var _a, _b;
2376
+ let i = 1;
2377
+ i = skipAsciiWhitespace(openTag, i);
2378
+ if (!openTag.toLowerCase().startsWith(tagNameLower, i)) {
2328
2379
  return null;
2329
2380
  }
2330
- return input.split("\n").slice(0, lineInfo.index).join("\n").trimEnd();
2381
+ i += tagNameLower.length;
2382
+ i = skipAsciiWhitespace(openTag, i);
2383
+ if (openTag[i] !== "=") {
2384
+ return null;
2385
+ }
2386
+ i += 1;
2387
+ i = skipAsciiWhitespace(openTag, i);
2388
+ const quote = (_a = openTag[i]) != null ? _a : "";
2389
+ if (quote === '"' || quote === "'") {
2390
+ const end = openTag.indexOf(quote, i + 1);
2391
+ if (end === -1) {
2392
+ return null;
2393
+ }
2394
+ return openTag.slice(i + 1, end);
2395
+ }
2396
+ const start = i;
2397
+ while (i < openTag.length) {
2398
+ const ch = (_b = openTag[i]) != null ? _b : "";
2399
+ if (isAsciiWhitespace(ch) || ch === ">" || ch === "/") {
2400
+ break;
2401
+ }
2402
+ i += 1;
2403
+ }
2404
+ const value = openTag.slice(start, i);
2405
+ return value.length > 0 ? value : null;
2331
2406
  }
2332
- function hasIncompleteMappingTail(normalized) {
2333
- const lineInfo = getLastMeaningfulLineInfo(normalized);
2334
- if (!lineInfo) {
2335
- return false;
2407
+ function parseQwen3CoderToolParserParamName(openTag, tagNameLower) {
2408
+ const shorthand = parseShorthandValue(openTag, tagNameLower);
2409
+ if (shorthand != null) {
2410
+ return unescapeXml(shorthand);
2336
2411
  }
2337
- return INCOMPLETE_MAPPING_TAIL_RE.test(lineInfo.trimmed);
2412
+ return getAttributeValue(openTag, "name");
2338
2413
  }
2339
- function hasIncompleteSequenceTail(normalized) {
2340
- const lineInfo = getLastMeaningfulLineInfo(normalized);
2341
- if (!lineInfo) {
2342
- return false;
2414
+ function getCdataSectionNextIndex(textLower, startIndex) {
2415
+ if (!textLower.startsWith("<![cdata[", startIndex)) {
2416
+ return startIndex;
2343
2417
  }
2344
- return INCOMPLETE_SEQUENCE_TAIL_RE.test(lineInfo.trimmed);
2418
+ const cdataEnd = textLower.indexOf("]]>", startIndex + "<![cdata[".length);
2419
+ if (cdataEnd === -1) {
2420
+ return null;
2421
+ }
2422
+ return cdataEnd + 3;
2345
2423
  }
2346
- function hasSplitNestedKeyTail(normalized) {
2424
+ function parseMatchingTagHeader(textLower, lt, tagNameLower) {
2347
2425
  var _a;
2348
- const lineInfo = getLastMeaningfulLineInfo(normalized);
2349
- if (!lineInfo) {
2350
- return false;
2426
+ let i = skipAsciiWhitespace(textLower, lt + 1);
2427
+ const isClosing = textLower[i] === "/";
2428
+ if (isClosing) {
2429
+ i += 1;
2430
+ i = skipAsciiWhitespace(textLower, i);
2351
2431
  }
2352
- const { trimmed, indent, index } = lineInfo;
2353
- if (indent === 0) {
2354
- return false;
2432
+ if (!textLower.startsWith(tagNameLower, i)) {
2433
+ return null;
2355
2434
  }
2356
- if (trimmed.startsWith("#") || trimmed.startsWith("-") || trimmed.includes(":")) {
2357
- return false;
2435
+ const afterName = i + tagNameLower.length;
2436
+ const boundary = (_a = textLower[afterName]) != null ? _a : "";
2437
+ const validBoundary = isClosing ? isTagBoundaryChar(boundary) : isTagBoundaryChar(boundary) || boundary === "=";
2438
+ if (boundary && !validBoundary) {
2439
+ return null;
2358
2440
  }
2359
- const lines = normalized.split("\n");
2360
- let parentIndex = index - 1;
2361
- while (parentIndex >= 0) {
2362
- const parentRaw = (_a = lines[parentIndex]) != null ? _a : "";
2363
- const parentTrimmed = parentRaw.trim();
2364
- if (parentTrimmed.length === 0 || parentTrimmed.startsWith("#")) {
2365
- parentIndex -= 1;
2441
+ return { isClosing, afterName };
2442
+ }
2443
+ function isSelfClosingXmlTag(textLower, lt, gt) {
2444
+ return textLower.slice(lt, gt + 1).trimEnd().endsWith("/>");
2445
+ }
2446
+ function findClosingTagEnd(textLower, startIndex, tagNameLower) {
2447
+ let depth = 1;
2448
+ let index = startIndex;
2449
+ while (true) {
2450
+ const lt = textLower.indexOf("<", index);
2451
+ if (lt === -1) {
2452
+ return null;
2453
+ }
2454
+ const cdataNextIndex = getCdataSectionNextIndex(textLower, lt);
2455
+ if (cdataNextIndex == null) {
2456
+ return null;
2457
+ }
2458
+ if (cdataNextIndex !== lt) {
2459
+ index = cdataNextIndex;
2366
2460
  continue;
2367
2461
  }
2368
- const parentIndent = parentRaw.length - parentRaw.trimStart().length;
2369
- if (parentIndent >= indent) {
2370
- parentIndex -= 1;
2462
+ const header = parseMatchingTagHeader(textLower, lt, tagNameLower);
2463
+ if (!header) {
2464
+ index = lt + 1;
2371
2465
  continue;
2372
2466
  }
2373
- if (!parentTrimmed.endsWith(":")) {
2374
- return false;
2467
+ const gt = textLower.indexOf(">", header.afterName);
2468
+ if (gt === -1) {
2469
+ return null;
2375
2470
  }
2376
- if (BLOCK_SCALAR_KEY_RE.test(parentTrimmed)) {
2377
- return false;
2471
+ if (header.isClosing) {
2472
+ depth -= 1;
2473
+ if (depth === 0) {
2474
+ return { start: lt, end: gt + 1 };
2475
+ }
2476
+ index = gt + 1;
2477
+ continue;
2378
2478
  }
2379
- return true;
2479
+ const isSelfClosing = isSelfClosingXmlTag(textLower, lt, gt);
2480
+ if (!isSelfClosing) {
2481
+ depth += 1;
2482
+ }
2483
+ index = gt + 1;
2380
2484
  }
2381
- return false;
2382
2485
  }
2383
- function extractTrailingPlainScalarValue(line) {
2486
+ function findClosingTagStartWithBoundary(lowerText, valueStart, tagNameLower, allowEndOfStringBoundary) {
2384
2487
  var _a;
2385
- if (BLOCK_SCALAR_KEY_RE.test(line)) {
2386
- return null;
2488
+ const needle = `</${tagNameLower}`;
2489
+ let searchIndex = valueStart;
2490
+ while (searchIndex < lowerText.length) {
2491
+ const found = lowerText.indexOf(needle, searchIndex);
2492
+ if (found === -1) {
2493
+ return -1;
2494
+ }
2495
+ const nextChar = (_a = lowerText[found + needle.length]) != null ? _a : "";
2496
+ if (nextChar === "" && !allowEndOfStringBoundary) {
2497
+ searchIndex = found + needle.length;
2498
+ continue;
2499
+ }
2500
+ if (isTagBoundaryChar(nextChar)) {
2501
+ return found;
2502
+ }
2503
+ searchIndex = found + needle.length;
2387
2504
  }
2388
- const mappingMatch = line.match(PLAIN_MAPPING_VALUE_RE);
2389
- const sequenceMatch = line.match(PLAIN_SEQUENCE_VALUE_RE);
2390
- const value = (_a = mappingMatch == null ? void 0 : mappingMatch[1]) != null ? _a : sequenceMatch == null ? void 0 : sequenceMatch[1];
2391
- if (!value) {
2505
+ return -1;
2506
+ }
2507
+ function toSupportedCallEndTagName(tagNameLower) {
2508
+ var _a;
2509
+ const normalized = (_a = tagNameLower == null ? void 0 : tagNameLower.trim().toLowerCase()) != null ? _a : "";
2510
+ if (!normalized) {
2392
2511
  return null;
2393
2512
  }
2394
- const trimmedValue = value.trim();
2395
- if (trimmedValue.length === 0) {
2513
+ return QWEN3CODER_TOOL_PARSER_CALL_TAG_NAMES.has(normalized) ? normalized : null;
2514
+ }
2515
+ function findUnclosedParamBoundaryIndex(lowerText, valueStart, callEndTagNameLower, allowEndOfString) {
2516
+ const normalizedCallEndTag = toSupportedCallEndTagName(callEndTagNameLower);
2517
+ const callCloseIndex = normalizedCallEndTag ? findClosingTagStartWithBoundary(
2518
+ lowerText,
2519
+ valueStart,
2520
+ normalizedCallEndTag,
2521
+ allowEndOfString
2522
+ ) : findClosingTagStartWithBoundary(
2523
+ lowerText,
2524
+ valueStart,
2525
+ "function",
2526
+ allowEndOfString
2527
+ );
2528
+ const indices = [
2529
+ lowerText.indexOf("<parameter", valueStart),
2530
+ lowerText.indexOf("<param", valueStart),
2531
+ lowerText.indexOf("<argument", valueStart),
2532
+ lowerText.indexOf("<arg", valueStart),
2533
+ callCloseIndex,
2534
+ findClosingTagStartWithBoundary(
2535
+ lowerText,
2536
+ valueStart,
2537
+ "tool_call",
2538
+ allowEndOfString
2539
+ ),
2540
+ lowerText.indexOf("<function", valueStart)
2541
+ ].filter((index) => index !== -1);
2542
+ if (indices.length === 0) {
2396
2543
  return null;
2397
2544
  }
2398
- if (trimmedValue.startsWith('"') || trimmedValue.startsWith("'")) {
2399
- return null;
2545
+ return Math.min(...indices);
2546
+ }
2547
+ function parseQwen3CoderToolParserParamTagNameLower(lowerText, startIndex) {
2548
+ var _a;
2549
+ let i = skipAsciiWhitespace(lowerText, startIndex + 1);
2550
+ if (i >= lowerText.length) {
2551
+ return { kind: "partial" };
2400
2552
  }
2401
- if (trimmedValue.startsWith("{") || trimmedValue.startsWith("[") || trimmedValue.startsWith("|") || trimmedValue.startsWith(">")) {
2553
+ if (lowerText[i] === "/") {
2402
2554
  return null;
2403
2555
  }
2404
- return trimmedValue;
2405
- }
2406
- function hasUnterminatedPlainScalarTail(normalized) {
2407
- if (normalized.endsWith("\n")) {
2408
- return false;
2556
+ const nameStart = i;
2557
+ while (i < lowerText.length) {
2558
+ const ch = (_a = lowerText[i]) != null ? _a : "";
2559
+ if (isAsciiWhitespace(ch) || ch === ">" || ch === "/" || ch === "=") {
2560
+ break;
2561
+ }
2562
+ i += 1;
2409
2563
  }
2410
- const lineInfo = getLastMeaningfulLineInfo(normalized);
2411
- if (!lineInfo) {
2412
- return false;
2564
+ const tagNameLower = lowerText.slice(nameStart, i);
2565
+ if (!QWEN3CODER_TOOL_PARSER_PARAM_TAG_NAMES.has(tagNameLower)) {
2566
+ return null;
2413
2567
  }
2414
- return extractTrailingPlainScalarValue(lineInfo.trimmed) != null;
2415
- }
2416
- function hasUnstableProgressTail(normalized) {
2417
- return hasIncompleteMappingTail(normalized) || hasIncompleteSequenceTail(normalized) || hasSplitNestedKeyTail(normalized) || hasUnterminatedPlainScalarTail(normalized);
2568
+ return { kind: "match", tagNameLower };
2418
2569
  }
2419
- function trimTrailingNewlineInUnknown(value) {
2420
- if (typeof value === "string") {
2421
- if (value.endsWith("\n")) {
2422
- return value.slice(0, -1);
2570
+ function parseQwen3CoderToolParserUnclosedParamValue(options) {
2571
+ var _a;
2572
+ const valueStart = options.openEnd + 1;
2573
+ const boundaryIndex = findUnclosedParamBoundaryIndex(
2574
+ options.lowerText,
2575
+ valueStart,
2576
+ (_a = options.callEndTagNameLower) != null ? _a : null,
2577
+ options.allowEndOfString
2578
+ );
2579
+ if (boundaryIndex == null) {
2580
+ if (!options.allowEndOfString) {
2581
+ return {
2582
+ kind: "partial",
2583
+ start: options.startIndex,
2584
+ openEnd: options.openEnd
2585
+ };
2423
2586
  }
2424
- return value;
2587
+ const rawValue2 = options.text.slice(valueStart);
2588
+ return {
2589
+ kind: "match",
2590
+ start: options.startIndex,
2591
+ end: options.text.length,
2592
+ name: options.paramName,
2593
+ value: rawValue2 ? normalizeXmlTextValue(rawValue2) : ""
2594
+ };
2425
2595
  }
2426
- if (Array.isArray(value)) {
2427
- return value.map((item) => trimTrailingNewlineInUnknown(item));
2596
+ const rawValue = options.text.slice(valueStart, boundaryIndex);
2597
+ return {
2598
+ kind: "match",
2599
+ start: options.startIndex,
2600
+ end: boundaryIndex,
2601
+ name: options.paramName,
2602
+ value: rawValue ? normalizeXmlTextValue(rawValue) : ""
2603
+ };
2604
+ }
2605
+ function parseQwen3CoderToolParserParamTagAt(text, lowerText, startIndex, options) {
2606
+ var _a;
2607
+ const tagNameParse = parseQwen3CoderToolParserParamTagNameLower(
2608
+ lowerText,
2609
+ startIndex
2610
+ );
2611
+ if (!tagNameParse) {
2612
+ return null;
2428
2613
  }
2429
- if (value && typeof value === "object") {
2430
- return Object.fromEntries(
2431
- Object.entries(value).map(([key, item]) => [
2432
- key,
2433
- trimTrailingNewlineInUnknown(item)
2614
+ if (tagNameParse.kind === "partial") {
2615
+ return { kind: "partial", start: startIndex, openEnd: null };
2616
+ }
2617
+ const tagNameLower = tagNameParse.tagNameLower;
2618
+ const openEnd = findTagEndIndex(text, startIndex);
2619
+ if (openEnd == null) {
2620
+ return { kind: "partial", start: startIndex, openEnd: null };
2621
+ }
2622
+ const openTag = text.slice(startIndex, openEnd + 1);
2623
+ const paramNameRaw = parseQwen3CoderToolParserParamName(
2624
+ openTag,
2625
+ tagNameLower
2626
+ );
2627
+ const paramName = (_a = paramNameRaw == null ? void 0 : paramNameRaw.trim()) != null ? _a : "";
2628
+ if (paramName.length === 0) {
2629
+ return null;
2630
+ }
2631
+ const selfClosing = openTag.trimEnd().endsWith("/>");
2632
+ if (selfClosing) {
2633
+ return {
2634
+ kind: "match",
2635
+ start: startIndex,
2636
+ end: openEnd + 1,
2637
+ name: paramName,
2638
+ value: ""
2639
+ };
2640
+ }
2641
+ const valueStart = openEnd + 1;
2642
+ const close = findClosingTagEnd(lowerText, valueStart, tagNameLower);
2643
+ if (!close) {
2644
+ return parseQwen3CoderToolParserUnclosedParamValue({
2645
+ text,
2646
+ lowerText,
2647
+ startIndex,
2648
+ openEnd,
2649
+ paramName,
2650
+ allowEndOfString: (options == null ? void 0 : options.allowEndOfString) === true,
2651
+ callEndTagNameLower: options == null ? void 0 : options.callEndTagNameLower
2652
+ });
2653
+ }
2654
+ const rawValue = text.slice(openEnd + 1, close.start);
2655
+ return {
2656
+ kind: "match",
2657
+ start: startIndex,
2658
+ end: close.end,
2659
+ name: paramName,
2660
+ value: rawValue ? normalizeXmlTextValue(rawValue) : ""
2661
+ };
2662
+ }
2663
+ function normalizeXmlTextValue(raw) {
2664
+ let out = raw.trim();
2665
+ if (out.startsWith("<![CDATA[") && out.endsWith("]]>")) {
2666
+ out = out.slice("<![CDATA[".length, -"]]>".length).trim();
2667
+ }
2668
+ return unescapeXml(out);
2669
+ }
2670
+ function getOpeningTag(xml) {
2671
+ const gt = xml.indexOf(">");
2672
+ if (gt === -1) {
2673
+ return null;
2674
+ }
2675
+ return xml.slice(0, gt + 1);
2676
+ }
2677
+ var attrValueRegExpCache = /* @__PURE__ */ new Map();
2678
+ function getAttributeValue(openTag, attrName) {
2679
+ var _a;
2680
+ let re = attrValueRegExpCache.get(attrName);
2681
+ if (!re) {
2682
+ re = new RegExp(
2683
+ `\\b${escapeRegExp(attrName)}\\s*=\\s*(["'])([\\s\\S]*?)\\1`,
2684
+ "i"
2685
+ );
2686
+ attrValueRegExpCache.set(attrName, re);
2687
+ }
2688
+ const match = re.exec(openTag);
2689
+ if (!match) {
2690
+ return null;
2691
+ }
2692
+ return unescapeXml((_a = match[2]) != null ? _a : "");
2693
+ }
2694
+ function getShorthandValue(openTag) {
2695
+ var _a, _b;
2696
+ const match = CALL_SHORTHAND_VALUE_RE.exec(openTag);
2697
+ if (!match) {
2698
+ return null;
2699
+ }
2700
+ const value = (_b = (_a = match[2]) != null ? _a : match[3]) != null ? _b : match[4];
2701
+ if (!value) {
2702
+ return null;
2703
+ }
2704
+ return unescapeXml(value);
2705
+ }
2706
+ function extractFirstTagText(xml, tagName) {
2707
+ var _a;
2708
+ const lower = xml.toLowerCase();
2709
+ const tagLower = tagName.toLowerCase();
2710
+ let index = 0;
2711
+ while (true) {
2712
+ const lt = lower.indexOf("<", index);
2713
+ if (lt === -1) {
2714
+ return null;
2715
+ }
2716
+ const i = skipAsciiWhitespace(lower, lt + 1);
2717
+ if (i >= lower.length || lower[i] === "/") {
2718
+ index = lt + 1;
2719
+ continue;
2720
+ }
2721
+ if (!lower.startsWith(tagLower, i)) {
2722
+ index = lt + 1;
2723
+ continue;
2724
+ }
2725
+ const afterName = i + tagLower.length;
2726
+ const boundary = (_a = lower[afterName]) != null ? _a : "";
2727
+ if (boundary && !isTagBoundaryChar(boundary)) {
2728
+ index = lt + 1;
2729
+ continue;
2730
+ }
2731
+ const openEnd = findTagEndIndex(xml, lt);
2732
+ if (openEnd == null) {
2733
+ return null;
2734
+ }
2735
+ const contentStart = openEnd + 1;
2736
+ const close = findClosingTagEnd(lower, contentStart, tagLower);
2737
+ if (!close) {
2738
+ return null;
2739
+ }
2740
+ return normalizeXmlTextValue(xml.slice(contentStart, close.start));
2741
+ }
2742
+ }
2743
+ function extractToolCallInnerXml(segment) {
2744
+ const openMatch = TOOL_CALL_OPEN_RE.exec(segment);
2745
+ const closeMatch = TOOL_CALL_CLOSE_RE.exec(segment);
2746
+ if (!(openMatch && closeMatch)) {
2747
+ return null;
2748
+ }
2749
+ const openIndex = openMatch.index;
2750
+ const openTag = openMatch[0];
2751
+ const openEnd = openIndex + openTag.length;
2752
+ const closeIndex = segment.toLowerCase().lastIndexOf("</tool_call");
2753
+ if (closeIndex === -1) {
2754
+ return null;
2755
+ }
2756
+ const closeGt = segment.indexOf(">", closeIndex);
2757
+ if (closeGt === -1) {
2758
+ return null;
2759
+ }
2760
+ return {
2761
+ outerOpenTag: openTag,
2762
+ inner: segment.slice(openEnd, closeIndex)
2763
+ };
2764
+ }
2765
+ function mergeParamValue(args, key, value) {
2766
+ const existing = args[key];
2767
+ if (existing === void 0) {
2768
+ args[key] = value;
2769
+ return;
2770
+ }
2771
+ if (Array.isArray(existing)) {
2772
+ existing.push(value);
2773
+ return;
2774
+ }
2775
+ args[key] = [existing, value];
2776
+ }
2777
+ function extractParameters(xml, options) {
2778
+ var _a;
2779
+ const args = {};
2780
+ const lower = xml.toLowerCase();
2781
+ let index = 0;
2782
+ while (true) {
2783
+ const lt = lower.indexOf("<", index);
2784
+ if (lt === -1) {
2785
+ break;
2786
+ }
2787
+ const parsed = parseQwen3CoderToolParserParamTagAt(xml, lower, lt, {
2788
+ allowEndOfString: true,
2789
+ callEndTagNameLower: options == null ? void 0 : options.callEndTagNameLower
2790
+ });
2791
+ if (!parsed) {
2792
+ index = lt + 1;
2793
+ continue;
2794
+ }
2795
+ if (parsed.kind === "match") {
2796
+ mergeParamValue(args, parsed.name, parsed.value);
2797
+ index = parsed.end;
2798
+ continue;
2799
+ }
2800
+ index = ((_a = parsed.openEnd) != null ? _a : lt) + 1;
2801
+ }
2802
+ return args;
2803
+ }
2804
+ function parseSingleFunctionCallXml(xml, fallbackToolName) {
2805
+ var _a, _b, _c;
2806
+ const openingTag = getOpeningTag(xml);
2807
+ const toolNameAttr = openingTag ? getAttributeValue(openingTag, "name") : null;
2808
+ const shorthandName = openingTag ? getShorthandValue(openingTag) : null;
2809
+ const toolName = (_c = (_b = (_a = toolNameAttr != null ? toolNameAttr : shorthandName) != null ? _a : extractFirstTagText(xml, "name")) != null ? _b : extractFirstTagText(xml, "tool_name")) != null ? _c : fallbackToolName;
2810
+ const callEndTagNameLower = toSupportedCallEndTagName(
2811
+ openingTag ? getOpenTagNameLower(openingTag) : null
2812
+ );
2813
+ if (!toolName || toolName.trim().length === 0) {
2814
+ return null;
2815
+ }
2816
+ return {
2817
+ toolName,
2818
+ args: extractParameters(xml, { callEndTagNameLower })
2819
+ };
2820
+ }
2821
+ function findImplicitCallOpenIndices(lowerText) {
2822
+ var _a;
2823
+ const indices = [];
2824
+ let index = 0;
2825
+ while (true) {
2826
+ const lt = lowerText.indexOf("<", index);
2827
+ if (lt === -1) {
2828
+ break;
2829
+ }
2830
+ const i = skipAsciiWhitespace(lowerText, lt + 1);
2831
+ if (i >= lowerText.length) {
2832
+ break;
2833
+ }
2834
+ if (lowerText[i] === "/") {
2835
+ index = lt + 1;
2836
+ continue;
2837
+ }
2838
+ const tagNames = ["call", "function", "tool", "invoke"];
2839
+ for (const tagName of tagNames) {
2840
+ if (!lowerText.startsWith(tagName, i)) {
2841
+ continue;
2842
+ }
2843
+ const after = i + tagName.length;
2844
+ const boundary = (_a = lowerText[after]) != null ? _a : "";
2845
+ if (boundary && !isTagBoundaryChar(boundary) && boundary !== "=") {
2846
+ continue;
2847
+ }
2848
+ indices.push(lt);
2849
+ break;
2850
+ }
2851
+ index = lt + 1;
2852
+ }
2853
+ return indices;
2854
+ }
2855
+ function splitImplicitCallBlocks(xml) {
2856
+ var _a, _b;
2857
+ const lower = xml.toLowerCase();
2858
+ const starts = findImplicitCallOpenIndices(lower);
2859
+ if (starts.length === 0) {
2860
+ return [];
2861
+ }
2862
+ const blocks = [];
2863
+ for (let i = 0; i < starts.length; i += 1) {
2864
+ const start = (_a = starts[i]) != null ? _a : 0;
2865
+ const end = (_b = starts[i + 1]) != null ? _b : xml.length;
2866
+ blocks.push(xml.slice(start, end));
2867
+ }
2868
+ return blocks;
2869
+ }
2870
+ function stripLeadingCallCloseTags(text) {
2871
+ let out = text;
2872
+ while (true) {
2873
+ const match = LEADING_CALL_CLOSE_TAG_RE.exec(out);
2874
+ if (!match) {
2875
+ return out;
2876
+ }
2877
+ out = out.slice(match[0].length);
2878
+ }
2879
+ }
2880
+ function getOpenTagNameLower(openTag) {
2881
+ var _a;
2882
+ const lowerOpenTag = openTag.toLowerCase();
2883
+ const lt = lowerOpenTag.indexOf("<");
2884
+ if (lt === -1) {
2885
+ return null;
2886
+ }
2887
+ let i = skipAsciiWhitespace(lowerOpenTag, lt + 1);
2888
+ if (i >= lowerOpenTag.length || lowerOpenTag[i] === "/") {
2889
+ return null;
2890
+ }
2891
+ const start = i;
2892
+ while (i < lowerOpenTag.length) {
2893
+ const ch = (_a = lowerOpenTag[i]) != null ? _a : "";
2894
+ if (isAsciiWhitespace(ch) || ch === ">" || ch === "/" || ch === "=") {
2895
+ break;
2896
+ }
2897
+ i += 1;
2898
+ }
2899
+ const tagName = lowerOpenTag.slice(start, i);
2900
+ return tagName.length > 0 ? tagName : null;
2901
+ }
2902
+ function splitImplicitCallAndTail(callBlock) {
2903
+ var _a;
2904
+ const openingTag = getOpeningTag(callBlock);
2905
+ const openingTagName = toSupportedCallEndTagName(
2906
+ openingTag ? getOpenTagNameLower(openingTag) : null
2907
+ );
2908
+ const lowerCallBlock = callBlock.toLowerCase();
2909
+ let consumed = 0;
2910
+ if (openingTag) {
2911
+ consumed = openingTag.length;
2912
+ if (openingTagName) {
2913
+ const close = findClosingTagEnd(lowerCallBlock, consumed, openingTagName);
2914
+ if (close) {
2915
+ consumed = Math.max(consumed, close.end);
2916
+ }
2917
+ }
2918
+ }
2919
+ let index = 0;
2920
+ while (true) {
2921
+ const lt = lowerCallBlock.indexOf("<", index);
2922
+ if (lt === -1) {
2923
+ break;
2924
+ }
2925
+ const parsed = parseQwen3CoderToolParserParamTagAt(
2926
+ callBlock,
2927
+ lowerCallBlock,
2928
+ lt,
2929
+ {
2930
+ allowEndOfString: true,
2931
+ callEndTagNameLower: openingTagName
2932
+ }
2933
+ );
2934
+ if (!parsed) {
2935
+ index = lt + 1;
2936
+ continue;
2937
+ }
2938
+ if (parsed.kind === "partial") {
2939
+ index = ((_a = parsed.openEnd) != null ? _a : lt) + 1;
2940
+ continue;
2941
+ }
2942
+ consumed = Math.max(consumed, parsed.end);
2943
+ index = parsed.end;
2944
+ }
2945
+ const clamped = Math.max(0, Math.min(consumed, callBlock.length));
2946
+ return {
2947
+ callContent: callBlock.slice(0, clamped),
2948
+ trailingText: callBlock.slice(clamped)
2949
+ };
2950
+ }
2951
+ function parseQwen3CoderToolParserCallBlocks(blocks, outerNameAttr) {
2952
+ const calls = [];
2953
+ for (const block of blocks) {
2954
+ const parsed = parseSingleFunctionCallXml(block, outerNameAttr);
2955
+ if (!parsed) {
2956
+ return null;
2957
+ }
2958
+ calls.push(parsed);
2959
+ }
2960
+ return calls;
2961
+ }
2962
+ function parseQwen3CoderToolParserClosedMatches(inner, outerNameAttr) {
2963
+ var _a, _b;
2964
+ const callBlockMatches = Array.from(inner.matchAll(CALL_BLOCK_RE));
2965
+ if (callBlockMatches.length === 0) {
2966
+ return void 0;
2967
+ }
2968
+ const closedBlocks = [];
2969
+ let lastClosedEnd = 0;
2970
+ for (const match of callBlockMatches) {
2971
+ const callBlock = (_a = match[0]) != null ? _a : "";
2972
+ const startIndex = (_b = match.index) != null ? _b : -1;
2973
+ if (!callBlock || startIndex < 0) {
2974
+ continue;
2975
+ }
2976
+ closedBlocks.push(callBlock);
2977
+ lastClosedEnd = startIndex + callBlock.length;
2978
+ }
2979
+ const closedCalls = parseQwen3CoderToolParserCallBlocks(
2980
+ closedBlocks,
2981
+ outerNameAttr
2982
+ );
2983
+ if (!closedCalls) {
2984
+ return null;
2985
+ }
2986
+ const trailingInner = inner.slice(lastClosedEnd);
2987
+ if (trailingInner.trim().length === 0) {
2988
+ return closedCalls;
2989
+ }
2990
+ const trailingBlocks = splitImplicitCallBlocks(trailingInner).filter(
2991
+ (b) => b.trim().length > 0
2992
+ );
2993
+ if (trailingBlocks.length === 0) {
2994
+ return closedCalls;
2995
+ }
2996
+ const trailingCalls = parseQwen3CoderToolParserCallBlocks(
2997
+ trailingBlocks,
2998
+ outerNameAttr
2999
+ );
3000
+ if (!trailingCalls) {
3001
+ return closedCalls;
3002
+ }
3003
+ return closedCalls.concat(trailingCalls);
3004
+ }
3005
+ function parseQwen3CoderToolParserToolCallSegment(segment) {
3006
+ var _a;
3007
+ const extracted = extractToolCallInnerXml(segment);
3008
+ if (!extracted) {
3009
+ return null;
3010
+ }
3011
+ const { inner, outerOpenTag } = extracted;
3012
+ const outerNameAttr = getAttributeValue(outerOpenTag, "name");
3013
+ const closedCalls = parseQwen3CoderToolParserClosedMatches(
3014
+ inner,
3015
+ outerNameAttr
3016
+ );
3017
+ if (closedCalls) {
3018
+ return closedCalls;
3019
+ }
3020
+ if (closedCalls === null) {
3021
+ return null;
3022
+ }
3023
+ const implicitBlocks = splitImplicitCallBlocks(inner).filter(
3024
+ (b) => b.trim().length > 0
3025
+ );
3026
+ if (implicitBlocks.length > 0) {
3027
+ return parseQwen3CoderToolParserCallBlocks(implicitBlocks, outerNameAttr);
3028
+ }
3029
+ const single = (_a = parseSingleFunctionCallXml(inner, outerNameAttr)) != null ? _a : parseSingleFunctionCallXml(segment, outerNameAttr);
3030
+ if (!single) {
3031
+ return null;
3032
+ }
3033
+ return [single];
3034
+ }
3035
+ function parseToolCallInput(input) {
3036
+ if (input == null) {
3037
+ return {};
3038
+ }
3039
+ try {
3040
+ return JSON.parse(input);
3041
+ } catch (e) {
3042
+ return input;
3043
+ }
3044
+ }
3045
+ function stringifyToolInputWithSchema(options) {
3046
+ const coerced = coerceToolCallInput(
3047
+ options.toolName,
3048
+ options.args,
3049
+ options.tools
3050
+ );
3051
+ return coerced != null ? coerced : JSON.stringify(options.args);
3052
+ }
3053
+ function toQwen3CoderToolParserParamText(value) {
3054
+ if (typeof value === "string") {
3055
+ return value;
3056
+ }
3057
+ if (value === null) {
3058
+ return "None";
3059
+ }
3060
+ if (typeof value === "boolean") {
3061
+ return value ? "True" : "False";
3062
+ }
3063
+ if (value === void 0) {
3064
+ return "";
3065
+ }
3066
+ if (typeof value === "object") {
3067
+ return JSON.stringify(value);
3068
+ }
3069
+ return String(value);
3070
+ }
3071
+ function appendQwen3CoderToolParserParameter(lines, key, value) {
3072
+ const nameAttr = escapeXmlMinimalAttr(key, '"');
3073
+ const text = escapeXmlMinimalText(toQwen3CoderToolParserParamText(value));
3074
+ lines.push(` <parameter="${nameAttr}">${text}</parameter>`);
3075
+ }
3076
+ function appendQwen3CoderToolParserArgs(lines, args) {
3077
+ if (args && typeof args === "object" && !Array.isArray(args)) {
3078
+ for (const [key, value] of Object.entries(args)) {
3079
+ if (Array.isArray(value)) {
3080
+ for (const item of value) {
3081
+ appendQwen3CoderToolParserParameter(lines, key, item);
3082
+ }
3083
+ } else {
3084
+ appendQwen3CoderToolParserParameter(lines, key, value);
3085
+ }
3086
+ }
3087
+ return;
3088
+ }
3089
+ if (args !== void 0 && args !== null && args !== "") {
3090
+ appendQwen3CoderToolParserParameter(lines, "input", args);
3091
+ }
3092
+ }
3093
+ var qwen3CoderProtocol = () => ({
3094
+ formatTools({ tools, toolSystemPromptTemplate }) {
3095
+ return toolSystemPromptTemplate(tools || []);
3096
+ },
3097
+ formatToolCall(toolCall) {
3098
+ const args = parseToolCallInput(toolCall.input);
3099
+ const lines = ["<tool_call>"];
3100
+ lines.push(
3101
+ ` <function="${escapeXmlMinimalAttr(toolCall.toolName, '"')}">`
3102
+ );
3103
+ appendQwen3CoderToolParserArgs(lines, args);
3104
+ lines.push(" </function>");
3105
+ lines.push("</tool_call>");
3106
+ return lines.join("\n");
3107
+ },
3108
+ parseGeneratedText({ text, tools, options }) {
3109
+ const processedElements = [];
3110
+ const emitToolCalls = (calls) => {
3111
+ for (const call of calls) {
3112
+ processedElements.push({
3113
+ type: "tool-call",
3114
+ toolCallId: generateToolCallId(),
3115
+ toolName: call.toolName,
3116
+ input: stringifyToolInputWithSchema({
3117
+ tools,
3118
+ toolName: call.toolName,
3119
+ args: call.args
3120
+ })
3121
+ });
3122
+ }
3123
+ };
3124
+ const pushText = (value) => {
3125
+ if (value.length === 0) {
3126
+ return;
3127
+ }
3128
+ processedElements.push({ type: "text", text: value });
3129
+ };
3130
+ const tryEmitToolCallSegment = (segment, fallbackText = segment) => {
3131
+ var _a;
3132
+ const parsedCalls = parseQwen3CoderToolParserToolCallSegment(segment);
3133
+ if (!parsedCalls) {
3134
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3135
+ options,
3136
+ "Could not process Qwen3CoderToolParser XML tool call; keeping original text.",
3137
+ { toolCall: fallbackText }
3138
+ );
3139
+ processedElements.push({ type: "text", text: fallbackText });
3140
+ return false;
3141
+ }
3142
+ emitToolCalls(parsedCalls);
3143
+ return true;
3144
+ };
3145
+ const emitWrapperlessCallParseFailureAsText = (raw) => {
3146
+ var _a;
3147
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3148
+ options,
3149
+ "Could not process Qwen3CoderToolParser <function> call; keeping original text.",
3150
+ { toolCall: raw }
3151
+ );
3152
+ processedElements.push({ type: "text", text: raw });
3153
+ };
3154
+ const tryParseCallBlocksWithoutWrapperByImplicitStarts = (sourceText, starts) => {
3155
+ var _a, _b;
3156
+ let index = 0;
3157
+ for (let i = 0; i < starts.length; i += 1) {
3158
+ const startIndex = (_a = starts[i]) != null ? _a : -1;
3159
+ if (startIndex < 0) {
3160
+ continue;
3161
+ }
3162
+ const endIndex = (_b = starts[i + 1]) != null ? _b : sourceText.length;
3163
+ pushText(
3164
+ stripTrailingToolCallCloseTags(
3165
+ stripLeadingToolCallCloseTags(sourceText.slice(index, startIndex))
3166
+ )
3167
+ );
3168
+ const full = sourceText.slice(startIndex, endIndex);
3169
+ const { callContent, trailingText } = splitImplicitCallAndTail(full);
3170
+ const parsed = parseSingleFunctionCallXml(callContent, null);
3171
+ if (parsed) {
3172
+ emitToolCalls([parsed]);
3173
+ pushText(
3174
+ stripTrailingToolCallCloseTags(
3175
+ stripLeadingToolCallCloseTags(trailingText)
3176
+ )
3177
+ );
3178
+ } else {
3179
+ emitWrapperlessCallParseFailureAsText(full);
3180
+ }
3181
+ index = endIndex;
3182
+ }
3183
+ pushText(
3184
+ stripTrailingToolCallCloseTags(
3185
+ stripLeadingToolCallCloseTags(sourceText.slice(index))
3186
+ )
3187
+ );
3188
+ return true;
3189
+ };
3190
+ const tryParseCallBlocksWithoutWrapperByMatches = (sourceText, matches) => {
3191
+ var _a;
3192
+ let index = 0;
3193
+ for (const match of matches) {
3194
+ const full = match[0];
3195
+ const startIndex = (_a = match.index) != null ? _a : -1;
3196
+ if (!full || startIndex < 0) {
3197
+ continue;
3198
+ }
3199
+ pushText(
3200
+ stripTrailingToolCallCloseTags(
3201
+ stripLeadingToolCallCloseTags(sourceText.slice(index, startIndex))
3202
+ )
3203
+ );
3204
+ const parsed = parseSingleFunctionCallXml(full, null);
3205
+ if (parsed) {
3206
+ emitToolCalls([parsed]);
3207
+ } else {
3208
+ emitWrapperlessCallParseFailureAsText(full);
3209
+ }
3210
+ index = startIndex + full.length;
3211
+ }
3212
+ const trailing = sourceText.slice(index);
3213
+ const trailingStarts = findImplicitCallOpenIndices(
3214
+ trailing.toLowerCase()
3215
+ );
3216
+ if (trailingStarts.length > 0) {
3217
+ return tryParseCallBlocksWithoutWrapperByImplicitStarts(
3218
+ trailing,
3219
+ trailingStarts
3220
+ );
3221
+ }
3222
+ pushText(
3223
+ stripTrailingToolCallCloseTags(stripLeadingToolCallCloseTags(trailing))
3224
+ );
3225
+ return true;
3226
+ };
3227
+ const tryParseCallBlocksWithoutWrapperText = (sourceText) => {
3228
+ const matches = Array.from(sourceText.matchAll(CALL_BLOCK_RE));
3229
+ if (matches.length > 0) {
3230
+ return tryParseCallBlocksWithoutWrapperByMatches(sourceText, matches);
3231
+ }
3232
+ const starts = findImplicitCallOpenIndices(sourceText.toLowerCase());
3233
+ if (starts.length === 0) {
3234
+ return false;
3235
+ }
3236
+ return tryParseCallBlocksWithoutWrapperByImplicitStarts(
3237
+ sourceText,
3238
+ starts
3239
+ );
3240
+ };
3241
+ const pushTextOrParseWrapperlessCalls = (segment) => {
3242
+ if (segment.length === 0) {
3243
+ return;
3244
+ }
3245
+ if (!tryParseCallBlocksWithoutWrapperText(segment)) {
3246
+ pushText(segment);
3247
+ }
3248
+ };
3249
+ const handleCompleteToolCallRemainder = (remainder) => {
3250
+ if (!remainder) {
3251
+ return;
3252
+ }
3253
+ const lowerRemainder = remainder.toLowerCase();
3254
+ const trailingIndex = lowerRemainder.indexOf("<tool_call");
3255
+ if (trailingIndex === -1) {
3256
+ pushTextOrParseWrapperlessCalls(remainder);
3257
+ return;
3258
+ }
3259
+ pushTextOrParseWrapperlessCalls(remainder.slice(0, trailingIndex));
3260
+ const trailing = remainder.slice(trailingIndex);
3261
+ const synthetic = TOOL_CALL_CLOSE_RE.test(trailing) ? trailing : `${trailing}</tool_call>`;
3262
+ tryEmitToolCallSegment(synthetic, trailing);
3263
+ };
3264
+ const tryParseCompleteToolCallBlocks = () => {
3265
+ var _a;
3266
+ const matches = Array.from(text.matchAll(TOOL_CALL_BLOCK_RE));
3267
+ if (matches.length === 0) {
3268
+ return false;
3269
+ }
3270
+ let index = 0;
3271
+ for (const match of matches) {
3272
+ const full = match[0];
3273
+ const startIndex = (_a = match.index) != null ? _a : -1;
3274
+ if (!full || startIndex < 0) {
3275
+ continue;
3276
+ }
3277
+ pushTextOrParseWrapperlessCalls(text.slice(index, startIndex));
3278
+ tryEmitToolCallSegment(full);
3279
+ index = startIndex + full.length;
3280
+ }
3281
+ handleCompleteToolCallRemainder(text.slice(index));
3282
+ return true;
3283
+ };
3284
+ const tryParseIncompleteToolCall = () => {
3285
+ const lowerText = text.toLowerCase();
3286
+ const startIndex = lowerText.indexOf("<tool_call");
3287
+ if (startIndex === -1) {
3288
+ return false;
3289
+ }
3290
+ pushTextOrParseWrapperlessCalls(text.slice(0, startIndex));
3291
+ const trailing = text.slice(startIndex);
3292
+ const synthetic = TOOL_CALL_CLOSE_RE.test(trailing) ? trailing : `${trailing}</tool_call>`;
3293
+ tryEmitToolCallSegment(synthetic, trailing);
3294
+ return true;
3295
+ };
3296
+ const tryParseCallBlocksWithoutWrapper = () => {
3297
+ return tryParseCallBlocksWithoutWrapperText(text);
3298
+ };
3299
+ const tryParseSingleFunctionCall = () => {
3300
+ const lowerText = text.toLowerCase();
3301
+ const startIndex = lowerText.indexOf("<function");
3302
+ if (startIndex === -1) {
3303
+ return false;
3304
+ }
3305
+ pushText(stripTrailingToolCallCloseTags(text.slice(0, startIndex)));
3306
+ const trailing = stripLeadingToolCallCloseTags(text.slice(startIndex));
3307
+ const parsed = parseSingleFunctionCallXml(trailing, null);
3308
+ if (!parsed) {
3309
+ processedElements.push({ type: "text", text: trailing });
3310
+ return true;
3311
+ }
3312
+ emitToolCalls([parsed]);
3313
+ return true;
3314
+ };
3315
+ if (tryParseCompleteToolCallBlocks()) {
3316
+ return processedElements;
3317
+ }
3318
+ if (tryParseIncompleteToolCall()) {
3319
+ return processedElements;
3320
+ }
3321
+ if (tryParseCallBlocksWithoutWrapper()) {
3322
+ return processedElements;
3323
+ }
3324
+ if (tryParseSingleFunctionCall()) {
3325
+ return processedElements;
3326
+ }
3327
+ return [{ type: "text", text }];
3328
+ },
3329
+ extractToolCallSegments({ text }) {
3330
+ return Array.from(text.matchAll(TOOL_CALL_BLOCK_RE)).map((m) => m[0]).filter((s) => Boolean(s));
3331
+ },
3332
+ createStreamParser({ tools, options }) {
3333
+ const toolCallStartPrefixLower = "<tool_call";
3334
+ const implicitCallPrefixesLower = [
3335
+ "<function",
3336
+ "<call",
3337
+ "<tool",
3338
+ "<invoke"
3339
+ ];
3340
+ let buffer = "";
3341
+ let toolCall = null;
3342
+ let implicitCall = null;
3343
+ let implicitCallOpenTag = null;
3344
+ let currentTextId = null;
3345
+ let hasEmittedTextStart = false;
3346
+ const flushText = createFlushTextHandler(
3347
+ () => currentTextId,
3348
+ (id) => {
3349
+ currentTextId = id;
3350
+ },
3351
+ () => hasEmittedTextStart,
3352
+ (value) => {
3353
+ hasEmittedTextStart = value;
3354
+ }
3355
+ );
3356
+ const removeSlice = (text, start, end) => text.slice(0, start) + text.slice(end);
3357
+ const maybeEmitToolInputStart = (controller, callState) => {
3358
+ if (callState.hasEmittedStart) {
3359
+ return;
3360
+ }
3361
+ const toolName = callState.toolName;
3362
+ if (!toolName || toolName.trim().length === 0) {
3363
+ return;
3364
+ }
3365
+ flushText(controller);
3366
+ controller.enqueue({
3367
+ type: "tool-input-start",
3368
+ id: callState.toolCallId,
3369
+ toolName
3370
+ });
3371
+ callState.hasEmittedStart = true;
3372
+ };
3373
+ const maybeEmitToolInputProgress = (controller, callState) => {
3374
+ if (!callState.hasEmittedStart) {
3375
+ return;
3376
+ }
3377
+ const toolName = callState.toolName;
3378
+ if (!toolName) {
3379
+ return;
3380
+ }
3381
+ const fullInput = stringifyToolInputWithSchema({
3382
+ tools,
3383
+ toolName,
3384
+ args: callState.args
3385
+ });
3386
+ if (fullInput === "{}") {
3387
+ return;
3388
+ }
3389
+ const prefixCandidate = toIncompleteJsonPrefix(fullInput);
3390
+ emitPrefixDelta({
3391
+ controller,
3392
+ id: callState.toolCallId,
3393
+ state: callState,
3394
+ candidate: prefixCandidate
3395
+ });
3396
+ };
3397
+ const finalizeCall = (controller, callState, fallbackToolName, rawToolCallText = null) => {
3398
+ var _a, _b;
3399
+ const resolvedToolName = (_a = callState.toolName) != null ? _a : fallbackToolName;
3400
+ if (!resolvedToolName || resolvedToolName.trim().length === 0) {
3401
+ const shouldEmitRaw = shouldEmitRawToolCallTextOnError3(options);
3402
+ (_b = options == null ? void 0 : options.onError) == null ? void 0 : _b.call(
3403
+ options,
3404
+ shouldEmitRaw && rawToolCallText ? "Could not resolve Qwen3CoderToolParser tool name for tool call; emitting original text." : "Could not resolve Qwen3CoderToolParser tool name for tool call",
3405
+ {
3406
+ toolCallId: callState.toolCallId,
3407
+ toolCall: rawToolCallText
3408
+ }
3409
+ );
3410
+ if (callState.hasEmittedStart) {
3411
+ controller.enqueue({
3412
+ type: "tool-input-end",
3413
+ id: callState.toolCallId
3414
+ });
3415
+ }
3416
+ if (shouldEmitRaw && rawToolCallText) {
3417
+ flushText(controller, rawToolCallText);
3418
+ }
3419
+ return false;
3420
+ }
3421
+ callState.toolName = resolvedToolName;
3422
+ maybeEmitToolInputStart(controller, callState);
3423
+ maybeEmitToolInputProgress(controller, callState);
3424
+ const finalInput = stringifyToolInputWithSchema({
3425
+ tools,
3426
+ toolName: resolvedToolName,
3427
+ args: callState.args
3428
+ });
3429
+ emitFinalRemainder({
3430
+ controller,
3431
+ id: callState.toolCallId,
3432
+ state: callState,
3433
+ finalFullJson: finalInput,
3434
+ onMismatch: options == null ? void 0 : options.onError
3435
+ });
3436
+ controller.enqueue({
3437
+ type: "tool-input-end",
3438
+ id: callState.toolCallId
3439
+ });
3440
+ controller.enqueue({
3441
+ type: "tool-call",
3442
+ toolCallId: callState.toolCallId,
3443
+ toolName: resolvedToolName,
3444
+ input: finalInput
3445
+ });
3446
+ return true;
3447
+ };
3448
+ const consumeToolNameTag = (controller, callState, work) => {
3449
+ var _a, _b, _c, _d;
3450
+ if (callState.toolName) {
3451
+ return work;
3452
+ }
3453
+ const match = QWEN3CODER_TOOL_PARSER_STREAM_NAME_TAG_RE.exec(work);
3454
+ if (!match) {
3455
+ return work;
3456
+ }
3457
+ const value = normalizeXmlTextValue((_a = match[2]) != null ? _a : "");
3458
+ if (value.trim().length > 0) {
3459
+ callState.toolName = value;
3460
+ }
3461
+ const start = (_b = match.index) != null ? _b : 0;
3462
+ const nextWork = removeSlice(
3463
+ work,
3464
+ start,
3465
+ start + ((_d = (_c = match[0]) == null ? void 0 : _c.length) != null ? _d : 0)
3466
+ );
3467
+ maybeEmitToolInputStart(controller, callState);
3468
+ return nextWork;
3469
+ };
3470
+ const consumeParamTags = (controller, callState, work, allowEndOfString) => {
3471
+ const lower = work.toLowerCase();
3472
+ let index = 0;
3473
+ let lastKept = 0;
3474
+ let pieces = null;
3475
+ while (true) {
3476
+ const lt = lower.indexOf("<", index);
3477
+ if (lt === -1) {
3478
+ break;
3479
+ }
3480
+ const parsed = parseQwen3CoderToolParserParamTagAt(work, lower, lt, {
3481
+ allowEndOfString,
3482
+ callEndTagNameLower: callState.endTagName
3483
+ });
3484
+ if (!parsed) {
3485
+ index = lt + 1;
3486
+ continue;
3487
+ }
3488
+ if (parsed.kind === "partial") {
3489
+ break;
3490
+ }
3491
+ mergeParamValue(callState.args, parsed.name, parsed.value);
3492
+ pieces != null ? pieces : pieces = [];
3493
+ pieces.push(work.slice(lastKept, parsed.start));
3494
+ lastKept = parsed.end;
3495
+ index = parsed.end;
3496
+ }
3497
+ maybeEmitToolInputStart(controller, callState);
3498
+ if (!pieces) {
3499
+ return work;
3500
+ }
3501
+ pieces.push(work.slice(lastKept));
3502
+ return pieces.join("");
3503
+ };
3504
+ const parseCallContent = (controller, callState, content, allowEndOfString) => {
3505
+ let work = content;
3506
+ work = consumeToolNameTag(controller, callState, work);
3507
+ work = consumeParamTags(controller, callState, work, allowEndOfString);
3508
+ maybeEmitToolInputStart(controller, callState);
3509
+ maybeEmitToolInputProgress(controller, callState);
3510
+ return work;
3511
+ };
3512
+ const closeTagCache = /* @__PURE__ */ new Map();
3513
+ const getCloseTagPattern = (endTagName) => {
3514
+ const cached = closeTagCache.get(endTagName);
3515
+ if (cached) {
3516
+ return cached;
3517
+ }
3518
+ const created = new RegExp(
3519
+ `<\\s*\\/\\s*${escapeRegExp(endTagName)}\\s*>`,
3520
+ "i"
3521
+ );
3522
+ closeTagCache.set(endTagName, created);
3523
+ return created;
3524
+ };
3525
+ const getNextCallStartInBuffer = (callState) => {
3526
+ var _a;
3527
+ if (callState.endTagName === "tool_call") {
3528
+ return -1;
3529
+ }
3530
+ const match = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE.exec(
3531
+ callState.buffer
3532
+ );
3533
+ return (_a = match == null ? void 0 : match.index) != null ? _a : -1;
3534
+ };
3535
+ const finalizeStreamingCall = (controller, callState, fallbackToolName, remainder) => {
3536
+ const rawToolCallText = remainder.length > 0 && callState.raw.endsWith(remainder) ? callState.raw.slice(0, -remainder.length) : callState.raw;
3537
+ const ok = finalizeCall(
3538
+ controller,
3539
+ callState,
3540
+ fallbackToolName,
3541
+ rawToolCallText
3542
+ );
3543
+ if (ok && toolCall) {
3544
+ toolCall.emittedToolCallCount += 1;
3545
+ }
3546
+ };
3547
+ const consumeCallAtNextBoundary = (controller, callState, fallbackToolName, nextCallStart) => {
3548
+ const beforeNextCall = callState.buffer.slice(0, nextCallStart);
3549
+ const afterNextCall = callState.buffer.slice(nextCallStart);
3550
+ callState.buffer = parseCallContent(
3551
+ controller,
3552
+ callState,
3553
+ beforeNextCall,
3554
+ true
3555
+ );
3556
+ finalizeStreamingCall(
3557
+ controller,
3558
+ callState,
3559
+ fallbackToolName,
3560
+ afterNextCall
3561
+ );
3562
+ return { done: true, remainder: afterNextCall };
3563
+ };
3564
+ const consumeCall = (controller, callState, incoming, fallbackToolName) => {
3565
+ var _a, _b, _c;
3566
+ callState.buffer += incoming;
3567
+ callState.raw += incoming;
3568
+ const closeMatch = getCloseTagPattern(callState.endTagName).exec(
3569
+ callState.buffer
3570
+ );
3571
+ const closeStart = (_a = closeMatch == null ? void 0 : closeMatch.index) != null ? _a : -1;
3572
+ const nextCallStart = getNextCallStartInBuffer(callState);
3573
+ const shouldCloseAtNextBoundary = nextCallStart !== -1 && (closeStart === -1 || nextCallStart < closeStart);
3574
+ if (shouldCloseAtNextBoundary) {
3575
+ return consumeCallAtNextBoundary(
3576
+ controller,
3577
+ callState,
3578
+ fallbackToolName,
3579
+ nextCallStart
3580
+ );
3581
+ }
3582
+ if (!closeMatch) {
3583
+ callState.buffer = parseCallContent(
3584
+ controller,
3585
+ callState,
3586
+ callState.buffer,
3587
+ false
3588
+ );
3589
+ return { done: false, remainder: "" };
3590
+ }
3591
+ const closeEnd = closeStart + ((_c = (_b = closeMatch[0]) == null ? void 0 : _b.length) != null ? _c : 0);
3592
+ const beforeClose = callState.buffer.slice(0, closeStart);
3593
+ const afterClose = callState.buffer.slice(closeEnd);
3594
+ parseCallContent(controller, callState, beforeClose, true);
3595
+ callState.buffer = "";
3596
+ finalizeStreamingCall(
3597
+ controller,
3598
+ callState,
3599
+ fallbackToolName,
3600
+ afterClose
3601
+ );
3602
+ return { done: true, remainder: afterClose };
3603
+ };
3604
+ const finalizeCallAtFinish = (controller, callState, fallbackToolName) => {
3605
+ callState.buffer = parseCallContent(
3606
+ controller,
3607
+ callState,
3608
+ callState.buffer,
3609
+ true
3610
+ );
3611
+ const trailingText = stripLeadingCallCloseTags(callState.buffer);
3612
+ callState.buffer = "";
3613
+ const ok = finalizeCall(controller, callState, fallbackToolName, null);
3614
+ return {
3615
+ ok,
3616
+ trailingText
3617
+ };
3618
+ };
3619
+ const flushSafeTextPrefix = (controller) => {
3620
+ const lower = buffer.toLowerCase();
3621
+ const potentialIndices = [
3622
+ getPotentialStartIndex(lower, toolCallStartPrefixLower),
3623
+ ...implicitCallPrefixesLower.map(
3624
+ (prefix) => getPotentialStartIndex(lower, prefix)
3625
+ )
3626
+ ].filter((value) => value != null);
3627
+ const potentialIndex = potentialIndices.length > 0 ? Math.min(...potentialIndices) : null;
3628
+ if (potentialIndex == null) {
3629
+ if (buffer.length > 0) {
3630
+ flushText(controller, buffer);
3631
+ buffer = "";
3632
+ }
3633
+ return;
3634
+ }
3635
+ if (potentialIndex > 0) {
3636
+ flushText(controller, buffer.slice(0, potentialIndex));
3637
+ buffer = buffer.slice(potentialIndex);
3638
+ }
3639
+ };
3640
+ const stripLeadingToolCallCloseTagsFromBuffer = () => {
3641
+ if (!buffer) {
3642
+ return;
3643
+ }
3644
+ const stripped = stripLeadingToolCallCloseTags(buffer);
3645
+ if (stripped !== buffer) {
3646
+ buffer = stripped;
3647
+ }
3648
+ };
3649
+ const startToolCallIfPresent = (_controller) => {
3650
+ if (toolCall) {
3651
+ return;
3652
+ }
3653
+ if (implicitCall) {
3654
+ return;
3655
+ }
3656
+ const lower = buffer.toLowerCase();
3657
+ const startIndex = getPotentialStartIndex(
3658
+ lower,
3659
+ toolCallStartPrefixLower
3660
+ );
3661
+ if (startIndex == null || startIndex !== 0) {
3662
+ return;
3663
+ }
3664
+ const gtIndex = buffer.indexOf(">");
3665
+ if (gtIndex === -1) {
3666
+ return;
3667
+ }
3668
+ const openTag = buffer.slice(0, gtIndex + 1);
3669
+ if (!TOOL_CALL_OPEN_RE.test(openTag)) {
3670
+ return;
3671
+ }
3672
+ toolCall = {
3673
+ outerOpenTag: openTag,
3674
+ outerNameAttr: getAttributeValue(openTag, "name"),
3675
+ raw: openTag,
3676
+ mode: "unknown",
3677
+ innerBuffer: "",
3678
+ activeCall: null,
3679
+ emittedToolCallCount: 0
3680
+ };
3681
+ const remainder = buffer.slice(gtIndex + 1);
3682
+ buffer = "";
3683
+ if (remainder.length > 0) {
3684
+ toolCall.raw += remainder;
3685
+ toolCall.innerBuffer += remainder;
3686
+ }
3687
+ };
3688
+ const startImplicitCallIfPresent = (controller) => {
3689
+ var _a, _b, _c, _d;
3690
+ if (toolCall || implicitCall) {
3691
+ return;
3692
+ }
3693
+ const match = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE.exec(buffer);
3694
+ const startIndex = (_a = match == null ? void 0 : match.index) != null ? _a : -1;
3695
+ const openTag = (_b = match == null ? void 0 : match[0]) != null ? _b : "";
3696
+ const callTagName = ((_c = match == null ? void 0 : match[1]) != null ? _c : "").toLowerCase();
3697
+ if (!match || startIndex !== 0 || !openTag || !callTagName) {
3698
+ return;
3699
+ }
3700
+ const inlineToolName = (_d = getAttributeValue(openTag, "name")) != null ? _d : getShorthandValue(openTag);
3701
+ if (!inlineToolName || inlineToolName.trim().length === 0) {
3702
+ return;
3703
+ }
3704
+ const selfClosing = QWEN3CODER_TOOL_PARSER_STREAM_SELF_CLOSING_TAG_RE.test(openTag);
3705
+ buffer = buffer.slice(openTag.length);
3706
+ const newCall = {
3707
+ endTagName: callTagName,
3708
+ toolCallId: generateToolCallId(),
3709
+ toolName: inlineToolName,
3710
+ hasEmittedStart: false,
3711
+ emittedInput: "",
3712
+ raw: openTag,
3713
+ args: {},
3714
+ buffer: ""
3715
+ };
3716
+ maybeEmitToolInputStart(controller, newCall);
3717
+ if (selfClosing) {
3718
+ finalizeCall(controller, newCall, inlineToolName, newCall.raw);
3719
+ return;
3720
+ }
3721
+ implicitCall = newCall;
3722
+ implicitCallOpenTag = openTag;
3723
+ };
3724
+ const processImplicitCall = (controller) => {
3725
+ while (implicitCall) {
3726
+ const callState = implicitCall;
3727
+ const { done, remainder } = consumeCall(
3728
+ controller,
3729
+ callState,
3730
+ buffer,
3731
+ null
3732
+ );
3733
+ buffer = "";
3734
+ if (!done) {
3735
+ return;
3736
+ }
3737
+ implicitCall = null;
3738
+ implicitCallOpenTag = null;
3739
+ if (remainder.length > 0) {
3740
+ buffer = remainder;
3741
+ }
3742
+ stripLeadingToolCallCloseTagsFromBuffer();
3743
+ flushSafeTextPrefix(controller);
3744
+ startToolCallIfPresent(controller);
3745
+ if (toolCall) {
3746
+ processToolCall2(controller);
3747
+ return;
3748
+ }
3749
+ startImplicitCallIfPresent(controller);
3750
+ }
3751
+ };
3752
+ const drainStarts = (controller) => {
3753
+ while (true) {
3754
+ if (toolCall || implicitCall) {
3755
+ return;
3756
+ }
3757
+ const before = buffer;
3758
+ startToolCallIfPresent(controller);
3759
+ if (toolCall) {
3760
+ processToolCall2(controller);
3761
+ return;
3762
+ }
3763
+ startImplicitCallIfPresent(controller);
3764
+ if (implicitCall) {
3765
+ processImplicitCall(controller);
3766
+ return;
3767
+ }
3768
+ if (buffer === before) {
3769
+ return;
3770
+ }
3771
+ stripLeadingToolCallCloseTagsFromBuffer();
3772
+ flushSafeTextPrefix(controller);
3773
+ }
3774
+ };
3775
+ const processToolCall2 = (controller) => {
3776
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3777
+ while (toolCall) {
3778
+ if (toolCall.mode === "unknown") {
3779
+ const callMatch = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_START_RE.exec(
3780
+ toolCall.innerBuffer
3781
+ );
3782
+ const signalMatch = QWEN3CODER_TOOL_PARSER_STREAM_NAME_OR_PARAM_SIGNAL_RE.exec(
3783
+ toolCall.innerBuffer
3784
+ );
3785
+ if (callMatch && (!signalMatch || ((_a = callMatch.index) != null ? _a : 0) < ((_b = signalMatch.index) != null ? _b : 0))) {
3786
+ toolCall.mode = "multi";
3787
+ } else if (signalMatch) {
3788
+ toolCall.mode = "single";
3789
+ const activeCall = {
3790
+ endTagName: "tool_call",
3791
+ toolCallId: generateToolCallId(),
3792
+ toolName: toolCall.outerNameAttr,
3793
+ hasEmittedStart: false,
3794
+ emittedInput: "",
3795
+ raw: toolCall.outerOpenTag,
3796
+ args: {},
3797
+ buffer: ""
3798
+ };
3799
+ toolCall.activeCall = activeCall;
3800
+ if (toolCall.outerNameAttr) {
3801
+ maybeEmitToolInputStart(controller, activeCall);
3802
+ }
3803
+ } else {
3804
+ return;
3805
+ }
3806
+ }
3807
+ if (toolCall.mode === "single") {
3808
+ const callState = toolCall.activeCall;
3809
+ if (!callState) {
3810
+ return;
3811
+ }
3812
+ const { done, remainder } = consumeCall(
3813
+ controller,
3814
+ callState,
3815
+ toolCall.innerBuffer,
3816
+ toolCall.outerNameAttr
3817
+ );
3818
+ toolCall.innerBuffer = "";
3819
+ if (!done) {
3820
+ return;
3821
+ }
3822
+ toolCall = null;
3823
+ if (remainder.length > 0) {
3824
+ buffer = remainder + buffer;
3825
+ }
3826
+ flushSafeTextPrefix(controller);
3827
+ startToolCallIfPresent(controller);
3828
+ continue;
3829
+ }
3830
+ if (toolCall.mode === "multi") {
3831
+ if (toolCall.activeCall) {
3832
+ const callState = toolCall.activeCall;
3833
+ const { done, remainder } = consumeCall(
3834
+ controller,
3835
+ callState,
3836
+ toolCall.innerBuffer,
3837
+ toolCall.outerNameAttr
3838
+ );
3839
+ toolCall.innerBuffer = "";
3840
+ if (!done) {
3841
+ return;
3842
+ }
3843
+ toolCall.activeCall = null;
3844
+ toolCall.innerBuffer = remainder;
3845
+ continue;
3846
+ }
3847
+ const closeMatch = QWEN3CODER_TOOL_PARSER_STREAM_TOOL_CALL_CLOSE_TAG_RE.exec(
3848
+ toolCall.innerBuffer
3849
+ );
3850
+ const callOpenMatch = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_TAG_RE.exec(
3851
+ toolCall.innerBuffer
3852
+ );
3853
+ if (!(closeMatch || callOpenMatch)) {
3854
+ return;
3855
+ }
3856
+ const closeIndex = (_c = closeMatch == null ? void 0 : closeMatch.index) != null ? _c : -1;
3857
+ const callIndex = (_d = callOpenMatch == null ? void 0 : callOpenMatch.index) != null ? _d : -1;
3858
+ const hasClose = closeIndex !== -1;
3859
+ const hasCall = callIndex !== -1;
3860
+ const chooseClose = hasClose && (!hasCall || closeIndex < callIndex);
3861
+ const nextIndex = chooseClose ? closeIndex : callIndex;
3862
+ if (nextIndex > 0) {
3863
+ toolCall.innerBuffer = toolCall.innerBuffer.slice(nextIndex);
3864
+ }
3865
+ if (chooseClose) {
3866
+ const matchLen = (_f = (_e = closeMatch == null ? void 0 : closeMatch[0]) == null ? void 0 : _e.length) != null ? _f : 0;
3867
+ const remainder = toolCall.innerBuffer.slice(matchLen);
3868
+ toolCall = null;
3869
+ if (remainder.length > 0) {
3870
+ buffer = remainder + buffer;
3871
+ }
3872
+ flushSafeTextPrefix(controller);
3873
+ startToolCallIfPresent(controller);
3874
+ continue;
3875
+ }
3876
+ if (!callOpenMatch) {
3877
+ return;
3878
+ }
3879
+ const openTag = (_g = callOpenMatch[0]) != null ? _g : "";
3880
+ const callTagName = ((_h = callOpenMatch[1]) != null ? _h : "").toLowerCase();
3881
+ const rest = toolCall.innerBuffer.slice(openTag.length);
3882
+ const selfClosing = QWEN3CODER_TOOL_PARSER_STREAM_SELF_CLOSING_TAG_RE.test(openTag);
3883
+ if (selfClosing) {
3884
+ const toolNameAttr2 = (_j = (_i = getAttributeValue(openTag, "name")) != null ? _i : getShorthandValue(openTag)) != null ? _j : toolCall.outerNameAttr;
3885
+ const immediateCall = {
3886
+ endTagName: callTagName,
3887
+ toolCallId: generateToolCallId(),
3888
+ toolName: toolNameAttr2,
3889
+ hasEmittedStart: false,
3890
+ emittedInput: "",
3891
+ raw: openTag,
3892
+ args: {},
3893
+ buffer: ""
3894
+ };
3895
+ const ok = finalizeCall(
3896
+ controller,
3897
+ immediateCall,
3898
+ toolNameAttr2,
3899
+ immediateCall.raw
3900
+ );
3901
+ if (ok) {
3902
+ toolCall.emittedToolCallCount += 1;
3903
+ }
3904
+ toolCall.innerBuffer = rest;
3905
+ continue;
3906
+ }
3907
+ const toolNameAttr = (_k = getAttributeValue(openTag, "name")) != null ? _k : getShorthandValue(openTag);
3908
+ const newCall = {
3909
+ endTagName: callTagName,
3910
+ toolCallId: generateToolCallId(),
3911
+ toolName: toolNameAttr,
3912
+ hasEmittedStart: false,
3913
+ emittedInput: "",
3914
+ raw: openTag,
3915
+ args: {},
3916
+ buffer: ""
3917
+ };
3918
+ if (toolNameAttr) {
3919
+ maybeEmitToolInputStart(controller, newCall);
3920
+ }
3921
+ toolCall.activeCall = newCall;
3922
+ toolCall.innerBuffer = rest;
3923
+ }
3924
+ }
3925
+ };
3926
+ const reportUnfinishedToolCallAtFinish = (controller, rawToolCall) => {
3927
+ var _a;
3928
+ const shouldEmitRaw = shouldEmitRawToolCallTextOnError3(options);
3929
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3930
+ options,
3931
+ shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser XML tool call at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser XML tool call at finish.",
3932
+ { toolCall: rawToolCall }
3933
+ );
3934
+ if (shouldEmitRaw) {
3935
+ flushText(controller, rawToolCall);
3936
+ }
3937
+ };
3938
+ const reportUnfinishedImplicitCallAtFinish = (controller, rawCallText) => {
3939
+ var _a;
3940
+ const shouldEmitRaw = shouldEmitRawToolCallTextOnError3(options);
3941
+ (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
3942
+ options,
3943
+ shouldEmitRaw ? "Could not complete streaming Qwen3CoderToolParser call block at finish; emitting original text." : "Could not complete streaming Qwen3CoderToolParser call block at finish.",
3944
+ { toolCall: rawCallText }
3945
+ );
3946
+ if (shouldEmitRaw) {
3947
+ flushText(controller, rawCallText);
3948
+ }
3949
+ };
3950
+ const handleFinish = (controller) => {
3951
+ var _a, _b;
3952
+ if (toolCall) {
3953
+ processToolCall2(controller);
3954
+ if (toolCall) {
3955
+ if (toolCall.mode === "unknown") {
3956
+ const callMatch = QWEN3CODER_TOOL_PARSER_STREAM_CALL_OPEN_START_RE.exec(
3957
+ toolCall.innerBuffer
3958
+ );
3959
+ const signalMatch = QWEN3CODER_TOOL_PARSER_STREAM_NAME_OR_PARAM_SIGNAL_RE.exec(
3960
+ toolCall.innerBuffer
3961
+ );
3962
+ if (callMatch && (!signalMatch || ((_a = callMatch.index) != null ? _a : 0) < ((_b = signalMatch.index) != null ? _b : 0))) {
3963
+ toolCall.mode = "multi";
3964
+ } else if (signalMatch) {
3965
+ toolCall.mode = "single";
3966
+ toolCall.activeCall = {
3967
+ endTagName: "tool_call",
3968
+ toolCallId: generateToolCallId(),
3969
+ toolName: toolCall.outerNameAttr,
3970
+ hasEmittedStart: false,
3971
+ emittedInput: "",
3972
+ raw: toolCall.outerOpenTag,
3973
+ args: {},
3974
+ buffer: ""
3975
+ };
3976
+ }
3977
+ }
3978
+ if (toolCall.mode === "single" && toolCall.activeCall) {
3979
+ toolCall.activeCall.buffer += toolCall.innerBuffer;
3980
+ toolCall.innerBuffer = "";
3981
+ const result = finalizeCallAtFinish(
3982
+ controller,
3983
+ toolCall.activeCall,
3984
+ toolCall.outerNameAttr
3985
+ );
3986
+ if (result.ok) {
3987
+ toolCall.emittedToolCallCount += 1;
3988
+ }
3989
+ const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError3(options);
3990
+ if (shouldFlushTrailingText && result.trailingText.length > 0) {
3991
+ flushText(controller, result.trailingText);
3992
+ }
3993
+ if (!result.ok && toolCall.emittedToolCallCount === 0) {
3994
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
3995
+ }
3996
+ } else if (toolCall.mode === "multi") {
3997
+ if (toolCall.activeCall) {
3998
+ const result = finalizeCallAtFinish(
3999
+ controller,
4000
+ toolCall.activeCall,
4001
+ toolCall.outerNameAttr
4002
+ );
4003
+ if (result.ok) {
4004
+ toolCall.emittedToolCallCount += 1;
4005
+ }
4006
+ const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError3(options);
4007
+ if (shouldFlushTrailingText && result.trailingText.length > 0) {
4008
+ flushText(controller, result.trailingText);
4009
+ }
4010
+ if (!result.ok && toolCall.emittedToolCallCount === 0) {
4011
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4012
+ }
4013
+ toolCall.activeCall = null;
4014
+ } else if (toolCall.emittedToolCallCount === 0) {
4015
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4016
+ }
4017
+ } else {
4018
+ reportUnfinishedToolCallAtFinish(controller, toolCall.raw);
4019
+ }
4020
+ toolCall = null;
4021
+ }
4022
+ }
4023
+ if (implicitCall) {
4024
+ const callState = implicitCall;
4025
+ const openTag = implicitCallOpenTag;
4026
+ implicitCall = null;
4027
+ implicitCallOpenTag = null;
4028
+ const result = finalizeCallAtFinish(controller, callState, null);
4029
+ const shouldFlushTrailingText = result.ok || !shouldEmitRawToolCallTextOnError3(options);
4030
+ if (shouldFlushTrailingText && result.trailingText.length > 0) {
4031
+ flushText(controller, result.trailingText);
4032
+ }
4033
+ if (!result.ok && openTag) {
4034
+ reportUnfinishedImplicitCallAtFinish(
4035
+ controller,
4036
+ callState.raw || openTag + callState.buffer
4037
+ );
4038
+ }
4039
+ } else {
4040
+ stripLeadingToolCallCloseTagsFromBuffer();
4041
+ flushSafeTextPrefix(controller);
4042
+ drainStarts(controller);
4043
+ }
4044
+ if (buffer.length > 0) {
4045
+ flushText(controller, buffer);
4046
+ buffer = "";
4047
+ }
4048
+ flushText(controller);
4049
+ };
4050
+ const handlePassthroughChunk = (controller, chunk) => {
4051
+ if (!toolCall && buffer) {
4052
+ flushText(controller, buffer);
4053
+ buffer = "";
4054
+ }
4055
+ controller.enqueue(chunk);
4056
+ };
4057
+ const handleTextDeltaChunk = (controller, delta) => {
4058
+ if (toolCall) {
4059
+ toolCall.raw += delta;
4060
+ toolCall.innerBuffer += delta;
4061
+ processToolCall2(controller);
4062
+ return;
4063
+ }
4064
+ if (implicitCall) {
4065
+ const callState = implicitCall;
4066
+ const { done, remainder } = consumeCall(
4067
+ controller,
4068
+ callState,
4069
+ delta,
4070
+ null
4071
+ );
4072
+ if (!done) {
4073
+ return;
4074
+ }
4075
+ implicitCall = null;
4076
+ implicitCallOpenTag = null;
4077
+ if (remainder.length > 0) {
4078
+ buffer = remainder + buffer;
4079
+ }
4080
+ stripLeadingToolCallCloseTagsFromBuffer();
4081
+ flushSafeTextPrefix(controller);
4082
+ drainStarts(controller);
4083
+ return;
4084
+ }
4085
+ buffer += delta;
4086
+ stripLeadingToolCallCloseTagsFromBuffer();
4087
+ flushSafeTextPrefix(controller);
4088
+ drainStarts(controller);
4089
+ };
4090
+ const handleTransformChunk = (controller, chunk) => {
4091
+ if (chunk.type === "finish") {
4092
+ handleFinish(controller);
4093
+ controller.enqueue(chunk);
4094
+ return;
4095
+ }
4096
+ if (chunk.type !== "text-delta") {
4097
+ handlePassthroughChunk(controller, chunk);
4098
+ return;
4099
+ }
4100
+ const delta = chunk.delta;
4101
+ if (!delta) {
4102
+ return;
4103
+ }
4104
+ handleTextDeltaChunk(controller, delta);
4105
+ };
4106
+ return new TransformStream({
4107
+ transform(chunk, controller) {
4108
+ handleTransformChunk(controller, chunk);
4109
+ },
4110
+ flush(controller) {
4111
+ handleFinish(controller);
4112
+ }
4113
+ });
4114
+ }
4115
+ });
4116
+ var uiTarsXmlProtocol = qwen3CoderProtocol;
4117
+ var Qwen3CoderToolParser = qwen3CoderProtocol;
4118
+
4119
+ // src/core/protocols/yaml-xml-protocol.ts
4120
+ import YAML from "yaml";
4121
+ function shouldEmitRawToolCallTextOnError4(options) {
4122
+ return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
4123
+ }
4124
+ var selfClosingTagCache2 = /* @__PURE__ */ new Map();
4125
+ function getSelfClosingTagPattern2(toolName) {
4126
+ let pattern = selfClosingTagCache2.get(toolName);
4127
+ if (!pattern) {
4128
+ pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
4129
+ selfClosingTagCache2.set(toolName, pattern);
4130
+ }
4131
+ return pattern;
4132
+ }
4133
+ var LEADING_WHITESPACE_RE = /^(\s*)/;
4134
+ var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
4135
+ var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
4136
+ var BLOCK_SCALAR_KEY_RE = /:\s*[|>][-+0-9]*\s*$/;
4137
+ var PLAIN_MAPPING_VALUE_RE = /^[^:[\]{}-][^:]*:\s*(.+)$/;
4138
+ var PLAIN_SEQUENCE_VALUE_RE = /^-\s+(.+)$/;
4139
+ function normalizeYamlContent(yamlContent) {
4140
+ let normalized = yamlContent;
4141
+ if (normalized.startsWith("\n")) {
4142
+ normalized = normalized.slice(1);
4143
+ }
4144
+ const lines = normalized.split("\n");
4145
+ const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
4146
+ if (nonEmptyLines.length === 0) {
4147
+ return { normalized: "", nonEmptyLines };
4148
+ }
4149
+ const minIndent = Math.min(
4150
+ ...nonEmptyLines.map((line) => {
4151
+ const match = line.match(LEADING_WHITESPACE_RE);
4152
+ return match ? match[1].length : 0;
4153
+ })
4154
+ );
4155
+ if (minIndent > 0) {
4156
+ normalized = lines.map((line) => line.slice(minIndent)).join("\n");
4157
+ }
4158
+ return { normalized, nonEmptyLines };
4159
+ }
4160
+ function parseYamlDocumentAsMapping(normalized) {
4161
+ try {
4162
+ const doc = YAML.parseDocument(normalized);
4163
+ const errors = doc.errors.map((e) => e.message);
4164
+ const result = doc.toJSON();
4165
+ if (result === null) {
4166
+ return { value: {}, errors };
4167
+ }
4168
+ if (typeof result !== "object" || Array.isArray(result)) {
4169
+ return { value: null, errors };
4170
+ }
4171
+ return { value: result, errors };
4172
+ } catch (error) {
4173
+ return {
4174
+ value: null,
4175
+ errors: [
4176
+ error instanceof Error ? error.message : "Unknown YAML parsing error"
4177
+ ]
4178
+ };
4179
+ }
4180
+ }
4181
+ function getLastMeaningfulLineInfo(input) {
4182
+ var _a;
4183
+ const lines = input.split("\n");
4184
+ let index = lines.length - 1;
4185
+ while (index >= 0) {
4186
+ const raw = (_a = lines[index]) != null ? _a : "";
4187
+ const trimmed = raw.trim();
4188
+ if (trimmed.length > 0 && !trimmed.startsWith("#")) {
4189
+ return {
4190
+ index,
4191
+ raw,
4192
+ trimmed,
4193
+ indent: raw.length - raw.trimStart().length
4194
+ };
4195
+ }
4196
+ index -= 1;
4197
+ }
4198
+ return null;
4199
+ }
4200
+ function dropLastMeaningfulLine(input) {
4201
+ const lineInfo = getLastMeaningfulLineInfo(input);
4202
+ if (!lineInfo) {
4203
+ return null;
4204
+ }
4205
+ return input.split("\n").slice(0, lineInfo.index).join("\n").trimEnd();
4206
+ }
4207
+ function hasIncompleteMappingTail(normalized) {
4208
+ const lineInfo = getLastMeaningfulLineInfo(normalized);
4209
+ if (!lineInfo) {
4210
+ return false;
4211
+ }
4212
+ return INCOMPLETE_MAPPING_TAIL_RE.test(lineInfo.trimmed);
4213
+ }
4214
+ function hasIncompleteSequenceTail(normalized) {
4215
+ const lineInfo = getLastMeaningfulLineInfo(normalized);
4216
+ if (!lineInfo) {
4217
+ return false;
4218
+ }
4219
+ return INCOMPLETE_SEQUENCE_TAIL_RE.test(lineInfo.trimmed);
4220
+ }
4221
+ function hasSplitNestedKeyTail(normalized) {
4222
+ var _a;
4223
+ const lineInfo = getLastMeaningfulLineInfo(normalized);
4224
+ if (!lineInfo) {
4225
+ return false;
4226
+ }
4227
+ const { trimmed, indent, index } = lineInfo;
4228
+ if (indent === 0) {
4229
+ return false;
4230
+ }
4231
+ if (trimmed.startsWith("#") || trimmed.startsWith("-") || trimmed.includes(":")) {
4232
+ return false;
4233
+ }
4234
+ const lines = normalized.split("\n");
4235
+ let parentIndex = index - 1;
4236
+ while (parentIndex >= 0) {
4237
+ const parentRaw = (_a = lines[parentIndex]) != null ? _a : "";
4238
+ const parentTrimmed = parentRaw.trim();
4239
+ if (parentTrimmed.length === 0 || parentTrimmed.startsWith("#")) {
4240
+ parentIndex -= 1;
4241
+ continue;
4242
+ }
4243
+ const parentIndent = parentRaw.length - parentRaw.trimStart().length;
4244
+ if (parentIndent >= indent) {
4245
+ parentIndex -= 1;
4246
+ continue;
4247
+ }
4248
+ if (!parentTrimmed.endsWith(":")) {
4249
+ return false;
4250
+ }
4251
+ if (BLOCK_SCALAR_KEY_RE.test(parentTrimmed)) {
4252
+ return false;
4253
+ }
4254
+ return true;
4255
+ }
4256
+ return false;
4257
+ }
4258
+ function extractTrailingPlainScalarValue(line) {
4259
+ var _a;
4260
+ if (BLOCK_SCALAR_KEY_RE.test(line)) {
4261
+ return null;
4262
+ }
4263
+ const mappingMatch = line.match(PLAIN_MAPPING_VALUE_RE);
4264
+ const sequenceMatch = line.match(PLAIN_SEQUENCE_VALUE_RE);
4265
+ const value = (_a = mappingMatch == null ? void 0 : mappingMatch[1]) != null ? _a : sequenceMatch == null ? void 0 : sequenceMatch[1];
4266
+ if (!value) {
4267
+ return null;
4268
+ }
4269
+ const trimmedValue = value.trim();
4270
+ if (trimmedValue.length === 0) {
4271
+ return null;
4272
+ }
4273
+ if (trimmedValue.startsWith('"') || trimmedValue.startsWith("'")) {
4274
+ return null;
4275
+ }
4276
+ if (trimmedValue.startsWith("{") || trimmedValue.startsWith("[") || trimmedValue.startsWith("|") || trimmedValue.startsWith(">")) {
4277
+ return null;
4278
+ }
4279
+ return trimmedValue;
4280
+ }
4281
+ function hasUnterminatedPlainScalarTail(normalized) {
4282
+ if (normalized.endsWith("\n")) {
4283
+ return false;
4284
+ }
4285
+ const lineInfo = getLastMeaningfulLineInfo(normalized);
4286
+ if (!lineInfo) {
4287
+ return false;
4288
+ }
4289
+ return extractTrailingPlainScalarValue(lineInfo.trimmed) != null;
4290
+ }
4291
+ function hasUnstableProgressTail(normalized) {
4292
+ return hasIncompleteMappingTail(normalized) || hasIncompleteSequenceTail(normalized) || hasSplitNestedKeyTail(normalized) || hasUnterminatedPlainScalarTail(normalized);
4293
+ }
4294
+ function trimTrailingNewlineInUnknown(value) {
4295
+ if (typeof value === "string") {
4296
+ if (value.endsWith("\n")) {
4297
+ return value.slice(0, -1);
4298
+ }
4299
+ return value;
4300
+ }
4301
+ if (Array.isArray(value)) {
4302
+ return value.map((item) => trimTrailingNewlineInUnknown(item));
4303
+ }
4304
+ if (value && typeof value === "object") {
4305
+ return Object.fromEntries(
4306
+ Object.entries(value).map(([key, item]) => [
4307
+ key,
4308
+ trimTrailingNewlineInUnknown(item)
2434
4309
  ])
2435
4310
  );
2436
4311
  }
@@ -2442,7 +4317,7 @@ function stabilizeParsedValueForStreamProgress(value, source) {
2442
4317
  }
2443
4318
  return trimTrailingNewlineInUnknown(value);
2444
4319
  }
2445
- function findClosingTagEnd(text, contentStart, toolName) {
4320
+ function findClosingTagEnd2(text, contentStart, toolName) {
2446
4321
  let pos = contentStart;
2447
4322
  let depth = 1;
2448
4323
  while (pos < text.length) {
@@ -2513,9 +4388,9 @@ function findEarliestTagPosition(openIdx, selfIdx) {
2513
4388
  function collectToolCallsForName(text, toolName) {
2514
4389
  const toolCalls = [];
2515
4390
  let searchIndex = 0;
4391
+ const startTag = `<${toolName}>`;
2516
4392
  const selfTagRegex = getSelfClosingTagPattern2(toolName);
2517
4393
  while (searchIndex < text.length) {
2518
- const startTag = `<${toolName}>`;
2519
4394
  const openIdx = text.indexOf(startTag, searchIndex);
2520
4395
  selfTagRegex.lastIndex = searchIndex;
2521
4396
  const selfMatch = selfTagRegex.exec(text);
@@ -2540,7 +4415,7 @@ function collectToolCallsForName(text, toolName) {
2540
4415
  continue;
2541
4416
  }
2542
4417
  const contentStart = tagStart + startTag.length;
2543
- const fullTagEnd = findClosingTagEnd(text, contentStart, toolName);
4418
+ const fullTagEnd = findClosingTagEnd2(text, contentStart, toolName);
2544
4419
  if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
2545
4420
  const endTag = `</${toolName}>`;
2546
4421
  const endTagStart = fullTagEnd - endTag.length;
@@ -2690,7 +4565,7 @@ function stripTrailingPartialCloseTag(content, toolName) {
2690
4565
  )}${preservedLeadingWhitespace}`;
2691
4566
  return contentWithoutPartial.trimEnd();
2692
4567
  }
2693
- var yamlProtocol = (_protocolOptions) => {
4568
+ var yamlXmlProtocol = (_protocolOptions) => {
2694
4569
  return {
2695
4570
  formatTools({ tools, toolSystemPromptTemplate }) {
2696
4571
  return toolSystemPromptTemplate(tools || []);
@@ -2814,7 +4689,7 @@ ${yamlContent}</${toolCall.toolName}>`;
2814
4689
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
2815
4690
  toolCall: original
2816
4691
  });
2817
- if (shouldEmitRawToolCallTextOnError3(options)) {
4692
+ if (shouldEmitRawToolCallTextOnError4(options)) {
2818
4693
  flushText(controller, original);
2819
4694
  }
2820
4695
  }
@@ -2859,7 +4734,7 @@ ${yamlContent}</${toolCall.toolName}>`;
2859
4734
  "Could not complete streaming YAML tool call at finish.",
2860
4735
  { toolCall: unfinishedContent }
2861
4736
  );
2862
- if (shouldEmitRawToolCallTextOnError3(options)) {
4737
+ if (shouldEmitRawToolCallTextOnError4(options)) {
2863
4738
  flushText(controller, unfinishedContent);
2864
4739
  }
2865
4740
  }
@@ -3400,36 +5275,6 @@ function recoverToolCallFromJsonCandidates(text, tools) {
3400
5275
  return null;
3401
5276
  }
3402
5277
 
3403
- // src/core/utils/tool-call-coercion.ts
3404
- function coerceToolCallInput(toolName, input, tools) {
3405
- var _a;
3406
- let args = {};
3407
- if (typeof input === "string") {
3408
- try {
3409
- args = JSON.parse(input);
3410
- } catch (e) {
3411
- return;
3412
- }
3413
- } else if (input && typeof input === "object") {
3414
- args = input;
3415
- } else {
3416
- return;
3417
- }
3418
- const schema = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
3419
- const coerced = coerceBySchema(args, schema);
3420
- return JSON.stringify(coerced != null ? coerced : {});
3421
- }
3422
- function coerceToolCallPart(part, tools) {
3423
- const coercedInput = coerceToolCallInput(part.toolName, part.input, tools);
3424
- if (coercedInput === void 0) {
3425
- return part;
3426
- }
3427
- return {
3428
- ...part,
3429
- input: coercedInput
3430
- };
3431
- }
3432
-
3433
5278
  // src/core/utils/tool-choice.ts
3434
5279
  function ensureNonEmptyToolName(name) {
3435
5280
  if (typeof name !== "string") {
@@ -3637,23 +5482,127 @@ async function wrapGenerate({
3637
5482
  };
3638
5483
  }
3639
5484
 
3640
- // src/core/prompts/hermes-system-prompt.ts
3641
- function hermesSystemPromptTemplate(tools) {
3642
- const toolsJson = JSON.stringify(tools);
3643
- return `You are a function calling AI model.
3644
- You are provided with function signatures within <tools></tools> XML tags.
3645
- You may call one or more functions to assist with the user query.
3646
- Don't make assumptions about what values to plug into functions.
3647
- Here are the available tools: <tools>${toolsJson}</tools>
3648
- Use the following pydantic model json schema for each tool call you will make: {"title": "FunctionCall", "type": "object", "properties": {"arguments": {"title": "Arguments", "type": "object"}, "name": {"title": "Name", "type": "string"}}, "required": ["arguments", "name"]}
3649
- For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
3650
- <tool_call>
3651
- {"name": "<function-name>", "arguments": <args-dict>}
3652
- </tool_call>`;
5485
+ // src/core/prompts/shared/tool-result-normalizer.ts
5486
+ function isMapping(value) {
5487
+ return typeof value === "object" && value !== null && !Array.isArray(value);
5488
+ }
5489
+ function getMediaKindFromMediaType(mediaType) {
5490
+ if (mediaType.startsWith("image/")) {
5491
+ return "image";
5492
+ }
5493
+ if (mediaType.startsWith("audio/")) {
5494
+ return "audio";
5495
+ }
5496
+ if (mediaType.startsWith("video/")) {
5497
+ return "video";
5498
+ }
5499
+ return "file";
5500
+ }
5501
+ function getContentPartMediaKind(part) {
5502
+ const contentPart = isMapping(part) ? part : void 0;
5503
+ const type = contentPart == null ? void 0 : contentPart.type;
5504
+ switch (type) {
5505
+ case "image-data":
5506
+ case "image-url":
5507
+ case "image-file-id":
5508
+ return "image";
5509
+ case "file-data":
5510
+ case "file-url":
5511
+ case "file-id": {
5512
+ const mediaType = contentPart == null ? void 0 : contentPart.mediaType;
5513
+ if (typeof mediaType === "string") {
5514
+ return getMediaKindFromMediaType(mediaType);
5515
+ }
5516
+ return "file";
5517
+ }
5518
+ case "media": {
5519
+ const mediaType = contentPart == null ? void 0 : contentPart.mediaType;
5520
+ if (typeof mediaType === "string") {
5521
+ return getMediaKindFromMediaType(mediaType);
5522
+ }
5523
+ return "file";
5524
+ }
5525
+ default:
5526
+ return null;
5527
+ }
5528
+ }
5529
+ function shouldPassRawByStrategy(mediaKind, strategy) {
5530
+ var _a, _b;
5531
+ const mode = (_a = strategy == null ? void 0 : strategy.mode) != null ? _a : "placeholder";
5532
+ if (mode === "raw") {
5533
+ return true;
5534
+ }
5535
+ if (mode === "placeholder") {
5536
+ return false;
5537
+ }
5538
+ if (mode === "model") {
5539
+ return false;
5540
+ }
5541
+ return ((_b = strategy == null ? void 0 : strategy.capabilities) == null ? void 0 : _b[mediaKind]) === true;
5542
+ }
5543
+ function shouldPassRawContent(contentParts, strategy) {
5544
+ var _a;
5545
+ const mode = (_a = strategy == null ? void 0 : strategy.mode) != null ? _a : "placeholder";
5546
+ if (mode === "raw") {
5547
+ return true;
5548
+ }
5549
+ if (mode === "placeholder") {
5550
+ return false;
5551
+ }
5552
+ if (mode === "model") {
5553
+ return false;
5554
+ }
5555
+ let hasSupportedMediaContent = false;
5556
+ for (const part of contentParts) {
5557
+ const mediaKind = getContentPartMediaKind(part);
5558
+ if (!mediaKind) {
5559
+ continue;
5560
+ }
5561
+ hasSupportedMediaContent = true;
5562
+ if (!shouldPassRawByStrategy(mediaKind, strategy)) {
5563
+ return false;
5564
+ }
5565
+ }
5566
+ return hasSupportedMediaContent;
5567
+ }
5568
+ function formatContentPartPlaceholder(part) {
5569
+ var _a;
5570
+ const contentPart = part;
5571
+ switch (contentPart.type) {
5572
+ case "text":
5573
+ return (_a = contentPart.text) != null ? _a : "";
5574
+ case "image-data":
5575
+ return `[Image: ${contentPart.mediaType}]`;
5576
+ case "image-url":
5577
+ return `[Image URL: ${contentPart.url}]`;
5578
+ case "image-file-id": {
5579
+ const fileId = contentPart.fileId;
5580
+ const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
5581
+ return `[Image ID: ${displayId}]`;
5582
+ }
5583
+ case "file-data": {
5584
+ const filePart = contentPart;
5585
+ if (filePart.filename) {
5586
+ return `[File: ${filePart.filename} (${filePart.mediaType})]`;
5587
+ }
5588
+ return `[File: ${filePart.mediaType}]`;
5589
+ }
5590
+ case "file-url":
5591
+ return `[File URL: ${contentPart.url}]`;
5592
+ case "file-id": {
5593
+ const fileId = contentPart.fileId;
5594
+ const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
5595
+ return `[File ID: ${displayId}]`;
5596
+ }
5597
+ case "media":
5598
+ return `[Media: ${contentPart.mediaType}]`;
5599
+ case "custom":
5600
+ return "[Custom content]";
5601
+ default:
5602
+ return "[Unknown content]";
5603
+ }
3653
5604
  }
3654
-
3655
- // src/core/prompts/tool-response.ts
3656
- function unwrapToolResult(result) {
5605
+ function unwrapToolResult(result, mediaStrategy) {
3657
5606
  var _a, _b;
3658
5607
  switch (result.type) {
3659
5608
  case "text":
@@ -3669,43 +5618,11 @@ function unwrapToolResult(result) {
3669
5618
  case "error-json":
3670
5619
  return `[Error: ${JSON.stringify(result.value)}]`;
3671
5620
  case "content": {
3672
- return result.value.map((part) => {
3673
- var _a2;
3674
- const contentPart = part;
3675
- switch (contentPart.type) {
3676
- case "text":
3677
- return (_a2 = contentPart.text) != null ? _a2 : "";
3678
- case "image-data":
3679
- return `[Image: ${contentPart.mediaType}]`;
3680
- case "image-url":
3681
- return `[Image URL: ${contentPart.url}]`;
3682
- case "image-file-id": {
3683
- const fileId = contentPart.fileId;
3684
- const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
3685
- return `[Image ID: ${displayId}]`;
3686
- }
3687
- case "file-data": {
3688
- const filePart = contentPart;
3689
- if (filePart.filename) {
3690
- return `[File: ${filePart.filename} (${filePart.mediaType})]`;
3691
- }
3692
- return `[File: ${filePart.mediaType}]`;
3693
- }
3694
- case "file-url":
3695
- return `[File URL: ${contentPart.url}]`;
3696
- case "file-id": {
3697
- const fileId = contentPart.fileId;
3698
- const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
3699
- return `[File ID: ${displayId}]`;
3700
- }
3701
- case "media":
3702
- return `[Media: ${contentPart.mediaType}]`;
3703
- case "custom":
3704
- return "[Custom content]";
3705
- default:
3706
- return "[Unknown content]";
3707
- }
3708
- }).join("\n");
5621
+ const parts = result.value;
5622
+ if (shouldPassRawContent(parts, mediaStrategy)) {
5623
+ return parts;
5624
+ }
5625
+ return parts.map(formatContentPartPlaceholder).join("\n");
3709
5626
  }
3710
5627
  default: {
3711
5628
  const _exhaustive = result;
@@ -3713,58 +5630,89 @@ function unwrapToolResult(result) {
3713
5630
  }
3714
5631
  }
3715
5632
  }
3716
- function formatToolResponseAsJsonInXml(toolResult) {
3717
- const unwrappedResult = unwrapToolResult(toolResult.output);
5633
+
5634
+ // src/core/prompts/hermes-prompt.ts
5635
+ function formatToolResponseAsHermesWithOptions(toolResult, options) {
5636
+ const unwrappedResult = unwrapToolResult(
5637
+ toolResult.output,
5638
+ options == null ? void 0 : options.mediaStrategy
5639
+ );
3718
5640
  return `<tool_response>${JSON.stringify({
3719
- toolName: toolResult.toolName,
3720
- result: unwrappedResult
5641
+ name: toolResult.toolName,
5642
+ content: unwrappedResult
3721
5643
  })}</tool_response>`;
3722
5644
  }
3723
- function formatToolResponseAsXml(toolResult) {
3724
- const unwrappedResult = unwrapToolResult(toolResult.output);
3725
- const toolNameXml = `<tool_name>${toolResult.toolName}</tool_name>`;
3726
- const resultLines = formatXmlNode("result", unwrappedResult, 1);
3727
- return [
3728
- "<tool_response>",
3729
- ` ${toolNameXml}`,
3730
- ...resultLines,
3731
- "</tool_response>"
3732
- ].join("\n");
5645
+ function formatToolResponseAsHermes(toolResult) {
5646
+ return formatToolResponseAsHermesWithOptions(toolResult);
3733
5647
  }
3734
- function formatXmlNode(tagName, value, depth) {
3735
- const indent = " ".repeat(depth);
3736
- if (value === null || value === void 0) {
3737
- return [`${indent}<${tagName}></${tagName}>`];
5648
+ function jsonSchemaToPythonType(schema) {
5649
+ const type = schema.type;
5650
+ if (type === "string") {
5651
+ return "str";
3738
5652
  }
3739
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3740
- return [`${indent}<${tagName}>${String(value)}</${tagName}>`];
5653
+ if (type === "number") {
5654
+ return "float";
3741
5655
  }
3742
- if (Array.isArray(value)) {
3743
- if (value.length === 0) {
3744
- return [`${indent}<${tagName}></${tagName}>`];
5656
+ if (type === "integer") {
5657
+ return "int";
5658
+ }
5659
+ if (type === "boolean") {
5660
+ return "bool";
5661
+ }
5662
+ if (type === "array") {
5663
+ const items = schema.items;
5664
+ if (items) {
5665
+ return `list[${jsonSchemaToPythonType(items)}]`;
3745
5666
  }
3746
- const lines2 = [`${indent}<${tagName}>`];
3747
- for (const item of value) {
3748
- lines2.push(...formatXmlNode("item", item, depth + 1));
5667
+ return "list[Any]";
5668
+ }
5669
+ if (type === "object") {
5670
+ const additionalProperties = schema.additionalProperties;
5671
+ if (additionalProperties) {
5672
+ return `dict[str, ${jsonSchemaToPythonType(additionalProperties)}]`;
3749
5673
  }
3750
- lines2.push(`${indent}</${tagName}>`);
3751
- return lines2;
5674
+ return "dict";
3752
5675
  }
3753
- const entries = Object.entries(value);
3754
- if (entries.length === 0) {
3755
- return [`${indent}<${tagName}></${tagName}>`];
5676
+ if (Array.isArray(type)) {
5677
+ return `Union[${type.map((t) => jsonSchemaToPythonType({ type: t })).join(",")}]`;
3756
5678
  }
3757
- const lines = [`${indent}<${tagName}>`];
3758
- for (const [key, entryValue] of entries) {
3759
- lines.push(...formatXmlNode(key, entryValue, depth + 1));
5679
+ return "Any";
5680
+ }
5681
+ function renderToolDefinition(tool) {
5682
+ var _a, _b;
5683
+ const schema = tool.inputSchema;
5684
+ const properties = schema.properties;
5685
+ const paramSignature = properties ? Object.entries(properties).map(([name, field]) => `${name}: ${jsonSchemaToPythonType(field)}`).join(", ") : "";
5686
+ const desc = (_a = tool.description) != null ? _a : "";
5687
+ let description = `${tool.name}(${paramSignature}) - ${desc}
5688
+
5689
+ `;
5690
+ if (properties && Object.keys(properties).length > 0) {
5691
+ description += " Args:\n";
5692
+ for (const [paramName, paramFields] of Object.entries(properties)) {
5693
+ const paramDesc = (_b = paramFields.description) != null ? _b : "";
5694
+ description += ` ${paramName}(${jsonSchemaToPythonType(paramFields)}): ${paramDesc.trim()}
5695
+ `;
5696
+ }
3760
5697
  }
3761
- lines.push(`${indent}</${tagName}>`);
3762
- return lines;
5698
+ const parametersJson = JSON.stringify(schema);
5699
+ const descJson = JSON.stringify(description);
5700
+ const nameJson = JSON.stringify(tool.name);
5701
+ return `{"type": "function", "function": {"name": ${nameJson}, "description": ${descJson}, "parameters": ${parametersJson}}}`;
5702
+ }
5703
+ function hermesSystemPromptTemplate(tools) {
5704
+ const toolsRendered = tools.map(renderToolDefinition).join("\n");
5705
+ return `You are a function calling AI model. You are provided with function signatures within <tools></tools> XML tags. You may call one or more functions to assist with the user query. Don't make assumptions about what values to plug into functions. Here are the available tools: <tools> ${toolsRendered} </tools>
5706
+ Use the following pydantic model json schema for each tool call you will make: {"properties": {"name": {"title": "Name", "type": "string"}, "arguments": {"title": "Arguments", "type": "object"}}, "required": ["name", "arguments"], "title": "FunctionCall", "type": "object"}
5707
+ For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
5708
+ <tool_call>
5709
+ {"name": "<function-name>", "arguments": <args-dict>}
5710
+ </tool_call>`;
3763
5711
  }
3764
5712
 
3765
- // src/core/prompts/xml-system-prompt.ts
5713
+ // src/core/prompts/morph-xml-prompt.ts
3766
5714
  import dedent from "dedent";
3767
- function xmlSystemPromptTemplate(tools) {
5715
+ function morphXmlSystemPromptTemplate(tools) {
3768
5716
  const toolsText = renderToolsForXmlPrompt(tools);
3769
5717
  const header = dedent`
3770
5718
  # Tools
@@ -3988,9 +5936,241 @@ function stripSchemaKeys(value) {
3988
5936
  }
3989
5937
  return value;
3990
5938
  }
5939
+ function formatXmlNode(tagName, value, depth) {
5940
+ const indent = " ".repeat(depth);
5941
+ if (value === null || value === void 0) {
5942
+ return [`${indent}<${tagName}></${tagName}>`];
5943
+ }
5944
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
5945
+ return [`${indent}<${tagName}>${String(value)}</${tagName}>`];
5946
+ }
5947
+ if (Array.isArray(value)) {
5948
+ if (value.length === 0) {
5949
+ return [`${indent}<${tagName}></${tagName}>`];
5950
+ }
5951
+ const lines2 = [`${indent}<${tagName}>`];
5952
+ for (const item of value) {
5953
+ lines2.push(...formatXmlNode("item", item, depth + 1));
5954
+ }
5955
+ lines2.push(`${indent}</${tagName}>`);
5956
+ return lines2;
5957
+ }
5958
+ const entries = Object.entries(value);
5959
+ if (entries.length === 0) {
5960
+ return [`${indent}<${tagName}></${tagName}>`];
5961
+ }
5962
+ const lines = [`${indent}<${tagName}>`];
5963
+ for (const [key, entryValue] of entries) {
5964
+ lines.push(...formatXmlNode(key, entryValue, depth + 1));
5965
+ }
5966
+ lines.push(`${indent}</${tagName}>`);
5967
+ return lines;
5968
+ }
5969
+ function morphFormatToolResponseAsXmlWithOptions(toolResult, options) {
5970
+ const unwrappedResult = unwrapToolResult(
5971
+ toolResult.output,
5972
+ options == null ? void 0 : options.mediaStrategy
5973
+ );
5974
+ const toolNameXml = `<tool_name>${toolResult.toolName}</tool_name>`;
5975
+ const resultLines = formatXmlNode("result", unwrappedResult, 1);
5976
+ return [
5977
+ "<tool_response>",
5978
+ ` ${toolNameXml}`,
5979
+ ...resultLines,
5980
+ "</tool_response>"
5981
+ ].join("\n");
5982
+ }
5983
+ function morphFormatToolResponseAsXml(toolResult) {
5984
+ return morphFormatToolResponseAsXmlWithOptions(toolResult);
5985
+ }
5986
+
5987
+ // src/core/prompts/shared/assistant-tool-calls-to-text.ts
5988
+ function assistantToolCallsToTextContent(options) {
5989
+ var _a, _b;
5990
+ const newContent = [];
5991
+ for (const item of options.content) {
5992
+ switch (item.type) {
5993
+ case "tool-call":
5994
+ newContent.push({
5995
+ type: "text",
5996
+ text: options.protocol.formatToolCall(item)
5997
+ });
5998
+ break;
5999
+ case "text":
6000
+ case "reasoning":
6001
+ newContent.push(item);
6002
+ break;
6003
+ default:
6004
+ (_b = (_a = options.conversionOptions) == null ? void 0 : _a.onError) == null ? void 0 : _b.call(
6005
+ _a,
6006
+ "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
6007
+ { content: item }
6008
+ );
6009
+ newContent.push({
6010
+ type: "text",
6011
+ text: JSON.stringify(item)
6012
+ });
6013
+ }
6014
+ }
6015
+ if (!newContent.every((entry) => entry.type === "text")) {
6016
+ return newContent;
6017
+ }
6018
+ return [
6019
+ {
6020
+ type: "text",
6021
+ text: newContent.map((entry) => entry.text).join("\n")
6022
+ }
6023
+ ];
6024
+ }
6025
+
6026
+ // src/core/prompts/qwen3coder-prompt.ts
6027
+ var QWEN3CODER_TOOL_HEADER = "# Tools\n\nYou have access to the following functions:\n\n";
6028
+ var QWEN3CODER_TOOL_CALL_INSTRUCTIONS = "\n\nIf you choose to call a function ONLY reply in the following format with NO suffix:\n\n<tool_call>\n<function=example_function_name>\n<parameter=example_parameter_1>\nvalue_1\n</parameter>\n<parameter=example_parameter_2>\nThis is the value for the second parameter\nthat can span\nmultiple lines\n</parameter>\n</function>\n</tool_call>\n\n<IMPORTANT>\nReminder:\n- Function calls MUST follow the specified format: an inner <function=...></function> block must be nested within <tool_call></tool_call> XML tags\n- Required parameters MUST be specified\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\n</IMPORTANT>";
6029
+ var XML_PROMPT_TAG_NAME_RE = /^[A-Za-z_][A-Za-z0-9_.-]*$/;
6030
+ function isMapping2(value) {
6031
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6032
+ }
6033
+ function isSequence(value) {
6034
+ return Array.isArray(value);
6035
+ }
6036
+ function toJinjaString(value) {
6037
+ if (value === void 0) {
6038
+ return "";
6039
+ }
6040
+ if (value === null) {
6041
+ return "None";
6042
+ }
6043
+ if (typeof value === "boolean") {
6044
+ return value ? "True" : "False";
6045
+ }
6046
+ return String(value);
6047
+ }
6048
+ function toJinjaTrimmedString(value) {
6049
+ return toJinjaString(value).trim();
6050
+ }
6051
+ function toEscapedXmlText(value) {
6052
+ return escapeXmlMinimalText(toJinjaString(value));
6053
+ }
6054
+ function toEscapedTrimmedXmlText(value) {
6055
+ return escapeXmlMinimalText(toJinjaTrimmedString(value));
6056
+ }
6057
+ function renderXmlPromptField(key, escapedValue) {
6058
+ if (XML_PROMPT_TAG_NAME_RE.test(key)) {
6059
+ return `
6060
+ <${key}>${escapedValue}</${key}>`;
6061
+ }
6062
+ return `
6063
+ <property name="${escapeXmlMinimalAttr(
6064
+ key,
6065
+ '"'
6066
+ )}">${escapedValue}</property>`;
6067
+ }
6068
+ function renderExtraKeys(jsonDict, handledKeys) {
6069
+ if (!isMapping2(jsonDict)) {
6070
+ return "";
6071
+ }
6072
+ const handled = new Set(handledKeys);
6073
+ let out = "";
6074
+ for (const [jsonKey, jsonValue] of Object.entries(jsonDict)) {
6075
+ if (handled.has(jsonKey)) {
6076
+ continue;
6077
+ }
6078
+ const renderedValue = isMapping2(jsonValue) || isSequence(jsonValue) ? JSON.stringify(jsonValue) : toJinjaString(jsonValue);
6079
+ out += renderXmlPromptField(jsonKey, escapeXmlMinimalText(renderedValue));
6080
+ }
6081
+ return out;
6082
+ }
6083
+ function normalizeInputSchema(inputSchema) {
6084
+ if (typeof inputSchema !== "string") {
6085
+ return inputSchema;
6086
+ }
6087
+ try {
6088
+ return JSON.parse(inputSchema);
6089
+ } catch (e) {
6090
+ return inputSchema;
6091
+ }
6092
+ }
6093
+ function normalizeTool(rawTool) {
6094
+ return {
6095
+ name: rawTool.name,
6096
+ description: rawTool.description,
6097
+ parameters: normalizeInputSchema(rawTool.inputSchema)
6098
+ };
6099
+ }
6100
+ function renderParameter(paramName, paramFieldsRaw) {
6101
+ const paramFields = isMapping2(paramFieldsRaw) ? paramFieldsRaw : void 0;
6102
+ let out = "\n<parameter>";
6103
+ out += `
6104
+ <name>${toEscapedXmlText(paramName)}</name>`;
6105
+ if ((paramFields == null ? void 0 : paramFields.type) !== void 0) {
6106
+ out += `
6107
+ <type>${toEscapedXmlText(paramFields.type)}</type>`;
6108
+ }
6109
+ if ((paramFields == null ? void 0 : paramFields.description) !== void 0) {
6110
+ out += `
6111
+ <description>${toEscapedTrimmedXmlText(paramFields.description)}</description>`;
6112
+ }
6113
+ out += renderExtraKeys(paramFieldsRaw, ["name", "type", "description"]);
6114
+ out += "\n</parameter>";
6115
+ return out;
6116
+ }
6117
+ function renderTool(tool) {
6118
+ let out = `
6119
+ <function>
6120
+ <name>${toEscapedXmlText(tool.name)}</name>`;
6121
+ if (tool.description !== void 0) {
6122
+ out += `
6123
+ <description>${toEscapedTrimmedXmlText(tool.description)}</description>`;
6124
+ }
6125
+ out += "\n<parameters>";
6126
+ const parameters = tool.parameters;
6127
+ if (isMapping2(parameters) && isMapping2(parameters.properties)) {
6128
+ for (const [paramName, paramFieldsRaw] of Object.entries(
6129
+ parameters.properties
6130
+ )) {
6131
+ out += renderParameter(paramName, paramFieldsRaw);
6132
+ }
6133
+ }
6134
+ out += renderExtraKeys(parameters, ["type", "properties"]);
6135
+ out += "\n</parameters>";
6136
+ out += renderExtraKeys(tool, ["type", "name", "description", "parameters"]);
6137
+ out += "\n</function>";
6138
+ return out;
6139
+ }
6140
+ function qwen3coderSystemPromptTemplate(tools) {
6141
+ if (!tools.length) {
6142
+ return "";
6143
+ }
6144
+ let out = `${QWEN3CODER_TOOL_HEADER}<tools>`;
6145
+ for (const tool of tools) {
6146
+ out += renderTool(normalizeTool(tool));
6147
+ }
6148
+ out += "\n</tools>";
6149
+ out += QWEN3CODER_TOOL_CALL_INSTRUCTIONS;
6150
+ return out;
6151
+ }
6152
+ function stringifyToolResponseContent(value) {
6153
+ if (typeof value === "string") {
6154
+ return value;
6155
+ }
6156
+ return JSON.stringify(value);
6157
+ }
6158
+ function formatToolResponseAsQwen3CoderXmlWithOptions(toolResult, options) {
6159
+ const unwrappedResult = unwrapToolResult(
6160
+ toolResult.output,
6161
+ options == null ? void 0 : options.mediaStrategy
6162
+ );
6163
+ const content = stringifyToolResponseContent(unwrappedResult);
6164
+ return `<tool_response>
6165
+ ${content}
6166
+ </tool_response>`;
6167
+ }
6168
+ function formatToolResponseAsQwen3CoderXml(toolResult) {
6169
+ return formatToolResponseAsQwen3CoderXmlWithOptions(toolResult);
6170
+ }
3991
6171
 
3992
- // src/core/prompts/yaml-system-prompt.ts
3993
- function yamlSystemPromptTemplate(tools, includeMultilineExample = true) {
6172
+ // src/core/prompts/yaml-xml-prompt.ts
6173
+ function yamlXmlSystemPromptTemplate(tools, includeMultilineExample = true) {
3994
6174
  const toolsJson = JSON.stringify(tools);
3995
6175
  const multilineExample = includeMultilineExample ? `
3996
6176
 
@@ -4029,6 +6209,9 @@ unit: celsius
4029
6209
  - Do NOT ask clarifying questions. Use reasonable defaults for optional parameters.
4030
6210
  - If a task requires multiple function calls, make ALL of them at once.`;
4031
6211
  }
6212
+ function formatToolResponseAsYaml(toolResult) {
6213
+ return morphFormatToolResponseAsXml(toolResult);
6214
+ }
4032
6215
 
4033
6216
  // src/stream-handler.ts
4034
6217
  async function wrapStream({
@@ -4193,8 +6376,75 @@ function normalizeUsage(usage) {
4193
6376
  return ZERO_USAGE;
4194
6377
  }
4195
6378
 
6379
+ // src/core/prompts/shared/tool-role-to-user-message.ts
6380
+ function formatApprovalResponse(part) {
6381
+ const status = part.approved ? "Approved" : "Denied";
6382
+ const reason = part.reason ? `: ${part.reason}` : "";
6383
+ return `[Tool Approval ${status}${reason}]`;
6384
+ }
6385
+ function toTextPart(text) {
6386
+ return {
6387
+ type: "text",
6388
+ text
6389
+ };
6390
+ }
6391
+ function normalizeTemplateResult(result) {
6392
+ if (typeof result === "string") {
6393
+ return [toTextPart(result)];
6394
+ }
6395
+ return result;
6396
+ }
6397
+ function appendSection(target, section) {
6398
+ if (section.length === 0) {
6399
+ return;
6400
+ }
6401
+ if (target.length > 0) {
6402
+ target.push(toTextPart("\n"));
6403
+ }
6404
+ target.push(...section);
6405
+ }
6406
+ function mergeAdjacentTextParts(parts) {
6407
+ const merged = [];
6408
+ for (const part of parts) {
6409
+ const last = merged.at(-1);
6410
+ const canMergeTextParts = part.type === "text" && (last == null ? void 0 : last.type) === "text" && part.providerOptions === void 0 && last.providerOptions === void 0;
6411
+ if (canMergeTextParts) {
6412
+ last.text += part.text;
6413
+ continue;
6414
+ }
6415
+ merged.push(part);
6416
+ }
6417
+ return merged;
6418
+ }
6419
+ function toolRoleContentToUserTextMessage(options) {
6420
+ const toolResultParts = options.toolContent.filter(
6421
+ (part) => part.type === "tool-result"
6422
+ );
6423
+ const approvalResponseParts = options.toolContent.filter(
6424
+ (part) => part.type === "tool-approval-response"
6425
+ );
6426
+ const sections = [];
6427
+ for (const toolResult of toolResultParts) {
6428
+ const result = options.toolResponsePromptTemplate(toolResult);
6429
+ appendSection(sections, normalizeTemplateResult(result));
6430
+ }
6431
+ for (const approvalResponse of approvalResponseParts) {
6432
+ appendSection(sections, [
6433
+ toTextPart(formatApprovalResponse(approvalResponse))
6434
+ ]);
6435
+ }
6436
+ const normalizedSections = sections.length > 0 ? sections : [toTextPart("")];
6437
+ return {
6438
+ role: "user",
6439
+ content: mergeAdjacentTextParts(normalizedSections)
6440
+ };
6441
+ }
6442
+
4196
6443
  // src/transform-handler.ts
4197
6444
  function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
6445
+ if (systemPrompt.trim().length === 0) {
6446
+ return processedPrompt;
6447
+ }
4198
6448
  const systemIndex = processedPrompt.findIndex((m) => m.role === "system");
4199
6449
  if (systemIndex !== -1) {
4200
6450
  const existing = processedPrompt[systemIndex].content;
@@ -4390,94 +6640,30 @@ function transformParams({
4390
6640
  }
4391
6641
  return baseReturnParams;
4392
6642
  }
4393
- function processAssistantContent(content, resolvedProtocol, providerOptions) {
4394
- var _a;
4395
- const newContent = [];
4396
- for (const item of content) {
4397
- switch (item.type) {
4398
- case "tool-call":
4399
- newContent.push({
4400
- type: "text",
4401
- text: resolvedProtocol.formatToolCall(item)
4402
- });
4403
- break;
4404
- case "text":
4405
- case "reasoning":
4406
- newContent.push(item);
4407
- break;
4408
- default: {
4409
- const options = extractOnErrorOption(providerOptions);
4410
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4411
- options,
4412
- "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
4413
- { content: item }
4414
- );
4415
- newContent.push({
4416
- type: "text",
4417
- text: JSON.stringify(item)
4418
- });
4419
- }
4420
- }
4421
- }
4422
- const onlyText = newContent.every((c) => c.type === "text");
4423
- return onlyText ? [
4424
- {
4425
- type: "text",
4426
- text: newContent.map((c) => c.text).join("\n")
4427
- }
4428
- ] : newContent;
4429
- }
4430
- function formatApprovalResponse(part) {
4431
- const status = part.approved ? "Approved" : "Denied";
4432
- const reason = part.reason ? `: ${part.reason}` : "";
4433
- return `[Tool Approval ${status}${reason}]`;
4434
- }
4435
- function processToolMessage(toolResults, approvalResponses, toolResponsePromptTemplate) {
4436
- const resultTexts = toolResults.map((toolResult) => {
4437
- return toolResponsePromptTemplate(toolResult);
4438
- });
4439
- const approvalTexts = approvalResponses.map(formatApprovalResponse);
4440
- const allTexts = [...resultTexts, ...approvalTexts];
4441
- return {
4442
- role: "user",
4443
- content: [
4444
- {
4445
- type: "text",
4446
- text: allTexts.join("\n")
4447
- }
4448
- ]
4449
- };
4450
- }
4451
6643
  function processMessage(message, resolvedProtocol, providerOptions, toolResponsePromptTemplate) {
4452
6644
  if (message.role === "assistant") {
4453
- const condensedContent = processAssistantContent(
4454
- message.content,
4455
- resolvedProtocol,
4456
- providerOptions
4457
- );
6645
+ const condensedContent = assistantToolCallsToTextContent({
6646
+ content: message.content,
6647
+ protocol: resolvedProtocol,
6648
+ conversionOptions: {
6649
+ onError: providerOptions == null ? void 0 : providerOptions.onError
6650
+ }
6651
+ });
4458
6652
  return {
4459
6653
  role: "assistant",
4460
6654
  content: condensedContent
4461
6655
  };
4462
6656
  }
4463
6657
  if (message.role === "tool") {
4464
- const toolContent = message.content;
4465
- const toolResultParts = toolContent.filter(
4466
- (part) => part.type === "tool-result"
4467
- );
4468
- const approvalResponseParts = toolContent.filter(
4469
- (part) => part.type === "tool-approval-response"
4470
- );
4471
6658
  if (!toolResponsePromptTemplate) {
4472
6659
  throw new Error(
4473
6660
  'toolResponsePromptTemplate is required when processing messages with role "tool". This parameter is optional for other roles but is required here so tool-result content can be converted into a prompt. Ensure your middleware or transform configuration passes a toolResponsePromptTemplate when tool message processing is enabled.'
4474
6661
  );
4475
6662
  }
4476
- return processToolMessage(
4477
- toolResultParts,
4478
- approvalResponseParts,
6663
+ return toolRoleContentToUserTextMessage({
6664
+ toolContent: message.content,
4479
6665
  toolResponsePromptTemplate
4480
- );
6666
+ });
4481
6667
  }
4482
6668
  return message;
4483
6669
  }
@@ -4528,6 +6714,9 @@ function mergeConsecutiveUserMessages(processedPrompt) {
4528
6714
  const current = processedPrompt[i];
4529
6715
  const prev = processedPrompt[i - 1];
4530
6716
  if (current.role === "user" && prev.role === "user") {
6717
+ if (!(isAllTextContent(prev.content) && isAllTextContent(current.content))) {
6718
+ continue;
6719
+ }
4531
6720
  const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
4532
6721
  const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
4533
6722
  processedPrompt[i - 1] = {
@@ -4587,19 +6776,24 @@ function createToolMiddleware({
4587
6776
 
4588
6777
  // src/preconfigured-middleware.ts
4589
6778
  var hermesToolMiddleware = createToolMiddleware({
4590
- protocol: jsonProtocol({}),
6779
+ protocol: hermesProtocol(),
4591
6780
  toolSystemPromptTemplate: hermesSystemPromptTemplate,
4592
- toolResponsePromptTemplate: formatToolResponseAsJsonInXml
6781
+ toolResponsePromptTemplate: formatToolResponseAsHermes
6782
+ });
6783
+ var qwen3CoderToolMiddleware = createToolMiddleware({
6784
+ protocol: qwen3CoderProtocol,
6785
+ toolSystemPromptTemplate: qwen3coderSystemPromptTemplate,
6786
+ toolResponsePromptTemplate: formatToolResponseAsQwen3CoderXml
4593
6787
  });
4594
- var xmlToolMiddleware = createToolMiddleware({
4595
- protocol: xmlProtocol({}),
4596
- toolSystemPromptTemplate: xmlSystemPromptTemplate,
4597
- toolResponsePromptTemplate: formatToolResponseAsXml
6788
+ var morphXmlToolMiddleware = createToolMiddleware({
6789
+ protocol: morphXmlProtocol({}),
6790
+ toolSystemPromptTemplate: morphXmlSystemPromptTemplate,
6791
+ toolResponsePromptTemplate: morphFormatToolResponseAsXml
4598
6792
  });
4599
- var yamlToolMiddleware = createToolMiddleware({
4600
- protocol: yamlProtocol({}),
4601
- toolSystemPromptTemplate: yamlSystemPromptTemplate,
4602
- toolResponsePromptTemplate: formatToolResponseAsXml
6793
+ var yamlXmlToolMiddleware = createToolMiddleware({
6794
+ protocol: yamlXmlProtocol({}),
6795
+ toolSystemPromptTemplate: yamlXmlSystemPromptTemplate,
6796
+ toolResponsePromptTemplate: formatToolResponseAsYaml
4603
6797
  });
4604
6798
 
4605
6799
  export {
@@ -4609,11 +6803,14 @@ export {
4609
6803
  logParsedChunk,
4610
6804
  logParsedSummary,
4611
6805
  getPotentialStartIndex,
4612
- jsonProtocol,
6806
+ hermesProtocol,
6807
+ morphXmlProtocol,
4613
6808
  isProtocolFactory,
4614
6809
  isTCMProtocolFactory,
4615
- xmlProtocol,
4616
- yamlProtocol,
6810
+ qwen3CoderProtocol,
6811
+ uiTarsXmlProtocol,
6812
+ Qwen3CoderToolParser,
6813
+ yamlXmlProtocol,
4617
6814
  createDynamicIfThenElseSchema,
4618
6815
  extractOnErrorOption,
4619
6816
  originalToolsSchema,
@@ -4624,12 +6821,14 @@ export {
4624
6821
  isToolResultPart,
4625
6822
  hasInputProperty,
4626
6823
  wrapGenerate,
6824
+ morphFormatToolResponseAsXml,
4627
6825
  wrapStream,
4628
6826
  toolChoiceStream,
4629
6827
  transformParams,
4630
6828
  createToolMiddleware,
4631
6829
  hermesToolMiddleware,
4632
- xmlToolMiddleware,
4633
- yamlToolMiddleware
6830
+ qwen3CoderToolMiddleware,
6831
+ morphXmlToolMiddleware,
6832
+ yamlXmlToolMiddleware
4634
6833
  };
4635
- //# sourceMappingURL=chunk-ERJKQKCR.js.map
6834
+ //# sourceMappingURL=chunk-O6NWVXQD.js.map