@amical/aiagent-sdk 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +476 -0
- package/dist/index.d.ts +476 -0
- package/dist/index.js +968 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +951 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +7 -1
- package/.agents/skills/Viral_Writer/SKILL.md +0 -239
- package/.cline_memory.json +0 -58
- package/.node-version +0 -1
- package/Agents.md +0 -95
- package/src/agent/Agent.ts +0 -566
- package/src/agent/index.ts +0 -1
- package/src/index.ts +0 -15
- package/src/llm/NodeApiHandler.ts +0 -117
- package/src/llm/WebApiHandler.ts +0 -118
- package/src/llm/index.ts +0 -47
- package/src/mcp/NodeMcpManager.ts +0 -158
- package/src/mcp/WebMcpManager.ts +0 -30
- package/src/mcp/index.ts +0 -56
- package/src/memory/NodeMemoryManager.ts +0 -82
- package/src/memory/WebMemoryManager.ts +0 -89
- package/src/memory/index.ts +0 -36
- package/src/parser/diff.ts +0 -855
- package/src/parser/index.ts +0 -111
- package/src/parser/parse-assistant-message.ts +0 -240
- package/src/prompt/NodePromptManager.ts +0 -276
- package/src/prompt/WebPromptManager.ts +0 -277
- package/src/prompt/index.ts +0 -28
- package/src/runtime/nodeRuntime.ts +0 -112
- package/src/runtime/web.test.ts +0 -95
- package/src/runtime/webRuntime.ts +0 -119
- package/src/runtime.ts +0 -46
- package/src/shared/tools.ts +0 -270
- package/test-node-agent.ts +0 -113
- package/test-runtime.mjs +0 -36
- package/test.md +0 -33
- package/tsconfig.json +0 -28
- package/tsup.config.ts +0 -21
- package/uapi.ts +0 -3
- package/webFetch.ts +0 -49
- package/webSearch.ts +0 -19
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,951 @@
|
|
|
1
|
+
import { nanoid } from 'nanoid';
|
|
2
|
+
import matter from 'gray-matter';
|
|
3
|
+
|
|
4
|
+
// src/shared/tools.ts
|
|
5
|
+
var AgentDefaultTool = /* @__PURE__ */ ((AgentDefaultTool2) => {
|
|
6
|
+
AgentDefaultTool2["ASK"] = "agent_ask_followup_question";
|
|
7
|
+
AgentDefaultTool2["ATTEMPT"] = "agent_attempt_completion";
|
|
8
|
+
AgentDefaultTool2["BASH"] = "agent_execute_command";
|
|
9
|
+
AgentDefaultTool2["FILE_EDIT"] = "agent_replace_in_file";
|
|
10
|
+
AgentDefaultTool2["FILE_READ"] = "agent_read_file";
|
|
11
|
+
AgentDefaultTool2["FILE_NEW"] = "agent_write_to_file";
|
|
12
|
+
AgentDefaultTool2["FILE_DELETE"] = "agent_delete_file";
|
|
13
|
+
AgentDefaultTool2["DIR_DELETE"] = "agent_delete_directory";
|
|
14
|
+
AgentDefaultTool2["SEARCH"] = "agent_search_files";
|
|
15
|
+
AgentDefaultTool2["LIST_FILES"] = "agent_list_files";
|
|
16
|
+
AgentDefaultTool2["LIST_CODE_DEF"] = "agent_list_code_definition_names";
|
|
17
|
+
AgentDefaultTool2["BROWSER"] = "agent_browser_action";
|
|
18
|
+
AgentDefaultTool2["MCP_USE"] = "agent_use_mcp_tool";
|
|
19
|
+
AgentDefaultTool2["MCP_ACCESS"] = "agent_access_mcp_resource";
|
|
20
|
+
AgentDefaultTool2["MCP_DOCS"] = "agent_load_mcp_documentation";
|
|
21
|
+
AgentDefaultTool2["NEW_TASK"] = "agent_new_task";
|
|
22
|
+
AgentDefaultTool2["PLAN_MODE"] = "agent_plan_mode_respond";
|
|
23
|
+
AgentDefaultTool2["ACT_MODE"] = "agent_act_mode_respond";
|
|
24
|
+
AgentDefaultTool2["TODO"] = "agent_focus_chain";
|
|
25
|
+
AgentDefaultTool2["WEB_FETCH"] = "agent_web_fetch";
|
|
26
|
+
AgentDefaultTool2["WEB_SEARCH"] = "agent_web_search";
|
|
27
|
+
AgentDefaultTool2["CONDENSE"] = "agent_condense";
|
|
28
|
+
AgentDefaultTool2["SUMMARIZE_TASK"] = "agent_summarize_task";
|
|
29
|
+
AgentDefaultTool2["REPORT_BUG"] = "agent_report_bug";
|
|
30
|
+
AgentDefaultTool2["NEW_RULE"] = "agent_new_rule";
|
|
31
|
+
AgentDefaultTool2["APPLY_PATCH"] = "agent_apply_patch";
|
|
32
|
+
AgentDefaultTool2["GENERATE_EXPLANATION"] = "agent_generate_explanation";
|
|
33
|
+
AgentDefaultTool2["LOAD_SKILL"] = "agent_load_skill";
|
|
34
|
+
AgentDefaultTool2["USE_SUBAGENTS"] = "agent_use_subagents";
|
|
35
|
+
return AgentDefaultTool2;
|
|
36
|
+
})(AgentDefaultTool || {});
|
|
37
|
+
var TOOL_RESULT_BLOCK = "tool_call_result";
|
|
38
|
+
var defaultTools = [
|
|
39
|
+
{
|
|
40
|
+
name: "agent_ask_followup_question" /* ASK */,
|
|
41
|
+
description: "Ask the user a clarifying question if more information is needed.",
|
|
42
|
+
params: {
|
|
43
|
+
question: "The question to ask the user."
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "agent_attempt_completion" /* ATTEMPT */,
|
|
48
|
+
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.",
|
|
49
|
+
params: {
|
|
50
|
+
result: "(required) The result of the tool use. This should be a clear, specific description of the result."
|
|
51
|
+
},
|
|
52
|
+
example: `## Example: ${"agent_attempt_completion" /* ATTEMPT */}
|
|
53
|
+
<${"agent_attempt_completion" /* ATTEMPT */}>
|
|
54
|
+
<result>final result or message</result>
|
|
55
|
+
<task_progress>
|
|
56
|
+
- [x] Set up project structure
|
|
57
|
+
- [x] Install dependencies
|
|
58
|
+
- [x] Run command to start server
|
|
59
|
+
- [x] Test application
|
|
60
|
+
</task_progress>
|
|
61
|
+
</${"agent_attempt_completion" /* ATTEMPT */}>`
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
name: "agent_execute_command" /* BASH */,
|
|
65
|
+
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.",
|
|
66
|
+
params: {
|
|
67
|
+
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."
|
|
68
|
+
},
|
|
69
|
+
example: `## Example: Requesting to execute a command
|
|
70
|
+
|
|
71
|
+
<${"agent_execute_command" /* BASH */}>
|
|
72
|
+
<command>npm run dev</command>
|
|
73
|
+
<requires_approval>false</requires_approval>
|
|
74
|
+
<task_progress>
|
|
75
|
+
- [x] Set up project structure
|
|
76
|
+
- [x] Install dependencies
|
|
77
|
+
- [ ] Run command to start server
|
|
78
|
+
- [ ] Test application
|
|
79
|
+
</task_progress>
|
|
80
|
+
</${"agent_execute_command" /* BASH */}>`
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "agent_replace_in_file" /* FILE_EDIT */,
|
|
84
|
+
description: "Replace specific content in a file using a search/replace diff block.",
|
|
85
|
+
params: {
|
|
86
|
+
path: "(required) The absolute or relative file path to modify.",
|
|
87
|
+
diff: "(required) The diff content to apply."
|
|
88
|
+
},
|
|
89
|
+
example: `## Example: Requesting to make targeted edits to a file
|
|
90
|
+
|
|
91
|
+
<${"agent_replace_in_file" /* FILE_EDIT */}>
|
|
92
|
+
<path>src/components/App.tsx</path>
|
|
93
|
+
<diff>
|
|
94
|
+
------- SEARCH
|
|
95
|
+
import React from 'react';
|
|
96
|
+
=======
|
|
97
|
+
import React, { useState } from 'react';
|
|
98
|
+
+++++++ REPLACE
|
|
99
|
+
|
|
100
|
+
------- SEARCH
|
|
101
|
+
function handleSubmit() {
|
|
102
|
+
saveData();
|
|
103
|
+
setLoading(false);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
=======
|
|
107
|
+
+++++++ REPLACE
|
|
108
|
+
|
|
109
|
+
------- SEARCH
|
|
110
|
+
return (
|
|
111
|
+
<div>
|
|
112
|
+
=======
|
|
113
|
+
function handleSubmit() {
|
|
114
|
+
saveData();
|
|
115
|
+
setLoading(false);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<div>
|
|
120
|
+
+++++++ REPLACE
|
|
121
|
+
</diff>
|
|
122
|
+
<task_progress>
|
|
123
|
+
- [x] Set up project structure
|
|
124
|
+
- [x] Install dependencies
|
|
125
|
+
- [ ] Create components
|
|
126
|
+
- [ ] Test application
|
|
127
|
+
</task_progress>
|
|
128
|
+
</${"agent_replace_in_file" /* FILE_EDIT */}>`
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
name: "agent_read_file" /* FILE_READ */,
|
|
132
|
+
description: "Read the contents of a specific file.",
|
|
133
|
+
params: {
|
|
134
|
+
path: "(required) The absolute or relative file path to read."
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: "agent_write_to_file" /* FILE_NEW */,
|
|
139
|
+
description: "Create or overwrite a file with new content.",
|
|
140
|
+
params: {
|
|
141
|
+
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.",
|
|
142
|
+
content: "(required) The content to write to the file."
|
|
143
|
+
},
|
|
144
|
+
example: `## Example: Requesting to create a new file
|
|
145
|
+
|
|
146
|
+
<${"agent_write_to_file" /* FILE_NEW */}>
|
|
147
|
+
<path>src/frontend-config.json</path>
|
|
148
|
+
<content>
|
|
149
|
+
{
|
|
150
|
+
"apiEndpoint": "https://api.example.com",
|
|
151
|
+
"theme": {
|
|
152
|
+
"primaryColor": "#007bff",
|
|
153
|
+
"secondaryColor": "#6c757d",
|
|
154
|
+
"fontFamily": "Arial, sans-serif"
|
|
155
|
+
},
|
|
156
|
+
"features": {
|
|
157
|
+
"darkMode": true,
|
|
158
|
+
"notifications": true,
|
|
159
|
+
"analytics": false
|
|
160
|
+
},
|
|
161
|
+
"version": "1.0.0"
|
|
162
|
+
}
|
|
163
|
+
</content>
|
|
164
|
+
<task_progress>
|
|
165
|
+
- [x] Set up project structure
|
|
166
|
+
- [x] Install dependencies
|
|
167
|
+
- [x] Create components
|
|
168
|
+
- [ ] Test application
|
|
169
|
+
</task_progress>
|
|
170
|
+
</${"agent_write_to_file" /* FILE_NEW */}>`
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
name: "agent_delete_file" /* FILE_DELETE */,
|
|
174
|
+
description: "Delete a file.",
|
|
175
|
+
params: {
|
|
176
|
+
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."
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
name: "agent_delete_directory" /* DIR_DELETE */,
|
|
181
|
+
description: "Delete a directory.",
|
|
182
|
+
params: {
|
|
183
|
+
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."
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: "agent_search_files" /* SEARCH */,
|
|
188
|
+
description: "Search for files in a directory that match a regex pattern or glob pattern.",
|
|
189
|
+
params: {
|
|
190
|
+
path: "(required) The absolute or relative directory path to search.",
|
|
191
|
+
regex: "(required) The regex pattern to match files against.",
|
|
192
|
+
file_pattern: "(optional) glob pattern like *.ts."
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: "agent_list_files" /* LIST_FILES */,
|
|
197
|
+
description: "List all files in a directory.",
|
|
198
|
+
params: {
|
|
199
|
+
path: "(required) The absolute or relative directory path to list."
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
//================
|
|
203
|
+
{
|
|
204
|
+
name: "agent_new_task" /* NEW_TASK */,
|
|
205
|
+
description: "Create a new task with a given context.",
|
|
206
|
+
params: {
|
|
207
|
+
context: "(required) The context of the new task."
|
|
208
|
+
},
|
|
209
|
+
example: `## Example: Creating a new task
|
|
210
|
+
<${"agent_new_task" /* NEW_TASK */}>
|
|
211
|
+
<context>
|
|
212
|
+
1. Current Work:
|
|
213
|
+
[Detailed description]
|
|
214
|
+
|
|
215
|
+
2. Key Technical Concepts:
|
|
216
|
+
- [Concept 1]
|
|
217
|
+
- [Concept 2]
|
|
218
|
+
- [...]
|
|
219
|
+
|
|
220
|
+
3. Relevant Files and Code:
|
|
221
|
+
- [File Name 1]
|
|
222
|
+
- [Summary of why this file is important]
|
|
223
|
+
- [Summary of the changes made to this file, if any]
|
|
224
|
+
- [Important Code Snippet]
|
|
225
|
+
- [File Name 2]
|
|
226
|
+
- [Important Code Snippet]
|
|
227
|
+
- [...]
|
|
228
|
+
|
|
229
|
+
4. Problem Solving:
|
|
230
|
+
[Detailed description]
|
|
231
|
+
|
|
232
|
+
5. Pending Tasks and Next Steps:
|
|
233
|
+
- [Task 1 details & next steps]
|
|
234
|
+
- [Task 2 details & next steps]
|
|
235
|
+
- [...]
|
|
236
|
+
</context>
|
|
237
|
+
</${"agent_new_task" /* NEW_TASK */}>`
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
name: "agent_load_skill" /* LOAD_SKILL */,
|
|
241
|
+
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.",
|
|
242
|
+
params: {
|
|
243
|
+
skill_name: "(required) The name of the skill to load."
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
];
|
|
247
|
+
var toolUseNames = Object.values(AgentDefaultTool);
|
|
248
|
+
var dynamicToolUseNamesByNamespace = /* @__PURE__ */ new Map();
|
|
249
|
+
function setDynamicToolUseNames(namespace, names) {
|
|
250
|
+
dynamicToolUseNamesByNamespace.set(namespace, new Set(names.map((name) => name.trim()).filter(Boolean)));
|
|
251
|
+
}
|
|
252
|
+
function getToolUseNames() {
|
|
253
|
+
const defaults = [...toolUseNames];
|
|
254
|
+
const dynamic = Array.from(dynamicToolUseNamesByNamespace.values()).flatMap((set) => Array.from(set));
|
|
255
|
+
return Array.from(/* @__PURE__ */ new Set([...defaults, ...dynamic]));
|
|
256
|
+
}
|
|
257
|
+
var READ_ONLY_TOOLS = [
|
|
258
|
+
"agent_list_files" /* LIST_FILES */,
|
|
259
|
+
"agent_read_file" /* FILE_READ */,
|
|
260
|
+
"agent_search_files" /* SEARCH */,
|
|
261
|
+
"agent_list_code_definition_names" /* LIST_CODE_DEF */,
|
|
262
|
+
"agent_browser_action" /* BROWSER */,
|
|
263
|
+
"agent_ask_followup_question" /* ASK */,
|
|
264
|
+
"agent_web_search" /* WEB_SEARCH */,
|
|
265
|
+
"agent_web_fetch" /* WEB_FETCH */,
|
|
266
|
+
"agent_load_skill" /* LOAD_SKILL */,
|
|
267
|
+
"agent_use_subagents" /* USE_SUBAGENTS */
|
|
268
|
+
];
|
|
269
|
+
function parseAssistantMessageV2(assistantMessage, toolParamNames2) {
|
|
270
|
+
const contentBlocks = [];
|
|
271
|
+
let currentTextContentStart = 0;
|
|
272
|
+
let currentTextContent;
|
|
273
|
+
let currentToolUseStart = 0;
|
|
274
|
+
let currentToolUse;
|
|
275
|
+
let currentParamValueStart = 0;
|
|
276
|
+
let currentParamName;
|
|
277
|
+
const toolUseOpenTags = /* @__PURE__ */ new Map();
|
|
278
|
+
const toolParamOpenTags = /* @__PURE__ */ new Map();
|
|
279
|
+
for (const name of getToolUseNames()) {
|
|
280
|
+
toolUseOpenTags.set(`<${name}>`, name);
|
|
281
|
+
}
|
|
282
|
+
for (const name of toolParamNames2) {
|
|
283
|
+
toolParamOpenTags.set(`<${name}>`, name);
|
|
284
|
+
}
|
|
285
|
+
const len = assistantMessage.length;
|
|
286
|
+
for (let i = 0; i < len; i++) {
|
|
287
|
+
const currentCharIndex = i;
|
|
288
|
+
if (currentToolUse && currentParamName) {
|
|
289
|
+
const closeTag = `</${currentParamName}>`;
|
|
290
|
+
if (currentCharIndex >= closeTag.length - 1 && assistantMessage.startsWith(
|
|
291
|
+
closeTag,
|
|
292
|
+
currentCharIndex - closeTag.length + 1
|
|
293
|
+
// Start checking from potential start of tag
|
|
294
|
+
)) {
|
|
295
|
+
const value = assistantMessage.slice(
|
|
296
|
+
currentParamValueStart,
|
|
297
|
+
// Start after the opening tag
|
|
298
|
+
currentCharIndex - closeTag.length + 1
|
|
299
|
+
// End before the closing tag
|
|
300
|
+
).trim();
|
|
301
|
+
currentToolUse.params[currentParamName] = value;
|
|
302
|
+
currentParamName = void 0;
|
|
303
|
+
} else {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
if (currentToolUse && !currentParamName) {
|
|
308
|
+
let startedNewParam = false;
|
|
309
|
+
for (const [tag, paramName] of toolParamOpenTags.entries()) {
|
|
310
|
+
if (currentCharIndex >= tag.length - 1 && assistantMessage.startsWith(tag, currentCharIndex - tag.length + 1)) {
|
|
311
|
+
currentParamName = paramName;
|
|
312
|
+
currentParamValueStart = currentCharIndex + 1;
|
|
313
|
+
startedNewParam = true;
|
|
314
|
+
break;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
if (startedNewParam) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const toolCloseTag = `</${currentToolUse.name}>`;
|
|
321
|
+
if (currentCharIndex >= toolCloseTag.length - 1 && assistantMessage.startsWith(toolCloseTag, currentCharIndex - toolCloseTag.length + 1)) {
|
|
322
|
+
const toolContentSlice = assistantMessage.slice(
|
|
323
|
+
currentToolUseStart,
|
|
324
|
+
// From after the tool opening tag
|
|
325
|
+
currentCharIndex - toolCloseTag.length + 1
|
|
326
|
+
// To before the tool closing tag
|
|
327
|
+
);
|
|
328
|
+
const contentParamName = "content";
|
|
329
|
+
if (currentToolUse.name === "agent_write_to_file" /* FILE_NEW */ && toolContentSlice.includes(`<${contentParamName}>`)) {
|
|
330
|
+
const contentStartTag = `<${contentParamName}>`;
|
|
331
|
+
const contentEndTag = `</${contentParamName}>`;
|
|
332
|
+
const contentStart = toolContentSlice.indexOf(contentStartTag);
|
|
333
|
+
const contentEnd = toolContentSlice.lastIndexOf(contentEndTag);
|
|
334
|
+
if (contentStart !== -1 && contentEnd !== -1 && contentEnd > contentStart) {
|
|
335
|
+
const contentValue = toolContentSlice.slice(contentStart + contentStartTag.length, contentEnd).trim();
|
|
336
|
+
currentToolUse.params[contentParamName] = contentValue;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
currentToolUse.partial = false;
|
|
340
|
+
contentBlocks.push(currentToolUse);
|
|
341
|
+
currentToolUse = void 0;
|
|
342
|
+
currentTextContentStart = currentCharIndex + 1;
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
if (!currentToolUse) {
|
|
348
|
+
let startedNewTool = false;
|
|
349
|
+
for (const [tag, toolName] of toolUseOpenTags.entries()) {
|
|
350
|
+
if (currentCharIndex >= tag.length - 1 && assistantMessage.startsWith(tag, currentCharIndex - tag.length + 1)) {
|
|
351
|
+
if (currentTextContent) {
|
|
352
|
+
currentTextContent.content = assistantMessage.slice(
|
|
353
|
+
currentTextContentStart,
|
|
354
|
+
// From where text started
|
|
355
|
+
currentCharIndex - tag.length + 1
|
|
356
|
+
// To before the tool tag starts
|
|
357
|
+
).trim();
|
|
358
|
+
currentTextContent.partial = false;
|
|
359
|
+
if (currentTextContent.content.length > 0) {
|
|
360
|
+
contentBlocks.push(currentTextContent);
|
|
361
|
+
}
|
|
362
|
+
currentTextContent = void 0;
|
|
363
|
+
} else {
|
|
364
|
+
const potentialText = assistantMessage.slice(
|
|
365
|
+
currentTextContentStart,
|
|
366
|
+
// From where text *might* have started
|
|
367
|
+
currentCharIndex - tag.length + 1
|
|
368
|
+
// To before the tool tag starts
|
|
369
|
+
).trim();
|
|
370
|
+
if (potentialText.length > 0) {
|
|
371
|
+
contentBlocks.push({
|
|
372
|
+
type: "text",
|
|
373
|
+
content: potentialText,
|
|
374
|
+
partial: false
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
currentToolUse = {
|
|
379
|
+
type: "tool_use",
|
|
380
|
+
name: toolName,
|
|
381
|
+
params: {},
|
|
382
|
+
partial: true,
|
|
383
|
+
// Assume partial until closing tag is found
|
|
384
|
+
call_id: nanoid(8),
|
|
385
|
+
isNativeToolCall: false
|
|
386
|
+
};
|
|
387
|
+
currentToolUseStart = currentCharIndex + 1;
|
|
388
|
+
startedNewTool = true;
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (startedNewTool) {
|
|
393
|
+
continue;
|
|
394
|
+
}
|
|
395
|
+
if (!currentTextContent) {
|
|
396
|
+
currentTextContentStart = currentCharIndex;
|
|
397
|
+
currentTextContent = {
|
|
398
|
+
type: "text",
|
|
399
|
+
content: "",
|
|
400
|
+
// Will be determined by slicing at the end or when a tool starts
|
|
401
|
+
partial: true
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
if (currentToolUse && currentParamName) {
|
|
407
|
+
currentToolUse.params[currentParamName] = assistantMessage.slice(currentParamValueStart).trim();
|
|
408
|
+
}
|
|
409
|
+
if (currentToolUse) {
|
|
410
|
+
contentBlocks.push(currentToolUse);
|
|
411
|
+
} else if (currentTextContent) {
|
|
412
|
+
currentTextContent.content = assistantMessage.slice(currentTextContentStart).trim();
|
|
413
|
+
if (currentTextContent.content.length > 0) {
|
|
414
|
+
contentBlocks.push(currentTextContent);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return contentBlocks;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// src/parser/index.ts
|
|
421
|
+
var toolParamNames = [
|
|
422
|
+
"command",
|
|
423
|
+
"requires_approval",
|
|
424
|
+
"path",
|
|
425
|
+
"absolutePath",
|
|
426
|
+
"content",
|
|
427
|
+
"diff",
|
|
428
|
+
"regex",
|
|
429
|
+
"file_pattern",
|
|
430
|
+
"recursive",
|
|
431
|
+
"action",
|
|
432
|
+
"url",
|
|
433
|
+
"coordinate",
|
|
434
|
+
"text",
|
|
435
|
+
"query",
|
|
436
|
+
"allowed_domains",
|
|
437
|
+
"blocked_domains",
|
|
438
|
+
"prompt",
|
|
439
|
+
"server_name",
|
|
440
|
+
"tool_name",
|
|
441
|
+
"arguments",
|
|
442
|
+
"uri",
|
|
443
|
+
"question",
|
|
444
|
+
"options",
|
|
445
|
+
"response",
|
|
446
|
+
"result",
|
|
447
|
+
"context",
|
|
448
|
+
"title",
|
|
449
|
+
"what_happened",
|
|
450
|
+
"steps_to_reproduce",
|
|
451
|
+
"api_request_output",
|
|
452
|
+
"additional_context",
|
|
453
|
+
"needs_more_exploration",
|
|
454
|
+
"task_progress",
|
|
455
|
+
"timeout",
|
|
456
|
+
"input",
|
|
457
|
+
"from_ref",
|
|
458
|
+
"to_ref",
|
|
459
|
+
"skill_name",
|
|
460
|
+
"prompt_1",
|
|
461
|
+
"prompt_2",
|
|
462
|
+
"prompt_3",
|
|
463
|
+
"prompt_4",
|
|
464
|
+
"prompt_5",
|
|
465
|
+
"start_line",
|
|
466
|
+
"end_line"
|
|
467
|
+
];
|
|
468
|
+
var AgentState = /* @__PURE__ */ ((AgentState2) => {
|
|
469
|
+
AgentState2["IDLE"] = "idle";
|
|
470
|
+
AgentState2["THINKING"] = "thinking";
|
|
471
|
+
AgentState2["WAITING_FOR_USER"] = "waiting_for_user";
|
|
472
|
+
AgentState2["FINISHED"] = "finished";
|
|
473
|
+
AgentState2["ERROR"] = "error";
|
|
474
|
+
return AgentState2;
|
|
475
|
+
})(AgentState || {});
|
|
476
|
+
var ClineAgent = class {
|
|
477
|
+
runtime;
|
|
478
|
+
api;
|
|
479
|
+
promptManager;
|
|
480
|
+
memory;
|
|
481
|
+
mcp;
|
|
482
|
+
state = "idle" /* IDLE */;
|
|
483
|
+
allToolParamNames = [...toolParamNames];
|
|
484
|
+
/** 循环计数器 */
|
|
485
|
+
loopCount = 0;
|
|
486
|
+
/** 最大循环次数 */
|
|
487
|
+
maxLoopCount;
|
|
488
|
+
skillDir;
|
|
489
|
+
customTools;
|
|
490
|
+
customToolNames;
|
|
491
|
+
allowDefaultTools;
|
|
492
|
+
customInstructions;
|
|
493
|
+
sysPrompt;
|
|
494
|
+
noUseTollSysPrompt;
|
|
495
|
+
// 简单的事件回调系统,供宿主环境注册以监听 Agent 内部事件
|
|
496
|
+
onStateChange;
|
|
497
|
+
onStreamChunk;
|
|
498
|
+
onToolCall;
|
|
499
|
+
constructor(options) {
|
|
500
|
+
this.runtime = options.runtime;
|
|
501
|
+
this.api = options.api;
|
|
502
|
+
this.promptManager = options.promptManager;
|
|
503
|
+
this.memory = options.memory;
|
|
504
|
+
this.mcp = options.mcp;
|
|
505
|
+
this.maxLoopCount = options.maxLoopCount ?? 150;
|
|
506
|
+
this.customTools = options.customTools || [];
|
|
507
|
+
this.allowDefaultTools = options.allowDefaultTools;
|
|
508
|
+
if (this.allowDefaultTools && !this.allowDefaultTools.includes("agent_attempt_completion" /* ATTEMPT */)) {
|
|
509
|
+
this.allowDefaultTools.push("agent_attempt_completion" /* ATTEMPT */);
|
|
510
|
+
}
|
|
511
|
+
this.customInstructions = options.customInstructions;
|
|
512
|
+
if (this.customTools.length > 0) {
|
|
513
|
+
const dynamicToolNames = /* @__PURE__ */ new Set();
|
|
514
|
+
const customToolParams = /* @__PURE__ */ new Set();
|
|
515
|
+
for (const customTool of this.customTools) {
|
|
516
|
+
dynamicToolNames.add(customTool.name);
|
|
517
|
+
if (customTool.params) {
|
|
518
|
+
for (const key in customTool.params) {
|
|
519
|
+
if (!Object.hasOwn(customTool.params, key)) continue;
|
|
520
|
+
customToolParams.add(key);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
const defaultToolNames = Object.values(AgentDefaultTool);
|
|
525
|
+
const overlappingTools = Array.from(dynamicToolNames).filter((name) => defaultToolNames.includes(name));
|
|
526
|
+
if (overlappingTools.length > 0) {
|
|
527
|
+
throw new Error(`Custom tools and default tools have overlapping names: ${overlappingTools.join(", ")}`);
|
|
528
|
+
}
|
|
529
|
+
if (dynamicToolNames.size > 0) {
|
|
530
|
+
setDynamicToolUseNames("customUser", Array.from(dynamicToolNames));
|
|
531
|
+
}
|
|
532
|
+
if (customToolParams.size > 0) {
|
|
533
|
+
this.allToolParamNames = Array.from(/* @__PURE__ */ new Set([...this.allToolParamNames, ...Array.from(customToolParams)]));
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
this.customToolNames = new Set(this.customTools.map((t) => t.name));
|
|
537
|
+
this.skillDir = this.runtime.path.join(this.runtime.env.cwd(), ".agent/skills");
|
|
538
|
+
}
|
|
539
|
+
setState(newState) {
|
|
540
|
+
this.state = newState;
|
|
541
|
+
if (this.onStateChange) {
|
|
542
|
+
this.onStateChange(newState);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* 获取当前 Agent 的系统提示词
|
|
547
|
+
* 如果 force 为 true,则强制重新获取系统提示词
|
|
548
|
+
*/
|
|
549
|
+
async getPrompt(force = false) {
|
|
550
|
+
if (!force && this.sysPrompt && this.noUseTollSysPrompt) {
|
|
551
|
+
return { sysPrompt: this.sysPrompt, noUseTollSysPrompt: this.noUseTollSysPrompt };
|
|
552
|
+
}
|
|
553
|
+
const context = {
|
|
554
|
+
cwd: this.runtime.env.cwd(),
|
|
555
|
+
os: this.runtime.env.osInfo(),
|
|
556
|
+
shell: this.runtime.env.shell(),
|
|
557
|
+
skills: await this.getSkills(),
|
|
558
|
+
customTools: this.customTools,
|
|
559
|
+
allowDefaultTools: this.allowDefaultTools,
|
|
560
|
+
customInstructions: this.customInstructions
|
|
561
|
+
};
|
|
562
|
+
this.sysPrompt = await this.promptManager.getSystemPrompt(context);
|
|
563
|
+
this.noUseTollSysPrompt = this.promptManager.getNoUseToolInstructions(context);
|
|
564
|
+
return { sysPrompt: this.sysPrompt, noUseTollSysPrompt: this.noUseTollSysPrompt };
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* 启动一个新的任务
|
|
568
|
+
*/
|
|
569
|
+
async startTask(taskDescription) {
|
|
570
|
+
this.setState("thinking" /* THINKING */);
|
|
571
|
+
try {
|
|
572
|
+
await this.memory.clear();
|
|
573
|
+
this.loopCount = 0;
|
|
574
|
+
await this.memory.appendMessage({
|
|
575
|
+
role: "user",
|
|
576
|
+
content: taskDescription
|
|
577
|
+
});
|
|
578
|
+
await this.loop();
|
|
579
|
+
} catch (err) {
|
|
580
|
+
this.setState("error" /* ERROR */);
|
|
581
|
+
throw err;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
async getSkills() {
|
|
585
|
+
const skillDir = this.skillDir;
|
|
586
|
+
const skillList = [];
|
|
587
|
+
if (!this.runtime.fs.fileExists(skillDir)) {
|
|
588
|
+
return skillList;
|
|
589
|
+
}
|
|
590
|
+
const files = await this.runtime.fs.readDir(skillDir);
|
|
591
|
+
const skills = files.filter((item) => item.isDirectory()).map((item) => item.name);
|
|
592
|
+
if (skills.length === 0) {
|
|
593
|
+
return [];
|
|
594
|
+
}
|
|
595
|
+
for (const skill of skills) {
|
|
596
|
+
try {
|
|
597
|
+
const skillPath = this.runtime.path.join(skillDir, skill);
|
|
598
|
+
const files2 = await this.runtime.fs.readDir(skillPath);
|
|
599
|
+
const skillFile = files2.map((item) => item.isFile()).find((f) => f.toLowerCase() === "skill.md");
|
|
600
|
+
if (skillFile) {
|
|
601
|
+
const mdPath = this.runtime.path.join(skillPath, skillFile);
|
|
602
|
+
const mdContent = await this.runtime.fs.readFile(mdPath);
|
|
603
|
+
const parsed = matter(mdContent);
|
|
604
|
+
if (parsed.data && parsed.data.description) {
|
|
605
|
+
let description = String(parsed.data.description).trim();
|
|
606
|
+
description = description.replace(/\s+/g, " ").trim();
|
|
607
|
+
if (description) {
|
|
608
|
+
skillList.push({
|
|
609
|
+
name: skill,
|
|
610
|
+
description
|
|
611
|
+
});
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
} catch (e) {
|
|
616
|
+
return skillList;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* 核心任务循环
|
|
622
|
+
*/
|
|
623
|
+
async loop() {
|
|
624
|
+
const { sysPrompt, noUseTollSysPrompt } = await this.getPrompt(true);
|
|
625
|
+
const { customTools, customToolNames } = this;
|
|
626
|
+
while (this.state === "thinking" /* THINKING */) {
|
|
627
|
+
this.loopCount++;
|
|
628
|
+
if (this.loopCount > this.maxLoopCount) {
|
|
629
|
+
await this.memory.appendMessage({
|
|
630
|
+
role: "user",
|
|
631
|
+
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.`
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
const history = await this.memory.getHistory();
|
|
635
|
+
const stream = this.api.createMessage(sysPrompt, history);
|
|
636
|
+
let fullResponseText = "";
|
|
637
|
+
for await (const chunk of stream) {
|
|
638
|
+
if (chunk.type === "text" && chunk.text) {
|
|
639
|
+
fullResponseText += chunk.text;
|
|
640
|
+
}
|
|
641
|
+
if (this.onStreamChunk) {
|
|
642
|
+
this.onStreamChunk(chunk);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
await this.memory.appendMessage({
|
|
646
|
+
role: "assistant",
|
|
647
|
+
content: fullResponseText
|
|
648
|
+
});
|
|
649
|
+
const parsedBlocks = parseAssistantMessageV2(fullResponseText, this.allToolParamNames);
|
|
650
|
+
const toolUses = parsedBlocks.filter((b) => b.type === "tool_use");
|
|
651
|
+
if (toolUses.length === 0) {
|
|
652
|
+
await this.memory.appendMessage({
|
|
653
|
+
role: "user",
|
|
654
|
+
content: noUseTollSysPrompt
|
|
655
|
+
});
|
|
656
|
+
} else {
|
|
657
|
+
const toolResults = [];
|
|
658
|
+
for (const tool of toolUses) {
|
|
659
|
+
if (this.onToolCall) {
|
|
660
|
+
const hookResult = await this.onToolCall(tool);
|
|
661
|
+
if (hookResult) {
|
|
662
|
+
toolResults.push({ tool, result: hookResult });
|
|
663
|
+
continue;
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
if (customToolNames.has(tool.name)) {
|
|
667
|
+
const customTool = customTools.find((t) => t.name === tool.name);
|
|
668
|
+
if (customTool.onCall) {
|
|
669
|
+
try {
|
|
670
|
+
const res = await customTool.onCall(tool.params);
|
|
671
|
+
toolResults.push({ tool, result: res });
|
|
672
|
+
} catch (error) {
|
|
673
|
+
toolResults.push({ tool, result: `Error: ${error.message}` });
|
|
674
|
+
}
|
|
675
|
+
} else {
|
|
676
|
+
toolResults.push({ tool, result: `Error: Custom tool "${tool.name}" does not have an onCall method.` });
|
|
677
|
+
}
|
|
678
|
+
continue;
|
|
679
|
+
}
|
|
680
|
+
if (tool.name === "agent_attempt_completion" /* ATTEMPT */) {
|
|
681
|
+
toolResults.push({ tool, result: "Task marked as completed." });
|
|
682
|
+
this.setState("finished" /* FINISHED */);
|
|
683
|
+
break;
|
|
684
|
+
} else if (tool.name === "agent_read_file" /* FILE_READ */) {
|
|
685
|
+
const path = tool.params.path;
|
|
686
|
+
if (path) {
|
|
687
|
+
try {
|
|
688
|
+
const content = await this.runtime.fs.readFile(path);
|
|
689
|
+
toolResults.push({ tool, result: content });
|
|
690
|
+
} catch (error) {
|
|
691
|
+
toolResults.push({ tool, result: `Error: ${error.message}` });
|
|
692
|
+
}
|
|
693
|
+
} else {
|
|
694
|
+
toolResults.push({ tool, result: "Error: No path provided." });
|
|
695
|
+
}
|
|
696
|
+
} else if (tool.name === "agent_execute_command" /* BASH */) {
|
|
697
|
+
const cmd = tool.params.command;
|
|
698
|
+
if (cmd) {
|
|
699
|
+
const result = await this.runtime.terminal.execCommand(cmd);
|
|
700
|
+
toolResults.push({ tool, result: `STDOUT: ${result.stdout}
|
|
701
|
+
STDERR: ${result.stderr}` });
|
|
702
|
+
}
|
|
703
|
+
} else if (tool.name === "agent_write_to_file" /* FILE_NEW */) {
|
|
704
|
+
const path = tool.params.path;
|
|
705
|
+
const content = tool.params.content;
|
|
706
|
+
if (path && content !== void 0) {
|
|
707
|
+
try {
|
|
708
|
+
await this.runtime.fs.writeFile(path, content);
|
|
709
|
+
toolResults.push({ tool, result: `Successfully wrote to ${path}` });
|
|
710
|
+
} catch (error) {
|
|
711
|
+
toolResults.push({ tool, result: `Error: ${error.message}` });
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
} else if (tool.name === "agent_list_files" /* LIST_FILES */) {
|
|
715
|
+
const path = tool.params.path || this.runtime.env.cwd();
|
|
716
|
+
try {
|
|
717
|
+
const files = await this.runtime.fs.readDir(path);
|
|
718
|
+
toolResults.push({ tool, result: files.map((f) => f.name + (f.isDirectory() ? "/" : "")).join("\n") });
|
|
719
|
+
} catch (e) {
|
|
720
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
721
|
+
}
|
|
722
|
+
} else if (tool.name === "agent_replace_in_file" /* FILE_EDIT */) {
|
|
723
|
+
const path = tool.params.path;
|
|
724
|
+
const diff = tool.params.diff;
|
|
725
|
+
if (path && diff) {
|
|
726
|
+
try {
|
|
727
|
+
const content = await this.runtime.fs.readFile(path);
|
|
728
|
+
const newContent = this.applyDiff(content, diff);
|
|
729
|
+
await this.runtime.fs.writeFile(path, newContent);
|
|
730
|
+
toolResults.push({ tool, result: `Successfully replaced content in ${path}` });
|
|
731
|
+
} catch (e) {
|
|
732
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
733
|
+
}
|
|
734
|
+
} else {
|
|
735
|
+
toolResults.push({ tool, result: "Error: Missing path or diff." });
|
|
736
|
+
}
|
|
737
|
+
} else if (tool.name === "agent_delete_file" /* FILE_DELETE */) {
|
|
738
|
+
const path = tool.params.path;
|
|
739
|
+
if (path) {
|
|
740
|
+
try {
|
|
741
|
+
await this.runtime.fs.deleteFile(path);
|
|
742
|
+
toolResults.push({ tool, result: `Successfully deleted ${path}` });
|
|
743
|
+
} catch (e) {
|
|
744
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
toolResults.push({ tool, result: "Error: Missing path." });
|
|
748
|
+
}
|
|
749
|
+
} else if (tool.name === "agent_delete_directory" /* DIR_DELETE */) {
|
|
750
|
+
const path = tool.params.path;
|
|
751
|
+
if (path) {
|
|
752
|
+
try {
|
|
753
|
+
await this.runtime.fs.deleteDirectory(path);
|
|
754
|
+
toolResults.push({ tool, result: `Successfully deleted ${path}` });
|
|
755
|
+
} catch (e) {
|
|
756
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
757
|
+
}
|
|
758
|
+
} else {
|
|
759
|
+
toolResults.push({ tool, result: "Error: Missing path." });
|
|
760
|
+
}
|
|
761
|
+
} else if (tool.name === "agent_ask_followup_question" /* ASK */) {
|
|
762
|
+
const question = tool.params.question;
|
|
763
|
+
toolResults.push({ tool, result: `Asking user: ${question}` });
|
|
764
|
+
this.setState("waiting_for_user" /* WAITING_FOR_USER */);
|
|
765
|
+
break;
|
|
766
|
+
} else if (tool.name === "agent_search_files" /* SEARCH */) {
|
|
767
|
+
const path = tool.params.path || this.runtime.env.cwd();
|
|
768
|
+
const regexStr = tool.params.regex;
|
|
769
|
+
const filePattern = tool.params.file_pattern;
|
|
770
|
+
if (regexStr && this.runtime.fs.searchFiles) {
|
|
771
|
+
try {
|
|
772
|
+
const result = await this.runtime.fs.searchFiles(path, regexStr, filePattern);
|
|
773
|
+
toolResults.push({ tool, result: `${result}` });
|
|
774
|
+
} catch (e) {
|
|
775
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
776
|
+
}
|
|
777
|
+
} else {
|
|
778
|
+
toolResults.push({ tool, result: `Error: searchFiles not supported by runtime or missing regex.` });
|
|
779
|
+
}
|
|
780
|
+
} else if (tool.name === "agent_use_mcp_tool" /* MCP_USE */) {
|
|
781
|
+
const serverName = tool.params.server_name;
|
|
782
|
+
const toolName = tool.params.tool_name;
|
|
783
|
+
const args = tool.params.arguments;
|
|
784
|
+
if (this.mcp && serverName && toolName) {
|
|
785
|
+
try {
|
|
786
|
+
let parsedArgs = args;
|
|
787
|
+
if (typeof args === "string") {
|
|
788
|
+
parsedArgs = JSON.parse(args);
|
|
789
|
+
}
|
|
790
|
+
const result = await this.mcp.callTool(serverName, toolName, parsedArgs);
|
|
791
|
+
if (result.isError) {
|
|
792
|
+
toolResults.push({ tool, result: `Error executing MCP tool: ${JSON.stringify(result.content)}` });
|
|
793
|
+
} else {
|
|
794
|
+
toolResults.push({ tool, result: `${JSON.stringify(result.content)}` });
|
|
795
|
+
}
|
|
796
|
+
} catch (e) {
|
|
797
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
798
|
+
}
|
|
799
|
+
} else {
|
|
800
|
+
toolResults.push({ tool, result: `Error: MCP Manager not available or missing parameters.` });
|
|
801
|
+
}
|
|
802
|
+
} else if (tool.name === "agent_access_mcp_resource" /* MCP_ACCESS */) {
|
|
803
|
+
const serverName = tool.params.server_name;
|
|
804
|
+
const uri = tool.params.uri;
|
|
805
|
+
if (this.mcp && this.mcp.readResource && serverName && uri) {
|
|
806
|
+
try {
|
|
807
|
+
const result = await this.mcp.readResource(serverName, uri);
|
|
808
|
+
toolResults.push({ tool, result: `${JSON.stringify(result)}` });
|
|
809
|
+
} catch (e) {
|
|
810
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
811
|
+
}
|
|
812
|
+
} else {
|
|
813
|
+
toolResults.push({ tool, result: `Error: MCP Manager not available, readResource not implemented, or missing parameters.` });
|
|
814
|
+
}
|
|
815
|
+
} else if (tool.name === "agent_load_mcp_documentation" /* MCP_DOCS */) {
|
|
816
|
+
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...`;
|
|
817
|
+
toolResults.push({ tool, result: docs });
|
|
818
|
+
} else if (tool.name === "agent_list_code_definition_names" /* LIST_CODE_DEF */) {
|
|
819
|
+
const path = tool.params.path || this.runtime.env.cwd();
|
|
820
|
+
try {
|
|
821
|
+
const result = await this.runtime.fs.searchFiles?.(path, "^(class|function|const|let|var|export|interface|type)\\s+\\w+", "*.ts|*.js");
|
|
822
|
+
toolResults.push({ tool, result: `${result ? result : "No definitions found or searchFiles not supported."}` });
|
|
823
|
+
} catch (e) {
|
|
824
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
825
|
+
}
|
|
826
|
+
} else if (tool.name === "agent_web_fetch" /* WEB_FETCH */) {
|
|
827
|
+
const url = tool.params.url;
|
|
828
|
+
if (url) {
|
|
829
|
+
try {
|
|
830
|
+
const res = await fetch(url);
|
|
831
|
+
const text = await res.text();
|
|
832
|
+
toolResults.push({ tool, result: text.substring(0, 3e3) });
|
|
833
|
+
} catch (e) {
|
|
834
|
+
toolResults.push({ tool, result: `Error: ${e.message}` });
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
} else if (tool.name === "agent_focus_chain" /* TODO */) {
|
|
838
|
+
toolResults.push({ tool, result: `Focus chain updated successfully.` });
|
|
839
|
+
} else if (tool.name === "agent_plan_mode_respond" /* PLAN_MODE */ || tool.name === "agent_act_mode_respond" /* ACT_MODE */) {
|
|
840
|
+
toolResults.push({ tool, result: `Mode switch acknowledged.` });
|
|
841
|
+
} else if (tool.name === "agent_new_rule" /* NEW_RULE */) {
|
|
842
|
+
toolResults.push({ tool, result: `Rule recorded in current context.` });
|
|
843
|
+
} else if (tool.name === "agent_new_task" /* NEW_TASK */) {
|
|
844
|
+
toolResults.push({ tool, result: `New task request received. Terminating current task.` });
|
|
845
|
+
this.setState("finished" /* FINISHED */);
|
|
846
|
+
break;
|
|
847
|
+
} else if (tool.name === "agent_load_skill" /* LOAD_SKILL */) {
|
|
848
|
+
const skillName = tool.params.skill_name || tool.params.skill;
|
|
849
|
+
if (!skillName) {
|
|
850
|
+
toolResults.push({ tool, result: `"Error: Missing required parameter 'skill_name'. Please provide the name of the skill to activate."` });
|
|
851
|
+
} else {
|
|
852
|
+
const skillDir = this.skillDir;
|
|
853
|
+
const skillFilePath = this.runtime.path.join(skillDir, skillName, "SKILL.md");
|
|
854
|
+
try {
|
|
855
|
+
const fileExists = await this.runtime.fs.fileExists(skillFilePath);
|
|
856
|
+
if (!fileExists) {
|
|
857
|
+
toolResults.push({ tool, result: `Error: Skill "${skillName}" not found at ${skillFilePath}.` });
|
|
858
|
+
} else {
|
|
859
|
+
const content = await this.runtime.fs.readFile(skillFilePath);
|
|
860
|
+
toolResults.push({
|
|
861
|
+
tool,
|
|
862
|
+
result: `# Skill "${skillName}" is now active
|
|
863
|
+
|
|
864
|
+
${content}
|
|
865
|
+
|
|
866
|
+
---
|
|
867
|
+
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.`
|
|
868
|
+
});
|
|
869
|
+
}
|
|
870
|
+
} catch (err) {
|
|
871
|
+
toolResults.push({ tool, result: `Error loading skill "${skillName}": ${err.message}` });
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
} else if (tool.name === "agent_browser_action" /* BROWSER */ || tool.name === "agent_web_search" /* WEB_SEARCH */ || tool.name === "agent_apply_patch" /* APPLY_PATCH */) {
|
|
875
|
+
toolResults.push({ tool, result: `This tool requires specific host integration. If you see this, the host environment has not implemented it yet.` });
|
|
876
|
+
} 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 */) {
|
|
877
|
+
toolResults.push({ tool, result: `Action logged successfully.` });
|
|
878
|
+
} else {
|
|
879
|
+
toolResults.push({ tool, result: `Executed by host or unsupported.` });
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
if (this.state === "thinking" /* THINKING */ && toolResults.length > 0) {
|
|
883
|
+
const toolResultsContext = toolResults.map((tr) => `<${TOOL_RESULT_BLOCK} tool_name="${tr.tool.name}">
|
|
884
|
+
${typeof tr.result === "string" ? tr.result.trim() : JSON.stringify(tr.result)}
|
|
885
|
+
</${TOOL_RESULT_BLOCK}>`).join("\n\n");
|
|
886
|
+
if (this.onStreamChunk) {
|
|
887
|
+
this.onStreamChunk({ type: "text", text: toolResultsContext });
|
|
888
|
+
}
|
|
889
|
+
await this.memory.appendMessage({
|
|
890
|
+
role: "user",
|
|
891
|
+
content: toolResultsContext
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* 简单的 Diff 解析与替换辅助方法
|
|
899
|
+
*/
|
|
900
|
+
applyDiff(content, diff) {
|
|
901
|
+
const regex = /-------\s*SEARCH\r?\n(.*?)\r?\n=======\r?\n(.*?)\r?\n\+\+\+\+\+\+\+\s*REPLACE/gs;
|
|
902
|
+
let newContent = content;
|
|
903
|
+
let match;
|
|
904
|
+
let matchCount = 0;
|
|
905
|
+
while ((match = regex.exec(diff)) !== null) {
|
|
906
|
+
matchCount++;
|
|
907
|
+
const searchBlock = match[1];
|
|
908
|
+
const replaceBlock = match[2];
|
|
909
|
+
const idx = newContent.indexOf(searchBlock);
|
|
910
|
+
if (idx !== -1) {
|
|
911
|
+
newContent = newContent.substring(0, idx) + replaceBlock + newContent.substring(idx + searchBlock.length);
|
|
912
|
+
} else {
|
|
913
|
+
throw new Error(`Search block not found in file:
|
|
914
|
+
${searchBlock.substring(0, 100)}...`);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
if (matchCount === 0) {
|
|
918
|
+
throw new Error(`No valid SEARCH/REPLACE blocks found in the diff.`);
|
|
919
|
+
}
|
|
920
|
+
return newContent;
|
|
921
|
+
}
|
|
922
|
+
/**
|
|
923
|
+
* 恢复被中断的循环(例如等待用户输入/确认后继续)
|
|
924
|
+
*/
|
|
925
|
+
async resume(userInput) {
|
|
926
|
+
if (userInput) {
|
|
927
|
+
await this.memory.appendMessage({
|
|
928
|
+
role: "user",
|
|
929
|
+
content: userInput
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
this.setState("thinking" /* THINKING */);
|
|
933
|
+
await this.loop();
|
|
934
|
+
}
|
|
935
|
+
async appendHistory(history) {
|
|
936
|
+
for (const message of history) {
|
|
937
|
+
await this.memory.appendMessage(message);
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
async getHistory() {
|
|
941
|
+
return this.memory.getHistory();
|
|
942
|
+
}
|
|
943
|
+
};
|
|
944
|
+
|
|
945
|
+
// src/index.ts
|
|
946
|
+
var VERSION = "0.1.0";
|
|
947
|
+
globalThis.AI_SDK_LOG_WARNINGS = false;
|
|
948
|
+
|
|
949
|
+
export { AgentDefaultTool, AgentState, ClineAgent, READ_ONLY_TOOLS, TOOL_RESULT_BLOCK, VERSION, defaultTools, getToolUseNames, parseAssistantMessageV2, setDynamicToolUseNames, toolParamNames, toolUseNames };
|
|
950
|
+
//# sourceMappingURL=index.mjs.map
|
|
951
|
+
//# sourceMappingURL=index.mjs.map
|