@ai-sdk-tool/parser 3.0.0-canary.0 → 3.0.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-FOANBZRH.js → chunk-L4X363EL.js} +889 -235
- package/dist/chunk-L4X363EL.js.map +1 -0
- package/dist/community.cjs +873 -240
- package/dist/community.cjs.map +1 -1
- package/dist/community.js +2 -2
- package/dist/community.js.map +1 -1
- package/dist/index.cjs +881 -220
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -22
- package/dist/index.d.ts +21 -22
- package/dist/index.js +3 -3
- package/package.json +23 -16
- package/dist/chunk-FOANBZRH.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
-
RJSON: () => robust_json_exports,
|
|
24
23
|
createDynamicIfThenElseSchema: () => createDynamicIfThenElseSchema,
|
|
25
24
|
createToolMiddleware: () => createToolMiddleware,
|
|
26
25
|
decodeOriginalTools: () => decodeOriginalTools,
|
|
@@ -37,6 +36,7 @@ __export(src_exports, {
|
|
|
37
36
|
isToolChoiceActive: () => isToolChoiceActive,
|
|
38
37
|
isToolResultPart: () => isToolResultPart,
|
|
39
38
|
jsonMixProtocol: () => jsonMixProtocol,
|
|
39
|
+
logParseFailure: () => logParseFailure,
|
|
40
40
|
logParsedChunk: () => logParsedChunk,
|
|
41
41
|
logParsedSummary: () => logParsedSummary,
|
|
42
42
|
logRawChunk: () => logRawChunk,
|
|
@@ -49,11 +49,8 @@ __export(src_exports, {
|
|
|
49
49
|
});
|
|
50
50
|
module.exports = __toCommonJS(src_exports);
|
|
51
51
|
|
|
52
|
-
// src/protocols/dummy-protocol.ts
|
|
53
|
-
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
54
|
-
|
|
55
52
|
// src/protocols/json-mix-protocol.ts
|
|
56
|
-
var
|
|
53
|
+
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
57
54
|
|
|
58
55
|
// src/utils/debug.ts
|
|
59
56
|
var LINE_SPLIT_REGEX = /\r?\n/;
|
|
@@ -101,6 +98,7 @@ var cBgGreen = color(ANSI_BG_GREEN);
|
|
|
101
98
|
var cInverse = color(ANSI_INVERSE);
|
|
102
99
|
var cUnderline = color(ANSI_UNDERLINE);
|
|
103
100
|
var cBold = color(ANSI_BOLD);
|
|
101
|
+
var MAX_SNIPPET_LENGTH = 800;
|
|
104
102
|
function safeStringify(value) {
|
|
105
103
|
try {
|
|
106
104
|
return `
|
|
@@ -109,6 +107,41 @@ ${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
|
|
|
109
107
|
return String(value);
|
|
110
108
|
}
|
|
111
109
|
}
|
|
110
|
+
function formatError(error) {
|
|
111
|
+
if (error instanceof Error) {
|
|
112
|
+
const stack = error.stack ? `
|
|
113
|
+
${error.stack}` : "";
|
|
114
|
+
return `
|
|
115
|
+
${error.name}: ${error.message}${stack}`;
|
|
116
|
+
}
|
|
117
|
+
return safeStringify(error);
|
|
118
|
+
}
|
|
119
|
+
function truncateSnippet(snippet) {
|
|
120
|
+
if (snippet.length <= MAX_SNIPPET_LENGTH) {
|
|
121
|
+
return snippet;
|
|
122
|
+
}
|
|
123
|
+
return `${snippet.slice(0, MAX_SNIPPET_LENGTH)}
|
|
124
|
+
\u2026[truncated ${snippet.length - MAX_SNIPPET_LENGTH} chars]`;
|
|
125
|
+
}
|
|
126
|
+
function logParseFailure({
|
|
127
|
+
phase,
|
|
128
|
+
reason,
|
|
129
|
+
snippet,
|
|
130
|
+
error
|
|
131
|
+
}) {
|
|
132
|
+
if (getDebugLevel() !== "parse") {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const label = cBgBlue(`[${phase}]`);
|
|
136
|
+
console.log(cGray("[debug:mw:fail]"), label, cYellow(reason));
|
|
137
|
+
if (snippet) {
|
|
138
|
+
const formatted = truncateSnippet(snippet);
|
|
139
|
+
console.log(cGray("[debug:mw:fail:snippet]"), formatted);
|
|
140
|
+
}
|
|
141
|
+
if (error) {
|
|
142
|
+
console.log(cGray("[debug:mw:fail:error]"), cCyan(formatError(error)));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
112
145
|
function logRawChunk(part) {
|
|
113
146
|
console.log(cGray("[debug:mw:raw]"), cYellow(safeStringify(part)));
|
|
114
147
|
}
|
|
@@ -174,63 +207,6 @@ ${rendered}`);
|
|
|
174
207
|
}
|
|
175
208
|
}
|
|
176
209
|
|
|
177
|
-
// src/utils/dynamic-tool-schema.ts
|
|
178
|
-
function createDynamicIfThenElseSchema(tools) {
|
|
179
|
-
let currentSchema = {};
|
|
180
|
-
const toolNames = [];
|
|
181
|
-
for (let i = tools.length - 1; i >= 0; i -= 1) {
|
|
182
|
-
const tool = tools[i];
|
|
183
|
-
if (tool.type === "provider-defined") {
|
|
184
|
-
throw new Error(
|
|
185
|
-
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
186
|
-
);
|
|
187
|
-
}
|
|
188
|
-
toolNames.unshift(tool.name);
|
|
189
|
-
const toolCondition = {
|
|
190
|
-
if: {
|
|
191
|
-
properties: {
|
|
192
|
-
name: {
|
|
193
|
-
const: tool.name
|
|
194
|
-
}
|
|
195
|
-
},
|
|
196
|
-
required: ["name"]
|
|
197
|
-
},
|
|
198
|
-
// biome-ignore lint/suspicious/noThenProperty: JSON Schema uses 'then' as a keyword
|
|
199
|
-
then: {
|
|
200
|
-
properties: {
|
|
201
|
-
name: {
|
|
202
|
-
const: tool.name
|
|
203
|
-
},
|
|
204
|
-
arguments: tool.inputSchema
|
|
205
|
-
},
|
|
206
|
-
required: ["name", "arguments"]
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
if (Object.keys(currentSchema).length > 0) {
|
|
210
|
-
toolCondition.else = currentSchema;
|
|
211
|
-
}
|
|
212
|
-
currentSchema = toolCondition;
|
|
213
|
-
}
|
|
214
|
-
return {
|
|
215
|
-
type: "object",
|
|
216
|
-
// Explicitly specify type as "object"
|
|
217
|
-
properties: {
|
|
218
|
-
name: {
|
|
219
|
-
type: "string",
|
|
220
|
-
description: "Name of the tool to call",
|
|
221
|
-
enum: toolNames
|
|
222
|
-
},
|
|
223
|
-
arguments: {
|
|
224
|
-
type: "object",
|
|
225
|
-
// By default, arguments is also specified as object type
|
|
226
|
-
description: "Argument object to be passed to the tool"
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
required: ["name", "arguments"],
|
|
230
|
-
...currentSchema
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
|
|
234
210
|
// src/utils/get-potential-start-index.ts
|
|
235
211
|
function getPotentialStartIndex(text, searchedText) {
|
|
236
212
|
if (searchedText.length === 0) {
|
|
@@ -249,60 +225,12 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
249
225
|
return null;
|
|
250
226
|
}
|
|
251
227
|
|
|
252
|
-
// src/utils/on-error.ts
|
|
253
|
-
function extractOnErrorOption(providerOptions) {
|
|
254
|
-
var _a;
|
|
255
|
-
if (providerOptions && typeof providerOptions === "object") {
|
|
256
|
-
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
257
|
-
return onError ? { onError } : void 0;
|
|
258
|
-
}
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// src/utils/provider-options.ts
|
|
263
|
-
var originalToolsSchema = {
|
|
264
|
-
encode: encodeOriginalTools,
|
|
265
|
-
decode: decodeOriginalTools
|
|
266
|
-
};
|
|
267
|
-
function encodeOriginalTools(tools) {
|
|
268
|
-
return (tools == null ? void 0 : tools.map((t) => ({
|
|
269
|
-
name: t.name,
|
|
270
|
-
inputSchema: JSON.stringify(t.inputSchema)
|
|
271
|
-
}))) || [];
|
|
272
|
-
}
|
|
273
|
-
function decodeOriginalTools(originalTools) {
|
|
274
|
-
if (!originalTools) {
|
|
275
|
-
return [];
|
|
276
|
-
}
|
|
277
|
-
return originalTools.map(
|
|
278
|
-
(t) => ({
|
|
279
|
-
type: "function",
|
|
280
|
-
name: t.name,
|
|
281
|
-
inputSchema: JSON.parse(t.inputSchema)
|
|
282
|
-
})
|
|
283
|
-
);
|
|
284
|
-
}
|
|
285
|
-
function extractToolNamesFromOriginalTools(originalTools) {
|
|
286
|
-
return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
|
|
287
|
-
}
|
|
288
|
-
function isToolChoiceActive(params) {
|
|
289
|
-
var _a, _b, _c;
|
|
290
|
-
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
291
|
-
return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
|
|
292
|
-
}
|
|
293
|
-
|
|
294
228
|
// src/utils/regex.ts
|
|
295
229
|
function escapeRegExp(literal) {
|
|
296
230
|
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
297
231
|
}
|
|
298
232
|
|
|
299
233
|
// src/utils/robust-json.ts
|
|
300
|
-
var robust_json_exports = {};
|
|
301
|
-
__export(robust_json_exports, {
|
|
302
|
-
parse: () => parse,
|
|
303
|
-
stringify: () => stringify,
|
|
304
|
-
transform: () => transform
|
|
305
|
-
});
|
|
306
234
|
var WHITESPACE_TEST_REGEX = /\s/;
|
|
307
235
|
var WHITESPACE_REGEX = /^\s+/;
|
|
308
236
|
var OBJECT_START_REGEX = /^\{/;
|
|
@@ -967,19 +895,6 @@ function stringify(obj) {
|
|
|
967
895
|
return "null";
|
|
968
896
|
}
|
|
969
897
|
|
|
970
|
-
// src/utils/type-guards.ts
|
|
971
|
-
function isToolCallContent(content) {
|
|
972
|
-
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
973
|
-
(typeof content.input === "string" || typeof content.input === "object");
|
|
974
|
-
}
|
|
975
|
-
function isToolResultPart(content) {
|
|
976
|
-
const c = content;
|
|
977
|
-
return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
|
|
978
|
-
}
|
|
979
|
-
function hasInputProperty(obj) {
|
|
980
|
-
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
981
|
-
}
|
|
982
|
-
|
|
983
898
|
// src/protocols/json-mix-protocol.ts
|
|
984
899
|
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
985
900
|
var _a;
|
|
@@ -987,11 +902,17 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
|
|
|
987
902
|
const parsedToolCall = parse(toolCallJson);
|
|
988
903
|
processedElements.push({
|
|
989
904
|
type: "tool-call",
|
|
990
|
-
toolCallId: (0,
|
|
905
|
+
toolCallId: (0, import_provider_utils.generateId)(),
|
|
991
906
|
toolName: parsedToolCall.name,
|
|
992
907
|
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
993
908
|
});
|
|
994
909
|
} catch (error) {
|
|
910
|
+
logParseFailure({
|
|
911
|
+
phase: "generated-text",
|
|
912
|
+
reason: "Failed to parse tool call JSON segment",
|
|
913
|
+
snippet: fullMatch,
|
|
914
|
+
error
|
|
915
|
+
});
|
|
995
916
|
if (options == null ? void 0 : options.onError) {
|
|
996
917
|
options.onError(
|
|
997
918
|
"Could not process JSON tool call, keeping original text.",
|
|
@@ -1024,7 +945,7 @@ function flushBuffer(state, controller, toolCallStart) {
|
|
|
1024
945
|
return;
|
|
1025
946
|
}
|
|
1026
947
|
if (!state.currentTextId) {
|
|
1027
|
-
state.currentTextId = (0,
|
|
948
|
+
state.currentTextId = (0, import_provider_utils.generateId)();
|
|
1028
949
|
controller.enqueue({ type: "text-start", id: state.currentTextId });
|
|
1029
950
|
state.hasEmittedTextStart = true;
|
|
1030
951
|
}
|
|
@@ -1047,7 +968,12 @@ function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
|
1047
968
|
if (!state.currentToolCallJson) {
|
|
1048
969
|
return;
|
|
1049
970
|
}
|
|
1050
|
-
|
|
971
|
+
logParseFailure({
|
|
972
|
+
phase: "stream",
|
|
973
|
+
reason: "Incomplete streaming tool call segment emitted as text",
|
|
974
|
+
snippet: `${toolCallStart}${state.currentToolCallJson}`
|
|
975
|
+
});
|
|
976
|
+
const errorId = (0, import_provider_utils.generateId)();
|
|
1051
977
|
controller.enqueue({ type: "text-start", id: errorId });
|
|
1052
978
|
controller.enqueue({
|
|
1053
979
|
type: "text-delta",
|
|
@@ -1071,7 +997,7 @@ function publishText(text, state, controller) {
|
|
|
1071
997
|
state.currentToolCallJson += text;
|
|
1072
998
|
} else if (text.length > 0) {
|
|
1073
999
|
if (!state.currentTextId) {
|
|
1074
|
-
state.currentTextId = (0,
|
|
1000
|
+
state.currentTextId = (0, import_provider_utils.generateId)();
|
|
1075
1001
|
controller.enqueue({ type: "text-start", id: state.currentTextId });
|
|
1076
1002
|
state.hasEmittedTextStart = true;
|
|
1077
1003
|
}
|
|
@@ -1086,16 +1012,22 @@ function emitToolCall(context) {
|
|
|
1086
1012
|
var _a;
|
|
1087
1013
|
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
1088
1014
|
try {
|
|
1089
|
-
const parsedToolCall =
|
|
1015
|
+
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1090
1016
|
closeTextBlock(state, controller);
|
|
1091
1017
|
controller.enqueue({
|
|
1092
1018
|
type: "tool-call",
|
|
1093
|
-
toolCallId: (0,
|
|
1019
|
+
toolCallId: (0, import_provider_utils.generateId)(),
|
|
1094
1020
|
toolName: parsedToolCall.name,
|
|
1095
1021
|
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1096
1022
|
});
|
|
1097
|
-
} catch (
|
|
1098
|
-
|
|
1023
|
+
} catch (error) {
|
|
1024
|
+
logParseFailure({
|
|
1025
|
+
phase: "stream",
|
|
1026
|
+
reason: "Failed to parse streaming tool call JSON segment",
|
|
1027
|
+
snippet: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`,
|
|
1028
|
+
error
|
|
1029
|
+
});
|
|
1030
|
+
const errorId = (0, import_provider_utils.generateId)();
|
|
1099
1031
|
controller.enqueue({ type: "text-start", id: errorId });
|
|
1100
1032
|
controller.enqueue({
|
|
1101
1033
|
type: "text-delta",
|
|
@@ -1260,9 +1192,340 @@ var jsonMixProtocol = ({
|
|
|
1260
1192
|
});
|
|
1261
1193
|
|
|
1262
1194
|
// src/protocols/morph-xml-protocol.ts
|
|
1263
|
-
var
|
|
1195
|
+
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
1264
1196
|
var import_rxml = require("@ai-sdk-tool/rxml");
|
|
1197
|
+
|
|
1198
|
+
// src/utils/type-guards.ts
|
|
1199
|
+
function isToolCallContent(content) {
|
|
1200
|
+
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
1201
|
+
(typeof content.input === "string" || typeof content.input === "object");
|
|
1202
|
+
}
|
|
1203
|
+
function isToolResultPart(content) {
|
|
1204
|
+
const c = content;
|
|
1205
|
+
return !!c && c.type === "tool-result" && typeof c.toolName === "string" && typeof c.toolCallId === "string" && "output" in c;
|
|
1206
|
+
}
|
|
1207
|
+
function hasInputProperty(obj) {
|
|
1208
|
+
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
// src/protocols/morph-xml-protocol.ts
|
|
1265
1212
|
var WHITESPACE_REGEX2 = /\s/;
|
|
1213
|
+
var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
|
|
1214
|
+
var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
|
|
1215
|
+
var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
|
|
1216
|
+
var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
|
|
1217
|
+
var STEP_TAG_RE = /<step>([\s\S]*?)<\/step>/i;
|
|
1218
|
+
var STATUS_TAG_RE = /<status>([\s\S]*?)<\/status>/i;
|
|
1219
|
+
function normalizeCloseTags(xml) {
|
|
1220
|
+
return xml.replace(MALFORMED_CLOSE_RE_G, "</$1>");
|
|
1221
|
+
}
|
|
1222
|
+
function escapeInvalidLt(xml) {
|
|
1223
|
+
const len = xml.length;
|
|
1224
|
+
let out = "";
|
|
1225
|
+
for (let i = 0; i < len; i += 1) {
|
|
1226
|
+
const ch = xml[i];
|
|
1227
|
+
if (ch === "<") {
|
|
1228
|
+
const next = i + 1 < len ? xml[i + 1] : "";
|
|
1229
|
+
if (!(NAME_CHAR_RE.test(next) || next === "/" || next === "!" || next === "?")) {
|
|
1230
|
+
out += "<";
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
out += ch;
|
|
1235
|
+
}
|
|
1236
|
+
return out;
|
|
1237
|
+
}
|
|
1238
|
+
function shouldDeduplicateStringTags(schema) {
|
|
1239
|
+
const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
|
|
1240
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
1241
|
+
return false;
|
|
1242
|
+
}
|
|
1243
|
+
const props = unwrapped.properties;
|
|
1244
|
+
if (!props) {
|
|
1245
|
+
return false;
|
|
1246
|
+
}
|
|
1247
|
+
const commandRaw = props.command;
|
|
1248
|
+
if (!commandRaw) {
|
|
1249
|
+
return false;
|
|
1250
|
+
}
|
|
1251
|
+
const command = (0, import_rxml.unwrapJsonSchema)(commandRaw);
|
|
1252
|
+
return (command == null ? void 0 : command.type) === "array";
|
|
1253
|
+
}
|
|
1254
|
+
function tryParseSecondaryXml(content, toolSchema, options) {
|
|
1255
|
+
const normalized = normalizeCloseTags(content);
|
|
1256
|
+
const balanced = balanceTags(content);
|
|
1257
|
+
const hasMalformedClose = MALFORMED_CLOSE_RE.test(content);
|
|
1258
|
+
if (!hasMalformedClose && balanced.length > normalized.length) {
|
|
1259
|
+
return null;
|
|
1260
|
+
}
|
|
1261
|
+
try {
|
|
1262
|
+
let parsed = (0, import_rxml.parse)(balanced, toolSchema, {
|
|
1263
|
+
onError: options == null ? void 0 : options.onError,
|
|
1264
|
+
noChildNodes: []
|
|
1265
|
+
});
|
|
1266
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema, options);
|
|
1267
|
+
return parsed;
|
|
1268
|
+
} catch (_e) {
|
|
1269
|
+
if (shouldDeduplicateStringTags(toolSchema)) {
|
|
1270
|
+
const deduped = dedupeStringTagsAgainstSchema(balanced, toolSchema);
|
|
1271
|
+
if (deduped !== balanced) {
|
|
1272
|
+
try {
|
|
1273
|
+
let reparsed = (0, import_rxml.parse)(deduped, toolSchema, {
|
|
1274
|
+
onError: options == null ? void 0 : options.onError,
|
|
1275
|
+
noChildNodes: []
|
|
1276
|
+
});
|
|
1277
|
+
reparsed = repairParsedAgainstSchema(reparsed, toolSchema, options);
|
|
1278
|
+
return reparsed;
|
|
1279
|
+
} catch (_) {
|
|
1280
|
+
return null;
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
return null;
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
function balanceTags(xml) {
|
|
1288
|
+
const src = normalizeCloseTags(xml).replace(
|
|
1289
|
+
STATUS_TO_STEP_BOUNDARY_RE,
|
|
1290
|
+
"</status></step><step>"
|
|
1291
|
+
);
|
|
1292
|
+
let i = 0;
|
|
1293
|
+
const len = src.length;
|
|
1294
|
+
const out = [];
|
|
1295
|
+
const stack = [];
|
|
1296
|
+
while (i < len) {
|
|
1297
|
+
const lt = src.indexOf("<", i);
|
|
1298
|
+
if (lt === -1) {
|
|
1299
|
+
out.push(src.slice(i));
|
|
1300
|
+
break;
|
|
1301
|
+
}
|
|
1302
|
+
out.push(src.slice(i, lt));
|
|
1303
|
+
if (lt + 1 >= len) {
|
|
1304
|
+
break;
|
|
1305
|
+
}
|
|
1306
|
+
const next = src[lt + 1];
|
|
1307
|
+
if (next === "!" || next === "?") {
|
|
1308
|
+
i = handleSpecialTagSegment(src, lt, out);
|
|
1309
|
+
continue;
|
|
1310
|
+
}
|
|
1311
|
+
if (next === "/") {
|
|
1312
|
+
i = handleClosingTagSegment(src, lt, out, stack);
|
|
1313
|
+
continue;
|
|
1314
|
+
}
|
|
1315
|
+
i = handleOpeningTagSegment(src, lt, out, stack);
|
|
1316
|
+
}
|
|
1317
|
+
for (let k = stack.length - 1; k >= 0; k -= 1) {
|
|
1318
|
+
out.push(`</${stack[k]}>`);
|
|
1319
|
+
}
|
|
1320
|
+
return out.join("");
|
|
1321
|
+
}
|
|
1322
|
+
function skipWs(s, p, len) {
|
|
1323
|
+
let idx = p;
|
|
1324
|
+
while (idx < len && WHITESPACE_REGEX2.test(s[idx])) {
|
|
1325
|
+
idx += 1;
|
|
1326
|
+
}
|
|
1327
|
+
return idx;
|
|
1328
|
+
}
|
|
1329
|
+
function parseTagNameAt(s, p, len) {
|
|
1330
|
+
let idx = p;
|
|
1331
|
+
const start = idx;
|
|
1332
|
+
while (idx < len && NAME_CHAR_RE.test(s[idx])) {
|
|
1333
|
+
idx += 1;
|
|
1334
|
+
}
|
|
1335
|
+
return { name: s.slice(start, idx), pos: idx };
|
|
1336
|
+
}
|
|
1337
|
+
function handleSpecialTagSegment(src, lt, out) {
|
|
1338
|
+
const gt = src.indexOf(">", lt + 1);
|
|
1339
|
+
if (gt === -1) {
|
|
1340
|
+
out.push(src.slice(lt));
|
|
1341
|
+
return src.length;
|
|
1342
|
+
}
|
|
1343
|
+
out.push(src.slice(lt, gt + 1));
|
|
1344
|
+
return gt + 1;
|
|
1345
|
+
}
|
|
1346
|
+
function handleClosingTagSegment(src, lt, out, stack) {
|
|
1347
|
+
const len = src.length;
|
|
1348
|
+
let p = skipWs(src, lt + 2, len);
|
|
1349
|
+
const { name, pos } = parseTagNameAt(src, p, len);
|
|
1350
|
+
p = pos;
|
|
1351
|
+
const gt = src.indexOf(">", p);
|
|
1352
|
+
const closingText = gt === -1 ? src.slice(lt) : src.slice(lt, gt + 1);
|
|
1353
|
+
const idx = stack.lastIndexOf(name);
|
|
1354
|
+
if (idx !== -1) {
|
|
1355
|
+
for (let k = stack.length - 1; k > idx; k -= 1) {
|
|
1356
|
+
out.push(`</${stack[k]}>`);
|
|
1357
|
+
stack.pop();
|
|
1358
|
+
}
|
|
1359
|
+
out.push(closingText);
|
|
1360
|
+
stack.pop();
|
|
1361
|
+
}
|
|
1362
|
+
return gt === -1 ? len : gt + 1;
|
|
1363
|
+
}
|
|
1364
|
+
function handleOpeningTagSegment(src, lt, out, stack) {
|
|
1365
|
+
const len = src.length;
|
|
1366
|
+
let p = skipWs(src, lt + 1, len);
|
|
1367
|
+
const nameStart = p;
|
|
1368
|
+
const parsed = parseTagNameAt(src, p, len);
|
|
1369
|
+
p = parsed.pos;
|
|
1370
|
+
const name = src.slice(nameStart, p);
|
|
1371
|
+
const q = src.indexOf(">", p);
|
|
1372
|
+
if (q === -1) {
|
|
1373
|
+
out.push(src.slice(lt));
|
|
1374
|
+
return len;
|
|
1375
|
+
}
|
|
1376
|
+
let r = q - 1;
|
|
1377
|
+
while (r >= nameStart && WHITESPACE_REGEX2.test(src[r])) {
|
|
1378
|
+
r -= 1;
|
|
1379
|
+
}
|
|
1380
|
+
const selfClosing = src[r] === "/";
|
|
1381
|
+
out.push(src.slice(lt, q + 1));
|
|
1382
|
+
if (!selfClosing && name) {
|
|
1383
|
+
stack.push(name);
|
|
1384
|
+
}
|
|
1385
|
+
return q + 1;
|
|
1386
|
+
}
|
|
1387
|
+
function repairParsedAgainstSchema(input, schema, options) {
|
|
1388
|
+
if (!input || typeof input !== "object") {
|
|
1389
|
+
return input;
|
|
1390
|
+
}
|
|
1391
|
+
const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
|
|
1392
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
1393
|
+
return input;
|
|
1394
|
+
}
|
|
1395
|
+
const properties = unwrapped.properties;
|
|
1396
|
+
if (!properties) {
|
|
1397
|
+
return input;
|
|
1398
|
+
}
|
|
1399
|
+
applySchemaProps(input, properties, options);
|
|
1400
|
+
return input;
|
|
1401
|
+
}
|
|
1402
|
+
function applySchemaProps(obj, properties, options) {
|
|
1403
|
+
for (const key of Object.keys(obj)) {
|
|
1404
|
+
const propSchema = properties[key];
|
|
1405
|
+
if (!propSchema) {
|
|
1406
|
+
continue;
|
|
1407
|
+
}
|
|
1408
|
+
const prop = (0, import_rxml.unwrapJsonSchema)(propSchema);
|
|
1409
|
+
const propType = prop.type;
|
|
1410
|
+
if (propType === "array" && prop.items) {
|
|
1411
|
+
const itemSchemaRaw = prop.items;
|
|
1412
|
+
const itemSchema = (0, import_rxml.unwrapJsonSchema)(itemSchemaRaw);
|
|
1413
|
+
obj[key] = coerceArrayItems(obj[key], itemSchema, options);
|
|
1414
|
+
continue;
|
|
1415
|
+
}
|
|
1416
|
+
if (propType === "object") {
|
|
1417
|
+
const val = obj[key];
|
|
1418
|
+
if (val && typeof val === "object") {
|
|
1419
|
+
obj[key] = repairParsedAgainstSchema(
|
|
1420
|
+
val,
|
|
1421
|
+
prop,
|
|
1422
|
+
options
|
|
1423
|
+
);
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
function coerceArrayItems(val, itemSchema, options) {
|
|
1429
|
+
if (!Array.isArray(val)) {
|
|
1430
|
+
return val;
|
|
1431
|
+
}
|
|
1432
|
+
return val.map((v) => coerceArrayItem(v, itemSchema, options));
|
|
1433
|
+
}
|
|
1434
|
+
function coerceArrayItem(v, itemSchema, options) {
|
|
1435
|
+
const itemType = itemSchema == null ? void 0 : itemSchema.type;
|
|
1436
|
+
if (typeof v === "string" && itemType === "object") {
|
|
1437
|
+
const parsed = tryParseStringToSchemaObject(v, itemSchema, options);
|
|
1438
|
+
if (parsed !== null) {
|
|
1439
|
+
return parsed;
|
|
1440
|
+
}
|
|
1441
|
+
const fallback = extractStepStatusFromString(normalizeCloseTags(v));
|
|
1442
|
+
if (fallback) {
|
|
1443
|
+
return fallback;
|
|
1444
|
+
}
|
|
1445
|
+
return v;
|
|
1446
|
+
}
|
|
1447
|
+
if (v && typeof v === "object" && itemType === "object") {
|
|
1448
|
+
return repairParsedAgainstSchema(
|
|
1449
|
+
v,
|
|
1450
|
+
itemSchema,
|
|
1451
|
+
options
|
|
1452
|
+
);
|
|
1453
|
+
}
|
|
1454
|
+
return v;
|
|
1455
|
+
}
|
|
1456
|
+
function getStringPropertyNames(schema) {
|
|
1457
|
+
const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
|
|
1458
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
1459
|
+
return [];
|
|
1460
|
+
}
|
|
1461
|
+
const props = unwrapped.properties;
|
|
1462
|
+
if (!props) {
|
|
1463
|
+
return [];
|
|
1464
|
+
}
|
|
1465
|
+
const names = [];
|
|
1466
|
+
for (const key of Object.keys(props)) {
|
|
1467
|
+
const prop = (0, import_rxml.unwrapJsonSchema)(
|
|
1468
|
+
props[key]
|
|
1469
|
+
);
|
|
1470
|
+
const type = prop.type;
|
|
1471
|
+
if (type === "string") {
|
|
1472
|
+
names.push(key);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
return names;
|
|
1476
|
+
}
|
|
1477
|
+
function escapeRegExp2(s) {
|
|
1478
|
+
return s.replace(/[.*+?^${}()|[\\]\\]/g, "\\$&");
|
|
1479
|
+
}
|
|
1480
|
+
function dedupeStringTagsAgainstSchema(xml, schema) {
|
|
1481
|
+
const names = getStringPropertyNames(schema);
|
|
1482
|
+
let out = xml;
|
|
1483
|
+
for (const key of names) {
|
|
1484
|
+
out = dedupeSingleTag(out, key);
|
|
1485
|
+
}
|
|
1486
|
+
return out;
|
|
1487
|
+
}
|
|
1488
|
+
function dedupeSingleTag(xml, key) {
|
|
1489
|
+
var _a, _b;
|
|
1490
|
+
const escaped = escapeRegExp2(key);
|
|
1491
|
+
const re = new RegExp(`<${escaped}>([\\s\\S]*?)<\\/${escaped}>`, "g");
|
|
1492
|
+
const matches = Array.from(xml.matchAll(re));
|
|
1493
|
+
if (matches.length <= 1) {
|
|
1494
|
+
return xml;
|
|
1495
|
+
}
|
|
1496
|
+
const last = matches.at(-1);
|
|
1497
|
+
let result = "";
|
|
1498
|
+
let cursor = 0;
|
|
1499
|
+
for (const m of matches) {
|
|
1500
|
+
const idx = (_a = m.index) != null ? _a : 0;
|
|
1501
|
+
result += xml.slice(cursor, idx);
|
|
1502
|
+
if (last && idx === ((_b = last.index) != null ? _b : -1)) {
|
|
1503
|
+
result += m[0];
|
|
1504
|
+
}
|
|
1505
|
+
cursor = idx + m[0].length;
|
|
1506
|
+
}
|
|
1507
|
+
result += xml.slice(cursor);
|
|
1508
|
+
return result;
|
|
1509
|
+
}
|
|
1510
|
+
function tryParseStringToSchemaObject(xml, itemSchema, options) {
|
|
1511
|
+
try {
|
|
1512
|
+
const fixed = (0, import_rxml.parse)(normalizeCloseTags(xml), itemSchema, {
|
|
1513
|
+
onError: options == null ? void 0 : options.onError,
|
|
1514
|
+
noChildNodes: []
|
|
1515
|
+
});
|
|
1516
|
+
return typeof fixed === "string" ? null : fixed;
|
|
1517
|
+
} catch (e) {
|
|
1518
|
+
return null;
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
function extractStepStatusFromString(normXml) {
|
|
1522
|
+
const stepMatch = normXml.match(STEP_TAG_RE);
|
|
1523
|
+
const statusMatch = normXml.match(STATUS_TAG_RE);
|
|
1524
|
+
if (stepMatch && statusMatch) {
|
|
1525
|
+
return { step: stepMatch[1], status: statusMatch[1] };
|
|
1526
|
+
}
|
|
1527
|
+
return null;
|
|
1528
|
+
}
|
|
1266
1529
|
function processTextBeforeToolCall(text, currentIndex, toolCallStartIndex, processedElements) {
|
|
1267
1530
|
if (toolCallStartIndex > currentIndex) {
|
|
1268
1531
|
const textSegment = text.substring(currentIndex, toolCallStartIndex);
|
|
@@ -1275,20 +1538,36 @@ function processTextBeforeToolCall(text, currentIndex, toolCallStartIndex, proce
|
|
|
1275
1538
|
function processToolCall(params) {
|
|
1276
1539
|
var _a;
|
|
1277
1540
|
const { toolCall, tools, options, text, processedElements } = params;
|
|
1541
|
+
const toolSchema = getToolSchema(tools, toolCall.toolName);
|
|
1278
1542
|
try {
|
|
1279
|
-
const
|
|
1280
|
-
|
|
1543
|
+
const primary = escapeInvalidLt(normalizeCloseTags(toolCall.content));
|
|
1544
|
+
let parsed = (0, import_rxml.parse)(primary, toolSchema, {
|
|
1281
1545
|
onError: options == null ? void 0 : options.onError,
|
|
1282
1546
|
// Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
|
|
1283
1547
|
noChildNodes: []
|
|
1284
1548
|
});
|
|
1549
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema, options);
|
|
1285
1550
|
processedElements.push({
|
|
1286
1551
|
type: "tool-call",
|
|
1287
|
-
toolCallId: (0,
|
|
1552
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1288
1553
|
toolName: toolCall.toolName,
|
|
1289
1554
|
input: JSON.stringify(parsed)
|
|
1290
1555
|
});
|
|
1291
1556
|
} catch (error) {
|
|
1557
|
+
const reparsed = tryParseSecondaryXml(
|
|
1558
|
+
toolCall.content,
|
|
1559
|
+
toolSchema,
|
|
1560
|
+
options
|
|
1561
|
+
);
|
|
1562
|
+
if (reparsed !== null) {
|
|
1563
|
+
processedElements.push({
|
|
1564
|
+
type: "tool-call",
|
|
1565
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1566
|
+
toolName: toolCall.toolName,
|
|
1567
|
+
input: JSON.stringify(reparsed)
|
|
1568
|
+
});
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1292
1571
|
const originalCallText = text.substring(
|
|
1293
1572
|
toolCall.startIndex,
|
|
1294
1573
|
toolCall.endIndex
|
|
@@ -1312,20 +1591,33 @@ function addRemainingText(text, currentIndex, processedElements) {
|
|
|
1312
1591
|
}
|
|
1313
1592
|
function handleStreamingToolCallEnd(params) {
|
|
1314
1593
|
const { toolContent, currentToolCall, tools, options, ctrl, flushText } = params;
|
|
1594
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
1315
1595
|
try {
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1596
|
+
const primary = escapeInvalidLt(normalizeCloseTags(toolContent));
|
|
1597
|
+
let parsed = (0, import_rxml.parse)(primary, toolSchema, {
|
|
1318
1598
|
onError: options == null ? void 0 : options.onError,
|
|
1319
1599
|
noChildNodes: []
|
|
1320
1600
|
});
|
|
1601
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema, options);
|
|
1321
1602
|
flushText(ctrl);
|
|
1322
1603
|
ctrl.enqueue({
|
|
1323
1604
|
type: "tool-call",
|
|
1324
|
-
toolCallId: (0,
|
|
1605
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1325
1606
|
toolName: currentToolCall.name,
|
|
1326
1607
|
input: JSON.stringify(parsed)
|
|
1327
1608
|
});
|
|
1328
1609
|
} catch (error) {
|
|
1610
|
+
const parsed = tryParseSecondaryXml(toolContent, toolSchema, options);
|
|
1611
|
+
if (parsed !== null) {
|
|
1612
|
+
flushText(ctrl);
|
|
1613
|
+
ctrl.enqueue({
|
|
1614
|
+
type: "tool-call",
|
|
1615
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1616
|
+
toolName: currentToolCall.name,
|
|
1617
|
+
input: JSON.stringify(parsed)
|
|
1618
|
+
});
|
|
1619
|
+
return;
|
|
1620
|
+
}
|
|
1329
1621
|
handleStreamingToolCallError({
|
|
1330
1622
|
error,
|
|
1331
1623
|
currentToolCall,
|
|
@@ -1357,19 +1649,28 @@ function handleStreamingToolCallError(params) {
|
|
|
1357
1649
|
flushText(ctrl, originalCallText);
|
|
1358
1650
|
}
|
|
1359
1651
|
function findEarliestToolTag(buffer, toolNames) {
|
|
1360
|
-
let
|
|
1361
|
-
let
|
|
1652
|
+
let bestIndex = -1;
|
|
1653
|
+
let bestName = "";
|
|
1654
|
+
let bestSelfClosing = false;
|
|
1362
1655
|
if (toolNames.length > 0) {
|
|
1363
1656
|
for (const name of toolNames) {
|
|
1364
|
-
const
|
|
1365
|
-
const
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1657
|
+
const openTag = `<${name}>`;
|
|
1658
|
+
const selfTag = `<${name}/>`;
|
|
1659
|
+
const idxOpen = buffer.indexOf(openTag);
|
|
1660
|
+
const idxSelf = buffer.indexOf(selfTag);
|
|
1661
|
+
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
1662
|
+
bestIndex = idxOpen;
|
|
1663
|
+
bestName = name;
|
|
1664
|
+
bestSelfClosing = false;
|
|
1665
|
+
}
|
|
1666
|
+
if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
|
|
1667
|
+
bestIndex = idxSelf;
|
|
1668
|
+
bestName = name;
|
|
1669
|
+
bestSelfClosing = true;
|
|
1369
1670
|
}
|
|
1370
1671
|
}
|
|
1371
1672
|
}
|
|
1372
|
-
return { index:
|
|
1673
|
+
return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
|
|
1373
1674
|
}
|
|
1374
1675
|
function handleNoToolTagInBuffer(buffer, maxStartTagLen, controller, flushText) {
|
|
1375
1676
|
const tail = Math.max(0, maxStartTagLen - 1);
|
|
@@ -1392,10 +1693,12 @@ function processToolCallInBuffer(params) {
|
|
|
1392
1693
|
setBuffer
|
|
1393
1694
|
} = params;
|
|
1394
1695
|
const endTag = `</${currentToolCall.name}>`;
|
|
1395
|
-
const
|
|
1696
|
+
const normalized = normalizeCloseTags(buffer);
|
|
1697
|
+
const effectiveBuffer = normalized;
|
|
1698
|
+
const endTagIndex = effectiveBuffer.indexOf(endTag);
|
|
1396
1699
|
if (endTagIndex !== -1) {
|
|
1397
|
-
const toolContent =
|
|
1398
|
-
const newBuffer =
|
|
1700
|
+
const toolContent = effectiveBuffer.substring(0, endTagIndex);
|
|
1701
|
+
const newBuffer = effectiveBuffer.substring(endTagIndex + endTag.length);
|
|
1399
1702
|
setBuffer("");
|
|
1400
1703
|
handleStreamingToolCallEnd({
|
|
1401
1704
|
toolContent,
|
|
@@ -1408,14 +1711,46 @@ function processToolCallInBuffer(params) {
|
|
|
1408
1711
|
setBuffer(newBuffer);
|
|
1409
1712
|
return { buffer: newBuffer, currentToolCall: null, shouldBreak: false };
|
|
1410
1713
|
}
|
|
1411
|
-
return { buffer, currentToolCall, shouldBreak: true };
|
|
1714
|
+
return { buffer: effectiveBuffer, currentToolCall, shouldBreak: true };
|
|
1412
1715
|
}
|
|
1413
1716
|
function processNoToolCallInBuffer(params) {
|
|
1414
|
-
const {
|
|
1415
|
-
|
|
1717
|
+
const {
|
|
1718
|
+
buffer,
|
|
1719
|
+
toolNames,
|
|
1720
|
+
maxStartTagLen,
|
|
1721
|
+
controller,
|
|
1722
|
+
flushText,
|
|
1723
|
+
tools,
|
|
1724
|
+
options
|
|
1725
|
+
} = params;
|
|
1726
|
+
const {
|
|
1727
|
+
index: earliestStartTagIndex,
|
|
1728
|
+
name: earliestToolName,
|
|
1729
|
+
selfClosing
|
|
1730
|
+
} = findEarliestToolTag(buffer, toolNames);
|
|
1416
1731
|
if (earliestStartTagIndex !== -1) {
|
|
1417
1732
|
const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
|
|
1418
1733
|
flushText(controller, textBeforeTag);
|
|
1734
|
+
if (selfClosing) {
|
|
1735
|
+
const selfTag = `<${earliestToolName}/>`;
|
|
1736
|
+
const newBuffer2 = buffer.substring(
|
|
1737
|
+
earliestStartTagIndex + selfTag.length
|
|
1738
|
+
);
|
|
1739
|
+
handleStreamingToolCallEnd({
|
|
1740
|
+
toolContent: "",
|
|
1741
|
+
currentToolCall: { name: earliestToolName, content: "" },
|
|
1742
|
+
tools,
|
|
1743
|
+
options,
|
|
1744
|
+
ctrl: controller,
|
|
1745
|
+
flushText
|
|
1746
|
+
});
|
|
1747
|
+
return {
|
|
1748
|
+
buffer: newBuffer2,
|
|
1749
|
+
currentToolCall: null,
|
|
1750
|
+
shouldBreak: false,
|
|
1751
|
+
shouldContinue: false
|
|
1752
|
+
};
|
|
1753
|
+
}
|
|
1419
1754
|
const startTag = `<${earliestToolName}>`;
|
|
1420
1755
|
const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
|
|
1421
1756
|
return {
|
|
@@ -1444,7 +1779,7 @@ function createFlushTextHandler(getBuffer, setBuffer, getCurrentTextId, setCurre
|
|
|
1444
1779
|
if (content) {
|
|
1445
1780
|
const currentTextId2 = getCurrentTextId();
|
|
1446
1781
|
if (!currentTextId2) {
|
|
1447
|
-
const newId = (0,
|
|
1782
|
+
const newId = (0, import_provider_utils2.generateId)();
|
|
1448
1783
|
setCurrentTextId(newId);
|
|
1449
1784
|
controller.enqueue({ type: "text-start", id: newId });
|
|
1450
1785
|
}
|
|
@@ -1496,6 +1831,8 @@ function processBufferWithoutToolCall(params, controller) {
|
|
|
1496
1831
|
getBuffer,
|
|
1497
1832
|
setBuffer,
|
|
1498
1833
|
setCurrentToolCall,
|
|
1834
|
+
tools,
|
|
1835
|
+
options,
|
|
1499
1836
|
toolNames,
|
|
1500
1837
|
maxStartTagLen,
|
|
1501
1838
|
flushText
|
|
@@ -1505,7 +1842,9 @@ function processBufferWithoutToolCall(params, controller) {
|
|
|
1505
1842
|
toolNames,
|
|
1506
1843
|
maxStartTagLen,
|
|
1507
1844
|
controller,
|
|
1508
|
-
flushText
|
|
1845
|
+
flushText,
|
|
1846
|
+
tools,
|
|
1847
|
+
options
|
|
1509
1848
|
});
|
|
1510
1849
|
setBuffer(result.buffer);
|
|
1511
1850
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -1580,7 +1919,17 @@ var morphXmlProtocol = () => ({
|
|
|
1580
1919
|
}
|
|
1581
1920
|
const processedElements = [];
|
|
1582
1921
|
let currentIndex = 0;
|
|
1583
|
-
const
|
|
1922
|
+
const toolCallsRaw = findToolCalls(text, toolNames);
|
|
1923
|
+
const toolCallsNorm = collectToolCallsFromNormalizedText(text, toolNames);
|
|
1924
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1925
|
+
const toolCalls = [...toolCallsRaw, ...toolCallsNorm].filter((tc) => {
|
|
1926
|
+
const key = `${tc.toolName}:${tc.startIndex}:${tc.endIndex}`;
|
|
1927
|
+
if (seen.has(key)) {
|
|
1928
|
+
return false;
|
|
1929
|
+
}
|
|
1930
|
+
seen.add(key);
|
|
1931
|
+
return true;
|
|
1932
|
+
}).sort((a, b) => a.startIndex - b.startIndex);
|
|
1584
1933
|
for (const toolCall of toolCalls) {
|
|
1585
1934
|
currentIndex = processTextBeforeToolCall(
|
|
1586
1935
|
text,
|
|
@@ -1668,53 +2017,225 @@ function getToolSchema(tools, toolName) {
|
|
|
1668
2017
|
var _a;
|
|
1669
2018
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
1670
2019
|
}
|
|
1671
|
-
function
|
|
1672
|
-
let
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
2020
|
+
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
2021
|
+
let pos = contentStart;
|
|
2022
|
+
let depth = 1;
|
|
2023
|
+
while (pos < text.length) {
|
|
2024
|
+
const tok = nextTagToken(text, pos);
|
|
2025
|
+
if (tok.kind === "eof") {
|
|
2026
|
+
break;
|
|
2027
|
+
}
|
|
2028
|
+
const result = updateDepthWithToken(tok, toolName, depth);
|
|
2029
|
+
depth = result.depth;
|
|
2030
|
+
if (result.closedAt !== void 0) {
|
|
2031
|
+
return result.closedAt;
|
|
2032
|
+
}
|
|
2033
|
+
pos = tok.nextPos;
|
|
2034
|
+
}
|
|
2035
|
+
return -1;
|
|
2036
|
+
}
|
|
2037
|
+
function skipSpecialSegment(text, lt) {
|
|
2038
|
+
const next = text[lt + 1];
|
|
2039
|
+
if (next !== "!" && next !== "?") {
|
|
2040
|
+
return null;
|
|
2041
|
+
}
|
|
2042
|
+
const gt = text.indexOf(">", lt + 1);
|
|
2043
|
+
if (gt === -1) {
|
|
2044
|
+
return null;
|
|
2045
|
+
}
|
|
2046
|
+
return gt + 1;
|
|
2047
|
+
}
|
|
2048
|
+
function consumeClosingTag(text, lt, toolName) {
|
|
2049
|
+
let p = lt + 2;
|
|
2050
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
2051
|
+
p += 1;
|
|
2052
|
+
}
|
|
2053
|
+
if (text.slice(p, p + toolName.length) === toolName) {
|
|
2054
|
+
p += toolName.length;
|
|
1676
2055
|
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
1677
2056
|
p += 1;
|
|
1678
2057
|
}
|
|
1679
2058
|
if (text[p] === ">") {
|
|
1680
|
-
|
|
2059
|
+
const endPos2 = p + 1;
|
|
2060
|
+
return { matched: true, endPos: endPos2 };
|
|
1681
2061
|
}
|
|
1682
2062
|
}
|
|
1683
|
-
|
|
2063
|
+
const gt = text.indexOf(">", lt + 1);
|
|
2064
|
+
const endPos = gt === -1 ? text.length : gt + 1;
|
|
2065
|
+
return { matched: false, endPos };
|
|
1684
2066
|
}
|
|
1685
|
-
function
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
const
|
|
1691
|
-
|
|
1692
|
-
|
|
2067
|
+
function consumeOpenTag(text, lt) {
|
|
2068
|
+
let p = lt + 1;
|
|
2069
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
2070
|
+
p += 1;
|
|
2071
|
+
}
|
|
2072
|
+
const nameStart = p;
|
|
2073
|
+
while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
2074
|
+
p += 1;
|
|
2075
|
+
}
|
|
2076
|
+
const name = text.slice(nameStart, p);
|
|
2077
|
+
const q = text.indexOf(">", p);
|
|
2078
|
+
if (q === -1) {
|
|
2079
|
+
return null;
|
|
2080
|
+
}
|
|
2081
|
+
let r = q - 1;
|
|
2082
|
+
while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
|
|
2083
|
+
r -= 1;
|
|
2084
|
+
}
|
|
2085
|
+
const selfClosing = text[r] === "/";
|
|
2086
|
+
return { name, selfClosing, nextPos: q + 1 };
|
|
2087
|
+
}
|
|
2088
|
+
function updateDepthWithToken(tok, toolName, depth) {
|
|
2089
|
+
if (tok.kind === "close" && tok.name === toolName) {
|
|
2090
|
+
const newDepth = depth - 1;
|
|
2091
|
+
return newDepth === 0 ? { depth: newDepth, closedAt: tok.nextPos } : { depth: newDepth };
|
|
2092
|
+
}
|
|
2093
|
+
if (tok.kind === "open" && tok.name === toolName && !tok.selfClosing) {
|
|
2094
|
+
return { depth: depth + 1 };
|
|
2095
|
+
}
|
|
2096
|
+
return { depth };
|
|
2097
|
+
}
|
|
2098
|
+
function nextTagToken(text, fromPos) {
|
|
2099
|
+
const lt = text.indexOf("<", fromPos);
|
|
2100
|
+
if (lt === -1 || lt + 1 >= text.length) {
|
|
2101
|
+
return { kind: "eof", nextPos: text.length };
|
|
2102
|
+
}
|
|
2103
|
+
const next = text[lt + 1];
|
|
2104
|
+
const specialEnd = skipSpecialSegment(text, lt);
|
|
2105
|
+
if (specialEnd !== null) {
|
|
2106
|
+
return { kind: "special", nextPos: specialEnd };
|
|
2107
|
+
}
|
|
2108
|
+
if (next === "/") {
|
|
2109
|
+
const closing = consumeClosingTag(text, lt, "");
|
|
2110
|
+
let p = lt + 2;
|
|
2111
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
2112
|
+
p += 1;
|
|
2113
|
+
}
|
|
2114
|
+
const nameStart = p;
|
|
2115
|
+
while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
2116
|
+
p += 1;
|
|
2117
|
+
}
|
|
2118
|
+
const name = text.slice(nameStart, p);
|
|
2119
|
+
return { kind: "close", name, nextPos: closing.endPos };
|
|
2120
|
+
}
|
|
2121
|
+
const open = consumeOpenTag(text, lt);
|
|
2122
|
+
if (open === null) {
|
|
2123
|
+
return { kind: "eof", nextPos: text.length };
|
|
2124
|
+
}
|
|
1693
2125
|
return {
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
segment
|
|
2126
|
+
kind: "open",
|
|
2127
|
+
name: open.name,
|
|
2128
|
+
selfClosing: open.selfClosing,
|
|
2129
|
+
nextPos: open.nextPos
|
|
1699
2130
|
};
|
|
1700
2131
|
}
|
|
2132
|
+
function collectToolCallsFromNormalizedText(text, toolNames) {
|
|
2133
|
+
var _a;
|
|
2134
|
+
const normalizedText = normalizeCloseTags(text);
|
|
2135
|
+
const collected = [];
|
|
2136
|
+
for (const toolName of toolNames) {
|
|
2137
|
+
const startTag = `<${toolName}>`;
|
|
2138
|
+
let idx = 0;
|
|
2139
|
+
let lastOrigIdx = 0;
|
|
2140
|
+
while (idx < normalizedText.length) {
|
|
2141
|
+
const tagStartNorm = normalizedText.indexOf(startTag, idx);
|
|
2142
|
+
if (tagStartNorm === -1) {
|
|
2143
|
+
break;
|
|
2144
|
+
}
|
|
2145
|
+
const contentStartNorm = tagStartNorm + startTag.length;
|
|
2146
|
+
const endNorm = findClosingTagEndFlexible(
|
|
2147
|
+
normalizedText,
|
|
2148
|
+
contentStartNorm,
|
|
2149
|
+
toolName
|
|
2150
|
+
);
|
|
2151
|
+
if (endNorm > contentStartNorm) {
|
|
2152
|
+
const tagStartOrig = text.indexOf(startTag, lastOrigIdx);
|
|
2153
|
+
const contentStartOrig = tagStartOrig + startTag.length;
|
|
2154
|
+
let endOrig = findClosingTagEndFlexible(
|
|
2155
|
+
text,
|
|
2156
|
+
contentStartOrig,
|
|
2157
|
+
toolName
|
|
2158
|
+
);
|
|
2159
|
+
if (endOrig === -1) {
|
|
2160
|
+
const approxLen = endNorm - tagStartNorm;
|
|
2161
|
+
endOrig = Math.min(text.length, tagStartOrig + approxLen);
|
|
2162
|
+
}
|
|
2163
|
+
const segment = text.substring(tagStartOrig, endOrig);
|
|
2164
|
+
const inner = (_a = (0, import_rxml.extractRawInner)(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
|
|
2165
|
+
collected.push({
|
|
2166
|
+
toolName,
|
|
2167
|
+
startIndex: tagStartOrig,
|
|
2168
|
+
endIndex: endOrig,
|
|
2169
|
+
content: inner,
|
|
2170
|
+
segment
|
|
2171
|
+
});
|
|
2172
|
+
lastOrigIdx = endOrig;
|
|
2173
|
+
idx = endNorm;
|
|
2174
|
+
} else {
|
|
2175
|
+
idx = contentStartNorm;
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
}
|
|
2179
|
+
return collected.sort((a, b) => a.startIndex - b.startIndex);
|
|
2180
|
+
}
|
|
2181
|
+
function getNextTagInfo(text, toolName, fromIndex) {
|
|
2182
|
+
const startTag = `<${toolName}>`;
|
|
2183
|
+
const selfTag = `<${toolName}/>`;
|
|
2184
|
+
const openIdx = text.indexOf(startTag, fromIndex);
|
|
2185
|
+
const selfIdx = text.indexOf(selfTag, fromIndex);
|
|
2186
|
+
const hasOpen = openIdx !== -1;
|
|
2187
|
+
const hasSelf = selfIdx !== -1;
|
|
2188
|
+
if (!(hasOpen || hasSelf)) {
|
|
2189
|
+
return {
|
|
2190
|
+
found: false,
|
|
2191
|
+
tagStart: -1,
|
|
2192
|
+
selfClosing: false,
|
|
2193
|
+
startTag,
|
|
2194
|
+
selfTag
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
2197
|
+
const pickSelf = hasSelf && (!hasOpen || selfIdx < openIdx);
|
|
2198
|
+
const tagStart = pickSelf ? selfIdx : openIdx;
|
|
2199
|
+
return { found: true, tagStart, selfClosing: pickSelf, startTag, selfTag };
|
|
2200
|
+
}
|
|
1701
2201
|
function findToolCallsForName(text, toolName) {
|
|
2202
|
+
var _a;
|
|
1702
2203
|
const toolCalls = [];
|
|
1703
|
-
const startTag = `<${toolName}>`;
|
|
1704
2204
|
let searchIndex = 0;
|
|
1705
2205
|
while (searchIndex < text.length) {
|
|
1706
|
-
const
|
|
1707
|
-
if (
|
|
2206
|
+
const info = getNextTagInfo(text, toolName, searchIndex);
|
|
2207
|
+
if (!info.found) {
|
|
1708
2208
|
break;
|
|
1709
2209
|
}
|
|
1710
|
-
const
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
const
|
|
1714
|
-
toolCalls.push(
|
|
1715
|
-
|
|
2210
|
+
const { tagStart, selfClosing, startTag, selfTag } = info;
|
|
2211
|
+
if (selfClosing) {
|
|
2212
|
+
const endIndex = tagStart + selfTag.length;
|
|
2213
|
+
const segment = text.substring(tagStart, endIndex);
|
|
2214
|
+
toolCalls.push({
|
|
2215
|
+
toolName,
|
|
2216
|
+
startIndex: tagStart,
|
|
2217
|
+
endIndex,
|
|
2218
|
+
content: "",
|
|
2219
|
+
segment
|
|
2220
|
+
});
|
|
2221
|
+
searchIndex = endIndex;
|
|
2222
|
+
continue;
|
|
2223
|
+
}
|
|
2224
|
+
const contentStart = tagStart + startTag.length;
|
|
2225
|
+
const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
|
|
2226
|
+
if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
|
|
2227
|
+
const segment = text.substring(tagStart, fullTagEnd);
|
|
2228
|
+
const inner = (_a = (0, import_rxml.extractRawInner)(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
|
|
2229
|
+
toolCalls.push({
|
|
2230
|
+
toolName,
|
|
2231
|
+
startIndex: tagStart,
|
|
2232
|
+
endIndex: fullTagEnd,
|
|
2233
|
+
content: inner,
|
|
2234
|
+
segment
|
|
2235
|
+
});
|
|
2236
|
+
searchIndex = fullTagEnd;
|
|
1716
2237
|
} else {
|
|
1717
|
-
searchIndex =
|
|
2238
|
+
searchIndex = contentStart;
|
|
1718
2239
|
}
|
|
1719
2240
|
}
|
|
1720
2241
|
return toolCalls;
|
|
@@ -1728,14 +2249,53 @@ function findToolCalls(text, toolNames) {
|
|
|
1728
2249
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
1729
2250
|
}
|
|
1730
2251
|
|
|
1731
|
-
// src/
|
|
1732
|
-
|
|
1733
|
-
|
|
2252
|
+
// src/generate-handler.ts
|
|
2253
|
+
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
2254
|
+
var import_rxml2 = require("@ai-sdk-tool/rxml");
|
|
2255
|
+
|
|
2256
|
+
// src/utils/on-error.ts
|
|
2257
|
+
function extractOnErrorOption(providerOptions) {
|
|
2258
|
+
var _a;
|
|
2259
|
+
if (providerOptions && typeof providerOptions === "object") {
|
|
2260
|
+
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
2261
|
+
return onError ? { onError } : void 0;
|
|
2262
|
+
}
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2266
|
+
// src/utils/provider-options.ts
|
|
2267
|
+
var originalToolsSchema = {
|
|
2268
|
+
encode: encodeOriginalTools,
|
|
2269
|
+
decode: decodeOriginalTools
|
|
2270
|
+
};
|
|
2271
|
+
function encodeOriginalTools(tools) {
|
|
2272
|
+
return (tools == null ? void 0 : tools.map((t) => ({
|
|
2273
|
+
name: t.name,
|
|
2274
|
+
inputSchema: JSON.stringify(t.inputSchema)
|
|
2275
|
+
}))) || [];
|
|
2276
|
+
}
|
|
2277
|
+
function decodeOriginalTools(originalTools) {
|
|
2278
|
+
if (!originalTools) {
|
|
2279
|
+
return [];
|
|
2280
|
+
}
|
|
2281
|
+
return originalTools.map(
|
|
2282
|
+
(t) => ({
|
|
2283
|
+
type: "function",
|
|
2284
|
+
name: t.name,
|
|
2285
|
+
inputSchema: JSON.parse(t.inputSchema)
|
|
2286
|
+
})
|
|
2287
|
+
);
|
|
2288
|
+
}
|
|
2289
|
+
function extractToolNamesFromOriginalTools(originalTools) {
|
|
2290
|
+
return (originalTools == null ? void 0 : originalTools.map((t) => t.name)) || [];
|
|
2291
|
+
}
|
|
2292
|
+
function isToolChoiceActive(params) {
|
|
2293
|
+
var _a, _b, _c;
|
|
2294
|
+
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
2295
|
+
return !!(typeof params.providerOptions === "object" && params.providerOptions !== null && typeof ((_c = params.providerOptions) == null ? void 0 : _c.toolCallMiddleware) === "object" && toolChoice && typeof toolChoice === "object" && (toolChoice.type === "tool" || toolChoice.type === "required"));
|
|
1734
2296
|
}
|
|
1735
2297
|
|
|
1736
2298
|
// src/generate-handler.ts
|
|
1737
|
-
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
1738
|
-
var import_rxml2 = require("@ai-sdk-tool/rxml");
|
|
1739
2299
|
function parseToolChoiceJson(text, providerOptions) {
|
|
1740
2300
|
var _a;
|
|
1741
2301
|
try {
|
|
@@ -1779,7 +2339,7 @@ async function handleToolChoice(doGenerate, params) {
|
|
|
1779
2339
|
}
|
|
1780
2340
|
const toolCall = {
|
|
1781
2341
|
type: "tool-call",
|
|
1782
|
-
toolCallId: (0,
|
|
2342
|
+
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1783
2343
|
toolName: parsed.name || "unknown",
|
|
1784
2344
|
input: JSON.stringify(parsed.arguments || {})
|
|
1785
2345
|
};
|
|
@@ -1905,8 +2465,13 @@ function fixToolCallWithSchema(part, tools) {
|
|
|
1905
2465
|
};
|
|
1906
2466
|
}
|
|
1907
2467
|
|
|
2468
|
+
// src/protocols/tool-call-protocol.ts
|
|
2469
|
+
function isProtocolFactory(protocol) {
|
|
2470
|
+
return typeof protocol === "function";
|
|
2471
|
+
}
|
|
2472
|
+
|
|
1908
2473
|
// src/stream-handler.ts
|
|
1909
|
-
var
|
|
2474
|
+
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
1910
2475
|
function extractToolCallSegments(protocol, fullRawText, tools) {
|
|
1911
2476
|
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
|
|
1912
2477
|
text: fullRawText,
|
|
@@ -1943,7 +2508,7 @@ function handleDebugSummary(parsedToolCalls, origin, params) {
|
|
|
1943
2508
|
}
|
|
1944
2509
|
function createDebugSummaryTransform({
|
|
1945
2510
|
protocol,
|
|
1946
|
-
|
|
2511
|
+
getFullRawText,
|
|
1947
2512
|
tools,
|
|
1948
2513
|
params
|
|
1949
2514
|
}) {
|
|
@@ -1956,11 +2521,9 @@ function createDebugSummaryTransform({
|
|
|
1956
2521
|
}
|
|
1957
2522
|
if (part.type === "finish") {
|
|
1958
2523
|
try {
|
|
1959
|
-
const
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
tools
|
|
1963
|
-
);
|
|
2524
|
+
const raw = getFullRawText();
|
|
2525
|
+
logRawChunk(raw);
|
|
2526
|
+
const origin = extractToolCallSegments(protocol, raw, tools);
|
|
1964
2527
|
handleDebugSummary(parsedToolCalls, origin, params);
|
|
1965
2528
|
} catch (e) {
|
|
1966
2529
|
}
|
|
@@ -2058,7 +2621,7 @@ async function wrapStream({
|
|
|
2058
2621
|
const withSummary = parsed.pipeThrough(
|
|
2059
2622
|
createDebugSummaryTransform({
|
|
2060
2623
|
protocol,
|
|
2061
|
-
fullRawText,
|
|
2624
|
+
getFullRawText: () => fullRawText,
|
|
2062
2625
|
tools,
|
|
2063
2626
|
params
|
|
2064
2627
|
})
|
|
@@ -2092,19 +2655,26 @@ async function toolChoiceStream({
|
|
|
2092
2655
|
}
|
|
2093
2656
|
const toolCallChunk = {
|
|
2094
2657
|
type: "tool-call",
|
|
2095
|
-
toolCallId: (0,
|
|
2658
|
+
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
2096
2659
|
toolName: toolJson.name || "unknown",
|
|
2097
2660
|
input: JSON.stringify(toolJson.arguments || {})
|
|
2098
2661
|
};
|
|
2099
2662
|
const finishChunk = {
|
|
2100
2663
|
type: "finish",
|
|
2101
|
-
usage: (result == null ? void 0 : result.usage) ||
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2664
|
+
usage: (result == null ? void 0 : result.usage) || {
|
|
2665
|
+
inputTokens: {
|
|
2666
|
+
total: 0,
|
|
2667
|
+
noCache: void 0,
|
|
2668
|
+
cacheRead: void 0,
|
|
2669
|
+
cacheWrite: void 0
|
|
2670
|
+
},
|
|
2671
|
+
outputTokens: {
|
|
2672
|
+
total: 0,
|
|
2673
|
+
text: void 0,
|
|
2674
|
+
reasoning: void 0
|
|
2675
|
+
}
|
|
2106
2676
|
},
|
|
2107
|
-
finishReason: "tool-calls"
|
|
2677
|
+
finishReason: { unified: "tool-calls", raw: void 0 }
|
|
2108
2678
|
};
|
|
2109
2679
|
const stream = new ReadableStream({
|
|
2110
2680
|
start(controller) {
|
|
@@ -2138,26 +2708,106 @@ async function toolChoiceStream({
|
|
|
2138
2708
|
};
|
|
2139
2709
|
}
|
|
2140
2710
|
|
|
2711
|
+
// src/utils/dynamic-tool-schema.ts
|
|
2712
|
+
function createDynamicIfThenElseSchema(tools) {
|
|
2713
|
+
let currentSchema = {};
|
|
2714
|
+
const toolNames = [];
|
|
2715
|
+
for (let i = tools.length - 1; i >= 0; i -= 1) {
|
|
2716
|
+
const tool = tools[i];
|
|
2717
|
+
if (tool.type === "provider") {
|
|
2718
|
+
throw new Error(
|
|
2719
|
+
"Provider tools are not supported by this middleware. Please use function tools."
|
|
2720
|
+
);
|
|
2721
|
+
}
|
|
2722
|
+
toolNames.unshift(tool.name);
|
|
2723
|
+
const toolCondition = {
|
|
2724
|
+
if: {
|
|
2725
|
+
properties: {
|
|
2726
|
+
name: {
|
|
2727
|
+
const: tool.name
|
|
2728
|
+
}
|
|
2729
|
+
},
|
|
2730
|
+
required: ["name"]
|
|
2731
|
+
},
|
|
2732
|
+
// biome-ignore lint/suspicious/noThenProperty: JSON Schema uses 'then' as a keyword
|
|
2733
|
+
then: {
|
|
2734
|
+
properties: {
|
|
2735
|
+
name: {
|
|
2736
|
+
const: tool.name
|
|
2737
|
+
},
|
|
2738
|
+
arguments: tool.inputSchema
|
|
2739
|
+
},
|
|
2740
|
+
required: ["name", "arguments"]
|
|
2741
|
+
}
|
|
2742
|
+
};
|
|
2743
|
+
if (Object.keys(currentSchema).length > 0) {
|
|
2744
|
+
toolCondition.else = currentSchema;
|
|
2745
|
+
}
|
|
2746
|
+
currentSchema = toolCondition;
|
|
2747
|
+
}
|
|
2748
|
+
return {
|
|
2749
|
+
type: "object",
|
|
2750
|
+
// Explicitly specify type as "object"
|
|
2751
|
+
properties: {
|
|
2752
|
+
name: {
|
|
2753
|
+
type: "string",
|
|
2754
|
+
description: "Name of the tool to call",
|
|
2755
|
+
enum: toolNames
|
|
2756
|
+
},
|
|
2757
|
+
arguments: {
|
|
2758
|
+
type: "object",
|
|
2759
|
+
// By default, arguments is also specified as object type
|
|
2760
|
+
description: "Argument object to be passed to the tool"
|
|
2761
|
+
}
|
|
2762
|
+
},
|
|
2763
|
+
required: ["name", "arguments"],
|
|
2764
|
+
...currentSchema
|
|
2765
|
+
};
|
|
2766
|
+
}
|
|
2767
|
+
|
|
2141
2768
|
// src/transform-handler.ts
|
|
2142
|
-
function buildFinalPrompt(systemPrompt, processedPrompt) {
|
|
2143
|
-
|
|
2144
|
-
if (
|
|
2769
|
+
function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
|
|
2770
|
+
const systemIndex = processedPrompt.findIndex((m) => m.role === "system");
|
|
2771
|
+
if (systemIndex !== -1) {
|
|
2772
|
+
const existing = processedPrompt[systemIndex].content;
|
|
2773
|
+
let existingText = "";
|
|
2774
|
+
if (typeof existing === "string") {
|
|
2775
|
+
existingText = existing;
|
|
2776
|
+
} else if (Array.isArray(existing)) {
|
|
2777
|
+
existingText = existing.map((p) => {
|
|
2778
|
+
var _a;
|
|
2779
|
+
return (p == null ? void 0 : p.type) === "text" ? (_a = p.text) != null ? _a : "" : "";
|
|
2780
|
+
}).filter(Boolean).join("\n");
|
|
2781
|
+
} else {
|
|
2782
|
+
existingText = String(existing != null ? existing : "");
|
|
2783
|
+
}
|
|
2784
|
+
const mergedContent = placement === "first" ? `${systemPrompt}
|
|
2785
|
+
|
|
2786
|
+
${existingText}` : `${existingText}
|
|
2787
|
+
|
|
2788
|
+
${systemPrompt}`;
|
|
2789
|
+
return processedPrompt.map(
|
|
2790
|
+
(m, idx) => idx === systemIndex ? {
|
|
2791
|
+
...m,
|
|
2792
|
+
content: mergedContent
|
|
2793
|
+
} : m
|
|
2794
|
+
);
|
|
2795
|
+
}
|
|
2796
|
+
if (placement === "first") {
|
|
2145
2797
|
return [
|
|
2146
2798
|
{
|
|
2147
2799
|
role: "system",
|
|
2148
|
-
content:
|
|
2149
|
-
|
|
2150
|
-
${processedPrompt[0].content}`
|
|
2800
|
+
content: systemPrompt
|
|
2151
2801
|
},
|
|
2152
|
-
...processedPrompt
|
|
2802
|
+
...processedPrompt
|
|
2153
2803
|
];
|
|
2154
2804
|
}
|
|
2155
2805
|
return [
|
|
2806
|
+
...processedPrompt,
|
|
2156
2807
|
{
|
|
2157
2808
|
role: "system",
|
|
2158
2809
|
content: systemPrompt
|
|
2159
|
-
}
|
|
2160
|
-
...processedPrompt
|
|
2810
|
+
}
|
|
2161
2811
|
];
|
|
2162
2812
|
}
|
|
2163
2813
|
function buildBaseReturnParams(params, finalPrompt, functionTools) {
|
|
@@ -2257,7 +2907,8 @@ function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
|
|
|
2257
2907
|
function transformParams({
|
|
2258
2908
|
params,
|
|
2259
2909
|
protocol,
|
|
2260
|
-
toolSystemPromptTemplate
|
|
2910
|
+
toolSystemPromptTemplate,
|
|
2911
|
+
placement = "first"
|
|
2261
2912
|
}) {
|
|
2262
2913
|
var _a, _b, _c, _d, _e;
|
|
2263
2914
|
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
@@ -2273,7 +2924,11 @@ function transformParams({
|
|
|
2273
2924
|
resolvedProtocol,
|
|
2274
2925
|
extractOnErrorOption(params.providerOptions)
|
|
2275
2926
|
);
|
|
2276
|
-
const finalPrompt = buildFinalPrompt(
|
|
2927
|
+
const finalPrompt = buildFinalPrompt(
|
|
2928
|
+
systemPrompt,
|
|
2929
|
+
processedPrompt,
|
|
2930
|
+
placement
|
|
2931
|
+
);
|
|
2277
2932
|
const baseReturnParams = buildBaseReturnParams(
|
|
2278
2933
|
params,
|
|
2279
2934
|
finalPrompt,
|
|
@@ -2350,7 +3005,10 @@ function processMessage(message, resolvedProtocol, providerOptions) {
|
|
|
2350
3005
|
};
|
|
2351
3006
|
}
|
|
2352
3007
|
if (message.role === "tool") {
|
|
2353
|
-
|
|
3008
|
+
const toolResultParts = message.content.filter(
|
|
3009
|
+
(part) => part.type === "tool-result"
|
|
3010
|
+
);
|
|
3011
|
+
return processToolMessage(toolResultParts, resolvedProtocol);
|
|
2354
3012
|
}
|
|
2355
3013
|
return message;
|
|
2356
3014
|
}
|
|
@@ -2425,7 +3083,8 @@ function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
|
|
|
2425
3083
|
// src/tool-call-middleware.ts
|
|
2426
3084
|
function createToolMiddleware({
|
|
2427
3085
|
protocol,
|
|
2428
|
-
toolSystemPromptTemplate
|
|
3086
|
+
toolSystemPromptTemplate,
|
|
3087
|
+
placement = "last"
|
|
2429
3088
|
}) {
|
|
2430
3089
|
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
2431
3090
|
return {
|
|
@@ -2452,6 +3111,7 @@ function createToolMiddleware({
|
|
|
2452
3111
|
transformParams: async ({ params }) => transformParams({
|
|
2453
3112
|
protocol: resolvedProtocol,
|
|
2454
3113
|
toolSystemPromptTemplate,
|
|
3114
|
+
placement,
|
|
2455
3115
|
params
|
|
2456
3116
|
})
|
|
2457
3117
|
};
|
|
@@ -2497,6 +3157,7 @@ For each function call return a json object with function name and arguments wit
|
|
|
2497
3157
|
});
|
|
2498
3158
|
var morphXmlToolMiddleware = createToolMiddleware({
|
|
2499
3159
|
protocol: morphXmlProtocol,
|
|
3160
|
+
placement: "last",
|
|
2500
3161
|
toolSystemPromptTemplate(tools) {
|
|
2501
3162
|
return `You are a function calling AI model.
|
|
2502
3163
|
|
|
@@ -2520,7 +3181,6 @@ Available functions are listed inside <tools></tools>.
|
|
|
2520
3181
|
});
|
|
2521
3182
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2522
3183
|
0 && (module.exports = {
|
|
2523
|
-
RJSON,
|
|
2524
3184
|
createDynamicIfThenElseSchema,
|
|
2525
3185
|
createToolMiddleware,
|
|
2526
3186
|
decodeOriginalTools,
|
|
@@ -2537,6 +3197,7 @@ Available functions are listed inside <tools></tools>.
|
|
|
2537
3197
|
isToolChoiceActive,
|
|
2538
3198
|
isToolResultPart,
|
|
2539
3199
|
jsonMixProtocol,
|
|
3200
|
+
logParseFailure,
|
|
2540
3201
|
logParsedChunk,
|
|
2541
3202
|
logParsedSummary,
|
|
2542
3203
|
logRawChunk,
|