@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/community.cjs
CHANGED
|
@@ -25,11 +25,8 @@ __export(community_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(community_exports);
|
|
27
27
|
|
|
28
|
-
// src/protocols/dummy-protocol.ts
|
|
29
|
-
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
30
|
-
|
|
31
28
|
// src/protocols/json-mix-protocol.ts
|
|
32
|
-
var
|
|
29
|
+
var import_provider_utils = require("@ai-sdk/provider-utils");
|
|
33
30
|
|
|
34
31
|
// src/utils/debug.ts
|
|
35
32
|
var LINE_SPLIT_REGEX = /\r?\n/;
|
|
@@ -77,6 +74,7 @@ var cBgGreen = color(ANSI_BG_GREEN);
|
|
|
77
74
|
var cInverse = color(ANSI_INVERSE);
|
|
78
75
|
var cUnderline = color(ANSI_UNDERLINE);
|
|
79
76
|
var cBold = color(ANSI_BOLD);
|
|
77
|
+
var MAX_SNIPPET_LENGTH = 800;
|
|
80
78
|
function safeStringify(value) {
|
|
81
79
|
try {
|
|
82
80
|
return `
|
|
@@ -85,6 +83,41 @@ ${typeof value === "string" ? value : JSON.stringify(value, null, 2)}`;
|
|
|
85
83
|
return String(value);
|
|
86
84
|
}
|
|
87
85
|
}
|
|
86
|
+
function formatError(error) {
|
|
87
|
+
if (error instanceof Error) {
|
|
88
|
+
const stack = error.stack ? `
|
|
89
|
+
${error.stack}` : "";
|
|
90
|
+
return `
|
|
91
|
+
${error.name}: ${error.message}${stack}`;
|
|
92
|
+
}
|
|
93
|
+
return safeStringify(error);
|
|
94
|
+
}
|
|
95
|
+
function truncateSnippet(snippet) {
|
|
96
|
+
if (snippet.length <= MAX_SNIPPET_LENGTH) {
|
|
97
|
+
return snippet;
|
|
98
|
+
}
|
|
99
|
+
return `${snippet.slice(0, MAX_SNIPPET_LENGTH)}
|
|
100
|
+
\u2026[truncated ${snippet.length - MAX_SNIPPET_LENGTH} chars]`;
|
|
101
|
+
}
|
|
102
|
+
function logParseFailure({
|
|
103
|
+
phase,
|
|
104
|
+
reason,
|
|
105
|
+
snippet,
|
|
106
|
+
error
|
|
107
|
+
}) {
|
|
108
|
+
if (getDebugLevel() !== "parse") {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const label = cBgBlue(`[${phase}]`);
|
|
112
|
+
console.log(cGray("[debug:mw:fail]"), label, cYellow(reason));
|
|
113
|
+
if (snippet) {
|
|
114
|
+
const formatted = truncateSnippet(snippet);
|
|
115
|
+
console.log(cGray("[debug:mw:fail:snippet]"), formatted);
|
|
116
|
+
}
|
|
117
|
+
if (error) {
|
|
118
|
+
console.log(cGray("[debug:mw:fail:error]"), cCyan(formatError(error)));
|
|
119
|
+
}
|
|
120
|
+
}
|
|
88
121
|
function logRawChunk(part) {
|
|
89
122
|
console.log(cGray("[debug:mw:raw]"), cYellow(safeStringify(part)));
|
|
90
123
|
}
|
|
@@ -150,63 +183,6 @@ ${rendered}`);
|
|
|
150
183
|
}
|
|
151
184
|
}
|
|
152
185
|
|
|
153
|
-
// src/utils/dynamic-tool-schema.ts
|
|
154
|
-
function createDynamicIfThenElseSchema(tools) {
|
|
155
|
-
let currentSchema = {};
|
|
156
|
-
const toolNames = [];
|
|
157
|
-
for (let i = tools.length - 1; i >= 0; i -= 1) {
|
|
158
|
-
const tool = tools[i];
|
|
159
|
-
if (tool.type === "provider-defined") {
|
|
160
|
-
throw new Error(
|
|
161
|
-
"Provider-defined tools are not supported by this middleware. Please use custom tools."
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
toolNames.unshift(tool.name);
|
|
165
|
-
const toolCondition = {
|
|
166
|
-
if: {
|
|
167
|
-
properties: {
|
|
168
|
-
name: {
|
|
169
|
-
const: tool.name
|
|
170
|
-
}
|
|
171
|
-
},
|
|
172
|
-
required: ["name"]
|
|
173
|
-
},
|
|
174
|
-
// biome-ignore lint/suspicious/noThenProperty: JSON Schema uses 'then' as a keyword
|
|
175
|
-
then: {
|
|
176
|
-
properties: {
|
|
177
|
-
name: {
|
|
178
|
-
const: tool.name
|
|
179
|
-
},
|
|
180
|
-
arguments: tool.inputSchema
|
|
181
|
-
},
|
|
182
|
-
required: ["name", "arguments"]
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
if (Object.keys(currentSchema).length > 0) {
|
|
186
|
-
toolCondition.else = currentSchema;
|
|
187
|
-
}
|
|
188
|
-
currentSchema = toolCondition;
|
|
189
|
-
}
|
|
190
|
-
return {
|
|
191
|
-
type: "object",
|
|
192
|
-
// Explicitly specify type as "object"
|
|
193
|
-
properties: {
|
|
194
|
-
name: {
|
|
195
|
-
type: "string",
|
|
196
|
-
description: "Name of the tool to call",
|
|
197
|
-
enum: toolNames
|
|
198
|
-
},
|
|
199
|
-
arguments: {
|
|
200
|
-
type: "object",
|
|
201
|
-
// By default, arguments is also specified as object type
|
|
202
|
-
description: "Argument object to be passed to the tool"
|
|
203
|
-
}
|
|
204
|
-
},
|
|
205
|
-
required: ["name", "arguments"],
|
|
206
|
-
...currentSchema
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
186
|
// src/utils/get-potential-start-index.ts
|
|
211
187
|
function getPotentialStartIndex(text, searchedText) {
|
|
212
188
|
if (searchedText.length === 0) {
|
|
@@ -225,57 +201,12 @@ function getPotentialStartIndex(text, searchedText) {
|
|
|
225
201
|
return null;
|
|
226
202
|
}
|
|
227
203
|
|
|
228
|
-
// src/utils/on-error.ts
|
|
229
|
-
function extractOnErrorOption(providerOptions) {
|
|
230
|
-
var _a;
|
|
231
|
-
if (providerOptions && typeof providerOptions === "object") {
|
|
232
|
-
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
233
|
-
return onError ? { onError } : void 0;
|
|
234
|
-
}
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// src/utils/provider-options.ts
|
|
239
|
-
var originalToolsSchema = {
|
|
240
|
-
encode: encodeOriginalTools,
|
|
241
|
-
decode: decodeOriginalTools
|
|
242
|
-
};
|
|
243
|
-
function encodeOriginalTools(tools) {
|
|
244
|
-
return (tools == null ? void 0 : tools.map((t) => ({
|
|
245
|
-
name: t.name,
|
|
246
|
-
inputSchema: JSON.stringify(t.inputSchema)
|
|
247
|
-
}))) || [];
|
|
248
|
-
}
|
|
249
|
-
function decodeOriginalTools(originalTools) {
|
|
250
|
-
if (!originalTools) {
|
|
251
|
-
return [];
|
|
252
|
-
}
|
|
253
|
-
return originalTools.map(
|
|
254
|
-
(t) => ({
|
|
255
|
-
type: "function",
|
|
256
|
-
name: t.name,
|
|
257
|
-
inputSchema: JSON.parse(t.inputSchema)
|
|
258
|
-
})
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
function isToolChoiceActive(params) {
|
|
262
|
-
var _a, _b, _c;
|
|
263
|
-
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
264
|
-
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"));
|
|
265
|
-
}
|
|
266
|
-
|
|
267
204
|
// src/utils/regex.ts
|
|
268
205
|
function escapeRegExp(literal) {
|
|
269
206
|
return literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
270
207
|
}
|
|
271
208
|
|
|
272
209
|
// src/utils/robust-json.ts
|
|
273
|
-
var robust_json_exports = {};
|
|
274
|
-
__export(robust_json_exports, {
|
|
275
|
-
parse: () => parse,
|
|
276
|
-
stringify: () => stringify,
|
|
277
|
-
transform: () => transform
|
|
278
|
-
});
|
|
279
210
|
var WHITESPACE_TEST_REGEX = /\s/;
|
|
280
211
|
var WHITESPACE_REGEX = /^\s+/;
|
|
281
212
|
var OBJECT_START_REGEX = /^\{/;
|
|
@@ -516,11 +447,6 @@ function stripTrailingComma(tokens) {
|
|
|
516
447
|
});
|
|
517
448
|
return res;
|
|
518
449
|
}
|
|
519
|
-
function transform(text) {
|
|
520
|
-
let tokens = lexer(text);
|
|
521
|
-
tokens = stripTrailingComma(tokens);
|
|
522
|
-
return tokens.reduce((str, token) => str + token.match, "");
|
|
523
|
-
}
|
|
524
450
|
function popToken(tokens, state) {
|
|
525
451
|
var _a, _b;
|
|
526
452
|
const token = tokens[state.pos];
|
|
@@ -916,38 +842,6 @@ function parse(text, optsOrReviver) {
|
|
|
916
842
|
}
|
|
917
843
|
return parseWithTransform(text, options);
|
|
918
844
|
}
|
|
919
|
-
function stringifyPair(obj, key) {
|
|
920
|
-
return `${JSON.stringify(key)}:${stringify(obj[key])}`;
|
|
921
|
-
}
|
|
922
|
-
function stringify(obj) {
|
|
923
|
-
const type = typeof obj;
|
|
924
|
-
if (type === "string" || type === "number" || type === "boolean" || obj === null) {
|
|
925
|
-
return JSON.stringify(obj);
|
|
926
|
-
}
|
|
927
|
-
if (type === "undefined") {
|
|
928
|
-
return "null";
|
|
929
|
-
}
|
|
930
|
-
if (Array.isArray(obj)) {
|
|
931
|
-
const elements = obj.map(stringify).join(",");
|
|
932
|
-
return `[${elements}]`;
|
|
933
|
-
}
|
|
934
|
-
if (type === "object") {
|
|
935
|
-
const keys = Object.keys(obj);
|
|
936
|
-
keys.sort();
|
|
937
|
-
const pairs = keys.map((key) => stringifyPair(obj, key)).join(",");
|
|
938
|
-
return `{${pairs}}`;
|
|
939
|
-
}
|
|
940
|
-
return "null";
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
// src/utils/type-guards.ts
|
|
944
|
-
function isToolCallContent(content) {
|
|
945
|
-
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
946
|
-
(typeof content.input === "string" || typeof content.input === "object");
|
|
947
|
-
}
|
|
948
|
-
function hasInputProperty(obj) {
|
|
949
|
-
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
950
|
-
}
|
|
951
845
|
|
|
952
846
|
// src/protocols/json-mix-protocol.ts
|
|
953
847
|
function processToolCallJson(toolCallJson, fullMatch, processedElements, options) {
|
|
@@ -956,11 +850,17 @@ function processToolCallJson(toolCallJson, fullMatch, processedElements, options
|
|
|
956
850
|
const parsedToolCall = parse(toolCallJson);
|
|
957
851
|
processedElements.push({
|
|
958
852
|
type: "tool-call",
|
|
959
|
-
toolCallId: (0,
|
|
853
|
+
toolCallId: (0, import_provider_utils.generateId)(),
|
|
960
854
|
toolName: parsedToolCall.name,
|
|
961
855
|
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
962
856
|
});
|
|
963
857
|
} catch (error) {
|
|
858
|
+
logParseFailure({
|
|
859
|
+
phase: "generated-text",
|
|
860
|
+
reason: "Failed to parse tool call JSON segment",
|
|
861
|
+
snippet: fullMatch,
|
|
862
|
+
error
|
|
863
|
+
});
|
|
964
864
|
if (options == null ? void 0 : options.onError) {
|
|
965
865
|
options.onError(
|
|
966
866
|
"Could not process JSON tool call, keeping original text.",
|
|
@@ -993,7 +893,7 @@ function flushBuffer(state, controller, toolCallStart) {
|
|
|
993
893
|
return;
|
|
994
894
|
}
|
|
995
895
|
if (!state.currentTextId) {
|
|
996
|
-
state.currentTextId = (0,
|
|
896
|
+
state.currentTextId = (0, import_provider_utils.generateId)();
|
|
997
897
|
controller.enqueue({ type: "text-start", id: state.currentTextId });
|
|
998
898
|
state.hasEmittedTextStart = true;
|
|
999
899
|
}
|
|
@@ -1016,7 +916,12 @@ function emitIncompleteToolCall(state, controller, toolCallStart) {
|
|
|
1016
916
|
if (!state.currentToolCallJson) {
|
|
1017
917
|
return;
|
|
1018
918
|
}
|
|
1019
|
-
|
|
919
|
+
logParseFailure({
|
|
920
|
+
phase: "stream",
|
|
921
|
+
reason: "Incomplete streaming tool call segment emitted as text",
|
|
922
|
+
snippet: `${toolCallStart}${state.currentToolCallJson}`
|
|
923
|
+
});
|
|
924
|
+
const errorId = (0, import_provider_utils.generateId)();
|
|
1020
925
|
controller.enqueue({ type: "text-start", id: errorId });
|
|
1021
926
|
controller.enqueue({
|
|
1022
927
|
type: "text-delta",
|
|
@@ -1040,7 +945,7 @@ function publishText(text, state, controller) {
|
|
|
1040
945
|
state.currentToolCallJson += text;
|
|
1041
946
|
} else if (text.length > 0) {
|
|
1042
947
|
if (!state.currentTextId) {
|
|
1043
|
-
state.currentTextId = (0,
|
|
948
|
+
state.currentTextId = (0, import_provider_utils.generateId)();
|
|
1044
949
|
controller.enqueue({ type: "text-start", id: state.currentTextId });
|
|
1045
950
|
state.hasEmittedTextStart = true;
|
|
1046
951
|
}
|
|
@@ -1055,16 +960,22 @@ function emitToolCall(context) {
|
|
|
1055
960
|
var _a;
|
|
1056
961
|
const { state, controller, toolCallStart, toolCallEnd, options } = context;
|
|
1057
962
|
try {
|
|
1058
|
-
const parsedToolCall =
|
|
963
|
+
const parsedToolCall = parse(state.currentToolCallJson);
|
|
1059
964
|
closeTextBlock(state, controller);
|
|
1060
965
|
controller.enqueue({
|
|
1061
966
|
type: "tool-call",
|
|
1062
|
-
toolCallId: (0,
|
|
967
|
+
toolCallId: (0, import_provider_utils.generateId)(),
|
|
1063
968
|
toolName: parsedToolCall.name,
|
|
1064
969
|
input: JSON.stringify((_a = parsedToolCall.arguments) != null ? _a : {})
|
|
1065
970
|
});
|
|
1066
|
-
} catch (
|
|
1067
|
-
|
|
971
|
+
} catch (error) {
|
|
972
|
+
logParseFailure({
|
|
973
|
+
phase: "stream",
|
|
974
|
+
reason: "Failed to parse streaming tool call JSON segment",
|
|
975
|
+
snippet: `${toolCallStart}${state.currentToolCallJson}${toolCallEnd}`,
|
|
976
|
+
error
|
|
977
|
+
});
|
|
978
|
+
const errorId = (0, import_provider_utils.generateId)();
|
|
1068
979
|
controller.enqueue({ type: "text-start", id: errorId });
|
|
1069
980
|
controller.enqueue({
|
|
1070
981
|
type: "text-delta",
|
|
@@ -1229,9 +1140,336 @@ var jsonMixProtocol = ({
|
|
|
1229
1140
|
});
|
|
1230
1141
|
|
|
1231
1142
|
// src/protocols/morph-xml-protocol.ts
|
|
1232
|
-
var
|
|
1143
|
+
var import_provider_utils2 = require("@ai-sdk/provider-utils");
|
|
1233
1144
|
var import_rxml = require("@ai-sdk-tool/rxml");
|
|
1145
|
+
|
|
1146
|
+
// src/utils/type-guards.ts
|
|
1147
|
+
function isToolCallContent(content) {
|
|
1148
|
+
return content.type === "tool-call" && typeof content.toolName === "string" && // input may be a JSON string or an already-parsed object depending on provider/runtime
|
|
1149
|
+
(typeof content.input === "string" || typeof content.input === "object");
|
|
1150
|
+
}
|
|
1151
|
+
function hasInputProperty(obj) {
|
|
1152
|
+
return typeof obj === "object" && obj !== null && "input" in obj;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
// src/protocols/morph-xml-protocol.ts
|
|
1234
1156
|
var WHITESPACE_REGEX2 = /\s/;
|
|
1157
|
+
var MALFORMED_CLOSE_RE = /<\/\s+([A-Za-z0-9_:-]+)\s*>/;
|
|
1158
|
+
var MALFORMED_CLOSE_RE_G = /<\/\s+([A-Za-z0-9_:-]+)\s*>/g;
|
|
1159
|
+
var NAME_CHAR_RE = /[A-Za-z0-9_:-]/;
|
|
1160
|
+
var STATUS_TO_STEP_BOUNDARY_RE = /<\/status>\s*<step>/g;
|
|
1161
|
+
var STEP_TAG_RE = /<step>([\s\S]*?)<\/step>/i;
|
|
1162
|
+
var STATUS_TAG_RE = /<status>([\s\S]*?)<\/status>/i;
|
|
1163
|
+
function normalizeCloseTags(xml) {
|
|
1164
|
+
return xml.replace(MALFORMED_CLOSE_RE_G, "</$1>");
|
|
1165
|
+
}
|
|
1166
|
+
function escapeInvalidLt(xml) {
|
|
1167
|
+
const len = xml.length;
|
|
1168
|
+
let out = "";
|
|
1169
|
+
for (let i = 0; i < len; i += 1) {
|
|
1170
|
+
const ch = xml[i];
|
|
1171
|
+
if (ch === "<") {
|
|
1172
|
+
const next = i + 1 < len ? xml[i + 1] : "";
|
|
1173
|
+
if (!(NAME_CHAR_RE.test(next) || next === "/" || next === "!" || next === "?")) {
|
|
1174
|
+
out += "<";
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
out += ch;
|
|
1179
|
+
}
|
|
1180
|
+
return out;
|
|
1181
|
+
}
|
|
1182
|
+
function shouldDeduplicateStringTags(schema) {
|
|
1183
|
+
const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
|
|
1184
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
1185
|
+
return false;
|
|
1186
|
+
}
|
|
1187
|
+
const props = unwrapped.properties;
|
|
1188
|
+
if (!props) {
|
|
1189
|
+
return false;
|
|
1190
|
+
}
|
|
1191
|
+
const commandRaw = props.command;
|
|
1192
|
+
if (!commandRaw) {
|
|
1193
|
+
return false;
|
|
1194
|
+
}
|
|
1195
|
+
const command = (0, import_rxml.unwrapJsonSchema)(commandRaw);
|
|
1196
|
+
return (command == null ? void 0 : command.type) === "array";
|
|
1197
|
+
}
|
|
1198
|
+
function tryParseSecondaryXml(content, toolSchema, options) {
|
|
1199
|
+
const normalized = normalizeCloseTags(content);
|
|
1200
|
+
const balanced = balanceTags(content);
|
|
1201
|
+
const hasMalformedClose = MALFORMED_CLOSE_RE.test(content);
|
|
1202
|
+
if (!hasMalformedClose && balanced.length > normalized.length) {
|
|
1203
|
+
return null;
|
|
1204
|
+
}
|
|
1205
|
+
try {
|
|
1206
|
+
let parsed = (0, import_rxml.parse)(balanced, toolSchema, {
|
|
1207
|
+
onError: options == null ? void 0 : options.onError,
|
|
1208
|
+
noChildNodes: []
|
|
1209
|
+
});
|
|
1210
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema, options);
|
|
1211
|
+
return parsed;
|
|
1212
|
+
} catch (_e) {
|
|
1213
|
+
if (shouldDeduplicateStringTags(toolSchema)) {
|
|
1214
|
+
const deduped = dedupeStringTagsAgainstSchema(balanced, toolSchema);
|
|
1215
|
+
if (deduped !== balanced) {
|
|
1216
|
+
try {
|
|
1217
|
+
let reparsed = (0, import_rxml.parse)(deduped, toolSchema, {
|
|
1218
|
+
onError: options == null ? void 0 : options.onError,
|
|
1219
|
+
noChildNodes: []
|
|
1220
|
+
});
|
|
1221
|
+
reparsed = repairParsedAgainstSchema(reparsed, toolSchema, options);
|
|
1222
|
+
return reparsed;
|
|
1223
|
+
} catch (_) {
|
|
1224
|
+
return null;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
return null;
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
function balanceTags(xml) {
|
|
1232
|
+
const src = normalizeCloseTags(xml).replace(
|
|
1233
|
+
STATUS_TO_STEP_BOUNDARY_RE,
|
|
1234
|
+
"</status></step><step>"
|
|
1235
|
+
);
|
|
1236
|
+
let i = 0;
|
|
1237
|
+
const len = src.length;
|
|
1238
|
+
const out = [];
|
|
1239
|
+
const stack = [];
|
|
1240
|
+
while (i < len) {
|
|
1241
|
+
const lt = src.indexOf("<", i);
|
|
1242
|
+
if (lt === -1) {
|
|
1243
|
+
out.push(src.slice(i));
|
|
1244
|
+
break;
|
|
1245
|
+
}
|
|
1246
|
+
out.push(src.slice(i, lt));
|
|
1247
|
+
if (lt + 1 >= len) {
|
|
1248
|
+
break;
|
|
1249
|
+
}
|
|
1250
|
+
const next = src[lt + 1];
|
|
1251
|
+
if (next === "!" || next === "?") {
|
|
1252
|
+
i = handleSpecialTagSegment(src, lt, out);
|
|
1253
|
+
continue;
|
|
1254
|
+
}
|
|
1255
|
+
if (next === "/") {
|
|
1256
|
+
i = handleClosingTagSegment(src, lt, out, stack);
|
|
1257
|
+
continue;
|
|
1258
|
+
}
|
|
1259
|
+
i = handleOpeningTagSegment(src, lt, out, stack);
|
|
1260
|
+
}
|
|
1261
|
+
for (let k = stack.length - 1; k >= 0; k -= 1) {
|
|
1262
|
+
out.push(`</${stack[k]}>`);
|
|
1263
|
+
}
|
|
1264
|
+
return out.join("");
|
|
1265
|
+
}
|
|
1266
|
+
function skipWs(s, p, len) {
|
|
1267
|
+
let idx = p;
|
|
1268
|
+
while (idx < len && WHITESPACE_REGEX2.test(s[idx])) {
|
|
1269
|
+
idx += 1;
|
|
1270
|
+
}
|
|
1271
|
+
return idx;
|
|
1272
|
+
}
|
|
1273
|
+
function parseTagNameAt(s, p, len) {
|
|
1274
|
+
let idx = p;
|
|
1275
|
+
const start = idx;
|
|
1276
|
+
while (idx < len && NAME_CHAR_RE.test(s[idx])) {
|
|
1277
|
+
idx += 1;
|
|
1278
|
+
}
|
|
1279
|
+
return { name: s.slice(start, idx), pos: idx };
|
|
1280
|
+
}
|
|
1281
|
+
function handleSpecialTagSegment(src, lt, out) {
|
|
1282
|
+
const gt = src.indexOf(">", lt + 1);
|
|
1283
|
+
if (gt === -1) {
|
|
1284
|
+
out.push(src.slice(lt));
|
|
1285
|
+
return src.length;
|
|
1286
|
+
}
|
|
1287
|
+
out.push(src.slice(lt, gt + 1));
|
|
1288
|
+
return gt + 1;
|
|
1289
|
+
}
|
|
1290
|
+
function handleClosingTagSegment(src, lt, out, stack) {
|
|
1291
|
+
const len = src.length;
|
|
1292
|
+
let p = skipWs(src, lt + 2, len);
|
|
1293
|
+
const { name, pos } = parseTagNameAt(src, p, len);
|
|
1294
|
+
p = pos;
|
|
1295
|
+
const gt = src.indexOf(">", p);
|
|
1296
|
+
const closingText = gt === -1 ? src.slice(lt) : src.slice(lt, gt + 1);
|
|
1297
|
+
const idx = stack.lastIndexOf(name);
|
|
1298
|
+
if (idx !== -1) {
|
|
1299
|
+
for (let k = stack.length - 1; k > idx; k -= 1) {
|
|
1300
|
+
out.push(`</${stack[k]}>`);
|
|
1301
|
+
stack.pop();
|
|
1302
|
+
}
|
|
1303
|
+
out.push(closingText);
|
|
1304
|
+
stack.pop();
|
|
1305
|
+
}
|
|
1306
|
+
return gt === -1 ? len : gt + 1;
|
|
1307
|
+
}
|
|
1308
|
+
function handleOpeningTagSegment(src, lt, out, stack) {
|
|
1309
|
+
const len = src.length;
|
|
1310
|
+
let p = skipWs(src, lt + 1, len);
|
|
1311
|
+
const nameStart = p;
|
|
1312
|
+
const parsed = parseTagNameAt(src, p, len);
|
|
1313
|
+
p = parsed.pos;
|
|
1314
|
+
const name = src.slice(nameStart, p);
|
|
1315
|
+
const q = src.indexOf(">", p);
|
|
1316
|
+
if (q === -1) {
|
|
1317
|
+
out.push(src.slice(lt));
|
|
1318
|
+
return len;
|
|
1319
|
+
}
|
|
1320
|
+
let r = q - 1;
|
|
1321
|
+
while (r >= nameStart && WHITESPACE_REGEX2.test(src[r])) {
|
|
1322
|
+
r -= 1;
|
|
1323
|
+
}
|
|
1324
|
+
const selfClosing = src[r] === "/";
|
|
1325
|
+
out.push(src.slice(lt, q + 1));
|
|
1326
|
+
if (!selfClosing && name) {
|
|
1327
|
+
stack.push(name);
|
|
1328
|
+
}
|
|
1329
|
+
return q + 1;
|
|
1330
|
+
}
|
|
1331
|
+
function repairParsedAgainstSchema(input, schema, options) {
|
|
1332
|
+
if (!input || typeof input !== "object") {
|
|
1333
|
+
return input;
|
|
1334
|
+
}
|
|
1335
|
+
const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
|
|
1336
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
1337
|
+
return input;
|
|
1338
|
+
}
|
|
1339
|
+
const properties = unwrapped.properties;
|
|
1340
|
+
if (!properties) {
|
|
1341
|
+
return input;
|
|
1342
|
+
}
|
|
1343
|
+
applySchemaProps(input, properties, options);
|
|
1344
|
+
return input;
|
|
1345
|
+
}
|
|
1346
|
+
function applySchemaProps(obj, properties, options) {
|
|
1347
|
+
for (const key of Object.keys(obj)) {
|
|
1348
|
+
const propSchema = properties[key];
|
|
1349
|
+
if (!propSchema) {
|
|
1350
|
+
continue;
|
|
1351
|
+
}
|
|
1352
|
+
const prop = (0, import_rxml.unwrapJsonSchema)(propSchema);
|
|
1353
|
+
const propType = prop.type;
|
|
1354
|
+
if (propType === "array" && prop.items) {
|
|
1355
|
+
const itemSchemaRaw = prop.items;
|
|
1356
|
+
const itemSchema = (0, import_rxml.unwrapJsonSchema)(itemSchemaRaw);
|
|
1357
|
+
obj[key] = coerceArrayItems(obj[key], itemSchema, options);
|
|
1358
|
+
continue;
|
|
1359
|
+
}
|
|
1360
|
+
if (propType === "object") {
|
|
1361
|
+
const val = obj[key];
|
|
1362
|
+
if (val && typeof val === "object") {
|
|
1363
|
+
obj[key] = repairParsedAgainstSchema(
|
|
1364
|
+
val,
|
|
1365
|
+
prop,
|
|
1366
|
+
options
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
function coerceArrayItems(val, itemSchema, options) {
|
|
1373
|
+
if (!Array.isArray(val)) {
|
|
1374
|
+
return val;
|
|
1375
|
+
}
|
|
1376
|
+
return val.map((v) => coerceArrayItem(v, itemSchema, options));
|
|
1377
|
+
}
|
|
1378
|
+
function coerceArrayItem(v, itemSchema, options) {
|
|
1379
|
+
const itemType = itemSchema == null ? void 0 : itemSchema.type;
|
|
1380
|
+
if (typeof v === "string" && itemType === "object") {
|
|
1381
|
+
const parsed = tryParseStringToSchemaObject(v, itemSchema, options);
|
|
1382
|
+
if (parsed !== null) {
|
|
1383
|
+
return parsed;
|
|
1384
|
+
}
|
|
1385
|
+
const fallback = extractStepStatusFromString(normalizeCloseTags(v));
|
|
1386
|
+
if (fallback) {
|
|
1387
|
+
return fallback;
|
|
1388
|
+
}
|
|
1389
|
+
return v;
|
|
1390
|
+
}
|
|
1391
|
+
if (v && typeof v === "object" && itemType === "object") {
|
|
1392
|
+
return repairParsedAgainstSchema(
|
|
1393
|
+
v,
|
|
1394
|
+
itemSchema,
|
|
1395
|
+
options
|
|
1396
|
+
);
|
|
1397
|
+
}
|
|
1398
|
+
return v;
|
|
1399
|
+
}
|
|
1400
|
+
function getStringPropertyNames(schema) {
|
|
1401
|
+
const unwrapped = (0, import_rxml.unwrapJsonSchema)(schema);
|
|
1402
|
+
if (!unwrapped || typeof unwrapped !== "object") {
|
|
1403
|
+
return [];
|
|
1404
|
+
}
|
|
1405
|
+
const props = unwrapped.properties;
|
|
1406
|
+
if (!props) {
|
|
1407
|
+
return [];
|
|
1408
|
+
}
|
|
1409
|
+
const names = [];
|
|
1410
|
+
for (const key of Object.keys(props)) {
|
|
1411
|
+
const prop = (0, import_rxml.unwrapJsonSchema)(
|
|
1412
|
+
props[key]
|
|
1413
|
+
);
|
|
1414
|
+
const type = prop.type;
|
|
1415
|
+
if (type === "string") {
|
|
1416
|
+
names.push(key);
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
return names;
|
|
1420
|
+
}
|
|
1421
|
+
function escapeRegExp2(s) {
|
|
1422
|
+
return s.replace(/[.*+?^${}()|[\\]\\]/g, "\\$&");
|
|
1423
|
+
}
|
|
1424
|
+
function dedupeStringTagsAgainstSchema(xml, schema) {
|
|
1425
|
+
const names = getStringPropertyNames(schema);
|
|
1426
|
+
let out = xml;
|
|
1427
|
+
for (const key of names) {
|
|
1428
|
+
out = dedupeSingleTag(out, key);
|
|
1429
|
+
}
|
|
1430
|
+
return out;
|
|
1431
|
+
}
|
|
1432
|
+
function dedupeSingleTag(xml, key) {
|
|
1433
|
+
var _a, _b;
|
|
1434
|
+
const escaped = escapeRegExp2(key);
|
|
1435
|
+
const re = new RegExp(`<${escaped}>([\\s\\S]*?)<\\/${escaped}>`, "g");
|
|
1436
|
+
const matches = Array.from(xml.matchAll(re));
|
|
1437
|
+
if (matches.length <= 1) {
|
|
1438
|
+
return xml;
|
|
1439
|
+
}
|
|
1440
|
+
const last = matches.at(-1);
|
|
1441
|
+
let result = "";
|
|
1442
|
+
let cursor = 0;
|
|
1443
|
+
for (const m of matches) {
|
|
1444
|
+
const idx = (_a = m.index) != null ? _a : 0;
|
|
1445
|
+
result += xml.slice(cursor, idx);
|
|
1446
|
+
if (last && idx === ((_b = last.index) != null ? _b : -1)) {
|
|
1447
|
+
result += m[0];
|
|
1448
|
+
}
|
|
1449
|
+
cursor = idx + m[0].length;
|
|
1450
|
+
}
|
|
1451
|
+
result += xml.slice(cursor);
|
|
1452
|
+
return result;
|
|
1453
|
+
}
|
|
1454
|
+
function tryParseStringToSchemaObject(xml, itemSchema, options) {
|
|
1455
|
+
try {
|
|
1456
|
+
const fixed = (0, import_rxml.parse)(normalizeCloseTags(xml), itemSchema, {
|
|
1457
|
+
onError: options == null ? void 0 : options.onError,
|
|
1458
|
+
noChildNodes: []
|
|
1459
|
+
});
|
|
1460
|
+
return typeof fixed === "string" ? null : fixed;
|
|
1461
|
+
} catch (e) {
|
|
1462
|
+
return null;
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
function extractStepStatusFromString(normXml) {
|
|
1466
|
+
const stepMatch = normXml.match(STEP_TAG_RE);
|
|
1467
|
+
const statusMatch = normXml.match(STATUS_TAG_RE);
|
|
1468
|
+
if (stepMatch && statusMatch) {
|
|
1469
|
+
return { step: stepMatch[1], status: statusMatch[1] };
|
|
1470
|
+
}
|
|
1471
|
+
return null;
|
|
1472
|
+
}
|
|
1235
1473
|
function processTextBeforeToolCall(text, currentIndex, toolCallStartIndex, processedElements) {
|
|
1236
1474
|
if (toolCallStartIndex > currentIndex) {
|
|
1237
1475
|
const textSegment = text.substring(currentIndex, toolCallStartIndex);
|
|
@@ -1244,20 +1482,36 @@ function processTextBeforeToolCall(text, currentIndex, toolCallStartIndex, proce
|
|
|
1244
1482
|
function processToolCall(params) {
|
|
1245
1483
|
var _a;
|
|
1246
1484
|
const { toolCall, tools, options, text, processedElements } = params;
|
|
1485
|
+
const toolSchema = getToolSchema(tools, toolCall.toolName);
|
|
1247
1486
|
try {
|
|
1248
|
-
const
|
|
1249
|
-
|
|
1487
|
+
const primary = escapeInvalidLt(normalizeCloseTags(toolCall.content));
|
|
1488
|
+
let parsed = (0, import_rxml.parse)(primary, toolSchema, {
|
|
1250
1489
|
onError: options == null ? void 0 : options.onError,
|
|
1251
1490
|
// Disable HTML self-closing tag behavior to allow base, meta, link etc. as regular tags
|
|
1252
1491
|
noChildNodes: []
|
|
1253
1492
|
});
|
|
1493
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema, options);
|
|
1254
1494
|
processedElements.push({
|
|
1255
1495
|
type: "tool-call",
|
|
1256
|
-
toolCallId: (0,
|
|
1496
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1257
1497
|
toolName: toolCall.toolName,
|
|
1258
1498
|
input: JSON.stringify(parsed)
|
|
1259
1499
|
});
|
|
1260
1500
|
} catch (error) {
|
|
1501
|
+
const reparsed = tryParseSecondaryXml(
|
|
1502
|
+
toolCall.content,
|
|
1503
|
+
toolSchema,
|
|
1504
|
+
options
|
|
1505
|
+
);
|
|
1506
|
+
if (reparsed !== null) {
|
|
1507
|
+
processedElements.push({
|
|
1508
|
+
type: "tool-call",
|
|
1509
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1510
|
+
toolName: toolCall.toolName,
|
|
1511
|
+
input: JSON.stringify(reparsed)
|
|
1512
|
+
});
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1261
1515
|
const originalCallText = text.substring(
|
|
1262
1516
|
toolCall.startIndex,
|
|
1263
1517
|
toolCall.endIndex
|
|
@@ -1281,20 +1535,33 @@ function addRemainingText(text, currentIndex, processedElements) {
|
|
|
1281
1535
|
}
|
|
1282
1536
|
function handleStreamingToolCallEnd(params) {
|
|
1283
1537
|
const { toolContent, currentToolCall, tools, options, ctrl, flushText } = params;
|
|
1538
|
+
const toolSchema = getToolSchema(tools, currentToolCall.name);
|
|
1284
1539
|
try {
|
|
1285
|
-
const
|
|
1286
|
-
|
|
1540
|
+
const primary = escapeInvalidLt(normalizeCloseTags(toolContent));
|
|
1541
|
+
let parsed = (0, import_rxml.parse)(primary, toolSchema, {
|
|
1287
1542
|
onError: options == null ? void 0 : options.onError,
|
|
1288
1543
|
noChildNodes: []
|
|
1289
1544
|
});
|
|
1545
|
+
parsed = repairParsedAgainstSchema(parsed, toolSchema, options);
|
|
1290
1546
|
flushText(ctrl);
|
|
1291
1547
|
ctrl.enqueue({
|
|
1292
1548
|
type: "tool-call",
|
|
1293
|
-
toolCallId: (0,
|
|
1549
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1294
1550
|
toolName: currentToolCall.name,
|
|
1295
1551
|
input: JSON.stringify(parsed)
|
|
1296
1552
|
});
|
|
1297
1553
|
} catch (error) {
|
|
1554
|
+
const parsed = tryParseSecondaryXml(toolContent, toolSchema, options);
|
|
1555
|
+
if (parsed !== null) {
|
|
1556
|
+
flushText(ctrl);
|
|
1557
|
+
ctrl.enqueue({
|
|
1558
|
+
type: "tool-call",
|
|
1559
|
+
toolCallId: (0, import_provider_utils2.generateId)(),
|
|
1560
|
+
toolName: currentToolCall.name,
|
|
1561
|
+
input: JSON.stringify(parsed)
|
|
1562
|
+
});
|
|
1563
|
+
return;
|
|
1564
|
+
}
|
|
1298
1565
|
handleStreamingToolCallError({
|
|
1299
1566
|
error,
|
|
1300
1567
|
currentToolCall,
|
|
@@ -1326,19 +1593,28 @@ function handleStreamingToolCallError(params) {
|
|
|
1326
1593
|
flushText(ctrl, originalCallText);
|
|
1327
1594
|
}
|
|
1328
1595
|
function findEarliestToolTag(buffer, toolNames) {
|
|
1329
|
-
let
|
|
1330
|
-
let
|
|
1596
|
+
let bestIndex = -1;
|
|
1597
|
+
let bestName = "";
|
|
1598
|
+
let bestSelfClosing = false;
|
|
1331
1599
|
if (toolNames.length > 0) {
|
|
1332
1600
|
for (const name of toolNames) {
|
|
1333
|
-
const
|
|
1334
|
-
const
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1601
|
+
const openTag = `<${name}>`;
|
|
1602
|
+
const selfTag = `<${name}/>`;
|
|
1603
|
+
const idxOpen = buffer.indexOf(openTag);
|
|
1604
|
+
const idxSelf = buffer.indexOf(selfTag);
|
|
1605
|
+
if (idxOpen !== -1 && (bestIndex === -1 || idxOpen < bestIndex)) {
|
|
1606
|
+
bestIndex = idxOpen;
|
|
1607
|
+
bestName = name;
|
|
1608
|
+
bestSelfClosing = false;
|
|
1609
|
+
}
|
|
1610
|
+
if (idxSelf !== -1 && (bestIndex === -1 || idxSelf < bestIndex)) {
|
|
1611
|
+
bestIndex = idxSelf;
|
|
1612
|
+
bestName = name;
|
|
1613
|
+
bestSelfClosing = true;
|
|
1338
1614
|
}
|
|
1339
1615
|
}
|
|
1340
1616
|
}
|
|
1341
|
-
return { index:
|
|
1617
|
+
return { index: bestIndex, name: bestName, selfClosing: bestSelfClosing };
|
|
1342
1618
|
}
|
|
1343
1619
|
function handleNoToolTagInBuffer(buffer, maxStartTagLen, controller, flushText) {
|
|
1344
1620
|
const tail = Math.max(0, maxStartTagLen - 1);
|
|
@@ -1361,10 +1637,12 @@ function processToolCallInBuffer(params) {
|
|
|
1361
1637
|
setBuffer
|
|
1362
1638
|
} = params;
|
|
1363
1639
|
const endTag = `</${currentToolCall.name}>`;
|
|
1364
|
-
const
|
|
1640
|
+
const normalized = normalizeCloseTags(buffer);
|
|
1641
|
+
const effectiveBuffer = normalized;
|
|
1642
|
+
const endTagIndex = effectiveBuffer.indexOf(endTag);
|
|
1365
1643
|
if (endTagIndex !== -1) {
|
|
1366
|
-
const toolContent =
|
|
1367
|
-
const newBuffer =
|
|
1644
|
+
const toolContent = effectiveBuffer.substring(0, endTagIndex);
|
|
1645
|
+
const newBuffer = effectiveBuffer.substring(endTagIndex + endTag.length);
|
|
1368
1646
|
setBuffer("");
|
|
1369
1647
|
handleStreamingToolCallEnd({
|
|
1370
1648
|
toolContent,
|
|
@@ -1377,14 +1655,46 @@ function processToolCallInBuffer(params) {
|
|
|
1377
1655
|
setBuffer(newBuffer);
|
|
1378
1656
|
return { buffer: newBuffer, currentToolCall: null, shouldBreak: false };
|
|
1379
1657
|
}
|
|
1380
|
-
return { buffer, currentToolCall, shouldBreak: true };
|
|
1658
|
+
return { buffer: effectiveBuffer, currentToolCall, shouldBreak: true };
|
|
1381
1659
|
}
|
|
1382
1660
|
function processNoToolCallInBuffer(params) {
|
|
1383
|
-
const {
|
|
1384
|
-
|
|
1661
|
+
const {
|
|
1662
|
+
buffer,
|
|
1663
|
+
toolNames,
|
|
1664
|
+
maxStartTagLen,
|
|
1665
|
+
controller,
|
|
1666
|
+
flushText,
|
|
1667
|
+
tools,
|
|
1668
|
+
options
|
|
1669
|
+
} = params;
|
|
1670
|
+
const {
|
|
1671
|
+
index: earliestStartTagIndex,
|
|
1672
|
+
name: earliestToolName,
|
|
1673
|
+
selfClosing
|
|
1674
|
+
} = findEarliestToolTag(buffer, toolNames);
|
|
1385
1675
|
if (earliestStartTagIndex !== -1) {
|
|
1386
1676
|
const textBeforeTag = buffer.substring(0, earliestStartTagIndex);
|
|
1387
1677
|
flushText(controller, textBeforeTag);
|
|
1678
|
+
if (selfClosing) {
|
|
1679
|
+
const selfTag = `<${earliestToolName}/>`;
|
|
1680
|
+
const newBuffer2 = buffer.substring(
|
|
1681
|
+
earliestStartTagIndex + selfTag.length
|
|
1682
|
+
);
|
|
1683
|
+
handleStreamingToolCallEnd({
|
|
1684
|
+
toolContent: "",
|
|
1685
|
+
currentToolCall: { name: earliestToolName, content: "" },
|
|
1686
|
+
tools,
|
|
1687
|
+
options,
|
|
1688
|
+
ctrl: controller,
|
|
1689
|
+
flushText
|
|
1690
|
+
});
|
|
1691
|
+
return {
|
|
1692
|
+
buffer: newBuffer2,
|
|
1693
|
+
currentToolCall: null,
|
|
1694
|
+
shouldBreak: false,
|
|
1695
|
+
shouldContinue: false
|
|
1696
|
+
};
|
|
1697
|
+
}
|
|
1388
1698
|
const startTag = `<${earliestToolName}>`;
|
|
1389
1699
|
const newBuffer = buffer.substring(earliestStartTagIndex + startTag.length);
|
|
1390
1700
|
return {
|
|
@@ -1413,7 +1723,7 @@ function createFlushTextHandler(getBuffer, setBuffer, getCurrentTextId, setCurre
|
|
|
1413
1723
|
if (content) {
|
|
1414
1724
|
const currentTextId2 = getCurrentTextId();
|
|
1415
1725
|
if (!currentTextId2) {
|
|
1416
|
-
const newId = (0,
|
|
1726
|
+
const newId = (0, import_provider_utils2.generateId)();
|
|
1417
1727
|
setCurrentTextId(newId);
|
|
1418
1728
|
controller.enqueue({ type: "text-start", id: newId });
|
|
1419
1729
|
}
|
|
@@ -1465,6 +1775,8 @@ function processBufferWithoutToolCall(params, controller) {
|
|
|
1465
1775
|
getBuffer,
|
|
1466
1776
|
setBuffer,
|
|
1467
1777
|
setCurrentToolCall,
|
|
1778
|
+
tools,
|
|
1779
|
+
options,
|
|
1468
1780
|
toolNames,
|
|
1469
1781
|
maxStartTagLen,
|
|
1470
1782
|
flushText
|
|
@@ -1474,7 +1786,9 @@ function processBufferWithoutToolCall(params, controller) {
|
|
|
1474
1786
|
toolNames,
|
|
1475
1787
|
maxStartTagLen,
|
|
1476
1788
|
controller,
|
|
1477
|
-
flushText
|
|
1789
|
+
flushText,
|
|
1790
|
+
tools,
|
|
1791
|
+
options
|
|
1478
1792
|
});
|
|
1479
1793
|
setBuffer(result.buffer);
|
|
1480
1794
|
setCurrentToolCall(result.currentToolCall);
|
|
@@ -1549,7 +1863,17 @@ var morphXmlProtocol = () => ({
|
|
|
1549
1863
|
}
|
|
1550
1864
|
const processedElements = [];
|
|
1551
1865
|
let currentIndex = 0;
|
|
1552
|
-
const
|
|
1866
|
+
const toolCallsRaw = findToolCalls(text, toolNames);
|
|
1867
|
+
const toolCallsNorm = collectToolCallsFromNormalizedText(text, toolNames);
|
|
1868
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1869
|
+
const toolCalls = [...toolCallsRaw, ...toolCallsNorm].filter((tc) => {
|
|
1870
|
+
const key = `${tc.toolName}:${tc.startIndex}:${tc.endIndex}`;
|
|
1871
|
+
if (seen.has(key)) {
|
|
1872
|
+
return false;
|
|
1873
|
+
}
|
|
1874
|
+
seen.add(key);
|
|
1875
|
+
return true;
|
|
1876
|
+
}).sort((a, b) => a.startIndex - b.startIndex);
|
|
1553
1877
|
for (const toolCall of toolCalls) {
|
|
1554
1878
|
currentIndex = processTextBeforeToolCall(
|
|
1555
1879
|
text,
|
|
@@ -1637,53 +1961,225 @@ function getToolSchema(tools, toolName) {
|
|
|
1637
1961
|
var _a;
|
|
1638
1962
|
return (_a = tools.find((t) => t.name === toolName)) == null ? void 0 : _a.inputSchema;
|
|
1639
1963
|
}
|
|
1640
|
-
function
|
|
1641
|
-
let
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1964
|
+
function findClosingTagEndFlexible(text, contentStart, toolName) {
|
|
1965
|
+
let pos = contentStart;
|
|
1966
|
+
let depth = 1;
|
|
1967
|
+
while (pos < text.length) {
|
|
1968
|
+
const tok = nextTagToken(text, pos);
|
|
1969
|
+
if (tok.kind === "eof") {
|
|
1970
|
+
break;
|
|
1971
|
+
}
|
|
1972
|
+
const result = updateDepthWithToken(tok, toolName, depth);
|
|
1973
|
+
depth = result.depth;
|
|
1974
|
+
if (result.closedAt !== void 0) {
|
|
1975
|
+
return result.closedAt;
|
|
1976
|
+
}
|
|
1977
|
+
pos = tok.nextPos;
|
|
1978
|
+
}
|
|
1979
|
+
return -1;
|
|
1980
|
+
}
|
|
1981
|
+
function skipSpecialSegment(text, lt) {
|
|
1982
|
+
const next = text[lt + 1];
|
|
1983
|
+
if (next !== "!" && next !== "?") {
|
|
1984
|
+
return null;
|
|
1985
|
+
}
|
|
1986
|
+
const gt = text.indexOf(">", lt + 1);
|
|
1987
|
+
if (gt === -1) {
|
|
1988
|
+
return null;
|
|
1989
|
+
}
|
|
1990
|
+
return gt + 1;
|
|
1991
|
+
}
|
|
1992
|
+
function consumeClosingTag(text, lt, toolName) {
|
|
1993
|
+
let p = lt + 2;
|
|
1994
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
1995
|
+
p += 1;
|
|
1996
|
+
}
|
|
1997
|
+
if (text.slice(p, p + toolName.length) === toolName) {
|
|
1998
|
+
p += toolName.length;
|
|
1645
1999
|
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
1646
2000
|
p += 1;
|
|
1647
2001
|
}
|
|
1648
2002
|
if (text[p] === ">") {
|
|
1649
|
-
|
|
2003
|
+
const endPos2 = p + 1;
|
|
2004
|
+
return { matched: true, endPos: endPos2 };
|
|
1650
2005
|
}
|
|
1651
2006
|
}
|
|
1652
|
-
|
|
2007
|
+
const gt = text.indexOf(">", lt + 1);
|
|
2008
|
+
const endPos = gt === -1 ? text.length : gt + 1;
|
|
2009
|
+
return { matched: false, endPos };
|
|
1653
2010
|
}
|
|
1654
|
-
function
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
const
|
|
1660
|
-
|
|
1661
|
-
|
|
2011
|
+
function consumeOpenTag(text, lt) {
|
|
2012
|
+
let p = lt + 1;
|
|
2013
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
2014
|
+
p += 1;
|
|
2015
|
+
}
|
|
2016
|
+
const nameStart = p;
|
|
2017
|
+
while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
2018
|
+
p += 1;
|
|
2019
|
+
}
|
|
2020
|
+
const name = text.slice(nameStart, p);
|
|
2021
|
+
const q = text.indexOf(">", p);
|
|
2022
|
+
if (q === -1) {
|
|
2023
|
+
return null;
|
|
2024
|
+
}
|
|
2025
|
+
let r = q - 1;
|
|
2026
|
+
while (r >= nameStart && WHITESPACE_REGEX2.test(text[r])) {
|
|
2027
|
+
r -= 1;
|
|
2028
|
+
}
|
|
2029
|
+
const selfClosing = text[r] === "/";
|
|
2030
|
+
return { name, selfClosing, nextPos: q + 1 };
|
|
2031
|
+
}
|
|
2032
|
+
function updateDepthWithToken(tok, toolName, depth) {
|
|
2033
|
+
if (tok.kind === "close" && tok.name === toolName) {
|
|
2034
|
+
const newDepth = depth - 1;
|
|
2035
|
+
return newDepth === 0 ? { depth: newDepth, closedAt: tok.nextPos } : { depth: newDepth };
|
|
2036
|
+
}
|
|
2037
|
+
if (tok.kind === "open" && tok.name === toolName && !tok.selfClosing) {
|
|
2038
|
+
return { depth: depth + 1 };
|
|
2039
|
+
}
|
|
2040
|
+
return { depth };
|
|
2041
|
+
}
|
|
2042
|
+
function nextTagToken(text, fromPos) {
|
|
2043
|
+
const lt = text.indexOf("<", fromPos);
|
|
2044
|
+
if (lt === -1 || lt + 1 >= text.length) {
|
|
2045
|
+
return { kind: "eof", nextPos: text.length };
|
|
2046
|
+
}
|
|
2047
|
+
const next = text[lt + 1];
|
|
2048
|
+
const specialEnd = skipSpecialSegment(text, lt);
|
|
2049
|
+
if (specialEnd !== null) {
|
|
2050
|
+
return { kind: "special", nextPos: specialEnd };
|
|
2051
|
+
}
|
|
2052
|
+
if (next === "/") {
|
|
2053
|
+
const closing = consumeClosingTag(text, lt, "");
|
|
2054
|
+
let p = lt + 2;
|
|
2055
|
+
while (p < text.length && WHITESPACE_REGEX2.test(text[p])) {
|
|
2056
|
+
p += 1;
|
|
2057
|
+
}
|
|
2058
|
+
const nameStart = p;
|
|
2059
|
+
while (p < text.length && NAME_CHAR_RE.test(text.charAt(p))) {
|
|
2060
|
+
p += 1;
|
|
2061
|
+
}
|
|
2062
|
+
const name = text.slice(nameStart, p);
|
|
2063
|
+
return { kind: "close", name, nextPos: closing.endPos };
|
|
2064
|
+
}
|
|
2065
|
+
const open = consumeOpenTag(text, lt);
|
|
2066
|
+
if (open === null) {
|
|
2067
|
+
return { kind: "eof", nextPos: text.length };
|
|
2068
|
+
}
|
|
1662
2069
|
return {
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
segment
|
|
2070
|
+
kind: "open",
|
|
2071
|
+
name: open.name,
|
|
2072
|
+
selfClosing: open.selfClosing,
|
|
2073
|
+
nextPos: open.nextPos
|
|
1668
2074
|
};
|
|
1669
2075
|
}
|
|
2076
|
+
function collectToolCallsFromNormalizedText(text, toolNames) {
|
|
2077
|
+
var _a;
|
|
2078
|
+
const normalizedText = normalizeCloseTags(text);
|
|
2079
|
+
const collected = [];
|
|
2080
|
+
for (const toolName of toolNames) {
|
|
2081
|
+
const startTag = `<${toolName}>`;
|
|
2082
|
+
let idx = 0;
|
|
2083
|
+
let lastOrigIdx = 0;
|
|
2084
|
+
while (idx < normalizedText.length) {
|
|
2085
|
+
const tagStartNorm = normalizedText.indexOf(startTag, idx);
|
|
2086
|
+
if (tagStartNorm === -1) {
|
|
2087
|
+
break;
|
|
2088
|
+
}
|
|
2089
|
+
const contentStartNorm = tagStartNorm + startTag.length;
|
|
2090
|
+
const endNorm = findClosingTagEndFlexible(
|
|
2091
|
+
normalizedText,
|
|
2092
|
+
contentStartNorm,
|
|
2093
|
+
toolName
|
|
2094
|
+
);
|
|
2095
|
+
if (endNorm > contentStartNorm) {
|
|
2096
|
+
const tagStartOrig = text.indexOf(startTag, lastOrigIdx);
|
|
2097
|
+
const contentStartOrig = tagStartOrig + startTag.length;
|
|
2098
|
+
let endOrig = findClosingTagEndFlexible(
|
|
2099
|
+
text,
|
|
2100
|
+
contentStartOrig,
|
|
2101
|
+
toolName
|
|
2102
|
+
);
|
|
2103
|
+
if (endOrig === -1) {
|
|
2104
|
+
const approxLen = endNorm - tagStartNorm;
|
|
2105
|
+
endOrig = Math.min(text.length, tagStartOrig + approxLen);
|
|
2106
|
+
}
|
|
2107
|
+
const segment = text.substring(tagStartOrig, endOrig);
|
|
2108
|
+
const inner = (_a = (0, import_rxml.extractRawInner)(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
|
|
2109
|
+
collected.push({
|
|
2110
|
+
toolName,
|
|
2111
|
+
startIndex: tagStartOrig,
|
|
2112
|
+
endIndex: endOrig,
|
|
2113
|
+
content: inner,
|
|
2114
|
+
segment
|
|
2115
|
+
});
|
|
2116
|
+
lastOrigIdx = endOrig;
|
|
2117
|
+
idx = endNorm;
|
|
2118
|
+
} else {
|
|
2119
|
+
idx = contentStartNorm;
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
}
|
|
2123
|
+
return collected.sort((a, b) => a.startIndex - b.startIndex);
|
|
2124
|
+
}
|
|
2125
|
+
function getNextTagInfo(text, toolName, fromIndex) {
|
|
2126
|
+
const startTag = `<${toolName}>`;
|
|
2127
|
+
const selfTag = `<${toolName}/>`;
|
|
2128
|
+
const openIdx = text.indexOf(startTag, fromIndex);
|
|
2129
|
+
const selfIdx = text.indexOf(selfTag, fromIndex);
|
|
2130
|
+
const hasOpen = openIdx !== -1;
|
|
2131
|
+
const hasSelf = selfIdx !== -1;
|
|
2132
|
+
if (!(hasOpen || hasSelf)) {
|
|
2133
|
+
return {
|
|
2134
|
+
found: false,
|
|
2135
|
+
tagStart: -1,
|
|
2136
|
+
selfClosing: false,
|
|
2137
|
+
startTag,
|
|
2138
|
+
selfTag
|
|
2139
|
+
};
|
|
2140
|
+
}
|
|
2141
|
+
const pickSelf = hasSelf && (!hasOpen || selfIdx < openIdx);
|
|
2142
|
+
const tagStart = pickSelf ? selfIdx : openIdx;
|
|
2143
|
+
return { found: true, tagStart, selfClosing: pickSelf, startTag, selfTag };
|
|
2144
|
+
}
|
|
1670
2145
|
function findToolCallsForName(text, toolName) {
|
|
2146
|
+
var _a;
|
|
1671
2147
|
const toolCalls = [];
|
|
1672
|
-
const startTag = `<${toolName}>`;
|
|
1673
2148
|
let searchIndex = 0;
|
|
1674
2149
|
while (searchIndex < text.length) {
|
|
1675
|
-
const
|
|
1676
|
-
if (
|
|
2150
|
+
const info = getNextTagInfo(text, toolName, searchIndex);
|
|
2151
|
+
if (!info.found) {
|
|
1677
2152
|
break;
|
|
1678
2153
|
}
|
|
1679
|
-
const
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
const
|
|
1683
|
-
toolCalls.push(
|
|
1684
|
-
|
|
2154
|
+
const { tagStart, selfClosing, startTag, selfTag } = info;
|
|
2155
|
+
if (selfClosing) {
|
|
2156
|
+
const endIndex = tagStart + selfTag.length;
|
|
2157
|
+
const segment = text.substring(tagStart, endIndex);
|
|
2158
|
+
toolCalls.push({
|
|
2159
|
+
toolName,
|
|
2160
|
+
startIndex: tagStart,
|
|
2161
|
+
endIndex,
|
|
2162
|
+
content: "",
|
|
2163
|
+
segment
|
|
2164
|
+
});
|
|
2165
|
+
searchIndex = endIndex;
|
|
2166
|
+
continue;
|
|
2167
|
+
}
|
|
2168
|
+
const contentStart = tagStart + startTag.length;
|
|
2169
|
+
const fullTagEnd = findClosingTagEndFlexible(text, contentStart, toolName);
|
|
2170
|
+
if (fullTagEnd !== -1 && fullTagEnd > contentStart) {
|
|
2171
|
+
const segment = text.substring(tagStart, fullTagEnd);
|
|
2172
|
+
const inner = (_a = (0, import_rxml.extractRawInner)(segment, toolName)) != null ? _a : segment.substring(startTag.length, segment.lastIndexOf("<"));
|
|
2173
|
+
toolCalls.push({
|
|
2174
|
+
toolName,
|
|
2175
|
+
startIndex: tagStart,
|
|
2176
|
+
endIndex: fullTagEnd,
|
|
2177
|
+
content: inner,
|
|
2178
|
+
segment
|
|
2179
|
+
});
|
|
2180
|
+
searchIndex = fullTagEnd;
|
|
1685
2181
|
} else {
|
|
1686
|
-
searchIndex =
|
|
2182
|
+
searchIndex = contentStart;
|
|
1687
2183
|
}
|
|
1688
2184
|
}
|
|
1689
2185
|
return toolCalls;
|
|
@@ -1697,14 +2193,50 @@ function findToolCalls(text, toolNames) {
|
|
|
1697
2193
|
return toolCalls.sort((a, b) => a.startIndex - b.startIndex);
|
|
1698
2194
|
}
|
|
1699
2195
|
|
|
1700
|
-
// src/
|
|
1701
|
-
|
|
1702
|
-
|
|
2196
|
+
// src/generate-handler.ts
|
|
2197
|
+
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
2198
|
+
var import_rxml2 = require("@ai-sdk-tool/rxml");
|
|
2199
|
+
|
|
2200
|
+
// src/utils/on-error.ts
|
|
2201
|
+
function extractOnErrorOption(providerOptions) {
|
|
2202
|
+
var _a;
|
|
2203
|
+
if (providerOptions && typeof providerOptions === "object") {
|
|
2204
|
+
const onError = (_a = providerOptions.toolCallMiddleware) == null ? void 0 : _a.onError;
|
|
2205
|
+
return onError ? { onError } : void 0;
|
|
2206
|
+
}
|
|
2207
|
+
return;
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
// src/utils/provider-options.ts
|
|
2211
|
+
var originalToolsSchema = {
|
|
2212
|
+
encode: encodeOriginalTools,
|
|
2213
|
+
decode: decodeOriginalTools
|
|
2214
|
+
};
|
|
2215
|
+
function encodeOriginalTools(tools) {
|
|
2216
|
+
return (tools == null ? void 0 : tools.map((t) => ({
|
|
2217
|
+
name: t.name,
|
|
2218
|
+
inputSchema: JSON.stringify(t.inputSchema)
|
|
2219
|
+
}))) || [];
|
|
2220
|
+
}
|
|
2221
|
+
function decodeOriginalTools(originalTools) {
|
|
2222
|
+
if (!originalTools) {
|
|
2223
|
+
return [];
|
|
2224
|
+
}
|
|
2225
|
+
return originalTools.map(
|
|
2226
|
+
(t) => ({
|
|
2227
|
+
type: "function",
|
|
2228
|
+
name: t.name,
|
|
2229
|
+
inputSchema: JSON.parse(t.inputSchema)
|
|
2230
|
+
})
|
|
2231
|
+
);
|
|
2232
|
+
}
|
|
2233
|
+
function isToolChoiceActive(params) {
|
|
2234
|
+
var _a, _b, _c;
|
|
2235
|
+
const toolChoice = (_b = (_a = params.providerOptions) == null ? void 0 : _a.toolCallMiddleware) == null ? void 0 : _b.toolChoice;
|
|
2236
|
+
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"));
|
|
1703
2237
|
}
|
|
1704
2238
|
|
|
1705
2239
|
// src/generate-handler.ts
|
|
1706
|
-
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
1707
|
-
var import_rxml2 = require("@ai-sdk-tool/rxml");
|
|
1708
2240
|
function parseToolChoiceJson(text, providerOptions) {
|
|
1709
2241
|
var _a;
|
|
1710
2242
|
try {
|
|
@@ -1748,7 +2280,7 @@ async function handleToolChoice(doGenerate, params) {
|
|
|
1748
2280
|
}
|
|
1749
2281
|
const toolCall = {
|
|
1750
2282
|
type: "tool-call",
|
|
1751
|
-
toolCallId: (0,
|
|
2283
|
+
toolCallId: (0, import_provider_utils3.generateId)(),
|
|
1752
2284
|
toolName: parsed.name || "unknown",
|
|
1753
2285
|
input: JSON.stringify(parsed.arguments || {})
|
|
1754
2286
|
};
|
|
@@ -1874,8 +2406,13 @@ function fixToolCallWithSchema(part, tools) {
|
|
|
1874
2406
|
};
|
|
1875
2407
|
}
|
|
1876
2408
|
|
|
2409
|
+
// src/protocols/tool-call-protocol.ts
|
|
2410
|
+
function isProtocolFactory(protocol) {
|
|
2411
|
+
return typeof protocol === "function";
|
|
2412
|
+
}
|
|
2413
|
+
|
|
1877
2414
|
// src/stream-handler.ts
|
|
1878
|
-
var
|
|
2415
|
+
var import_provider_utils4 = require("@ai-sdk/provider-utils");
|
|
1879
2416
|
function extractToolCallSegments(protocol, fullRawText, tools) {
|
|
1880
2417
|
const segments = protocol.extractToolCallSegments ? protocol.extractToolCallSegments({
|
|
1881
2418
|
text: fullRawText,
|
|
@@ -1912,7 +2449,7 @@ function handleDebugSummary(parsedToolCalls, origin, params) {
|
|
|
1912
2449
|
}
|
|
1913
2450
|
function createDebugSummaryTransform({
|
|
1914
2451
|
protocol,
|
|
1915
|
-
|
|
2452
|
+
getFullRawText,
|
|
1916
2453
|
tools,
|
|
1917
2454
|
params
|
|
1918
2455
|
}) {
|
|
@@ -1925,11 +2462,9 @@ function createDebugSummaryTransform({
|
|
|
1925
2462
|
}
|
|
1926
2463
|
if (part.type === "finish") {
|
|
1927
2464
|
try {
|
|
1928
|
-
const
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
tools
|
|
1932
|
-
);
|
|
2465
|
+
const raw = getFullRawText();
|
|
2466
|
+
logRawChunk(raw);
|
|
2467
|
+
const origin = extractToolCallSegments(protocol, raw, tools);
|
|
1933
2468
|
handleDebugSummary(parsedToolCalls, origin, params);
|
|
1934
2469
|
} catch (e) {
|
|
1935
2470
|
}
|
|
@@ -2027,7 +2562,7 @@ async function wrapStream({
|
|
|
2027
2562
|
const withSummary = parsed.pipeThrough(
|
|
2028
2563
|
createDebugSummaryTransform({
|
|
2029
2564
|
protocol,
|
|
2030
|
-
fullRawText,
|
|
2565
|
+
getFullRawText: () => fullRawText,
|
|
2031
2566
|
tools,
|
|
2032
2567
|
params
|
|
2033
2568
|
})
|
|
@@ -2061,19 +2596,26 @@ async function toolChoiceStream({
|
|
|
2061
2596
|
}
|
|
2062
2597
|
const toolCallChunk = {
|
|
2063
2598
|
type: "tool-call",
|
|
2064
|
-
toolCallId: (0,
|
|
2599
|
+
toolCallId: (0, import_provider_utils4.generateId)(),
|
|
2065
2600
|
toolName: toolJson.name || "unknown",
|
|
2066
2601
|
input: JSON.stringify(toolJson.arguments || {})
|
|
2067
2602
|
};
|
|
2068
2603
|
const finishChunk = {
|
|
2069
2604
|
type: "finish",
|
|
2070
|
-
usage: (result == null ? void 0 : result.usage) ||
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2605
|
+
usage: (result == null ? void 0 : result.usage) || {
|
|
2606
|
+
inputTokens: {
|
|
2607
|
+
total: 0,
|
|
2608
|
+
noCache: void 0,
|
|
2609
|
+
cacheRead: void 0,
|
|
2610
|
+
cacheWrite: void 0
|
|
2611
|
+
},
|
|
2612
|
+
outputTokens: {
|
|
2613
|
+
total: 0,
|
|
2614
|
+
text: void 0,
|
|
2615
|
+
reasoning: void 0
|
|
2616
|
+
}
|
|
2075
2617
|
},
|
|
2076
|
-
finishReason: "tool-calls"
|
|
2618
|
+
finishReason: { unified: "tool-calls", raw: void 0 }
|
|
2077
2619
|
};
|
|
2078
2620
|
const stream = new ReadableStream({
|
|
2079
2621
|
start(controller) {
|
|
@@ -2107,26 +2649,106 @@ async function toolChoiceStream({
|
|
|
2107
2649
|
};
|
|
2108
2650
|
}
|
|
2109
2651
|
|
|
2652
|
+
// src/utils/dynamic-tool-schema.ts
|
|
2653
|
+
function createDynamicIfThenElseSchema(tools) {
|
|
2654
|
+
let currentSchema = {};
|
|
2655
|
+
const toolNames = [];
|
|
2656
|
+
for (let i = tools.length - 1; i >= 0; i -= 1) {
|
|
2657
|
+
const tool = tools[i];
|
|
2658
|
+
if (tool.type === "provider") {
|
|
2659
|
+
throw new Error(
|
|
2660
|
+
"Provider tools are not supported by this middleware. Please use function tools."
|
|
2661
|
+
);
|
|
2662
|
+
}
|
|
2663
|
+
toolNames.unshift(tool.name);
|
|
2664
|
+
const toolCondition = {
|
|
2665
|
+
if: {
|
|
2666
|
+
properties: {
|
|
2667
|
+
name: {
|
|
2668
|
+
const: tool.name
|
|
2669
|
+
}
|
|
2670
|
+
},
|
|
2671
|
+
required: ["name"]
|
|
2672
|
+
},
|
|
2673
|
+
// biome-ignore lint/suspicious/noThenProperty: JSON Schema uses 'then' as a keyword
|
|
2674
|
+
then: {
|
|
2675
|
+
properties: {
|
|
2676
|
+
name: {
|
|
2677
|
+
const: tool.name
|
|
2678
|
+
},
|
|
2679
|
+
arguments: tool.inputSchema
|
|
2680
|
+
},
|
|
2681
|
+
required: ["name", "arguments"]
|
|
2682
|
+
}
|
|
2683
|
+
};
|
|
2684
|
+
if (Object.keys(currentSchema).length > 0) {
|
|
2685
|
+
toolCondition.else = currentSchema;
|
|
2686
|
+
}
|
|
2687
|
+
currentSchema = toolCondition;
|
|
2688
|
+
}
|
|
2689
|
+
return {
|
|
2690
|
+
type: "object",
|
|
2691
|
+
// Explicitly specify type as "object"
|
|
2692
|
+
properties: {
|
|
2693
|
+
name: {
|
|
2694
|
+
type: "string",
|
|
2695
|
+
description: "Name of the tool to call",
|
|
2696
|
+
enum: toolNames
|
|
2697
|
+
},
|
|
2698
|
+
arguments: {
|
|
2699
|
+
type: "object",
|
|
2700
|
+
// By default, arguments is also specified as object type
|
|
2701
|
+
description: "Argument object to be passed to the tool"
|
|
2702
|
+
}
|
|
2703
|
+
},
|
|
2704
|
+
required: ["name", "arguments"],
|
|
2705
|
+
...currentSchema
|
|
2706
|
+
};
|
|
2707
|
+
}
|
|
2708
|
+
|
|
2110
2709
|
// src/transform-handler.ts
|
|
2111
|
-
function buildFinalPrompt(systemPrompt, processedPrompt) {
|
|
2112
|
-
|
|
2113
|
-
if (
|
|
2710
|
+
function buildFinalPrompt(systemPrompt, processedPrompt, placement) {
|
|
2711
|
+
const systemIndex = processedPrompt.findIndex((m) => m.role === "system");
|
|
2712
|
+
if (systemIndex !== -1) {
|
|
2713
|
+
const existing = processedPrompt[systemIndex].content;
|
|
2714
|
+
let existingText = "";
|
|
2715
|
+
if (typeof existing === "string") {
|
|
2716
|
+
existingText = existing;
|
|
2717
|
+
} else if (Array.isArray(existing)) {
|
|
2718
|
+
existingText = existing.map((p) => {
|
|
2719
|
+
var _a;
|
|
2720
|
+
return (p == null ? void 0 : p.type) === "text" ? (_a = p.text) != null ? _a : "" : "";
|
|
2721
|
+
}).filter(Boolean).join("\n");
|
|
2722
|
+
} else {
|
|
2723
|
+
existingText = String(existing != null ? existing : "");
|
|
2724
|
+
}
|
|
2725
|
+
const mergedContent = placement === "first" ? `${systemPrompt}
|
|
2726
|
+
|
|
2727
|
+
${existingText}` : `${existingText}
|
|
2728
|
+
|
|
2729
|
+
${systemPrompt}`;
|
|
2730
|
+
return processedPrompt.map(
|
|
2731
|
+
(m, idx) => idx === systemIndex ? {
|
|
2732
|
+
...m,
|
|
2733
|
+
content: mergedContent
|
|
2734
|
+
} : m
|
|
2735
|
+
);
|
|
2736
|
+
}
|
|
2737
|
+
if (placement === "first") {
|
|
2114
2738
|
return [
|
|
2115
2739
|
{
|
|
2116
2740
|
role: "system",
|
|
2117
|
-
content:
|
|
2118
|
-
|
|
2119
|
-
${processedPrompt[0].content}`
|
|
2741
|
+
content: systemPrompt
|
|
2120
2742
|
},
|
|
2121
|
-
...processedPrompt
|
|
2743
|
+
...processedPrompt
|
|
2122
2744
|
];
|
|
2123
2745
|
}
|
|
2124
2746
|
return [
|
|
2747
|
+
...processedPrompt,
|
|
2125
2748
|
{
|
|
2126
2749
|
role: "system",
|
|
2127
2750
|
content: systemPrompt
|
|
2128
|
-
}
|
|
2129
|
-
...processedPrompt
|
|
2751
|
+
}
|
|
2130
2752
|
];
|
|
2131
2753
|
}
|
|
2132
2754
|
function buildBaseReturnParams(params, finalPrompt, functionTools) {
|
|
@@ -2226,7 +2848,8 @@ function handleToolChoiceRequired(params, baseReturnParams, functionTools) {
|
|
|
2226
2848
|
function transformParams({
|
|
2227
2849
|
params,
|
|
2228
2850
|
protocol,
|
|
2229
|
-
toolSystemPromptTemplate
|
|
2851
|
+
toolSystemPromptTemplate,
|
|
2852
|
+
placement = "first"
|
|
2230
2853
|
}) {
|
|
2231
2854
|
var _a, _b, _c, _d, _e;
|
|
2232
2855
|
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
@@ -2242,7 +2865,11 @@ function transformParams({
|
|
|
2242
2865
|
resolvedProtocol,
|
|
2243
2866
|
extractOnErrorOption(params.providerOptions)
|
|
2244
2867
|
);
|
|
2245
|
-
const finalPrompt = buildFinalPrompt(
|
|
2868
|
+
const finalPrompt = buildFinalPrompt(
|
|
2869
|
+
systemPrompt,
|
|
2870
|
+
processedPrompt,
|
|
2871
|
+
placement
|
|
2872
|
+
);
|
|
2246
2873
|
const baseReturnParams = buildBaseReturnParams(
|
|
2247
2874
|
params,
|
|
2248
2875
|
finalPrompt,
|
|
@@ -2319,7 +2946,10 @@ function processMessage(message, resolvedProtocol, providerOptions) {
|
|
|
2319
2946
|
};
|
|
2320
2947
|
}
|
|
2321
2948
|
if (message.role === "tool") {
|
|
2322
|
-
|
|
2949
|
+
const toolResultParts = message.content.filter(
|
|
2950
|
+
(part) => part.type === "tool-result"
|
|
2951
|
+
);
|
|
2952
|
+
return processToolMessage(toolResultParts, resolvedProtocol);
|
|
2323
2953
|
}
|
|
2324
2954
|
return message;
|
|
2325
2955
|
}
|
|
@@ -2394,7 +3024,8 @@ function convertToolPrompt(prompt, resolvedProtocol, providerOptions) {
|
|
|
2394
3024
|
// src/tool-call-middleware.ts
|
|
2395
3025
|
function createToolMiddleware({
|
|
2396
3026
|
protocol,
|
|
2397
|
-
toolSystemPromptTemplate
|
|
3027
|
+
toolSystemPromptTemplate,
|
|
3028
|
+
placement = "last"
|
|
2398
3029
|
}) {
|
|
2399
3030
|
const resolvedProtocol = isProtocolFactory(protocol) ? protocol() : protocol;
|
|
2400
3031
|
return {
|
|
@@ -2421,6 +3052,7 @@ function createToolMiddleware({
|
|
|
2421
3052
|
transformParams: async ({ params }) => transformParams({
|
|
2422
3053
|
protocol: resolvedProtocol,
|
|
2423
3054
|
toolSystemPromptTemplate,
|
|
3055
|
+
placement,
|
|
2424
3056
|
params
|
|
2425
3057
|
})
|
|
2426
3058
|
};
|
|
@@ -2466,6 +3098,7 @@ For each function call return a json object with function name and arguments wit
|
|
|
2466
3098
|
});
|
|
2467
3099
|
var morphXmlToolMiddleware = createToolMiddleware({
|
|
2468
3100
|
protocol: morphXmlProtocol,
|
|
3101
|
+
placement: "last",
|
|
2469
3102
|
toolSystemPromptTemplate(tools) {
|
|
2470
3103
|
return `You are a function calling AI model.
|
|
2471
3104
|
|
|
@@ -2488,7 +3121,7 @@ Available functions are listed inside <tools></tools>.
|
|
|
2488
3121
|
}
|
|
2489
3122
|
});
|
|
2490
3123
|
|
|
2491
|
-
// src/community/
|
|
3124
|
+
// src/community/sijawara.ts
|
|
2492
3125
|
var sijawaraDetailedXmlToolMiddleware = createToolMiddleware({
|
|
2493
3126
|
protocol: morphXmlProtocol,
|
|
2494
3127
|
toolSystemPromptTemplate(tools) {
|