@amical/aiagent-sdk 0.1.1 → 0.1.3

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.
@@ -0,0 +1,1618 @@
1
+ 'use strict';
2
+
3
+ var nanoid = require('nanoid');
4
+ var matter = require('gray-matter');
5
+ var ai = require('ai');
6
+ var openai = require('@ai-sdk/openai');
7
+ var difyAiProvider = require('dify-ai-provider');
8
+ var fs2 = require('fs/promises');
9
+ var path2 = require('path');
10
+ var os = require('os');
11
+ var child_process = require('child_process');
12
+ var util = require('util');
13
+ var index_js = require('@modelcontextprotocol/sdk/client/index.js');
14
+ var stdio_js = require('@modelcontextprotocol/sdk/client/stdio.js');
15
+
16
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
+
18
+ function _interopNamespace(e) {
19
+ if (e && e.__esModule) return e;
20
+ var n = Object.create(null);
21
+ if (e) {
22
+ Object.keys(e).forEach(function (k) {
23
+ if (k !== 'default') {
24
+ var d = Object.getOwnPropertyDescriptor(e, k);
25
+ Object.defineProperty(n, k, d.get ? d : {
26
+ enumerable: true,
27
+ get: function () { return e[k]; }
28
+ });
29
+ }
30
+ });
31
+ }
32
+ n.default = e;
33
+ return Object.freeze(n);
34
+ }
35
+
36
+ var matter__default = /*#__PURE__*/_interopDefault(matter);
37
+ var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
38
+ var path2__namespace = /*#__PURE__*/_interopNamespace(path2);
39
+ var os__namespace = /*#__PURE__*/_interopNamespace(os);
40
+
41
+ // src/shared/tools.ts
42
+ var AgentDefaultTool = /* @__PURE__ */ ((AgentDefaultTool2) => {
43
+ AgentDefaultTool2["ASK"] = "agent_ask_followup_question";
44
+ AgentDefaultTool2["ATTEMPT"] = "agent_attempt_completion";
45
+ AgentDefaultTool2["BASH"] = "agent_execute_command";
46
+ AgentDefaultTool2["FILE_EDIT"] = "agent_replace_in_file";
47
+ AgentDefaultTool2["FILE_READ"] = "agent_read_file";
48
+ AgentDefaultTool2["FILE_NEW"] = "agent_write_to_file";
49
+ AgentDefaultTool2["FILE_DELETE"] = "agent_delete_file";
50
+ AgentDefaultTool2["DIR_DELETE"] = "agent_delete_directory";
51
+ AgentDefaultTool2["SEARCH"] = "agent_search_files";
52
+ AgentDefaultTool2["LIST_FILES"] = "agent_list_files";
53
+ AgentDefaultTool2["LIST_CODE_DEF"] = "agent_list_code_definition_names";
54
+ AgentDefaultTool2["BROWSER"] = "agent_browser_action";
55
+ AgentDefaultTool2["MCP_USE"] = "agent_use_mcp_tool";
56
+ AgentDefaultTool2["MCP_ACCESS"] = "agent_access_mcp_resource";
57
+ AgentDefaultTool2["MCP_DOCS"] = "agent_load_mcp_documentation";
58
+ AgentDefaultTool2["NEW_TASK"] = "agent_new_task";
59
+ AgentDefaultTool2["PLAN_MODE"] = "agent_plan_mode_respond";
60
+ AgentDefaultTool2["ACT_MODE"] = "agent_act_mode_respond";
61
+ AgentDefaultTool2["TODO"] = "agent_focus_chain";
62
+ AgentDefaultTool2["WEB_FETCH"] = "agent_web_fetch";
63
+ AgentDefaultTool2["WEB_SEARCH"] = "agent_web_search";
64
+ AgentDefaultTool2["CONDENSE"] = "agent_condense";
65
+ AgentDefaultTool2["SUMMARIZE_TASK"] = "agent_summarize_task";
66
+ AgentDefaultTool2["REPORT_BUG"] = "agent_report_bug";
67
+ AgentDefaultTool2["NEW_RULE"] = "agent_new_rule";
68
+ AgentDefaultTool2["APPLY_PATCH"] = "agent_apply_patch";
69
+ AgentDefaultTool2["GENERATE_EXPLANATION"] = "agent_generate_explanation";
70
+ AgentDefaultTool2["LOAD_SKILL"] = "agent_load_skill";
71
+ AgentDefaultTool2["USE_SUBAGENTS"] = "agent_use_subagents";
72
+ return AgentDefaultTool2;
73
+ })(AgentDefaultTool || {});
74
+ var TOOL_RESULT_BLOCK = "tool_call_result";
75
+ var defaultTools = [
76
+ {
77
+ name: "agent_ask_followup_question" /* ASK */,
78
+ description: "Ask the user a clarifying question if more information is needed.",
79
+ params: {
80
+ question: "The question to ask the user."
81
+ }
82
+ },
83
+ {
84
+ name: "agent_attempt_completion" /* ATTEMPT */,
85
+ description: "After each tool use, the user will respond with the result of that tool use, i.e. if it succeeded or failed, along with any reasons for failure. Once you've received the results of tool uses and can confirm that the task is complete, use this tool to present the result of your work to the user. Optionally you may provide a CLI command to showcase the result of your work. The user may respond with feedback if they are not satisfied with the result, which you can use to make improvements and try again. IMPORTANT NOTE: This tool CANNOT be used until you've confirmed from the user that any previous tool uses were successful. Failure to do so will result in code corruption and system failure. Before using this tool, you must ask yourself in tags if you've confirmed from the user that any previous tool uses were successful. If not, then DO NOT use this tool. If you were using task_progress to update the task progress, you must include the completed list in the result as well.",
86
+ params: {
87
+ result: "(required) The result of the tool use. This should be a clear, specific description of the result."
88
+ },
89
+ example: `## Example: ${"agent_attempt_completion" /* ATTEMPT */}
90
+ <${"agent_attempt_completion" /* ATTEMPT */}>
91
+ <result>final result or message</result>
92
+ <task_progress>
93
+ - [x] Set up project structure
94
+ - [x] Install dependencies
95
+ - [x] Run command to start server
96
+ - [x] Test application
97
+ </task_progress>
98
+ </${"agent_attempt_completion" /* ATTEMPT */}>`
99
+ },
100
+ {
101
+ name: "agent_execute_command" /* BASH */,
102
+ description: "Request to execute a CLI command on the system. Use this when you need to perform system operations or run specific commands to accomplish any step in the user's task. You must tailor your command to the user's system and provide a clear explanation of what the command does. For command chaining, use the appropriate chaining syntax for the user's shell. Prefer to execute complex CLI commands over creating executable scripts, as they are more flexible and easier to run. Commands will be executed in the current working directory: ${context.cwd} Use @workspace:path syntax (e.g., @frontend:src/index.ts) to specify a workspace.",
103
+ params: {
104
+ command: "(required) The CLI command to execute. This should be valid for the current operating system. Ensure the command is properly formatted and does not contain any harmful instructions."
105
+ },
106
+ example: `## Example: Requesting to execute a command
107
+
108
+ <${"agent_execute_command" /* BASH */}>
109
+ <command>npm run dev</command>
110
+ <requires_approval>false</requires_approval>
111
+ <task_progress>
112
+ - [x] Set up project structure
113
+ - [x] Install dependencies
114
+ - [ ] Run command to start server
115
+ - [ ] Test application
116
+ </task_progress>
117
+ </${"agent_execute_command" /* BASH */}>`
118
+ },
119
+ {
120
+ name: "agent_replace_in_file" /* FILE_EDIT */,
121
+ description: "Replace specific content in a file using a search/replace diff block.",
122
+ params: {
123
+ path: "(required) The absolute or relative file path to modify.",
124
+ diff: "(required) The diff content to apply."
125
+ },
126
+ example: `## Example: Requesting to make targeted edits to a file
127
+
128
+ <${"agent_replace_in_file" /* FILE_EDIT */}>
129
+ <path>src/components/App.tsx</path>
130
+ <diff>
131
+ ------- SEARCH
132
+ import React from 'react';
133
+ =======
134
+ import React, { useState } from 'react';
135
+ +++++++ REPLACE
136
+
137
+ ------- SEARCH
138
+ function handleSubmit() {
139
+ saveData();
140
+ setLoading(false);
141
+ }
142
+
143
+ =======
144
+ +++++++ REPLACE
145
+
146
+ ------- SEARCH
147
+ return (
148
+ <div>
149
+ =======
150
+ function handleSubmit() {
151
+ saveData();
152
+ setLoading(false);
153
+ }
154
+
155
+ return (
156
+ <div>
157
+ +++++++ REPLACE
158
+ </diff>
159
+ <task_progress>
160
+ - [x] Set up project structure
161
+ - [x] Install dependencies
162
+ - [ ] Create components
163
+ - [ ] Test application
164
+ </task_progress>
165
+ </${"agent_replace_in_file" /* FILE_EDIT */}>`
166
+ },
167
+ {
168
+ name: "agent_read_file" /* FILE_READ */,
169
+ description: "Read the contents of a specific file.",
170
+ params: {
171
+ path: "(required) The absolute or relative file path to read."
172
+ }
173
+ },
174
+ {
175
+ name: "agent_write_to_file" /* FILE_NEW */,
176
+ description: "Create or overwrite a file with new content.",
177
+ params: {
178
+ path: "(required) The path of the file to write to (relative to the current working directory ${context.cwd}) Use @workspace:path syntax (e.g., @frontend:src/index.ts) to specify a workspace.",
179
+ content: "(required) The content to write to the file."
180
+ },
181
+ example: `## Example: Requesting to create a new file
182
+
183
+ <${"agent_write_to_file" /* FILE_NEW */}>
184
+ <path>src/frontend-config.json</path>
185
+ <content>
186
+ {
187
+ "apiEndpoint": "https://api.example.com",
188
+ "theme": {
189
+ "primaryColor": "#007bff",
190
+ "secondaryColor": "#6c757d",
191
+ "fontFamily": "Arial, sans-serif"
192
+ },
193
+ "features": {
194
+ "darkMode": true,
195
+ "notifications": true,
196
+ "analytics": false
197
+ },
198
+ "version": "1.0.0"
199
+ }
200
+ </content>
201
+ <task_progress>
202
+ - [x] Set up project structure
203
+ - [x] Install dependencies
204
+ - [x] Create components
205
+ - [ ] Test application
206
+ </task_progress>
207
+ </${"agent_write_to_file" /* FILE_NEW */}>`
208
+ },
209
+ {
210
+ name: "agent_delete_file" /* FILE_DELETE */,
211
+ description: "Delete a file.",
212
+ params: {
213
+ path: "(required) The path of the file to delete to (relative to the current working directory ${context.cwd}) Use @workspace:path syntax (e.g., @frontend:src/index.ts) to specify a workspace."
214
+ }
215
+ },
216
+ {
217
+ name: "agent_delete_directory" /* DIR_DELETE */,
218
+ description: "Delete a directory.",
219
+ params: {
220
+ path: "(required) The path of the directory to delete to (relative to the current working directory ${context.cwd}) Use @workspace:path syntax (e.g., @frontend:src/index.ts) to specify a workspace."
221
+ }
222
+ },
223
+ {
224
+ name: "agent_search_files" /* SEARCH */,
225
+ description: "Search for files in a directory that match a regex pattern or glob pattern.",
226
+ params: {
227
+ path: "(required) The absolute or relative directory path to search.",
228
+ regex: "(required) The regex pattern to match files against.",
229
+ file_pattern: "(optional) glob pattern like *.ts."
230
+ }
231
+ },
232
+ {
233
+ name: "agent_list_files" /* LIST_FILES */,
234
+ description: "List all files in a directory.",
235
+ params: {
236
+ path: "(required) The absolute or relative directory path to list."
237
+ }
238
+ },
239
+ //================
240
+ {
241
+ name: "agent_new_task" /* NEW_TASK */,
242
+ description: "Create a new task with a given context.",
243
+ params: {
244
+ context: "(required) The context of the new task."
245
+ },
246
+ example: `## Example: Creating a new task
247
+ <${"agent_new_task" /* NEW_TASK */}>
248
+ <context>
249
+ 1. Current Work:
250
+ [Detailed description]
251
+
252
+ 2. Key Technical Concepts:
253
+ - [Concept 1]
254
+ - [Concept 2]
255
+ - [...]
256
+
257
+ 3. Relevant Files and Code:
258
+ - [File Name 1]
259
+ - [Summary of why this file is important]
260
+ - [Summary of the changes made to this file, if any]
261
+ - [Important Code Snippet]
262
+ - [File Name 2]
263
+ - [Important Code Snippet]
264
+ - [...]
265
+
266
+ 4. Problem Solving:
267
+ [Detailed description]
268
+
269
+ 5. Pending Tasks and Next Steps:
270
+ - [Task 1 details & next steps]
271
+ - [Task 2 details & next steps]
272
+ - [...]
273
+ </context>
274
+ </${"agent_new_task" /* NEW_TASK */}>`
275
+ },
276
+ {
277
+ name: "agent_load_skill" /* LOAD_SKILL */,
278
+ description: "Load a skill to perform a task. important: skill_name is required. must use this tool to load the skill; do not use any other method to read it.",
279
+ params: {
280
+ skill_name: "(required) The name of the skill to load."
281
+ }
282
+ }
283
+ ];
284
+ var toolUseNames = Object.values(AgentDefaultTool);
285
+ var dynamicToolUseNamesByNamespace = /* @__PURE__ */ new Map();
286
+ function setDynamicToolUseNames(namespace, names) {
287
+ dynamicToolUseNamesByNamespace.set(namespace, new Set(names.map((name) => name.trim()).filter(Boolean)));
288
+ }
289
+ function getToolUseNames() {
290
+ const defaults = [...toolUseNames];
291
+ const dynamic = Array.from(dynamicToolUseNamesByNamespace.values()).flatMap((set) => Array.from(set));
292
+ return Array.from(/* @__PURE__ */ new Set([...defaults, ...dynamic]));
293
+ }
294
+ var READ_ONLY_TOOLS = [
295
+ "agent_list_files" /* LIST_FILES */,
296
+ "agent_read_file" /* FILE_READ */,
297
+ "agent_search_files" /* SEARCH */,
298
+ "agent_list_code_definition_names" /* LIST_CODE_DEF */,
299
+ "agent_browser_action" /* BROWSER */,
300
+ "agent_ask_followup_question" /* ASK */,
301
+ "agent_web_search" /* WEB_SEARCH */,
302
+ "agent_web_fetch" /* WEB_FETCH */,
303
+ "agent_load_skill" /* LOAD_SKILL */,
304
+ "agent_use_subagents" /* USE_SUBAGENTS */
305
+ ];
306
+ function parseAssistantMessageV2(assistantMessage, toolParamNames2) {
307
+ const contentBlocks = [];
308
+ let currentTextContentStart = 0;
309
+ let currentTextContent;
310
+ let currentToolUseStart = 0;
311
+ let currentToolUse;
312
+ let currentParamValueStart = 0;
313
+ let currentParamName;
314
+ const toolUseOpenTags = /* @__PURE__ */ new Map();
315
+ const toolParamOpenTags = /* @__PURE__ */ new Map();
316
+ for (const name of getToolUseNames()) {
317
+ toolUseOpenTags.set(`<${name}>`, name);
318
+ }
319
+ for (const name of toolParamNames2) {
320
+ toolParamOpenTags.set(`<${name}>`, name);
321
+ }
322
+ const len = assistantMessage.length;
323
+ for (let i = 0; i < len; i++) {
324
+ const currentCharIndex = i;
325
+ if (currentToolUse && currentParamName) {
326
+ const closeTag = `</${currentParamName}>`;
327
+ if (currentCharIndex >= closeTag.length - 1 && assistantMessage.startsWith(
328
+ closeTag,
329
+ currentCharIndex - closeTag.length + 1
330
+ // Start checking from potential start of tag
331
+ )) {
332
+ const value = assistantMessage.slice(
333
+ currentParamValueStart,
334
+ // Start after the opening tag
335
+ currentCharIndex - closeTag.length + 1
336
+ // End before the closing tag
337
+ ).trim();
338
+ currentToolUse.params[currentParamName] = value;
339
+ currentParamName = void 0;
340
+ } else {
341
+ continue;
342
+ }
343
+ }
344
+ if (currentToolUse && !currentParamName) {
345
+ let startedNewParam = false;
346
+ for (const [tag, paramName] of toolParamOpenTags.entries()) {
347
+ if (currentCharIndex >= tag.length - 1 && assistantMessage.startsWith(tag, currentCharIndex - tag.length + 1)) {
348
+ currentParamName = paramName;
349
+ currentParamValueStart = currentCharIndex + 1;
350
+ startedNewParam = true;
351
+ break;
352
+ }
353
+ }
354
+ if (startedNewParam) {
355
+ continue;
356
+ }
357
+ const toolCloseTag = `</${currentToolUse.name}>`;
358
+ if (currentCharIndex >= toolCloseTag.length - 1 && assistantMessage.startsWith(toolCloseTag, currentCharIndex - toolCloseTag.length + 1)) {
359
+ const toolContentSlice = assistantMessage.slice(
360
+ currentToolUseStart,
361
+ // From after the tool opening tag
362
+ currentCharIndex - toolCloseTag.length + 1
363
+ // To before the tool closing tag
364
+ );
365
+ const contentParamName = "content";
366
+ if (currentToolUse.name === "agent_write_to_file" /* FILE_NEW */ && toolContentSlice.includes(`<${contentParamName}>`)) {
367
+ const contentStartTag = `<${contentParamName}>`;
368
+ const contentEndTag = `</${contentParamName}>`;
369
+ const contentStart = toolContentSlice.indexOf(contentStartTag);
370
+ const contentEnd = toolContentSlice.lastIndexOf(contentEndTag);
371
+ if (contentStart !== -1 && contentEnd !== -1 && contentEnd > contentStart) {
372
+ const contentValue = toolContentSlice.slice(contentStart + contentStartTag.length, contentEnd).trim();
373
+ currentToolUse.params[contentParamName] = contentValue;
374
+ }
375
+ }
376
+ currentToolUse.partial = false;
377
+ contentBlocks.push(currentToolUse);
378
+ currentToolUse = void 0;
379
+ currentTextContentStart = currentCharIndex + 1;
380
+ continue;
381
+ }
382
+ continue;
383
+ }
384
+ if (!currentToolUse) {
385
+ let startedNewTool = false;
386
+ for (const [tag, toolName] of toolUseOpenTags.entries()) {
387
+ if (currentCharIndex >= tag.length - 1 && assistantMessage.startsWith(tag, currentCharIndex - tag.length + 1)) {
388
+ if (currentTextContent) {
389
+ currentTextContent.content = assistantMessage.slice(
390
+ currentTextContentStart,
391
+ // From where text started
392
+ currentCharIndex - tag.length + 1
393
+ // To before the tool tag starts
394
+ ).trim();
395
+ currentTextContent.partial = false;
396
+ if (currentTextContent.content.length > 0) {
397
+ contentBlocks.push(currentTextContent);
398
+ }
399
+ currentTextContent = void 0;
400
+ } else {
401
+ const potentialText = assistantMessage.slice(
402
+ currentTextContentStart,
403
+ // From where text *might* have started
404
+ currentCharIndex - tag.length + 1
405
+ // To before the tool tag starts
406
+ ).trim();
407
+ if (potentialText.length > 0) {
408
+ contentBlocks.push({
409
+ type: "text",
410
+ content: potentialText,
411
+ partial: false
412
+ });
413
+ }
414
+ }
415
+ currentToolUse = {
416
+ type: "tool_use",
417
+ name: toolName,
418
+ params: {},
419
+ partial: true,
420
+ // Assume partial until closing tag is found
421
+ call_id: nanoid.nanoid(8),
422
+ isNativeToolCall: false
423
+ };
424
+ currentToolUseStart = currentCharIndex + 1;
425
+ startedNewTool = true;
426
+ break;
427
+ }
428
+ }
429
+ if (startedNewTool) {
430
+ continue;
431
+ }
432
+ if (!currentTextContent) {
433
+ currentTextContentStart = currentCharIndex;
434
+ currentTextContent = {
435
+ type: "text",
436
+ content: "",
437
+ // Will be determined by slicing at the end or when a tool starts
438
+ partial: true
439
+ };
440
+ }
441
+ }
442
+ }
443
+ if (currentToolUse && currentParamName) {
444
+ currentToolUse.params[currentParamName] = assistantMessage.slice(currentParamValueStart).trim();
445
+ }
446
+ if (currentToolUse) {
447
+ contentBlocks.push(currentToolUse);
448
+ } else if (currentTextContent) {
449
+ currentTextContent.content = assistantMessage.slice(currentTextContentStart).trim();
450
+ if (currentTextContent.content.length > 0) {
451
+ contentBlocks.push(currentTextContent);
452
+ }
453
+ }
454
+ return contentBlocks;
455
+ }
456
+
457
+ // src/parser/index.ts
458
+ var toolParamNames = [
459
+ "command",
460
+ "requires_approval",
461
+ "path",
462
+ "absolutePath",
463
+ "content",
464
+ "diff",
465
+ "regex",
466
+ "file_pattern",
467
+ "recursive",
468
+ "action",
469
+ "url",
470
+ "coordinate",
471
+ "text",
472
+ "query",
473
+ "allowed_domains",
474
+ "blocked_domains",
475
+ "prompt",
476
+ "server_name",
477
+ "tool_name",
478
+ "arguments",
479
+ "uri",
480
+ "question",
481
+ "options",
482
+ "response",
483
+ "result",
484
+ "context",
485
+ "title",
486
+ "what_happened",
487
+ "steps_to_reproduce",
488
+ "api_request_output",
489
+ "additional_context",
490
+ "needs_more_exploration",
491
+ "task_progress",
492
+ "timeout",
493
+ "input",
494
+ "from_ref",
495
+ "to_ref",
496
+ "skill_name",
497
+ "prompt_1",
498
+ "prompt_2",
499
+ "prompt_3",
500
+ "prompt_4",
501
+ "prompt_5",
502
+ "start_line",
503
+ "end_line"
504
+ ];
505
+ var AgentState = /* @__PURE__ */ ((AgentState2) => {
506
+ AgentState2["IDLE"] = "idle";
507
+ AgentState2["THINKING"] = "thinking";
508
+ AgentState2["WAITING_FOR_USER"] = "waiting_for_user";
509
+ AgentState2["FINISHED"] = "finished";
510
+ AgentState2["ERROR"] = "error";
511
+ return AgentState2;
512
+ })(AgentState || {});
513
+ var ClineAgent = class {
514
+ runtime;
515
+ api;
516
+ promptManager;
517
+ memory;
518
+ mcp;
519
+ state = "idle" /* IDLE */;
520
+ allToolParamNames = [...toolParamNames];
521
+ /** 循环计数器 */
522
+ loopCount = 0;
523
+ /** 最大循环次数 */
524
+ maxLoopCount;
525
+ skillDir;
526
+ customTools;
527
+ customToolNames;
528
+ allowDefaultTools;
529
+ customInstructions;
530
+ sysPrompt;
531
+ noUseTollSysPrompt;
532
+ // 简单的事件回调系统,供宿主环境注册以监听 Agent 内部事件
533
+ onStateChange;
534
+ onStreamChunk;
535
+ onToolCall;
536
+ constructor(options) {
537
+ this.runtime = options.runtime;
538
+ this.api = options.api;
539
+ this.promptManager = options.promptManager;
540
+ this.memory = options.memory;
541
+ this.mcp = options.mcp;
542
+ this.maxLoopCount = options.maxLoopCount ?? 150;
543
+ this.customTools = options.customTools || [];
544
+ this.allowDefaultTools = options.allowDefaultTools;
545
+ if (this.allowDefaultTools && !this.allowDefaultTools.includes("agent_attempt_completion" /* ATTEMPT */)) {
546
+ this.allowDefaultTools.push("agent_attempt_completion" /* ATTEMPT */);
547
+ }
548
+ this.customInstructions = options.customInstructions;
549
+ if (this.customTools.length > 0) {
550
+ const dynamicToolNames = /* @__PURE__ */ new Set();
551
+ const customToolParams = /* @__PURE__ */ new Set();
552
+ for (const customTool of this.customTools) {
553
+ dynamicToolNames.add(customTool.name);
554
+ if (customTool.params) {
555
+ for (const key in customTool.params) {
556
+ if (!Object.hasOwn(customTool.params, key)) continue;
557
+ customToolParams.add(key);
558
+ }
559
+ }
560
+ }
561
+ const defaultToolNames = Object.values(AgentDefaultTool);
562
+ const overlappingTools = Array.from(dynamicToolNames).filter((name) => defaultToolNames.includes(name));
563
+ if (overlappingTools.length > 0) {
564
+ throw new Error(`Custom tools and default tools have overlapping names: ${overlappingTools.join(", ")}`);
565
+ }
566
+ if (dynamicToolNames.size > 0) {
567
+ setDynamicToolUseNames("customUser", Array.from(dynamicToolNames));
568
+ }
569
+ if (customToolParams.size > 0) {
570
+ this.allToolParamNames = Array.from(/* @__PURE__ */ new Set([...this.allToolParamNames, ...Array.from(customToolParams)]));
571
+ }
572
+ }
573
+ this.customToolNames = new Set(this.customTools.map((t) => t.name));
574
+ this.skillDir = this.runtime.path.join(this.runtime.env.cwd(), ".agent/skills");
575
+ }
576
+ setState(newState) {
577
+ this.state = newState;
578
+ if (this.onStateChange) {
579
+ this.onStateChange(newState);
580
+ }
581
+ }
582
+ /**
583
+ * 获取当前 Agent 的系统提示词
584
+ * 如果 force 为 true,则强制重新获取系统提示词
585
+ */
586
+ async getPrompt(force = false) {
587
+ if (!force && this.sysPrompt && this.noUseTollSysPrompt) {
588
+ return { sysPrompt: this.sysPrompt, noUseTollSysPrompt: this.noUseTollSysPrompt };
589
+ }
590
+ const context = {
591
+ cwd: this.runtime.env.cwd(),
592
+ os: this.runtime.env.osInfo(),
593
+ shell: this.runtime.env.shell(),
594
+ skills: await this.getSkills(),
595
+ customTools: this.customTools,
596
+ allowDefaultTools: this.allowDefaultTools,
597
+ customInstructions: this.customInstructions
598
+ };
599
+ this.sysPrompt = await this.promptManager.getSystemPrompt(context);
600
+ this.noUseTollSysPrompt = this.promptManager.getNoUseToolInstructions(context);
601
+ return { sysPrompt: this.sysPrompt, noUseTollSysPrompt: this.noUseTollSysPrompt };
602
+ }
603
+ /**
604
+ * 启动一个新的任务
605
+ */
606
+ async startTask(taskDescription) {
607
+ this.setState("thinking" /* THINKING */);
608
+ try {
609
+ await this.memory.clear();
610
+ this.loopCount = 0;
611
+ await this.memory.appendMessage({
612
+ role: "user",
613
+ content: taskDescription
614
+ });
615
+ await this.loop();
616
+ } catch (err) {
617
+ this.setState("error" /* ERROR */);
618
+ throw err;
619
+ }
620
+ }
621
+ async getSkills() {
622
+ const skillDir = this.skillDir;
623
+ const skillList = [];
624
+ if (!this.runtime.fs.fileExists(skillDir)) {
625
+ return skillList;
626
+ }
627
+ const files = await this.runtime.fs.readDir(skillDir);
628
+ const skills = files.filter((item) => item.isDirectory()).map((item) => item.name);
629
+ if (skills.length === 0) {
630
+ return [];
631
+ }
632
+ for (const skill of skills) {
633
+ try {
634
+ const skillPath = this.runtime.path.join(skillDir, skill);
635
+ const files2 = await this.runtime.fs.readDir(skillPath);
636
+ const skillFile = files2.map((item) => item.isFile()).find((f) => f.toLowerCase() === "skill.md");
637
+ if (skillFile) {
638
+ const mdPath = this.runtime.path.join(skillPath, skillFile);
639
+ const mdContent = await this.runtime.fs.readFile(mdPath);
640
+ const parsed = matter__default.default(mdContent);
641
+ if (parsed.data && parsed.data.description) {
642
+ let description = String(parsed.data.description).trim();
643
+ description = description.replace(/\s+/g, " ").trim();
644
+ if (description) {
645
+ skillList.push({
646
+ name: skill,
647
+ description
648
+ });
649
+ }
650
+ }
651
+ }
652
+ } catch (e) {
653
+ return skillList;
654
+ }
655
+ }
656
+ }
657
+ /**
658
+ * 核心任务循环
659
+ */
660
+ async loop() {
661
+ const { sysPrompt, noUseTollSysPrompt } = await this.getPrompt(true);
662
+ const { customTools, customToolNames } = this;
663
+ while (this.state === "thinking" /* THINKING */) {
664
+ this.loopCount++;
665
+ if (this.loopCount > this.maxLoopCount) {
666
+ await this.memory.appendMessage({
667
+ role: "user",
668
+ content: `[ERROR] You have exceeded the maximum loop limit of ${this.maxLoopCount} times. Please immediately call the agent_attempt_completion tool to return the final result. If you have pending user-specified tools to execute, you may run them first before calling agent_attempt_completion.`
669
+ });
670
+ }
671
+ const history = await this.memory.getHistory();
672
+ const stream = this.api.createMessage(sysPrompt, history);
673
+ let fullResponseText = "";
674
+ for await (const chunk of stream) {
675
+ if (chunk.type === "text" && chunk.text) {
676
+ fullResponseText += chunk.text;
677
+ }
678
+ if (this.onStreamChunk) {
679
+ this.onStreamChunk(chunk);
680
+ }
681
+ }
682
+ await this.memory.appendMessage({
683
+ role: "assistant",
684
+ content: fullResponseText
685
+ });
686
+ const parsedBlocks = parseAssistantMessageV2(fullResponseText, this.allToolParamNames);
687
+ const toolUses = parsedBlocks.filter((b) => b.type === "tool_use");
688
+ if (toolUses.length === 0) {
689
+ await this.memory.appendMessage({
690
+ role: "user",
691
+ content: noUseTollSysPrompt
692
+ });
693
+ } else {
694
+ const toolResults = [];
695
+ for (const tool of toolUses) {
696
+ if (this.onToolCall) {
697
+ const hookResult = await this.onToolCall(tool);
698
+ if (hookResult) {
699
+ toolResults.push({ tool, result: hookResult });
700
+ continue;
701
+ }
702
+ }
703
+ if (customToolNames.has(tool.name)) {
704
+ const customTool = customTools.find((t) => t.name === tool.name);
705
+ if (customTool.onCall) {
706
+ try {
707
+ const res = await customTool.onCall(tool.params);
708
+ toolResults.push({ tool, result: res });
709
+ } catch (error) {
710
+ toolResults.push({ tool, result: `Error: ${error.message}` });
711
+ }
712
+ } else {
713
+ toolResults.push({ tool, result: `Error: Custom tool "${tool.name}" does not have an onCall method.` });
714
+ }
715
+ continue;
716
+ }
717
+ if (tool.name === "agent_attempt_completion" /* ATTEMPT */) {
718
+ toolResults.push({ tool, result: "Task marked as completed." });
719
+ this.setState("finished" /* FINISHED */);
720
+ break;
721
+ } else if (tool.name === "agent_read_file" /* FILE_READ */) {
722
+ const path3 = tool.params.path;
723
+ if (path3) {
724
+ try {
725
+ const content = await this.runtime.fs.readFile(path3);
726
+ toolResults.push({ tool, result: content });
727
+ } catch (error) {
728
+ toolResults.push({ tool, result: `Error: ${error.message}` });
729
+ }
730
+ } else {
731
+ toolResults.push({ tool, result: "Error: No path provided." });
732
+ }
733
+ } else if (tool.name === "agent_execute_command" /* BASH */) {
734
+ const cmd = tool.params.command;
735
+ if (cmd) {
736
+ const result = await this.runtime.terminal.execCommand(cmd);
737
+ toolResults.push({ tool, result: `STDOUT: ${result.stdout}
738
+ STDERR: ${result.stderr}` });
739
+ }
740
+ } else if (tool.name === "agent_write_to_file" /* FILE_NEW */) {
741
+ const path3 = tool.params.path;
742
+ const content = tool.params.content;
743
+ if (path3 && content !== void 0) {
744
+ try {
745
+ await this.runtime.fs.writeFile(path3, content);
746
+ toolResults.push({ tool, result: `Successfully wrote to ${path3}` });
747
+ } catch (error) {
748
+ toolResults.push({ tool, result: `Error: ${error.message}` });
749
+ }
750
+ }
751
+ } else if (tool.name === "agent_list_files" /* LIST_FILES */) {
752
+ const path3 = tool.params.path || this.runtime.env.cwd();
753
+ try {
754
+ const files = await this.runtime.fs.readDir(path3);
755
+ toolResults.push({ tool, result: files.map((f) => f.name + (f.isDirectory() ? "/" : "")).join("\n") });
756
+ } catch (e) {
757
+ toolResults.push({ tool, result: `Error: ${e.message}` });
758
+ }
759
+ } else if (tool.name === "agent_replace_in_file" /* FILE_EDIT */) {
760
+ const path3 = tool.params.path;
761
+ const diff = tool.params.diff;
762
+ if (path3 && diff) {
763
+ try {
764
+ const content = await this.runtime.fs.readFile(path3);
765
+ const newContent = this.applyDiff(content, diff);
766
+ await this.runtime.fs.writeFile(path3, newContent);
767
+ toolResults.push({ tool, result: `Successfully replaced content in ${path3}` });
768
+ } catch (e) {
769
+ toolResults.push({ tool, result: `Error: ${e.message}` });
770
+ }
771
+ } else {
772
+ toolResults.push({ tool, result: "Error: Missing path or diff." });
773
+ }
774
+ } else if (tool.name === "agent_delete_file" /* FILE_DELETE */) {
775
+ const path3 = tool.params.path;
776
+ if (path3) {
777
+ try {
778
+ await this.runtime.fs.deleteFile(path3);
779
+ toolResults.push({ tool, result: `Successfully deleted ${path3}` });
780
+ } catch (e) {
781
+ toolResults.push({ tool, result: `Error: ${e.message}` });
782
+ }
783
+ } else {
784
+ toolResults.push({ tool, result: "Error: Missing path." });
785
+ }
786
+ } else if (tool.name === "agent_delete_directory" /* DIR_DELETE */) {
787
+ const path3 = tool.params.path;
788
+ if (path3) {
789
+ try {
790
+ await this.runtime.fs.deleteDirectory(path3);
791
+ toolResults.push({ tool, result: `Successfully deleted ${path3}` });
792
+ } catch (e) {
793
+ toolResults.push({ tool, result: `Error: ${e.message}` });
794
+ }
795
+ } else {
796
+ toolResults.push({ tool, result: "Error: Missing path." });
797
+ }
798
+ } else if (tool.name === "agent_ask_followup_question" /* ASK */) {
799
+ const question = tool.params.question;
800
+ toolResults.push({ tool, result: `Asking user: ${question}` });
801
+ this.setState("waiting_for_user" /* WAITING_FOR_USER */);
802
+ break;
803
+ } else if (tool.name === "agent_search_files" /* SEARCH */) {
804
+ const path3 = tool.params.path || this.runtime.env.cwd();
805
+ const regexStr = tool.params.regex;
806
+ const filePattern = tool.params.file_pattern;
807
+ if (regexStr && this.runtime.fs.searchFiles) {
808
+ try {
809
+ const result = await this.runtime.fs.searchFiles(path3, regexStr, filePattern);
810
+ toolResults.push({ tool, result: `${result}` });
811
+ } catch (e) {
812
+ toolResults.push({ tool, result: `Error: ${e.message}` });
813
+ }
814
+ } else {
815
+ toolResults.push({ tool, result: `Error: searchFiles not supported by runtime or missing regex.` });
816
+ }
817
+ } else if (tool.name === "agent_use_mcp_tool" /* MCP_USE */) {
818
+ const serverName = tool.params.server_name;
819
+ const toolName = tool.params.tool_name;
820
+ const args = tool.params.arguments;
821
+ if (this.mcp && serverName && toolName) {
822
+ try {
823
+ let parsedArgs = args;
824
+ if (typeof args === "string") {
825
+ parsedArgs = JSON.parse(args);
826
+ }
827
+ const result = await this.mcp.callTool(serverName, toolName, parsedArgs);
828
+ if (result.isError) {
829
+ toolResults.push({ tool, result: `Error executing MCP tool: ${JSON.stringify(result.content)}` });
830
+ } else {
831
+ toolResults.push({ tool, result: `${JSON.stringify(result.content)}` });
832
+ }
833
+ } catch (e) {
834
+ toolResults.push({ tool, result: `Error: ${e.message}` });
835
+ }
836
+ } else {
837
+ toolResults.push({ tool, result: `Error: MCP Manager not available or missing parameters.` });
838
+ }
839
+ } else if (tool.name === "agent_access_mcp_resource" /* MCP_ACCESS */) {
840
+ const serverName = tool.params.server_name;
841
+ const uri = tool.params.uri;
842
+ if (this.mcp && this.mcp.readResource && serverName && uri) {
843
+ try {
844
+ const result = await this.mcp.readResource(serverName, uri);
845
+ toolResults.push({ tool, result: `${JSON.stringify(result)}` });
846
+ } catch (e) {
847
+ toolResults.push({ tool, result: `Error: ${e.message}` });
848
+ }
849
+ } else {
850
+ toolResults.push({ tool, result: `Error: MCP Manager not available, readResource not implemented, or missing parameters.` });
851
+ }
852
+ } else if (tool.name === "agent_load_mcp_documentation" /* MCP_DOCS */) {
853
+ const docs = `MCP (Model Context Protocol) is used to connect to external tools/resources. To build one, typically you create an HTTP/stdio server responding to MCP defined JSON-RPC messages...`;
854
+ toolResults.push({ tool, result: docs });
855
+ } else if (tool.name === "agent_list_code_definition_names" /* LIST_CODE_DEF */) {
856
+ const path3 = tool.params.path || this.runtime.env.cwd();
857
+ try {
858
+ const result = await this.runtime.fs.searchFiles?.(path3, "^(class|function|const|let|var|export|interface|type)\\s+\\w+", "*.ts|*.js");
859
+ toolResults.push({ tool, result: `${result ? result : "No definitions found or searchFiles not supported."}` });
860
+ } catch (e) {
861
+ toolResults.push({ tool, result: `Error: ${e.message}` });
862
+ }
863
+ } else if (tool.name === "agent_web_fetch" /* WEB_FETCH */) {
864
+ const url = tool.params.url;
865
+ if (url) {
866
+ try {
867
+ const res = await fetch(url);
868
+ const text = await res.text();
869
+ toolResults.push({ tool, result: text.substring(0, 3e3) });
870
+ } catch (e) {
871
+ toolResults.push({ tool, result: `Error: ${e.message}` });
872
+ }
873
+ }
874
+ } else if (tool.name === "agent_focus_chain" /* TODO */) {
875
+ toolResults.push({ tool, result: `Focus chain updated successfully.` });
876
+ } else if (tool.name === "agent_plan_mode_respond" /* PLAN_MODE */ || tool.name === "agent_act_mode_respond" /* ACT_MODE */) {
877
+ toolResults.push({ tool, result: `Mode switch acknowledged.` });
878
+ } else if (tool.name === "agent_new_rule" /* NEW_RULE */) {
879
+ toolResults.push({ tool, result: `Rule recorded in current context.` });
880
+ } else if (tool.name === "agent_new_task" /* NEW_TASK */) {
881
+ toolResults.push({ tool, result: `New task request received. Terminating current task.` });
882
+ this.setState("finished" /* FINISHED */);
883
+ break;
884
+ } else if (tool.name === "agent_load_skill" /* LOAD_SKILL */) {
885
+ const skillName = tool.params.skill_name || tool.params.skill;
886
+ if (!skillName) {
887
+ toolResults.push({ tool, result: `"Error: Missing required parameter 'skill_name'. Please provide the name of the skill to activate."` });
888
+ } else {
889
+ const skillDir = this.skillDir;
890
+ const skillFilePath = this.runtime.path.join(skillDir, skillName, "SKILL.md");
891
+ try {
892
+ const fileExists = await this.runtime.fs.fileExists(skillFilePath);
893
+ if (!fileExists) {
894
+ toolResults.push({ tool, result: `Error: Skill "${skillName}" not found at ${skillFilePath}.` });
895
+ } else {
896
+ const content = await this.runtime.fs.readFile(skillFilePath);
897
+ toolResults.push({
898
+ tool,
899
+ result: `# Skill "${skillName}" is now active
900
+
901
+ ${content}
902
+
903
+ ---
904
+ IMPORTANT: The skill is now loaded. Do NOT call agent_load_skill again for this task. Simply follow the instructions above to complete the user's request.`
905
+ });
906
+ }
907
+ } catch (err) {
908
+ toolResults.push({ tool, result: `Error loading skill "${skillName}": ${err.message}` });
909
+ }
910
+ }
911
+ } else if (tool.name === "agent_browser_action" /* BROWSER */ || tool.name === "agent_web_search" /* WEB_SEARCH */ || tool.name === "agent_apply_patch" /* APPLY_PATCH */) {
912
+ toolResults.push({ tool, result: `This tool requires specific host integration. If you see this, the host environment has not implemented it yet.` });
913
+ } else if (tool.name === "agent_condense" /* CONDENSE */ || tool.name === "agent_summarize_task" /* SUMMARIZE_TASK */ || tool.name === "agent_report_bug" /* REPORT_BUG */ || tool.name === "agent_generate_explanation" /* GENERATE_EXPLANATION */) {
914
+ toolResults.push({ tool, result: `Action logged successfully.` });
915
+ } else {
916
+ toolResults.push({ tool, result: `Executed by host or unsupported.` });
917
+ }
918
+ }
919
+ if (this.state === "thinking" /* THINKING */ && toolResults.length > 0) {
920
+ const toolResultsContext = toolResults.map((tr) => `<${TOOL_RESULT_BLOCK} tool_name="${tr.tool.name}">
921
+ ${typeof tr.result === "string" ? tr.result.trim() : JSON.stringify(tr.result)}
922
+ </${TOOL_RESULT_BLOCK}>`).join("\n\n");
923
+ if (this.onStreamChunk) {
924
+ this.onStreamChunk({ type: "text", text: toolResultsContext });
925
+ }
926
+ await this.memory.appendMessage({
927
+ role: "user",
928
+ content: toolResultsContext
929
+ });
930
+ }
931
+ }
932
+ }
933
+ }
934
+ /**
935
+ * 简单的 Diff 解析与替换辅助方法
936
+ */
937
+ applyDiff(content, diff) {
938
+ const regex = /-------\s*SEARCH\r?\n(.*?)\r?\n=======\r?\n(.*?)\r?\n\+\+\+\+\+\+\+\s*REPLACE/gs;
939
+ let newContent = content;
940
+ let match;
941
+ let matchCount = 0;
942
+ while ((match = regex.exec(diff)) !== null) {
943
+ matchCount++;
944
+ const searchBlock = match[1];
945
+ const replaceBlock = match[2];
946
+ const idx = newContent.indexOf(searchBlock);
947
+ if (idx !== -1) {
948
+ newContent = newContent.substring(0, idx) + replaceBlock + newContent.substring(idx + searchBlock.length);
949
+ } else {
950
+ throw new Error(`Search block not found in file:
951
+ ${searchBlock.substring(0, 100)}...`);
952
+ }
953
+ }
954
+ if (matchCount === 0) {
955
+ throw new Error(`No valid SEARCH/REPLACE blocks found in the diff.`);
956
+ }
957
+ return newContent;
958
+ }
959
+ /**
960
+ * 恢复被中断的循环(例如等待用户输入/确认后继续)
961
+ */
962
+ async resume(userInput) {
963
+ if (userInput) {
964
+ await this.memory.appendMessage({
965
+ role: "user",
966
+ content: userInput
967
+ });
968
+ }
969
+ this.setState("thinking" /* THINKING */);
970
+ await this.loop();
971
+ }
972
+ async appendHistory(history) {
973
+ for (const message of history) {
974
+ await this.memory.appendMessage(message);
975
+ }
976
+ }
977
+ async getHistory() {
978
+ return this.memory.getHistory();
979
+ }
980
+ };
981
+ var NodeApiHandler = class {
982
+ config;
983
+ conversationId;
984
+ constructor(config) {
985
+ this.config = config;
986
+ }
987
+ getModelInfo() {
988
+ return {
989
+ providerId: this.config.providerId || "openai-compatible",
990
+ modelId: this.config.modelId
991
+ };
992
+ }
993
+ async *createMessage(systemPrompt, messages) {
994
+ let model;
995
+ if (this.config.providerId === "dify") {
996
+ const customDify = difyAiProvider.createDifyProvider({
997
+ baseURL: this.config.baseURL,
998
+ headers: this.config.headers,
999
+ fetch: this.config.fetch
1000
+ });
1001
+ model = customDify(this.config.modelId || "", {
1002
+ apiKey: this.config.apiKey,
1003
+ responseMode: "streaming"
1004
+ });
1005
+ } else {
1006
+ const customOpenAI = openai.createOpenAI({
1007
+ baseURL: this.config.baseURL,
1008
+ apiKey: this.config.apiKey,
1009
+ headers: this.config.headers,
1010
+ fetch: this.config.fetch
1011
+ });
1012
+ model = customOpenAI(this.config.modelId || "");
1013
+ }
1014
+ try {
1015
+ const streamOptions = {
1016
+ model,
1017
+ headers: {
1018
+ ...this.config.headers
1019
+ },
1020
+ allowSystemInMessages: true
1021
+ };
1022
+ if (this.config.providerId === "dify" && this.conversationId) {
1023
+ streamOptions.headers["chat-id"] = this.conversationId;
1024
+ }
1025
+ streamOptions.messages = [
1026
+ { role: "system", content: systemPrompt },
1027
+ ...messages.map((m) => ({
1028
+ role: m.role === "system" ? "system" : m.role === "user" ? "user" : "assistant",
1029
+ content: m.content
1030
+ }))
1031
+ ];
1032
+ const { fullStream } = ai.streamText(streamOptions);
1033
+ for await (const part of fullStream) {
1034
+ if (this.config.providerId === "dify" && !this.conversationId && part?.providerMetadata?.difyWorkflowData?.conversationId || part?.providerMetadata?.dify?.conversationId) {
1035
+ this.conversationId = part.providerMetadata?.difyWorkflowData?.conversationId || part.providerMetadata?.dify?.conversationId;
1036
+ }
1037
+ if (part.type === "text-delta") {
1038
+ yield {
1039
+ type: "text",
1040
+ text: part.textDelta || part.text || ""
1041
+ };
1042
+ } else if (part.type === "finish") {
1043
+ yield {
1044
+ type: "usage",
1045
+ usage: {
1046
+ inputTokens: part.usage?.promptTokens || part.totalUsage?.promptTokens || part.totalUsage?.inputTokens || 0,
1047
+ outputTokens: part.usage?.completionTokens || part.totalUsage?.completionTokens || part.totalUsage?.outputTokens || 0
1048
+ }
1049
+ };
1050
+ } else if (part.type === "error") {
1051
+ yield {
1052
+ type: "error",
1053
+ error: part.error
1054
+ };
1055
+ }
1056
+ }
1057
+ } catch (err) {
1058
+ yield {
1059
+ type: "error",
1060
+ error: err
1061
+ };
1062
+ }
1063
+ }
1064
+ };
1065
+
1066
+ // src/prompt/NodePromptManager.ts
1067
+ var NodePromptManager = class {
1068
+ async getSystemPrompt(context) {
1069
+ let prompt = `# Role
1070
+ you are a highly skilled software engineer AI running in a Node.js/Desktop environment.
1071
+ You have FULL access to the local file system and can execute arbitrary shell commands on the user's machine.
1072
+
1073
+ # Capabilities & Rules
1074
+ 1. **File System**: You can read, write, create, and delete files/directories anywhere accessible to the user process. Always use absolute paths or paths relative to the Current Working Directory.
1075
+ 2. **Terminal**: You can execute system commands (e.g., git, npm, python, file manipulation) directly.
1076
+ 3. **Context**: You are running on a real machine, meaning you have access to real environment variables, local servers (localhost), and local network.
1077
+ 4. **Destructive Actions**: Be extremely careful when executing commands that modify system state or delete files. Double-check paths and commands before execution.
1078
+ 5. **Step-by-step**: Use tools one at a time. Do not assume the outcome of any tool use. Each step must be informed by the previous step's result.
1079
+ 6. **Verification**: Always verify the result of your actions (e.g., run tests, compile code, list directories) before proceeding to the next step or completing the task.
1080
+ 7. **Communication**: Be concise and technical. Formulate your output strictly according to the tools' XML specification.
1081
+
1082
+ TOOL USE
1083
+
1084
+ You have access to a set of tools that are executed upon the user's approval. You can use one tool per message, and will receive the result of that tool use in the user's response. You use tools step-by-step to accomplish a given task, with each tool use informed by the result of the previous tool use.
1085
+
1086
+ # Tool Use Formatting
1087
+
1088
+ Tool use is formatted using XML-style tags. The tool name is enclosed in opening and closing tags, and each parameter is similarly enclosed within its own set of tags. Here's the structure:
1089
+
1090
+ <tool_name>
1091
+ <parameter1_name>value1</parameter1_name>
1092
+ <parameter2_name>value2</parameter2_name>
1093
+ ...
1094
+ </tool_name>
1095
+
1096
+ For example:
1097
+
1098
+ <agent_read_file>
1099
+ <path>src/main.js</path>
1100
+ <task_progress>
1101
+ Checklist here (optional)
1102
+ </task_progress>
1103
+ </agent_read_file>
1104
+
1105
+ Always adhere to this format for the tool use to ensure proper parsing and execution.
1106
+ `;
1107
+ const skillsPrompt = await this.getSkillsPrompt(context.skills);
1108
+ if (skillsPrompt) {
1109
+ prompt += `
1110
+ ${skillsPrompt}
1111
+ `;
1112
+ }
1113
+ prompt += `
1114
+ ${this.getToolInstructions(context)}
1115
+ `;
1116
+ const envPrompt = this.getEnvironmentInfoPrompt(context);
1117
+ if (envPrompt) {
1118
+ prompt += `
1119
+ ${envPrompt}
1120
+ `;
1121
+ }
1122
+ if (context.customInstructions) {
1123
+ prompt += `
1124
+ # User Custom Instructions
1125
+ ${context.customInstructions}
1126
+ `;
1127
+ }
1128
+ return prompt;
1129
+ }
1130
+ getEnvironmentInfoPrompt(context) {
1131
+ let environmentPrompt = `<environment_details>
1132
+ # Environment Info
1133
+ - **Current Working Directory**: \`${context.cwd}\`
1134
+ - **Operating System**: \`${context.os}\`
1135
+ `;
1136
+ if (context.shell) {
1137
+ environmentPrompt += `- **Current Shell**: \`${context.shell}\`
1138
+ `;
1139
+ }
1140
+ return environmentPrompt + `
1141
+ </environment_details>`;
1142
+ }
1143
+ async getSkillsPrompt(skills) {
1144
+ if (!skills || skills.length === 0) return "";
1145
+ try {
1146
+ let prompt = `# Available Skills
1147
+ `;
1148
+ prompt += `You have access to the following skills. You can use the \`agent_load_skill\` tool to load any of them when needed.
1149
+ `;
1150
+ for (const skill of skills) {
1151
+ if (skill && skill.name && skill.description) {
1152
+ prompt += `- **${skill.name}**: ${skill.description}
1153
+ `;
1154
+ }
1155
+ }
1156
+ return prompt;
1157
+ } catch (e) {
1158
+ return "";
1159
+ }
1160
+ }
1161
+ getToolInstructions(context) {
1162
+ const allowDefaultTools = context.allowDefaultTools;
1163
+ const customTools = context.customTools || [];
1164
+ let useDefaultTools = [...defaultTools];
1165
+ if (allowDefaultTools) {
1166
+ useDefaultTools = defaultTools.filter((tool) => allowDefaultTools.includes(tool.name));
1167
+ }
1168
+ return `# Available Tools
1169
+ You can use the following tools by formatting your output as XML blocks. Only use ONE tool per message, and ALWAYS wait for the user's response with the execution result before proceeding.
1170
+
1171
+ ${[...useDefaultTools, ...customTools].map((tool) => {
1172
+ return `### ${tool.name}
1173
+ Description: ${tool.description}
1174
+ Parameters:
1175
+ ${Object.entries(tool.params).map(([name, description]) => `- ${name}: ${description.replaceAll("${context.cwd}", context.cwd)}`).join("\n")}
1176
+ - task_progress: (optional) A checklist showing task progress after this tool use is completed. The task_progress parameter must be included as a separate parameter inside of the parent tool call, it must be separate from other parameters such as content, arguments, etc. (See 'UPDATING TASK PROGRESS' section for more details)
1177
+ Usage:
1178
+ <${tool.name}>
1179
+ ${Object.entries(tool.params).map(([name, description]) => `<${name}>${description.replaceAll("${context.cwd}", context.cwd)}</${name}>`).join("\n")}
1180
+ <task_progress>Checklist here (optional)</task_progress>
1181
+ </${tool.name}>
1182
+ `;
1183
+ }).join("\n")}
1184
+
1185
+ # Tool Use Examples
1186
+ ${useDefaultTools.filter((item) => Boolean(item.example)).map((item) => item.example).join("\n")}}
1187
+
1188
+ # Tool Use Guidelines
1189
+
1190
+ 1. In <thinking> tags, assess what information you already have and what information you need to proceed with the task.
1191
+ 2. Choose the most appropriate tool based on the task and the tool descriptions provided. Assess if you need additional information to proceed, and which of the available tools would be most effective for gathering this information. For example using the list_files tool is more effective than running a command like \`ls\` in the terminal. It's critical that you think about each available tool and use the one that best fits the current step in the task.
1192
+ 3. If multiple actions are needed, use one tool at a time per message to accomplish the task iteratively, with each tool use being informed by the result of the previous tool use. Do not assume the outcome of any tool use. Each step must be informed by the previous step's result.
1193
+ 4. Formulate your tool use using the XML format specified for each tool.
1194
+ 5. After each tool use, the user will respond with the result of that tool use. This result will provide you with the necessary information to continue your task or make further decisions. This response may include:
1195
+ - Information about whether the tool succeeded or failed, along with any reasons for failure.
1196
+ - Linter errors that may have arisen due to the changes you made, which you'll need to address.
1197
+ - New terminal output in reaction to the changes, which you may need to consider or act upon.
1198
+ - Any other relevant feedback or information related to the tool use.
1199
+ 6. ALWAYS wait for user confirmation after each tool use before proceeding. Never assume the success of a tool use without explicit confirmation of the result from the user.
1200
+
1201
+ It is crucial to proceed step-by-step, waiting for the user's message after each tool use before moving forward with the task. This approach allows you to:
1202
+ 1. Confirm the success of each step before proceeding.
1203
+ 2. Address any issues or errors that arise immediately.
1204
+ 3. Adapt your approach based on new information or unexpected results.
1205
+ 4. Ensure that each action builds correctly on the previous ones.
1206
+
1207
+ By waiting for and carefully considering the user's response after each tool use, you can react accordingly and make informed decisions about how to proceed with the task. This iterative process helps ensure the overall success and accuracy of your work.
1208
+
1209
+ ====
1210
+
1211
+ UPDATING TASK PROGRESS
1212
+
1213
+ You can track and communicate your progress on the overall task using the task_progress parameter supported by every tool call. Using task_progress ensures you remain on task, and stay focused on completing the user's objective. This parameter can be used in any mode, and with any tool call.
1214
+
1215
+ - When switching from PLAN MODE to ACT MODE, you must create a comprehensive todo list for the task using the task_progress parameter
1216
+ - Todo list updates should be done silently using the task_progress parameter - do not announce these updates to the user
1217
+ - Use standard Markdown checklist format: "- [ ]" for incomplete items and "- [x]" for completed items
1218
+ - Keep items focused on meaningful progress milestones rather than minor technical details. The checklist should not be so granular that minor implementation details clutter the progress tracking.
1219
+ - For simple tasks, short checklists with even a single item are acceptable. For complex tasks, avoid making the checklist too long or verbose.
1220
+ - If you are creating this checklist for the first time, and the tool use completes the first step in the checklist, make sure to mark it as completed in your task_progress parameter.
1221
+ - Provide the whole checklist of steps you intend to complete in the task, and keep the checkboxes updated as you make progress. It's okay to rewrite this checklist as needed if it becomes invalid due to scope changes or new information.
1222
+ - If a checklist is being used, be sure to update it any time a step has been completed.
1223
+ - The system will automatically include todo list context in your prompts when appropriate - these reminders are important.
1224
+
1225
+ Example:
1226
+ <agent_execute_command>
1227
+ <command>npm install react</command>
1228
+ <requires_approval>false</requires_approval>
1229
+ <task_progress>
1230
+ - [x] Set up project structure
1231
+ - [x] Install dependencies
1232
+ - [ ] Create components
1233
+ - [ ] Test application
1234
+ </task_progress>
1235
+ </agent_execute_command>
1236
+
1237
+ ====
1238
+
1239
+ EDITING FILES
1240
+
1241
+ You have access to two tools for working with files: **agent_write_to_file** and **agent_replace_in_file**. Understanding their roles and selecting the right one for the job will help ensure efficient and accurate modifications.
1242
+
1243
+ # agent_write_to_file
1244
+
1245
+ ## Purpose
1246
+
1247
+ - Create a new file, or overwrite the entire contents of an existing file.
1248
+
1249
+ ## When to Use
1250
+
1251
+ - Initial file creation, such as when scaffolding a new project.
1252
+ - Overwriting large boilerplate files where you want to replace the entire content at once.
1253
+ - When the complexity or number of changes would make agent_replace_in_file unwieldy or error-prone.
1254
+ - When you need to completely restructure a file's content or change its fundamental organization.
1255
+
1256
+ ## Important Considerations
1257
+
1258
+ - Using agent_write_to_file requires providing the file's complete final content.
1259
+ - If you only need to make small changes to an existing file, consider using agent_replace_in_file instead to avoid unnecessarily rewriting the entire file.
1260
+ - While agent_write_to_file should not be your default choice, don't hesitate to use it when the situation truly calls for it.
1261
+
1262
+ # agent_replace_in_file
1263
+
1264
+ ## Purpose
1265
+
1266
+ - Make targeted edits to specific parts of an existing file without overwriting the entire file.
1267
+
1268
+ ## When to Use
1269
+
1270
+ - Small, localized changes like updating a few lines, function implementations, changing variable names, modifying a section of text, etc.
1271
+ - Targeted improvements where only specific portions of the file's content needs to be altered.
1272
+ - Especially useful for long files where much of the file will remain unchanged.
1273
+
1274
+ ## Advantages
1275
+
1276
+ - More efficient for minor edits, since you don't need to supply the entire file content.
1277
+ - Reduces the chance of errors that can occur when overwriting large files.
1278
+
1279
+ # Choosing the Appropriate Tool
1280
+
1281
+ - **Default to agent_replace_in_file** for most changes. It's the safer, more precise option that minimizes potential issues.
1282
+ - **Use agent_write_to_file** when:
1283
+ - Creating new files
1284
+ - The changes are so extensive that using agent_replace_in_file would be more complex or risky
1285
+ - You need to completely reorganize or restructure a file
1286
+ - The file is relatively small and the changes affect most of its content
1287
+ - You're generating boilerplate or template files
1288
+
1289
+ # Auto-formatting Considerations
1290
+
1291
+ - After using either agent_write_to_file or agent_replace_in_file, the user's editor may automatically format the file
1292
+ - This auto-formatting may modify the file contents, for example:
1293
+ - Breaking single lines into multiple lines
1294
+ - Adjusting indentation to match project style (e.g. 2 spaces vs 4 spaces vs tabs)
1295
+ - Converting single quotes to double quotes (or vice versa based on project preferences)
1296
+ - Organizing imports (e.g. sorting, grouping by type)
1297
+ - Adding/removing trailing commas in objects and arrays
1298
+ - Enforcing consistent brace style (e.g. same-line vs new-line)
1299
+ - Standardizing semicolon usage (adding or removing based on style)
1300
+ - The agent_write_to_file and agent_replace_in_file tool responses will include the final state of the file after any auto-formatting
1301
+ - Use this final state as your reference point for any subsequent edits. This is ESPECIALLY important when crafting SEARCH blocks for replace_in_file which require the content to match what's in the file exactly.
1302
+
1303
+ # Workflow Tips
1304
+
1305
+ 1. Before editing, assess the scope of your changes and decide which tool to use.
1306
+ 2. For targeted edits, apply agent_replace_in_file with carefully crafted SEARCH/REPLACE blocks. If you need multiple changes, you can stack multiple SEARCH/REPLACE blocks within a single agent_replace_in_file call.
1307
+ 3. IMPORTANT: When you determine that you need to make several changes to the same file, prefer to use a single replace_in_file call with multiple SEARCH/REPLACE blocks. DO NOT prefer to make multiple successive replace_in_file calls for the same file. For example, if you were to add a component to a file, you would use a single replace_in_file call with a SEARCH/REPLACE block to add the import statement and another SEARCH/REPLACE block to add the component usage, rather than making one replace_in_file call for the import statement and then another separate replace_in_file call for the component usage.
1308
+ 4. For major overhauls or initial file creation, rely on agent_write_to_file.
1309
+ 5. Once the file has been edited with either agent_write_to_file or agent_replace_in_file, the system will provide you with the final state of the modified file. Use this updated content as the reference point for any subsequent SEARCH/REPLACE operations, since it reflects any auto-formatting or user-applied changes.
1310
+ By thoughtfully selecting between agent_write_to_file and agent_replace_in_file, you can make your file editing process smoother, safer, and more efficient.
1311
+
1312
+ ====
1313
+ `;
1314
+ }
1315
+ getNoUseToolInstructions(context) {
1316
+ return `[ERROR] You did not use a tool in your previous response! Please retry with a tool use.
1317
+
1318
+ # Reminder: Instructions for Tool Use
1319
+ Tool uses are formatted using XML-style tags. The tool name is enclosed in opening and closing tags, and each parameter is similarly enclosed within its own set of tags. Here's the structure:
1320
+ <tool_name>
1321
+ <parameter1_name>value1</parameter1_name>
1322
+ <parameter2_name>value2</parameter2_name>
1323
+ ...
1324
+ </tool_name>
1325
+ For example:
1326
+ <agent_attempt_completion>
1327
+ <result>
1328
+ I have completed the task...
1329
+ </result>
1330
+ </agent_attempt_completion>
1331
+ Always adhere to this format for all tool uses to ensure proper parsing and execution.
1332
+
1333
+ # Next Steps
1334
+
1335
+ If you have completed the user's task, use the attempt_completion tool.
1336
+ If you require additional information from the user, use the ask_followup_question tool.
1337
+ Otherwise, if you have not completed the task and do not need additional information, then proceed with the next step of the task.
1338
+ (This is an automated message, so do not respond to it conversationally.)
1339
+ ${this?.getEnvironmentInfoPrompt?.(context)}`;
1340
+ }
1341
+ };
1342
+ var NodeMemoryManager = class {
1343
+ filePath;
1344
+ maxMessages;
1345
+ /**
1346
+ * @param dbPath 存储历史记录的本地文件路径(例如:'./.cline_memory.json')
1347
+ * @param maxMessages 保留的最大消息数量,用于简单的历史截断(默认 150)
1348
+ */
1349
+ constructor(dbPath, maxMessages = 150) {
1350
+ this.filePath = path2__namespace.resolve(dbPath);
1351
+ this.maxMessages = maxMessages;
1352
+ }
1353
+ async ensureFile() {
1354
+ try {
1355
+ await fs2__namespace.access(this.filePath);
1356
+ } catch {
1357
+ const dir = path2__namespace.dirname(this.filePath);
1358
+ await fs2__namespace.mkdir(dir, { recursive: true });
1359
+ await fs2__namespace.writeFile(this.filePath, "[]", "utf-8");
1360
+ }
1361
+ }
1362
+ async readMessages() {
1363
+ await this.ensureFile();
1364
+ const data = await fs2__namespace.readFile(this.filePath, "utf-8");
1365
+ try {
1366
+ return JSON.parse(data);
1367
+ } catch {
1368
+ return [];
1369
+ }
1370
+ }
1371
+ async writeMessages(messages) {
1372
+ await this.ensureFile();
1373
+ await fs2__namespace.writeFile(this.filePath, JSON.stringify(messages, null, 2), "utf-8");
1374
+ }
1375
+ async getHistory() {
1376
+ return this.readMessages();
1377
+ }
1378
+ async appendMessage(message) {
1379
+ const messages = await this.readMessages();
1380
+ messages.push(message);
1381
+ await this.writeMessages(messages);
1382
+ await this.condenseHistory();
1383
+ }
1384
+ async condenseHistory() {
1385
+ const messages = await this.readMessages();
1386
+ if (messages.length > this.maxMessages) {
1387
+ const firstMessage = messages[0];
1388
+ const isFirstSystem = firstMessage && firstMessage.role === "system";
1389
+ const sliceCount = messages.length - this.maxMessages;
1390
+ let condensed;
1391
+ if (isFirstSystem) {
1392
+ condensed = [firstMessage, ...messages.slice(sliceCount + 1)];
1393
+ } else {
1394
+ condensed = messages.slice(sliceCount);
1395
+ }
1396
+ await this.writeMessages(condensed);
1397
+ }
1398
+ }
1399
+ async clear() {
1400
+ await this.writeMessages([]);
1401
+ }
1402
+ };
1403
+
1404
+ // src/index.ts
1405
+ var VERSION = "0.1.0";
1406
+ globalThis.AI_SDK_LOG_WARNINGS = false;
1407
+ var NodeMcpManager = class {
1408
+ config;
1409
+ clients = /* @__PURE__ */ new Map();
1410
+ transports = /* @__PURE__ */ new Map();
1411
+ serverStatuses = /* @__PURE__ */ new Map();
1412
+ constructor(config) {
1413
+ this.config = config;
1414
+ }
1415
+ /**
1416
+ * 初始化并连接所有的 MCP Servers
1417
+ */
1418
+ async init() {
1419
+ const connectPromises = Object.entries(this.config.servers).map(async ([name, serverConfig]) => {
1420
+ this.serverStatuses.set(name, { name, status: "connecting" });
1421
+ try {
1422
+ const transport = new stdio_js.StdioClientTransport({
1423
+ command: serverConfig.command,
1424
+ args: serverConfig.args,
1425
+ env: { ...process.env, ...serverConfig.env }
1426
+ });
1427
+ const client = new index_js.Client(
1428
+ {
1429
+ name: "cline-agent-sdk",
1430
+ version: "0.1.0"
1431
+ },
1432
+ {
1433
+ capabilities: {}
1434
+ }
1435
+ );
1436
+ await client.connect(transport);
1437
+ this.clients.set(name, client);
1438
+ this.transports.set(name, transport);
1439
+ this.serverStatuses.set(name, { name, status: "connected" });
1440
+ } catch (err) {
1441
+ this.serverStatuses.set(name, { name, status: "disconnected", error: err.message });
1442
+ }
1443
+ });
1444
+ await Promise.all(connectPromises);
1445
+ }
1446
+ getServers() {
1447
+ return Array.from(this.serverStatuses.values());
1448
+ }
1449
+ async getTools() {
1450
+ const allTools = [];
1451
+ for (const [serverName, client] of this.clients.entries()) {
1452
+ try {
1453
+ const response = await client.listTools();
1454
+ if (response && response.tools) {
1455
+ for (const tool of response.tools) {
1456
+ allTools.push({
1457
+ name: `${serverName}__${tool.name}`,
1458
+ description: tool.description,
1459
+ inputSchema: tool.inputSchema
1460
+ });
1461
+ }
1462
+ }
1463
+ } catch (err) {
1464
+ console.error(`Failed to get tools from MCP server [${serverName}]: ${err.message}`);
1465
+ }
1466
+ }
1467
+ return allTools;
1468
+ }
1469
+ async callTool(serverName, toolName, args) {
1470
+ const client = this.clients.get(serverName);
1471
+ if (!client) {
1472
+ return {
1473
+ content: [{ type: "text", text: `MCP Server [${serverName}] is not connected.` }],
1474
+ isError: true
1475
+ };
1476
+ }
1477
+ const prefix = `${serverName}__`;
1478
+ const actualToolName = toolName.startsWith(prefix) ? toolName.slice(prefix.length) : toolName;
1479
+ try {
1480
+ const response = await client.callTool({
1481
+ name: actualToolName,
1482
+ arguments: args
1483
+ });
1484
+ return {
1485
+ content: response.content,
1486
+ isError: !!response.isError
1487
+ };
1488
+ } catch (err) {
1489
+ return {
1490
+ content: [{ type: "text", text: `Error calling tool ${toolName} on server ${serverName}: ${err.message}` }],
1491
+ isError: true
1492
+ };
1493
+ }
1494
+ }
1495
+ async readResource(serverName, uri) {
1496
+ const client = this.clients.get(serverName);
1497
+ if (!client) {
1498
+ throw new Error(`MCP Server [${serverName}] is not connected.`);
1499
+ }
1500
+ try {
1501
+ const response = await client.readResource({ uri });
1502
+ return response.contents;
1503
+ } catch (err) {
1504
+ throw new Error(`Error reading resource ${uri} from server ${serverName}: ${err.message}`);
1505
+ }
1506
+ }
1507
+ /**
1508
+ * 断开并清理所有的 MCP Servers
1509
+ */
1510
+ async destroy() {
1511
+ for (const [name, client] of this.clients.entries()) {
1512
+ try {
1513
+ await client.close();
1514
+ } catch (e) {
1515
+ }
1516
+ }
1517
+ for (const [name, transport] of this.transports.entries()) {
1518
+ try {
1519
+ await transport.close();
1520
+ } catch (e) {
1521
+ }
1522
+ }
1523
+ this.clients.clear();
1524
+ this.transports.clear();
1525
+ this.serverStatuses.clear();
1526
+ }
1527
+ };
1528
+
1529
+ // src/runtime/nodeRuntime.ts
1530
+ var execAsync = util.promisify(child_process.exec);
1531
+ var DefaultNodeRuntime = class {
1532
+ fs = {
1533
+ readFile: async (filepath) => fs2__namespace.readFile(filepath, "utf-8"),
1534
+ writeFile: async (filepath, content) => {
1535
+ await fs2__namespace.mkdir(path2__namespace.dirname(filepath), { recursive: true });
1536
+ await fs2__namespace.writeFile(filepath, content, "utf-8");
1537
+ },
1538
+ deleteFile: (filepath) => fs2__namespace.unlink(filepath),
1539
+ deleteDirectory: (dirpath) => fs2__namespace.rm(dirpath, { recursive: true, force: true }),
1540
+ fileExists: async (filepath) => {
1541
+ try {
1542
+ await fs2__namespace.access(filepath);
1543
+ return true;
1544
+ } catch {
1545
+ return false;
1546
+ }
1547
+ },
1548
+ readDir: (dirpath) => fs2__namespace.readdir(dirpath, { withFileTypes: true }),
1549
+ mkdir: async (dirpath) => {
1550
+ await fs2__namespace.mkdir(dirpath, { recursive: true });
1551
+ }
1552
+ };
1553
+ path = {
1554
+ join: (...paths) => path2__namespace.join(...paths)
1555
+ };
1556
+ env = {
1557
+ get: (key) => process.env[key],
1558
+ cwd: () => process.cwd(),
1559
+ osInfo: () => `${os__namespace.type()} ${os__namespace.release()} ${os__namespace.arch()}`,
1560
+ shell: () => process.env.SHELL || process.env.ComSpec || "unknown"
1561
+ };
1562
+ terminal = {
1563
+ execCommand: async (command, options) => {
1564
+ try {
1565
+ const { stdout, stderr } = await execAsync(command, { cwd: options?.cwd || process.cwd() });
1566
+ return { stdout, stderr, exitCode: 0 };
1567
+ } catch (err) {
1568
+ return { stdout: err.stdout || "", stderr: err.stderr || err.message, exitCode: err.code || 1 };
1569
+ }
1570
+ }
1571
+ };
1572
+ };
1573
+ function createNodeAgent(options) {
1574
+ const runtime = new DefaultNodeRuntime();
1575
+ const api = new NodeApiHandler(options.apiConfig);
1576
+ const memory = options.memory || new NodeMemoryManager(options.dbPath || path2__namespace.join(runtime.env.cwd(), ".cline_memory.json"));
1577
+ const customTools = options.customTools || [];
1578
+ const customToolNames = new Set(customTools.map((t) => t.name));
1579
+ const promptManager = new NodePromptManager();
1580
+ const agent = new ClineAgent({
1581
+ runtime,
1582
+ api,
1583
+ promptManager,
1584
+ memory,
1585
+ customTools,
1586
+ allowDefaultTools: options.allowDefaultTools,
1587
+ maxLoopCount: options.maxLoopCount,
1588
+ customInstructions: options.customInstructions
1589
+ });
1590
+ agent.onToolCall = async (tool) => {
1591
+ if (customToolNames.has(tool.name)) {
1592
+ const customTool = customTools.find((t) => t.name === tool.name);
1593
+ if (customTool.onCall) {
1594
+ return customTool.onCall(tool.params);
1595
+ }
1596
+ return `Error: Custom tool "${tool.name}" does not have an onCall method.`;
1597
+ }
1598
+ };
1599
+ return agent;
1600
+ }
1601
+
1602
+ exports.AgentDefaultTool = AgentDefaultTool;
1603
+ exports.AgentState = AgentState;
1604
+ exports.ClineAgent = ClineAgent;
1605
+ exports.DefaultNodeRuntime = DefaultNodeRuntime;
1606
+ exports.NodeMcpManager = NodeMcpManager;
1607
+ exports.READ_ONLY_TOOLS = READ_ONLY_TOOLS;
1608
+ exports.TOOL_RESULT_BLOCK = TOOL_RESULT_BLOCK;
1609
+ exports.VERSION = VERSION;
1610
+ exports.createNodeAgent = createNodeAgent;
1611
+ exports.defaultTools = defaultTools;
1612
+ exports.getToolUseNames = getToolUseNames;
1613
+ exports.parseAssistantMessageV2 = parseAssistantMessageV2;
1614
+ exports.setDynamicToolUseNames = setDynamicToolUseNames;
1615
+ exports.toolParamNames = toolParamNames;
1616
+ exports.toolUseNames = toolUseNames;
1617
+ //# sourceMappingURL=nodeRuntime.js.map
1618
+ //# sourceMappingURL=nodeRuntime.js.map