@crewai-ts/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +692 -0
- package/dist/chunk-3PVW4JKT.js +9749 -0
- package/dist/chunk-BE4JYKSG.js +4677 -0
- package/dist/chunk-LWD4QED4.js +656 -0
- package/dist/index.cjs +71303 -0
- package/dist/index.d.cts +13068 -0
- package/dist/index.d.ts +13068 -0
- package/dist/index.js +54839 -0
- package/dist/llms-hooks-transport-ChGiFBiU.d.ts +233 -0
- package/dist/llms-hooks-transport-DZlurMUQ.d.cts +233 -0
- package/dist/llms-hooks-transport.cjs +70 -0
- package/dist/llms-hooks-transport.d.cts +2 -0
- package/dist/llms-hooks-transport.d.ts +2 -0
- package/dist/llms-hooks-transport.js +10 -0
- package/dist/mcp-DS7UMYAM.js +62 -0
- package/dist/state-provider-core-Be9RKRAm.d.cts +4876 -0
- package/dist/state-provider-core-Be9RKRAm.d.ts +4876 -0
- package/dist/state-provider-core.cjs +55 -0
- package/dist/state-provider-core.d.cts +1 -0
- package/dist/state-provider-core.d.ts +1 -0
- package/dist/state-provider-core.js +7 -0
- package/package.json +5049 -0
|
@@ -0,0 +1,4677 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InternalInstructor,
|
|
3
|
+
MCPConfigFetchFailedEvent,
|
|
4
|
+
MCPConnectionCompletedEvent,
|
|
5
|
+
MCPConnectionFailedEvent,
|
|
6
|
+
MCPConnectionStartedEvent,
|
|
7
|
+
MCPToolExecutionCompletedEvent,
|
|
8
|
+
MCPToolExecutionFailedEvent,
|
|
9
|
+
MCPToolExecutionStartedEvent,
|
|
10
|
+
ToolSelectionErrorEvent,
|
|
11
|
+
ToolUsageErrorEvent,
|
|
12
|
+
ToolUsageFinishedEvent,
|
|
13
|
+
ToolUsageStartedEvent,
|
|
14
|
+
ToolValidateInputErrorEvent,
|
|
15
|
+
crewaiEventBus
|
|
16
|
+
} from "./chunk-3PVW4JKT.js";
|
|
17
|
+
import {
|
|
18
|
+
ToolCallHookContext,
|
|
19
|
+
getAfterToolCallHooks,
|
|
20
|
+
getBeforeToolCallHooks,
|
|
21
|
+
runAfterToolCallHooks,
|
|
22
|
+
runBeforeToolCallHooks
|
|
23
|
+
} from "./chunk-LWD4QED4.js";
|
|
24
|
+
|
|
25
|
+
// src/mcp.ts
|
|
26
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
27
|
+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
28
|
+
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
29
|
+
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
30
|
+
|
|
31
|
+
// src/string-utils.ts
|
|
32
|
+
import { createHash } from "crypto";
|
|
33
|
+
var variablePattern = /\{([A-Za-z_][A-Za-z0-9_-]*)\}/g;
|
|
34
|
+
var quotePattern = /['"]+/g;
|
|
35
|
+
var camelUpperLowerPattern = /([A-Z]+)([A-Z][a-z])/g;
|
|
36
|
+
var camelLowerUpperPattern = /([a-z])([A-Z])/g;
|
|
37
|
+
var disallowedCharsPattern = /[^a-zA-Z0-9]+/g;
|
|
38
|
+
var duplicateUnderscorePattern = /_+/g;
|
|
39
|
+
var maxToolNameLength = 64;
|
|
40
|
+
function sanitizeToolName(name, maxLength = maxToolNameLength) {
|
|
41
|
+
let normalized = normalizeAscii(name);
|
|
42
|
+
normalized = normalized.replace(camelUpperLowerPattern, "$1_$2");
|
|
43
|
+
normalized = normalized.replace(camelLowerUpperPattern, "$1_$2");
|
|
44
|
+
normalized = normalized.toLowerCase();
|
|
45
|
+
normalized = normalized.replace(quotePattern, "");
|
|
46
|
+
normalized = normalized.replace(disallowedCharsPattern, "_");
|
|
47
|
+
normalized = normalized.replace(duplicateUnderscorePattern, "_");
|
|
48
|
+
normalized = normalized.replace(/^_+|_+$/g, "");
|
|
49
|
+
if (normalized.length > maxLength) {
|
|
50
|
+
const hash = createHash("sha256").update(normalized).digest("hex").slice(0, 8);
|
|
51
|
+
const suffix = `_${hash}`;
|
|
52
|
+
normalized = `${normalized.slice(0, maxLength - suffix.length).replace(/_+$/g, "")}${suffix}`;
|
|
53
|
+
}
|
|
54
|
+
return normalized;
|
|
55
|
+
}
|
|
56
|
+
var sanitize_tool_name = sanitizeToolName;
|
|
57
|
+
function slugify(text, separator = "_") {
|
|
58
|
+
let normalized = normalizeAscii(text);
|
|
59
|
+
normalized = normalized.toLowerCase();
|
|
60
|
+
normalized = normalized.replace(quotePattern, "");
|
|
61
|
+
normalized = normalized.replace(disallowedCharsPattern, separator);
|
|
62
|
+
normalized = normalized.replace(_duplicate_separator_pattern(separator), separator);
|
|
63
|
+
return trimSeparator(normalized, separator);
|
|
64
|
+
}
|
|
65
|
+
function _duplicate_separator_pattern(separator) {
|
|
66
|
+
return new RegExp(`(?:${escapeRegExp(separator)}){2,}`, "g");
|
|
67
|
+
}
|
|
68
|
+
function interpolateOnly(inputString, inputs, options = {}) {
|
|
69
|
+
const strictMissing = options.strictMissing ?? true;
|
|
70
|
+
validateInterpolationInputs(inputs);
|
|
71
|
+
if (!inputString) {
|
|
72
|
+
return "";
|
|
73
|
+
}
|
|
74
|
+
if (!inputString.includes("{") && !inputString.includes("}")) {
|
|
75
|
+
return inputString;
|
|
76
|
+
}
|
|
77
|
+
if (strictMissing && Object.keys(inputs).length === 0) {
|
|
78
|
+
throw new Error("Inputs dictionary cannot be empty when interpolating variables");
|
|
79
|
+
}
|
|
80
|
+
const variables = [...inputString.matchAll(variablePattern)].map((match) => match[1]).filter((key) => Boolean(key));
|
|
81
|
+
const missingVariable = variables.find((variable) => !(variable in inputs));
|
|
82
|
+
if (strictMissing && missingVariable) {
|
|
83
|
+
throw new Error(`Template variable '${missingVariable}' not found in inputs dictionary`);
|
|
84
|
+
}
|
|
85
|
+
let result = inputString;
|
|
86
|
+
for (const variable of variables) {
|
|
87
|
+
if (!(variable in inputs)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
result = result.replaceAll(`{${variable}}`, stringifyInterpolationValue(inputs[variable]));
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
94
|
+
var interpolate_only = interpolateOnly;
|
|
95
|
+
function validateInterpolationInputs(inputs) {
|
|
96
|
+
for (const [key, value] of Object.entries(inputs)) {
|
|
97
|
+
try {
|
|
98
|
+
validateInterpolationValue(value);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
101
|
+
throw new Error(`Invalid value for key '${key}': ${message}`, { cause: error });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function _validate_type(value) {
|
|
106
|
+
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (Array.isArray(value)) {
|
|
110
|
+
value.forEach(_validate_type);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (value && typeof value === "object" && isPlainObject(value)) {
|
|
114
|
+
Object.values(value).forEach(_validate_type);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
throw new Error(
|
|
118
|
+
`Unsupported type ${typeName(value)} in inputs. Only str, int, float, bool, dict, and list are allowed.`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
var validateInterpolationValue = _validate_type;
|
|
122
|
+
function stringifyInterpolationValue(value) {
|
|
123
|
+
if (typeof value === "string") {
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
if (typeof value === "number") {
|
|
127
|
+
return String(value);
|
|
128
|
+
}
|
|
129
|
+
if (typeof value === "boolean") {
|
|
130
|
+
return value ? "True" : "False";
|
|
131
|
+
}
|
|
132
|
+
if (value === null) {
|
|
133
|
+
return "None";
|
|
134
|
+
}
|
|
135
|
+
if (Array.isArray(value)) {
|
|
136
|
+
return `[${value.map((item) => pythonRepr(item)).join(", ")}]`;
|
|
137
|
+
}
|
|
138
|
+
if (value && typeof value === "object" && isPlainObject(value)) {
|
|
139
|
+
return `{${Object.entries(value).map(([key, item]) => `${pythonRepr(key)}: ${pythonRepr(item)}`).join(", ")}}`;
|
|
140
|
+
}
|
|
141
|
+
return JSON.stringify(value);
|
|
142
|
+
}
|
|
143
|
+
function pythonRepr(value) {
|
|
144
|
+
if (typeof value === "string") {
|
|
145
|
+
return `'${value.replaceAll("\\", "\\\\").replaceAll("'", "\\'")}'`;
|
|
146
|
+
}
|
|
147
|
+
if (typeof value === "number") {
|
|
148
|
+
return String(value);
|
|
149
|
+
}
|
|
150
|
+
if (typeof value === "boolean") {
|
|
151
|
+
return value ? "True" : "False";
|
|
152
|
+
}
|
|
153
|
+
if (value === null) {
|
|
154
|
+
return "None";
|
|
155
|
+
}
|
|
156
|
+
if (Array.isArray(value)) {
|
|
157
|
+
return `[${value.map((item) => pythonRepr(item)).join(", ")}]`;
|
|
158
|
+
}
|
|
159
|
+
if (value && typeof value === "object" && isPlainObject(value)) {
|
|
160
|
+
return `{${Object.entries(value).map(([key, item]) => `${pythonRepr(key)}: ${pythonRepr(item)}`).join(", ")}}`;
|
|
161
|
+
}
|
|
162
|
+
return JSON.stringify(value);
|
|
163
|
+
}
|
|
164
|
+
function normalizeAscii(value) {
|
|
165
|
+
const decomposed = value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
|
|
166
|
+
let ascii = "";
|
|
167
|
+
for (let index = 0; index < decomposed.length; index += 1) {
|
|
168
|
+
const char = decomposed[index];
|
|
169
|
+
if (char && char.charCodeAt(0) <= 127) {
|
|
170
|
+
ascii += char;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return ascii;
|
|
174
|
+
}
|
|
175
|
+
function trimSeparator(value, separator) {
|
|
176
|
+
if (!separator) {
|
|
177
|
+
return value;
|
|
178
|
+
}
|
|
179
|
+
const escapedSeparator = escapeRegExp(separator);
|
|
180
|
+
return value.replace(new RegExp(`^(?:${escapedSeparator})+|(?:${escapedSeparator})+$`, "g"), "");
|
|
181
|
+
}
|
|
182
|
+
function escapeRegExp(value) {
|
|
183
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
184
|
+
}
|
|
185
|
+
function isPlainObject(value) {
|
|
186
|
+
return Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null;
|
|
187
|
+
}
|
|
188
|
+
function typeName(value) {
|
|
189
|
+
if (value === null) {
|
|
190
|
+
return "NoneType";
|
|
191
|
+
}
|
|
192
|
+
if (value && typeof value === "object") {
|
|
193
|
+
return value.constructor.name;
|
|
194
|
+
}
|
|
195
|
+
return typeof value;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// src/i18n.ts
|
|
199
|
+
import { readFileSync } from "fs";
|
|
200
|
+
var defaultPrompts = {
|
|
201
|
+
hierarchical_manager_agent: {
|
|
202
|
+
role: "Crew Manager",
|
|
203
|
+
goal: "Manage the team to complete the task in the best way possible.",
|
|
204
|
+
backstory: [
|
|
205
|
+
"You are a seasoned manager with a knack for getting the best out of your team.",
|
|
206
|
+
"You are also known for your ability to delegate work to the right people, and to ask the right questions to get the best out of your team.",
|
|
207
|
+
"Even though you don't perform tasks by yourself, you have a lot of experience in the field, which allows you to properly evaluate the work of your team members."
|
|
208
|
+
].join("\n")
|
|
209
|
+
},
|
|
210
|
+
slices: {
|
|
211
|
+
observation: "\nObservation:",
|
|
212
|
+
task: "\nCurrent Task: {input}\n\nBegin! This is VERY important to you, use the tools available and give your best Final Answer, your job depends on it!\n\nThought:",
|
|
213
|
+
memory: "\n\n# Memories from past conversations:\n{memory}\n\nIMPORTANT: The memories above are an automatic selection and may be INCOMPLETE. If the task involves counting, listing, or summing items (e.g. 'how many', 'total', 'list all'), you MUST use the Search memory tool with several different queries before answering -- do NOT rely solely on the memories shown above. Enumerate each distinct item you find before giving a final count.",
|
|
214
|
+
role_playing: "You are {role}. {backstory}\nYour personal goal is: {goal}",
|
|
215
|
+
tools: "\nYou ONLY have access to the following tools, and should NEVER make up tools that are not listed here:\n\n{tools}\n\nIMPORTANT: Use the following format in your response:\n\n```\nThought: you should always think about what to do\nAction: the action to take, only one name of [{tool_names}], just the name, exactly as it's written.\nAction Input: the input to the action, just a simple JSON object, enclosed in curly braces, using \" to wrap keys and values.\nObservation: the result of the action\n```\n\nOnce all necessary information is gathered, return the following format:\n\n```\nThought: I now know the final answer\nFinal Answer: the final answer to the original input question\n```",
|
|
216
|
+
no_tools: "",
|
|
217
|
+
task_no_tools: "\nCurrent Task: {input}\n\nProvide your complete response:",
|
|
218
|
+
native_tools: "",
|
|
219
|
+
native_task: "\nCurrent Task: {input}",
|
|
220
|
+
post_tool_reasoning: "Analyze the tool result. If requirements are met, provide the Final Answer. Otherwise, call the next tool. Deliver only the answer without meta-commentary.",
|
|
221
|
+
format: "Decide if you need a tool or can provide the final answer. Use one at a time.\nTo use a tool, use:\nThought: [reasoning]\nAction: [name from {tool_names}]\nAction Input: [JSON object]\n\nTo provide the final answer, use:\nThought: [reasoning]\nFinal Answer: [complete response]",
|
|
222
|
+
final_answer_format: "If you don't need to use any more tools, you must give your best complete final answer, make sure it satisfies the expected criteria, use the EXACT format below:\n\n```\nThought: I now can give a great answer\nFinal Answer: my best complete final answer to the task.\n\n```",
|
|
223
|
+
task_with_context: "{task}\n\nThis is the context you're working with:\n{context}",
|
|
224
|
+
expected_output: "\nThis is the expected criteria for your final answer: {expected_output}\nyou MUST return the actual complete content as the final answer, not a summary.",
|
|
225
|
+
human_feedback: "You got human feedback on your work, re-evaluate it and give a new Final Answer when ready.\n {human_feedback}",
|
|
226
|
+
formatted_task_instructions: "Format your final answer according to the following OpenAPI schema: {output_format}\n\nIMPORTANT: Preserve the original content exactly as-is. Do NOT rewrite, paraphrase, or modify the meaning of the content. Only structure it to match the schema format.\n\nDo not include the OpenAPI schema in the final output. Ensure the final output does not include any code block markers like ```json or ```python.",
|
|
227
|
+
conversation_history_instruction: "You are a member of a crew collaborating to achieve a common goal. Your task is a specific action that contributes to this larger objective. For additional context, please review the conversation history between you and the user that led to the initiation of this crew. Use any relevant information or feedback from the conversation to inform your task execution and ensure your response aligns with both the immediate task and the crew's overall goals.",
|
|
228
|
+
summarizer_system_message: "You are an expert conversation summarizer. Create comprehensive, structured summaries that preserve all critical context, tool results, decisions, and next steps. Your summaries will be used to continue conversations seamlessly after context compaction.",
|
|
229
|
+
summarize_instruction: "Analyze the following conversation and create a structured summary that preserves all information needed to continue the task seamlessly.\n\n<conversation>\n{conversation}\n</conversation>\n\nCreate a summary with these sections:\n1. **Task Overview**: What is the agent trying to accomplish?\n2. **Current State**: What has been completed so far? What step is the agent on?\n3. **Important Discoveries**: Key facts, data, tool results, or findings that must not be lost.\n4. **Next Steps**: What should the agent do next based on the conversation?\n5. **Context to Preserve**: Any specific values, names, URLs, code snippets, or details referenced in the conversation.\n\nWrap your entire summary in <summary> tags.\n\n<summary>\n[Your structured summary here]\n</summary>",
|
|
230
|
+
summary: "<summary>\n{merged_summary}\n</summary>\n\nContinue the task from where the conversation left off. The above is a structured summary of prior context.",
|
|
231
|
+
feedback_instructions: "User feedback: {feedback}\nInstructions: Use this feedback to enhance the next output iteration.\nNote: Do not respond or add commentary.",
|
|
232
|
+
lite_agent_system_prompt_with_tools: "You are {role}. {backstory}\nYour personal goal is: {goal}\n\nYou ONLY have access to the following tools, and should NEVER make up tools that are not listed here:\n\n{tools}\n\nIMPORTANT: Use the following format in your response:\n\n```\nThought: you should always think about what to do\nAction: the action to take, only one name of [{tool_names}], just the name, exactly as it's written.\nAction Input: the input to the action, just a simple JSON object, enclosed in curly braces, using \" to wrap keys and values.\nObservation: the result of the action\n```\n\nOnce all necessary information is gathered, return the following format:\n\n```\nThought: I now know the final answer\nFinal Answer: the final answer to the original input question\n```",
|
|
233
|
+
lite_agent_system_prompt_without_tools: "You are {role}. {backstory}\nYour personal goal is: {goal}\n\nTo give my best complete final answer to the task respond using the exact following format:\n\nThought: I now can give a great answer\nFinal Answer: Your final answer must be the great and the most complete as possible, it must be outcome described.\n\nI MUST use these formats, my job depends on it!",
|
|
234
|
+
lite_agent_response_format: "Format your final answer according to the following OpenAPI schema: {response_format}\n\nIMPORTANT: Preserve the original content exactly as-is. Do NOT rewrite, paraphrase, or modify the meaning of the content. Only structure it to match the schema format.\n\nDo not include the OpenAPI schema in the final output. Ensure the final output does not include any code block markers like ```json or ```python.",
|
|
235
|
+
knowledge_search_query: "The original query is: {task_prompt}.",
|
|
236
|
+
knowledge_search_query_system_prompt: "Your goal is to rewrite the user query so that it is optimized for retrieval from a vector database. Consider how the query will be used to find relevant documents, and aim to make it more specific and context-aware. \n\n Do not include any other text than the rewritten query, especially any preamble or postamble and only add expected output format if its relevant to the rewritten query. \n\n Focus on the key words of the intended task and to retrieve the most relevant information. \n\n There will be some extra context provided that might need to be removed such as expected_output formats structured_outputs and other instructions.",
|
|
237
|
+
human_feedback_collapse: "Based on the following human feedback, determine which outcome best matches their intent.\n\nFeedback: {feedback}\n\nPossible outcomes: {outcomes}\n\nRespond with ONLY one of the exact outcome values listed above, nothing else."
|
|
238
|
+
},
|
|
239
|
+
errors: {
|
|
240
|
+
force_final_answer_error: "You can't keep going, here is the best final answer you generated:\n\n {formatted_answer}",
|
|
241
|
+
force_final_answer: "Now it's time you MUST give your absolute best final answer. You'll ignore all previous instructions, stop using any tools, and just return your absolute BEST Final answer.",
|
|
242
|
+
agent_tool_unexisting_coworker: "\nError executing tool. coworker mentioned not found, it must be one of the following options:\n{coworkers}\n",
|
|
243
|
+
task_repeated_usage: "I tried reusing the same input, I must stop using this action input. I'll try something else instead.\n\n",
|
|
244
|
+
tool_usage_error: "I encountered an error: {error}",
|
|
245
|
+
tool_arguments_error: "Error: the Action Input is not a valid key, value dictionary.",
|
|
246
|
+
wrong_tool_name: "You tried to use the tool {tool}, but it doesn't exist. You must use one of the following tools, use one at time: {tools}.",
|
|
247
|
+
tool_usage_exception: "I encountered an error while trying to use the tool. This was the error: {error}.\n Tool {tool} accepts these inputs: {tool_inputs}",
|
|
248
|
+
agent_tool_execution_error: "Error executing task with agent '{agent_role}'. Error: {error}",
|
|
249
|
+
validation_error: "### Previous attempt failed validation: {guardrail_result_error}\n\n\n### Previous result:\n{task_output}\n\n\nTry again, making sure to address the validation error."
|
|
250
|
+
},
|
|
251
|
+
tools: {
|
|
252
|
+
delegate_work: "Delegate a specific task to one of the following coworkers: {coworkers}\nThe input to this tool should be the coworker, the task you want them to do, and ALL necessary context to execute the task, they know nothing about the task, so share absolutely everything you know, don't reference things but instead explain them.",
|
|
253
|
+
ask_question: "Ask a specific question to one of the following coworkers: {coworkers}\nThe input to this tool should be the coworker, the question you have for them, and ALL necessary context to ask the question properly, they know nothing about the question, so share absolutely everything you know, don't reference things but instead explain them.",
|
|
254
|
+
add_image: {
|
|
255
|
+
name: "Add image to content",
|
|
256
|
+
description: "See image to understand its content, you can optionally ask a question about the image",
|
|
257
|
+
default_action: "Please provide a detailed description of this image, including all visual elements, context, and any notable details you can observe."
|
|
258
|
+
},
|
|
259
|
+
recall_memory: "Search through the team's shared memory for relevant information. Pass one or more queries to search for multiple things at once. Use this when you need to find facts, decisions, preferences, or past results that may have been stored previously. IMPORTANT: For questions that require counting, summing, or listing items across multiple conversations (e.g. 'how many X', 'total Y', 'list all Z'), you MUST search multiple times with different phrasings to ensure you find ALL relevant items before giving a final count or total. Do not rely on a single search -- items may be described differently across conversations.",
|
|
260
|
+
save_to_memory: "Store one or more important facts, decisions, observations, or lessons in memory so they can be recalled later by you or other agents. Pass multiple items at once when you have several things worth remembering."
|
|
261
|
+
},
|
|
262
|
+
memory: {
|
|
263
|
+
query_system: "You analyze a query for searching memory.\nGiven the query and available scopes, output:\n1. keywords: Key entities or keywords that can be used to filter by category.\n2. suggested_scopes: Which available scopes are most relevant (empty for all).\n3. complexity: 'simple' or 'complex'.\n4. recall_queries: 1-3 short, targeted search phrases distilled from the query. Each should be a concise phrase optimized for semantic vector search. If the query is already short and focused, return it as-is in a single-item list. For long task descriptions, extract the distinct things worth searching for.\n5. time_filter: If the query references a time period (like 'last week', 'yesterday', 'in January'), return an ISO 8601 date string for the earliest relevant date (e.g. '2026-02-01'). Return null if no time constraint is implied.",
|
|
264
|
+
extract_memories_user: "Content:\n{content}\n\nExtract memory statements as described. Return structured output.",
|
|
265
|
+
query_user: "Query: {query}\n\nAvailable scopes: {available_scopes}\n{scope_desc}\n\nReturn the analysis as structured output."
|
|
266
|
+
},
|
|
267
|
+
reasoning: {
|
|
268
|
+
initial_plan: "You are {role}. Create a focused execution plan using only the essential steps needed.",
|
|
269
|
+
refine_plan: "You are {role}. Refine your plan to address the specific gap while keeping it minimal."
|
|
270
|
+
},
|
|
271
|
+
planning: {
|
|
272
|
+
system_prompt: "You are a strategic planning assistant. Create concrete, executable plans where every step produces a verifiable result.",
|
|
273
|
+
create_plan_prompt: `Create an execution plan for the following task:
|
|
274
|
+
|
|
275
|
+
## Task
|
|
276
|
+
{description}
|
|
277
|
+
|
|
278
|
+
## Expected Output
|
|
279
|
+
{expected_output}
|
|
280
|
+
|
|
281
|
+
## Available Tools
|
|
282
|
+
{tools}
|
|
283
|
+
|
|
284
|
+
## Planning Principles
|
|
285
|
+
Focus on CONCRETE, EXECUTABLE steps. Each step must clearly state WHAT ACTION to take and HOW to verify it succeeded. The number of steps should match the task complexity. Hard limit: {max_steps} steps.
|
|
286
|
+
|
|
287
|
+
## Rules:
|
|
288
|
+
- Each step must have a clear DONE criterion
|
|
289
|
+
- Do NOT group unrelated actions: if steps can fail independently, keep them separate
|
|
290
|
+
- NO standalone "thinking" or "planning" steps -- act, don't just observe
|
|
291
|
+
- The last step must produce the required output
|
|
292
|
+
|
|
293
|
+
After your plan, state READY or NOT READY.`,
|
|
294
|
+
synthesis_system_prompt: "You are {role}. Synthesize the completed plan steps into a clear final answer.",
|
|
295
|
+
synthesis_user_prompt: "Original task:\n{task_description}\n\nCompleted steps:\n{combined_steps}\n\nProvide the final answer based on the completed steps."
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
var I18N = class {
|
|
299
|
+
promptFile;
|
|
300
|
+
prompt_file;
|
|
301
|
+
prompts;
|
|
302
|
+
constructor(options = {}) {
|
|
303
|
+
this.promptFile = options.promptFile ?? options.prompt_file ?? null;
|
|
304
|
+
this.prompt_file = this.promptFile;
|
|
305
|
+
this.prompts = options.prompts ?? (this.promptFile ? loadPromptCatalog(this.promptFile) : defaultPrompts);
|
|
306
|
+
}
|
|
307
|
+
loadPrompts() {
|
|
308
|
+
this.prompts = this.promptFile ? loadPromptCatalog(this.promptFile) : defaultPrompts;
|
|
309
|
+
return this;
|
|
310
|
+
}
|
|
311
|
+
load_prompts() {
|
|
312
|
+
return this.loadPrompts();
|
|
313
|
+
}
|
|
314
|
+
slice(slice) {
|
|
315
|
+
return this.retrieveString("slices", slice);
|
|
316
|
+
}
|
|
317
|
+
errors(error) {
|
|
318
|
+
return this.retrieveString("errors", error);
|
|
319
|
+
}
|
|
320
|
+
tools(tool) {
|
|
321
|
+
return this.retrieve("tools", tool);
|
|
322
|
+
}
|
|
323
|
+
memory(key) {
|
|
324
|
+
return this.retrieveString("memory", key);
|
|
325
|
+
}
|
|
326
|
+
retrieve(kind, key) {
|
|
327
|
+
const prompt = this.prompts[kind]?.[key];
|
|
328
|
+
if (prompt === void 0) {
|
|
329
|
+
throw new Error(`Prompt for '${kind}':'${key}' not found.`);
|
|
330
|
+
}
|
|
331
|
+
return prompt;
|
|
332
|
+
}
|
|
333
|
+
retrieveString(kind, key) {
|
|
334
|
+
const prompt = this.retrieve(kind, key);
|
|
335
|
+
if (typeof prompt !== "string") {
|
|
336
|
+
throw new Error(`Prompt for '${kind}':'${key}' is not a string.`);
|
|
337
|
+
}
|
|
338
|
+
return prompt;
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
var i18nCache = /* @__PURE__ */ new Map();
|
|
342
|
+
function getI18N(promptFile = null) {
|
|
343
|
+
const key = promptFile ?? "__default__";
|
|
344
|
+
const cached = i18nCache.get(key);
|
|
345
|
+
if (cached) {
|
|
346
|
+
return cached;
|
|
347
|
+
}
|
|
348
|
+
const i18n = new I18N({ promptFile });
|
|
349
|
+
i18nCache.set(key, i18n);
|
|
350
|
+
return i18n;
|
|
351
|
+
}
|
|
352
|
+
function clearI18NCache() {
|
|
353
|
+
i18nCache.clear();
|
|
354
|
+
}
|
|
355
|
+
function loadPromptCatalog(promptFile) {
|
|
356
|
+
try {
|
|
357
|
+
const parsed = JSON.parse(readFileSync(promptFile, "utf8"));
|
|
358
|
+
if (!isPromptCatalog(parsed)) {
|
|
359
|
+
throw new Error("Prompt catalog must be an object of prompt groups.");
|
|
360
|
+
}
|
|
361
|
+
return parsed;
|
|
362
|
+
} catch (error) {
|
|
363
|
+
if (error instanceof SyntaxError) {
|
|
364
|
+
throw new Error("Error decoding JSON from the prompts file.", { cause: error });
|
|
365
|
+
}
|
|
366
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
367
|
+
throw new Error(`Prompt file '${promptFile}' not found.`, { cause: error });
|
|
368
|
+
}
|
|
369
|
+
throw error;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function isPromptCatalog(value) {
|
|
373
|
+
if (!isRecord(value)) {
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
return Object.values(value).every((group) => {
|
|
377
|
+
return isRecord(group) && Object.values(group).every((entry) => {
|
|
378
|
+
return typeof entry === "string" || isRecord(entry) && Object.values(entry).every((leaf) => typeof leaf === "string");
|
|
379
|
+
});
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
function isRecord(value) {
|
|
383
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
384
|
+
}
|
|
385
|
+
var I18N_DEFAULT = getI18N();
|
|
386
|
+
var get_i18n = getI18N;
|
|
387
|
+
var clear_i18n_cache = clearI18NCache;
|
|
388
|
+
|
|
389
|
+
// src/agent-parser.ts
|
|
390
|
+
var FINAL_ANSWER_ACTION = "Final Answer:";
|
|
391
|
+
var MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE = "I did it wrong. Invalid Format: I missed the 'Action:' after 'Thought:'. I will do right next, and don't use a tool I have already used.\n";
|
|
392
|
+
var MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE = "I did it wrong. Invalid Format: I missed the 'Action Input:' after 'Action:'. I will do right next, and don't use a tool I have already used.\n";
|
|
393
|
+
var FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE = "I did it wrong. Tried to both perform Action and give a Final Answer at the same time, I must do one or the other";
|
|
394
|
+
var UNABLE_TO_REPAIR_JSON_RESULTS = /* @__PURE__ */ new Set(['""', "{}"]);
|
|
395
|
+
var ACTION_INPUT_REGEX = /Action\s*\d*\s*:\s*(.*?)\s*Action\s*\d*\s*Input\s*\d*\s*:\s*(.*)/s;
|
|
396
|
+
var ACTION_REGEX = /Action\s*\d*\s*:\s*(.*?)/s;
|
|
397
|
+
var ACTION_INPUT_ONLY_REGEX = /\s*Action\s*\d*\s*Input\s*\d*\s*:\s*(.*)/s;
|
|
398
|
+
var AgentAction = class {
|
|
399
|
+
thought;
|
|
400
|
+
tool;
|
|
401
|
+
toolInput;
|
|
402
|
+
tool_input;
|
|
403
|
+
text;
|
|
404
|
+
result;
|
|
405
|
+
constructor(options) {
|
|
406
|
+
this.thought = options.thought;
|
|
407
|
+
this.tool = options.tool;
|
|
408
|
+
this.toolInput = options.toolInput ?? options.tool_input ?? "";
|
|
409
|
+
this.tool_input = this.toolInput;
|
|
410
|
+
this.text = options.text;
|
|
411
|
+
this.result = options.result ?? null;
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
var AgentFinish = class {
|
|
415
|
+
thought;
|
|
416
|
+
output;
|
|
417
|
+
text;
|
|
418
|
+
constructor(options) {
|
|
419
|
+
this.thought = options.thought;
|
|
420
|
+
this.output = options.output;
|
|
421
|
+
this.text = options.text;
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
var OutputParserError = class extends Error {
|
|
425
|
+
error;
|
|
426
|
+
constructor(error) {
|
|
427
|
+
super(error);
|
|
428
|
+
this.name = "OutputParserError";
|
|
429
|
+
this.error = error;
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
function parseAgentOutput(text) {
|
|
433
|
+
const thought = extractThought(text);
|
|
434
|
+
const includesAnswer = text.includes(FINAL_ANSWER_ACTION);
|
|
435
|
+
const actionMatch = ACTION_INPUT_REGEX.exec(text);
|
|
436
|
+
if (includesAnswer) {
|
|
437
|
+
let finalAnswer = text.split(FINAL_ANSWER_ACTION).at(-1)?.trim() ?? "";
|
|
438
|
+
if (finalAnswer.endsWith("```") && finalAnswer.split("```").length % 2 === 0) {
|
|
439
|
+
finalAnswer = finalAnswer.slice(0, -3).trimEnd();
|
|
440
|
+
}
|
|
441
|
+
return new AgentFinish({ thought, output: finalAnswer, text });
|
|
442
|
+
}
|
|
443
|
+
if (actionMatch) {
|
|
444
|
+
const action = actionMatch[1] ?? "";
|
|
445
|
+
const actionInput = cleanActionInput(actionMatch[2] ?? "");
|
|
446
|
+
const toolInput = actionInput.trim().replace(/^"|"$/g, "");
|
|
447
|
+
return new AgentAction({
|
|
448
|
+
thought,
|
|
449
|
+
tool: cleanAction(action),
|
|
450
|
+
toolInput: safeRepairJson(toolInput),
|
|
451
|
+
text
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
if (!ACTION_REGEX.test(text)) {
|
|
455
|
+
throw new OutputParserError(`${MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE}
|
|
456
|
+
${I18N_DEFAULT.slice("final_answer_format")}`);
|
|
457
|
+
}
|
|
458
|
+
if (!ACTION_INPUT_ONLY_REGEX.test(text)) {
|
|
459
|
+
throw new OutputParserError(MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE);
|
|
460
|
+
}
|
|
461
|
+
throw new OutputParserError(I18N_DEFAULT.slice("format_without_tools"));
|
|
462
|
+
}
|
|
463
|
+
var parse = parseAgentOutput;
|
|
464
|
+
function extractThought(text) {
|
|
465
|
+
let thoughtIndex = text.indexOf("\nAction");
|
|
466
|
+
if (thoughtIndex === -1) {
|
|
467
|
+
thoughtIndex = text.indexOf("\nFinal Answer");
|
|
468
|
+
}
|
|
469
|
+
if (thoughtIndex === -1) {
|
|
470
|
+
return "";
|
|
471
|
+
}
|
|
472
|
+
return text.slice(0, thoughtIndex).trim().replaceAll("```", "").trim();
|
|
473
|
+
}
|
|
474
|
+
function cleanAction(text) {
|
|
475
|
+
return text.trim().replace(/^\*+|\*+$/g, "").trim();
|
|
476
|
+
}
|
|
477
|
+
function cleanActionInput(text) {
|
|
478
|
+
return text.trim().replace(/^\*+\s+/, "").trim();
|
|
479
|
+
}
|
|
480
|
+
function safeRepairJson(toolInput) {
|
|
481
|
+
if (toolInput.startsWith("[") && toolInput.endsWith("]")) {
|
|
482
|
+
return toolInput;
|
|
483
|
+
}
|
|
484
|
+
const normalized = toolInput.replaceAll('"""', '"');
|
|
485
|
+
try {
|
|
486
|
+
const parsed = JSON.parse(normalized);
|
|
487
|
+
const repaired = JSON.stringify(parsed);
|
|
488
|
+
return UNABLE_TO_REPAIR_JSON_RESULTS.has(repaired) ? toolInput : repaired;
|
|
489
|
+
} catch {
|
|
490
|
+
return repairLooseJsonObject(normalized) ?? toolInput;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
function repairLooseJsonObject(value) {
|
|
494
|
+
const trimmed = extractLooseJsonObject(value.trim());
|
|
495
|
+
if (trimmed === null) {
|
|
496
|
+
return null;
|
|
497
|
+
}
|
|
498
|
+
const withoutRawNewlines = trimmed.replaceAll(/\r?\n/g, "");
|
|
499
|
+
const withoutTrailingCommas = withoutRawNewlines.replace(/,\s*([}\]])/g, "$1");
|
|
500
|
+
const quotedKeys = withoutTrailingCommas.replace(/([{,]\s*)([A-Za-z_][\w-]*)(\s*:)/g, '$1"$2"$3');
|
|
501
|
+
const singleToDouble = quotedKeys.replace(/'([^']*)'/g, (_match, inner) => JSON.stringify(inner));
|
|
502
|
+
const withMissingColons = singleToDouble.replace(/("([^"\\]|\\.)*")\s+("([^"\\]|\\.)*")(?=\s*[,}])/g, "$1: $3");
|
|
503
|
+
const withMissingCommas = withMissingColons.replace(/("([^"\\]|\\.)*")\s+("([^"\\]|\\.)*"\s*:)/g, "$1, $3");
|
|
504
|
+
const withQuotedBareValues = withMissingCommas.replace(
|
|
505
|
+
/:\s*([^,}]*?)(\s*[,}])/g,
|
|
506
|
+
(match, raw, suffix) => {
|
|
507
|
+
const value2 = raw.trim();
|
|
508
|
+
if (value2 === "" || value2.startsWith('"') || value2.startsWith("{") || value2.startsWith("[")) {
|
|
509
|
+
return match;
|
|
510
|
+
}
|
|
511
|
+
if (/^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(value2) || ["true", "false", "null"].includes(value2)) {
|
|
512
|
+
return `: ${value2}${suffix}`;
|
|
513
|
+
}
|
|
514
|
+
return `: ${JSON.stringify(value2)}${suffix}`;
|
|
515
|
+
}
|
|
516
|
+
);
|
|
517
|
+
try {
|
|
518
|
+
const parsed = JSON.parse(withQuotedBareValues);
|
|
519
|
+
return JSON.stringify(parsed);
|
|
520
|
+
} catch {
|
|
521
|
+
return null;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function extractLooseJsonObject(value) {
|
|
525
|
+
if (!value.startsWith("{")) {
|
|
526
|
+
return null;
|
|
527
|
+
}
|
|
528
|
+
let depth = 0;
|
|
529
|
+
let inString = null;
|
|
530
|
+
let escaped = false;
|
|
531
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
532
|
+
const char = value[index];
|
|
533
|
+
if (escaped) {
|
|
534
|
+
escaped = false;
|
|
535
|
+
continue;
|
|
536
|
+
}
|
|
537
|
+
if (char === "\\") {
|
|
538
|
+
escaped = true;
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
if (inString) {
|
|
542
|
+
if (char === inString) {
|
|
543
|
+
inString = null;
|
|
544
|
+
}
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
if (char === '"' || char === "'") {
|
|
548
|
+
inString = char;
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
if (char === "{") {
|
|
552
|
+
depth += 1;
|
|
553
|
+
} else if (char === "}") {
|
|
554
|
+
depth -= 1;
|
|
555
|
+
if (depth === 0) {
|
|
556
|
+
return value.slice(0, index + 1);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
if (depth > 0) {
|
|
561
|
+
return `${value}${inString ?? ""}${"}".repeat(depth)}`;
|
|
562
|
+
}
|
|
563
|
+
return null;
|
|
564
|
+
}
|
|
565
|
+
var parse_agent_output = parseAgentOutput;
|
|
566
|
+
var _extract_thought = extractThought;
|
|
567
|
+
var _clean_action = cleanAction;
|
|
568
|
+
var _safe_repair_json = safeRepairJson;
|
|
569
|
+
|
|
570
|
+
// src/converter.ts
|
|
571
|
+
var CreateConverterKwargs = class {
|
|
572
|
+
agent;
|
|
573
|
+
converterCls;
|
|
574
|
+
converter_cls;
|
|
575
|
+
llm;
|
|
576
|
+
text;
|
|
577
|
+
model;
|
|
578
|
+
instructions;
|
|
579
|
+
constructor(options) {
|
|
580
|
+
this.agent = options.agent;
|
|
581
|
+
this.converterCls = options.converterCls ?? options.converter_cls ?? Converter;
|
|
582
|
+
this.converter_cls = this.converterCls;
|
|
583
|
+
this.llm = options.llm;
|
|
584
|
+
this.text = options.text;
|
|
585
|
+
this.model = options.model;
|
|
586
|
+
this.instructions = options.instructions;
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
var jsonPattern = /({.*})/s;
|
|
590
|
+
var ConverterError = class extends Error {
|
|
591
|
+
message;
|
|
592
|
+
constructor(message) {
|
|
593
|
+
super(message);
|
|
594
|
+
this.name = "ConverterError";
|
|
595
|
+
this.message = message;
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
var Converter = class {
|
|
599
|
+
llm;
|
|
600
|
+
text;
|
|
601
|
+
model;
|
|
602
|
+
instructions;
|
|
603
|
+
maxAttempts;
|
|
604
|
+
max_attempts;
|
|
605
|
+
constructor(options) {
|
|
606
|
+
this.llm = options.llm;
|
|
607
|
+
this.text = options.text;
|
|
608
|
+
this.model = options.model;
|
|
609
|
+
this.instructions = options.instructions;
|
|
610
|
+
this.maxAttempts = options.maxAttempts ?? options.max_attempts ?? 3;
|
|
611
|
+
this.max_attempts = this.maxAttempts;
|
|
612
|
+
}
|
|
613
|
+
buildMessages() {
|
|
614
|
+
return [
|
|
615
|
+
{ role: "system", content: this.instructions },
|
|
616
|
+
{ role: "user", content: this.text }
|
|
617
|
+
];
|
|
618
|
+
}
|
|
619
|
+
_build_messages() {
|
|
620
|
+
return this.buildMessages();
|
|
621
|
+
}
|
|
622
|
+
async toPydantic(currentAttempt = 1) {
|
|
623
|
+
try {
|
|
624
|
+
const messages = this.buildMessages();
|
|
625
|
+
const response = supportsFunctionCalling(this.llm) ? await this.llm.call(messages, { responseModel: this.model }) : await this.llm.call(messages);
|
|
626
|
+
return this._coerce_response_to_pydantic(response);
|
|
627
|
+
} catch (error) {
|
|
628
|
+
if (currentAttempt < this.maxAttempts) {
|
|
629
|
+
return await this.toPydantic(currentAttempt + 1);
|
|
630
|
+
}
|
|
631
|
+
throw new ConverterError(`Failed to convert text into a Pydantic model due to error: ${error instanceof Error ? error.message : String(error)}`);
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
to_pydantic(currentAttempt = 1) {
|
|
635
|
+
return this.toPydantic(currentAttempt);
|
|
636
|
+
}
|
|
637
|
+
async atoPydantic(currentAttempt = 1) {
|
|
638
|
+
try {
|
|
639
|
+
const messages = this.buildMessages();
|
|
640
|
+
const response = supportsFunctionCalling(this.llm) ? await callLlmAsync(this.llm, messages, { responseModel: this.model }) : await callLlmAsync(this.llm, messages);
|
|
641
|
+
return this._coerce_response_to_pydantic(response);
|
|
642
|
+
} catch (error) {
|
|
643
|
+
if (currentAttempt < this.maxAttempts) {
|
|
644
|
+
return await this.atoPydantic(currentAttempt + 1);
|
|
645
|
+
}
|
|
646
|
+
throw new ConverterError(`Failed to convert text into a Pydantic model due to error: ${error instanceof Error ? error.message : String(error)}`);
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
ato_pydantic(currentAttempt = 1) {
|
|
650
|
+
return this.atoPydantic(currentAttempt);
|
|
651
|
+
}
|
|
652
|
+
async toJson(currentAttempt = 1) {
|
|
653
|
+
try {
|
|
654
|
+
if (supportsFunctionCalling(this.llm)) {
|
|
655
|
+
return this._create_instructor().toJson();
|
|
656
|
+
}
|
|
657
|
+
return JSON.stringify(await this.llm.call(this.buildMessages()));
|
|
658
|
+
} catch (error) {
|
|
659
|
+
if (currentAttempt < this.maxAttempts) {
|
|
660
|
+
return await this.toJson(currentAttempt + 1);
|
|
661
|
+
}
|
|
662
|
+
return new ConverterError(`Failed to convert text into JSON, error: ${error instanceof Error ? error.message : String(error)}.`);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
to_json(currentAttempt = 1) {
|
|
666
|
+
return this.toJson(currentAttempt);
|
|
667
|
+
}
|
|
668
|
+
async atoJson(currentAttempt = 1) {
|
|
669
|
+
try {
|
|
670
|
+
if (supportsFunctionCalling(this.llm)) {
|
|
671
|
+
return await runSyncAfterAsyncTurn(() => this._create_instructor().toJson());
|
|
672
|
+
}
|
|
673
|
+
return JSON.stringify(await callLlmAsync(this.llm, this.buildMessages()));
|
|
674
|
+
} catch (error) {
|
|
675
|
+
if (currentAttempt < this.maxAttempts) {
|
|
676
|
+
return await this.atoJson(currentAttempt + 1);
|
|
677
|
+
}
|
|
678
|
+
return new ConverterError(`Failed to convert text into JSON, error: ${error instanceof Error ? error.message : String(error)}.`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
ato_json(currentAttempt = 1) {
|
|
682
|
+
return this.atoJson(currentAttempt);
|
|
683
|
+
}
|
|
684
|
+
_coerce_response_to_pydantic(response) {
|
|
685
|
+
return coerceResponseToModel(response, this.model);
|
|
686
|
+
}
|
|
687
|
+
_create_instructor() {
|
|
688
|
+
return new InternalInstructor(this.text, this.model, null, this.llm);
|
|
689
|
+
}
|
|
690
|
+
};
|
|
691
|
+
function runSyncAfterAsyncTurn(operation) {
|
|
692
|
+
return new Promise((resolve, reject) => {
|
|
693
|
+
const run = () => {
|
|
694
|
+
try {
|
|
695
|
+
resolve(operation());
|
|
696
|
+
} catch (error) {
|
|
697
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
if (typeof setImmediate === "function") {
|
|
701
|
+
setImmediate(run);
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
setTimeout(run, 0);
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
function validateModel(result, model, isJsonOutput) {
|
|
708
|
+
const parsed = parseJsonLenient(result);
|
|
709
|
+
const validated = validateStructuredModel(parsed, model);
|
|
710
|
+
return isJsonOutput ? dumpStructuredModel(validated, model) : validated;
|
|
711
|
+
}
|
|
712
|
+
var validate_model = validateModel;
|
|
713
|
+
function handlePartialJson(result, model, isJsonOutput, agent = null, converterClass) {
|
|
714
|
+
const match = jsonPattern.exec(result);
|
|
715
|
+
if (match?.[1]) {
|
|
716
|
+
try {
|
|
717
|
+
return validateModel(match[1], model, isJsonOutput);
|
|
718
|
+
} catch {
|
|
719
|
+
if (!agent && !converterClass) {
|
|
720
|
+
return result;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
if (!agent && !converterClass) {
|
|
725
|
+
return result;
|
|
726
|
+
}
|
|
727
|
+
return convertWithInstructions(result, model, isJsonOutput, agent, converterClass ?? Converter);
|
|
728
|
+
}
|
|
729
|
+
var handle_partial_json = handlePartialJson;
|
|
730
|
+
async function asyncHandlePartialJson(result, model, isJsonOutput, agent = null, converterClass) {
|
|
731
|
+
const match = jsonPattern.exec(result);
|
|
732
|
+
if (match?.[1]) {
|
|
733
|
+
try {
|
|
734
|
+
return validateModel(match[1], model, isJsonOutput);
|
|
735
|
+
} catch (error) {
|
|
736
|
+
if (!agent) {
|
|
737
|
+
return result;
|
|
738
|
+
}
|
|
739
|
+
if (error instanceof SyntaxError) {
|
|
740
|
+
return await asyncConvertWithInstructions(result, model, isJsonOutput, agent, converterClass ?? Converter);
|
|
741
|
+
}
|
|
742
|
+
throw error;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
if (!agent) {
|
|
746
|
+
return result;
|
|
747
|
+
}
|
|
748
|
+
return await asyncConvertWithInstructions(result, model, isJsonOutput, agent, converterClass ?? Converter);
|
|
749
|
+
}
|
|
750
|
+
var async_handle_partial_json = asyncHandlePartialJson;
|
|
751
|
+
function convertToModel(result, outputPydantic, outputJson, agent = null, converterClass) {
|
|
752
|
+
const model = outputPydantic ?? outputJson;
|
|
753
|
+
if (!model) {
|
|
754
|
+
return result;
|
|
755
|
+
}
|
|
756
|
+
if (typeof result !== "string") {
|
|
757
|
+
return outputJson ? dumpStructuredModel(result, model) : result;
|
|
758
|
+
}
|
|
759
|
+
if (converterClass) {
|
|
760
|
+
throw new ConverterError("Use asyncConvertToModel when converterClass fallback is required.");
|
|
761
|
+
}
|
|
762
|
+
try {
|
|
763
|
+
return validateModel(JSON.stringify(JSON.parse(result)), model, Boolean(outputJson));
|
|
764
|
+
} catch {
|
|
765
|
+
return handlePartialJson(result, model, Boolean(outputJson), agent, converterClass);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
var convert_to_model = convertToModel;
|
|
769
|
+
function convertWithInstructions(result, model, isJsonOutput, agent, converterClass = Converter) {
|
|
770
|
+
if (!agent) {
|
|
771
|
+
throw new TypeError("Agent must be provided if converter_cls is not specified.");
|
|
772
|
+
}
|
|
773
|
+
if (converterClass !== Converter) {
|
|
774
|
+
throw new ConverterError("Use asyncConvertToModel when converterClass fallback is required.");
|
|
775
|
+
}
|
|
776
|
+
const llm = agent.functionCallingLlm ?? agent.function_calling_llm ?? agent.llm;
|
|
777
|
+
if (!llm) {
|
|
778
|
+
throw new Error("Agent must have a valid LLM instance for conversion");
|
|
779
|
+
}
|
|
780
|
+
const response = llm.call(
|
|
781
|
+
[
|
|
782
|
+
{ role: "system", content: getConversionInstructions(model, llm) },
|
|
783
|
+
{ role: "user", content: result }
|
|
784
|
+
],
|
|
785
|
+
{ responseModel: model }
|
|
786
|
+
);
|
|
787
|
+
if (isPromiseLike(response)) {
|
|
788
|
+
throw new ConverterError("Use asyncConvertToModel when the LLM conversion fallback returns a Promise.");
|
|
789
|
+
}
|
|
790
|
+
if (isJsonOutput) {
|
|
791
|
+
const converted = typeof response === "string" ? response : JSON.stringify(response);
|
|
792
|
+
try {
|
|
793
|
+
return validateModel(converted, model, true);
|
|
794
|
+
} catch {
|
|
795
|
+
return result;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
try {
|
|
799
|
+
return coerceResponseToModel(response, model);
|
|
800
|
+
} catch {
|
|
801
|
+
return result;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
var convert_with_instructions = convertWithInstructions;
|
|
805
|
+
var convertWithInstructionsSync = convertWithInstructions;
|
|
806
|
+
var convert_with_instructions_sync = convertWithInstructions;
|
|
807
|
+
async function asyncConvertWithInstructions(result, model, isJsonOutput, agent, converterClass = Converter) {
|
|
808
|
+
if (!agent) {
|
|
809
|
+
throw new TypeError("Agent must be provided if converter_cls is not specified.");
|
|
810
|
+
}
|
|
811
|
+
const llm = agent.functionCallingLlm ?? agent.function_calling_llm ?? agent.llm;
|
|
812
|
+
if (!llm) {
|
|
813
|
+
throw new Error("Agent must have a valid LLM instance for conversion");
|
|
814
|
+
}
|
|
815
|
+
const converter = new converterClass({
|
|
816
|
+
agent,
|
|
817
|
+
llm,
|
|
818
|
+
text: result,
|
|
819
|
+
model,
|
|
820
|
+
instructions: getConversionInstructions(model, llm)
|
|
821
|
+
});
|
|
822
|
+
const converted = isJsonOutput ? await converter.toJson() : await converter.toPydantic();
|
|
823
|
+
if (converted instanceof ConverterError) {
|
|
824
|
+
return result;
|
|
825
|
+
}
|
|
826
|
+
if (isJsonOutput && typeof converted === "string") {
|
|
827
|
+
return validateModel(converted, model, true);
|
|
828
|
+
}
|
|
829
|
+
return converted;
|
|
830
|
+
}
|
|
831
|
+
var async_convert_with_instructions = asyncConvertWithInstructions;
|
|
832
|
+
function createConverter(first, converterClass, ...args) {
|
|
833
|
+
if (isConverterOptions(first) && converterClass === void 0 && args.length === 0) {
|
|
834
|
+
const options = first;
|
|
835
|
+
return new Converter(options);
|
|
836
|
+
}
|
|
837
|
+
let converter;
|
|
838
|
+
if (first && !converterClass) {
|
|
839
|
+
const agent = first;
|
|
840
|
+
const factory = typeof agent.getOutputConverter === "function" ? agent.getOutputConverter : agent.get_output_converter;
|
|
841
|
+
if (!factory) {
|
|
842
|
+
throw new Error("Agent does not have a 'get_output_converter' method");
|
|
843
|
+
}
|
|
844
|
+
converter = factory(...args);
|
|
845
|
+
} else if (converterClass) {
|
|
846
|
+
converter = new converterClass(...args);
|
|
847
|
+
} else {
|
|
848
|
+
throw new Error("Either agent or converter_cls must be provided");
|
|
849
|
+
}
|
|
850
|
+
if (!converter) {
|
|
851
|
+
throw new Error("No output converter found or set.");
|
|
852
|
+
}
|
|
853
|
+
return converter;
|
|
854
|
+
}
|
|
855
|
+
var create_converter = createConverter;
|
|
856
|
+
async function asyncConvertToModel(result, outputPydantic, outputJson, agent = null, converterClass) {
|
|
857
|
+
const model = outputPydantic ?? outputJson;
|
|
858
|
+
if (!model) {
|
|
859
|
+
return result;
|
|
860
|
+
}
|
|
861
|
+
if (typeof result !== "string") {
|
|
862
|
+
return outputJson ? dumpStructuredModel(result, model) : result;
|
|
863
|
+
}
|
|
864
|
+
try {
|
|
865
|
+
return validateModel(JSON.stringify(JSON.parse(result)), model, Boolean(outputJson));
|
|
866
|
+
} catch {
|
|
867
|
+
if (converterClass) {
|
|
868
|
+
return await asyncConvertWithInstructions(result, model, Boolean(outputJson), agent, converterClass);
|
|
869
|
+
}
|
|
870
|
+
return await asyncHandlePartialJson(result, model, Boolean(outputJson), agent, converterClass);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
var async_convert_to_model = asyncConvertToModel;
|
|
874
|
+
function getConversionInstructions(model, _llm) {
|
|
875
|
+
void _llm;
|
|
876
|
+
return `Convert the following text into the requested JSON schema:
|
|
877
|
+
${JSON.stringify(describeModel(model), null, 2)}`;
|
|
878
|
+
}
|
|
879
|
+
var get_conversion_instructions = getConversionInstructions;
|
|
880
|
+
function coerceResponseToModel(response, model) {
|
|
881
|
+
if (typeof response === "string") {
|
|
882
|
+
try {
|
|
883
|
+
return validateStructuredModel(parseJsonLenient(response), model);
|
|
884
|
+
} catch {
|
|
885
|
+
const partial = handlePartialJson(response, model, false);
|
|
886
|
+
if (typeof partial === "string") {
|
|
887
|
+
throw new ConverterError(`Failed to convert partial JSON result into Pydantic: ${partial}`);
|
|
888
|
+
}
|
|
889
|
+
return partial;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
return validateStructuredModel(response, model);
|
|
893
|
+
}
|
|
894
|
+
function parseJsonLenient(result) {
|
|
895
|
+
try {
|
|
896
|
+
return JSON.parse(result);
|
|
897
|
+
} catch (error) {
|
|
898
|
+
try {
|
|
899
|
+
return JSON.parse(escapeControlCharactersInsideStrings(result));
|
|
900
|
+
} catch {
|
|
901
|
+
throw error;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
function escapeControlCharactersInsideStrings(result) {
|
|
906
|
+
let output = "";
|
|
907
|
+
let inString = false;
|
|
908
|
+
let escaped = false;
|
|
909
|
+
for (const char of result) {
|
|
910
|
+
if (escaped) {
|
|
911
|
+
output += char;
|
|
912
|
+
escaped = false;
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
if (char === "\\") {
|
|
916
|
+
output += char;
|
|
917
|
+
escaped = inString;
|
|
918
|
+
continue;
|
|
919
|
+
}
|
|
920
|
+
if (char === '"') {
|
|
921
|
+
inString = !inString;
|
|
922
|
+
output += char;
|
|
923
|
+
continue;
|
|
924
|
+
}
|
|
925
|
+
if (inString && char.charCodeAt(0) < 32) {
|
|
926
|
+
output += escapeJsonControlCharacter(char);
|
|
927
|
+
continue;
|
|
928
|
+
}
|
|
929
|
+
output += char;
|
|
930
|
+
}
|
|
931
|
+
return output;
|
|
932
|
+
}
|
|
933
|
+
function escapeJsonControlCharacter(char) {
|
|
934
|
+
switch (char) {
|
|
935
|
+
case "\b":
|
|
936
|
+
return "\\b";
|
|
937
|
+
case "\f":
|
|
938
|
+
return "\\f";
|
|
939
|
+
case "\n":
|
|
940
|
+
return "\\n";
|
|
941
|
+
case "\r":
|
|
942
|
+
return "\\r";
|
|
943
|
+
case " ":
|
|
944
|
+
return "\\t";
|
|
945
|
+
default:
|
|
946
|
+
return `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}`;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
function supportsFunctionCalling(llm) {
|
|
950
|
+
if (typeof llm.supportsFunctionCalling === "function") {
|
|
951
|
+
return llm.supportsFunctionCalling();
|
|
952
|
+
}
|
|
953
|
+
if (typeof llm.supports_function_calling === "function") {
|
|
954
|
+
return llm.supports_function_calling();
|
|
955
|
+
}
|
|
956
|
+
return true;
|
|
957
|
+
}
|
|
958
|
+
async function callLlmAsync(llm, messages, options) {
|
|
959
|
+
if (typeof llm.acall === "function") {
|
|
960
|
+
return await llm.acall(messages, options);
|
|
961
|
+
}
|
|
962
|
+
return await llm.call(messages, options);
|
|
963
|
+
}
|
|
964
|
+
function validateStructuredModel(value, model) {
|
|
965
|
+
if (typeof model === "function") {
|
|
966
|
+
return model(value);
|
|
967
|
+
}
|
|
968
|
+
if (model.modelValidate) {
|
|
969
|
+
return model.modelValidate(value);
|
|
970
|
+
}
|
|
971
|
+
if (model.model_validate) {
|
|
972
|
+
return model.model_validate(value);
|
|
973
|
+
}
|
|
974
|
+
if (typeof value === "string" && model.modelValidateJson) {
|
|
975
|
+
return model.modelValidateJson(value);
|
|
976
|
+
}
|
|
977
|
+
if (typeof value === "string" && model.model_validate_json) {
|
|
978
|
+
return model.model_validate_json(value);
|
|
979
|
+
}
|
|
980
|
+
return value;
|
|
981
|
+
}
|
|
982
|
+
function dumpStructuredModel(value, model) {
|
|
983
|
+
if (typeof model !== "function" && model.modelDump) {
|
|
984
|
+
return model.modelDump(value);
|
|
985
|
+
}
|
|
986
|
+
if (typeof model !== "function" && model.model_dump) {
|
|
987
|
+
return model.model_dump(value);
|
|
988
|
+
}
|
|
989
|
+
return value && typeof value === "object" && !Array.isArray(value) ? { ...value } : { value };
|
|
990
|
+
}
|
|
991
|
+
function isPromiseLike(value) {
|
|
992
|
+
return Boolean(value && typeof value === "object" && "then" in value && typeof value.then === "function");
|
|
993
|
+
}
|
|
994
|
+
function isConverterOptions(value) {
|
|
995
|
+
return Boolean(
|
|
996
|
+
value && typeof value === "object" && "llm" in value && "text" in value && "model" in value && "instructions" in value
|
|
997
|
+
);
|
|
998
|
+
}
|
|
999
|
+
function describeModel(model) {
|
|
1000
|
+
return typeof model === "function" ? { name: model.name || "Model" } : model.schema ?? { name: model.name ?? "Model" };
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// src/security.ts
|
|
1004
|
+
import { createHash as createHash2, randomUUID } from "crypto";
|
|
1005
|
+
var CREW_AI_NAMESPACE = "f47ac10b-58cc-4372-a567-0e02b2c3d479";
|
|
1006
|
+
var Fingerprint = class _Fingerprint {
|
|
1007
|
+
uuidValue;
|
|
1008
|
+
createdAtValue;
|
|
1009
|
+
metadata;
|
|
1010
|
+
constructor(options = {}) {
|
|
1011
|
+
this.uuidValue = randomUUID();
|
|
1012
|
+
this.createdAtValue = /* @__PURE__ */ new Date();
|
|
1013
|
+
this.metadata = validateMetadata(options.metadata ?? {});
|
|
1014
|
+
}
|
|
1015
|
+
get uuidStr() {
|
|
1016
|
+
return this.uuidValue;
|
|
1017
|
+
}
|
|
1018
|
+
get uuid_str() {
|
|
1019
|
+
return this.uuidStr;
|
|
1020
|
+
}
|
|
1021
|
+
get createdAt() {
|
|
1022
|
+
return this.createdAtValue;
|
|
1023
|
+
}
|
|
1024
|
+
get created_at() {
|
|
1025
|
+
return this.createdAt;
|
|
1026
|
+
}
|
|
1027
|
+
get uuid() {
|
|
1028
|
+
validateUuid(this.uuidValue);
|
|
1029
|
+
return this.uuidValue;
|
|
1030
|
+
}
|
|
1031
|
+
static generate(seed, metadata) {
|
|
1032
|
+
const fingerprint = new _Fingerprint({ metadata: metadata ?? {} });
|
|
1033
|
+
if (seed !== void 0 && seed !== null) {
|
|
1034
|
+
fingerprint.uuidValue = _Fingerprint.generateUuid(seed);
|
|
1035
|
+
}
|
|
1036
|
+
return fingerprint;
|
|
1037
|
+
}
|
|
1038
|
+
static generateUuid(seed) {
|
|
1039
|
+
if (!seed.trim()) {
|
|
1040
|
+
throw new Error("Seed cannot be empty or whitespace");
|
|
1041
|
+
}
|
|
1042
|
+
return uuidV5(seed, CREW_AI_NAMESPACE);
|
|
1043
|
+
}
|
|
1044
|
+
static _generate_uuid(seed) {
|
|
1045
|
+
return _Fingerprint.generateUuid(seed);
|
|
1046
|
+
}
|
|
1047
|
+
static fromDict(data) {
|
|
1048
|
+
if (!data) {
|
|
1049
|
+
return new _Fingerprint();
|
|
1050
|
+
}
|
|
1051
|
+
const fingerprint = new _Fingerprint({ metadata: data.metadata ?? {} });
|
|
1052
|
+
fingerprint.uuidValue = data.uuidStr ?? data.uuid_str ?? fingerprint.uuidValue;
|
|
1053
|
+
const createdAt = data.createdAt ?? data.created_at;
|
|
1054
|
+
if (createdAt) {
|
|
1055
|
+
fingerprint.createdAtValue = new Date(createdAt);
|
|
1056
|
+
}
|
|
1057
|
+
return fingerprint;
|
|
1058
|
+
}
|
|
1059
|
+
static from_dict(data) {
|
|
1060
|
+
return _Fingerprint.fromDict(data);
|
|
1061
|
+
}
|
|
1062
|
+
toDict() {
|
|
1063
|
+
return {
|
|
1064
|
+
uuid_str: this.uuidStr,
|
|
1065
|
+
created_at: this.createdAt.toISOString(),
|
|
1066
|
+
metadata: this.metadata
|
|
1067
|
+
};
|
|
1068
|
+
}
|
|
1069
|
+
to_dict() {
|
|
1070
|
+
return this.toDict();
|
|
1071
|
+
}
|
|
1072
|
+
equals(other) {
|
|
1073
|
+
return other instanceof _Fingerprint && other.uuidStr === this.uuidStr;
|
|
1074
|
+
}
|
|
1075
|
+
__eq__(other) {
|
|
1076
|
+
return this.equals(other);
|
|
1077
|
+
}
|
|
1078
|
+
__hash__() {
|
|
1079
|
+
return stringHash(this.uuidStr);
|
|
1080
|
+
}
|
|
1081
|
+
toString() {
|
|
1082
|
+
return this.uuidStr;
|
|
1083
|
+
}
|
|
1084
|
+
__str__() {
|
|
1085
|
+
return this.toString();
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
function stringHash(value) {
|
|
1089
|
+
let hash = 0;
|
|
1090
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1091
|
+
hash = Math.imul(31, hash) + value.charCodeAt(index);
|
|
1092
|
+
hash |= 0;
|
|
1093
|
+
}
|
|
1094
|
+
return hash;
|
|
1095
|
+
}
|
|
1096
|
+
var SecurityConfig = class _SecurityConfig {
|
|
1097
|
+
fingerprint;
|
|
1098
|
+
constructor(options = {}) {
|
|
1099
|
+
this.fingerprint = coerceFingerprint(options.fingerprint);
|
|
1100
|
+
}
|
|
1101
|
+
static validateFingerprint(value) {
|
|
1102
|
+
return coerceFingerprint(value);
|
|
1103
|
+
}
|
|
1104
|
+
static validate_fingerprint(value) {
|
|
1105
|
+
return _SecurityConfig.validateFingerprint(value);
|
|
1106
|
+
}
|
|
1107
|
+
static fromDict(data) {
|
|
1108
|
+
return new _SecurityConfig({ fingerprint: data?.fingerprint ?? null });
|
|
1109
|
+
}
|
|
1110
|
+
static from_dict(data) {
|
|
1111
|
+
return _SecurityConfig.fromDict(data);
|
|
1112
|
+
}
|
|
1113
|
+
cloneWithNewFingerprint() {
|
|
1114
|
+
return new _SecurityConfig({
|
|
1115
|
+
fingerprint: new Fingerprint({ metadata: { ...this.fingerprint.metadata } })
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
toDict() {
|
|
1119
|
+
return { fingerprint: this.fingerprint.toDict() };
|
|
1120
|
+
}
|
|
1121
|
+
to_dict() {
|
|
1122
|
+
return this.toDict();
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1125
|
+
function coerceSecurityConfig(value) {
|
|
1126
|
+
if (value instanceof SecurityConfig) {
|
|
1127
|
+
return value;
|
|
1128
|
+
}
|
|
1129
|
+
return new SecurityConfig(value ?? {});
|
|
1130
|
+
}
|
|
1131
|
+
function coerceFingerprint(value) {
|
|
1132
|
+
if (value === void 0 || value === null) {
|
|
1133
|
+
return new Fingerprint();
|
|
1134
|
+
}
|
|
1135
|
+
if (value instanceof Fingerprint) {
|
|
1136
|
+
return value;
|
|
1137
|
+
}
|
|
1138
|
+
if (typeof value === "string") {
|
|
1139
|
+
if (!value.trim()) {
|
|
1140
|
+
throw new Error("Fingerprint seed cannot be empty");
|
|
1141
|
+
}
|
|
1142
|
+
return Fingerprint.generate(value);
|
|
1143
|
+
}
|
|
1144
|
+
return Fingerprint.fromDict(value);
|
|
1145
|
+
}
|
|
1146
|
+
function validateMetadata(metadata) {
|
|
1147
|
+
if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) {
|
|
1148
|
+
throw new Error("Metadata must be a dictionary");
|
|
1149
|
+
}
|
|
1150
|
+
const record = metadata;
|
|
1151
|
+
for (const [key, value] of Object.entries(record)) {
|
|
1152
|
+
if (typeof key !== "string") {
|
|
1153
|
+
throw new Error(`Metadata keys must be strings, got ${typeof key}`);
|
|
1154
|
+
}
|
|
1155
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
1156
|
+
for (const [nestedKey, nestedValue] of Object.entries(value)) {
|
|
1157
|
+
if (typeof nestedKey !== "string") {
|
|
1158
|
+
throw new Error(`Nested metadata keys must be strings, got ${typeof nestedKey}`);
|
|
1159
|
+
}
|
|
1160
|
+
if (nestedValue && typeof nestedValue === "object" && !Array.isArray(nestedValue)) {
|
|
1161
|
+
throw new Error("Metadata can only be nested one level deep");
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
if (JSON.stringify(record).length > 1e4) {
|
|
1167
|
+
throw new Error("Metadata size exceeds maximum allowed (10KB)");
|
|
1168
|
+
}
|
|
1169
|
+
return { ...record };
|
|
1170
|
+
}
|
|
1171
|
+
var _validate_metadata = validateMetadata;
|
|
1172
|
+
function uuidV5(seed, namespace) {
|
|
1173
|
+
const namespaceBytes = uuidToBytes(namespace);
|
|
1174
|
+
const seedBytes = Buffer.from(seed, "utf8");
|
|
1175
|
+
const hash = createHash2("sha1").update(namespaceBytes).update(seedBytes).digest();
|
|
1176
|
+
const bytes = Buffer.from(hash.subarray(0, 16));
|
|
1177
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 80;
|
|
1178
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
1179
|
+
return bytesToUuid(bytes);
|
|
1180
|
+
}
|
|
1181
|
+
function uuidToBytes(uuid) {
|
|
1182
|
+
validateUuid(uuid);
|
|
1183
|
+
return Buffer.from(uuid.replaceAll("-", ""), "hex");
|
|
1184
|
+
}
|
|
1185
|
+
function bytesToUuid(bytes) {
|
|
1186
|
+
const hex = bytes.toString("hex");
|
|
1187
|
+
return [
|
|
1188
|
+
hex.slice(0, 8),
|
|
1189
|
+
hex.slice(8, 12),
|
|
1190
|
+
hex.slice(12, 16),
|
|
1191
|
+
hex.slice(16, 20),
|
|
1192
|
+
hex.slice(20, 32)
|
|
1193
|
+
].join("-");
|
|
1194
|
+
}
|
|
1195
|
+
function validateUuid(uuid) {
|
|
1196
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(uuid)) {
|
|
1197
|
+
throw new Error(`Invalid UUID: ${uuid}`);
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
// src/tools.ts
|
|
1202
|
+
var OPENAI_BIGGER_MODELS = Object.freeze([
|
|
1203
|
+
"gpt-4",
|
|
1204
|
+
"gpt-4o",
|
|
1205
|
+
"gpt-4.1"
|
|
1206
|
+
]);
|
|
1207
|
+
var EnvVar = class {
|
|
1208
|
+
name;
|
|
1209
|
+
description;
|
|
1210
|
+
required;
|
|
1211
|
+
default;
|
|
1212
|
+
constructor(options) {
|
|
1213
|
+
this.name = options.name;
|
|
1214
|
+
this.description = options.description;
|
|
1215
|
+
this.required = options.required ?? true;
|
|
1216
|
+
this.default = options.default ?? null;
|
|
1217
|
+
}
|
|
1218
|
+
};
|
|
1219
|
+
var ToolCalling = class ToolCalling2 {
|
|
1220
|
+
toolName;
|
|
1221
|
+
tool_name;
|
|
1222
|
+
arguments;
|
|
1223
|
+
constructor(options) {
|
|
1224
|
+
const toolName = options.toolName ?? options.tool_name;
|
|
1225
|
+
if (!toolName) {
|
|
1226
|
+
throw new Error("ToolCalling requires a toolName or tool_name.");
|
|
1227
|
+
}
|
|
1228
|
+
this.toolName = toolName;
|
|
1229
|
+
this.tool_name = toolName;
|
|
1230
|
+
this.arguments = options.arguments ?? null;
|
|
1231
|
+
}
|
|
1232
|
+
};
|
|
1233
|
+
var InstructorToolCalling = ToolCalling;
|
|
1234
|
+
var _ArgsSchemaPlaceholder = class {
|
|
1235
|
+
kind = "_ArgsSchemaPlaceholder";
|
|
1236
|
+
};
|
|
1237
|
+
function _default_cache_function(_args = null, _result = null) {
|
|
1238
|
+
void _args;
|
|
1239
|
+
void _result;
|
|
1240
|
+
return true;
|
|
1241
|
+
}
|
|
1242
|
+
function _is_async_callable(func) {
|
|
1243
|
+
return typeof func === "function" && func.constructor.name === "AsyncFunction";
|
|
1244
|
+
}
|
|
1245
|
+
function _is_awaitable(value) {
|
|
1246
|
+
return !!value && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
|
|
1247
|
+
}
|
|
1248
|
+
function _serialize_schema(schema) {
|
|
1249
|
+
return schema ? { ...schema } : null;
|
|
1250
|
+
}
|
|
1251
|
+
function _deserialize_schema(value) {
|
|
1252
|
+
if (value === null || value === void 0) {
|
|
1253
|
+
return null;
|
|
1254
|
+
}
|
|
1255
|
+
if (isToolArgsSchema(value)) {
|
|
1256
|
+
return { ...value };
|
|
1257
|
+
}
|
|
1258
|
+
return null;
|
|
1259
|
+
}
|
|
1260
|
+
var ToolResult = class {
|
|
1261
|
+
result;
|
|
1262
|
+
resultAsAnswer;
|
|
1263
|
+
result_as_answer;
|
|
1264
|
+
constructor(resultOrOptions, resultAsAnswer = false) {
|
|
1265
|
+
if (isToolResultOptions(resultOrOptions)) {
|
|
1266
|
+
this.result = resultOrOptions.result;
|
|
1267
|
+
this.resultAsAnswer = resultOrOptions.resultAsAnswer ?? resultOrOptions.result_as_answer ?? false;
|
|
1268
|
+
} else {
|
|
1269
|
+
this.result = resultOrOptions;
|
|
1270
|
+
this.resultAsAnswer = resultAsAnswer;
|
|
1271
|
+
}
|
|
1272
|
+
this.result_as_answer = this.resultAsAnswer;
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
function build_schema_hint(argsSchema = null) {
|
|
1276
|
+
if (!argsSchema || Object.keys(argsSchema).length === 0) {
|
|
1277
|
+
return "";
|
|
1278
|
+
}
|
|
1279
|
+
const properties = Object.fromEntries(Object.entries(argsSchema).map(([name, spec]) => {
|
|
1280
|
+
const property = Object.fromEntries(Object.entries(spec).filter(([key]) => key !== "required"));
|
|
1281
|
+
return [name, property];
|
|
1282
|
+
}));
|
|
1283
|
+
const required = Object.entries(argsSchema).filter(([, spec]) => spec.required).map(([name]) => name);
|
|
1284
|
+
return `
|
|
1285
|
+
Expected arguments: ${jsonDumpsForHint(properties)}
|
|
1286
|
+
Required: ${jsonDumpsForHint(required)}`;
|
|
1287
|
+
}
|
|
1288
|
+
var ToolUsageLimitExceededError = class extends Error {
|
|
1289
|
+
constructor(message) {
|
|
1290
|
+
super(message);
|
|
1291
|
+
this.name = "ToolUsageLimitExceededError";
|
|
1292
|
+
}
|
|
1293
|
+
};
|
|
1294
|
+
var ToolValidationError = class extends Error {
|
|
1295
|
+
constructor(message) {
|
|
1296
|
+
super(message);
|
|
1297
|
+
this.name = "ToolValidationError";
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
var InMemoryToolCache = class {
|
|
1301
|
+
cache = /* @__PURE__ */ new Map();
|
|
1302
|
+
read(toolName, input) {
|
|
1303
|
+
const key = toolCacheKey(toolName, input);
|
|
1304
|
+
if (!this.cache.has(key)) {
|
|
1305
|
+
return { hit: false };
|
|
1306
|
+
}
|
|
1307
|
+
return { hit: true, value: this.cache.get(key) };
|
|
1308
|
+
}
|
|
1309
|
+
write(toolName, input, output) {
|
|
1310
|
+
this.cache.set(toolCacheKey(toolName, input), output);
|
|
1311
|
+
}
|
|
1312
|
+
clear() {
|
|
1313
|
+
this.cache.clear();
|
|
1314
|
+
}
|
|
1315
|
+
};
|
|
1316
|
+
var CacheHandler = class {
|
|
1317
|
+
cache = /* @__PURE__ */ new Map();
|
|
1318
|
+
add(tool, input, output) {
|
|
1319
|
+
this.cache.set(toolCacheKey(tool, input), output);
|
|
1320
|
+
}
|
|
1321
|
+
read(tool, input) {
|
|
1322
|
+
return this.cache.has(toolCacheKey(tool, input)) ? this.cache.get(toolCacheKey(tool, input)) : null;
|
|
1323
|
+
}
|
|
1324
|
+
clear() {
|
|
1325
|
+
this.cache.clear();
|
|
1326
|
+
}
|
|
1327
|
+
asToolCache() {
|
|
1328
|
+
return {
|
|
1329
|
+
read: (toolName, input) => {
|
|
1330
|
+
const value = this.read(toolName, input);
|
|
1331
|
+
return value === null ? { hit: false } : { hit: true, value };
|
|
1332
|
+
},
|
|
1333
|
+
write: (toolName, input, output) => {
|
|
1334
|
+
this.add(toolName, input, output);
|
|
1335
|
+
},
|
|
1336
|
+
clear: () => {
|
|
1337
|
+
this.clear();
|
|
1338
|
+
}
|
|
1339
|
+
};
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
var ToolsHandler = class {
|
|
1343
|
+
cache;
|
|
1344
|
+
lastUsedTool;
|
|
1345
|
+
last_used_tool;
|
|
1346
|
+
constructor(options = {}) {
|
|
1347
|
+
this.cache = options.cache ?? null;
|
|
1348
|
+
this.lastUsedTool = options.lastUsedTool ?? options.last_used_tool ?? null;
|
|
1349
|
+
this.last_used_tool = this.lastUsedTool;
|
|
1350
|
+
}
|
|
1351
|
+
onToolUse(calling, output, shouldCache = true) {
|
|
1352
|
+
this.lastUsedTool = calling;
|
|
1353
|
+
this.last_used_tool = calling;
|
|
1354
|
+
if (!this.cache || !shouldCache || sanitizedCallingName(calling) === "hit_tool_cache") {
|
|
1355
|
+
return;
|
|
1356
|
+
}
|
|
1357
|
+
this.cache.add(
|
|
1358
|
+
sanitizedCallingName(calling),
|
|
1359
|
+
stringifyToolCallingArguments(calling.arguments),
|
|
1360
|
+
output
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1363
|
+
on_tool_use(calling, output, should_cache = true) {
|
|
1364
|
+
this.onToolUse(calling, output, should_cache);
|
|
1365
|
+
}
|
|
1366
|
+
};
|
|
1367
|
+
var BaseTool = class _BaseTool {
|
|
1368
|
+
name;
|
|
1369
|
+
description;
|
|
1370
|
+
envVars;
|
|
1371
|
+
argsSchema;
|
|
1372
|
+
descriptionUpdated;
|
|
1373
|
+
resultAsAnswer;
|
|
1374
|
+
maxUsageCount;
|
|
1375
|
+
cacheFunction;
|
|
1376
|
+
cache;
|
|
1377
|
+
currentUsageCount = 0;
|
|
1378
|
+
constructor(options) {
|
|
1379
|
+
const maxUsageCount = options.maxUsageCount ?? options.max_usage_count ?? null;
|
|
1380
|
+
_BaseTool.validateMaxUsageCount(maxUsageCount);
|
|
1381
|
+
this.name = sanitizeToolName(options.name);
|
|
1382
|
+
this.description = options.description;
|
|
1383
|
+
this.envVars = options.envVars ?? options.env_vars ?? [];
|
|
1384
|
+
this.argsSchema = options.argsSchema ?? options.args_schema ?? {};
|
|
1385
|
+
this.descriptionUpdated = options.descriptionUpdated ?? options.description_updated ?? false;
|
|
1386
|
+
this.resultAsAnswer = options.resultAsAnswer ?? options.result_as_answer ?? false;
|
|
1387
|
+
this.maxUsageCount = maxUsageCount;
|
|
1388
|
+
this.currentUsageCount = options.currentUsageCount ?? options.current_usage_count ?? 0;
|
|
1389
|
+
this.cacheFunction = options.cacheFunction ?? options.cache_function ?? _default_cache_function;
|
|
1390
|
+
this.cache = options.cache === false ? null : options.cache ?? new InMemoryToolCache();
|
|
1391
|
+
}
|
|
1392
|
+
static validateMaxUsageCount(value) {
|
|
1393
|
+
if (value !== null && value <= 0) {
|
|
1394
|
+
throw new Error("max_usage_count must be a positive integer");
|
|
1395
|
+
}
|
|
1396
|
+
return value;
|
|
1397
|
+
}
|
|
1398
|
+
static validate_max_usage_count(value) {
|
|
1399
|
+
return this.validateMaxUsageCount(value);
|
|
1400
|
+
}
|
|
1401
|
+
static defaultArgsSchema(value) {
|
|
1402
|
+
return _deserialize_schema(value) ?? {};
|
|
1403
|
+
}
|
|
1404
|
+
static _default_args_schema(value) {
|
|
1405
|
+
return this.defaultArgsSchema(value);
|
|
1406
|
+
}
|
|
1407
|
+
static fromLangchain(tool) {
|
|
1408
|
+
if (typeof tool.func !== "function") {
|
|
1409
|
+
throw new Error("The provided tool must have a callable 'func' attribute.");
|
|
1410
|
+
}
|
|
1411
|
+
const func = tool.func;
|
|
1412
|
+
return new StructuredTool({
|
|
1413
|
+
name: tool.name ?? "Unnamed Tool",
|
|
1414
|
+
description: tool.description ?? "",
|
|
1415
|
+
argsSchema: tool.argsSchema ?? tool.args_schema ?? {},
|
|
1416
|
+
func
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
static from_langchain(tool) {
|
|
1420
|
+
return this.fromLangchain(tool);
|
|
1421
|
+
}
|
|
1422
|
+
get toolType() {
|
|
1423
|
+
return this.constructor.name;
|
|
1424
|
+
}
|
|
1425
|
+
get tool_type() {
|
|
1426
|
+
return this.toolType;
|
|
1427
|
+
}
|
|
1428
|
+
modelPostInit(_context) {
|
|
1429
|
+
void _context;
|
|
1430
|
+
}
|
|
1431
|
+
model_post_init(_context) {
|
|
1432
|
+
this.modelPostInit(_context);
|
|
1433
|
+
}
|
|
1434
|
+
setArgsSchema() {
|
|
1435
|
+
return this.argsSchema;
|
|
1436
|
+
}
|
|
1437
|
+
_set_args_schema() {
|
|
1438
|
+
return this.setArgsSchema();
|
|
1439
|
+
}
|
|
1440
|
+
generateDescription() {
|
|
1441
|
+
return this.renderDescription();
|
|
1442
|
+
}
|
|
1443
|
+
_generate_description() {
|
|
1444
|
+
return this.generateDescription();
|
|
1445
|
+
}
|
|
1446
|
+
serializeArgsSchema(schema = this.argsSchema) {
|
|
1447
|
+
return schema === null ? null : { ...schema };
|
|
1448
|
+
}
|
|
1449
|
+
_serialize_args_schema(schema = this.argsSchema) {
|
|
1450
|
+
return this.serializeArgsSchema(schema);
|
|
1451
|
+
}
|
|
1452
|
+
_claim_usage() {
|
|
1453
|
+
return this.claimUsage();
|
|
1454
|
+
}
|
|
1455
|
+
validateKwargs(kwargs) {
|
|
1456
|
+
return validateArgs(this.name, this.argsSchema, kwargs);
|
|
1457
|
+
}
|
|
1458
|
+
_validate_kwargs(kwargs) {
|
|
1459
|
+
return this.validateKwargs(kwargs);
|
|
1460
|
+
}
|
|
1461
|
+
get env_vars() {
|
|
1462
|
+
return this.envVars;
|
|
1463
|
+
}
|
|
1464
|
+
get args_schema() {
|
|
1465
|
+
return this.argsSchema;
|
|
1466
|
+
}
|
|
1467
|
+
get args() {
|
|
1468
|
+
return this.argsSchema;
|
|
1469
|
+
}
|
|
1470
|
+
get description_updated() {
|
|
1471
|
+
return this.descriptionUpdated;
|
|
1472
|
+
}
|
|
1473
|
+
get result_as_answer() {
|
|
1474
|
+
return this.resultAsAnswer;
|
|
1475
|
+
}
|
|
1476
|
+
get max_usage_count() {
|
|
1477
|
+
return this.maxUsageCount;
|
|
1478
|
+
}
|
|
1479
|
+
get current_usage_count() {
|
|
1480
|
+
return this.currentUsageCount;
|
|
1481
|
+
}
|
|
1482
|
+
set current_usage_count(value) {
|
|
1483
|
+
this.currentUsageCount = value;
|
|
1484
|
+
}
|
|
1485
|
+
get cache_function() {
|
|
1486
|
+
return this.cacheFunction;
|
|
1487
|
+
}
|
|
1488
|
+
run(input, hookContext = {}) {
|
|
1489
|
+
let args;
|
|
1490
|
+
try {
|
|
1491
|
+
args = this.parseArgs(input);
|
|
1492
|
+
} catch (error) {
|
|
1493
|
+
crewaiEventBus.emit(this, new ToolValidateInputErrorEvent({
|
|
1494
|
+
toolName: this.name,
|
|
1495
|
+
toolArgs: rawToolArgs(input),
|
|
1496
|
+
toolClass: this.constructor.name,
|
|
1497
|
+
error
|
|
1498
|
+
}));
|
|
1499
|
+
throw error;
|
|
1500
|
+
}
|
|
1501
|
+
if (getBeforeToolCallHooks().length > 0 || getAfterToolCallHooks().length > 0) {
|
|
1502
|
+
return this.runWithHooks(args, hookContext);
|
|
1503
|
+
}
|
|
1504
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
1505
|
+
crewaiEventBus.emit(this, new ToolUsageStartedEvent({
|
|
1506
|
+
toolName: this.name,
|
|
1507
|
+
toolArgs: args,
|
|
1508
|
+
toolClass: this.constructor.name,
|
|
1509
|
+
...toolEventContext(hookContext)
|
|
1510
|
+
}));
|
|
1511
|
+
const cacheInput = stableStringify(args);
|
|
1512
|
+
const cached = this.cache?.read(this.name, cacheInput);
|
|
1513
|
+
if (cached?.hit) {
|
|
1514
|
+
this.emitToolFinished(args, startedAt, cached.value, hookContext);
|
|
1515
|
+
return cached.value;
|
|
1516
|
+
}
|
|
1517
|
+
try {
|
|
1518
|
+
const usageLimitError = this.claimUsage();
|
|
1519
|
+
if (usageLimitError) {
|
|
1520
|
+
this.emitToolFinished(args, startedAt, usageLimitError, hookContext);
|
|
1521
|
+
return usageLimitError;
|
|
1522
|
+
}
|
|
1523
|
+
const result = this._run(args);
|
|
1524
|
+
if (isPromiseLike2(result)) {
|
|
1525
|
+
return result.then((output) => {
|
|
1526
|
+
this.writeCache(args, cacheInput, output);
|
|
1527
|
+
this.emitToolFinished(args, startedAt, output, hookContext);
|
|
1528
|
+
return output;
|
|
1529
|
+
}).catch((error) => {
|
|
1530
|
+
this.emitToolError(args, error, hookContext);
|
|
1531
|
+
throw error;
|
|
1532
|
+
});
|
|
1533
|
+
}
|
|
1534
|
+
this.writeCache(args, cacheInput, result);
|
|
1535
|
+
this.emitToolFinished(args, startedAt, result, hookContext);
|
|
1536
|
+
return result;
|
|
1537
|
+
} catch (error) {
|
|
1538
|
+
this.emitToolError(args, error, hookContext);
|
|
1539
|
+
throw error;
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
async runWithHooks(args, hookContext) {
|
|
1543
|
+
await runBeforeToolCallHooks(new ToolCallHookContext({
|
|
1544
|
+
toolName: this.name,
|
|
1545
|
+
toolInput: args,
|
|
1546
|
+
tool: this,
|
|
1547
|
+
agent: hookContext.agent,
|
|
1548
|
+
task: hookContext.task,
|
|
1549
|
+
crew: hookContext.crew
|
|
1550
|
+
}));
|
|
1551
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
1552
|
+
crewaiEventBus.emit(this, new ToolUsageStartedEvent({
|
|
1553
|
+
toolName: this.name,
|
|
1554
|
+
toolArgs: args,
|
|
1555
|
+
toolClass: this.constructor.name,
|
|
1556
|
+
...toolEventContext(hookContext)
|
|
1557
|
+
}));
|
|
1558
|
+
const cacheInput = stableStringify(args);
|
|
1559
|
+
const cached = this.cache?.read(this.name, cacheInput);
|
|
1560
|
+
if (cached?.hit) {
|
|
1561
|
+
this.emitToolFinished(args, startedAt, cached.value, hookContext);
|
|
1562
|
+
return cached.value;
|
|
1563
|
+
}
|
|
1564
|
+
try {
|
|
1565
|
+
const usageLimitError = this.claimUsage();
|
|
1566
|
+
if (usageLimitError) {
|
|
1567
|
+
this.emitToolFinished(args, startedAt, usageLimitError, hookContext);
|
|
1568
|
+
return usageLimitError;
|
|
1569
|
+
}
|
|
1570
|
+
const rawResult = await this._run(args);
|
|
1571
|
+
const result = await runAfterToolCallHooks(new ToolCallHookContext({
|
|
1572
|
+
toolName: this.name,
|
|
1573
|
+
toolInput: args,
|
|
1574
|
+
tool: this,
|
|
1575
|
+
agent: hookContext.agent,
|
|
1576
|
+
task: hookContext.task,
|
|
1577
|
+
crew: hookContext.crew,
|
|
1578
|
+
toolResult: rawResult
|
|
1579
|
+
}));
|
|
1580
|
+
this.writeCache(args, cacheInput, result);
|
|
1581
|
+
this.emitToolFinished(args, startedAt, result, hookContext);
|
|
1582
|
+
return result;
|
|
1583
|
+
} catch (error) {
|
|
1584
|
+
this.emitToolError(args, error, hookContext);
|
|
1585
|
+
throw error;
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
async arun(input) {
|
|
1589
|
+
let args;
|
|
1590
|
+
try {
|
|
1591
|
+
args = this.parseArgs(input);
|
|
1592
|
+
} catch (error) {
|
|
1593
|
+
crewaiEventBus.emit(this, new ToolValidateInputErrorEvent({
|
|
1594
|
+
toolName: this.name,
|
|
1595
|
+
toolArgs: rawToolArgs(input),
|
|
1596
|
+
toolClass: this.constructor.name,
|
|
1597
|
+
error
|
|
1598
|
+
}));
|
|
1599
|
+
throw error;
|
|
1600
|
+
}
|
|
1601
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
1602
|
+
crewaiEventBus.emit(this, new ToolUsageStartedEvent({
|
|
1603
|
+
toolName: this.name,
|
|
1604
|
+
toolArgs: args,
|
|
1605
|
+
toolClass: this.constructor.name
|
|
1606
|
+
}));
|
|
1607
|
+
const cacheInput = stableStringify(args);
|
|
1608
|
+
const cached = this.cache?.read(this.name, cacheInput);
|
|
1609
|
+
if (cached?.hit) {
|
|
1610
|
+
this.emitToolFinished(args, startedAt, cached.value);
|
|
1611
|
+
return cached.value;
|
|
1612
|
+
}
|
|
1613
|
+
try {
|
|
1614
|
+
const usageLimitError = this.claimUsage();
|
|
1615
|
+
if (usageLimitError) {
|
|
1616
|
+
this.emitToolFinished(args, startedAt, usageLimitError);
|
|
1617
|
+
return usageLimitError;
|
|
1618
|
+
}
|
|
1619
|
+
const result = await this._arun(args);
|
|
1620
|
+
this.writeCache(args, cacheInput, result);
|
|
1621
|
+
this.emitToolFinished(args, startedAt, result);
|
|
1622
|
+
return result;
|
|
1623
|
+
} catch (error) {
|
|
1624
|
+
this.emitToolError(args, error);
|
|
1625
|
+
throw error;
|
|
1626
|
+
}
|
|
1627
|
+
}
|
|
1628
|
+
invoke(input, _config) {
|
|
1629
|
+
void _config;
|
|
1630
|
+
return this.run(input);
|
|
1631
|
+
}
|
|
1632
|
+
async ainvoke(input, _config) {
|
|
1633
|
+
void _config;
|
|
1634
|
+
return await this.arun(input);
|
|
1635
|
+
}
|
|
1636
|
+
hasReachedMaxUsageCount() {
|
|
1637
|
+
return this.maxUsageCount !== null && this.currentUsageCount >= this.maxUsageCount;
|
|
1638
|
+
}
|
|
1639
|
+
has_reached_max_usage_count() {
|
|
1640
|
+
return this.hasReachedMaxUsageCount();
|
|
1641
|
+
}
|
|
1642
|
+
resetUsageCount() {
|
|
1643
|
+
this.currentUsageCount = 0;
|
|
1644
|
+
}
|
|
1645
|
+
reset_usage_count() {
|
|
1646
|
+
this.resetUsageCount();
|
|
1647
|
+
}
|
|
1648
|
+
clearCache() {
|
|
1649
|
+
this.cache?.clear?.();
|
|
1650
|
+
}
|
|
1651
|
+
clear_cache() {
|
|
1652
|
+
this.clearCache();
|
|
1653
|
+
}
|
|
1654
|
+
toStructuredTool() {
|
|
1655
|
+
return this.withCache(this.cache ?? false);
|
|
1656
|
+
}
|
|
1657
|
+
to_structured_tool() {
|
|
1658
|
+
return this.toStructuredTool();
|
|
1659
|
+
}
|
|
1660
|
+
toLangChain() {
|
|
1661
|
+
return this.toStructuredTool();
|
|
1662
|
+
}
|
|
1663
|
+
to_langchain() {
|
|
1664
|
+
return this.toLangChain();
|
|
1665
|
+
}
|
|
1666
|
+
withCache(cache) {
|
|
1667
|
+
return new StructuredTool({
|
|
1668
|
+
name: this.name,
|
|
1669
|
+
description: this.description,
|
|
1670
|
+
argsSchema: this.argsSchema,
|
|
1671
|
+
resultAsAnswer: this.resultAsAnswer,
|
|
1672
|
+
maxUsageCount: this.maxUsageCount,
|
|
1673
|
+
currentUsageCount: this.currentUsageCount,
|
|
1674
|
+
cacheFunction: this.cacheFunction,
|
|
1675
|
+
cache,
|
|
1676
|
+
func: (args) => this._run(args),
|
|
1677
|
+
originalTool: this
|
|
1678
|
+
});
|
|
1679
|
+
}
|
|
1680
|
+
renderDescription() {
|
|
1681
|
+
return [
|
|
1682
|
+
`Tool Name: ${this.name}`,
|
|
1683
|
+
`Tool Arguments: ${JSON.stringify(this.argsSchema)}`,
|
|
1684
|
+
`Tool Description: ${this.description}`
|
|
1685
|
+
].join("\n");
|
|
1686
|
+
}
|
|
1687
|
+
_arun(args) {
|
|
1688
|
+
void args;
|
|
1689
|
+
return Promise.reject(new Error(`${this.constructor.name} does not implement _arun. Override _arun for async support or use run() for sync execution.`));
|
|
1690
|
+
}
|
|
1691
|
+
parseArgs(input) {
|
|
1692
|
+
const raw = normalizeToolInput(input);
|
|
1693
|
+
return validateArgs(this.name, this.argsSchema, raw);
|
|
1694
|
+
}
|
|
1695
|
+
claimUsage() {
|
|
1696
|
+
if (this.maxUsageCount !== null && this.currentUsageCount >= this.maxUsageCount) {
|
|
1697
|
+
return `Tool '${this.name}' has reached its usage limit of ${String(this.maxUsageCount)} times and cannot be used anymore.`;
|
|
1698
|
+
}
|
|
1699
|
+
this.currentUsageCount += 1;
|
|
1700
|
+
this.onUsageClaimed();
|
|
1701
|
+
return null;
|
|
1702
|
+
}
|
|
1703
|
+
onUsageClaimed() {
|
|
1704
|
+
}
|
|
1705
|
+
writeCache(args, cacheInput, output) {
|
|
1706
|
+
if (this.cache && this.cacheFunction(args, output)) {
|
|
1707
|
+
this.cache.write(this.name, cacheInput, output);
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
emitToolFinished(args, startedAt, output, hookContext = {}) {
|
|
1711
|
+
crewaiEventBus.emit(this, new ToolUsageFinishedEvent({
|
|
1712
|
+
toolName: this.name,
|
|
1713
|
+
toolArgs: args,
|
|
1714
|
+
toolClass: this.constructor.name,
|
|
1715
|
+
startedAt,
|
|
1716
|
+
output,
|
|
1717
|
+
...toolEventContext(hookContext)
|
|
1718
|
+
}));
|
|
1719
|
+
}
|
|
1720
|
+
emitToolError(args, error, hookContext = {}) {
|
|
1721
|
+
crewaiEventBus.emit(this, new ToolUsageErrorEvent({
|
|
1722
|
+
toolName: this.name,
|
|
1723
|
+
toolArgs: args,
|
|
1724
|
+
toolClass: this.constructor.name,
|
|
1725
|
+
error,
|
|
1726
|
+
...toolEventContext(hookContext)
|
|
1727
|
+
}));
|
|
1728
|
+
}
|
|
1729
|
+
};
|
|
1730
|
+
function toolEventContext(hookContext) {
|
|
1731
|
+
const context = {};
|
|
1732
|
+
if (hookContext.task !== void 0) {
|
|
1733
|
+
context.from_task = hookContext.task;
|
|
1734
|
+
}
|
|
1735
|
+
if (hookContext.agent !== void 0) {
|
|
1736
|
+
context.from_agent = hookContext.agent;
|
|
1737
|
+
const agentRecord = hookContext.agent && typeof hookContext.agent === "object" ? hookContext.agent : {};
|
|
1738
|
+
if (typeof agentRecord.key === "string") {
|
|
1739
|
+
context.agent_key = agentRecord.key;
|
|
1740
|
+
}
|
|
1741
|
+
if (typeof agentRecord.role === "string") {
|
|
1742
|
+
context.agent_role = agentRecord.role;
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
return context;
|
|
1746
|
+
}
|
|
1747
|
+
function to_langchain(toolOrTools) {
|
|
1748
|
+
if (Array.isArray(toolOrTools)) {
|
|
1749
|
+
return toolOrTools.map((tool) => tool instanceof StructuredTool ? tool : tool.toStructuredTool());
|
|
1750
|
+
}
|
|
1751
|
+
return toolOrTools.toStructuredTool();
|
|
1752
|
+
}
|
|
1753
|
+
var StructuredTool = class extends BaseTool {
|
|
1754
|
+
func;
|
|
1755
|
+
originalTool;
|
|
1756
|
+
constructor(options) {
|
|
1757
|
+
super(options);
|
|
1758
|
+
this.func = options.func;
|
|
1759
|
+
this.originalTool = options.originalTool ?? options.original_tool ?? null;
|
|
1760
|
+
}
|
|
1761
|
+
static fromFunction(func, optionsOrName = {}, description, returnDirect = false, argsSchema, inferSchema = true) {
|
|
1762
|
+
const options = normalizeFromFunctionOptions(optionsOrName, description, returnDirect, argsSchema, inferSchema);
|
|
1763
|
+
const shouldInferSchema = options.inferSchema ?? options.infer_schema ?? true;
|
|
1764
|
+
if (!shouldInferSchema && !(options.argsSchema ?? options.args_schema)) {
|
|
1765
|
+
throw new Error("Either argsSchema must be provided or inferSchema must be true.");
|
|
1766
|
+
}
|
|
1767
|
+
return createToolFromFunction(func, {
|
|
1768
|
+
...options,
|
|
1769
|
+
resultAsAnswer: options.returnDirect ?? options.return_direct ?? false
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
static from_function(func, optionsOrName = {}, description, returnDirect = false, argsSchema, inferSchema = true) {
|
|
1773
|
+
const options = normalizeFromFunctionOptions(optionsOrName, description, returnDirect, argsSchema, inferSchema);
|
|
1774
|
+
const shouldInferSchema = options.inferSchema ?? options.infer_schema ?? true;
|
|
1775
|
+
if (!shouldInferSchema && !(options.argsSchema ?? options.args_schema)) {
|
|
1776
|
+
throw new Error("Either argsSchema must be provided or inferSchema must be true.");
|
|
1777
|
+
}
|
|
1778
|
+
return createToolFromFunction(func, {
|
|
1779
|
+
...options,
|
|
1780
|
+
resultAsAnswer: options.returnDirect ?? options.return_direct ?? false
|
|
1781
|
+
});
|
|
1782
|
+
}
|
|
1783
|
+
_run(args) {
|
|
1784
|
+
return this.callStructuredFunction(args);
|
|
1785
|
+
}
|
|
1786
|
+
parseArgs(input) {
|
|
1787
|
+
const rawArgs = normalizeStructuredToolInput(input, this.argsSchema, false);
|
|
1788
|
+
return validateArgs(this.name, this.argsSchema, rawArgs);
|
|
1789
|
+
}
|
|
1790
|
+
invoke(input, _config) {
|
|
1791
|
+
void _config;
|
|
1792
|
+
const parsedArgs = this._parseArgs(input);
|
|
1793
|
+
if (this.hasReachedMaxUsageCount()) {
|
|
1794
|
+
throw new ToolUsageLimitExceededError(
|
|
1795
|
+
`Tool '${sanitizeToolName(this.name)}' has reached its maximum usage limit of ${String(this.maxUsageCount)}. You should not use the ${sanitizeToolName(this.name)} tool again.`
|
|
1796
|
+
);
|
|
1797
|
+
}
|
|
1798
|
+
this._incrementUsageCount();
|
|
1799
|
+
return this.callStructuredFunction(parsedArgs);
|
|
1800
|
+
}
|
|
1801
|
+
async ainvoke(input, _config) {
|
|
1802
|
+
void _config;
|
|
1803
|
+
const parsedArgs = this._parseArgs(input);
|
|
1804
|
+
if (this.hasReachedMaxUsageCount()) {
|
|
1805
|
+
throw new ToolUsageLimitExceededError(
|
|
1806
|
+
`Tool '${sanitizeToolName(this.name)}' has reached its maximum usage limit of ${String(this.maxUsageCount)}. You should not use the ${sanitizeToolName(this.name)} tool again.`
|
|
1807
|
+
);
|
|
1808
|
+
}
|
|
1809
|
+
this._incrementUsageCount();
|
|
1810
|
+
return await this.callStructuredFunction(parsedArgs);
|
|
1811
|
+
}
|
|
1812
|
+
async arun(input) {
|
|
1813
|
+
return await this.run(input);
|
|
1814
|
+
}
|
|
1815
|
+
_validate_func() {
|
|
1816
|
+
this._validate_function_signature();
|
|
1817
|
+
return this;
|
|
1818
|
+
}
|
|
1819
|
+
static _create_schema_from_function(name, func) {
|
|
1820
|
+
void name;
|
|
1821
|
+
const parameterNames = inferFunctionParameterNames(func);
|
|
1822
|
+
return Object.fromEntries(parameterNames.map((parameterName) => [
|
|
1823
|
+
parameterName,
|
|
1824
|
+
{ type: "unknown", required: true }
|
|
1825
|
+
]));
|
|
1826
|
+
}
|
|
1827
|
+
_validate_function_signature() {
|
|
1828
|
+
const parameterNames = inferFunctionParameterNames(this.func);
|
|
1829
|
+
if (parameterNames.length === 1 && parameterNames[0] === "args" && !this.argsSchema.args) {
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
for (const parameterName of parameterNames) {
|
|
1833
|
+
const spec = this.argsSchema[parameterName];
|
|
1834
|
+
if (!spec) {
|
|
1835
|
+
throw new Error(`Required function parameter '${parameterName}' not found in args_schema`);
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
_parseArgs(input) {
|
|
1840
|
+
const rawArgs = normalizeStructuredToolInput(input, this.argsSchema, true);
|
|
1841
|
+
try {
|
|
1842
|
+
return validateArgs(this.name, this.argsSchema, rawArgs);
|
|
1843
|
+
} catch (error) {
|
|
1844
|
+
throw new Error(`Arguments validation failed: ${error instanceof Error ? error.message : String(error)}${build_schema_hint(this.argsSchema)}`, {
|
|
1845
|
+
cause: error
|
|
1846
|
+
});
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
_parse_args(input) {
|
|
1850
|
+
return this._parseArgs(input);
|
|
1851
|
+
}
|
|
1852
|
+
_incrementUsageCount() {
|
|
1853
|
+
this.currentUsageCount += 1;
|
|
1854
|
+
this.onUsageClaimed();
|
|
1855
|
+
}
|
|
1856
|
+
_increment_usage_count() {
|
|
1857
|
+
this._incrementUsageCount();
|
|
1858
|
+
}
|
|
1859
|
+
callStructuredFunction(parsedArgs) {
|
|
1860
|
+
const parameterNames = inferFunctionParameterNames(this.func);
|
|
1861
|
+
if (parameterNames.length <= 1) {
|
|
1862
|
+
return this.func(parsedArgs);
|
|
1863
|
+
}
|
|
1864
|
+
const orderedNames = Object.keys(this.argsSchema).length > 0 ? Object.keys(this.argsSchema) : parameterNames;
|
|
1865
|
+
const positional = orderedNames.map((parameterName) => parsedArgs[parameterName]);
|
|
1866
|
+
return this.func(...positional);
|
|
1867
|
+
}
|
|
1868
|
+
__repr__() {
|
|
1869
|
+
return `CrewStructuredTool(name='${sanitizeToolName(this.name)}', description='${this.description}')`;
|
|
1870
|
+
}
|
|
1871
|
+
toString() {
|
|
1872
|
+
return this.__repr__();
|
|
1873
|
+
}
|
|
1874
|
+
onUsageClaimed() {
|
|
1875
|
+
if (this.originalTool) {
|
|
1876
|
+
this.originalTool.current_usage_count = this.currentUsageCount;
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
};
|
|
1880
|
+
var CrewStructuredTool = StructuredTool;
|
|
1881
|
+
var AddImageToolSchema = {
|
|
1882
|
+
image_url: { type: "string", required: true, description: "The URL or path of the image to add" },
|
|
1883
|
+
action: { type: "string", required: false, description: "Optional context or question about the image" }
|
|
1884
|
+
};
|
|
1885
|
+
var AddImageTool = class extends BaseTool {
|
|
1886
|
+
constructor(options = {}) {
|
|
1887
|
+
const addImage = I18N_DEFAULT.tools("add_image");
|
|
1888
|
+
super({
|
|
1889
|
+
name: options.name ?? addImage.name,
|
|
1890
|
+
description: options.description ?? addImage.description,
|
|
1891
|
+
argsSchema: options.argsSchema ?? options.args_schema ?? AddImageToolSchema,
|
|
1892
|
+
...baseToolPassthroughOptions(options)
|
|
1893
|
+
});
|
|
1894
|
+
}
|
|
1895
|
+
_run(args) {
|
|
1896
|
+
const addImage = I18N_DEFAULT.tools("add_image");
|
|
1897
|
+
const action = typeof args.action === "string" && args.action.trim() ? args.action : addImage.default_action;
|
|
1898
|
+
return {
|
|
1899
|
+
role: "user",
|
|
1900
|
+
content: [
|
|
1901
|
+
{ type: "text", text: action },
|
|
1902
|
+
{ type: "image_url", image_url: { url: toToolString(args.image_url) } }
|
|
1903
|
+
]
|
|
1904
|
+
};
|
|
1905
|
+
}
|
|
1906
|
+
};
|
|
1907
|
+
var ReadFileToolSchema = {
|
|
1908
|
+
file_name: { type: "string", required: true, description: "The name of the input file to read" }
|
|
1909
|
+
};
|
|
1910
|
+
var ReadFileTool = class extends BaseTool {
|
|
1911
|
+
files = null;
|
|
1912
|
+
constructor(options = {}) {
|
|
1913
|
+
super({
|
|
1914
|
+
name: options.name ?? "read_file",
|
|
1915
|
+
description: options.description ?? "Read content from an input file by name. Returns file content as text for text files, or base64 for binary files.",
|
|
1916
|
+
argsSchema: options.argsSchema ?? options.args_schema ?? ReadFileToolSchema,
|
|
1917
|
+
cache: options.cache ?? false,
|
|
1918
|
+
...baseToolPassthroughOptions(options)
|
|
1919
|
+
});
|
|
1920
|
+
this.files = options.files ?? null;
|
|
1921
|
+
}
|
|
1922
|
+
setFiles(files) {
|
|
1923
|
+
this.files = files;
|
|
1924
|
+
}
|
|
1925
|
+
set_files(files) {
|
|
1926
|
+
this.setFiles(files);
|
|
1927
|
+
}
|
|
1928
|
+
_run(args) {
|
|
1929
|
+
if (!this.files) {
|
|
1930
|
+
return "No input files available.";
|
|
1931
|
+
}
|
|
1932
|
+
const fileName = toToolString(args.file_name ?? args.fileName);
|
|
1933
|
+
const file = this.files[fileName];
|
|
1934
|
+
if (!file) {
|
|
1935
|
+
return `File '${fileName}' not found. Available files: ${Object.keys(this.files).join(", ")}`;
|
|
1936
|
+
}
|
|
1937
|
+
const content = file.read();
|
|
1938
|
+
const contentType = file.content_type ?? file.contentType ?? "application/octet-stream";
|
|
1939
|
+
if (contentType === "application/pdf") {
|
|
1940
|
+
const bytes = typeof content === "string" ? Buffer.from(content) : Buffer.from(content);
|
|
1941
|
+
return readPDFFileText(bytes, file.filename ?? fileName);
|
|
1942
|
+
}
|
|
1943
|
+
if (contentType.startsWith("text/") || ["application/json", "application/xml", "application/x-yaml"].includes(contentType)) {
|
|
1944
|
+
return typeof content === "string" ? content : Buffer.from(content).toString("utf8");
|
|
1945
|
+
}
|
|
1946
|
+
const encoded = typeof content === "string" ? Buffer.from(content).toString("base64") : Buffer.from(content).toString("base64");
|
|
1947
|
+
return `[Binary file: ${file.filename ?? fileName} (${contentType})]
|
|
1948
|
+
Base64: ${encoded}`;
|
|
1949
|
+
}
|
|
1950
|
+
};
|
|
1951
|
+
async function readPDFFileText(content, filename) {
|
|
1952
|
+
try {
|
|
1953
|
+
const module = await import("pdf-parse");
|
|
1954
|
+
const PDFParse = module.PDFParse;
|
|
1955
|
+
const parser = new PDFParse({ data: content });
|
|
1956
|
+
try {
|
|
1957
|
+
const result = await parser.getText();
|
|
1958
|
+
const text = result.text?.trim() ?? "";
|
|
1959
|
+
return text.length > 0 ? text : `[PDF file with no extractable text: ${filename}]`;
|
|
1960
|
+
} finally {
|
|
1961
|
+
await parser.destroy?.();
|
|
1962
|
+
}
|
|
1963
|
+
} catch (error) {
|
|
1964
|
+
if (error instanceof Error && error.message.includes("Cannot find package")) {
|
|
1965
|
+
const encoded = content.toString("base64");
|
|
1966
|
+
return `[Binary file: ${filename} (application/pdf)]
|
|
1967
|
+
Base64: ${encoded}`;
|
|
1968
|
+
}
|
|
1969
|
+
return `Unable to extract text from PDF '${filename}': ${error instanceof Error ? error.message : String(error)}`;
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
var BaseAgentTool = class _BaseAgentTool extends BaseTool {
|
|
1973
|
+
agents;
|
|
1974
|
+
constructor(options = {}) {
|
|
1975
|
+
super({
|
|
1976
|
+
name: options.name ?? "agent_tool",
|
|
1977
|
+
description: options.description ?? "Agent tool",
|
|
1978
|
+
argsSchema: options.argsSchema ?? options.args_schema ?? {},
|
|
1979
|
+
...baseToolPassthroughOptions(options)
|
|
1980
|
+
});
|
|
1981
|
+
this.agents = options.agents ?? [];
|
|
1982
|
+
}
|
|
1983
|
+
sanitizeAgentName(name) {
|
|
1984
|
+
return name ? name.trim().split(/\s+/).join(" ").replaceAll('"', "").toLocaleLowerCase() : "";
|
|
1985
|
+
}
|
|
1986
|
+
sanitize_agent_name(name) {
|
|
1987
|
+
return this.sanitizeAgentName(name);
|
|
1988
|
+
}
|
|
1989
|
+
static _getCoworker(coworker, args = {}) {
|
|
1990
|
+
const raw = coworker ?? args.co_worker ?? args.coworker;
|
|
1991
|
+
if (typeof raw !== "string") {
|
|
1992
|
+
return null;
|
|
1993
|
+
}
|
|
1994
|
+
if (raw.startsWith("[") && raw.endsWith("]")) {
|
|
1995
|
+
return raw.slice(1, -1).split(",")[0]?.trim() ?? "";
|
|
1996
|
+
}
|
|
1997
|
+
return raw;
|
|
1998
|
+
}
|
|
1999
|
+
static _get_coworker(coworker, args = {}) {
|
|
2000
|
+
return this._getCoworker(coworker, args);
|
|
2001
|
+
}
|
|
2002
|
+
_getCoworker(coworker, args = {}) {
|
|
2003
|
+
return _BaseAgentTool._getCoworker(coworker, args);
|
|
2004
|
+
}
|
|
2005
|
+
_get_coworker(coworker, args = {}) {
|
|
2006
|
+
return this._getCoworker(coworker, args);
|
|
2007
|
+
}
|
|
2008
|
+
_execute(agentName, task, context = null) {
|
|
2009
|
+
const sanitizedName = this.sanitizeAgentName(agentName ?? "");
|
|
2010
|
+
const selectedAgent = this.agents.find((agent) => this.sanitizeAgentName(agent.role) === sanitizedName);
|
|
2011
|
+
if (!selectedAgent) {
|
|
2012
|
+
return I18N_DEFAULT.errors("agent_tool_unexisting_coworker").replace("{coworkers}", this.formatCoworkers());
|
|
2013
|
+
}
|
|
2014
|
+
const execute = selectedAgent.executeTask ?? selectedAgent.execute_task;
|
|
2015
|
+
if (!execute) {
|
|
2016
|
+
return I18N_DEFAULT.errors("agent_tool_execution_error").replace("{agent_role}", this.sanitizeAgentName(selectedAgent.role)).replace("{error}", "Selected agent does not expose executeTask.");
|
|
2017
|
+
}
|
|
2018
|
+
try {
|
|
2019
|
+
const result = execute.call(selectedAgent, { description: task, expected_output: I18N_DEFAULT.slice("manager_request"), agent: selectedAgent }, context);
|
|
2020
|
+
return isPromiseLike2(result) ? result.then(stringifyToolOutput) : stringifyToolOutput(result);
|
|
2021
|
+
} catch (error) {
|
|
2022
|
+
return I18N_DEFAULT.errors("agent_tool_execution_error").replace("{agent_role}", this.sanitizeAgentName(selectedAgent.role)).replace("{error}", error instanceof Error ? error.message : stringifyToolOutput(error));
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
_run(args) {
|
|
2026
|
+
void args;
|
|
2027
|
+
throw new Error("BaseAgentTool must be subclassed.");
|
|
2028
|
+
}
|
|
2029
|
+
formatCoworkers() {
|
|
2030
|
+
return this.agents.map((agent) => `- ${this.sanitizeAgentName(agent.role)}`).join("\n");
|
|
2031
|
+
}
|
|
2032
|
+
};
|
|
2033
|
+
var AskQuestionToolSchema = {
|
|
2034
|
+
question: { type: "string", required: true, description: "The question to ask" },
|
|
2035
|
+
context: { type: "string", required: true, description: "The context for the question" },
|
|
2036
|
+
coworker: { type: "string", required: true, description: "The role/name of the coworker to ask" }
|
|
2037
|
+
};
|
|
2038
|
+
var AskQuestionTool = class extends BaseAgentTool {
|
|
2039
|
+
constructor(options = {}) {
|
|
2040
|
+
super({
|
|
2041
|
+
...options,
|
|
2042
|
+
name: options.name ?? "Ask question to coworker",
|
|
2043
|
+
description: options.description ?? "Ask question to coworker",
|
|
2044
|
+
argsSchema: options.argsSchema ?? options.args_schema ?? AskQuestionToolSchema
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
_run(args) {
|
|
2048
|
+
return this._execute(
|
|
2049
|
+
this._getCoworker(args.coworker, args),
|
|
2050
|
+
toToolString(args.question),
|
|
2051
|
+
typeof args.context === "string" ? args.context : null
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
};
|
|
2055
|
+
var DelegateWorkToolSchema = {
|
|
2056
|
+
task: { type: "string", required: true, description: "The task to delegate" },
|
|
2057
|
+
context: { type: "string", required: true, description: "The context for the task" },
|
|
2058
|
+
coworker: { type: "string", required: true, description: "The role/name of the coworker to delegate to" }
|
|
2059
|
+
};
|
|
2060
|
+
var DelegateWorkTool = class extends BaseAgentTool {
|
|
2061
|
+
constructor(options = {}) {
|
|
2062
|
+
super({
|
|
2063
|
+
...options,
|
|
2064
|
+
name: options.name ?? "Delegate work to coworker",
|
|
2065
|
+
description: options.description ?? "Delegate work to coworker",
|
|
2066
|
+
argsSchema: options.argsSchema ?? options.args_schema ?? DelegateWorkToolSchema
|
|
2067
|
+
});
|
|
2068
|
+
}
|
|
2069
|
+
_run(args) {
|
|
2070
|
+
return this._execute(
|
|
2071
|
+
this._getCoworker(args.coworker, args),
|
|
2072
|
+
toToolString(args.task),
|
|
2073
|
+
typeof args.context === "string" ? args.context : null
|
|
2074
|
+
);
|
|
2075
|
+
}
|
|
2076
|
+
};
|
|
2077
|
+
var AgentTools = class {
|
|
2078
|
+
agents;
|
|
2079
|
+
constructor(agentsOrOptions) {
|
|
2080
|
+
this.agents = "agents" in agentsOrOptions ? agentsOrOptions.agents : agentsOrOptions;
|
|
2081
|
+
}
|
|
2082
|
+
tools() {
|
|
2083
|
+
const coworkers = this.agents.map((agent) => agent.role).join(", ");
|
|
2084
|
+
return [
|
|
2085
|
+
new DelegateWorkTool({
|
|
2086
|
+
agents: this.agents,
|
|
2087
|
+
description: promptLeafToString(I18N_DEFAULT.tools("delegate_work")).replace("{coworkers}", coworkers)
|
|
2088
|
+
}),
|
|
2089
|
+
new AskQuestionTool({
|
|
2090
|
+
agents: this.agents,
|
|
2091
|
+
description: promptLeafToString(I18N_DEFAULT.tools("ask_question")).replace("{coworkers}", coworkers)
|
|
2092
|
+
})
|
|
2093
|
+
];
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
var CacheTools = class {
|
|
2097
|
+
cacheHandler;
|
|
2098
|
+
cache_handler;
|
|
2099
|
+
constructor(cacheHandler = new CacheHandler()) {
|
|
2100
|
+
this.cacheHandler = cacheHandler;
|
|
2101
|
+
this.cache_handler = cacheHandler;
|
|
2102
|
+
}
|
|
2103
|
+
tool() {
|
|
2104
|
+
return new StructuredTool({
|
|
2105
|
+
name: "Hit Tool Cache",
|
|
2106
|
+
description: "Read cached output for a previous tool call.",
|
|
2107
|
+
argsSchema: {
|
|
2108
|
+
key: { type: "string", required: true }
|
|
2109
|
+
},
|
|
2110
|
+
func: ({ key }) => this.hitCache(String(key)) ?? ""
|
|
2111
|
+
});
|
|
2112
|
+
}
|
|
2113
|
+
hitCache(key) {
|
|
2114
|
+
const match = key.match(/tool:\s*(.*?)\s*\|\s*input:\s*(.*)$/s);
|
|
2115
|
+
if (!match) {
|
|
2116
|
+
return null;
|
|
2117
|
+
}
|
|
2118
|
+
const [, toolPart = "", inputPart = ""] = match;
|
|
2119
|
+
return this.cacheHandler.read(toolPart.trim(), inputPart.trim());
|
|
2120
|
+
}
|
|
2121
|
+
hit_cache(key) {
|
|
2122
|
+
return this.hitCache(key);
|
|
2123
|
+
}
|
|
2124
|
+
};
|
|
2125
|
+
var MCPNativeTool = class extends BaseTool {
|
|
2126
|
+
clientFactory;
|
|
2127
|
+
originalToolNameValue;
|
|
2128
|
+
serverNameValue;
|
|
2129
|
+
constructor(optionsOrClientFactory, toolName, toolSchema = {}, serverName, originalToolName = null) {
|
|
2130
|
+
const options = typeof optionsOrClientFactory === "function" ? {
|
|
2131
|
+
clientFactory: optionsOrClientFactory,
|
|
2132
|
+
...toolName === void 0 ? {} : { toolName },
|
|
2133
|
+
toolSchema,
|
|
2134
|
+
...serverName === void 0 ? {} : { serverName },
|
|
2135
|
+
originalToolName
|
|
2136
|
+
} : optionsOrClientFactory;
|
|
2137
|
+
const resolvedToolName = options.toolName ?? options.tool_name;
|
|
2138
|
+
const resolvedServerName = options.serverName ?? options.server_name;
|
|
2139
|
+
const resolvedClientFactory = options.clientFactory ?? options.client_factory;
|
|
2140
|
+
if (!resolvedToolName || !resolvedServerName || !resolvedClientFactory) {
|
|
2141
|
+
throw new Error("MCPNativeTool requires clientFactory, toolName, and serverName.");
|
|
2142
|
+
}
|
|
2143
|
+
const schema = options.toolSchema ?? options.tool_schema ?? {};
|
|
2144
|
+
super({
|
|
2145
|
+
name: `${resolvedServerName}_${resolvedToolName}`,
|
|
2146
|
+
description: toolSchemaDescription(schema, resolvedToolName, resolvedServerName),
|
|
2147
|
+
argsSchema: toolSchemaArgs(schema)
|
|
2148
|
+
});
|
|
2149
|
+
this.clientFactory = resolvedClientFactory;
|
|
2150
|
+
this.originalToolNameValue = options.originalToolName ?? options.original_tool_name ?? resolvedToolName;
|
|
2151
|
+
this.serverNameValue = resolvedServerName;
|
|
2152
|
+
}
|
|
2153
|
+
get originalToolName() {
|
|
2154
|
+
return this.originalToolNameValue;
|
|
2155
|
+
}
|
|
2156
|
+
get original_tool_name() {
|
|
2157
|
+
return this.originalToolName;
|
|
2158
|
+
}
|
|
2159
|
+
get serverName() {
|
|
2160
|
+
return this.serverNameValue;
|
|
2161
|
+
}
|
|
2162
|
+
get server_name() {
|
|
2163
|
+
return this.serverName;
|
|
2164
|
+
}
|
|
2165
|
+
_run(args) {
|
|
2166
|
+
return this.runAsync(args);
|
|
2167
|
+
}
|
|
2168
|
+
async _arun(args) {
|
|
2169
|
+
return await this.runAsync(args);
|
|
2170
|
+
}
|
|
2171
|
+
async runAsync(args = {}) {
|
|
2172
|
+
const client = this.clientFactory();
|
|
2173
|
+
if (!isMCPClientLike(client)) {
|
|
2174
|
+
throw new Error("MCPNativeTool clientFactory must return an MCPClient-like object.");
|
|
2175
|
+
}
|
|
2176
|
+
await client.connect();
|
|
2177
|
+
try {
|
|
2178
|
+
return stringifyToolOutput(await client.callTool(this.originalToolName, args));
|
|
2179
|
+
} finally {
|
|
2180
|
+
await client.disconnect();
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
async _run_async(args = {}) {
|
|
2184
|
+
return await this.runAsync(args);
|
|
2185
|
+
}
|
|
2186
|
+
};
|
|
2187
|
+
var MCP_WRAPPER_MAX_RETRIES = 3;
|
|
2188
|
+
var MCP_TOOL_EXECUTION_TIMEOUT_SECONDS = 60;
|
|
2189
|
+
var MCPToolWrapper = class extends BaseTool {
|
|
2190
|
+
mcpServerParamsValue;
|
|
2191
|
+
originalToolNameValue;
|
|
2192
|
+
serverNameValue;
|
|
2193
|
+
constructor(optionsOrServerParams, toolName, toolSchema = {}, serverName) {
|
|
2194
|
+
const options = isMCPToolWrapperOptions(optionsOrServerParams) ? optionsOrServerParams : {
|
|
2195
|
+
mcpServerParams: optionsOrServerParams,
|
|
2196
|
+
...toolName === void 0 ? {} : { toolName },
|
|
2197
|
+
toolSchema,
|
|
2198
|
+
...serverName === void 0 ? {} : { serverName }
|
|
2199
|
+
};
|
|
2200
|
+
const params = options.mcpServerParams ?? options.mcp_server_params;
|
|
2201
|
+
const resolvedToolName = options.toolName ?? options.tool_name;
|
|
2202
|
+
const resolvedServerName = options.serverName ?? options.server_name;
|
|
2203
|
+
if (!params || !resolvedToolName || !resolvedServerName) {
|
|
2204
|
+
throw new Error("MCPToolWrapper requires mcpServerParams, toolName, and serverName.");
|
|
2205
|
+
}
|
|
2206
|
+
const schema = options.toolSchema ?? options.tool_schema ?? {};
|
|
2207
|
+
super({
|
|
2208
|
+
name: `${resolvedServerName}_${resolvedToolName}`,
|
|
2209
|
+
description: toolSchemaDescription(schema, resolvedToolName, resolvedServerName),
|
|
2210
|
+
argsSchema: toolSchemaArgs(schema)
|
|
2211
|
+
});
|
|
2212
|
+
this.mcpServerParamsValue = { ...params };
|
|
2213
|
+
this.originalToolNameValue = resolvedToolName;
|
|
2214
|
+
this.serverNameValue = resolvedServerName;
|
|
2215
|
+
}
|
|
2216
|
+
get mcpServerParams() {
|
|
2217
|
+
return { ...this.mcpServerParamsValue };
|
|
2218
|
+
}
|
|
2219
|
+
get mcp_server_params() {
|
|
2220
|
+
return this.mcpServerParams;
|
|
2221
|
+
}
|
|
2222
|
+
get originalToolName() {
|
|
2223
|
+
return this.originalToolNameValue;
|
|
2224
|
+
}
|
|
2225
|
+
get original_tool_name() {
|
|
2226
|
+
return this.originalToolName;
|
|
2227
|
+
}
|
|
2228
|
+
get serverName() {
|
|
2229
|
+
return this.serverNameValue;
|
|
2230
|
+
}
|
|
2231
|
+
get server_name() {
|
|
2232
|
+
return this.serverName;
|
|
2233
|
+
}
|
|
2234
|
+
_run(args) {
|
|
2235
|
+
return this._run_async(args);
|
|
2236
|
+
}
|
|
2237
|
+
async _arun(args) {
|
|
2238
|
+
return await this._run_async(args);
|
|
2239
|
+
}
|
|
2240
|
+
async runAsync(args = {}) {
|
|
2241
|
+
return await this._execute_tool(args);
|
|
2242
|
+
}
|
|
2243
|
+
async _run_async(args = {}) {
|
|
2244
|
+
return await this._retry_with_exponential_backoff(this._execute_tool_with_timeout.bind(this), args);
|
|
2245
|
+
}
|
|
2246
|
+
async _retry_with_exponential_backoff(operationFunc, args = {}) {
|
|
2247
|
+
let lastError = "";
|
|
2248
|
+
for (let attempt = 0; attempt < MCP_WRAPPER_MAX_RETRIES; attempt += 1) {
|
|
2249
|
+
const [result, error, shouldRetry] = await this._execute_single_attempt(operationFunc, args);
|
|
2250
|
+
if (result !== null) {
|
|
2251
|
+
return result;
|
|
2252
|
+
}
|
|
2253
|
+
if (!shouldRetry) {
|
|
2254
|
+
return error;
|
|
2255
|
+
}
|
|
2256
|
+
lastError = error;
|
|
2257
|
+
if (attempt < MCP_WRAPPER_MAX_RETRIES - 1) {
|
|
2258
|
+
await waitForMCPWrapperRetry(2 ** attempt);
|
|
2259
|
+
}
|
|
2260
|
+
}
|
|
2261
|
+
return `MCP tool execution failed after ${String(MCP_WRAPPER_MAX_RETRIES)} attempts: ${lastError}`;
|
|
2262
|
+
}
|
|
2263
|
+
async _execute_single_attempt(operationFunc, args = {}) {
|
|
2264
|
+
try {
|
|
2265
|
+
return [await operationFunc(args), "", false];
|
|
2266
|
+
} catch (error) {
|
|
2267
|
+
const classified = classifyMCPWrapperError(error, this.originalToolName);
|
|
2268
|
+
return [null, classified.message, classified.retryable];
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
async _execute_tool_with_timeout(args = {}) {
|
|
2272
|
+
return await withMCPWrapperTimeout(this._execute_tool(args));
|
|
2273
|
+
}
|
|
2274
|
+
async _execute_tool(args = {}) {
|
|
2275
|
+
return await this._do_mcp_call(args);
|
|
2276
|
+
}
|
|
2277
|
+
async _do_mcp_call(args = {}) {
|
|
2278
|
+
const { MCPClient: MCPClient2, HTTPTransport: HTTPTransport2 } = await import("./mcp-DS7UMYAM.js");
|
|
2279
|
+
const url = this.mcpServerParamsValue.url;
|
|
2280
|
+
if (typeof url !== "string") {
|
|
2281
|
+
throw new Error("MCPToolWrapper requires an mcpServerParams.url string.");
|
|
2282
|
+
}
|
|
2283
|
+
const client = new MCPClient2(new HTTPTransport2({ url }), {
|
|
2284
|
+
connectTimeout: 15,
|
|
2285
|
+
executionTimeout: 60,
|
|
2286
|
+
discoveryTimeout: 15,
|
|
2287
|
+
maxRetries: 3
|
|
2288
|
+
});
|
|
2289
|
+
await client.connect();
|
|
2290
|
+
try {
|
|
2291
|
+
return await client.callTool(this.originalToolName, args);
|
|
2292
|
+
} finally {
|
|
2293
|
+
await client.disconnect();
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
function classifyMCPWrapperError(error, toolName) {
|
|
2298
|
+
const message = error instanceof Error ? error.message : stringifyToolOutput(error);
|
|
2299
|
+
const lower = message.toLowerCase();
|
|
2300
|
+
if (lower.includes("authentication") || lower.includes("unauthorized")) {
|
|
2301
|
+
return { message: `Authentication failed for MCP server: ${message}`, retryable: false };
|
|
2302
|
+
}
|
|
2303
|
+
if (lower.includes("not found")) {
|
|
2304
|
+
return { message: `Tool '${toolName}' not found on MCP server`, retryable: false };
|
|
2305
|
+
}
|
|
2306
|
+
if (lower.includes("connection") || lower.includes("network")) {
|
|
2307
|
+
return { message: `Network connection failed: ${message}`, retryable: true };
|
|
2308
|
+
}
|
|
2309
|
+
if (lower.includes("json") || lower.includes("parsing")) {
|
|
2310
|
+
return { message: `Server response parsing error: ${message}`, retryable: true };
|
|
2311
|
+
}
|
|
2312
|
+
return { message: `MCP execution error: ${message}`, retryable: false };
|
|
2313
|
+
}
|
|
2314
|
+
async function waitForMCPWrapperRetry(seconds) {
|
|
2315
|
+
await new Promise((resolve) => {
|
|
2316
|
+
setTimeout(resolve, seconds * 1e3);
|
|
2317
|
+
});
|
|
2318
|
+
}
|
|
2319
|
+
async function withMCPWrapperTimeout(operation) {
|
|
2320
|
+
let timeout;
|
|
2321
|
+
try {
|
|
2322
|
+
return await Promise.race([
|
|
2323
|
+
operation,
|
|
2324
|
+
new Promise((_, reject) => {
|
|
2325
|
+
timeout = setTimeout(() => {
|
|
2326
|
+
reject(new Error(`Connection timed out after ${String(MCP_TOOL_EXECUTION_TIMEOUT_SECONDS)} seconds`));
|
|
2327
|
+
}, MCP_TOOL_EXECUTION_TIMEOUT_SECONDS * 1e3);
|
|
2328
|
+
})
|
|
2329
|
+
]);
|
|
2330
|
+
} finally {
|
|
2331
|
+
clearTimeout(timeout);
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
var ToolUsageError = class extends Error {
|
|
2335
|
+
constructor(message) {
|
|
2336
|
+
super(message);
|
|
2337
|
+
this.name = "ToolUsageError";
|
|
2338
|
+
}
|
|
2339
|
+
};
|
|
2340
|
+
var ToolUsage = class _ToolUsage {
|
|
2341
|
+
runAttempts = 1;
|
|
2342
|
+
maxParsingAttempts = 3;
|
|
2343
|
+
rememberFormatAfterUsages = 3;
|
|
2344
|
+
toolsHandler;
|
|
2345
|
+
tools_handler;
|
|
2346
|
+
tools;
|
|
2347
|
+
task;
|
|
2348
|
+
functionCallingLlm;
|
|
2349
|
+
function_calling_llm;
|
|
2350
|
+
agent;
|
|
2351
|
+
action;
|
|
2352
|
+
fingerprintContext;
|
|
2353
|
+
fingerprint_context;
|
|
2354
|
+
constructor(options = {}) {
|
|
2355
|
+
this.toolsHandler = options.toolsHandler ?? options.tools_handler ?? null;
|
|
2356
|
+
this.tools_handler = this.toolsHandler;
|
|
2357
|
+
this.tools = options.tools ?? [];
|
|
2358
|
+
this.task = options.task;
|
|
2359
|
+
this.functionCallingLlm = options.functionCallingLlm ?? options.function_calling_llm;
|
|
2360
|
+
this.function_calling_llm = this.functionCallingLlm;
|
|
2361
|
+
this.agent = options.agent;
|
|
2362
|
+
this.action = options.action ?? null;
|
|
2363
|
+
this.fingerprintContext = options.fingerprintContext ?? options.fingerprint_context ?? {};
|
|
2364
|
+
this.fingerprint_context = this.fingerprintContext;
|
|
2365
|
+
}
|
|
2366
|
+
get run_attempts() {
|
|
2367
|
+
return this.runAttempts;
|
|
2368
|
+
}
|
|
2369
|
+
get _run_attempts() {
|
|
2370
|
+
return this.runAttempts;
|
|
2371
|
+
}
|
|
2372
|
+
get _max_parsing_attempts() {
|
|
2373
|
+
return this.maxParsingAttempts;
|
|
2374
|
+
}
|
|
2375
|
+
get _remember_format_after_usages() {
|
|
2376
|
+
return this.rememberFormatAfterUsages;
|
|
2377
|
+
}
|
|
2378
|
+
parseToolCalling(toolString) {
|
|
2379
|
+
const calling = normalizeToolCalling(toolString);
|
|
2380
|
+
return calling ?? new ToolUsageError("Could not parse tool calling.");
|
|
2381
|
+
}
|
|
2382
|
+
parse_tool_calling(toolString) {
|
|
2383
|
+
return this.parseToolCalling(toolString);
|
|
2384
|
+
}
|
|
2385
|
+
async use(calling, toolString = "") {
|
|
2386
|
+
if (calling instanceof ToolUsageError) {
|
|
2387
|
+
return calling.message;
|
|
2388
|
+
}
|
|
2389
|
+
const action = this.action ?? new AgentAction({
|
|
2390
|
+
thought: "",
|
|
2391
|
+
text: toolString,
|
|
2392
|
+
tool: calling.toolName,
|
|
2393
|
+
toolInput: JSON.stringify(calling.arguments ?? {})
|
|
2394
|
+
});
|
|
2395
|
+
const result = await aexecuteToolAndCheckFinality(action, this.tools, {
|
|
2396
|
+
toolsHandler: this.toolsHandler,
|
|
2397
|
+
task: this.task,
|
|
2398
|
+
agent: this.agent,
|
|
2399
|
+
functionCallingLlm: this.functionCallingLlm,
|
|
2400
|
+
fingerprintContext: this.fingerprintContext
|
|
2401
|
+
});
|
|
2402
|
+
return stringifyToolOutput(result.result);
|
|
2403
|
+
}
|
|
2404
|
+
async ause(calling, toolString = "") {
|
|
2405
|
+
return await this.use(calling, toolString);
|
|
2406
|
+
}
|
|
2407
|
+
async _ause(toolString, tool, calling) {
|
|
2408
|
+
if (this._check_tool_repeated_usage(calling)) {
|
|
2409
|
+
return this._format_result(I18N_DEFAULT.errors("task_repeated_usage"));
|
|
2410
|
+
}
|
|
2411
|
+
const startedAt = Date.now() / 1e3;
|
|
2412
|
+
try {
|
|
2413
|
+
const usageLimitError = _ToolUsage._check_usage_limit(tool, sanitizeToolName(tool.name));
|
|
2414
|
+
if (usageLimitError) {
|
|
2415
|
+
throw new ToolUsageLimitExceededError(usageLimitError);
|
|
2416
|
+
}
|
|
2417
|
+
const input = calling.arguments ?? {};
|
|
2418
|
+
const result = await tool.run(input);
|
|
2419
|
+
this.onToolUseFinished(tool, calling, false, startedAt, result);
|
|
2420
|
+
this.toolsHandler?.onToolUse(calling, stringifyToolOutput(result), true);
|
|
2421
|
+
return this._format_result(result);
|
|
2422
|
+
} catch (error) {
|
|
2423
|
+
this.onToolError(tool, calling, error);
|
|
2424
|
+
return stringifyToolError(error);
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
_format_result(result) {
|
|
2428
|
+
const taskRecord = getRecord(this.task);
|
|
2429
|
+
if (taskRecord) {
|
|
2430
|
+
const usedTools = typeof taskRecord.used_tools === "number" ? taskRecord.used_tools : 0;
|
|
2431
|
+
taskRecord.used_tools = usedTools + 1;
|
|
2432
|
+
}
|
|
2433
|
+
const output = stringifyToolOutput(result);
|
|
2434
|
+
return this._should_remember_format() ? this._remember_format(output) : output;
|
|
2435
|
+
}
|
|
2436
|
+
_should_remember_format() {
|
|
2437
|
+
const usedTools = getNumberProperty(this.task, "used_tools");
|
|
2438
|
+
return usedTools !== null && usedTools % this.rememberFormatAfterUsages === 0;
|
|
2439
|
+
}
|
|
2440
|
+
_remember_format(result) {
|
|
2441
|
+
const toolsSlice = I18N_DEFAULT.slice("tools").replaceAll("{tools}", renderToolsDescription(this.tools)).replaceAll("{tool_names}", this.tools.map((tool) => sanitizeToolName(tool.name)).join(", "));
|
|
2442
|
+
return `${stringifyToolOutput(result)}
|
|
2443
|
+
|
|
2444
|
+
${toolsSlice}`;
|
|
2445
|
+
}
|
|
2446
|
+
_check_tool_repeated_usage(calling) {
|
|
2447
|
+
const lastToolUsage = this.toolsHandler?.lastUsedTool;
|
|
2448
|
+
if (!lastToolUsage) {
|
|
2449
|
+
return false;
|
|
2450
|
+
}
|
|
2451
|
+
return sanitizedCallingName(calling) === sanitizedCallingName(lastToolUsage) && JSON.stringify(calling.arguments ?? {}) === JSON.stringify(lastToolUsage.arguments ?? {});
|
|
2452
|
+
}
|
|
2453
|
+
static _check_usage_limit(tool, toolName) {
|
|
2454
|
+
const record = getRecord(tool);
|
|
2455
|
+
const maxUsageCount = record?.max_usage_count ?? record?.maxUsageCount;
|
|
2456
|
+
const currentUsageCount = record?.current_usage_count ?? record?.currentUsageCount;
|
|
2457
|
+
if (typeof maxUsageCount === "number" && typeof currentUsageCount === "number" && currentUsageCount >= maxUsageCount) {
|
|
2458
|
+
return `Tool '${toolName}' has reached its usage limit of ${String(maxUsageCount)} times and cannot be used anymore.`;
|
|
2459
|
+
}
|
|
2460
|
+
return null;
|
|
2461
|
+
}
|
|
2462
|
+
_check_usage_limit(tool, toolName) {
|
|
2463
|
+
return _ToolUsage._check_usage_limit(tool, toolName);
|
|
2464
|
+
}
|
|
2465
|
+
_select_tool(toolName) {
|
|
2466
|
+
const sanitizedInput = sanitizeToolName(toolName);
|
|
2467
|
+
const orderedTools = [...this.tools].sort((left, right) => toolNameSimilarity(right.name, sanitizedInput) - toolNameSimilarity(left.name, sanitizedInput));
|
|
2468
|
+
for (const tool of orderedTools) {
|
|
2469
|
+
const sanitizedTool = sanitizeToolName(tool.name);
|
|
2470
|
+
if (sanitizedTool === sanitizedInput || toolNameSimilarity(tool.name, sanitizedInput) > 0.85) {
|
|
2471
|
+
return tool;
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
incrementTaskToolErrors(this.task);
|
|
2475
|
+
const error = toolName ? `Action '${toolName}' don't exist, these are the only available Actions:
|
|
2476
|
+
${renderToolsDescription(this.tools)}` : `I forgot the Action name, these are the only available Actions: ${renderToolsDescription(this.tools)}`;
|
|
2477
|
+
crewaiEventBus.emit(this, new ToolSelectionErrorEvent({
|
|
2478
|
+
toolName,
|
|
2479
|
+
toolArgs: {},
|
|
2480
|
+
toolClass: renderToolsDescription(this.tools),
|
|
2481
|
+
error,
|
|
2482
|
+
...this.toolUsageErrorEventContext(toolName, {})
|
|
2483
|
+
}));
|
|
2484
|
+
throw new Error(error);
|
|
2485
|
+
}
|
|
2486
|
+
_render() {
|
|
2487
|
+
return this.tools.map((tool) => tool.description ?? "").join("\n--\n");
|
|
2488
|
+
}
|
|
2489
|
+
async _function_calling(toolString) {
|
|
2490
|
+
if (!isLLMClient(this.functionCallingLlm)) {
|
|
2491
|
+
throw new ToolUsageError("Function calling LLM is not available.");
|
|
2492
|
+
}
|
|
2493
|
+
const converter = new Converter({
|
|
2494
|
+
text: `Only tools available:
|
|
2495
|
+
###
|
|
2496
|
+
${this._render()}
|
|
2497
|
+
|
|
2498
|
+
Return a valid schema for the tool, the tool name must be exactly equal one of the options, use this text to inform the valid output schema:
|
|
2499
|
+
|
|
2500
|
+
### TEXT
|
|
2501
|
+
${toolString}`,
|
|
2502
|
+
llm: this.functionCallingLlm,
|
|
2503
|
+
model: coerceToolCallingModel,
|
|
2504
|
+
instructions: [
|
|
2505
|
+
"The schema should have the following structure, only two keys:",
|
|
2506
|
+
"- tool_name: str",
|
|
2507
|
+
"- arguments: dict (always a dictionary, with all arguments being passed)",
|
|
2508
|
+
"",
|
|
2509
|
+
"Example:",
|
|
2510
|
+
'{"tool_name":"tool name","arguments":{"arg_name1":"value","arg_name2":2}}'
|
|
2511
|
+
].join("\n"),
|
|
2512
|
+
maxAttempts: 1
|
|
2513
|
+
});
|
|
2514
|
+
return await converter.toPydantic();
|
|
2515
|
+
}
|
|
2516
|
+
_original_tool_calling(_toolString, raiseError = false) {
|
|
2517
|
+
const action = this.action;
|
|
2518
|
+
if (!action) {
|
|
2519
|
+
return new ToolUsageError(I18N_DEFAULT.errors("tool_arguments_error"));
|
|
2520
|
+
}
|
|
2521
|
+
try {
|
|
2522
|
+
const tool = this._select_tool(action.tool);
|
|
2523
|
+
const arguments_ = this._validate_tool_input(action.toolInput);
|
|
2524
|
+
return new ToolCalling({
|
|
2525
|
+
toolName: sanitizeToolName(tool.name),
|
|
2526
|
+
arguments: arguments_
|
|
2527
|
+
});
|
|
2528
|
+
} catch (error) {
|
|
2529
|
+
if (raiseError) {
|
|
2530
|
+
throw error;
|
|
2531
|
+
}
|
|
2532
|
+
return new ToolUsageError(I18N_DEFAULT.errors("tool_arguments_error"));
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
async _tool_calling(toolString) {
|
|
2536
|
+
try {
|
|
2537
|
+
try {
|
|
2538
|
+
return this._original_tool_calling(toolString, true);
|
|
2539
|
+
} catch {
|
|
2540
|
+
if (this.functionCallingLlm) {
|
|
2541
|
+
return await this._function_calling(toolString);
|
|
2542
|
+
}
|
|
2543
|
+
return this._original_tool_calling(toolString);
|
|
2544
|
+
}
|
|
2545
|
+
} catch (error) {
|
|
2546
|
+
this.runAttempts += 1;
|
|
2547
|
+
if (this.runAttempts > this.maxParsingAttempts) {
|
|
2548
|
+
incrementTaskToolErrors(this.task);
|
|
2549
|
+
return new ToolUsageError(
|
|
2550
|
+
`${I18N_DEFAULT.errors("tool_usage_error").replace("{error}", error instanceof Error ? error.message : String(error))}
|
|
2551
|
+
Moving on then. ${I18N_DEFAULT.slice("format").replaceAll("{tool_names}", this.tools.map((tool) => sanitizeToolName(tool.name)).join(", "))}`
|
|
2552
|
+
);
|
|
2553
|
+
}
|
|
2554
|
+
return await this._tool_calling(toolString);
|
|
2555
|
+
}
|
|
2556
|
+
}
|
|
2557
|
+
_validate_tool_input(toolInput) {
|
|
2558
|
+
if (toolInput === null || toolInput === void 0) {
|
|
2559
|
+
return {};
|
|
2560
|
+
}
|
|
2561
|
+
if (typeof toolInput !== "string" || toolInput.trim().length === 0) {
|
|
2562
|
+
const error2 = "Tool input must be a valid dictionary in JSON or Python literal format";
|
|
2563
|
+
this._emit_validate_input_error(error2);
|
|
2564
|
+
throw new Error(error2);
|
|
2565
|
+
}
|
|
2566
|
+
const parsed = parseToolInputDictionary(toolInput);
|
|
2567
|
+
if (parsed) {
|
|
2568
|
+
return parsed;
|
|
2569
|
+
}
|
|
2570
|
+
const error = "Tool input must be a valid dictionary in JSON or Python literal format";
|
|
2571
|
+
this._emit_validate_input_error(error);
|
|
2572
|
+
throw new Error(error);
|
|
2573
|
+
}
|
|
2574
|
+
_emit_validate_input_error(finalError) {
|
|
2575
|
+
crewaiEventBus.emit(this, new ToolValidateInputErrorEvent({
|
|
2576
|
+
toolName: this.action?.tool ?? "",
|
|
2577
|
+
toolArgs: this.action?.toolInput ?? "",
|
|
2578
|
+
toolClass: this.constructor.name,
|
|
2579
|
+
error: finalError,
|
|
2580
|
+
...this.toolUsageErrorEventContext(this.action?.tool ?? "", this.action?.toolInput ?? "")
|
|
2581
|
+
}));
|
|
2582
|
+
}
|
|
2583
|
+
_prepare_event_data(tool, toolCalling) {
|
|
2584
|
+
return this.prepareEventData(tool, toolCalling);
|
|
2585
|
+
}
|
|
2586
|
+
_build_fingerprint_config() {
|
|
2587
|
+
const securityContext = {};
|
|
2588
|
+
const agentFingerprint = fingerprintToRecord(getRecord(getRecord(this.agent)?.security_config)?.fingerprint);
|
|
2589
|
+
if (agentFingerprint) {
|
|
2590
|
+
securityContext.agent_fingerprint = agentFingerprint;
|
|
2591
|
+
}
|
|
2592
|
+
const taskFingerprint = fingerprintToRecord(getRecord(getRecord(this.task)?.security_config)?.fingerprint);
|
|
2593
|
+
if (taskFingerprint) {
|
|
2594
|
+
securityContext.task_fingerprint = taskFingerprint;
|
|
2595
|
+
}
|
|
2596
|
+
return Object.keys(securityContext).length > 0 ? { security_context: securityContext } : {};
|
|
2597
|
+
}
|
|
2598
|
+
onToolError(tool, toolCalling, error) {
|
|
2599
|
+
const eventData = this.prepareEventData(tool, toolCalling);
|
|
2600
|
+
crewaiEventBus.emit(this, new ToolUsageErrorEvent({
|
|
2601
|
+
...eventData,
|
|
2602
|
+
task_id: getStringProperty(this.task, "id"),
|
|
2603
|
+
task_name: getTaskDisplayName(this.task),
|
|
2604
|
+
error
|
|
2605
|
+
}));
|
|
2606
|
+
}
|
|
2607
|
+
on_tool_error(tool, toolCalling, error) {
|
|
2608
|
+
this.onToolError(tool, toolCalling, error);
|
|
2609
|
+
}
|
|
2610
|
+
onToolUseFinished(tool, toolCalling, fromCache, startedAt, result) {
|
|
2611
|
+
const finishedAt = Date.now() / 1e3;
|
|
2612
|
+
crewaiEventBus.emit(this, new ToolUsageFinishedEvent({
|
|
2613
|
+
...this.prepareEventData(tool, toolCalling),
|
|
2614
|
+
started_at: new Date(startedAt * 1e3),
|
|
2615
|
+
finished_at: new Date(finishedAt * 1e3),
|
|
2616
|
+
from_cache: fromCache,
|
|
2617
|
+
output: result,
|
|
2618
|
+
...this.task ? {
|
|
2619
|
+
task_id: getStringProperty(this.task, "id"),
|
|
2620
|
+
task_name: getTaskDisplayName(this.task)
|
|
2621
|
+
} : {}
|
|
2622
|
+
}));
|
|
2623
|
+
}
|
|
2624
|
+
on_tool_use_finished(tool, toolCalling, fromCache, startedAt, result) {
|
|
2625
|
+
this.onToolUseFinished(tool, toolCalling, fromCache, startedAt, result);
|
|
2626
|
+
}
|
|
2627
|
+
prepareEventData(tool, toolCalling) {
|
|
2628
|
+
return {
|
|
2629
|
+
run_attempts: this.run_attempts,
|
|
2630
|
+
delegations: getNumberProperty(this.task, "delegations") ?? 0,
|
|
2631
|
+
tool_name: sanitizeToolName(getStringProperty(tool, "name") ?? toolCalling.toolName ?? toolCalling.tool_name ?? ""),
|
|
2632
|
+
tool_args: toolCalling.arguments ?? {},
|
|
2633
|
+
tool_class: getConstructorName(tool),
|
|
2634
|
+
agent_key: getStringProperty(this.agent, "key") ?? "unknown",
|
|
2635
|
+
agent_role: getStringProperty(this.agent, "_original_role") ?? getStringProperty(this.agent, "role") ?? "unknown",
|
|
2636
|
+
...this.fingerprintContext
|
|
2637
|
+
};
|
|
2638
|
+
}
|
|
2639
|
+
toolUsageErrorEventContext(toolName, toolArgs) {
|
|
2640
|
+
return {
|
|
2641
|
+
agent_key: getStringProperty(this.agent, "key") ?? "unknown",
|
|
2642
|
+
agent_role: getStringProperty(this.agent, "_original_role") ?? getStringProperty(this.agent, "role") ?? "unknown",
|
|
2643
|
+
tool_name: toolName,
|
|
2644
|
+
tool_args: toolArgs,
|
|
2645
|
+
...this.fingerprintContext
|
|
2646
|
+
};
|
|
2647
|
+
}
|
|
2648
|
+
};
|
|
2649
|
+
function createTool(options) {
|
|
2650
|
+
return new StructuredTool(options);
|
|
2651
|
+
}
|
|
2652
|
+
function functionTool(first, options = {}) {
|
|
2653
|
+
if (typeof first === "function") {
|
|
2654
|
+
return createToolFromFunction(first, {});
|
|
2655
|
+
}
|
|
2656
|
+
const normalizedOptions = typeof first === "string" ? { ...options, name: first } : first;
|
|
2657
|
+
return (func) => createToolFromFunction(func, normalizedOptions);
|
|
2658
|
+
}
|
|
2659
|
+
var create_tool = createTool;
|
|
2660
|
+
var createFunctionTool = functionTool;
|
|
2661
|
+
var create_function_tool = functionTool;
|
|
2662
|
+
function _make_tool(func) {
|
|
2663
|
+
return createToolFromFunction(func, {});
|
|
2664
|
+
}
|
|
2665
|
+
function _make_with_name(name, options = {}) {
|
|
2666
|
+
return (func) => createToolFromFunction(func, { ...options, name });
|
|
2667
|
+
}
|
|
2668
|
+
function _resolve_tool_dict(value) {
|
|
2669
|
+
const name = typeof value.name === "string" ? value.name : "tool";
|
|
2670
|
+
const description = typeof value.description === "string" ? value.description : "";
|
|
2671
|
+
const maxUsageCount = value.maxUsageCount ?? value.max_usage_count;
|
|
2672
|
+
const currentUsageCount = value.currentUsageCount ?? value.current_usage_count;
|
|
2673
|
+
return new StructuredTool({
|
|
2674
|
+
name,
|
|
2675
|
+
description,
|
|
2676
|
+
argsSchema: _deserialize_schema(value.argsSchema ?? value.args_schema) ?? {},
|
|
2677
|
+
resultAsAnswer: Boolean(value.resultAsAnswer ?? value.result_as_answer),
|
|
2678
|
+
maxUsageCount: typeof maxUsageCount === "number" ? maxUsageCount : null,
|
|
2679
|
+
currentUsageCount: typeof currentUsageCount === "number" ? currentUsageCount : 0,
|
|
2680
|
+
cacheFunction: typeof value.cacheFunction === "function" ? value.cacheFunction : typeof value.cache_function === "function" ? value.cache_function : _default_cache_function,
|
|
2681
|
+
func: typeof value.func === "function" ? value.func : (args) => args
|
|
2682
|
+
});
|
|
2683
|
+
}
|
|
2684
|
+
function createToolFromFunction(func, options) {
|
|
2685
|
+
const inferredName = options.name ?? func.name;
|
|
2686
|
+
if (!inferredName) {
|
|
2687
|
+
throw new Error("Tool function must have a name or explicit tool name.");
|
|
2688
|
+
}
|
|
2689
|
+
const parameterNames = inferFunctionParameterNames(func);
|
|
2690
|
+
const argsSchema = options.argsSchema ?? options.args_schema ?? inferFunctionArgsSchema(func);
|
|
2691
|
+
return new StructuredTool({
|
|
2692
|
+
name: inferredName,
|
|
2693
|
+
description: options.description ?? inferFunctionDescription(func, inferredName),
|
|
2694
|
+
argsSchema,
|
|
2695
|
+
envVars: options.envVars ?? options.env_vars ?? [],
|
|
2696
|
+
resultAsAnswer: options.resultAsAnswer ?? options.result_as_answer ?? false,
|
|
2697
|
+
maxUsageCount: options.maxUsageCount ?? options.max_usage_count ?? null,
|
|
2698
|
+
...options.cacheFunction === void 0 ? {} : { cacheFunction: options.cacheFunction },
|
|
2699
|
+
...options.cache === void 0 ? {} : { cache: options.cache },
|
|
2700
|
+
func: (args) => func(...parameterNames.map((parameterName) => args[parameterName]))
|
|
2701
|
+
});
|
|
2702
|
+
}
|
|
2703
|
+
function normalizeFromFunctionOptions(optionsOrName, description, returnDirect, argsSchema, inferSchema) {
|
|
2704
|
+
if (typeof optionsOrName === "string" || optionsOrName === null) {
|
|
2705
|
+
return {
|
|
2706
|
+
...optionsOrName === null ? {} : { name: optionsOrName },
|
|
2707
|
+
...description === void 0 || description === null ? {} : { description },
|
|
2708
|
+
returnDirect,
|
|
2709
|
+
...argsSchema === void 0 || argsSchema === null ? {} : { argsSchema },
|
|
2710
|
+
inferSchema
|
|
2711
|
+
};
|
|
2712
|
+
}
|
|
2713
|
+
return optionsOrName;
|
|
2714
|
+
}
|
|
2715
|
+
function isToolCalling(value) {
|
|
2716
|
+
if (!value || typeof value !== "object") {
|
|
2717
|
+
return false;
|
|
2718
|
+
}
|
|
2719
|
+
const record = value;
|
|
2720
|
+
return typeof (record.toolName ?? record.tool_name) === "string";
|
|
2721
|
+
}
|
|
2722
|
+
function normalizeToolCalling(value) {
|
|
2723
|
+
if (typeof value === "string") {
|
|
2724
|
+
try {
|
|
2725
|
+
return normalizeToolCalling(JSON.parse(value));
|
|
2726
|
+
} catch {
|
|
2727
|
+
try {
|
|
2728
|
+
const parsed = parseAgentOutput(value);
|
|
2729
|
+
if (!(parsed instanceof AgentAction)) {
|
|
2730
|
+
return null;
|
|
2731
|
+
}
|
|
2732
|
+
return {
|
|
2733
|
+
toolName: parsed.tool,
|
|
2734
|
+
arguments: normalizeToolInput(parsed.toolInput)
|
|
2735
|
+
};
|
|
2736
|
+
} catch (error) {
|
|
2737
|
+
if (error instanceof OutputParserError) {
|
|
2738
|
+
return null;
|
|
2739
|
+
}
|
|
2740
|
+
throw error;
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
if (!isToolCalling(value)) {
|
|
2745
|
+
return null;
|
|
2746
|
+
}
|
|
2747
|
+
const record = value;
|
|
2748
|
+
const args = record.arguments;
|
|
2749
|
+
return {
|
|
2750
|
+
toolName: String(record.toolName ?? record.tool_name),
|
|
2751
|
+
arguments: args && typeof args === "object" && !Array.isArray(args) ? args : null
|
|
2752
|
+
};
|
|
2753
|
+
}
|
|
2754
|
+
function coerceToolCallingModel(value) {
|
|
2755
|
+
const normalized = normalizeToolCalling(value);
|
|
2756
|
+
if (!normalized) {
|
|
2757
|
+
throw new ToolUsageError("Failed to parse tool calling");
|
|
2758
|
+
}
|
|
2759
|
+
return new ToolCalling(normalized);
|
|
2760
|
+
}
|
|
2761
|
+
function isLLMClient(value) {
|
|
2762
|
+
return Boolean(value && typeof value === "object" && typeof value.call === "function");
|
|
2763
|
+
}
|
|
2764
|
+
async function aexecuteToolAndCheckFinality(agentAction, tools, options = {}) {
|
|
2765
|
+
void options.functionCallingLlm;
|
|
2766
|
+
void options.function_calling_llm;
|
|
2767
|
+
const agentKey = options.agentKey ?? options.agent_key ?? null;
|
|
2768
|
+
const agentRole = options.agentRole ?? options.agent_role ?? null;
|
|
2769
|
+
if (agentKey && agentRole && options.agent) {
|
|
2770
|
+
setAgentFingerprintFromContext(options.agent, options.fingerprintContext ?? options.fingerprint_context ?? {});
|
|
2771
|
+
}
|
|
2772
|
+
const toolNameToToolMap = new Map(tools.map((tool2) => [sanitizeToolName(tool2.name), tool2]));
|
|
2773
|
+
const toolCalling = normalizeToolCalling(agentAction.text) ?? {
|
|
2774
|
+
toolName: agentAction.tool,
|
|
2775
|
+
arguments: normalizeToolInput(agentAction.toolInput)
|
|
2776
|
+
};
|
|
2777
|
+
const sanitizedToolName = sanitizeToolName(toolCalling.toolName);
|
|
2778
|
+
const tool = toolNameToToolMap.get(sanitizedToolName);
|
|
2779
|
+
if (!tool) {
|
|
2780
|
+
return new ToolResult({
|
|
2781
|
+
result: I18N_DEFAULT.errors("wrong_tool_name").replaceAll("{tool}", sanitizedToolName).replaceAll("{tools}", [...toolNameToToolMap.keys()].join(", ")),
|
|
2782
|
+
resultAsAnswer: false
|
|
2783
|
+
});
|
|
2784
|
+
}
|
|
2785
|
+
const toolInput = toolCalling.arguments ?? {};
|
|
2786
|
+
const output = tool instanceof BaseTool ? await tool.run(toolInput, { agent: options.agent, task: options.task, crew: options.crew }) : await runPlainToolWithHooks(tool, sanitizedToolName, toolInput, options);
|
|
2787
|
+
const result = new ToolResult({
|
|
2788
|
+
result: output,
|
|
2789
|
+
resultAsAnswer: tool.resultAsAnswer ?? false
|
|
2790
|
+
});
|
|
2791
|
+
const toolsHandler = options.toolsHandler ?? options.tools_handler ?? null;
|
|
2792
|
+
toolsHandler?.onToolUse({
|
|
2793
|
+
toolName: sanitizedToolName,
|
|
2794
|
+
tool_name: sanitizedToolName,
|
|
2795
|
+
arguments: toolInput
|
|
2796
|
+
}, stringifyToolOutput(output), true);
|
|
2797
|
+
return result;
|
|
2798
|
+
}
|
|
2799
|
+
var aexecute_tool_and_check_finality = aexecuteToolAndCheckFinality;
|
|
2800
|
+
function executeToolAndCheckFinality(agentAction, tools, options = {}) {
|
|
2801
|
+
return aexecuteToolAndCheckFinality(agentAction, tools, options);
|
|
2802
|
+
}
|
|
2803
|
+
var execute_tool_and_check_finality = executeToolAndCheckFinality;
|
|
2804
|
+
function renderToolsDescription(tools) {
|
|
2805
|
+
return tools.map((tool) => {
|
|
2806
|
+
if (tool instanceof BaseTool) {
|
|
2807
|
+
return tool.renderDescription();
|
|
2808
|
+
}
|
|
2809
|
+
return [
|
|
2810
|
+
`Tool Name: ${sanitizeToolName(tool.name)}`,
|
|
2811
|
+
"Tool Arguments: {}",
|
|
2812
|
+
`Tool Description: ${tool.description ?? ""}`
|
|
2813
|
+
].join("\n");
|
|
2814
|
+
}).join("\n\n");
|
|
2815
|
+
}
|
|
2816
|
+
function normalizeToolInput(input) {
|
|
2817
|
+
if (input === void 0) {
|
|
2818
|
+
return {};
|
|
2819
|
+
}
|
|
2820
|
+
if (typeof input === "string") {
|
|
2821
|
+
try {
|
|
2822
|
+
const parsed = JSON.parse(input);
|
|
2823
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : { input };
|
|
2824
|
+
} catch {
|
|
2825
|
+
return { input };
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
if (isToolContext(input)) {
|
|
2829
|
+
return { input: input.input, inputs: input.inputs };
|
|
2830
|
+
}
|
|
2831
|
+
return { ...input };
|
|
2832
|
+
}
|
|
2833
|
+
function normalizeStructuredToolInput(input, argsSchema = null, strictJsonStrings = true) {
|
|
2834
|
+
if (input === void 0) {
|
|
2835
|
+
return {};
|
|
2836
|
+
}
|
|
2837
|
+
if (typeof input === "string") {
|
|
2838
|
+
try {
|
|
2839
|
+
const parsed = JSON.parse(input);
|
|
2840
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
2841
|
+
return parsed;
|
|
2842
|
+
}
|
|
2843
|
+
const singleArgName = singleSchemaArgName(argsSchema);
|
|
2844
|
+
return singleArgName ? { [singleArgName]: parsed } : {};
|
|
2845
|
+
} catch (error) {
|
|
2846
|
+
const singleArgName = singleSchemaArgName(argsSchema);
|
|
2847
|
+
if (!strictJsonStrings && singleArgName) {
|
|
2848
|
+
return { [singleArgName]: input };
|
|
2849
|
+
}
|
|
2850
|
+
throw new Error(`Failed to parse arguments as JSON: ${error instanceof Error ? error.message : String(error)}`, {
|
|
2851
|
+
cause: error
|
|
2852
|
+
});
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
if (isToolContext(input)) {
|
|
2856
|
+
return { input: input.input, inputs: input.inputs };
|
|
2857
|
+
}
|
|
2858
|
+
return { ...input };
|
|
2859
|
+
}
|
|
2860
|
+
function singleSchemaArgName(argsSchema) {
|
|
2861
|
+
if (!argsSchema) {
|
|
2862
|
+
return null;
|
|
2863
|
+
}
|
|
2864
|
+
const argNames = Object.keys(argsSchema);
|
|
2865
|
+
return argNames.length === 1 ? argNames[0] ?? null : null;
|
|
2866
|
+
}
|
|
2867
|
+
function jsonDumpsForHint(value) {
|
|
2868
|
+
if (value === null || value === void 0) {
|
|
2869
|
+
return "null";
|
|
2870
|
+
}
|
|
2871
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
2872
|
+
return JSON.stringify(value);
|
|
2873
|
+
}
|
|
2874
|
+
if (Array.isArray(value)) {
|
|
2875
|
+
return `[${value.map((item) => jsonDumpsForHint(item)).join(", ")}]`;
|
|
2876
|
+
}
|
|
2877
|
+
if (typeof value === "object") {
|
|
2878
|
+
return `{${Object.entries(value).map(([key, item]) => `${JSON.stringify(key)}: ${jsonDumpsForHint(item)}`).join(", ")}}`;
|
|
2879
|
+
}
|
|
2880
|
+
return JSON.stringify(value);
|
|
2881
|
+
}
|
|
2882
|
+
function validateArgs(toolName, schema, args) {
|
|
2883
|
+
const schemaEntries = Object.entries(schema);
|
|
2884
|
+
if (schemaEntries.length === 0) {
|
|
2885
|
+
return { ...args };
|
|
2886
|
+
}
|
|
2887
|
+
const validated = {};
|
|
2888
|
+
for (const [name, spec] of schemaEntries) {
|
|
2889
|
+
const value = args[name];
|
|
2890
|
+
if (value === void 0) {
|
|
2891
|
+
if (spec.default !== void 0) {
|
|
2892
|
+
validated[name] = spec.default;
|
|
2893
|
+
continue;
|
|
2894
|
+
}
|
|
2895
|
+
if (spec.required) {
|
|
2896
|
+
throw new ToolValidationError(`Tool '${toolName}' missing required argument '${name}'.`);
|
|
2897
|
+
}
|
|
2898
|
+
continue;
|
|
2899
|
+
}
|
|
2900
|
+
if (spec.type && spec.type !== "unknown" && !matchesType(value, spec.type)) {
|
|
2901
|
+
throw new ToolValidationError(
|
|
2902
|
+
`Tool '${toolName}' argument '${name}' expected ${spec.type}, got ${Array.isArray(value) ? "array" : typeof value}.`
|
|
2903
|
+
);
|
|
2904
|
+
}
|
|
2905
|
+
validated[name] = value;
|
|
2906
|
+
}
|
|
2907
|
+
return validated;
|
|
2908
|
+
}
|
|
2909
|
+
function isToolContext(input) {
|
|
2910
|
+
return typeof input.input === "string" && "inputs" in input;
|
|
2911
|
+
}
|
|
2912
|
+
function matchesType(value, type) {
|
|
2913
|
+
switch (type) {
|
|
2914
|
+
case "array":
|
|
2915
|
+
return Array.isArray(value);
|
|
2916
|
+
case "object":
|
|
2917
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
2918
|
+
case "string":
|
|
2919
|
+
case "number":
|
|
2920
|
+
case "boolean":
|
|
2921
|
+
return typeof value === type;
|
|
2922
|
+
case "unknown":
|
|
2923
|
+
return true;
|
|
2924
|
+
default:
|
|
2925
|
+
return false;
|
|
2926
|
+
}
|
|
2927
|
+
}
|
|
2928
|
+
function buildToolContext(input, inputs) {
|
|
2929
|
+
return { input, inputs };
|
|
2930
|
+
}
|
|
2931
|
+
function rawToolArgs(input) {
|
|
2932
|
+
if (typeof input === "string") {
|
|
2933
|
+
return input;
|
|
2934
|
+
}
|
|
2935
|
+
if (input === void 0) {
|
|
2936
|
+
return {};
|
|
2937
|
+
}
|
|
2938
|
+
return { ...input };
|
|
2939
|
+
}
|
|
2940
|
+
async function runPlainToolWithHooks(tool, sanitizedToolName, toolInput, options) {
|
|
2941
|
+
const context = new ToolCallHookContext({
|
|
2942
|
+
toolName: sanitizedToolName,
|
|
2943
|
+
toolInput,
|
|
2944
|
+
tool,
|
|
2945
|
+
agent: options.agent,
|
|
2946
|
+
task: options.task,
|
|
2947
|
+
crew: options.crew
|
|
2948
|
+
});
|
|
2949
|
+
await runBeforeToolCallHooks(context);
|
|
2950
|
+
const rawResult = await tool.run(toolInput);
|
|
2951
|
+
return await runAfterToolCallHooks(new ToolCallHookContext({
|
|
2952
|
+
toolName: sanitizedToolName,
|
|
2953
|
+
toolInput,
|
|
2954
|
+
tool,
|
|
2955
|
+
agent: options.agent,
|
|
2956
|
+
task: options.task,
|
|
2957
|
+
crew: options.crew,
|
|
2958
|
+
toolResult: rawResult
|
|
2959
|
+
}));
|
|
2960
|
+
}
|
|
2961
|
+
function isToolResultOptions(value) {
|
|
2962
|
+
return value !== null && typeof value === "object" && "result" in value;
|
|
2963
|
+
}
|
|
2964
|
+
function isToolArgsSchema(value) {
|
|
2965
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
2966
|
+
return false;
|
|
2967
|
+
}
|
|
2968
|
+
return Object.values(value).every((entry) => entry !== null && typeof entry === "object" && !Array.isArray(entry));
|
|
2969
|
+
}
|
|
2970
|
+
function baseToolPassthroughOptions(options) {
|
|
2971
|
+
return {
|
|
2972
|
+
...options.envVars === void 0 ? {} : { envVars: options.envVars },
|
|
2973
|
+
...options.env_vars === void 0 ? {} : { env_vars: options.env_vars },
|
|
2974
|
+
...options.descriptionUpdated === void 0 ? {} : { descriptionUpdated: options.descriptionUpdated },
|
|
2975
|
+
...options.description_updated === void 0 ? {} : { description_updated: options.description_updated },
|
|
2976
|
+
...options.resultAsAnswer === void 0 ? {} : { resultAsAnswer: options.resultAsAnswer },
|
|
2977
|
+
...options.result_as_answer === void 0 ? {} : { result_as_answer: options.result_as_answer },
|
|
2978
|
+
...options.maxUsageCount === void 0 ? {} : { maxUsageCount: options.maxUsageCount },
|
|
2979
|
+
...options.max_usage_count === void 0 ? {} : { max_usage_count: options.max_usage_count },
|
|
2980
|
+
...options.cacheFunction === void 0 ? {} : { cacheFunction: options.cacheFunction },
|
|
2981
|
+
...options.cache_function === void 0 ? {} : { cache_function: options.cache_function },
|
|
2982
|
+
...options.cache === void 0 ? {} : { cache: options.cache }
|
|
2983
|
+
};
|
|
2984
|
+
}
|
|
2985
|
+
function promptLeafToString(value) {
|
|
2986
|
+
return typeof value === "string" ? value : "";
|
|
2987
|
+
}
|
|
2988
|
+
function toToolString(value) {
|
|
2989
|
+
if (typeof value === "string") {
|
|
2990
|
+
return value;
|
|
2991
|
+
}
|
|
2992
|
+
if (value === null || value === void 0) {
|
|
2993
|
+
return "";
|
|
2994
|
+
}
|
|
2995
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
2996
|
+
return value.toString();
|
|
2997
|
+
}
|
|
2998
|
+
return JSON.stringify(value);
|
|
2999
|
+
}
|
|
3000
|
+
function stringifyToolOutput(value) {
|
|
3001
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
3002
|
+
}
|
|
3003
|
+
function isPromiseLike2(value) {
|
|
3004
|
+
if (!value || typeof value !== "object" || !("then" in value)) {
|
|
3005
|
+
return false;
|
|
3006
|
+
}
|
|
3007
|
+
return typeof value.then === "function";
|
|
3008
|
+
}
|
|
3009
|
+
function toolCacheKey(toolName, input) {
|
|
3010
|
+
return `${sanitizeToolName(toolName)}-${input}`;
|
|
3011
|
+
}
|
|
3012
|
+
function sanitizedCallingName(calling) {
|
|
3013
|
+
return sanitizeToolName(calling.toolName ?? calling.tool_name ?? "");
|
|
3014
|
+
}
|
|
3015
|
+
function stringifyToolCallingArguments(args) {
|
|
3016
|
+
if (!args) {
|
|
3017
|
+
return "";
|
|
3018
|
+
}
|
|
3019
|
+
return JSON.stringify(args);
|
|
3020
|
+
}
|
|
3021
|
+
function getRecord(value) {
|
|
3022
|
+
return value && typeof value === "object" ? value : null;
|
|
3023
|
+
}
|
|
3024
|
+
function getStringProperty(value, key) {
|
|
3025
|
+
const property = getRecord(value)?.[key];
|
|
3026
|
+
return typeof property === "string" ? property : null;
|
|
3027
|
+
}
|
|
3028
|
+
function getNumberProperty(value, key) {
|
|
3029
|
+
const property = getRecord(value)?.[key];
|
|
3030
|
+
return typeof property === "number" ? property : null;
|
|
3031
|
+
}
|
|
3032
|
+
function getTaskDisplayName(task) {
|
|
3033
|
+
const name = getStringProperty(task, "name");
|
|
3034
|
+
if (name) {
|
|
3035
|
+
return name;
|
|
3036
|
+
}
|
|
3037
|
+
return getStringProperty(task, "description");
|
|
3038
|
+
}
|
|
3039
|
+
function getConstructorName(value) {
|
|
3040
|
+
return value && typeof value === "object" ? value.constructor.name : null;
|
|
3041
|
+
}
|
|
3042
|
+
function incrementTaskToolErrors(task) {
|
|
3043
|
+
const record = getRecord(task);
|
|
3044
|
+
if (!record) {
|
|
3045
|
+
return;
|
|
3046
|
+
}
|
|
3047
|
+
if (typeof record.increment_tools_errors === "function") {
|
|
3048
|
+
record.increment_tools_errors.call(task);
|
|
3049
|
+
return;
|
|
3050
|
+
}
|
|
3051
|
+
if (typeof record.incrementToolsErrors === "function") {
|
|
3052
|
+
record.incrementToolsErrors.call(task);
|
|
3053
|
+
return;
|
|
3054
|
+
}
|
|
3055
|
+
const current = typeof record.tools_errors === "number" ? record.tools_errors : 0;
|
|
3056
|
+
record.tools_errors = current + 1;
|
|
3057
|
+
}
|
|
3058
|
+
function parseToolInputDictionary(toolInput) {
|
|
3059
|
+
const candidates = [
|
|
3060
|
+
toolInput,
|
|
3061
|
+
toolInput.trim().replaceAll("'", '"'),
|
|
3062
|
+
normalizePythonLiteralObject(toolInput),
|
|
3063
|
+
normalizeJson5LikeObject(toolInput)
|
|
3064
|
+
].filter((candidate) => typeof candidate === "string");
|
|
3065
|
+
for (const candidate of candidates) {
|
|
3066
|
+
try {
|
|
3067
|
+
const parsed = JSON.parse(candidate);
|
|
3068
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
3069
|
+
return parsed;
|
|
3070
|
+
}
|
|
3071
|
+
} catch {
|
|
3072
|
+
}
|
|
3073
|
+
}
|
|
3074
|
+
return null;
|
|
3075
|
+
}
|
|
3076
|
+
function normalizePythonLiteralObject(value) {
|
|
3077
|
+
const trimmed = value.trim();
|
|
3078
|
+
if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) {
|
|
3079
|
+
return null;
|
|
3080
|
+
}
|
|
3081
|
+
return trimmed.replaceAll(/\bTrue\b/g, "true").replaceAll(/\bFalse\b/g, "false").replaceAll(/\bNone\b/g, "null").replaceAll(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, (_match, content) => JSON.stringify(content.replaceAll("\\'", "'")));
|
|
3082
|
+
}
|
|
3083
|
+
function normalizeJson5LikeObject(value) {
|
|
3084
|
+
const pythonLike = normalizePythonLiteralObject(value);
|
|
3085
|
+
if (!pythonLike) {
|
|
3086
|
+
return null;
|
|
3087
|
+
}
|
|
3088
|
+
return stripTrailingCommas(quoteUnquotedObjectKeys(pythonLike));
|
|
3089
|
+
}
|
|
3090
|
+
function stripTrailingCommas(value) {
|
|
3091
|
+
let output = "";
|
|
3092
|
+
let inString = false;
|
|
3093
|
+
let escaped = false;
|
|
3094
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
3095
|
+
const char = value[index] ?? "";
|
|
3096
|
+
if (inString) {
|
|
3097
|
+
output += char;
|
|
3098
|
+
if (escaped) {
|
|
3099
|
+
escaped = false;
|
|
3100
|
+
} else if (char === "\\") {
|
|
3101
|
+
escaped = true;
|
|
3102
|
+
} else if (char === '"') {
|
|
3103
|
+
inString = false;
|
|
3104
|
+
}
|
|
3105
|
+
continue;
|
|
3106
|
+
}
|
|
3107
|
+
if (char === '"') {
|
|
3108
|
+
inString = true;
|
|
3109
|
+
output += char;
|
|
3110
|
+
continue;
|
|
3111
|
+
}
|
|
3112
|
+
if (char === ",") {
|
|
3113
|
+
let nextIndex = index + 1;
|
|
3114
|
+
while (/\s/.test(value[nextIndex] ?? "")) {
|
|
3115
|
+
nextIndex += 1;
|
|
3116
|
+
}
|
|
3117
|
+
if (value[nextIndex] === "}" || value[nextIndex] === "]") {
|
|
3118
|
+
continue;
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
3121
|
+
output += char;
|
|
3122
|
+
}
|
|
3123
|
+
return output;
|
|
3124
|
+
}
|
|
3125
|
+
function quoteUnquotedObjectKeys(value) {
|
|
3126
|
+
let output = "";
|
|
3127
|
+
let inString = false;
|
|
3128
|
+
let escaped = false;
|
|
3129
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
3130
|
+
const char = value[index] ?? "";
|
|
3131
|
+
if (inString) {
|
|
3132
|
+
output += char;
|
|
3133
|
+
if (escaped) {
|
|
3134
|
+
escaped = false;
|
|
3135
|
+
} else if (char === "\\") {
|
|
3136
|
+
escaped = true;
|
|
3137
|
+
} else if (char === '"') {
|
|
3138
|
+
inString = false;
|
|
3139
|
+
}
|
|
3140
|
+
continue;
|
|
3141
|
+
}
|
|
3142
|
+
if (char === '"') {
|
|
3143
|
+
inString = true;
|
|
3144
|
+
output += char;
|
|
3145
|
+
continue;
|
|
3146
|
+
}
|
|
3147
|
+
if (char === "{" || char === ",") {
|
|
3148
|
+
output += char;
|
|
3149
|
+
let cursor = index + 1;
|
|
3150
|
+
while (/\s/.test(value[cursor] ?? "")) {
|
|
3151
|
+
output += value[cursor] ?? "";
|
|
3152
|
+
cursor += 1;
|
|
3153
|
+
}
|
|
3154
|
+
const keyStart = cursor;
|
|
3155
|
+
if (/[A-Za-z_$]/.test(value[cursor] ?? "")) {
|
|
3156
|
+
cursor += 1;
|
|
3157
|
+
while (/[A-Za-z0-9_$]/.test(value[cursor] ?? "")) {
|
|
3158
|
+
cursor += 1;
|
|
3159
|
+
}
|
|
3160
|
+
let colonCursor = cursor;
|
|
3161
|
+
while (/\s/.test(value[colonCursor] ?? "")) {
|
|
3162
|
+
colonCursor += 1;
|
|
3163
|
+
}
|
|
3164
|
+
if (value[colonCursor] === ":") {
|
|
3165
|
+
output += JSON.stringify(value.slice(keyStart, cursor));
|
|
3166
|
+
index = cursor - 1;
|
|
3167
|
+
continue;
|
|
3168
|
+
}
|
|
3169
|
+
}
|
|
3170
|
+
index = keyStart - 1;
|
|
3171
|
+
continue;
|
|
3172
|
+
}
|
|
3173
|
+
output += char;
|
|
3174
|
+
}
|
|
3175
|
+
return output;
|
|
3176
|
+
}
|
|
3177
|
+
function stringifyToolError(error) {
|
|
3178
|
+
if (error instanceof Error) {
|
|
3179
|
+
return error.message;
|
|
3180
|
+
}
|
|
3181
|
+
if (typeof error === "string") {
|
|
3182
|
+
return error;
|
|
3183
|
+
}
|
|
3184
|
+
return stringifyToolOutput(error);
|
|
3185
|
+
}
|
|
3186
|
+
function fingerprintToRecord(value) {
|
|
3187
|
+
const record = getRecord(value);
|
|
3188
|
+
if (!record) {
|
|
3189
|
+
return null;
|
|
3190
|
+
}
|
|
3191
|
+
if (typeof record.to_dict === "function") {
|
|
3192
|
+
return record.to_dict.call(value);
|
|
3193
|
+
}
|
|
3194
|
+
if (typeof record.toDict === "function") {
|
|
3195
|
+
return record.toDict.call(value);
|
|
3196
|
+
}
|
|
3197
|
+
return record;
|
|
3198
|
+
}
|
|
3199
|
+
function setAgentFingerprintFromContext(agent, fingerprintContext) {
|
|
3200
|
+
const record = getRecord(agent);
|
|
3201
|
+
if (!record) {
|
|
3202
|
+
return;
|
|
3203
|
+
}
|
|
3204
|
+
const setter = typeof record.set_fingerprint === "function" ? record.set_fingerprint : typeof record.setFingerprint === "function" ? record.setFingerprint : null;
|
|
3205
|
+
if (!setter) {
|
|
3206
|
+
return;
|
|
3207
|
+
}
|
|
3208
|
+
try {
|
|
3209
|
+
setter.call(agent, Fingerprint.fromDict(fingerprintContext));
|
|
3210
|
+
} catch (error) {
|
|
3211
|
+
throw new Error(`Failed to set fingerprint: ${stringifyToolError(error)}`, { cause: error });
|
|
3212
|
+
}
|
|
3213
|
+
}
|
|
3214
|
+
function toolNameSimilarity(toolName, sanitizedInput) {
|
|
3215
|
+
return stringSimilarity(sanitizeToolName(toolName), sanitizedInput);
|
|
3216
|
+
}
|
|
3217
|
+
function stringSimilarity(left, right) {
|
|
3218
|
+
if (left === right) {
|
|
3219
|
+
return 1;
|
|
3220
|
+
}
|
|
3221
|
+
if (left.length === 0 || right.length === 0) {
|
|
3222
|
+
return 0;
|
|
3223
|
+
}
|
|
3224
|
+
const distance = levenshteinDistance(left, right);
|
|
3225
|
+
return 1 - distance / Math.max(left.length, right.length);
|
|
3226
|
+
}
|
|
3227
|
+
function levenshteinDistance(left, right) {
|
|
3228
|
+
const previous = Array.from({ length: right.length + 1 }, (_value, index) => index);
|
|
3229
|
+
const current = Array.from({ length: right.length + 1 }, () => 0);
|
|
3230
|
+
for (let leftIndex = 1; leftIndex <= left.length; leftIndex += 1) {
|
|
3231
|
+
current[0] = leftIndex;
|
|
3232
|
+
for (let rightIndex = 1; rightIndex <= right.length; rightIndex += 1) {
|
|
3233
|
+
current[rightIndex] = Math.min(
|
|
3234
|
+
(current[rightIndex - 1] ?? 0) + 1,
|
|
3235
|
+
(previous[rightIndex] ?? 0) + 1,
|
|
3236
|
+
(previous[rightIndex - 1] ?? 0) + (left[leftIndex - 1] === right[rightIndex - 1] ? 0 : 1)
|
|
3237
|
+
);
|
|
3238
|
+
}
|
|
3239
|
+
previous.splice(0, previous.length, ...current);
|
|
3240
|
+
}
|
|
3241
|
+
return previous[right.length] ?? 0;
|
|
3242
|
+
}
|
|
3243
|
+
function inferFunctionParameterNames(func) {
|
|
3244
|
+
return inferFunctionParameters(func).map((parameter) => parameter.name);
|
|
3245
|
+
}
|
|
3246
|
+
function inferFunctionArgsSchema(func) {
|
|
3247
|
+
return Object.fromEntries(inferFunctionParameters(func).map((parameter) => [
|
|
3248
|
+
parameter.name,
|
|
3249
|
+
parameter.hasDefault ? { type: "unknown", required: false, default: parameter.defaultValue } : { type: "unknown", required: true }
|
|
3250
|
+
]));
|
|
3251
|
+
}
|
|
3252
|
+
function inferFunctionParameters(func) {
|
|
3253
|
+
const source = Function.prototype.toString.call(func);
|
|
3254
|
+
const parametersSource = source.match(/^[^(]*\(([^)]*)\)/)?.[1] ?? source.match(/^([^=()]+)=>/)?.[1] ?? "";
|
|
3255
|
+
return parametersSource.split(",").map((parameter) => parameter.trim()).map(parseFunctionParameter).filter((parameter) => parameter !== null && /^[A-Za-z_$][\w$]*$/.test(parameter.name));
|
|
3256
|
+
}
|
|
3257
|
+
function parseFunctionParameter(parameter) {
|
|
3258
|
+
const [rawName = "", ...defaultParts] = parameter.split("=");
|
|
3259
|
+
const name = rawName.trim();
|
|
3260
|
+
if (!name) {
|
|
3261
|
+
return null;
|
|
3262
|
+
}
|
|
3263
|
+
if (defaultParts.length === 0) {
|
|
3264
|
+
return { name, hasDefault: false };
|
|
3265
|
+
}
|
|
3266
|
+
return { name, hasDefault: true, defaultValue: parseFunctionDefaultValue(defaultParts.join("=").trim()) };
|
|
3267
|
+
}
|
|
3268
|
+
function parseFunctionDefaultValue(rawDefault) {
|
|
3269
|
+
if (rawDefault === "null") {
|
|
3270
|
+
return null;
|
|
3271
|
+
}
|
|
3272
|
+
if (rawDefault === "undefined") {
|
|
3273
|
+
return void 0;
|
|
3274
|
+
}
|
|
3275
|
+
if (rawDefault === "true") {
|
|
3276
|
+
return true;
|
|
3277
|
+
}
|
|
3278
|
+
if (rawDefault === "false") {
|
|
3279
|
+
return false;
|
|
3280
|
+
}
|
|
3281
|
+
if (/^-?\d+(?:\.\d+)?$/.test(rawDefault)) {
|
|
3282
|
+
return Number(rawDefault);
|
|
3283
|
+
}
|
|
3284
|
+
if (rawDefault.startsWith('"') && rawDefault.endsWith('"') || rawDefault.startsWith("'") && rawDefault.endsWith("'")) {
|
|
3285
|
+
try {
|
|
3286
|
+
return JSON.parse(rawDefault.startsWith("'") ? `"${rawDefault.slice(1, -1).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"` : rawDefault);
|
|
3287
|
+
} catch {
|
|
3288
|
+
return rawDefault.slice(1, -1);
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3291
|
+
return void 0;
|
|
3292
|
+
}
|
|
3293
|
+
function inferFunctionDescription(func, name) {
|
|
3294
|
+
if (typeof func !== "object" && typeof func !== "function" || func === null) {
|
|
3295
|
+
return `Tool generated from function ${name}.`;
|
|
3296
|
+
}
|
|
3297
|
+
const propertyDescription = Object.getOwnPropertyDescriptor(func, "description")?.value;
|
|
3298
|
+
if (typeof propertyDescription === "string" && propertyDescription.trim()) {
|
|
3299
|
+
return propertyDescription.trim();
|
|
3300
|
+
}
|
|
3301
|
+
return `Tool generated from function ${name}.`;
|
|
3302
|
+
}
|
|
3303
|
+
function isMCPClientLike(value) {
|
|
3304
|
+
return !!value && typeof value === "object" && typeof value.connect === "function" && typeof value.disconnect === "function" && typeof value.callTool === "function";
|
|
3305
|
+
}
|
|
3306
|
+
function isMCPToolWrapperOptions(value) {
|
|
3307
|
+
return "mcpServerParams" in value || "mcp_server_params" in value || "toolName" in value || "tool_name" in value || "toolSchema" in value || "tool_schema" in value || "serverName" in value || "server_name" in value;
|
|
3308
|
+
}
|
|
3309
|
+
function toolSchemaDescription(schema, toolName, serverName) {
|
|
3310
|
+
return typeof schema.description === "string" && schema.description.trim() ? schema.description : `Tool ${toolName} from ${serverName}`;
|
|
3311
|
+
}
|
|
3312
|
+
function toolSchemaArgs(schema) {
|
|
3313
|
+
const argsSchema = schema.argsSchema ?? schema.args_schema;
|
|
3314
|
+
if (argsSchema && typeof argsSchema === "object" && !Array.isArray(argsSchema)) {
|
|
3315
|
+
return argsSchema;
|
|
3316
|
+
}
|
|
3317
|
+
const inputSchema = schema.inputSchema ?? schema.input_schema;
|
|
3318
|
+
if (!inputSchema || typeof inputSchema !== "object" || Array.isArray(inputSchema)) {
|
|
3319
|
+
return {};
|
|
3320
|
+
}
|
|
3321
|
+
const record = inputSchema;
|
|
3322
|
+
const properties = record.properties;
|
|
3323
|
+
if (!properties || typeof properties !== "object" || Array.isArray(properties)) {
|
|
3324
|
+
return {};
|
|
3325
|
+
}
|
|
3326
|
+
const required = new Set(Array.isArray(record.required) ? record.required.filter((item) => typeof item === "string") : []);
|
|
3327
|
+
return Object.fromEntries(
|
|
3328
|
+
Object.entries(properties).map(([name, value]) => {
|
|
3329
|
+
const property = value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3330
|
+
const spec = {
|
|
3331
|
+
type: normalizeJsonSchemaType(property.type),
|
|
3332
|
+
required: required.has(name)
|
|
3333
|
+
};
|
|
3334
|
+
if (typeof property.description === "string") {
|
|
3335
|
+
spec.description = property.description;
|
|
3336
|
+
}
|
|
3337
|
+
if ("default" in property) {
|
|
3338
|
+
spec.default = property.default;
|
|
3339
|
+
}
|
|
3340
|
+
return [name, spec];
|
|
3341
|
+
})
|
|
3342
|
+
);
|
|
3343
|
+
}
|
|
3344
|
+
function normalizeJsonSchemaType(value) {
|
|
3345
|
+
if (value === "string" || value === "number" || value === "boolean" || value === "object" || value === "array") {
|
|
3346
|
+
return value;
|
|
3347
|
+
}
|
|
3348
|
+
if (value === "integer") {
|
|
3349
|
+
return "number";
|
|
3350
|
+
}
|
|
3351
|
+
return "unknown";
|
|
3352
|
+
}
|
|
3353
|
+
function stableStringify(value) {
|
|
3354
|
+
if (Array.isArray(value)) {
|
|
3355
|
+
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
3356
|
+
}
|
|
3357
|
+
if (value && typeof value === "object") {
|
|
3358
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${stableStringify(entry)}`).join(",")}}`;
|
|
3359
|
+
}
|
|
3360
|
+
return JSON.stringify(value);
|
|
3361
|
+
}
|
|
3362
|
+
|
|
3363
|
+
// src/mcp.ts
|
|
3364
|
+
var TransportType = {
|
|
3365
|
+
STDIO: "stdio",
|
|
3366
|
+
HTTP: "http",
|
|
3367
|
+
STREAMABLE_HTTP: "streamable-http",
|
|
3368
|
+
SSE: "sse"
|
|
3369
|
+
};
|
|
3370
|
+
var MCPReadStream = Object.freeze({ kind: "MCPReadStream" });
|
|
3371
|
+
var MCPWriteStream = Object.freeze({ kind: "MCPWriteStream" });
|
|
3372
|
+
var ToolFilterContext = class {
|
|
3373
|
+
agent;
|
|
3374
|
+
serverName;
|
|
3375
|
+
server_name;
|
|
3376
|
+
runContext;
|
|
3377
|
+
run_context;
|
|
3378
|
+
constructor(options) {
|
|
3379
|
+
this.agent = options.agent;
|
|
3380
|
+
this.serverName = options.serverName ?? options.server_name ?? "";
|
|
3381
|
+
this.server_name = this.serverName;
|
|
3382
|
+
this.runContext = options.runContext ?? options.run_context ?? null;
|
|
3383
|
+
this.run_context = this.runContext;
|
|
3384
|
+
}
|
|
3385
|
+
};
|
|
3386
|
+
var ToolFilter = Object.freeze({ kind: "ToolFilter" });
|
|
3387
|
+
var StaticToolFilter = class {
|
|
3388
|
+
allowedToolNames;
|
|
3389
|
+
allowed_tool_names;
|
|
3390
|
+
blockedToolNames;
|
|
3391
|
+
blocked_tool_names;
|
|
3392
|
+
constructor(options = {}) {
|
|
3393
|
+
this.allowedToolNames = new Set(options.allowedToolNames ?? options.allowed_tool_names ?? []);
|
|
3394
|
+
this.allowed_tool_names = this.allowedToolNames;
|
|
3395
|
+
this.blockedToolNames = new Set(options.blockedToolNames ?? options.blocked_tool_names ?? []);
|
|
3396
|
+
this.blocked_tool_names = this.blockedToolNames;
|
|
3397
|
+
}
|
|
3398
|
+
filter(tool) {
|
|
3399
|
+
const toolName = typeof tool.name === "string" ? tool.name : "";
|
|
3400
|
+
if (this.blockedToolNames.size > 0 && this.blockedToolNames.has(toolName)) {
|
|
3401
|
+
return false;
|
|
3402
|
+
}
|
|
3403
|
+
if (this.allowedToolNames.size > 0) {
|
|
3404
|
+
return this.allowedToolNames.has(toolName);
|
|
3405
|
+
}
|
|
3406
|
+
return true;
|
|
3407
|
+
}
|
|
3408
|
+
call(tool) {
|
|
3409
|
+
return this.filter(tool);
|
|
3410
|
+
}
|
|
3411
|
+
__call__(tool) {
|
|
3412
|
+
return this.filter(tool);
|
|
3413
|
+
}
|
|
3414
|
+
};
|
|
3415
|
+
function createStaticToolFilter(allowedToolNames = null, blockedToolNames = null) {
|
|
3416
|
+
const filter = new StaticToolFilter({ allowedToolNames, blockedToolNames });
|
|
3417
|
+
return (tool) => filter.filter(tool);
|
|
3418
|
+
}
|
|
3419
|
+
var create_static_tool_filter = createStaticToolFilter;
|
|
3420
|
+
function createDynamicToolFilter(filterFunc) {
|
|
3421
|
+
return filterFunc;
|
|
3422
|
+
}
|
|
3423
|
+
var create_dynamic_tool_filter = createDynamicToolFilter;
|
|
3424
|
+
var MCPServerStdio = class {
|
|
3425
|
+
command;
|
|
3426
|
+
args;
|
|
3427
|
+
env;
|
|
3428
|
+
toolFilter;
|
|
3429
|
+
tool_filter;
|
|
3430
|
+
cacheToolsList;
|
|
3431
|
+
cache_tools_list;
|
|
3432
|
+
constructor(options) {
|
|
3433
|
+
this.command = options.command;
|
|
3434
|
+
this.args = options.args ? [...options.args] : [];
|
|
3435
|
+
this.env = options.env ? { ...options.env } : null;
|
|
3436
|
+
this.toolFilter = options.toolFilter ?? options.tool_filter ?? null;
|
|
3437
|
+
this.tool_filter = this.toolFilter;
|
|
3438
|
+
this.cacheToolsList = options.cacheToolsList ?? options.cache_tools_list ?? false;
|
|
3439
|
+
this.cache_tools_list = this.cacheToolsList;
|
|
3440
|
+
}
|
|
3441
|
+
};
|
|
3442
|
+
var MCPServerHTTP = class {
|
|
3443
|
+
url;
|
|
3444
|
+
headers;
|
|
3445
|
+
streamable;
|
|
3446
|
+
toolFilter;
|
|
3447
|
+
tool_filter;
|
|
3448
|
+
cacheToolsList;
|
|
3449
|
+
cache_tools_list;
|
|
3450
|
+
constructor(options) {
|
|
3451
|
+
this.url = options.url;
|
|
3452
|
+
this.headers = options.headers ? { ...options.headers } : null;
|
|
3453
|
+
this.streamable = options.streamable ?? true;
|
|
3454
|
+
this.toolFilter = options.toolFilter ?? options.tool_filter ?? null;
|
|
3455
|
+
this.tool_filter = this.toolFilter;
|
|
3456
|
+
this.cacheToolsList = options.cacheToolsList ?? options.cache_tools_list ?? false;
|
|
3457
|
+
this.cache_tools_list = this.cacheToolsList;
|
|
3458
|
+
}
|
|
3459
|
+
};
|
|
3460
|
+
var MCPServerSSE = class {
|
|
3461
|
+
url;
|
|
3462
|
+
headers;
|
|
3463
|
+
toolFilter;
|
|
3464
|
+
tool_filter;
|
|
3465
|
+
cacheToolsList;
|
|
3466
|
+
cache_tools_list;
|
|
3467
|
+
constructor(options) {
|
|
3468
|
+
this.url = options.url;
|
|
3469
|
+
this.headers = options.headers ? { ...options.headers } : null;
|
|
3470
|
+
this.toolFilter = options.toolFilter ?? options.tool_filter ?? null;
|
|
3471
|
+
this.tool_filter = this.toolFilter;
|
|
3472
|
+
this.cacheToolsList = options.cacheToolsList ?? options.cache_tools_list ?? false;
|
|
3473
|
+
this.cache_tools_list = this.cacheToolsList;
|
|
3474
|
+
}
|
|
3475
|
+
};
|
|
3476
|
+
var MCPServerConfig = Object.freeze({ kind: "MCPServerConfig" });
|
|
3477
|
+
var BaseTransport = class {
|
|
3478
|
+
readStreamValue = null;
|
|
3479
|
+
writeStreamValue = null;
|
|
3480
|
+
connectedValue = false;
|
|
3481
|
+
sdkTransportValue = null;
|
|
3482
|
+
get transport_type() {
|
|
3483
|
+
return this.transportType;
|
|
3484
|
+
}
|
|
3485
|
+
get connected() {
|
|
3486
|
+
return this.connectedValue;
|
|
3487
|
+
}
|
|
3488
|
+
get readStream() {
|
|
3489
|
+
if (this.readStreamValue === null) {
|
|
3490
|
+
throw new Error("Transport not connected. Call connect() first.");
|
|
3491
|
+
}
|
|
3492
|
+
return this.readStreamValue;
|
|
3493
|
+
}
|
|
3494
|
+
get read_stream() {
|
|
3495
|
+
return this.readStream;
|
|
3496
|
+
}
|
|
3497
|
+
get writeStream() {
|
|
3498
|
+
if (this.writeStreamValue === null) {
|
|
3499
|
+
throw new Error("Transport not connected. Call connect() first.");
|
|
3500
|
+
}
|
|
3501
|
+
return this.writeStreamValue;
|
|
3502
|
+
}
|
|
3503
|
+
get write_stream() {
|
|
3504
|
+
return this.writeStream;
|
|
3505
|
+
}
|
|
3506
|
+
async connect() {
|
|
3507
|
+
if (this.connectedValue) {
|
|
3508
|
+
return this;
|
|
3509
|
+
}
|
|
3510
|
+
const transport = this.getSdkTransport();
|
|
3511
|
+
await transport.start();
|
|
3512
|
+
this.setStreams(transport, transport);
|
|
3513
|
+
return this;
|
|
3514
|
+
}
|
|
3515
|
+
async disconnect() {
|
|
3516
|
+
const transport = this.sdkTransportValue;
|
|
3517
|
+
this.clearStreams();
|
|
3518
|
+
if (transport) {
|
|
3519
|
+
await transport.close();
|
|
3520
|
+
}
|
|
3521
|
+
}
|
|
3522
|
+
async aenter() {
|
|
3523
|
+
return await this.connect();
|
|
3524
|
+
}
|
|
3525
|
+
async __aenter__() {
|
|
3526
|
+
return await this.aenter();
|
|
3527
|
+
}
|
|
3528
|
+
async aexit(_excType = null, _excVal = null, _excTb = null) {
|
|
3529
|
+
void _excType;
|
|
3530
|
+
void _excVal;
|
|
3531
|
+
void _excTb;
|
|
3532
|
+
await this.disconnect();
|
|
3533
|
+
}
|
|
3534
|
+
async __aexit__(excType = null, excVal = null, excTb = null) {
|
|
3535
|
+
await this.aexit(excType, excVal, excTb);
|
|
3536
|
+
}
|
|
3537
|
+
setStreams(read, write) {
|
|
3538
|
+
this.readStreamValue = read;
|
|
3539
|
+
this.writeStreamValue = write;
|
|
3540
|
+
this.connectedValue = true;
|
|
3541
|
+
}
|
|
3542
|
+
_set_streams(read, write) {
|
|
3543
|
+
this.setStreams(read, write);
|
|
3544
|
+
}
|
|
3545
|
+
clearStreams() {
|
|
3546
|
+
this.readStreamValue = null;
|
|
3547
|
+
this.writeStreamValue = null;
|
|
3548
|
+
this.connectedValue = false;
|
|
3549
|
+
}
|
|
3550
|
+
_clear_streams() {
|
|
3551
|
+
this.clearStreams();
|
|
3552
|
+
}
|
|
3553
|
+
markConnectedForClient() {
|
|
3554
|
+
const transport = this.getSdkTransport();
|
|
3555
|
+
this.setStreams(transport, transport);
|
|
3556
|
+
}
|
|
3557
|
+
clearConnectedForClient() {
|
|
3558
|
+
this.clearStreams();
|
|
3559
|
+
this.sdkTransportValue = null;
|
|
3560
|
+
}
|
|
3561
|
+
getSdkTransport() {
|
|
3562
|
+
this.sdkTransportValue ??= this.createSdkTransport();
|
|
3563
|
+
return this.sdkTransportValue;
|
|
3564
|
+
}
|
|
3565
|
+
};
|
|
3566
|
+
var HTTPTransport = class extends BaseTransport {
|
|
3567
|
+
url;
|
|
3568
|
+
headers;
|
|
3569
|
+
streamable;
|
|
3570
|
+
constructor(options, headers = null, streamable = true) {
|
|
3571
|
+
super();
|
|
3572
|
+
if (typeof options === "string") {
|
|
3573
|
+
this.url = options;
|
|
3574
|
+
this.headers = headers ? { ...headers } : {};
|
|
3575
|
+
this.streamable = streamable;
|
|
3576
|
+
} else {
|
|
3577
|
+
this.url = options.url;
|
|
3578
|
+
this.headers = options.headers ? { ...options.headers } : {};
|
|
3579
|
+
this.streamable = options.streamable ?? true;
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
get transportType() {
|
|
3583
|
+
return this.streamable ? TransportType.STREAMABLE_HTTP : TransportType.HTTP;
|
|
3584
|
+
}
|
|
3585
|
+
createSdkTransport() {
|
|
3586
|
+
const headers = { ...this.headers };
|
|
3587
|
+
const options = Object.keys(headers).length > 0 ? { requestInit: { headers } } : void 0;
|
|
3588
|
+
return new StreamableHTTPClientTransport(new URL(this.url), options);
|
|
3589
|
+
}
|
|
3590
|
+
};
|
|
3591
|
+
var SSETransport = class extends BaseTransport {
|
|
3592
|
+
url;
|
|
3593
|
+
headers;
|
|
3594
|
+
constructor(options, headers = null) {
|
|
3595
|
+
super();
|
|
3596
|
+
if (typeof options === "string") {
|
|
3597
|
+
this.url = options;
|
|
3598
|
+
this.headers = headers ? { ...headers } : {};
|
|
3599
|
+
} else {
|
|
3600
|
+
this.url = options.url;
|
|
3601
|
+
this.headers = options.headers ? { ...options.headers } : {};
|
|
3602
|
+
}
|
|
3603
|
+
}
|
|
3604
|
+
get transportType() {
|
|
3605
|
+
return TransportType.SSE;
|
|
3606
|
+
}
|
|
3607
|
+
createSdkTransport() {
|
|
3608
|
+
const headers = { ...this.headers };
|
|
3609
|
+
const options = Object.keys(headers).length > 0 ? {
|
|
3610
|
+
requestInit: { headers },
|
|
3611
|
+
eventSourceInit: {
|
|
3612
|
+
fetch: (url, init) => fetch(url, { ...init, headers: { ...headers, ...headersFromInit(init?.headers) } })
|
|
3613
|
+
}
|
|
3614
|
+
} : void 0;
|
|
3615
|
+
return new SSEClientTransport(new URL(this.url), options);
|
|
3616
|
+
}
|
|
3617
|
+
};
|
|
3618
|
+
var StdioTransport = class extends BaseTransport {
|
|
3619
|
+
command;
|
|
3620
|
+
args;
|
|
3621
|
+
env;
|
|
3622
|
+
constructor(options, args = null, env = null) {
|
|
3623
|
+
super();
|
|
3624
|
+
if (typeof options === "string") {
|
|
3625
|
+
this.command = options;
|
|
3626
|
+
this.args = args ? [...args] : [];
|
|
3627
|
+
this.env = env ? { ...env } : {};
|
|
3628
|
+
} else {
|
|
3629
|
+
this.command = options.command;
|
|
3630
|
+
this.args = options.args ? [...options.args] : [];
|
|
3631
|
+
this.env = options.env ? { ...options.env } : {};
|
|
3632
|
+
}
|
|
3633
|
+
}
|
|
3634
|
+
get transportType() {
|
|
3635
|
+
return TransportType.STDIO;
|
|
3636
|
+
}
|
|
3637
|
+
createSdkTransport() {
|
|
3638
|
+
return new StdioClientTransport({
|
|
3639
|
+
command: this.command,
|
|
3640
|
+
args: [...this.args],
|
|
3641
|
+
env: { ...this.env }
|
|
3642
|
+
});
|
|
3643
|
+
}
|
|
3644
|
+
};
|
|
3645
|
+
function isMCPServerConfig(value) {
|
|
3646
|
+
return value instanceof MCPServerStdio || value instanceof MCPServerHTTP || value instanceof MCPServerSSE;
|
|
3647
|
+
}
|
|
3648
|
+
var is_mcp_server_config = isMCPServerConfig;
|
|
3649
|
+
var MCP_CONNECTION_TIMEOUT = 30;
|
|
3650
|
+
var MCP_TOOL_EXECUTION_TIMEOUT = 30;
|
|
3651
|
+
var MCP_DISCOVERY_TIMEOUT = 30;
|
|
3652
|
+
var MCP_MAX_RETRIES = 3;
|
|
3653
|
+
var _MCPToolResult = class {
|
|
3654
|
+
content;
|
|
3655
|
+
isError;
|
|
3656
|
+
is_error;
|
|
3657
|
+
constructor(content, isError = false) {
|
|
3658
|
+
this.content = content;
|
|
3659
|
+
this.isError = isError;
|
|
3660
|
+
this.is_error = isError;
|
|
3661
|
+
}
|
|
3662
|
+
};
|
|
3663
|
+
var MCP_SCHEMA_CACHE_TTL_MS = 3e5;
|
|
3664
|
+
var mcpSchemaCache = /* @__PURE__ */ new Map();
|
|
3665
|
+
var MCPClient = class {
|
|
3666
|
+
transport;
|
|
3667
|
+
connectTimeout;
|
|
3668
|
+
connect_timeout;
|
|
3669
|
+
executionTimeout;
|
|
3670
|
+
execution_timeout;
|
|
3671
|
+
discoveryTimeout;
|
|
3672
|
+
discovery_timeout;
|
|
3673
|
+
maxRetries;
|
|
3674
|
+
max_retries;
|
|
3675
|
+
cacheToolsList;
|
|
3676
|
+
cache_tools_list;
|
|
3677
|
+
client = null;
|
|
3678
|
+
initialized = false;
|
|
3679
|
+
wasConnected = false;
|
|
3680
|
+
constructor(transport, options = {}) {
|
|
3681
|
+
this.transport = transport;
|
|
3682
|
+
this.connectTimeout = options.connectTimeout ?? options.connect_timeout ?? MCP_CONNECTION_TIMEOUT;
|
|
3683
|
+
this.connect_timeout = this.connectTimeout;
|
|
3684
|
+
this.executionTimeout = options.executionTimeout ?? options.execution_timeout ?? MCP_TOOL_EXECUTION_TIMEOUT;
|
|
3685
|
+
this.execution_timeout = this.executionTimeout;
|
|
3686
|
+
this.discoveryTimeout = options.discoveryTimeout ?? options.discovery_timeout ?? MCP_DISCOVERY_TIMEOUT;
|
|
3687
|
+
this.discovery_timeout = this.discoveryTimeout;
|
|
3688
|
+
this.maxRetries = options.maxRetries ?? options.max_retries ?? MCP_MAX_RETRIES;
|
|
3689
|
+
this.max_retries = this.maxRetries;
|
|
3690
|
+
this.cacheToolsList = options.cacheToolsList ?? options.cache_tools_list ?? false;
|
|
3691
|
+
this.cache_tools_list = this.cacheToolsList;
|
|
3692
|
+
}
|
|
3693
|
+
get connected() {
|
|
3694
|
+
return this.initialized;
|
|
3695
|
+
}
|
|
3696
|
+
get session() {
|
|
3697
|
+
if (!this.client || !this.initialized) {
|
|
3698
|
+
throw new Error("Client not connected. Call connect() first.");
|
|
3699
|
+
}
|
|
3700
|
+
return this.client;
|
|
3701
|
+
}
|
|
3702
|
+
async connect() {
|
|
3703
|
+
if (this.connected) {
|
|
3704
|
+
return this;
|
|
3705
|
+
}
|
|
3706
|
+
const [serverName, serverUrl, transportType] = this.getServerInfo();
|
|
3707
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
3708
|
+
const isReconnect = this.wasConnected;
|
|
3709
|
+
crewaiEventBus.emit(this, new MCPConnectionStartedEvent({
|
|
3710
|
+
server_name: serverName,
|
|
3711
|
+
server_url: serverUrl,
|
|
3712
|
+
transport_type: transportType,
|
|
3713
|
+
is_reconnect: isReconnect,
|
|
3714
|
+
connect_timeout: this.connectTimeout
|
|
3715
|
+
}));
|
|
3716
|
+
try {
|
|
3717
|
+
const client = new Client({ name: "@crewai-ts/core", version: "0.0.0" }, { capabilities: {} });
|
|
3718
|
+
await withTimeout(client.connect(this.transport.getSdkTransport()), this.connectTimeout, "MCP connection timed out");
|
|
3719
|
+
this.client = client;
|
|
3720
|
+
this.initialized = true;
|
|
3721
|
+
this.wasConnected = true;
|
|
3722
|
+
this.transport.markConnectedForClient();
|
|
3723
|
+
const completedAt = /* @__PURE__ */ new Date();
|
|
3724
|
+
crewaiEventBus.emit(this, new MCPConnectionCompletedEvent({
|
|
3725
|
+
server_name: serverName,
|
|
3726
|
+
server_url: serverUrl,
|
|
3727
|
+
transport_type: transportType,
|
|
3728
|
+
started_at: startedAt,
|
|
3729
|
+
completed_at: completedAt,
|
|
3730
|
+
connection_duration_ms: completedAt.getTime() - startedAt.getTime(),
|
|
3731
|
+
is_reconnect: isReconnect
|
|
3732
|
+
}));
|
|
3733
|
+
return this;
|
|
3734
|
+
} catch (error) {
|
|
3735
|
+
await this.cleanupOnError();
|
|
3736
|
+
const failedAt = /* @__PURE__ */ new Date();
|
|
3737
|
+
crewaiEventBus.emit(this, new MCPConnectionFailedEvent({
|
|
3738
|
+
server_name: serverName,
|
|
3739
|
+
server_url: serverUrl,
|
|
3740
|
+
transport_type: transportType,
|
|
3741
|
+
error,
|
|
3742
|
+
error_type: classifyMCPError(error),
|
|
3743
|
+
started_at: startedAt,
|
|
3744
|
+
failed_at: failedAt
|
|
3745
|
+
}));
|
|
3746
|
+
throw new Error(`Failed to connect to MCP server: ${formatMCPError(error)}`, { cause: error });
|
|
3747
|
+
}
|
|
3748
|
+
}
|
|
3749
|
+
async disconnect() {
|
|
3750
|
+
if (!this.client && !this.transport.connected) {
|
|
3751
|
+
return;
|
|
3752
|
+
}
|
|
3753
|
+
try {
|
|
3754
|
+
await this.client?.close();
|
|
3755
|
+
} finally {
|
|
3756
|
+
this.client = null;
|
|
3757
|
+
this.initialized = false;
|
|
3758
|
+
this.transport.clearConnectedForClient();
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
async aenter() {
|
|
3762
|
+
return await this.connect();
|
|
3763
|
+
}
|
|
3764
|
+
async __aenter__() {
|
|
3765
|
+
return await this.aenter();
|
|
3766
|
+
}
|
|
3767
|
+
async aexit(_excType = null, _excVal = null, _excTb = null) {
|
|
3768
|
+
void _excType;
|
|
3769
|
+
void _excVal;
|
|
3770
|
+
void _excTb;
|
|
3771
|
+
await this.disconnect();
|
|
3772
|
+
}
|
|
3773
|
+
async __aexit__(excType = null, excVal = null, excTb = null) {
|
|
3774
|
+
await this.aexit(excType, excVal, excTb);
|
|
3775
|
+
}
|
|
3776
|
+
async listTools(useCache = null) {
|
|
3777
|
+
if (!this.connected) {
|
|
3778
|
+
await this.connect();
|
|
3779
|
+
}
|
|
3780
|
+
const shouldUseCache = useCache ?? this.cacheToolsList;
|
|
3781
|
+
const cacheKey = this.getCacheKey("tools");
|
|
3782
|
+
if (shouldUseCache) {
|
|
3783
|
+
const cached = mcpSchemaCache.get(cacheKey);
|
|
3784
|
+
if (cached && Date.now() - cached.createdAt < MCP_SCHEMA_CACHE_TTL_MS) {
|
|
3785
|
+
return cached.tools.map((tool) => ({ ...tool }));
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
const tools = await this.retryOperation(async () => await this.listToolsImpl(), this.discoveryTimeout);
|
|
3789
|
+
if (shouldUseCache) {
|
|
3790
|
+
mcpSchemaCache.set(cacheKey, { tools, createdAt: Date.now() });
|
|
3791
|
+
}
|
|
3792
|
+
return tools;
|
|
3793
|
+
}
|
|
3794
|
+
async list_tools(useCache = null) {
|
|
3795
|
+
return await this.listTools(useCache);
|
|
3796
|
+
}
|
|
3797
|
+
async listToolsImpl() {
|
|
3798
|
+
const result = await withTimeout(this.session.listTools(), this.discoveryTimeout, "MCP tool discovery timed out");
|
|
3799
|
+
return result.tools.map((tool) => ({
|
|
3800
|
+
name: sanitizeToolName(tool.name),
|
|
3801
|
+
original_name: tool.name,
|
|
3802
|
+
description: tool.description ?? "",
|
|
3803
|
+
inputSchema: tool.inputSchema,
|
|
3804
|
+
...tool.outputSchema ? { outputSchema: tool.outputSchema } : {},
|
|
3805
|
+
...tool.annotations ? { annotations: tool.annotations } : {}
|
|
3806
|
+
}));
|
|
3807
|
+
}
|
|
3808
|
+
async _list_tools_impl() {
|
|
3809
|
+
return await this.listToolsImpl();
|
|
3810
|
+
}
|
|
3811
|
+
async callTool(toolName, args = null) {
|
|
3812
|
+
if (!this.connected) {
|
|
3813
|
+
await this.connect();
|
|
3814
|
+
}
|
|
3815
|
+
const cleanedArgs = cleanToolArguments(args ?? {});
|
|
3816
|
+
const [serverName, serverUrl, transportType] = this.getServerInfo();
|
|
3817
|
+
const startedAt = /* @__PURE__ */ new Date();
|
|
3818
|
+
crewaiEventBus.emit(this, new MCPToolExecutionStartedEvent({
|
|
3819
|
+
server_name: serverName,
|
|
3820
|
+
server_url: serverUrl,
|
|
3821
|
+
transport_type: transportType,
|
|
3822
|
+
tool_name: toolName,
|
|
3823
|
+
tool_args: cleanedArgs
|
|
3824
|
+
}));
|
|
3825
|
+
try {
|
|
3826
|
+
const toolResult = await this.retryOperation(
|
|
3827
|
+
async () => await this.callToolImpl(toolName, cleanedArgs),
|
|
3828
|
+
this.executionTimeout
|
|
3829
|
+
);
|
|
3830
|
+
const content = toolResult.content;
|
|
3831
|
+
const finishedAt = /* @__PURE__ */ new Date();
|
|
3832
|
+
if (toolResult.isError) {
|
|
3833
|
+
crewaiEventBus.emit(this, new MCPToolExecutionFailedEvent({
|
|
3834
|
+
server_name: serverName,
|
|
3835
|
+
server_url: serverUrl,
|
|
3836
|
+
transport_type: transportType,
|
|
3837
|
+
tool_name: toolName,
|
|
3838
|
+
tool_args: cleanedArgs,
|
|
3839
|
+
error: content,
|
|
3840
|
+
error_type: "tool_error",
|
|
3841
|
+
started_at: startedAt,
|
|
3842
|
+
failed_at: finishedAt
|
|
3843
|
+
}));
|
|
3844
|
+
} else {
|
|
3845
|
+
crewaiEventBus.emit(this, new MCPToolExecutionCompletedEvent({
|
|
3846
|
+
server_name: serverName,
|
|
3847
|
+
server_url: serverUrl,
|
|
3848
|
+
transport_type: transportType,
|
|
3849
|
+
tool_name: toolName,
|
|
3850
|
+
tool_args: cleanedArgs,
|
|
3851
|
+
result: content,
|
|
3852
|
+
started_at: startedAt,
|
|
3853
|
+
completed_at: finishedAt,
|
|
3854
|
+
execution_duration_ms: finishedAt.getTime() - startedAt.getTime()
|
|
3855
|
+
}));
|
|
3856
|
+
}
|
|
3857
|
+
return content;
|
|
3858
|
+
} catch (error) {
|
|
3859
|
+
const failedAt = /* @__PURE__ */ new Date();
|
|
3860
|
+
crewaiEventBus.emit(this, new MCPToolExecutionFailedEvent({
|
|
3861
|
+
server_name: serverName,
|
|
3862
|
+
server_url: serverUrl,
|
|
3863
|
+
transport_type: transportType,
|
|
3864
|
+
tool_name: toolName,
|
|
3865
|
+
tool_args: cleanedArgs,
|
|
3866
|
+
error,
|
|
3867
|
+
error_type: classifyMCPError(error),
|
|
3868
|
+
started_at: startedAt,
|
|
3869
|
+
failed_at: failedAt
|
|
3870
|
+
}));
|
|
3871
|
+
throw error;
|
|
3872
|
+
}
|
|
3873
|
+
}
|
|
3874
|
+
async call_tool(toolName, args = null) {
|
|
3875
|
+
return await this.callTool(toolName, args);
|
|
3876
|
+
}
|
|
3877
|
+
cleanToolArguments(args) {
|
|
3878
|
+
return cleanToolArguments(args);
|
|
3879
|
+
}
|
|
3880
|
+
_clean_tool_arguments(args) {
|
|
3881
|
+
return this.cleanToolArguments(args);
|
|
3882
|
+
}
|
|
3883
|
+
async callToolImpl(toolName, args) {
|
|
3884
|
+
const result = await withTimeout(
|
|
3885
|
+
this.session.callTool({ name: toolName, arguments: args }),
|
|
3886
|
+
this.executionTimeout,
|
|
3887
|
+
"MCP tool execution timed out"
|
|
3888
|
+
);
|
|
3889
|
+
return new _MCPToolResult(stringifyMCPToolResult(result), isErrorMCPToolResult(result));
|
|
3890
|
+
}
|
|
3891
|
+
async _call_tool_impl(toolName, args) {
|
|
3892
|
+
return await this.callToolImpl(toolName, args);
|
|
3893
|
+
}
|
|
3894
|
+
emitConnectionFailed(serverName, serverUrl, transportType, error, errorType, startedAt) {
|
|
3895
|
+
crewaiEventBus.emit(this, new MCPConnectionFailedEvent({
|
|
3896
|
+
server_name: serverName,
|
|
3897
|
+
server_url: serverUrl,
|
|
3898
|
+
transport_type: transportType,
|
|
3899
|
+
error,
|
|
3900
|
+
error_type: errorType,
|
|
3901
|
+
started_at: startedAt,
|
|
3902
|
+
failed_at: /* @__PURE__ */ new Date()
|
|
3903
|
+
}));
|
|
3904
|
+
}
|
|
3905
|
+
_emit_connection_failed(serverName, serverUrl, transportType, error, errorType, startedAt) {
|
|
3906
|
+
this.emitConnectionFailed(serverName, serverUrl, transportType, error, errorType, startedAt);
|
|
3907
|
+
}
|
|
3908
|
+
async listPrompts() {
|
|
3909
|
+
if (!this.connected) {
|
|
3910
|
+
await this.connect();
|
|
3911
|
+
}
|
|
3912
|
+
return await this.retryOperation(async () => await this.listPromptsImpl(), this.discoveryTimeout);
|
|
3913
|
+
}
|
|
3914
|
+
async listPromptsImpl() {
|
|
3915
|
+
const result = await withTimeout(this.session.listPrompts(), this.discoveryTimeout, "MCP prompt discovery timed out");
|
|
3916
|
+
return result.prompts.map((prompt) => ({
|
|
3917
|
+
name: typeof prompt.name === "string" ? prompt.name : "",
|
|
3918
|
+
description: typeof prompt.description === "string" ? prompt.description : "",
|
|
3919
|
+
arguments: Array.isArray(prompt.arguments) ? prompt.arguments : []
|
|
3920
|
+
}));
|
|
3921
|
+
}
|
|
3922
|
+
async _list_prompts_impl() {
|
|
3923
|
+
return await this.listPromptsImpl();
|
|
3924
|
+
}
|
|
3925
|
+
async list_prompts() {
|
|
3926
|
+
return await this.listPrompts();
|
|
3927
|
+
}
|
|
3928
|
+
async getPrompt(name, args = null) {
|
|
3929
|
+
if (!this.connected) {
|
|
3930
|
+
await this.connect();
|
|
3931
|
+
}
|
|
3932
|
+
const argumentsObject = args ?? {};
|
|
3933
|
+
return await this.retryOperation(
|
|
3934
|
+
async () => await this.getPromptImpl(name, argumentsObject),
|
|
3935
|
+
this.executionTimeout
|
|
3936
|
+
);
|
|
3937
|
+
}
|
|
3938
|
+
async getPromptImpl(name, args) {
|
|
3939
|
+
const result = await withTimeout(
|
|
3940
|
+
this.session.getPrompt({ name, arguments: args }),
|
|
3941
|
+
this.executionTimeout,
|
|
3942
|
+
"MCP prompt retrieval timed out"
|
|
3943
|
+
);
|
|
3944
|
+
const messages = isPlainRecord(result) && Array.isArray(result.messages) ? result.messages.map((message) => normalizePromptMessage(message)) : [];
|
|
3945
|
+
return {
|
|
3946
|
+
name,
|
|
3947
|
+
messages,
|
|
3948
|
+
arguments: args
|
|
3949
|
+
};
|
|
3950
|
+
}
|
|
3951
|
+
async get_prompt(name, args = null) {
|
|
3952
|
+
return await this.getPrompt(name, args);
|
|
3953
|
+
}
|
|
3954
|
+
async _get_prompt_impl(name, args) {
|
|
3955
|
+
return await this.getPromptImpl(name, args);
|
|
3956
|
+
}
|
|
3957
|
+
async listResources() {
|
|
3958
|
+
if (!this.connected) {
|
|
3959
|
+
await this.connect();
|
|
3960
|
+
}
|
|
3961
|
+
const result = await this.retryOperation(async () => await this.session.listResources());
|
|
3962
|
+
return result.resources.map((resource) => ({ ...resource }));
|
|
3963
|
+
}
|
|
3964
|
+
async list_resources() {
|
|
3965
|
+
return await this.listResources();
|
|
3966
|
+
}
|
|
3967
|
+
async readResource(uri) {
|
|
3968
|
+
if (!this.connected) {
|
|
3969
|
+
await this.connect();
|
|
3970
|
+
}
|
|
3971
|
+
return await this.retryOperation(async () => await this.session.readResource({ uri }));
|
|
3972
|
+
}
|
|
3973
|
+
async read_resource(uri) {
|
|
3974
|
+
return await this.readResource(uri);
|
|
3975
|
+
}
|
|
3976
|
+
getServerInfo() {
|
|
3977
|
+
if (this.transport instanceof StdioTransport) {
|
|
3978
|
+
return [[this.transport.command, ...this.transport.args].join(" "), null, this.transport.transportType];
|
|
3979
|
+
}
|
|
3980
|
+
if (this.transport instanceof HTTPTransport || this.transport instanceof SSETransport) {
|
|
3981
|
+
return [this.transport.url, this.transport.url, this.transport.transportType];
|
|
3982
|
+
}
|
|
3983
|
+
return ["Unknown MCP Server", null, this.transport.transportType];
|
|
3984
|
+
}
|
|
3985
|
+
_get_server_info() {
|
|
3986
|
+
return this.getServerInfo();
|
|
3987
|
+
}
|
|
3988
|
+
getCacheKey(kind) {
|
|
3989
|
+
const [serverName, serverUrl, transportType] = this.getServerInfo();
|
|
3990
|
+
return JSON.stringify([kind, transportType, serverName, serverUrl]);
|
|
3991
|
+
}
|
|
3992
|
+
_get_cache_key(kind) {
|
|
3993
|
+
return this.getCacheKey(kind);
|
|
3994
|
+
}
|
|
3995
|
+
async retryOperation(operation, timeout = null) {
|
|
3996
|
+
let lastError;
|
|
3997
|
+
for (let attempt = 0; attempt < this.maxRetries; attempt += 1) {
|
|
3998
|
+
try {
|
|
3999
|
+
return timeout && timeout > 0 ? await withTimeout(operation(), timeout, `MCP operation timed out`) : await operation();
|
|
4000
|
+
} catch (error) {
|
|
4001
|
+
const errorMessage = formatMCPError(error).toLowerCase();
|
|
4002
|
+
if (errorMessage.includes("authentication") || errorMessage.includes("unauthorized")) {
|
|
4003
|
+
throw new Error(`Authentication failed: ${formatMCPError(error)}`, { cause: error });
|
|
4004
|
+
}
|
|
4005
|
+
if (errorMessage.includes("not found")) {
|
|
4006
|
+
throw new Error(`Resource not found: ${formatMCPError(error)}`, { cause: error });
|
|
4007
|
+
}
|
|
4008
|
+
lastError = error;
|
|
4009
|
+
if (attempt < this.maxRetries - 1) {
|
|
4010
|
+
await delay(Math.min(100 * 2 ** attempt, 1e3));
|
|
4011
|
+
}
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
throw lastError;
|
|
4015
|
+
}
|
|
4016
|
+
async _retry_operation(operation, timeout = null) {
|
|
4017
|
+
return await this.retryOperation(operation, timeout);
|
|
4018
|
+
}
|
|
4019
|
+
async cleanupOnError() {
|
|
4020
|
+
this.client = null;
|
|
4021
|
+
this.initialized = false;
|
|
4022
|
+
await this.transport.disconnect();
|
|
4023
|
+
}
|
|
4024
|
+
async _cleanup_on_error() {
|
|
4025
|
+
await this.cleanupOnError();
|
|
4026
|
+
}
|
|
4027
|
+
};
|
|
4028
|
+
var MCPToolResolver = class _MCPToolResolver {
|
|
4029
|
+
agent;
|
|
4030
|
+
logger;
|
|
4031
|
+
clientsValue = [];
|
|
4032
|
+
constructor(optionsOrAgent = {}, logger = null) {
|
|
4033
|
+
if (isResolverOptions(optionsOrAgent)) {
|
|
4034
|
+
this.agent = optionsOrAgent.agent;
|
|
4035
|
+
this.logger = optionsOrAgent.logger ?? null;
|
|
4036
|
+
} else {
|
|
4037
|
+
this.agent = optionsOrAgent;
|
|
4038
|
+
this.logger = logger;
|
|
4039
|
+
}
|
|
4040
|
+
}
|
|
4041
|
+
get clients() {
|
|
4042
|
+
return [...this.clientsValue];
|
|
4043
|
+
}
|
|
4044
|
+
async resolve(mcps) {
|
|
4045
|
+
if (!mcps) {
|
|
4046
|
+
return [];
|
|
4047
|
+
}
|
|
4048
|
+
const tools = [];
|
|
4049
|
+
const ampRefs = [];
|
|
4050
|
+
for (const config of mcps) {
|
|
4051
|
+
if (typeof config === "string") {
|
|
4052
|
+
if (config.startsWith("https://")) {
|
|
4053
|
+
tools.push(...await this.resolveExternal(config));
|
|
4054
|
+
} else {
|
|
4055
|
+
ampRefs.push(this.parseAmpRef(config));
|
|
4056
|
+
}
|
|
4057
|
+
continue;
|
|
4058
|
+
}
|
|
4059
|
+
tools.push(...await this.resolveNative(config));
|
|
4060
|
+
}
|
|
4061
|
+
if (ampRefs.length > 0) {
|
|
4062
|
+
const [ampTools, ampClients] = await this._resolve_amp(ampRefs);
|
|
4063
|
+
tools.push(...ampTools);
|
|
4064
|
+
this.clientsValue.push(...ampClients);
|
|
4065
|
+
}
|
|
4066
|
+
return tools;
|
|
4067
|
+
}
|
|
4068
|
+
async cleanup() {
|
|
4069
|
+
const clients = this.clientsValue.splice(0);
|
|
4070
|
+
for (const client of clients) {
|
|
4071
|
+
try {
|
|
4072
|
+
await client.disconnect();
|
|
4073
|
+
} catch (error) {
|
|
4074
|
+
this.log("error", `Error during MCP client cleanup: ${formatMCPError(error)}`);
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
}
|
|
4078
|
+
async disconnectAll() {
|
|
4079
|
+
await this.cleanup();
|
|
4080
|
+
}
|
|
4081
|
+
async _disconnect_all() {
|
|
4082
|
+
await this.disconnectAll();
|
|
4083
|
+
}
|
|
4084
|
+
static parseAmpRef(mcpConfig) {
|
|
4085
|
+
const bare = mcpConfig.startsWith("crewai-amp:") ? mcpConfig.slice("crewai-amp:".length) : mcpConfig;
|
|
4086
|
+
const [slug = "", specificTool = ""] = bare.split("#", 2);
|
|
4087
|
+
return [slug, specificTool || null];
|
|
4088
|
+
}
|
|
4089
|
+
static _parse_amp_ref(mcpConfig) {
|
|
4090
|
+
return _MCPToolResolver.parseAmpRef(mcpConfig);
|
|
4091
|
+
}
|
|
4092
|
+
parseAmpRef(mcpConfig) {
|
|
4093
|
+
return _MCPToolResolver.parseAmpRef(mcpConfig);
|
|
4094
|
+
}
|
|
4095
|
+
_parse_amp_ref(mcpConfig) {
|
|
4096
|
+
return this.parseAmpRef(mcpConfig);
|
|
4097
|
+
}
|
|
4098
|
+
fetchAmpMcpConfigs(slugs) {
|
|
4099
|
+
void slugs;
|
|
4100
|
+
this.log("debug", "AMP MCP config fetching is not available in the local TypeScript runtime.");
|
|
4101
|
+
return {};
|
|
4102
|
+
}
|
|
4103
|
+
_fetch_amp_mcp_configs(slugs) {
|
|
4104
|
+
return this.fetchAmpMcpConfigs(slugs);
|
|
4105
|
+
}
|
|
4106
|
+
async resolveAmp(ampRefs) {
|
|
4107
|
+
const uniqueSlugs = [...new Set(ampRefs.map(([slug]) => slug))];
|
|
4108
|
+
const ampConfigs = this._fetch_amp_mcp_configs(uniqueSlugs);
|
|
4109
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
4110
|
+
const clients = [];
|
|
4111
|
+
for (const slug of uniqueSlugs) {
|
|
4112
|
+
const config = ampConfigs[slug];
|
|
4113
|
+
if (!isPlainRecord(config)) {
|
|
4114
|
+
crewaiEventBus.emit(this, new MCPConfigFetchFailedEvent({
|
|
4115
|
+
slug,
|
|
4116
|
+
error: `Config for '${slug}' not found. Make sure it is connected in your account.`,
|
|
4117
|
+
error_type: "not_connected"
|
|
4118
|
+
}));
|
|
4119
|
+
continue;
|
|
4120
|
+
}
|
|
4121
|
+
try {
|
|
4122
|
+
const nativeResult = await this._resolve_native(this._build_mcp_config_from_dict(config));
|
|
4123
|
+
resolved.set(slug, nativeResult);
|
|
4124
|
+
clients.push(...nativeResult[1]);
|
|
4125
|
+
} catch (error) {
|
|
4126
|
+
crewaiEventBus.emit(this, new MCPConfigFetchFailedEvent({
|
|
4127
|
+
slug,
|
|
4128
|
+
error: formatMCPError(error),
|
|
4129
|
+
error_type: "connection_failed"
|
|
4130
|
+
}));
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4133
|
+
const tools = [];
|
|
4134
|
+
for (const [slug, specificTool] of ampRefs) {
|
|
4135
|
+
const cached = resolved.get(slug);
|
|
4136
|
+
if (!cached) {
|
|
4137
|
+
continue;
|
|
4138
|
+
}
|
|
4139
|
+
const [slugTools] = cached;
|
|
4140
|
+
if (!specificTool) {
|
|
4141
|
+
tools.push(...slugTools);
|
|
4142
|
+
continue;
|
|
4143
|
+
}
|
|
4144
|
+
const sanitized = sanitizeToolName(specificTool);
|
|
4145
|
+
tools.push(...slugTools.filter((tool) => tool.name.endsWith(`_${sanitized}`)));
|
|
4146
|
+
}
|
|
4147
|
+
return [tools, clients];
|
|
4148
|
+
}
|
|
4149
|
+
async _resolve_amp(ampRefs) {
|
|
4150
|
+
return await this.resolveAmp(ampRefs);
|
|
4151
|
+
}
|
|
4152
|
+
async resolveNative(config) {
|
|
4153
|
+
const serverName = serverNameForConfig(config);
|
|
4154
|
+
const clientOptions = {
|
|
4155
|
+
cacheToolsList: config.cacheToolsList,
|
|
4156
|
+
cache_tools_list: config.cache_tools_list
|
|
4157
|
+
};
|
|
4158
|
+
const discoveryClient = new MCPClient(transportForConfig(config), clientOptions);
|
|
4159
|
+
try {
|
|
4160
|
+
await discoveryClient.connect();
|
|
4161
|
+
const definitions = await discoveryClient.listTools();
|
|
4162
|
+
const tools = [];
|
|
4163
|
+
for (const definition of definitions) {
|
|
4164
|
+
if (!await passesToolFilter(config, definition, this.agent)) {
|
|
4165
|
+
continue;
|
|
4166
|
+
}
|
|
4167
|
+
const originalName = typeof definition.original_name === "string" ? definition.original_name : typeof definition.name === "string" ? definition.name : "";
|
|
4168
|
+
const sanitizedName = sanitizeToolName(originalName);
|
|
4169
|
+
tools.push(new MCPNativeTool({
|
|
4170
|
+
clientFactory: () => new MCPClient(transportForConfig(config), clientOptions),
|
|
4171
|
+
toolName: sanitizedName,
|
|
4172
|
+
originalToolName: originalName,
|
|
4173
|
+
toolSchema: definition,
|
|
4174
|
+
serverName
|
|
4175
|
+
}));
|
|
4176
|
+
}
|
|
4177
|
+
if (tools.length === 0) {
|
|
4178
|
+
this.log("warning", `No tools discovered from MCP server '${serverName}'.`);
|
|
4179
|
+
}
|
|
4180
|
+
return tools;
|
|
4181
|
+
} catch (error) {
|
|
4182
|
+
throw new Error(`Failed to get native MCP tools: ${formatMCPError(error)}`, { cause: error });
|
|
4183
|
+
} finally {
|
|
4184
|
+
await discoveryClient.disconnect();
|
|
4185
|
+
}
|
|
4186
|
+
}
|
|
4187
|
+
async _resolve_native(config) {
|
|
4188
|
+
return [await this.resolveNative(config), []];
|
|
4189
|
+
}
|
|
4190
|
+
async resolveExternal(mcpRef) {
|
|
4191
|
+
const [serverUrl, specificTool] = splitMCPRef(mcpRef);
|
|
4192
|
+
const serverName = extractServerName(serverUrl);
|
|
4193
|
+
const client = new MCPClient(new HTTPTransport({ url: serverUrl }));
|
|
4194
|
+
try {
|
|
4195
|
+
await client.connect();
|
|
4196
|
+
const definitions = await client.listTools();
|
|
4197
|
+
const sanitizedSpecificTool = specificTool ? sanitizeToolName(specificTool) : null;
|
|
4198
|
+
return definitions.filter((definition) => {
|
|
4199
|
+
const toolName = typeof definition.name === "string" ? definition.name : "";
|
|
4200
|
+
return !sanitizedSpecificTool || sanitizeToolName(toolName) === sanitizedSpecificTool;
|
|
4201
|
+
}).map((definition) => {
|
|
4202
|
+
const originalName = typeof definition.original_name === "string" ? definition.original_name : typeof definition.name === "string" ? definition.name : "";
|
|
4203
|
+
return new MCPToolWrapper({
|
|
4204
|
+
mcpServerParams: { url: serverUrl },
|
|
4205
|
+
toolName: sanitizeToolName(originalName),
|
|
4206
|
+
toolSchema: definition,
|
|
4207
|
+
serverName
|
|
4208
|
+
});
|
|
4209
|
+
});
|
|
4210
|
+
} finally {
|
|
4211
|
+
await client.disconnect();
|
|
4212
|
+
}
|
|
4213
|
+
}
|
|
4214
|
+
async _resolve_external(mcpRef) {
|
|
4215
|
+
return await this.resolveExternal(mcpRef);
|
|
4216
|
+
}
|
|
4217
|
+
static createTransport(config) {
|
|
4218
|
+
return [transportForConfig(config), serverNameForConfig(config)];
|
|
4219
|
+
}
|
|
4220
|
+
static _create_transport(config) {
|
|
4221
|
+
return _MCPToolResolver.createTransport(config);
|
|
4222
|
+
}
|
|
4223
|
+
createTransport(config) {
|
|
4224
|
+
return _MCPToolResolver.createTransport(config);
|
|
4225
|
+
}
|
|
4226
|
+
_create_transport(config) {
|
|
4227
|
+
return this.createTransport(config);
|
|
4228
|
+
}
|
|
4229
|
+
static buildMcpConfigFromDict(config) {
|
|
4230
|
+
const type = typeof config.type === "string" ? config.type : "http";
|
|
4231
|
+
const url = typeof config.url === "string" ? config.url : "";
|
|
4232
|
+
const headers = isPlainRecord(config.headers) ? stringRecord(config.headers) : null;
|
|
4233
|
+
const cacheToolsList = config.cache_tools_list === true || config.cacheToolsList === true;
|
|
4234
|
+
if (type === "sse") {
|
|
4235
|
+
return new MCPServerSSE({ url, headers, cacheToolsList });
|
|
4236
|
+
}
|
|
4237
|
+
return new MCPServerHTTP({
|
|
4238
|
+
url,
|
|
4239
|
+
headers,
|
|
4240
|
+
streamable: config.streamable !== false,
|
|
4241
|
+
cacheToolsList
|
|
4242
|
+
});
|
|
4243
|
+
}
|
|
4244
|
+
static _build_mcp_config_from_dict(config) {
|
|
4245
|
+
return _MCPToolResolver.buildMcpConfigFromDict(config);
|
|
4246
|
+
}
|
|
4247
|
+
buildMcpConfigFromDict(config) {
|
|
4248
|
+
return _MCPToolResolver.buildMcpConfigFromDict(config);
|
|
4249
|
+
}
|
|
4250
|
+
_build_mcp_config_from_dict(config) {
|
|
4251
|
+
return this.buildMcpConfigFromDict(config);
|
|
4252
|
+
}
|
|
4253
|
+
static extractServerName(serverUrl) {
|
|
4254
|
+
return extractServerName(serverUrl);
|
|
4255
|
+
}
|
|
4256
|
+
static _extract_server_name(serverUrl) {
|
|
4257
|
+
return extractServerName(serverUrl);
|
|
4258
|
+
}
|
|
4259
|
+
extractServerName(serverUrl) {
|
|
4260
|
+
return extractServerName(serverUrl);
|
|
4261
|
+
}
|
|
4262
|
+
_extract_server_name(serverUrl) {
|
|
4263
|
+
return this.extractServerName(serverUrl);
|
|
4264
|
+
}
|
|
4265
|
+
async setupClientAndListTools(client) {
|
|
4266
|
+
if (!client.connected) {
|
|
4267
|
+
await client.connect();
|
|
4268
|
+
}
|
|
4269
|
+
try {
|
|
4270
|
+
return await client.listTools();
|
|
4271
|
+
} finally {
|
|
4272
|
+
await client.disconnect();
|
|
4273
|
+
}
|
|
4274
|
+
}
|
|
4275
|
+
async _setup_client_and_list_tools(client) {
|
|
4276
|
+
return await this.setupClientAndListTools(client);
|
|
4277
|
+
}
|
|
4278
|
+
getMcpToolSchemas(serverParams) {
|
|
4279
|
+
const url = typeof serverParams.url === "string" ? serverParams.url : "";
|
|
4280
|
+
if (!url) {
|
|
4281
|
+
return {};
|
|
4282
|
+
}
|
|
4283
|
+
const cached = mcpSchemaCache.get(url);
|
|
4284
|
+
if (cached && Date.now() - cached.createdAt < MCP_SCHEMA_CACHE_TTL_MS) {
|
|
4285
|
+
return Object.fromEntries(cached.tools.map((tool) => [tool.name ?? "", tool]));
|
|
4286
|
+
}
|
|
4287
|
+
return {};
|
|
4288
|
+
}
|
|
4289
|
+
_get_mcp_tool_schemas(serverParams) {
|
|
4290
|
+
return this.getMcpToolSchemas(serverParams);
|
|
4291
|
+
}
|
|
4292
|
+
async getMcpToolSchemasAsync(serverParams) {
|
|
4293
|
+
return await Promise.resolve(this.getMcpToolSchemas(serverParams));
|
|
4294
|
+
}
|
|
4295
|
+
async _get_mcp_tool_schemas_async(serverParams) {
|
|
4296
|
+
return await this.getMcpToolSchemasAsync(serverParams);
|
|
4297
|
+
}
|
|
4298
|
+
async retryMcpDiscovery(operation, serverUrl) {
|
|
4299
|
+
return await operation(serverUrl);
|
|
4300
|
+
}
|
|
4301
|
+
async _retry_mcp_discovery(operation, serverUrl) {
|
|
4302
|
+
return await this.retryMcpDiscovery(operation, serverUrl);
|
|
4303
|
+
}
|
|
4304
|
+
async attemptMcpDiscovery(operation, serverUrl) {
|
|
4305
|
+
try {
|
|
4306
|
+
return [await operation(serverUrl), "", false];
|
|
4307
|
+
} catch (error) {
|
|
4308
|
+
const message = formatMCPError(error);
|
|
4309
|
+
const lower = message.toLowerCase();
|
|
4310
|
+
if (lower.includes("authentication") || lower.includes("unauthorized")) {
|
|
4311
|
+
return [null, `Authentication failed for MCP server: ${message}`, false];
|
|
4312
|
+
}
|
|
4313
|
+
if (lower.includes("connection") || lower.includes("network") || lower.includes("timeout")) {
|
|
4314
|
+
return [null, `Network connection failed: ${message}`, true];
|
|
4315
|
+
}
|
|
4316
|
+
return [null, `MCP discovery error: ${message}`, false];
|
|
4317
|
+
}
|
|
4318
|
+
}
|
|
4319
|
+
async _attempt_mcp_discovery(operation, serverUrl) {
|
|
4320
|
+
return await this.attemptMcpDiscovery(operation, serverUrl);
|
|
4321
|
+
}
|
|
4322
|
+
async discoverMcpToolsWithTimeout(serverUrl) {
|
|
4323
|
+
return await withTimeout(this.discoverMcpTools(serverUrl), MCP_DISCOVERY_TIMEOUT, "MCP discovery timed out");
|
|
4324
|
+
}
|
|
4325
|
+
async _discover_mcp_tools_with_timeout(serverUrl) {
|
|
4326
|
+
return await this.discoverMcpToolsWithTimeout(serverUrl);
|
|
4327
|
+
}
|
|
4328
|
+
async discoverMcpTools(serverUrl) {
|
|
4329
|
+
await Promise.resolve();
|
|
4330
|
+
void serverUrl;
|
|
4331
|
+
return {};
|
|
4332
|
+
}
|
|
4333
|
+
async _discover_mcp_tools(serverUrl) {
|
|
4334
|
+
return await this.discoverMcpTools(serverUrl);
|
|
4335
|
+
}
|
|
4336
|
+
jsonSchemaToPydantic(toolName, jsonSchema) {
|
|
4337
|
+
return {
|
|
4338
|
+
name: `${toolName.replaceAll("-", "_").replaceAll(" ", "_")}Schema`,
|
|
4339
|
+
schema: jsonSchema
|
|
4340
|
+
};
|
|
4341
|
+
}
|
|
4342
|
+
_json_schema_to_pydantic(toolName, jsonSchema) {
|
|
4343
|
+
return this.jsonSchemaToPydantic(toolName, jsonSchema);
|
|
4344
|
+
}
|
|
4345
|
+
log(level, message) {
|
|
4346
|
+
this.logger?.log(level, message);
|
|
4347
|
+
}
|
|
4348
|
+
};
|
|
4349
|
+
var mcp_schema_cache = mcpSchemaCache;
|
|
4350
|
+
function delay(ms) {
|
|
4351
|
+
return new Promise((resolve) => {
|
|
4352
|
+
setTimeout(resolve, ms);
|
|
4353
|
+
});
|
|
4354
|
+
}
|
|
4355
|
+
async function withTimeout(promise, timeoutSeconds, message) {
|
|
4356
|
+
const timeoutRef = {};
|
|
4357
|
+
try {
|
|
4358
|
+
return await Promise.race([
|
|
4359
|
+
promise,
|
|
4360
|
+
new Promise((_resolve, reject) => {
|
|
4361
|
+
timeoutRef.current = setTimeout(() => {
|
|
4362
|
+
reject(new Error(`${message} after ${String(timeoutSeconds)} seconds.`));
|
|
4363
|
+
}, timeoutSeconds * 1e3);
|
|
4364
|
+
})
|
|
4365
|
+
]);
|
|
4366
|
+
} finally {
|
|
4367
|
+
if (timeoutRef.current) {
|
|
4368
|
+
clearTimeout(timeoutRef.current);
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
}
|
|
4372
|
+
function cleanToolArguments(argumentsObject) {
|
|
4373
|
+
const cleaned = {};
|
|
4374
|
+
for (const [key, value] of Object.entries(argumentsObject)) {
|
|
4375
|
+
if (value === null || value === void 0) {
|
|
4376
|
+
continue;
|
|
4377
|
+
}
|
|
4378
|
+
if (key === "sources" && Array.isArray(value)) {
|
|
4379
|
+
const sourceValues = value;
|
|
4380
|
+
const sources = sourceValues.filter((item) => item !== null && item !== void 0).map((item) => typeof item === "string" ? { type: item } : item);
|
|
4381
|
+
if (sources.length > 0) {
|
|
4382
|
+
cleaned[key] = sources;
|
|
4383
|
+
}
|
|
4384
|
+
continue;
|
|
4385
|
+
}
|
|
4386
|
+
if (Array.isArray(value)) {
|
|
4387
|
+
const listValues = value;
|
|
4388
|
+
const values = listValues.filter((item) => item !== null && item !== void 0).map((item) => isPlainRecord(item) ? cleanToolArguments(item) : item).filter((item) => !isPlainRecord(item) || Object.keys(item).length > 0);
|
|
4389
|
+
if (values.length > 0) {
|
|
4390
|
+
cleaned[key] = values;
|
|
4391
|
+
}
|
|
4392
|
+
continue;
|
|
4393
|
+
}
|
|
4394
|
+
if (isPlainRecord(value)) {
|
|
4395
|
+
const nested = cleanToolArguments(value);
|
|
4396
|
+
if (Object.keys(nested).length > 0) {
|
|
4397
|
+
cleaned[key] = nested;
|
|
4398
|
+
}
|
|
4399
|
+
continue;
|
|
4400
|
+
}
|
|
4401
|
+
cleaned[key] = value;
|
|
4402
|
+
}
|
|
4403
|
+
return cleaned;
|
|
4404
|
+
}
|
|
4405
|
+
function isPlainRecord(value) {
|
|
4406
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
4407
|
+
}
|
|
4408
|
+
function stringRecord(value) {
|
|
4409
|
+
return Object.fromEntries(
|
|
4410
|
+
Object.entries(value).filter((entry) => typeof entry[1] === "string")
|
|
4411
|
+
);
|
|
4412
|
+
}
|
|
4413
|
+
function stringifyMCPToolResult(result) {
|
|
4414
|
+
if (isPlainRecord(result) && Array.isArray(result.content) && result.content.length > 0) {
|
|
4415
|
+
const content = result.content;
|
|
4416
|
+
const first = content[0];
|
|
4417
|
+
if (isPlainRecord(first) && typeof first.text === "string") {
|
|
4418
|
+
return first.text;
|
|
4419
|
+
}
|
|
4420
|
+
return stringifyUnknown(first);
|
|
4421
|
+
}
|
|
4422
|
+
if (isPlainRecord(result) && "toolResult" in result) {
|
|
4423
|
+
return stringifyUnknown(result.toolResult);
|
|
4424
|
+
}
|
|
4425
|
+
return stringifyUnknown(result);
|
|
4426
|
+
}
|
|
4427
|
+
function normalizePromptMessage(message) {
|
|
4428
|
+
if (!isPlainRecord(message)) {
|
|
4429
|
+
return { role: "", content: message };
|
|
4430
|
+
}
|
|
4431
|
+
return {
|
|
4432
|
+
role: typeof message.role === "string" ? message.role : "",
|
|
4433
|
+
content: message.content
|
|
4434
|
+
};
|
|
4435
|
+
}
|
|
4436
|
+
function stringifyUnknown(value) {
|
|
4437
|
+
if (typeof value === "string") {
|
|
4438
|
+
return value;
|
|
4439
|
+
}
|
|
4440
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
4441
|
+
return value.toString();
|
|
4442
|
+
}
|
|
4443
|
+
if (value === null || value === void 0) {
|
|
4444
|
+
return "";
|
|
4445
|
+
}
|
|
4446
|
+
try {
|
|
4447
|
+
return JSON.stringify(value);
|
|
4448
|
+
} catch {
|
|
4449
|
+
return Object.prototype.toString.call(value);
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
function isErrorMCPToolResult(result) {
|
|
4453
|
+
return isPlainRecord(result) && result.isError === true;
|
|
4454
|
+
}
|
|
4455
|
+
function classifyMCPError(error) {
|
|
4456
|
+
const message = formatMCPError(error).toLowerCase();
|
|
4457
|
+
if (message.includes("timeout") || message.includes("timed out")) {
|
|
4458
|
+
return "timeout";
|
|
4459
|
+
}
|
|
4460
|
+
if (message.includes("401") || message.includes("unauthorized") || message.includes("auth")) {
|
|
4461
|
+
return "authentication";
|
|
4462
|
+
}
|
|
4463
|
+
return "network";
|
|
4464
|
+
}
|
|
4465
|
+
function formatMCPError(error) {
|
|
4466
|
+
return error instanceof Error ? error.message : stringifyUnknown(error);
|
|
4467
|
+
}
|
|
4468
|
+
function isResolverOptions(value) {
|
|
4469
|
+
return !!value && typeof value === "object" && ("agent" in value || "logger" in value);
|
|
4470
|
+
}
|
|
4471
|
+
function transportForConfig(config) {
|
|
4472
|
+
if (config instanceof MCPServerStdio) {
|
|
4473
|
+
return new StdioTransport(config);
|
|
4474
|
+
}
|
|
4475
|
+
if (config instanceof MCPServerSSE) {
|
|
4476
|
+
return new SSETransport(config);
|
|
4477
|
+
}
|
|
4478
|
+
return new HTTPTransport(config);
|
|
4479
|
+
}
|
|
4480
|
+
function serverNameForConfig(config) {
|
|
4481
|
+
if (config instanceof MCPServerStdio) {
|
|
4482
|
+
return sanitizeToolName([config.command, ...config.args].join("_"));
|
|
4483
|
+
}
|
|
4484
|
+
if (config instanceof MCPServerHTTP || config instanceof MCPServerSSE) {
|
|
4485
|
+
return extractServerName(config.url);
|
|
4486
|
+
}
|
|
4487
|
+
return "mcp_server";
|
|
4488
|
+
}
|
|
4489
|
+
function extractServerName(url) {
|
|
4490
|
+
try {
|
|
4491
|
+
const parsed = new URL(url);
|
|
4492
|
+
const domain = parsed.hostname.replace(/^www\./, "").replaceAll(".", "_");
|
|
4493
|
+
const path = parsed.pathname.replaceAll("/", "_").replace(/^_+|_+$/g, "");
|
|
4494
|
+
return sanitizeToolName(path ? `${domain}_${path}` : domain);
|
|
4495
|
+
} catch {
|
|
4496
|
+
return sanitizeToolName(url.split("/").filter(Boolean).at(-1) ?? "mcp_server");
|
|
4497
|
+
}
|
|
4498
|
+
}
|
|
4499
|
+
function splitMCPRef(ref) {
|
|
4500
|
+
const markerIndex = ref.indexOf("#");
|
|
4501
|
+
if (markerIndex === -1) {
|
|
4502
|
+
return [ref, null];
|
|
4503
|
+
}
|
|
4504
|
+
return [ref.slice(0, markerIndex), ref.slice(markerIndex + 1) || null];
|
|
4505
|
+
}
|
|
4506
|
+
async function passesToolFilter(config, definition, agent) {
|
|
4507
|
+
const filter = config.toolFilter ?? config.tool_filter;
|
|
4508
|
+
if (!filter) {
|
|
4509
|
+
return true;
|
|
4510
|
+
}
|
|
4511
|
+
if (filter.length >= 2) {
|
|
4512
|
+
return await filter(
|
|
4513
|
+
new ToolFilterContext({ agent, serverName: serverNameForConfig(config) }),
|
|
4514
|
+
definition
|
|
4515
|
+
);
|
|
4516
|
+
}
|
|
4517
|
+
return await filter(definition);
|
|
4518
|
+
}
|
|
4519
|
+
function headersFromInit(headers) {
|
|
4520
|
+
if (!headers) {
|
|
4521
|
+
return {};
|
|
4522
|
+
}
|
|
4523
|
+
if (headers instanceof Headers) {
|
|
4524
|
+
return Object.fromEntries(headers.entries());
|
|
4525
|
+
}
|
|
4526
|
+
if (Array.isArray(headers)) {
|
|
4527
|
+
return Object.fromEntries(headers);
|
|
4528
|
+
}
|
|
4529
|
+
if (typeof headers === "object") {
|
|
4530
|
+
return Object.fromEntries(
|
|
4531
|
+
Object.entries(headers).filter((entry) => typeof entry[1] === "string")
|
|
4532
|
+
);
|
|
4533
|
+
}
|
|
4534
|
+
return {};
|
|
4535
|
+
}
|
|
4536
|
+
|
|
4537
|
+
export {
|
|
4538
|
+
I18N,
|
|
4539
|
+
getI18N,
|
|
4540
|
+
clearI18NCache,
|
|
4541
|
+
I18N_DEFAULT,
|
|
4542
|
+
get_i18n,
|
|
4543
|
+
clear_i18n_cache,
|
|
4544
|
+
sanitizeToolName,
|
|
4545
|
+
sanitize_tool_name,
|
|
4546
|
+
slugify,
|
|
4547
|
+
_duplicate_separator_pattern,
|
|
4548
|
+
interpolateOnly,
|
|
4549
|
+
interpolate_only,
|
|
4550
|
+
_validate_type,
|
|
4551
|
+
FINAL_ANSWER_ACTION,
|
|
4552
|
+
MISSING_ACTION_AFTER_THOUGHT_ERROR_MESSAGE,
|
|
4553
|
+
MISSING_ACTION_INPUT_AFTER_ACTION_ERROR_MESSAGE,
|
|
4554
|
+
FINAL_ANSWER_AND_PARSABLE_ACTION_ERROR_MESSAGE,
|
|
4555
|
+
UNABLE_TO_REPAIR_JSON_RESULTS,
|
|
4556
|
+
AgentAction,
|
|
4557
|
+
AgentFinish,
|
|
4558
|
+
OutputParserError,
|
|
4559
|
+
parseAgentOutput,
|
|
4560
|
+
parse,
|
|
4561
|
+
extractThought,
|
|
4562
|
+
cleanAction,
|
|
4563
|
+
safeRepairJson,
|
|
4564
|
+
parse_agent_output,
|
|
4565
|
+
_extract_thought,
|
|
4566
|
+
_clean_action,
|
|
4567
|
+
_safe_repair_json,
|
|
4568
|
+
CreateConverterKwargs,
|
|
4569
|
+
ConverterError,
|
|
4570
|
+
Converter,
|
|
4571
|
+
validateModel,
|
|
4572
|
+
validate_model,
|
|
4573
|
+
handlePartialJson,
|
|
4574
|
+
handle_partial_json,
|
|
4575
|
+
asyncHandlePartialJson,
|
|
4576
|
+
async_handle_partial_json,
|
|
4577
|
+
convertToModel,
|
|
4578
|
+
convert_to_model,
|
|
4579
|
+
convertWithInstructions,
|
|
4580
|
+
convert_with_instructions,
|
|
4581
|
+
convertWithInstructionsSync,
|
|
4582
|
+
convert_with_instructions_sync,
|
|
4583
|
+
asyncConvertWithInstructions,
|
|
4584
|
+
async_convert_with_instructions,
|
|
4585
|
+
createConverter,
|
|
4586
|
+
create_converter,
|
|
4587
|
+
asyncConvertToModel,
|
|
4588
|
+
async_convert_to_model,
|
|
4589
|
+
getConversionInstructions,
|
|
4590
|
+
get_conversion_instructions,
|
|
4591
|
+
CREW_AI_NAMESPACE,
|
|
4592
|
+
Fingerprint,
|
|
4593
|
+
SecurityConfig,
|
|
4594
|
+
coerceSecurityConfig,
|
|
4595
|
+
validateMetadata,
|
|
4596
|
+
_validate_metadata,
|
|
4597
|
+
TransportType,
|
|
4598
|
+
MCPReadStream,
|
|
4599
|
+
MCPWriteStream,
|
|
4600
|
+
ToolFilterContext,
|
|
4601
|
+
ToolFilter,
|
|
4602
|
+
StaticToolFilter,
|
|
4603
|
+
createStaticToolFilter,
|
|
4604
|
+
create_static_tool_filter,
|
|
4605
|
+
createDynamicToolFilter,
|
|
4606
|
+
create_dynamic_tool_filter,
|
|
4607
|
+
MCPServerStdio,
|
|
4608
|
+
MCPServerHTTP,
|
|
4609
|
+
MCPServerSSE,
|
|
4610
|
+
MCPServerConfig,
|
|
4611
|
+
BaseTransport,
|
|
4612
|
+
HTTPTransport,
|
|
4613
|
+
SSETransport,
|
|
4614
|
+
StdioTransport,
|
|
4615
|
+
isMCPServerConfig,
|
|
4616
|
+
is_mcp_server_config,
|
|
4617
|
+
MCP_CONNECTION_TIMEOUT,
|
|
4618
|
+
MCP_TOOL_EXECUTION_TIMEOUT,
|
|
4619
|
+
MCP_DISCOVERY_TIMEOUT,
|
|
4620
|
+
MCP_MAX_RETRIES,
|
|
4621
|
+
_MCPToolResult,
|
|
4622
|
+
MCPClient,
|
|
4623
|
+
MCPToolResolver,
|
|
4624
|
+
mcp_schema_cache,
|
|
4625
|
+
OPENAI_BIGGER_MODELS,
|
|
4626
|
+
EnvVar,
|
|
4627
|
+
ToolCalling,
|
|
4628
|
+
InstructorToolCalling,
|
|
4629
|
+
_ArgsSchemaPlaceholder,
|
|
4630
|
+
_default_cache_function,
|
|
4631
|
+
_is_async_callable,
|
|
4632
|
+
_is_awaitable,
|
|
4633
|
+
_serialize_schema,
|
|
4634
|
+
_deserialize_schema,
|
|
4635
|
+
ToolResult,
|
|
4636
|
+
build_schema_hint,
|
|
4637
|
+
ToolUsageLimitExceededError,
|
|
4638
|
+
ToolValidationError,
|
|
4639
|
+
InMemoryToolCache,
|
|
4640
|
+
CacheHandler,
|
|
4641
|
+
ToolsHandler,
|
|
4642
|
+
BaseTool,
|
|
4643
|
+
to_langchain,
|
|
4644
|
+
StructuredTool,
|
|
4645
|
+
CrewStructuredTool,
|
|
4646
|
+
AddImageToolSchema,
|
|
4647
|
+
AddImageTool,
|
|
4648
|
+
ReadFileToolSchema,
|
|
4649
|
+
ReadFileTool,
|
|
4650
|
+
BaseAgentTool,
|
|
4651
|
+
AskQuestionToolSchema,
|
|
4652
|
+
AskQuestionTool,
|
|
4653
|
+
DelegateWorkToolSchema,
|
|
4654
|
+
DelegateWorkTool,
|
|
4655
|
+
AgentTools,
|
|
4656
|
+
CacheTools,
|
|
4657
|
+
MCPNativeTool,
|
|
4658
|
+
MCPToolWrapper,
|
|
4659
|
+
ToolUsageError,
|
|
4660
|
+
ToolUsage,
|
|
4661
|
+
createTool,
|
|
4662
|
+
create_tool,
|
|
4663
|
+
createFunctionTool,
|
|
4664
|
+
create_function_tool,
|
|
4665
|
+
_make_tool,
|
|
4666
|
+
_make_with_name,
|
|
4667
|
+
_resolve_tool_dict,
|
|
4668
|
+
normalizeToolCalling,
|
|
4669
|
+
aexecuteToolAndCheckFinality,
|
|
4670
|
+
aexecute_tool_and_check_finality,
|
|
4671
|
+
executeToolAndCheckFinality,
|
|
4672
|
+
execute_tool_and_check_finality,
|
|
4673
|
+
renderToolsDescription,
|
|
4674
|
+
normalizeToolInput,
|
|
4675
|
+
validateArgs,
|
|
4676
|
+
buildToolContext
|
|
4677
|
+
};
|