@ai-sdk-tool/parser 4.0.1 → 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-76E6H46R.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-DJB4DAZO.js";
16
+ } from "./chunk-GMTE7BY5.js";
14
17
 
15
18
  // src/core/utils/debug.ts
16
19
  var LINE_SPLIT_REGEX = /\r?\n/;
@@ -257,7 +260,7 @@ function createFlushTextHandler(getCurrentTextId, setCurrentTextId, getHasEmitte
257
260
  };
258
261
  }
259
262
 
260
- // src/core/protocols/json-protocol.ts
263
+ // src/core/protocols/hermes-protocol.ts
261
264
  function shouldEmitRawToolCallTextOnError(options) {
262
265
  return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
263
266
  }
@@ -800,7 +803,7 @@ function handlePartialTag(state, controller, toolCallStart, toolCallEnd) {
800
803
  state.buffer = "";
801
804
  }
802
805
  }
803
- var jsonProtocol = ({
806
+ var hermesProtocol = ({
804
807
  toolCallStart = "<tool_call>",
805
808
  toolCallEnd = "</tool_call>"
806
809
  } = {}) => ({
@@ -902,14 +905,6 @@ var jsonProtocol = ({
902
905
  }
903
906
  });
904
907
 
905
- // src/core/protocols/protocol-interface.ts
906
- function isProtocolFactory(protocol) {
907
- return typeof protocol === "function";
908
- }
909
- function isTCMProtocolFactory(protocol) {
910
- return typeof protocol === "function";
911
- }
912
-
913
908
  // src/core/utils/regex-constants.ts
914
909
  var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
915
910
  var WHITESPACE_REGEX = /\s/;
@@ -1012,7 +1007,7 @@ ${body}
1012
1007
  </${rootTag}>`;
1013
1008
  }
1014
1009
 
1015
- // src/core/protocols/xml-protocol.ts
1010
+ // src/core/protocols/morph-xml-protocol.ts
1016
1011
  function getToolSchema(tools, toolName) {
1017
1012
  var _a;
1018
1013
  return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
@@ -1988,7 +1983,7 @@ function findToolCallsWithFallbacks(text, toolNames) {
1988
1983
  }
1989
1984
  return { parseText, toolCalls };
1990
1985
  }
1991
- var xmlProtocol = (protocolOptions) => {
1986
+ var morphXmlProtocol = (protocolOptions) => {
1992
1987
  var _a;
1993
1988
  const parseOptions = {
1994
1989
  repair: true,
@@ -2251,200 +2246,2070 @@ var xmlProtocol = (protocolOptions) => {
2251
2246
  };
2252
2247
  };
2253
2248
 
2254
- // src/core/protocols/yaml-protocol.ts
2255
- import YAML from "yaml";
2256
- function shouldEmitRawToolCallTextOnError3(options) {
2257
- return (options == null ? void 0 : options.emitRawToolCallTextOnError) === true;
2249
+ // src/core/protocols/protocol-interface.ts
2250
+ function isProtocolFactory(protocol) {
2251
+ return typeof protocol === "function";
2258
2252
  }
2259
- var selfClosingTagCache2 = /* @__PURE__ */ new Map();
2260
- function getSelfClosingTagPattern2(toolName) {
2261
- let pattern = selfClosingTagCache2.get(toolName);
2262
- if (!pattern) {
2263
- pattern = new RegExp(`<\\s*${escapeRegExp(toolName)}\\s*/>`, "g");
2264
- selfClosingTagCache2.set(toolName, pattern);
2265
- }
2266
- return pattern;
2253
+ function isTCMProtocolFactory(protocol) {
2254
+ return typeof protocol === "function";
2267
2255
  }
2268
- var LEADING_WHITESPACE_RE = /^(\s*)/;
2269
- var INCOMPLETE_MAPPING_TAIL_RE = /^[^:[\]{}-][^:]*:\s*$/;
2270
- var INCOMPLETE_SEQUENCE_TAIL_RE = /^-\s*$/;
2271
- var BLOCK_SCALAR_KEY_RE = /:\s*[|>][-+0-9]*\s*$/;
2272
- var PLAIN_MAPPING_VALUE_RE = /^[^:[\]{}-][^:]*:\s*(.+)$/;
2273
- var PLAIN_SEQUENCE_VALUE_RE = /^-\s+(.+)$/;
2274
- function normalizeYamlContent(yamlContent) {
2275
- let normalized = yamlContent;
2276
- if (normalized.startsWith("\n")) {
2277
- 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;
2278
2271
  }
2279
- const lines = normalized.split("\n");
2280
- const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
2281
- if (nonEmptyLines.length === 0) {
2282
- 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;
2283
2280
  }
2284
- const minIndent = Math.min(
2285
- ...nonEmptyLines.map((line) => {
2286
- const match = line.match(LEADING_WHITESPACE_RE);
2287
- return match ? match[1].length : 0;
2288
- })
2289
- );
2290
- if (minIndent > 0) {
2291
- 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;
2292
2325
  }
2293
- return { normalized, nonEmptyLines };
2326
+ return i;
2294
2327
  }
2295
- function parseYamlDocumentAsMapping(normalized) {
2296
- try {
2297
- const doc = YAML.parseDocument(normalized);
2298
- const errors = doc.errors.map((e) => e.message);
2299
- const result = doc.toJSON();
2300
- if (result === null) {
2301
- 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;
2302
2336
  }
2303
- if (typeof result !== "object" || Array.isArray(result)) {
2304
- 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;
2305
2346
  }
2306
- return { value: result, errors };
2307
- } catch (error) {
2308
- return {
2309
- value: null,
2310
- errors: [
2311
- error instanceof Error ? error.message : "Unknown YAML parsing error"
2312
- ]
2313
- };
2347
+ out = next;
2314
2348
  }
2315
2349
  }
2316
- function getLastMeaningfulLineInfo(input) {
2350
+ function isTagBoundaryChar(ch) {
2351
+ return ch === "" || isAsciiWhitespace(ch) || ch === ">" || ch === "/";
2352
+ }
2353
+ function findTagEndIndex(text, startIndex) {
2317
2354
  var _a;
2318
- const lines = input.split("\n");
2319
- let index = lines.length - 1;
2320
- while (index >= 0) {
2321
- const raw = (_a = lines[index]) != null ? _a : "";
2322
- const trimmed = raw.trim();
2323
- if (trimmed.length > 0 && !trimmed.startsWith("#")) {
2324
- return {
2325
- index,
2326
- raw,
2327
- trimmed,
2328
- indent: raw.length - raw.trimStart().length
2329
- };
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;
2330
2370
  }
2331
- index -= 1;
2332
2371
  }
2333
2372
  return null;
2334
2373
  }
2335
- function dropLastMeaningfulLine(input) {
2336
- const lineInfo = getLastMeaningfulLineInfo(input);
2337
- 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)) {
2338
2379
  return null;
2339
2380
  }
2340
- 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;
2341
2406
  }
2342
- function hasIncompleteMappingTail(normalized) {
2343
- const lineInfo = getLastMeaningfulLineInfo(normalized);
2344
- if (!lineInfo) {
2345
- return false;
2407
+ function parseQwen3CoderToolParserParamName(openTag, tagNameLower) {
2408
+ const shorthand = parseShorthandValue(openTag, tagNameLower);
2409
+ if (shorthand != null) {
2410
+ return unescapeXml(shorthand);
2346
2411
  }
2347
- return INCOMPLETE_MAPPING_TAIL_RE.test(lineInfo.trimmed);
2412
+ return getAttributeValue(openTag, "name");
2348
2413
  }
2349
- function hasIncompleteSequenceTail(normalized) {
2350
- const lineInfo = getLastMeaningfulLineInfo(normalized);
2351
- if (!lineInfo) {
2352
- return false;
2414
+ function getCdataSectionNextIndex(textLower, startIndex) {
2415
+ if (!textLower.startsWith("<![cdata[", startIndex)) {
2416
+ return startIndex;
2353
2417
  }
2354
- 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;
2355
2423
  }
2356
- function hasSplitNestedKeyTail(normalized) {
2424
+ function parseMatchingTagHeader(textLower, lt, tagNameLower) {
2357
2425
  var _a;
2358
- const lineInfo = getLastMeaningfulLineInfo(normalized);
2359
- if (!lineInfo) {
2360
- 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);
2361
2431
  }
2362
- const { trimmed, indent, index } = lineInfo;
2363
- if (indent === 0) {
2364
- return false;
2432
+ if (!textLower.startsWith(tagNameLower, i)) {
2433
+ return null;
2365
2434
  }
2366
- if (trimmed.startsWith("#") || trimmed.startsWith("-") || trimmed.includes(":")) {
2367
- 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;
2368
2440
  }
2369
- const lines = normalized.split("\n");
2370
- let parentIndex = index - 1;
2371
- while (parentIndex >= 0) {
2372
- const parentRaw = (_a = lines[parentIndex]) != null ? _a : "";
2373
- const parentTrimmed = parentRaw.trim();
2374
- if (parentTrimmed.length === 0 || parentTrimmed.startsWith("#")) {
2375
- 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;
2376
2460
  continue;
2377
2461
  }
2378
- const parentIndent = parentRaw.length - parentRaw.trimStart().length;
2379
- if (parentIndent >= indent) {
2380
- parentIndex -= 1;
2462
+ const header = parseMatchingTagHeader(textLower, lt, tagNameLower);
2463
+ if (!header) {
2464
+ index = lt + 1;
2381
2465
  continue;
2382
2466
  }
2383
- if (!parentTrimmed.endsWith(":")) {
2384
- return false;
2467
+ const gt = textLower.indexOf(">", header.afterName);
2468
+ if (gt === -1) {
2469
+ return null;
2385
2470
  }
2386
- if (BLOCK_SCALAR_KEY_RE.test(parentTrimmed)) {
2387
- 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;
2388
2478
  }
2389
- return true;
2479
+ const isSelfClosing = isSelfClosingXmlTag(textLower, lt, gt);
2480
+ if (!isSelfClosing) {
2481
+ depth += 1;
2482
+ }
2483
+ index = gt + 1;
2390
2484
  }
2391
- return false;
2392
2485
  }
2393
- function extractTrailingPlainScalarValue(line) {
2486
+ function findClosingTagStartWithBoundary(lowerText, valueStart, tagNameLower, allowEndOfStringBoundary) {
2394
2487
  var _a;
2395
- if (BLOCK_SCALAR_KEY_RE.test(line)) {
2396
- 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;
2397
2504
  }
2398
- const mappingMatch = line.match(PLAIN_MAPPING_VALUE_RE);
2399
- const sequenceMatch = line.match(PLAIN_SEQUENCE_VALUE_RE);
2400
- const value = (_a = mappingMatch == null ? void 0 : mappingMatch[1]) != null ? _a : sequenceMatch == null ? void 0 : sequenceMatch[1];
2401
- 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) {
2402
2511
  return null;
2403
2512
  }
2404
- const trimmedValue = value.trim();
2405
- 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) {
2406
2543
  return null;
2407
2544
  }
2408
- if (trimmedValue.startsWith('"') || trimmedValue.startsWith("'")) {
2409
- 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" };
2410
2552
  }
2411
- if (trimmedValue.startsWith("{") || trimmedValue.startsWith("[") || trimmedValue.startsWith("|") || trimmedValue.startsWith(">")) {
2553
+ if (lowerText[i] === "/") {
2412
2554
  return null;
2413
2555
  }
2414
- return trimmedValue;
2415
- }
2416
- function hasUnterminatedPlainScalarTail(normalized) {
2417
- if (normalized.endsWith("\n")) {
2418
- 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;
2419
2563
  }
2420
- const lineInfo = getLastMeaningfulLineInfo(normalized);
2421
- if (!lineInfo) {
2422
- return false;
2564
+ const tagNameLower = lowerText.slice(nameStart, i);
2565
+ if (!QWEN3CODER_TOOL_PARSER_PARAM_TAG_NAMES.has(tagNameLower)) {
2566
+ return null;
2423
2567
  }
2424
- return extractTrailingPlainScalarValue(lineInfo.trimmed) != null;
2425
- }
2426
- function hasUnstableProgressTail(normalized) {
2427
- return hasIncompleteMappingTail(normalized) || hasIncompleteSequenceTail(normalized) || hasSplitNestedKeyTail(normalized) || hasUnterminatedPlainScalarTail(normalized);
2568
+ return { kind: "match", tagNameLower };
2428
2569
  }
2429
- function trimTrailingNewlineInUnknown(value) {
2430
- if (typeof value === "string") {
2431
- if (value.endsWith("\n")) {
2432
- 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
+ };
2433
2586
  }
2434
- 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
+ };
2435
2595
  }
2436
- if (Array.isArray(value)) {
2437
- 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;
2438
2613
  }
2439
- if (value && typeof value === "object") {
2440
- return Object.fromEntries(
2441
- Object.entries(value).map(([key, item]) => [
2442
- key,
2443
- trimTrailingNewlineInUnknown(item)
2444
- ])
2445
- );
2614
+ if (tagNameParse.kind === "partial") {
2615
+ return { kind: "partial", start: startIndex, openEnd: null };
2446
2616
  }
2447
- return value;
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)
4309
+ ])
4310
+ );
4311
+ }
4312
+ return value;
2448
4313
  }
2449
4314
  function stabilizeParsedValueForStreamProgress(value, source) {
2450
4315
  if (source.endsWith("\n")) {
@@ -2452,7 +4317,7 @@ function stabilizeParsedValueForStreamProgress(value, source) {
2452
4317
  }
2453
4318
  return trimTrailingNewlineInUnknown(value);
2454
4319
  }
2455
- function findClosingTagEnd(text, contentStart, toolName) {
4320
+ function findClosingTagEnd2(text, contentStart, toolName) {
2456
4321
  let pos = contentStart;
2457
4322
  let depth = 1;
2458
4323
  while (pos < text.length) {
@@ -2550,7 +4415,7 @@ function collectToolCallsForName(text, toolName) {
2550
4415
  continue;
2551
4416
  }
2552
4417
  const contentStart = tagStart + startTag.length;
2553
- const fullTagEnd = findClosingTagEnd(text, contentStart, toolName);
4418
+ const fullTagEnd = findClosingTagEnd2(text, contentStart, toolName);
2554
4419
  if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
2555
4420
  const endTag = `</${toolName}>`;
2556
4421
  const endTagStart = fullTagEnd - endTag.length;
@@ -2700,7 +4565,7 @@ function stripTrailingPartialCloseTag(content, toolName) {
2700
4565
  )}${preservedLeadingWhitespace}`;
2701
4566
  return contentWithoutPartial.trimEnd();
2702
4567
  }
2703
- var yamlProtocol = (_protocolOptions) => {
4568
+ var yamlXmlProtocol = (_protocolOptions) => {
2704
4569
  return {
2705
4570
  formatTools({ tools, toolSystemPromptTemplate }) {
2706
4571
  return toolSystemPromptTemplate(tools || []);
@@ -2824,7 +4689,7 @@ ${yamlContent}</${toolCall.toolName}>`;
2824
4689
  (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(options, "Could not parse streaming YAML tool call", {
2825
4690
  toolCall: original
2826
4691
  });
2827
- if (shouldEmitRawToolCallTextOnError3(options)) {
4692
+ if (shouldEmitRawToolCallTextOnError4(options)) {
2828
4693
  flushText(controller, original);
2829
4694
  }
2830
4695
  }
@@ -2869,7 +4734,7 @@ ${yamlContent}</${toolCall.toolName}>`;
2869
4734
  "Could not complete streaming YAML tool call at finish.",
2870
4735
  { toolCall: unfinishedContent }
2871
4736
  );
2872
- if (shouldEmitRawToolCallTextOnError3(options)) {
4737
+ if (shouldEmitRawToolCallTextOnError4(options)) {
2873
4738
  flushText(controller, unfinishedContent);
2874
4739
  }
2875
4740
  }
@@ -3410,36 +5275,6 @@ function recoverToolCallFromJsonCandidates(text, tools) {
3410
5275
  return null;
3411
5276
  }
3412
5277
 
3413
- // src/core/utils/tool-call-coercion.ts
3414
- function coerceToolCallInput(toolName, input, tools) {
3415
- var _a;
3416
- let args = {};
3417
- if (typeof input === "string") {
3418
- try {
3419
- args = JSON.parse(input);
3420
- } catch (e) {
3421
- return;
3422
- }
3423
- } else if (input && typeof input === "object") {
3424
- args = input;
3425
- } else {
3426
- return;
3427
- }
3428
- const schema = (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
3429
- const coerced = coerceBySchema(args, schema);
3430
- return JSON.stringify(coerced != null ? coerced : {});
3431
- }
3432
- function coerceToolCallPart(part, tools) {
3433
- const coercedInput = coerceToolCallInput(part.toolName, part.input, tools);
3434
- if (coercedInput === void 0) {
3435
- return part;
3436
- }
3437
- return {
3438
- ...part,
3439
- input: coercedInput
3440
- };
3441
- }
3442
-
3443
5278
  // src/core/utils/tool-choice.ts
3444
5279
  function ensureNonEmptyToolName(name) {
3445
5280
  if (typeof name !== "string") {
@@ -3647,23 +5482,127 @@ async function wrapGenerate({
3647
5482
  };
3648
5483
  }
3649
5484
 
3650
- // src/core/prompts/hermes-system-prompt.ts
3651
- function hermesSystemPromptTemplate(tools) {
3652
- const toolsJson = JSON.stringify(tools);
3653
- return `You are a function calling AI model.
3654
- You are provided with function signatures within <tools></tools> XML tags.
3655
- You may call one or more functions to assist with the user query.
3656
- Don't make assumptions about what values to plug into functions.
3657
- Here are the available tools: <tools>${toolsJson}</tools>
3658
- 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"]}
3659
- For each function call return a json object with function name and arguments within <tool_call></tool_call> XML tags as follows:
3660
- <tool_call>
3661
- {"name": "<function-name>", "arguments": <args-dict>}
3662
- </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
+ }
3663
5604
  }
3664
-
3665
- // src/core/prompts/tool-response.ts
3666
- function unwrapToolResult(result) {
5605
+ function unwrapToolResult(result, mediaStrategy) {
3667
5606
  var _a, _b;
3668
5607
  switch (result.type) {
3669
5608
  case "text":
@@ -3679,43 +5618,11 @@ function unwrapToolResult(result) {
3679
5618
  case "error-json":
3680
5619
  return `[Error: ${JSON.stringify(result.value)}]`;
3681
5620
  case "content": {
3682
- return result.value.map((part) => {
3683
- var _a2;
3684
- const contentPart = part;
3685
- switch (contentPart.type) {
3686
- case "text":
3687
- return (_a2 = contentPart.text) != null ? _a2 : "";
3688
- case "image-data":
3689
- return `[Image: ${contentPart.mediaType}]`;
3690
- case "image-url":
3691
- return `[Image URL: ${contentPart.url}]`;
3692
- case "image-file-id": {
3693
- const fileId = contentPart.fileId;
3694
- const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
3695
- return `[Image ID: ${displayId}]`;
3696
- }
3697
- case "file-data": {
3698
- const filePart = contentPart;
3699
- if (filePart.filename) {
3700
- return `[File: ${filePart.filename} (${filePart.mediaType})]`;
3701
- }
3702
- return `[File: ${filePart.mediaType}]`;
3703
- }
3704
- case "file-url":
3705
- return `[File URL: ${contentPart.url}]`;
3706
- case "file-id": {
3707
- const fileId = contentPart.fileId;
3708
- const displayId = typeof fileId === "string" ? fileId : JSON.stringify(fileId);
3709
- return `[File ID: ${displayId}]`;
3710
- }
3711
- case "media":
3712
- return `[Media: ${contentPart.mediaType}]`;
3713
- case "custom":
3714
- return "[Custom content]";
3715
- default:
3716
- return "[Unknown content]";
3717
- }
3718
- }).join("\n");
5621
+ const parts = result.value;
5622
+ if (shouldPassRawContent(parts, mediaStrategy)) {
5623
+ return parts;
5624
+ }
5625
+ return parts.map(formatContentPartPlaceholder).join("\n");
3719
5626
  }
3720
5627
  default: {
3721
5628
  const _exhaustive = result;
@@ -3723,58 +5630,89 @@ function unwrapToolResult(result) {
3723
5630
  }
3724
5631
  }
3725
5632
  }
3726
- function formatToolResponseAsJsonInXml(toolResult) {
3727
- 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
+ );
3728
5640
  return `<tool_response>${JSON.stringify({
3729
- toolName: toolResult.toolName,
3730
- result: unwrappedResult
5641
+ name: toolResult.toolName,
5642
+ content: unwrappedResult
3731
5643
  })}</tool_response>`;
3732
5644
  }
3733
- function formatToolResponseAsXml(toolResult) {
3734
- const unwrappedResult = unwrapToolResult(toolResult.output);
3735
- const toolNameXml = `<tool_name>${toolResult.toolName}</tool_name>`;
3736
- const resultLines = formatXmlNode("result", unwrappedResult, 1);
3737
- return [
3738
- "<tool_response>",
3739
- ` ${toolNameXml}`,
3740
- ...resultLines,
3741
- "</tool_response>"
3742
- ].join("\n");
5645
+ function formatToolResponseAsHermes(toolResult) {
5646
+ return formatToolResponseAsHermesWithOptions(toolResult);
3743
5647
  }
3744
- function formatXmlNode(tagName, value, depth) {
3745
- const indent = " ".repeat(depth);
3746
- if (value === null || value === void 0) {
3747
- return [`${indent}<${tagName}></${tagName}>`];
5648
+ function jsonSchemaToPythonType(schema) {
5649
+ const type = schema.type;
5650
+ if (type === "string") {
5651
+ return "str";
3748
5652
  }
3749
- if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
3750
- return [`${indent}<${tagName}>${String(value)}</${tagName}>`];
5653
+ if (type === "number") {
5654
+ return "float";
3751
5655
  }
3752
- if (Array.isArray(value)) {
3753
- if (value.length === 0) {
3754
- 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)}]`;
3755
5666
  }
3756
- const lines2 = [`${indent}<${tagName}>`];
3757
- for (const item of value) {
3758
- 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)}]`;
3759
5673
  }
3760
- lines2.push(`${indent}</${tagName}>`);
3761
- return lines2;
5674
+ return "dict";
3762
5675
  }
3763
- const entries = Object.entries(value);
3764
- if (entries.length === 0) {
3765
- return [`${indent}<${tagName}></${tagName}>`];
5676
+ if (Array.isArray(type)) {
5677
+ return `Union[${type.map((t) => jsonSchemaToPythonType({ type: t })).join(",")}]`;
3766
5678
  }
3767
- const lines = [`${indent}<${tagName}>`];
3768
- for (const [key, entryValue] of entries) {
3769
- 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
+ }
3770
5697
  }
3771
- lines.push(`${indent}</${tagName}>`);
3772
- 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>`;
3773
5711
  }
3774
5712
 
3775
- // src/core/prompts/xml-system-prompt.ts
5713
+ // src/core/prompts/morph-xml-prompt.ts
3776
5714
  import dedent from "dedent";
3777
- function xmlSystemPromptTemplate(tools) {
5715
+ function morphXmlSystemPromptTemplate(tools) {
3778
5716
  const toolsText = renderToolsForXmlPrompt(tools);
3779
5717
  const header = dedent`
3780
5718
  # Tools
@@ -3998,9 +5936,241 @@ function stripSchemaKeys(value) {
3998
5936
  }
3999
5937
  return value;
4000
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
+ }
4001
6171
 
4002
- // src/core/prompts/yaml-system-prompt.ts
4003
- function yamlSystemPromptTemplate(tools, includeMultilineExample = true) {
6172
+ // src/core/prompts/yaml-xml-prompt.ts
6173
+ function yamlXmlSystemPromptTemplate(tools, includeMultilineExample = true) {
4004
6174
  const toolsJson = JSON.stringify(tools);
4005
6175
  const multilineExample = includeMultilineExample ? `
4006
6176
 
@@ -4039,6 +6209,9 @@ unit: celsius
4039
6209
  - Do NOT ask clarifying questions. Use reasonable defaults for optional parameters.
4040
6210
  - If a task requires multiple function calls, make ALL of them at once.`;
4041
6211
  }
6212
+ function formatToolResponseAsYaml(toolResult) {
6213
+ return morphFormatToolResponseAsXml(toolResult);
6214
+ }
4042
6215
 
4043
6216
  // src/stream-handler.ts
4044
6217
  async function wrapStream({
@@ -4203,8 +6376,75 @@ function normalizeUsage(usage) {
4203
6376
  return ZERO_USAGE;
4204
6377
  }
4205
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
+
4206
6443
  // src/transform-handler.ts
4207
6444
  function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
6445
+ if (systemPrompt.trim().length === 0) {
6446
+ return processedPrompt;
6447
+ }
4208
6448
  const systemIndex = processedPrompt.findIndex((m) => m.role === "system");
4209
6449
  if (systemIndex !== -1) {
4210
6450
  const existing = processedPrompt[systemIndex].content;
@@ -4400,94 +6640,30 @@ function transformParams({
4400
6640
  }
4401
6641
  return baseReturnParams;
4402
6642
  }
4403
- function processAssistantContent(content, resolvedProtocol, providerOptions) {
4404
- var _a;
4405
- const newContent = [];
4406
- for (const item of content) {
4407
- switch (item.type) {
4408
- case "tool-call":
4409
- newContent.push({
4410
- type: "text",
4411
- text: resolvedProtocol.formatToolCall(item)
4412
- });
4413
- break;
4414
- case "text":
4415
- case "reasoning":
4416
- newContent.push(item);
4417
- break;
4418
- default: {
4419
- const options = extractOnErrorOption(providerOptions);
4420
- (_a = options == null ? void 0 : options.onError) == null ? void 0 : _a.call(
4421
- options,
4422
- "tool-call-middleware: unknown assistant content; stringifying for provider compatibility",
4423
- { content: item }
4424
- );
4425
- newContent.push({
4426
- type: "text",
4427
- text: JSON.stringify(item)
4428
- });
4429
- }
4430
- }
4431
- }
4432
- const onlyText = newContent.every((c) => c.type === "text");
4433
- return onlyText ? [
4434
- {
4435
- type: "text",
4436
- text: newContent.map((c) => c.text).join("\n")
4437
- }
4438
- ] : newContent;
4439
- }
4440
- function formatApprovalResponse(part) {
4441
- const status = part.approved ? "Approved" : "Denied";
4442
- const reason = part.reason ? `: ${part.reason}` : "";
4443
- return `[Tool Approval ${status}${reason}]`;
4444
- }
4445
- function processToolMessage(toolResults, approvalResponses, toolResponsePromptTemplate) {
4446
- const resultTexts = toolResults.map((toolResult) => {
4447
- return toolResponsePromptTemplate(toolResult);
4448
- });
4449
- const approvalTexts = approvalResponses.map(formatApprovalResponse);
4450
- const allTexts = [...resultTexts, ...approvalTexts];
4451
- return {
4452
- role: "user",
4453
- content: [
4454
- {
4455
- type: "text",
4456
- text: allTexts.join("\n")
4457
- }
4458
- ]
4459
- };
4460
- }
4461
6643
  function processMessage(message, resolvedProtocol, providerOptions, toolResponsePromptTemplate) {
4462
6644
  if (message.role === "assistant") {
4463
- const condensedContent = processAssistantContent(
4464
- message.content,
4465
- resolvedProtocol,
4466
- providerOptions
4467
- );
6645
+ const condensedContent = assistantToolCallsToTextContent({
6646
+ content: message.content,
6647
+ protocol: resolvedProtocol,
6648
+ conversionOptions: {
6649
+ onError: providerOptions == null ? void 0 : providerOptions.onError
6650
+ }
6651
+ });
4468
6652
  return {
4469
6653
  role: "assistant",
4470
6654
  content: condensedContent
4471
6655
  };
4472
6656
  }
4473
6657
  if (message.role === "tool") {
4474
- const toolContent = message.content;
4475
- const toolResultParts = toolContent.filter(
4476
- (part) => part.type === "tool-result"
4477
- );
4478
- const approvalResponseParts = toolContent.filter(
4479
- (part) => part.type === "tool-approval-response"
4480
- );
4481
6658
  if (!toolResponsePromptTemplate) {
4482
6659
  throw new Error(
4483
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.'
4484
6661
  );
4485
6662
  }
4486
- return processToolMessage(
4487
- toolResultParts,
4488
- approvalResponseParts,
6663
+ return toolRoleContentToUserTextMessage({
6664
+ toolContent: message.content,
4489
6665
  toolResponsePromptTemplate
4490
- );
6666
+ });
4491
6667
  }
4492
6668
  return message;
4493
6669
  }
@@ -4538,6 +6714,9 @@ function mergeConsecutiveUserMessages(processedPrompt) {
4538
6714
  const current = processedPrompt[i];
4539
6715
  const prev = processedPrompt[i - 1];
4540
6716
  if (current.role === "user" && prev.role === "user") {
6717
+ if (!(isAllTextContent(prev.content) && isAllTextContent(current.content))) {
6718
+ continue;
6719
+ }
4541
6720
  const prevContent = prev.content.map((c) => c.type === "text" ? c.text : "").join("\n");
4542
6721
  const currentContent = current.content.map((c) => c.type === "text" ? c.text : "").join("\n");
4543
6722
  processedPrompt[i - 1] = {
@@ -4597,19 +6776,24 @@ function createToolMiddleware({
4597
6776
 
4598
6777
  // src/preconfigured-middleware.ts
4599
6778
  var hermesToolMiddleware = createToolMiddleware({
4600
- protocol: jsonProtocol({}),
6779
+ protocol: hermesProtocol(),
4601
6780
  toolSystemPromptTemplate: hermesSystemPromptTemplate,
4602
- toolResponsePromptTemplate: formatToolResponseAsJsonInXml
6781
+ toolResponsePromptTemplate: formatToolResponseAsHermes
6782
+ });
6783
+ var qwen3CoderToolMiddleware = createToolMiddleware({
6784
+ protocol: qwen3CoderProtocol,
6785
+ toolSystemPromptTemplate: qwen3coderSystemPromptTemplate,
6786
+ toolResponsePromptTemplate: formatToolResponseAsQwen3CoderXml
4603
6787
  });
4604
- var xmlToolMiddleware = createToolMiddleware({
4605
- protocol: xmlProtocol({}),
4606
- toolSystemPromptTemplate: xmlSystemPromptTemplate,
4607
- toolResponsePromptTemplate: formatToolResponseAsXml
6788
+ var morphXmlToolMiddleware = createToolMiddleware({
6789
+ protocol: morphXmlProtocol({}),
6790
+ toolSystemPromptTemplate: morphXmlSystemPromptTemplate,
6791
+ toolResponsePromptTemplate: morphFormatToolResponseAsXml
4608
6792
  });
4609
- var yamlToolMiddleware = createToolMiddleware({
4610
- protocol: yamlProtocol({}),
4611
- toolSystemPromptTemplate: yamlSystemPromptTemplate,
4612
- toolResponsePromptTemplate: formatToolResponseAsXml
6793
+ var yamlXmlToolMiddleware = createToolMiddleware({
6794
+ protocol: yamlXmlProtocol({}),
6795
+ toolSystemPromptTemplate: yamlXmlSystemPromptTemplate,
6796
+ toolResponsePromptTemplate: formatToolResponseAsYaml
4613
6797
  });
4614
6798
 
4615
6799
  export {
@@ -4619,11 +6803,14 @@ export {
4619
6803
  logParsedChunk,
4620
6804
  logParsedSummary,
4621
6805
  getPotentialStartIndex,
4622
- jsonProtocol,
6806
+ hermesProtocol,
6807
+ morphXmlProtocol,
4623
6808
  isProtocolFactory,
4624
6809
  isTCMProtocolFactory,
4625
- xmlProtocol,
4626
- yamlProtocol,
6810
+ qwen3CoderProtocol,
6811
+ uiTarsXmlProtocol,
6812
+ Qwen3CoderToolParser,
6813
+ yamlXmlProtocol,
4627
6814
  createDynamicIfThenElseSchema,
4628
6815
  extractOnErrorOption,
4629
6816
  originalToolsSchema,
@@ -4634,12 +6821,14 @@ export {
4634
6821
  isToolResultPart,
4635
6822
  hasInputProperty,
4636
6823
  wrapGenerate,
6824
+ morphFormatToolResponseAsXml,
4637
6825
  wrapStream,
4638
6826
  toolChoiceStream,
4639
6827
  transformParams,
4640
6828
  createToolMiddleware,
4641
6829
  hermesToolMiddleware,
4642
- xmlToolMiddleware,
4643
- yamlToolMiddleware
6830
+ qwen3CoderToolMiddleware,
6831
+ morphXmlToolMiddleware,
6832
+ yamlXmlToolMiddleware
4644
6833
  };
4645
- //# sourceMappingURL=chunk-DPGORNPB.js.map
6834
+ //# sourceMappingURL=chunk-O6NWVXQD.js.map