@xagent-ai/cli 1.2.0 → 1.2.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/README.md +1 -1
- package/README_CN.md +1 -1
- package/dist/agents.js +164 -164
- package/dist/agents.js.map +1 -1
- package/dist/ai-client.d.ts +4 -6
- package/dist/ai-client.d.ts.map +1 -1
- package/dist/ai-client.js +137 -115
- package/dist/ai-client.js.map +1 -1
- package/dist/auth.js +4 -4
- package/dist/auth.js.map +1 -1
- package/dist/cli.js +184 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.js +3 -3
- package/dist/config.js.map +1 -1
- package/dist/context-compressor.d.ts.map +1 -1
- package/dist/context-compressor.js +65 -81
- package/dist/context-compressor.js.map +1 -1
- package/dist/conversation.d.ts +1 -1
- package/dist/conversation.d.ts.map +1 -1
- package/dist/conversation.js +5 -31
- package/dist/conversation.js.map +1 -1
- package/dist/memory.d.ts +5 -1
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +77 -37
- package/dist/memory.js.map +1 -1
- package/dist/remote-ai-client.d.ts +1 -8
- package/dist/remote-ai-client.d.ts.map +1 -1
- package/dist/remote-ai-client.js +55 -65
- package/dist/remote-ai-client.js.map +1 -1
- package/dist/retry.d.ts +35 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +166 -0
- package/dist/retry.js.map +1 -0
- package/dist/session.d.ts +0 -5
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +243 -312
- package/dist/session.js.map +1 -1
- package/dist/slash-commands.d.ts +1 -0
- package/dist/slash-commands.d.ts.map +1 -1
- package/dist/slash-commands.js +91 -9
- package/dist/slash-commands.js.map +1 -1
- package/dist/smart-approval.d.ts.map +1 -1
- package/dist/smart-approval.js +18 -17
- package/dist/smart-approval.js.map +1 -1
- package/dist/system-prompt-generator.d.ts.map +1 -1
- package/dist/system-prompt-generator.js +149 -139
- package/dist/system-prompt-generator.js.map +1 -1
- package/dist/theme.d.ts +48 -0
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +254 -0
- package/dist/theme.js.map +1 -1
- package/dist/tools/edit-diff.d.ts +32 -0
- package/dist/tools/edit-diff.d.ts.map +1 -0
- package/dist/tools/edit-diff.js +185 -0
- package/dist/tools/edit-diff.js.map +1 -0
- package/dist/tools/edit.d.ts +11 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +129 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools.d.ts +19 -5
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +979 -631
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +6 -31
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
- package/src/agents.ts +504 -504
- package/src/ai-client.ts +1559 -1458
- package/src/auth.ts +4 -4
- package/src/cli.ts +195 -1
- package/src/config.ts +3 -3
- package/src/memory.ts +55 -14
- package/src/remote-ai-client.ts +663 -683
- package/src/retry.ts +217 -0
- package/src/session.ts +1736 -1840
- package/src/slash-commands.ts +98 -9
- package/src/smart-approval.ts +626 -625
- package/src/system-prompt-generator.ts +853 -843
- package/src/theme.ts +284 -0
- package/src/tools.ts +390 -70
package/dist/tools.js
CHANGED
|
@@ -35,34 +35,34 @@ const execAsync = promisify(exec);
|
|
|
35
35
|
//
|
|
36
36
|
export class ReadTool {
|
|
37
37
|
name = 'Read';
|
|
38
|
-
description = `Read the contents of a file. This is your PRIMARY tool for understanding existing code, configuration, and documentation.
|
|
39
|
-
|
|
40
|
-
# When to Use
|
|
41
|
-
- When you need to understand existing code before making changes
|
|
42
|
-
- When user asks you to "read", "show", "view", or "check" a file
|
|
43
|
-
- When debugging and need to inspect source files
|
|
44
|
-
- When analyzing project structure by reading key files
|
|
45
|
-
- When examining configuration files (package.json, tsconfig.json, etc.)
|
|
46
|
-
- When checking documentation or README files
|
|
47
|
-
|
|
48
|
-
# When NOT to Use
|
|
49
|
-
- For files you've already read in the same conversation (use memory instead)
|
|
50
|
-
- When you only need file metadata (use ListDirectory or Bash with ls instead)
|
|
51
|
-
- For binary files that cannot be read as text
|
|
52
|
-
|
|
53
|
-
# Parameters
|
|
54
|
-
- \`filePath\`: Absolute path or path relative to project root
|
|
55
|
-
- \`offset\`: (Optional) Line number to start reading from (0-based)
|
|
56
|
-
- \`limit\`: (Optional) Maximum number of lines to read
|
|
57
|
-
|
|
58
|
-
# Examples
|
|
59
|
-
- Read specific file: Read(filePath="/path/to/file.ts")
|
|
60
|
-
- Read with pagination: Read(filePath="src/app.ts", offset=0, limit=100)
|
|
61
|
-
|
|
62
|
-
# Best Practices
|
|
63
|
-
- Use absolute paths or paths relative to the project root
|
|
64
|
-
- Use offset and limit for large files to avoid loading entire content
|
|
65
|
-
- Combine with ListDirectory to explore project structure first
|
|
38
|
+
description = `Read the contents of a file. This is your PRIMARY tool for understanding existing code, configuration, and documentation.
|
|
39
|
+
|
|
40
|
+
# When to Use
|
|
41
|
+
- When you need to understand existing code before making changes
|
|
42
|
+
- When user asks you to "read", "show", "view", or "check" a file
|
|
43
|
+
- When debugging and need to inspect source files
|
|
44
|
+
- When analyzing project structure by reading key files
|
|
45
|
+
- When examining configuration files (package.json, tsconfig.json, etc.)
|
|
46
|
+
- When checking documentation or README files
|
|
47
|
+
|
|
48
|
+
# When NOT to Use
|
|
49
|
+
- For files you've already read in the same conversation (use memory instead)
|
|
50
|
+
- When you only need file metadata (use ListDirectory or Bash with ls instead)
|
|
51
|
+
- For binary files that cannot be read as text
|
|
52
|
+
|
|
53
|
+
# Parameters
|
|
54
|
+
- \`filePath\`: Absolute path or path relative to project root
|
|
55
|
+
- \`offset\`: (Optional) Line number to start reading from (0-based)
|
|
56
|
+
- \`limit\`: (Optional) Maximum number of lines to read
|
|
57
|
+
|
|
58
|
+
# Examples
|
|
59
|
+
- Read specific file: Read(filePath="/path/to/file.ts")
|
|
60
|
+
- Read with pagination: Read(filePath="src/app.ts", offset=0, limit=100)
|
|
61
|
+
|
|
62
|
+
# Best Practices
|
|
63
|
+
- Use absolute paths or paths relative to the project root
|
|
64
|
+
- Use offset and limit for large files to avoid loading entire content
|
|
65
|
+
- Combine with ListDirectory to explore project structure first
|
|
66
66
|
- Don't re-read files unnecessarily`;
|
|
67
67
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
68
68
|
async execute(params) {
|
|
@@ -104,32 +104,32 @@ export class ReadTool {
|
|
|
104
104
|
}
|
|
105
105
|
export class WriteTool {
|
|
106
106
|
name = 'Write';
|
|
107
|
-
description = `Create a new file or completely overwrite an existing file with new content.
|
|
108
|
-
|
|
109
|
-
# When to Use
|
|
110
|
-
- Creating new files (source code, configuration, documentation)
|
|
111
|
-
- Completely replacing file content (not partial edits)
|
|
112
|
-
- Generating files from templates or scratch
|
|
113
|
-
- When user explicitly asks to "create", "write", or "generate" a file
|
|
114
|
-
|
|
115
|
-
# When NOT to Use
|
|
116
|
-
- For making small edits to existing files (use
|
|
117
|
-
- When you only need to append content (read file first, then write)
|
|
118
|
-
- For creating directories (use CreateDirectory instead)
|
|
119
|
-
|
|
120
|
-
# Parameters
|
|
121
|
-
- \`filePath\`: Absolute path or path relative to project root
|
|
122
|
-
- \`content\`: The complete content to write to the file
|
|
123
|
-
|
|
124
|
-
# Examples
|
|
125
|
-
- Create new file: Write(filePath="src/utils.ts", content="...")
|
|
126
|
-
- Create config file: Write(filePath=".env.example", content="API_KEY=...")
|
|
127
|
-
|
|
128
|
-
# Best Practices
|
|
129
|
-
- Parent directories are created automatically
|
|
130
|
-
- Use appropriate file extensions
|
|
131
|
-
- Ensure content is complete and syntactically correct
|
|
132
|
-
- For partial edits, use
|
|
107
|
+
description = `Create a new file or completely overwrite an existing file with new content.
|
|
108
|
+
|
|
109
|
+
# When to Use
|
|
110
|
+
- Creating new files (source code, configuration, documentation)
|
|
111
|
+
- Completely replacing file content (not partial edits)
|
|
112
|
+
- Generating files from templates or scratch
|
|
113
|
+
- When user explicitly asks to "create", "write", or "generate" a file
|
|
114
|
+
|
|
115
|
+
# When NOT to Use
|
|
116
|
+
- For making small edits to existing files (use edit instead)
|
|
117
|
+
- When you only need to append content (read file first, then write)
|
|
118
|
+
- For creating directories (use CreateDirectory instead)
|
|
119
|
+
|
|
120
|
+
# Parameters
|
|
121
|
+
- \`filePath\`: Absolute path or path relative to project root
|
|
122
|
+
- \`content\`: The complete content to write to the file
|
|
123
|
+
|
|
124
|
+
# Examples
|
|
125
|
+
- Create new file: Write(filePath="src/utils.ts", content="...")
|
|
126
|
+
- Create config file: Write(filePath=".env.example", content="API_KEY=...")
|
|
127
|
+
|
|
128
|
+
# Best Practices
|
|
129
|
+
- Parent directories are created automatically
|
|
130
|
+
- Use appropriate file extensions
|
|
131
|
+
- Ensure content is complete and syntactically correct
|
|
132
|
+
- For partial edits, use Edit tool instead`;
|
|
133
133
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.SMART];
|
|
134
134
|
async execute(params) {
|
|
135
135
|
const { filePath, content } = params;
|
|
@@ -138,9 +138,15 @@ export class WriteTool {
|
|
|
138
138
|
const dir = path.dirname(absolutePath);
|
|
139
139
|
await fs.mkdir(dir, { recursive: true });
|
|
140
140
|
await fs.writeFile(absolutePath, content, 'utf-8');
|
|
141
|
+
const lineCount = content.split('\n').length;
|
|
142
|
+
const preview = content.split('\n').slice(0, 10).join('\n');
|
|
143
|
+
const isTruncated = lineCount > 10;
|
|
141
144
|
return {
|
|
142
145
|
success: true,
|
|
143
|
-
message: `Successfully wrote to ${filePath}
|
|
146
|
+
message: `Successfully wrote to ${filePath}`,
|
|
147
|
+
filePath,
|
|
148
|
+
lineCount,
|
|
149
|
+
preview: isTruncated ? preview + '\n...' : preview
|
|
144
150
|
};
|
|
145
151
|
}
|
|
146
152
|
catch (error) {
|
|
@@ -150,39 +156,39 @@ export class WriteTool {
|
|
|
150
156
|
}
|
|
151
157
|
export class GrepTool {
|
|
152
158
|
name = 'Grep';
|
|
153
|
-
description = `Search for text patterns within files using regex or literal string matching. This is your PRIMARY tool for finding specific code, functions, or content.
|
|
154
|
-
|
|
155
|
-
# When to Use
|
|
156
|
-
- Finding specific function definitions or calls
|
|
157
|
-
- Searching for variable usages or imports
|
|
158
|
-
- Locating error messages or log statements
|
|
159
|
-
- Finding all occurrences of a pattern across the codebase
|
|
160
|
-
- When you need line-by-line results with context
|
|
161
|
-
|
|
162
|
-
# When NOT to Use
|
|
163
|
-
- When you only need to find files containing text (use
|
|
164
|
-
- When searching by file pattern rather than content (use
|
|
165
|
-
- For very large codebases where you only need file names (
|
|
166
|
-
|
|
167
|
-
# Parameters
|
|
168
|
-
- \`pattern\`: Regex or literal string to search for
|
|
169
|
-
- \`path\`: (Optional) Directory to search in, default: "."
|
|
170
|
-
- \`include\`: (Optional) File glob pattern to include
|
|
171
|
-
- \`exclude\`: (Optional) File glob pattern to exclude
|
|
172
|
-
- \`case_sensitive\`: (Optional) Case-sensitive search, default: false
|
|
173
|
-
- \`fixed_strings\`: (Optional) Treat pattern as literal string, default: false
|
|
174
|
-
- \`context\`: (Optional) Lines of context before/after matches
|
|
175
|
-
- \`no_ignore\`: (Optional) Don't ignore node_modules/.git, default: false
|
|
176
|
-
|
|
177
|
-
# Examples
|
|
178
|
-
- Find function: Grep(pattern="function myFunction")
|
|
179
|
-
- Find with context: Grep(pattern="TODO", context=3)
|
|
180
|
-
- TypeScript only: Grep(pattern="interface", include="*.ts")
|
|
181
|
-
|
|
182
|
-
# Best Practices
|
|
183
|
-
- Use case_sensitive=true for short patterns to reduce false positives
|
|
184
|
-
- Use fixed_strings=true if your pattern has special regex characters
|
|
185
|
-
- Use context to see the surrounding code for each match
|
|
159
|
+
description = `Search for text patterns within files using regex or literal string matching. This is your PRIMARY tool for finding specific code, functions, or content.
|
|
160
|
+
|
|
161
|
+
# When to Use
|
|
162
|
+
- Finding specific function definitions or calls
|
|
163
|
+
- Searching for variable usages or imports
|
|
164
|
+
- Locating error messages or log statements
|
|
165
|
+
- Finding all occurrences of a pattern across the codebase
|
|
166
|
+
- When you need line-by-line results with context
|
|
167
|
+
|
|
168
|
+
# When NOT to Use
|
|
169
|
+
- When you only need to find files containing text (use SearchFiles instead)
|
|
170
|
+
- When searching by file pattern rather than content (use SearchFiles)
|
|
171
|
+
- For very large codebases where you only need file names (SearchFiles is faster)
|
|
172
|
+
|
|
173
|
+
# Parameters
|
|
174
|
+
- \`pattern\`: Regex or literal string to search for
|
|
175
|
+
- \`path\`: (Optional) Directory to search in, default: "."
|
|
176
|
+
- \`include\`: (Optional) File glob pattern to include
|
|
177
|
+
- \`exclude\`: (Optional) File glob pattern to exclude
|
|
178
|
+
- \`case_sensitive\`: (Optional) Case-sensitive search, default: false
|
|
179
|
+
- \`fixed_strings\`: (Optional) Treat pattern as literal string, default: false
|
|
180
|
+
- \`context\`: (Optional) Lines of context before/after matches
|
|
181
|
+
- \`no_ignore\`: (Optional) Don't ignore node_modules/.git, default: false
|
|
182
|
+
|
|
183
|
+
# Examples
|
|
184
|
+
- Find function: Grep(pattern="function myFunction")
|
|
185
|
+
- Find with context: Grep(pattern="TODO", context=3)
|
|
186
|
+
- TypeScript only: Grep(pattern="interface", include="*.ts")
|
|
187
|
+
|
|
188
|
+
# Best Practices
|
|
189
|
+
- Use case_sensitive=true for short patterns to reduce false positives
|
|
190
|
+
- Use fixed_strings=true if your pattern has special regex characters
|
|
191
|
+
- Use context to see the surrounding code for each match
|
|
186
192
|
- Combine with include/exclude to narrow down file types`;
|
|
187
193
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
188
194
|
async execute(params) {
|
|
@@ -258,40 +264,40 @@ export class GrepTool {
|
|
|
258
264
|
}
|
|
259
265
|
export class BashTool {
|
|
260
266
|
name = 'Bash';
|
|
261
|
-
description = `Execute shell commands in the terminal. This is your PRIMARY tool for running commands, scripts, and system operations.
|
|
262
|
-
|
|
263
|
-
# When to Use
|
|
264
|
-
- Running build commands (npm run build, tsc, etc.)
|
|
265
|
-
- Installing dependencies (npm install, pip install, etc.)
|
|
266
|
-
- Running tests (npm test, pytest, etc.)
|
|
267
|
-
- Git operations (git commit, git push, etc.)
|
|
268
|
-
- Running linters or formatters
|
|
269
|
-
- Any command-line operations
|
|
270
|
-
|
|
271
|
-
# When NOT to Use
|
|
272
|
-
- For file operations (use Read/Write/
|
|
273
|
-
- For searching file content (use Grep instead)
|
|
274
|
-
- For finding files (use
|
|
275
|
-
- For commands that require user interaction (non-interactive only)
|
|
276
|
-
- For dangerous commands without understanding the impact
|
|
277
|
-
|
|
278
|
-
# Parameters
|
|
279
|
-
- \`command\`: The shell command to execute
|
|
280
|
-
- \`cwd\`: (Optional) Working directory for the command
|
|
281
|
-
- \`description\`: (Optional) Description of what the command does
|
|
282
|
-
- \`timeout\`: (Optional) Timeout in seconds, default: 120
|
|
283
|
-
- \`run_in_bg\`: (Optional) Run in background, default: false
|
|
284
|
-
|
|
285
|
-
# Examples
|
|
286
|
-
- Install dependencies: Bash(command="npm install", description="Install npm dependencies")
|
|
287
|
-
- Run tests: Bash(command="npm test", description="Run unit tests")
|
|
288
|
-
- Build project: Bash(command="npm run build", description="Build the project")
|
|
289
|
-
|
|
290
|
-
# Best Practices
|
|
291
|
-
- Always provide a description for context
|
|
292
|
-
- Set appropriate timeout for long-running commands
|
|
293
|
-
- Use run_in_bg=true for commands that take a long time
|
|
294
|
-
- Check the command is safe before executing
|
|
267
|
+
description = `Execute shell commands in the terminal. This is your PRIMARY tool for running commands, scripts, and system operations.
|
|
268
|
+
|
|
269
|
+
# When to Use
|
|
270
|
+
- Running build commands (npm run build, tsc, etc.)
|
|
271
|
+
- Installing dependencies (npm install, pip install, etc.)
|
|
272
|
+
- Running tests (npm test, pytest, etc.)
|
|
273
|
+
- Git operations (git commit, git push, etc.)
|
|
274
|
+
- Running linters or formatters
|
|
275
|
+
- Any command-line operations
|
|
276
|
+
|
|
277
|
+
# When NOT to Use
|
|
278
|
+
- For file operations (use Read/Write/Edit/CreateDirectory instead)
|
|
279
|
+
- For searching file content (use Grep instead)
|
|
280
|
+
- For finding files (use SearchFiles or ListDirectory instead)
|
|
281
|
+
- For commands that require user interaction (non-interactive only)
|
|
282
|
+
- For dangerous commands without understanding the impact
|
|
283
|
+
|
|
284
|
+
# Parameters
|
|
285
|
+
- \`command\`: The shell command to execute
|
|
286
|
+
- \`cwd\`: (Optional) Working directory for the command
|
|
287
|
+
- \`description\`: (Optional) Description of what the command does
|
|
288
|
+
- \`timeout\`: (Optional) Timeout in seconds, default: 120
|
|
289
|
+
- \`run_in_bg\`: (Optional) Run in background, default: false
|
|
290
|
+
|
|
291
|
+
# Examples
|
|
292
|
+
- Install dependencies: Bash(command="npm install", description="Install npm dependencies")
|
|
293
|
+
- Run tests: Bash(command="npm test", description="Run unit tests")
|
|
294
|
+
- Build project: Bash(command="npm run build", description="Build the project")
|
|
295
|
+
|
|
296
|
+
# Best Practices
|
|
297
|
+
- Always provide a description for context
|
|
298
|
+
- Set appropriate timeout for long-running commands
|
|
299
|
+
- Use run_in_bg=true for commands that take a long time
|
|
300
|
+
- Check the command is safe before executing
|
|
295
301
|
- Use absolute paths or paths relative to project root`;
|
|
296
302
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.SMART];
|
|
297
303
|
async execute(params) {
|
|
@@ -382,33 +388,33 @@ export class BashTool {
|
|
|
382
388
|
}
|
|
383
389
|
export class ListDirectoryTool {
|
|
384
390
|
name = 'ListDirectory';
|
|
385
|
-
description = `List files and directories in a path. This is your PRIMARY tool for exploring project structure.
|
|
386
|
-
|
|
387
|
-
# When to Use
|
|
388
|
-
- Exploring project structure and organization
|
|
389
|
-
- Finding what files exist in a directory
|
|
390
|
-
- Getting an overview of the codebase layout
|
|
391
|
-
- When user asks to "list files" or "show directory contents"
|
|
392
|
-
- Navigating through project directories
|
|
393
|
-
|
|
394
|
-
# When NOT to Use
|
|
395
|
-
- When you need to read file contents (use Read instead)
|
|
396
|
-
- For recursive exploration of entire codebase (use recursive=true)
|
|
397
|
-
- When you need to search for specific files (use
|
|
398
|
-
|
|
399
|
-
# Parameters
|
|
400
|
-
- \`path\`: (Optional) Directory path, default: "."
|
|
401
|
-
- \`recursive\`: (Optional) List recursively, default: false
|
|
402
|
-
|
|
403
|
-
# Examples
|
|
404
|
-
- List current directory: ListDirectory(path=".")
|
|
405
|
-
- List src directory: ListDirectory(path="src")
|
|
406
|
-
- List all files recursively: ListDirectory(path=".", recursive=true)
|
|
407
|
-
|
|
408
|
-
# Best Practices
|
|
409
|
-
- Use recursive=true to see entire subtree
|
|
410
|
-
- Results are absolute paths
|
|
411
|
-
- Ignores node_modules and .git by default
|
|
391
|
+
description = `List files and directories in a path. This is your PRIMARY tool for exploring project structure.
|
|
392
|
+
|
|
393
|
+
# When to Use
|
|
394
|
+
- Exploring project structure and organization
|
|
395
|
+
- Finding what files exist in a directory
|
|
396
|
+
- Getting an overview of the codebase layout
|
|
397
|
+
- When user asks to "list files" or "show directory contents"
|
|
398
|
+
- Navigating through project directories
|
|
399
|
+
|
|
400
|
+
# When NOT to Use
|
|
401
|
+
- When you need to read file contents (use Read instead)
|
|
402
|
+
- For recursive exploration of entire codebase (use recursive=true)
|
|
403
|
+
- When you need to search for specific files (use SearchFiles instead)
|
|
404
|
+
|
|
405
|
+
# Parameters
|
|
406
|
+
- \`path\`: (Optional) Directory path, default: "."
|
|
407
|
+
- \`recursive\`: (Optional) List recursively, default: false
|
|
408
|
+
|
|
409
|
+
# Examples
|
|
410
|
+
- List current directory: ListDirectory(path=".")
|
|
411
|
+
- List src directory: ListDirectory(path="src")
|
|
412
|
+
- List all files recursively: ListDirectory(path=".", recursive=true)
|
|
413
|
+
|
|
414
|
+
# Best Practices
|
|
415
|
+
- Use recursive=true to see entire subtree
|
|
416
|
+
- Results are absolute paths
|
|
417
|
+
- Ignores node_modules and .git by default
|
|
412
418
|
- Combine with Read to examine file contents`;
|
|
413
419
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
414
420
|
async execute(params) {
|
|
@@ -432,49 +438,59 @@ export class ListDirectoryTool {
|
|
|
432
438
|
}
|
|
433
439
|
}
|
|
434
440
|
}
|
|
435
|
-
export class
|
|
436
|
-
name = '
|
|
437
|
-
description = `Search for files matching a glob pattern. This is your PRIMARY tool for finding files by name or extension.
|
|
438
|
-
|
|
439
|
-
# When to Use
|
|
440
|
-
- Finding all files of a certain type (*.ts, *.json, *.md)
|
|
441
|
-
- Locating files in specific directories or subdirectories
|
|
442
|
-
- Finding configuration files, test files, or source files
|
|
443
|
-
- When you need a list of file paths, not content
|
|
444
|
-
|
|
445
|
-
# When NOT to Use
|
|
446
|
-
- When you need to search file contents (use Grep instead)
|
|
447
|
-
- When you need to find specific text within files (use Grep instead)
|
|
448
|
-
- For searching non-file patterns (use Grep or Bash)
|
|
449
|
-
|
|
450
|
-
# Parameters
|
|
451
|
-
- \`pattern\`: Glob pattern (e.g., "**/*.ts", "src/**/*.test.ts")
|
|
452
|
-
- \`path\`: (Optional) Directory to search in, default: "."
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
- Find
|
|
457
|
-
- Find
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
-
|
|
463
|
-
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
441
|
+
export class SearchFilesTool {
|
|
442
|
+
name = 'SearchFiles';
|
|
443
|
+
description = `Search for files matching a glob pattern. This is your PRIMARY tool for finding files by name or extension.
|
|
444
|
+
|
|
445
|
+
# When to Use
|
|
446
|
+
- Finding all files of a certain type (*.ts, *.json, *.md)
|
|
447
|
+
- Locating files in specific directories or subdirectories
|
|
448
|
+
- Finding configuration files, test files, or source files
|
|
449
|
+
- When you need a list of file paths, not content
|
|
450
|
+
|
|
451
|
+
# When NOT to Use
|
|
452
|
+
- When you need to search file contents (use Grep instead)
|
|
453
|
+
- When you need to find specific text within files (use Grep instead)
|
|
454
|
+
- For searching non-file patterns (use Grep or Bash)
|
|
455
|
+
|
|
456
|
+
# Parameters
|
|
457
|
+
- \`pattern\`: Glob pattern (e.g., "**/*.ts", "src/**/*.test.ts")
|
|
458
|
+
- \`path\`: (Optional) Directory to search in, default: "."
|
|
459
|
+
- \`limit\`: (Optional) Maximum number of results to return, default: 1000
|
|
460
|
+
|
|
461
|
+
# Examples
|
|
462
|
+
- Find all TypeScript files: SearchFiles(pattern="**/*.ts")
|
|
463
|
+
- Find test files: SearchFiles(pattern="**/*.test.ts")
|
|
464
|
+
- Find config files: SearchFiles(pattern="**/config.*")
|
|
465
|
+
- Limit results: SearchFiles(pattern="**/*.ts", limit=100)
|
|
466
|
+
|
|
467
|
+
# Glob Patterns
|
|
468
|
+
- \`*\` matches any characters except /
|
|
469
|
+
- \`**\` matches any characters including /
|
|
470
|
+
- \`?\` matches single character
|
|
471
|
+
- Use brackets for character classes: [abc]
|
|
472
|
+
|
|
473
|
+
# Best Practices
|
|
474
|
+
- Use **/*.ts for recursive search in all directories
|
|
475
|
+
- Combine with path parameter to search specific directories
|
|
476
|
+
- Use limit parameter to avoid huge result sets
|
|
468
477
|
- Results are file paths, not content (use Grep on results if needed)`;
|
|
469
478
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
470
479
|
async execute(params) {
|
|
471
|
-
const { pattern, path: searchPath = '.' } = params;
|
|
480
|
+
const { pattern, path: searchPath = '.', limit = 1000 } = params;
|
|
472
481
|
try {
|
|
473
482
|
const files = await glob(pattern, {
|
|
474
483
|
cwd: searchPath,
|
|
475
484
|
ignore: ['node_modules/**', '.git/**', 'dist/**', 'build/**']
|
|
476
485
|
});
|
|
477
|
-
|
|
486
|
+
const total = files.length;
|
|
487
|
+
const truncated = total > limit;
|
|
488
|
+
const result = truncated ? files.slice(0, limit) : files;
|
|
489
|
+
return {
|
|
490
|
+
files: result,
|
|
491
|
+
total,
|
|
492
|
+
truncated
|
|
493
|
+
};
|
|
478
494
|
}
|
|
479
495
|
catch (error) {
|
|
480
496
|
throw new Error(`Search failed: ${error.message}`);
|
|
@@ -483,29 +499,29 @@ export class SearchCodebaseTool {
|
|
|
483
499
|
}
|
|
484
500
|
export class DeleteFileTool {
|
|
485
501
|
name = 'DeleteFile';
|
|
486
|
-
description = `Delete a file from the filesystem.
|
|
487
|
-
|
|
488
|
-
# When to Use
|
|
489
|
-
- Removing temporary or debug files
|
|
490
|
-
- Cleaning up generated files
|
|
491
|
-
- Removing files as part of a refactoring task
|
|
492
|
-
- When user explicitly requests file deletion
|
|
493
|
-
|
|
494
|
-
# When NOT to Use
|
|
495
|
-
- For removing directories (use Bash with rm -rf instead)
|
|
496
|
-
- When uncertain if a file should be deleted (confirm with user first)
|
|
497
|
-
- For removing important source files without explicit user request
|
|
498
|
-
|
|
499
|
-
# Parameters
|
|
500
|
-
- \`filePath\`: Absolute path to the file to delete
|
|
501
|
-
|
|
502
|
-
# Examples
|
|
503
|
-
- Delete temporary file: DeleteFile(filePath="debug.log")
|
|
504
|
-
- Remove unused file: DeleteFile(filePath="src/old-component.tsx")
|
|
505
|
-
|
|
506
|
-
# Best Practices
|
|
507
|
-
- Ensure you have the correct file path
|
|
508
|
-
- Consider if the file might be needed later
|
|
502
|
+
description = `Delete a file from the filesystem.
|
|
503
|
+
|
|
504
|
+
# When to Use
|
|
505
|
+
- Removing temporary or debug files
|
|
506
|
+
- Cleaning up generated files
|
|
507
|
+
- Removing files as part of a refactoring task
|
|
508
|
+
- When user explicitly requests file deletion
|
|
509
|
+
|
|
510
|
+
# When NOT to Use
|
|
511
|
+
- For removing directories (use Bash with rm -rf instead)
|
|
512
|
+
- When uncertain if a file should be deleted (confirm with user first)
|
|
513
|
+
- For removing important source files without explicit user request
|
|
514
|
+
|
|
515
|
+
# Parameters
|
|
516
|
+
- \`filePath\`: Absolute path to the file to delete
|
|
517
|
+
|
|
518
|
+
# Examples
|
|
519
|
+
- Delete temporary file: DeleteFile(filePath="debug.log")
|
|
520
|
+
- Remove unused file: DeleteFile(filePath="src/old-component.tsx")
|
|
521
|
+
|
|
522
|
+
# Best Practices
|
|
523
|
+
- Ensure you have the correct file path
|
|
524
|
+
- Consider if the file might be needed later
|
|
509
525
|
- This action is irreversible - be certain before executing`;
|
|
510
526
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.SMART];
|
|
511
527
|
async execute(params) {
|
|
@@ -515,7 +531,8 @@ export class DeleteFileTool {
|
|
|
515
531
|
await fs.unlink(absolutePath);
|
|
516
532
|
return {
|
|
517
533
|
success: true,
|
|
518
|
-
message: `Successfully deleted ${filePath}
|
|
534
|
+
message: `Successfully deleted ${filePath}`,
|
|
535
|
+
filePath
|
|
519
536
|
};
|
|
520
537
|
}
|
|
521
538
|
catch (error) {
|
|
@@ -525,29 +542,29 @@ export class DeleteFileTool {
|
|
|
525
542
|
}
|
|
526
543
|
export class CreateDirectoryTool {
|
|
527
544
|
name = 'CreateDirectory';
|
|
528
|
-
description = `Create a new directory (folder) in the filesystem.
|
|
529
|
-
|
|
530
|
-
# When to Use
|
|
531
|
-
- Creating project structure (src/components, tests/unit, etc.)
|
|
532
|
-
- Setting up directories for new features or modules
|
|
533
|
-
- Organizing files into appropriate folders
|
|
534
|
-
- When user requests to create a folder structure
|
|
535
|
-
|
|
536
|
-
# When NOT to Use
|
|
537
|
-
- For creating parent directories while writing files (Write tool does this automatically)
|
|
538
|
-
- For creating multiple nested directories at once (create step by step or use Bash)
|
|
539
|
-
|
|
540
|
-
# Parameters
|
|
541
|
-
- \`dirPath\`: Path of the directory to create
|
|
542
|
-
- \`recursive\`: (Optional, default: true) Create parent directories if they don't exist
|
|
543
|
-
|
|
544
|
-
# Examples
|
|
545
|
-
- Create single directory: CreateDirectory(dirPath="src/utils")
|
|
546
|
-
- Create nested structure: CreateDirectory(dirPath="src/components/buttons", recursive=true)
|
|
547
|
-
|
|
548
|
-
# Best Practices
|
|
549
|
-
- recursive=true (default) creates all intermediate parent directories
|
|
550
|
-
- Use appropriate naming conventions (kebab-case for directories)
|
|
545
|
+
description = `Create a new directory (folder) in the filesystem.
|
|
546
|
+
|
|
547
|
+
# When to Use
|
|
548
|
+
- Creating project structure (src/components, tests/unit, etc.)
|
|
549
|
+
- Setting up directories for new features or modules
|
|
550
|
+
- Organizing files into appropriate folders
|
|
551
|
+
- When user requests to create a folder structure
|
|
552
|
+
|
|
553
|
+
# When NOT to Use
|
|
554
|
+
- For creating parent directories while writing files (Write tool does this automatically)
|
|
555
|
+
- For creating multiple nested directories at once (create step by step or use Bash)
|
|
556
|
+
|
|
557
|
+
# Parameters
|
|
558
|
+
- \`dirPath\`: Path of the directory to create
|
|
559
|
+
- \`recursive\`: (Optional, default: true) Create parent directories if they don't exist
|
|
560
|
+
|
|
561
|
+
# Examples
|
|
562
|
+
- Create single directory: CreateDirectory(dirPath="src/utils")
|
|
563
|
+
- Create nested structure: CreateDirectory(dirPath="src/components/buttons", recursive=true)
|
|
564
|
+
|
|
565
|
+
# Best Practices
|
|
566
|
+
- recursive=true (default) creates all intermediate parent directories
|
|
567
|
+
- Use appropriate naming conventions (kebab-case for directories)
|
|
551
568
|
- Consider the overall project structure before creating`;
|
|
552
569
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.SMART];
|
|
553
570
|
async execute(params) {
|
|
@@ -565,103 +582,286 @@ export class CreateDirectoryTool {
|
|
|
565
582
|
}
|
|
566
583
|
}
|
|
567
584
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
585
|
+
// 编辑工具辅助函数
|
|
586
|
+
function detectLineEnding(content) {
|
|
587
|
+
const crlfIdx = content.indexOf("\r\n");
|
|
588
|
+
const lfIdx = content.indexOf("\n");
|
|
589
|
+
if (lfIdx === -1)
|
|
590
|
+
return "\n";
|
|
591
|
+
if (crlfIdx === -1)
|
|
592
|
+
return "\n";
|
|
593
|
+
return crlfIdx < lfIdx ? "\r\n" : "\n";
|
|
594
|
+
}
|
|
595
|
+
function normalizeToLF(text) {
|
|
596
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
597
|
+
}
|
|
598
|
+
function restoreLineEndings(text, ending) {
|
|
599
|
+
return ending === "\r\n" ? text.replace(/\n/g, "\r\n") : text;
|
|
600
|
+
}
|
|
601
|
+
function normalizeForFuzzyMatch(text) {
|
|
602
|
+
return (text
|
|
603
|
+
.split("\n")
|
|
604
|
+
.map((line) => line.trimEnd())
|
|
605
|
+
.join("\n")
|
|
606
|
+
.replace(/['‘’""]/g, "'")
|
|
607
|
+
.replace(/["""]/g, '"')
|
|
608
|
+
.replace(/[—–‑−]/g, "-")
|
|
609
|
+
.replace(/[\u00A0\u2002-\u200A\u202F\u205F\u3000]/g, " "));
|
|
610
|
+
}
|
|
611
|
+
function fuzzyFindText(content, oldText) {
|
|
612
|
+
const exactIndex = content.indexOf(oldText);
|
|
613
|
+
if (exactIndex !== -1) {
|
|
614
|
+
return {
|
|
615
|
+
found: true,
|
|
616
|
+
index: exactIndex,
|
|
617
|
+
matchLength: oldText.length,
|
|
618
|
+
usedFuzzyMatch: false,
|
|
619
|
+
contentForReplacement: content,
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
const fuzzyContent = normalizeForFuzzyMatch(content);
|
|
623
|
+
const fuzzyOldText = normalizeForFuzzyMatch(oldText);
|
|
624
|
+
const fuzzyIndex = fuzzyContent.indexOf(fuzzyOldText);
|
|
625
|
+
if (fuzzyIndex === -1) {
|
|
626
|
+
return {
|
|
627
|
+
found: false,
|
|
628
|
+
index: -1,
|
|
629
|
+
matchLength: 0,
|
|
630
|
+
usedFuzzyMatch: false,
|
|
631
|
+
contentForReplacement: content,
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
return {
|
|
635
|
+
found: true,
|
|
636
|
+
index: fuzzyIndex,
|
|
637
|
+
matchLength: fuzzyOldText.length,
|
|
638
|
+
usedFuzzyMatch: true,
|
|
639
|
+
contentForReplacement: fuzzyContent,
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
function stripBom(content) {
|
|
643
|
+
return content.startsWith("\uFEFF") ? { bom: "\uFEFF", text: content.slice(1) } : { bom: "", text: content };
|
|
644
|
+
}
|
|
645
|
+
async function generateDiffString(oldContent, newContent, contextLines = 4) {
|
|
646
|
+
const diffModule = await import("diff");
|
|
647
|
+
const parts = diffModule.diffLines(oldContent, newContent);
|
|
648
|
+
const output = [];
|
|
649
|
+
const oldLines = oldContent.split("\n");
|
|
650
|
+
const newLines = newContent.split("\n");
|
|
651
|
+
const maxLineNum = Math.max(oldLines.length, newLines.length);
|
|
652
|
+
const lineNumWidth = String(maxLineNum).length;
|
|
653
|
+
let oldLineNum = 1;
|
|
654
|
+
let newLineNum = 1;
|
|
655
|
+
let lastWasChange = false;
|
|
656
|
+
let firstChangedLine;
|
|
657
|
+
for (let i = 0; i < parts.length; i++) {
|
|
658
|
+
const part = parts[i];
|
|
659
|
+
const raw = part.value.split("\n");
|
|
660
|
+
if (raw[raw.length - 1] === "") {
|
|
661
|
+
raw.pop();
|
|
662
|
+
}
|
|
663
|
+
if (part.added || part.removed) {
|
|
664
|
+
if (firstChangedLine === undefined) {
|
|
665
|
+
firstChangedLine = newLineNum;
|
|
666
|
+
}
|
|
667
|
+
for (const line of raw) {
|
|
668
|
+
if (part.added) {
|
|
669
|
+
const lineNum = String(newLineNum).padStart(lineNumWidth, " ");
|
|
670
|
+
output.push(`+${lineNum} ${line}`);
|
|
671
|
+
newLineNum++;
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
|
|
675
|
+
output.push(`-${lineNum} ${line}`);
|
|
676
|
+
oldLineNum++;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
lastWasChange = true;
|
|
680
|
+
}
|
|
681
|
+
else {
|
|
682
|
+
const nextPartIsChange = i < parts.length - 1 && (parts[i + 1].added || parts[i + 1].removed);
|
|
683
|
+
if (lastWasChange || nextPartIsChange) {
|
|
684
|
+
let linesToShow = raw;
|
|
685
|
+
let skipStart = 0;
|
|
686
|
+
let skipEnd = 0;
|
|
687
|
+
if (!lastWasChange) {
|
|
688
|
+
skipStart = Math.max(0, raw.length - contextLines);
|
|
689
|
+
linesToShow = raw.slice(skipStart);
|
|
690
|
+
}
|
|
691
|
+
if (!nextPartIsChange && linesToShow.length > contextLines) {
|
|
692
|
+
skipEnd = linesToShow.length - contextLines;
|
|
693
|
+
linesToShow = linesToShow.slice(0, contextLines);
|
|
694
|
+
}
|
|
695
|
+
if (skipStart > 0) {
|
|
696
|
+
output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
|
|
697
|
+
oldLineNum += skipStart;
|
|
698
|
+
newLineNum += skipStart;
|
|
699
|
+
}
|
|
700
|
+
for (const line of linesToShow) {
|
|
701
|
+
const lineNum = String(oldLineNum).padStart(lineNumWidth, " ");
|
|
702
|
+
output.push(` ${lineNum} ${line}`);
|
|
703
|
+
oldLineNum++;
|
|
704
|
+
newLineNum++;
|
|
705
|
+
}
|
|
706
|
+
if (skipEnd > 0) {
|
|
707
|
+
output.push(` ${"".padStart(lineNumWidth, " ")} ...`);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
else {
|
|
711
|
+
oldLineNum += raw.length;
|
|
712
|
+
newLineNum += raw.length;
|
|
713
|
+
}
|
|
714
|
+
lastWasChange = false;
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
return { diff: output.join("\n"), firstChangedLine };
|
|
718
|
+
}
|
|
719
|
+
export class EditTool {
|
|
720
|
+
name = 'Edit';
|
|
721
|
+
description = `Edit a file by replacing exact text. This is your PRIMARY tool for making targeted edits to code.
|
|
722
|
+
|
|
723
|
+
# When to Use
|
|
724
|
+
- Modifying specific code sections without rewriting entire files
|
|
725
|
+
- Changing function implementations, variable values, or configurations
|
|
726
|
+
- Fixing bugs by editing specific lines
|
|
727
|
+
- Updating imports, exports, or references
|
|
728
|
+
|
|
729
|
+
# When NOT to Use
|
|
730
|
+
- When you need to create a completely new file (use Write instead)
|
|
731
|
+
- When you want to append content to a file (read first, then Write)
|
|
732
|
+
- When making changes across multiple files (use Grep to find, then edit individually)
|
|
733
|
+
|
|
734
|
+
# Parameters
|
|
735
|
+
- \`file_path\`: Path to the file to edit (relative or absolute)
|
|
736
|
+
- \`instruction\`: Description of what to change (for your own tracking)
|
|
737
|
+
- \`old_string\`: The exact text to find and replace (must match exactly)
|
|
738
|
+
- \`new_string\`: The new text to replace with
|
|
739
|
+
|
|
740
|
+
# Critical Requirements
|
|
741
|
+
- \`old_string\` MUST be an EXACT match, including whitespace and indentation
|
|
742
|
+
- Include sufficient context (at least 3 lines) before and after the target text to ensure unique matching
|
|
743
|
+
- The file must exist before editing
|
|
744
|
+
|
|
745
|
+
# Fuzzy Matching
|
|
746
|
+
This tool supports fuzzy matching to handle minor formatting differences:
|
|
747
|
+
- Trailing whitespace is ignored
|
|
748
|
+
- Smart quotes (', ", , ) are normalized to ASCII
|
|
749
|
+
- Unicode dashes/hyphens are normalized to ASCII hyphen
|
|
750
|
+
- Special Unicode spaces are normalized to regular space
|
|
751
|
+
|
|
752
|
+
# Examples
|
|
753
|
+
edit(
|
|
754
|
+
file_path="src/app.ts",
|
|
755
|
+
instruction="Update API endpoint",
|
|
756
|
+
old_string="const API_URL = 'https://api.old.com'\\nconst PORT = 8080;",
|
|
757
|
+
new_string="const API_URL = 'https://api.new.com'\\nconst PORT = 3000;"
|
|
758
|
+
)
|
|
759
|
+
|
|
760
|
+
# Best Practices
|
|
761
|
+
- Read the file first to understand the exact content
|
|
762
|
+
- Include sufficient context in old_string to ensure unique match
|
|
763
|
+
- If fuzzy matching is needed, the tool will automatically apply it
|
|
764
|
+
- Check the diff output to verify the change is correct`;
|
|
607
765
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.SMART];
|
|
608
766
|
async execute(params) {
|
|
609
767
|
const { file_path, instruction, old_string, new_string } = params;
|
|
610
768
|
try {
|
|
611
769
|
const absolutePath = path.resolve(file_path);
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
770
|
+
// Check if file exists
|
|
771
|
+
try {
|
|
772
|
+
await fs.access(absolutePath);
|
|
773
|
+
}
|
|
774
|
+
catch {
|
|
775
|
+
return {
|
|
776
|
+
success: false,
|
|
777
|
+
message: `File not found: ${file_path}`,
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
// Read the file
|
|
781
|
+
const buffer = await fs.readFile(absolutePath);
|
|
782
|
+
const rawContent = buffer.toString("utf-8");
|
|
783
|
+
// Strip BOM before matching
|
|
784
|
+
const { bom, text: content } = stripBom(rawContent);
|
|
785
|
+
const originalEnding = detectLineEnding(content);
|
|
786
|
+
const normalizedContent = normalizeToLF(content);
|
|
787
|
+
const normalizedOldText = normalizeToLF(old_string);
|
|
788
|
+
const normalizedNewText = normalizeToLF(new_string);
|
|
789
|
+
// Find the old text using fuzzy matching
|
|
790
|
+
const matchResult = fuzzyFindText(normalizedContent, normalizedOldText);
|
|
791
|
+
if (!matchResult.found) {
|
|
792
|
+
return {
|
|
793
|
+
success: false,
|
|
794
|
+
message: `Could not find the exact text in ${file_path}. The old text must match exactly including all whitespace and newlines.`,
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
// Count occurrences using fuzzy-normalized content
|
|
798
|
+
const fuzzyContent = normalizeForFuzzyMatch(normalizedContent);
|
|
799
|
+
const fuzzyOldText = normalizeForFuzzyMatch(normalizedOldText);
|
|
800
|
+
const occurrences = fuzzyContent.split(fuzzyOldText).length - 1;
|
|
801
|
+
if (occurrences > 1) {
|
|
802
|
+
return {
|
|
803
|
+
success: false,
|
|
804
|
+
message: `Found ${occurrences} occurrences of the text in ${file_path}. The text must be unique. Please provide more context to make it unique.`,
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
// Perform replacement
|
|
808
|
+
const baseContent = matchResult.contentForReplacement;
|
|
809
|
+
const newContent = baseContent.substring(0, matchResult.index) +
|
|
810
|
+
normalizedNewText +
|
|
811
|
+
baseContent.substring(matchResult.index + matchResult.matchLength);
|
|
812
|
+
// Verify the replacement actually changed something
|
|
813
|
+
if (baseContent === newContent) {
|
|
615
814
|
return {
|
|
616
815
|
success: false,
|
|
617
|
-
message: `No
|
|
618
|
-
changes: 0
|
|
816
|
+
message: `No changes made to ${file_path}. The replacement produced identical content.`,
|
|
619
817
|
};
|
|
620
818
|
}
|
|
621
|
-
const
|
|
622
|
-
await fs.writeFile(absolutePath,
|
|
819
|
+
const finalContent = bom + restoreLineEndings(newContent, originalEnding);
|
|
820
|
+
await fs.writeFile(absolutePath, finalContent, "utf-8");
|
|
821
|
+
const diffResult = await generateDiffString(baseContent, newContent);
|
|
623
822
|
return {
|
|
624
823
|
success: true,
|
|
625
|
-
message: `Successfully replaced
|
|
626
|
-
|
|
824
|
+
message: `Successfully replaced text in ${file_path}.`,
|
|
825
|
+
diff: diffResult.diff,
|
|
826
|
+
firstChangedLine: diffResult.firstChangedLine,
|
|
627
827
|
};
|
|
628
828
|
}
|
|
629
829
|
catch (error) {
|
|
630
|
-
|
|
830
|
+
return {
|
|
831
|
+
success: false,
|
|
832
|
+
message: `Failed to edit file ${file_path}: ${error.message}`,
|
|
833
|
+
};
|
|
631
834
|
}
|
|
632
835
|
}
|
|
633
|
-
escapeRegExp(string) {
|
|
634
|
-
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
635
|
-
}
|
|
636
836
|
}
|
|
637
837
|
export class WebSearchTool {
|
|
638
838
|
name = 'web_search';
|
|
639
|
-
description = `Search the web for information. This tool queries a search API to find relevant results.
|
|
640
|
-
|
|
641
|
-
# When to Use
|
|
642
|
-
- When you need current information not in your training data
|
|
643
|
-
- Finding documentation, tutorials, or guides
|
|
644
|
-
- Researching APIs, libraries, or tools
|
|
645
|
-
- Getting up-to-date information on technical topics
|
|
646
|
-
- When user asks for "latest", "recent", or "current" information
|
|
647
|
-
|
|
648
|
-
# When NOT to Use
|
|
649
|
-
- When information is likely in the codebase or project files
|
|
650
|
-
- For information that doesn't change frequently (check docs first)
|
|
651
|
-
- When you can use web_fetch with a known URL instead
|
|
652
|
-
- For purely conversational queries
|
|
653
|
-
|
|
654
|
-
# Parameters
|
|
655
|
-
- \`query\`: Search query string
|
|
656
|
-
|
|
657
|
-
# Examples
|
|
658
|
-
- Find React documentation: web_search(query="React useEffect documentation")
|
|
659
|
-
- Get latest Node.js version: web_search(query="Node.js latest LTS version 2024")
|
|
660
|
-
|
|
661
|
-
# Best Practices
|
|
662
|
-
- Be specific in your query for better results
|
|
663
|
-
- Combine with web_fetch to get full content from relevant URLs
|
|
664
|
-
- Use quotes for exact phrase matching
|
|
839
|
+
description = `Search the web for information. This tool queries a search API to find relevant results.
|
|
840
|
+
|
|
841
|
+
# When to Use
|
|
842
|
+
- When you need current information not in your training data
|
|
843
|
+
- Finding documentation, tutorials, or guides
|
|
844
|
+
- Researching APIs, libraries, or tools
|
|
845
|
+
- Getting up-to-date information on technical topics
|
|
846
|
+
- When user asks for "latest", "recent", or "current" information
|
|
847
|
+
|
|
848
|
+
# When NOT to Use
|
|
849
|
+
- When information is likely in the codebase or project files
|
|
850
|
+
- For information that doesn't change frequently (check docs first)
|
|
851
|
+
- When you can use web_fetch with a known URL instead
|
|
852
|
+
- For purely conversational queries
|
|
853
|
+
|
|
854
|
+
# Parameters
|
|
855
|
+
- \`query\`: Search query string
|
|
856
|
+
|
|
857
|
+
# Examples
|
|
858
|
+
- Find React documentation: web_search(query="React useEffect documentation")
|
|
859
|
+
- Get latest Node.js version: web_search(query="Node.js latest LTS version 2024")
|
|
860
|
+
|
|
861
|
+
# Best Practices
|
|
862
|
+
- Be specific in your query for better results
|
|
863
|
+
- Combine with web_fetch to get full content from relevant URLs
|
|
864
|
+
- Use quotes for exact phrase matching
|
|
665
865
|
- Consider adding context like year or version in query`;
|
|
666
866
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
667
867
|
async execute(params) {
|
|
@@ -694,51 +894,51 @@ export class WebSearchTool {
|
|
|
694
894
|
}
|
|
695
895
|
export class TodoWriteTool {
|
|
696
896
|
name = 'todo_write';
|
|
697
|
-
description = `Create and manage structured task todo lists. Use this tool VERY frequently to track your progress and give users visibility into what needs to be done.
|
|
698
|
-
|
|
699
|
-
# When to Use
|
|
700
|
-
- Complex, multi-step tasks (3+ steps)
|
|
701
|
-
- User explicitly requests a todo list
|
|
702
|
-
- User provides multiple tasks to accomplish
|
|
703
|
-
- Immediately when starting work on a new feature
|
|
704
|
-
- After completing a task (update status immediately)
|
|
705
|
-
- Breaking down large features into smaller steps
|
|
706
|
-
- Tracking independent subtasks that can be worked on
|
|
707
|
-
|
|
708
|
-
# When NOT to Use
|
|
709
|
-
- Single, straightforward task
|
|
710
|
-
- Trivial operations in less than 3 steps
|
|
711
|
-
- Purely conversational or informational responses
|
|
712
|
-
- When you already have an up-to-date todo list
|
|
713
|
-
|
|
714
|
-
# Task States
|
|
715
|
-
- **pending** - Not started, waiting to be worked on
|
|
716
|
-
- **in_progress** - Currently working on (limit ONE at a time)
|
|
717
|
-
- **completed** - Finished successfully
|
|
718
|
-
- **failed** - Could not complete due to errors
|
|
719
|
-
|
|
720
|
-
# Task Descriptions
|
|
721
|
-
Each task needs:
|
|
722
|
-
- \`id\`: Unique identifier
|
|
723
|
-
- \`task\`: Clear, actionable description in imperative form (e.g., "Run tests")
|
|
724
|
-
- \`status\`: Current state
|
|
725
|
-
- \`priority\`: high/medium/low
|
|
726
|
-
|
|
727
|
-
# Examples
|
|
728
|
-
\`\`\`json
|
|
729
|
-
{
|
|
730
|
-
"todos": [
|
|
731
|
-
{ "id": "1", "task": "Run the build and check for errors", "status": "in_progress", "priority": "high" },
|
|
732
|
-
{ "id": "2", "task": "Fix any type errors found", "status": "pending", "priority": "high" },
|
|
733
|
-
{ "id": "3", "task": "Write unit tests for new feature", "status": "pending", "priority": "medium" }
|
|
734
|
-
]
|
|
735
|
-
}
|
|
736
|
-
\`\`\`
|
|
737
|
-
|
|
738
|
-
# Best Practices
|
|
739
|
-
- Mark tasks as completed IMMEDIATELY after finishing
|
|
740
|
-
- Don't batch multiple completions - update as you go
|
|
741
|
-
- Keep task descriptions clear and actionable
|
|
897
|
+
description = `Create and manage structured task todo lists. Use this tool VERY frequently to track your progress and give users visibility into what needs to be done.
|
|
898
|
+
|
|
899
|
+
# When to Use
|
|
900
|
+
- Complex, multi-step tasks (3+ steps)
|
|
901
|
+
- User explicitly requests a todo list
|
|
902
|
+
- User provides multiple tasks to accomplish
|
|
903
|
+
- Immediately when starting work on a new feature
|
|
904
|
+
- After completing a task (update status immediately)
|
|
905
|
+
- Breaking down large features into smaller steps
|
|
906
|
+
- Tracking independent subtasks that can be worked on
|
|
907
|
+
|
|
908
|
+
# When NOT to Use
|
|
909
|
+
- Single, straightforward task
|
|
910
|
+
- Trivial operations in less than 3 steps
|
|
911
|
+
- Purely conversational or informational responses
|
|
912
|
+
- When you already have an up-to-date todo list
|
|
913
|
+
|
|
914
|
+
# Task States
|
|
915
|
+
- **pending** - Not started, waiting to be worked on
|
|
916
|
+
- **in_progress** - Currently working on (limit ONE at a time)
|
|
917
|
+
- **completed** - Finished successfully
|
|
918
|
+
- **failed** - Could not complete due to errors
|
|
919
|
+
|
|
920
|
+
# Task Descriptions
|
|
921
|
+
Each task needs:
|
|
922
|
+
- \`id\`: Unique identifier
|
|
923
|
+
- \`task\`: Clear, actionable description in imperative form (e.g., "Run tests")
|
|
924
|
+
- \`status\`: Current state
|
|
925
|
+
- \`priority\`: high/medium/low
|
|
926
|
+
|
|
927
|
+
# Examples
|
|
928
|
+
\`\`\`json
|
|
929
|
+
{
|
|
930
|
+
"todos": [
|
|
931
|
+
{ "id": "1", "task": "Run the build and check for errors", "status": "in_progress", "priority": "high" },
|
|
932
|
+
{ "id": "2", "task": "Fix any type errors found", "status": "pending", "priority": "high" },
|
|
933
|
+
{ "id": "3", "task": "Write unit tests for new feature", "status": "pending", "priority": "medium" }
|
|
934
|
+
]
|
|
935
|
+
}
|
|
936
|
+
\`\`\`
|
|
937
|
+
|
|
938
|
+
# Best Practices
|
|
939
|
+
- Mark tasks as completed IMMEDIATELY after finishing
|
|
940
|
+
- Don't batch multiple completions - update as you go
|
|
941
|
+
- Keep task descriptions clear and actionable
|
|
742
942
|
- Use appropriate priority levels to indicate urgency`;
|
|
743
943
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
744
944
|
todoList = [];
|
|
@@ -768,24 +968,24 @@ Each task needs:
|
|
|
768
968
|
}
|
|
769
969
|
export class TodoReadTool {
|
|
770
970
|
name = 'todo_read';
|
|
771
|
-
description = `Read the current session's todo list and get a summary of all tasks. Use this to check what tasks remain and their current status.
|
|
772
|
-
|
|
773
|
-
# When to Use
|
|
774
|
-
- Before starting work to understand what needs to be done
|
|
775
|
-
- After completing a task to verify the todo list is updated
|
|
776
|
-
- When user asks about progress or remaining tasks
|
|
777
|
-
- To get an overview of task distribution (pending, in_progress, completed)
|
|
778
|
-
|
|
779
|
-
# What It Returns
|
|
780
|
-
- Full list of all todos with their IDs, tasks, statuses, and priorities
|
|
781
|
-
- Summary counts: total, pending, in_progress, completed, failed
|
|
782
|
-
|
|
783
|
-
# Examples
|
|
784
|
-
- User asks: "What are we working on right now?" → Use todo_read to show current state
|
|
785
|
-
- After a task completes → Check todo_read to confirm the list is accurate
|
|
786
|
-
|
|
787
|
-
# Best Practices
|
|
788
|
-
- Use todo_write to modify the list, not todo_read
|
|
971
|
+
description = `Read the current session's todo list and get a summary of all tasks. Use this to check what tasks remain and their current status.
|
|
972
|
+
|
|
973
|
+
# When to Use
|
|
974
|
+
- Before starting work to understand what needs to be done
|
|
975
|
+
- After completing a task to verify the todo list is updated
|
|
976
|
+
- When user asks about progress or remaining tasks
|
|
977
|
+
- To get an overview of task distribution (pending, in_progress, completed)
|
|
978
|
+
|
|
979
|
+
# What It Returns
|
|
980
|
+
- Full list of all todos with their IDs, tasks, statuses, and priorities
|
|
981
|
+
- Summary counts: total, pending, in_progress, completed, failed
|
|
982
|
+
|
|
983
|
+
# Examples
|
|
984
|
+
- User asks: "What are we working on right now?" → Use todo_read to show current state
|
|
985
|
+
- After a task completes → Check todo_read to confirm the list is accurate
|
|
986
|
+
|
|
987
|
+
# Best Practices
|
|
988
|
+
- Use todo_write to modify the list, not todo_read
|
|
789
989
|
- Check todo_read after todo_write to verify updates`;
|
|
790
990
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
791
991
|
todoWriteTool;
|
|
@@ -814,42 +1014,42 @@ export class TodoReadTool {
|
|
|
814
1014
|
}
|
|
815
1015
|
export class TaskTool {
|
|
816
1016
|
name = 'task';
|
|
817
|
-
description = `Launch specialized AI subagents to handle complex, multi-step tasks. Subagents are expert agents designed for specific domains like planning, code exploration, frontend testing, and more.
|
|
818
|
-
|
|
819
|
-
# When to Use
|
|
820
|
-
- Complex tasks requiring specialized expertise (planning, analysis, testing)
|
|
821
|
-
- Multi-step workflows that benefit from dedicated focus
|
|
822
|
-
- When you need to delegate work to avoid context overload
|
|
823
|
-
- Parallel execution of independent tasks across different domains
|
|
824
|
-
- User explicitly requests a specific type of agent (e.g., "use the frontend tester")
|
|
825
|
-
|
|
826
|
-
# Available SubAgents
|
|
827
|
-
1. **plan-agent** - Task planning and breakdown, risk analysis, implementation roadmaps
|
|
828
|
-
2. **explore-agent** - Codebase exploration, architecture analysis, finding specific code
|
|
829
|
-
3. **frontend-tester** - Writing and running frontend tests, UI validation
|
|
830
|
-
4. **code-reviewer** - Code review, security checks, bug detection
|
|
831
|
-
5. **frontend-developer** - Frontend development (React, TypeScript, modern web)
|
|
832
|
-
6. **backend-developer** - Backend development (Node.js, APIs, databases)
|
|
833
|
-
7. **gui-subagent** - Browser automation, visual web interactions, desktop application automation
|
|
834
|
-
|
|
835
|
-
# When NOT to Use
|
|
836
|
-
- Simple, straightforward tasks you can handle directly
|
|
837
|
-
- Tasks that don't require specialized expertise
|
|
838
|
-
- Single-step operations (use other tools instead)
|
|
839
|
-
|
|
840
|
-
# Examples
|
|
841
|
-
- "Analyze the authentication module and create a security report" → explore-agent
|
|
842
|
-
- "Create a detailed implementation plan for feature X" → plan-agent
|
|
843
|
-
- "Write unit tests for this React component" → frontend-tester
|
|
844
|
-
- "Review my changes for potential bugs" → code-reviewer
|
|
845
|
-
- "Automatically fill out this form and navigate the website" → gui-subagent
|
|
846
|
-
- "Test the login process on the desktop application" → gui-subagent
|
|
847
|
-
- "send a message to the my mom on the desktop application wechat" → gui-subagent
|
|
848
|
-
|
|
849
|
-
# Best Practices
|
|
850
|
-
- Provide clear, specific prompts to subagents
|
|
851
|
-
- Include relevant context (file paths, requirements, constraints)
|
|
852
|
-
- Set appropriate executionMode if needed
|
|
1017
|
+
description = `Launch specialized AI subagents to handle complex, multi-step tasks. Subagents are expert agents designed for specific domains like planning, code exploration, frontend testing, and more.
|
|
1018
|
+
|
|
1019
|
+
# When to Use
|
|
1020
|
+
- Complex tasks requiring specialized expertise (planning, analysis, testing)
|
|
1021
|
+
- Multi-step workflows that benefit from dedicated focus
|
|
1022
|
+
- When you need to delegate work to avoid context overload
|
|
1023
|
+
- Parallel execution of independent tasks across different domains
|
|
1024
|
+
- User explicitly requests a specific type of agent (e.g., "use the frontend tester")
|
|
1025
|
+
|
|
1026
|
+
# Available SubAgents
|
|
1027
|
+
1. **plan-agent** - Task planning and breakdown, risk analysis, implementation roadmaps
|
|
1028
|
+
2. **explore-agent** - Codebase exploration, architecture analysis, finding specific code
|
|
1029
|
+
3. **frontend-tester** - Writing and running frontend tests, UI validation
|
|
1030
|
+
4. **code-reviewer** - Code review, security checks, bug detection
|
|
1031
|
+
5. **frontend-developer** - Frontend development (React, TypeScript, modern web)
|
|
1032
|
+
6. **backend-developer** - Backend development (Node.js, APIs, databases)
|
|
1033
|
+
7. **gui-subagent** - Browser automation, visual web interactions, desktop application automation
|
|
1034
|
+
|
|
1035
|
+
# When NOT to Use
|
|
1036
|
+
- Simple, straightforward tasks you can handle directly
|
|
1037
|
+
- Tasks that don't require specialized expertise
|
|
1038
|
+
- Single-step operations (use other tools instead)
|
|
1039
|
+
|
|
1040
|
+
# Examples
|
|
1041
|
+
- "Analyze the authentication module and create a security report" → explore-agent
|
|
1042
|
+
- "Create a detailed implementation plan for feature X" → plan-agent
|
|
1043
|
+
- "Write unit tests for this React component" → frontend-tester
|
|
1044
|
+
- "Review my changes for potential bugs" → code-reviewer
|
|
1045
|
+
- "Automatically fill out this form and navigate the website" → gui-subagent
|
|
1046
|
+
- "Test the login process on the desktop application" → gui-subagent
|
|
1047
|
+
- "send a message to the my mom on the desktop application wechat" → gui-subagent
|
|
1048
|
+
|
|
1049
|
+
# Best Practices
|
|
1050
|
+
- Provide clear, specific prompts to subagents
|
|
1051
|
+
- Include relevant context (file paths, requirements, constraints)
|
|
1052
|
+
- Set appropriate executionMode if needed
|
|
853
1053
|
- For parallel execution, ensure tasks are truly independent`;
|
|
854
1054
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
855
1055
|
async execute(params, _executionMode) {
|
|
@@ -870,10 +1070,21 @@ export class TaskTool {
|
|
|
870
1070
|
if (params.agents && params.agents.length > 0) {
|
|
871
1071
|
return await this.executeParallelAgents(params.agents, params.description, mode, agentManager, toolRegistry, aiClient);
|
|
872
1072
|
}
|
|
873
|
-
if (!params.subagent_type
|
|
874
|
-
throw new Error('
|
|
875
|
-
}
|
|
876
|
-
|
|
1073
|
+
if (!params.subagent_type) {
|
|
1074
|
+
throw new Error('subagent_type is required for Task tool');
|
|
1075
|
+
}
|
|
1076
|
+
// Support both 'prompt' and 'query' parameter names (tool definition uses 'query')
|
|
1077
|
+
const prompt = params.prompt || params.query;
|
|
1078
|
+
if (!prompt) {
|
|
1079
|
+
throw new Error('Task query/prompt is required. Received params: ' + JSON.stringify({
|
|
1080
|
+
subagent_type: params.subagent_type,
|
|
1081
|
+
prompt: params.prompt,
|
|
1082
|
+
query: params.query,
|
|
1083
|
+
description: params.description,
|
|
1084
|
+
agents: params.agents?.length
|
|
1085
|
+
}));
|
|
1086
|
+
}
|
|
1087
|
+
const result = await this.executeSingleAgent(params.subagent_type, prompt, params.description, params.useContext ?? true, params.constraints || [], mode, agentManager, toolRegistry, aiClient, config);
|
|
877
1088
|
return result;
|
|
878
1089
|
}
|
|
879
1090
|
catch (error) {
|
|
@@ -1186,6 +1397,8 @@ export class TaskTool {
|
|
|
1186
1397
|
const indent = ' '.repeat(indentLevel);
|
|
1187
1398
|
const indentNext = ' '.repeat(indentLevel + 1);
|
|
1188
1399
|
const agentName = agent.name || subagent_type;
|
|
1400
|
+
// Track execution history for better reporting to main agent
|
|
1401
|
+
const executionHistory = [];
|
|
1189
1402
|
// Helper function to indent multi-line content
|
|
1190
1403
|
const indentMultiline = (content, baseIndent) => {
|
|
1191
1404
|
return content.split('\n').map(line => `${baseIndent} ${line}`).join('\n');
|
|
@@ -1291,6 +1504,7 @@ export class TaskTool {
|
|
|
1291
1504
|
}
|
|
1292
1505
|
const choice = result.choices[0];
|
|
1293
1506
|
const messageContent = choice.message?.content;
|
|
1507
|
+
const reasoningContent = choice.message?.reasoning_content || '';
|
|
1294
1508
|
const toolCalls = choice.message.tool_calls;
|
|
1295
1509
|
let contentStr;
|
|
1296
1510
|
let hasValidContent = false;
|
|
@@ -1319,6 +1533,13 @@ export class TaskTool {
|
|
|
1319
1533
|
}
|
|
1320
1534
|
// Add assistant message to conversation
|
|
1321
1535
|
messages.push({ role: 'assistant', content: contentStr });
|
|
1536
|
+
// Display reasoning content if present
|
|
1537
|
+
if (reasoningContent) {
|
|
1538
|
+
console.log(`\n${indent}${colors.textDim(`${icons.brain} Thinking Process:`)}`);
|
|
1539
|
+
const truncatedReasoning = reasoningContent.length > 500 ? reasoningContent.substring(0, 500) + '...' : reasoningContent;
|
|
1540
|
+
const indentedReasoning = indentMultiline(truncatedReasoning, indent);
|
|
1541
|
+
console.log(`${indentedReasoning}\n`);
|
|
1542
|
+
}
|
|
1322
1543
|
// Display assistant response (if there's any text content) with proper indentation
|
|
1323
1544
|
if (contentStr) {
|
|
1324
1545
|
console.log(`\n${indent}${colors.primaryBright(agentName)}: ${description}`);
|
|
@@ -1342,11 +1563,92 @@ export class TaskTool {
|
|
|
1342
1563
|
// Check cancellation before tool execution
|
|
1343
1564
|
checkCancellation();
|
|
1344
1565
|
const toolResult = await cancellationManager.withCancellation(toolRegistry.execute(name, parsedParams, mode, indent), `subagent-${subagent_type}-${name}-${iteration}`);
|
|
1345
|
-
//
|
|
1566
|
+
// Get showToolDetails config to control result display
|
|
1567
|
+
const showToolDetails = config.get('showToolDetails') || false;
|
|
1568
|
+
// Prepare result preview for history
|
|
1346
1569
|
const resultPreview = typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult, null, 2);
|
|
1347
1570
|
const truncatedPreview = resultPreview.length > 200 ? resultPreview.substring(0, 200) + '...' : resultPreview;
|
|
1348
|
-
|
|
1349
|
-
|
|
1571
|
+
// Special handling for different tools (consistent with session.ts display logic)
|
|
1572
|
+
const isTodoTool = name === 'todo_write' || name === 'todo_read';
|
|
1573
|
+
const isEditTool = name === 'Edit';
|
|
1574
|
+
const isWriteTool = name === 'Write';
|
|
1575
|
+
const isDeleteTool = name === 'DeleteFile';
|
|
1576
|
+
const hasDiff = isEditTool && toolResult?.diff;
|
|
1577
|
+
const hasFilePreview = isWriteTool && toolResult?.preview;
|
|
1578
|
+
const hasDeleteInfo = isDeleteTool && toolResult?.filePath;
|
|
1579
|
+
// Import render functions for consistent display
|
|
1580
|
+
const { renderDiff, renderLines } = await import('./theme.js');
|
|
1581
|
+
if (isTodoTool) {
|
|
1582
|
+
// Display todo list
|
|
1583
|
+
console.log(`${indent}${colors.success(`${icons.check} Todo List:`)}`);
|
|
1584
|
+
const todos = toolResult?.todos || [];
|
|
1585
|
+
if (todos.length === 0) {
|
|
1586
|
+
console.log(`${indent} ${colors.textMuted('No tasks')}`);
|
|
1587
|
+
}
|
|
1588
|
+
else {
|
|
1589
|
+
const statusConfig = {
|
|
1590
|
+
'pending': { icon: icons.circle, color: colors.textMuted, label: 'Pending' },
|
|
1591
|
+
'in_progress': { icon: icons.loading, color: colors.warning, label: 'In Progress' },
|
|
1592
|
+
'completed': { icon: icons.success, color: colors.success, label: 'Completed' },
|
|
1593
|
+
'failed': { icon: icons.error, color: colors.error, label: 'Failed' }
|
|
1594
|
+
};
|
|
1595
|
+
for (const todo of todos) {
|
|
1596
|
+
const status = statusConfig[todo.status] || statusConfig['pending'];
|
|
1597
|
+
console.log(`${indent} ${status.color(status.icon)} ${status.color(status.label)}: ${colors.text(todo.task)}`);
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
if (toolResult?.message) {
|
|
1601
|
+
console.log(`${indent}${colors.textDim(toolResult.message)}`);
|
|
1602
|
+
}
|
|
1603
|
+
console.log('');
|
|
1604
|
+
}
|
|
1605
|
+
else if (hasDiff) {
|
|
1606
|
+
// Display edit result with diff
|
|
1607
|
+
console.log('');
|
|
1608
|
+
const diffOutput = renderDiff(toolResult.diff);
|
|
1609
|
+
const indentedDiff = diffOutput.split('\n').map(line => `${indent} ${line}`).join('\n');
|
|
1610
|
+
console.log(`${indentedDiff}\n`);
|
|
1611
|
+
}
|
|
1612
|
+
else if (hasFilePreview) {
|
|
1613
|
+
// Display new file content in preview style
|
|
1614
|
+
console.log('');
|
|
1615
|
+
console.log(`${indent}${colors.success(`${icons.file} ${toolResult.filePath}`)}`);
|
|
1616
|
+
console.log(`${indent}${colors.textDim(` ${toolResult.lineCount} lines`)}`);
|
|
1617
|
+
console.log('');
|
|
1618
|
+
console.log(renderLines(toolResult.preview, { maxLines: 10, indent: indent + ' ' }));
|
|
1619
|
+
console.log('');
|
|
1620
|
+
}
|
|
1621
|
+
else if (hasDeleteInfo) {
|
|
1622
|
+
// Display DeleteFile result
|
|
1623
|
+
console.log('');
|
|
1624
|
+
console.log(`${indent}${colors.success(`${icons.check} Deleted: ${toolResult.filePath}`)}`);
|
|
1625
|
+
console.log('');
|
|
1626
|
+
}
|
|
1627
|
+
else if (showToolDetails) {
|
|
1628
|
+
// Show full result details
|
|
1629
|
+
const indentedPreview = indentMultiline(resultPreview, indent);
|
|
1630
|
+
console.log(`${indent}${colors.success(`${icons.check} Tool Result:`)}\n${indentedPreview}\n`);
|
|
1631
|
+
}
|
|
1632
|
+
else if (toolResult && toolResult.success === false) {
|
|
1633
|
+
// Tool failed
|
|
1634
|
+
console.log(`${indent}${colors.error(`${icons.cross} ${toolResult.message || 'Failed'}`)}\n`);
|
|
1635
|
+
}
|
|
1636
|
+
else if (toolResult) {
|
|
1637
|
+
// Show brief preview by default
|
|
1638
|
+
const indentedPreview = indentMultiline(truncatedPreview, indent);
|
|
1639
|
+
console.log(`${indent}${colors.success(`${icons.check} Completed`)}\n${indentedPreview}\n`);
|
|
1640
|
+
}
|
|
1641
|
+
else {
|
|
1642
|
+
console.log(`${indent}${colors.textDim('(no result)')}\n`);
|
|
1643
|
+
}
|
|
1644
|
+
// Record successful tool execution in history (use truncated preview to save memory)
|
|
1645
|
+
executionHistory.push({
|
|
1646
|
+
tool: name,
|
|
1647
|
+
status: 'success',
|
|
1648
|
+
params: parsedParams,
|
|
1649
|
+
result: truncatedPreview,
|
|
1650
|
+
timestamp: new Date().toISOString()
|
|
1651
|
+
});
|
|
1350
1652
|
messages.push({
|
|
1351
1653
|
role: 'tool',
|
|
1352
1654
|
content: JSON.stringify(toolResult),
|
|
@@ -1358,13 +1660,32 @@ export class TaskTool {
|
|
|
1358
1660
|
console.log(`${indent}${colors.warning(`⚠️ Operation cancelled`)}\n`);
|
|
1359
1661
|
cancellationManager.off('cancelled', cancelHandler);
|
|
1360
1662
|
cleanupStdinPolling();
|
|
1663
|
+
const summaryPreview = contentStr.length > 300 ? contentStr.substring(0, 300) + '...' : contentStr;
|
|
1361
1664
|
return {
|
|
1362
1665
|
success: false,
|
|
1363
1666
|
message: `Task "${description}" cancelled by user`,
|
|
1364
|
-
result:
|
|
1667
|
+
result: {
|
|
1668
|
+
summary: summaryPreview,
|
|
1669
|
+
executionHistory: {
|
|
1670
|
+
totalIterations: iteration,
|
|
1671
|
+
toolsExecuted: executionHistory.length,
|
|
1672
|
+
successfulTools: executionHistory.filter(t => t.status === 'success').length,
|
|
1673
|
+
failedTools: executionHistory.filter(t => t.status === 'error').length,
|
|
1674
|
+
history: executionHistory,
|
|
1675
|
+
cancelled: true
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1365
1678
|
};
|
|
1366
1679
|
}
|
|
1367
1680
|
console.log(`${indent}${colors.error(`${icons.cross} Error:`)} ${error.message}\n`);
|
|
1681
|
+
// Record failed tool execution in history
|
|
1682
|
+
executionHistory.push({
|
|
1683
|
+
tool: name,
|
|
1684
|
+
status: 'error',
|
|
1685
|
+
params: parsedParams,
|
|
1686
|
+
error: error.message,
|
|
1687
|
+
timestamp: new Date().toISOString()
|
|
1688
|
+
});
|
|
1368
1689
|
messages.push({
|
|
1369
1690
|
role: 'tool',
|
|
1370
1691
|
content: JSON.stringify({ error: error.message }),
|
|
@@ -1375,25 +1696,48 @@ export class TaskTool {
|
|
|
1375
1696
|
console.log('');
|
|
1376
1697
|
continue; // Continue to next iteration to get final response
|
|
1377
1698
|
}
|
|
1378
|
-
// No more tool calls, return the result
|
|
1699
|
+
// No more tool calls, return the result with execution history
|
|
1379
1700
|
cancellationManager.off('cancelled', cancelHandler);
|
|
1380
1701
|
cleanupStdinPolling();
|
|
1702
|
+
const summaryPreview = contentStr.length > 300 ? contentStr.substring(0, 300) + '...' : contentStr;
|
|
1381
1703
|
return {
|
|
1382
1704
|
success: true,
|
|
1383
1705
|
message: `Task "${description}" completed by ${subagent_type}`,
|
|
1384
|
-
result:
|
|
1706
|
+
result: {
|
|
1707
|
+
summary: summaryPreview,
|
|
1708
|
+
executionHistory: {
|
|
1709
|
+
totalIterations: iteration,
|
|
1710
|
+
toolsExecuted: executionHistory.length,
|
|
1711
|
+
successfulTools: executionHistory.filter(t => t.status === 'success').length,
|
|
1712
|
+
failedTools: executionHistory.filter(t => t.status === 'error').length,
|
|
1713
|
+
history: executionHistory
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1385
1716
|
};
|
|
1386
1717
|
}
|
|
1387
1718
|
// Max iterations reached - return accumulated results instead of throwing error
|
|
1388
1719
|
// Get the last assistant message content
|
|
1389
1720
|
const lastAssistantMsg = messages.filter(m => m.role === 'assistant').pop();
|
|
1390
|
-
const
|
|
1721
|
+
const lastContentStr = typeof lastAssistantMsg?.content === 'string'
|
|
1722
|
+
? lastAssistantMsg.content
|
|
1723
|
+
: JSON.stringify(lastAssistantMsg?.content || '');
|
|
1391
1724
|
cancellationManager.off('cancelled', cancelHandler);
|
|
1392
1725
|
cleanupStdinPolling();
|
|
1726
|
+
const summaryPreview = lastContentStr.length > 300 ? lastContentStr.substring(0, 300) + '...' : lastContentStr;
|
|
1393
1727
|
return {
|
|
1394
1728
|
success: true,
|
|
1395
1729
|
message: `Task "${description}" completed (max iterations reached) by ${subagent_type}`,
|
|
1396
|
-
result:
|
|
1730
|
+
result: {
|
|
1731
|
+
summary: summaryPreview,
|
|
1732
|
+
executionHistory: {
|
|
1733
|
+
totalIterations: iteration,
|
|
1734
|
+
toolsExecuted: executionHistory.length,
|
|
1735
|
+
successfulTools: executionHistory.filter(t => t.status === 'success').length,
|
|
1736
|
+
failedTools: executionHistory.filter(t => t.status === 'error').length,
|
|
1737
|
+
history: executionHistory,
|
|
1738
|
+
maxIterationsReached: true
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1397
1741
|
};
|
|
1398
1742
|
}
|
|
1399
1743
|
async executeParallelAgents(agents, description, mode, agentManager, toolRegistry, aiClient, indentLevel = 1) {
|
|
@@ -1512,31 +1856,31 @@ export class TaskTool {
|
|
|
1512
1856
|
}
|
|
1513
1857
|
export class ReadBashOutputTool {
|
|
1514
1858
|
name = 'ReadBashOutput';
|
|
1515
|
-
description = `Retrieve output from a background task that was started with Bash(run_in_bg=true).
|
|
1516
|
-
|
|
1517
|
-
# When to Use
|
|
1518
|
-
- Checking the output of a long-running background process
|
|
1519
|
-
- Monitoring progress of builds, tests, or servers
|
|
1520
|
-
- Retrieving logs from background tasks
|
|
1521
|
-
- When you started a task with run_in_bg=true and need results
|
|
1522
|
-
|
|
1523
|
-
# When NOT to Use
|
|
1524
|
-
- For synchronous commands (they return output directly)
|
|
1525
|
-
- When the background task hasn't been started yet
|
|
1526
|
-
- For tasks that have already completed (use Bash directly)
|
|
1527
|
-
|
|
1528
|
-
# Parameters
|
|
1529
|
-
- \`task_id\`: The ID returned from the background Bash command
|
|
1530
|
-
- \`poll_interval\`: (Optional) Seconds to wait before checking, default: 10
|
|
1531
|
-
|
|
1532
|
-
# Examples
|
|
1533
|
-
- Check build output: ReadBashOutput(task_id="task_1234567890")
|
|
1534
|
-
- Wait and check: ReadBashOutput(task_id="task_123", poll_interval=5)
|
|
1535
|
-
|
|
1536
|
-
# Best Practices
|
|
1537
|
-
- Save the task_id from Bash response for later use
|
|
1538
|
-
- Use appropriate poll_interval based on expected task duration
|
|
1539
|
-
- Check status to see if task is still running or completed
|
|
1859
|
+
description = `Retrieve output from a background task that was started with Bash(run_in_bg=true).
|
|
1860
|
+
|
|
1861
|
+
# When to Use
|
|
1862
|
+
- Checking the output of a long-running background process
|
|
1863
|
+
- Monitoring progress of builds, tests, or servers
|
|
1864
|
+
- Retrieving logs from background tasks
|
|
1865
|
+
- When you started a task with run_in_bg=true and need results
|
|
1866
|
+
|
|
1867
|
+
# When NOT to Use
|
|
1868
|
+
- For synchronous commands (they return output directly)
|
|
1869
|
+
- When the background task hasn't been started yet
|
|
1870
|
+
- For tasks that have already completed (use Bash directly)
|
|
1871
|
+
|
|
1872
|
+
# Parameters
|
|
1873
|
+
- \`task_id\`: The ID returned from the background Bash command
|
|
1874
|
+
- \`poll_interval\`: (Optional) Seconds to wait before checking, default: 10
|
|
1875
|
+
|
|
1876
|
+
# Examples
|
|
1877
|
+
- Check build output: ReadBashOutput(task_id="task_1234567890")
|
|
1878
|
+
- Wait and check: ReadBashOutput(task_id="task_123", poll_interval=5)
|
|
1879
|
+
|
|
1880
|
+
# Best Practices
|
|
1881
|
+
- Save the task_id from Bash response for later use
|
|
1882
|
+
- Use appropriate poll_interval based on expected task duration
|
|
1883
|
+
- Check status to see if task is still running or completed
|
|
1540
1884
|
- Combine with todo_write to track background task progress`;
|
|
1541
1885
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
1542
1886
|
async execute(params) {
|
|
@@ -1566,31 +1910,31 @@ export class ReadBashOutputTool {
|
|
|
1566
1910
|
}
|
|
1567
1911
|
export class WebFetchTool {
|
|
1568
1912
|
name = 'web_fetch';
|
|
1569
|
-
description = `Fetch and extract content from a specific URL. This tool retrieves the full content of a webpage.
|
|
1570
|
-
|
|
1571
|
-
# When to Use
|
|
1572
|
-
- When you have a specific URL and need its content
|
|
1573
|
-
- Extracting documentation from web pages
|
|
1574
|
-
- Fetching API documentation or guides
|
|
1575
|
-
- Getting content from known URLs (not for searching)
|
|
1576
|
-
|
|
1577
|
-
# When NOT to Use
|
|
1578
|
-
- When you need to search but don't have a specific URL (use web_search first)
|
|
1579
|
-
- For pages requiring authentication or login
|
|
1580
|
-
- For very large files or pages (may timeout)
|
|
1581
|
-
- When the URL format is unknown (use web_search first)
|
|
1582
|
-
|
|
1583
|
-
# Parameters
|
|
1584
|
-
- \`prompt\`: A prompt containing the URL to fetch (e.g., "Summarize https://example.com/docs")
|
|
1585
|
-
|
|
1586
|
-
# Examples
|
|
1587
|
-
- Fetch documentation: web_fetch(prompt="Extract key points from https://react.dev/docs")
|
|
1588
|
-
- Get API spec: web_fetch(prompt="Fetch the OpenAPI spec from https://api.example.com/openapi.json")
|
|
1589
|
-
|
|
1590
|
-
# Best Practices
|
|
1591
|
-
- Ensure the URL is accessible and doesn't require authentication
|
|
1592
|
-
- Use specific prompts to extract relevant information
|
|
1593
|
-
- Check if the page is accessible if you get errors
|
|
1913
|
+
description = `Fetch and extract content from a specific URL. This tool retrieves the full content of a webpage.
|
|
1914
|
+
|
|
1915
|
+
# When to Use
|
|
1916
|
+
- When you have a specific URL and need its content
|
|
1917
|
+
- Extracting documentation from web pages
|
|
1918
|
+
- Fetching API documentation or guides
|
|
1919
|
+
- Getting content from known URLs (not for searching)
|
|
1920
|
+
|
|
1921
|
+
# When NOT to Use
|
|
1922
|
+
- When you need to search but don't have a specific URL (use web_search first)
|
|
1923
|
+
- For pages requiring authentication or login
|
|
1924
|
+
- For very large files or pages (may timeout)
|
|
1925
|
+
- When the URL format is unknown (use web_search first)
|
|
1926
|
+
|
|
1927
|
+
# Parameters
|
|
1928
|
+
- \`prompt\`: A prompt containing the URL to fetch (e.g., "Summarize https://example.com/docs")
|
|
1929
|
+
|
|
1930
|
+
# Examples
|
|
1931
|
+
- Fetch documentation: web_fetch(prompt="Extract key points from https://react.dev/docs")
|
|
1932
|
+
- Get API spec: web_fetch(prompt="Fetch the OpenAPI spec from https://api.example.com/openapi.json")
|
|
1933
|
+
|
|
1934
|
+
# Best Practices
|
|
1935
|
+
- Ensure the URL is accessible and doesn't require authentication
|
|
1936
|
+
- Use specific prompts to extract relevant information
|
|
1937
|
+
- Check if the page is accessible if you get errors
|
|
1594
1938
|
- Large pages may be truncated due to size limits`;
|
|
1595
1939
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
1596
1940
|
async execute(params) {
|
|
@@ -1623,36 +1967,36 @@ export class WebFetchTool {
|
|
|
1623
1967
|
}
|
|
1624
1968
|
export class AskUserQuestionTool {
|
|
1625
1969
|
name = 'ask_user_question';
|
|
1626
|
-
description = `Ask the user questions during execution to gather input, preferences, or clarifications.
|
|
1627
|
-
|
|
1628
|
-
# When to Use
|
|
1629
|
-
- When you need user input or preferences to proceed
|
|
1630
|
-
- When a task has multiple options and user should choose
|
|
1631
|
-
- When clarification is needed for ambiguous requests
|
|
1632
|
-
- When user explicitly asks to be prompted
|
|
1633
|
-
|
|
1634
|
-
# When NOT to Use
|
|
1635
|
-
- When you can make reasonable assumptions
|
|
1636
|
-
- For simple confirmations (just proceed with reasonable default)
|
|
1637
|
-
- When the information is already available in context
|
|
1638
|
-
- For information you should know or can infer
|
|
1639
|
-
|
|
1640
|
-
# Parameters
|
|
1641
|
-
- \`questions\`: Array of questions with:
|
|
1642
|
-
- \`question\`: The question text
|
|
1643
|
-
- \`header\`: (Optional) Short label for the question
|
|
1644
|
-
- \`options\`: (Optional) Multiple choice options
|
|
1645
|
-
- \`multiSelect\`: (Optional) Allow multiple selections
|
|
1646
|
-
|
|
1647
|
-
# Examples
|
|
1648
|
-
- Simple input: Ask user their preferred name
|
|
1649
|
-
- Multiple choice: Ask which framework to use (React, Vue, Angular)
|
|
1650
|
-
- Multi-select: Ask which features to include (with checkboxes)
|
|
1651
|
-
|
|
1652
|
-
# Best Practices
|
|
1653
|
-
- Limit to 1-4 questions at a time
|
|
1654
|
-
- Provide options when possible for faster response
|
|
1655
|
-
- Use multiSelect=true when multiple answers are valid
|
|
1970
|
+
description = `Ask the user questions during execution to gather input, preferences, or clarifications.
|
|
1971
|
+
|
|
1972
|
+
# When to Use
|
|
1973
|
+
- When you need user input or preferences to proceed
|
|
1974
|
+
- When a task has multiple options and user should choose
|
|
1975
|
+
- When clarification is needed for ambiguous requests
|
|
1976
|
+
- When user explicitly asks to be prompted
|
|
1977
|
+
|
|
1978
|
+
# When NOT to Use
|
|
1979
|
+
- When you can make reasonable assumptions
|
|
1980
|
+
- For simple confirmations (just proceed with reasonable default)
|
|
1981
|
+
- When the information is already available in context
|
|
1982
|
+
- For information you should know or can infer
|
|
1983
|
+
|
|
1984
|
+
# Parameters
|
|
1985
|
+
- \`questions\`: Array of questions with:
|
|
1986
|
+
- \`question\`: The question text
|
|
1987
|
+
- \`header\`: (Optional) Short label for the question
|
|
1988
|
+
- \`options\`: (Optional) Multiple choice options
|
|
1989
|
+
- \`multiSelect\`: (Optional) Allow multiple selections
|
|
1990
|
+
|
|
1991
|
+
# Examples
|
|
1992
|
+
- Simple input: Ask user their preferred name
|
|
1993
|
+
- Multiple choice: Ask which framework to use (React, Vue, Angular)
|
|
1994
|
+
- Multi-select: Ask which features to include (with checkboxes)
|
|
1995
|
+
|
|
1996
|
+
# Best Practices
|
|
1997
|
+
- Limit to 1-4 questions at a time
|
|
1998
|
+
- Provide options when possible for faster response
|
|
1999
|
+
- Use multiSelect=true when multiple answers are valid
|
|
1656
2000
|
- Be clear and concise in question wording`;
|
|
1657
2001
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
1658
2002
|
async execute(params) {
|
|
@@ -1695,32 +2039,32 @@ export class AskUserQuestionTool {
|
|
|
1695
2039
|
}
|
|
1696
2040
|
export class SaveMemoryTool {
|
|
1697
2041
|
name = 'save_memory';
|
|
1698
|
-
description = `Save specific information to long-term memory for future sessions. Useful for remembering user preferences, project conventions, or important facts.
|
|
1699
|
-
|
|
1700
|
-
# When to Use
|
|
1701
|
-
- User explicitly asks to "remember" something
|
|
1702
|
-
- User provides preferences or configuration details
|
|
1703
|
-
- Important project conventions or patterns to remember
|
|
1704
|
-
- Information that should persist across sessions
|
|
1705
|
-
|
|
1706
|
-
# When NOT to Use
|
|
1707
|
-
- For temporary information only needed in current session
|
|
1708
|
-
- For information already in project files or configuration
|
|
1709
|
-
- For obvious or trivial facts
|
|
1710
|
-
- When user doesn't explicitly want information saved
|
|
1711
|
-
|
|
1712
|
-
# Parameters
|
|
1713
|
-
- \`fact\`: The specific fact or information to remember
|
|
1714
|
-
|
|
1715
|
-
# Examples
|
|
1716
|
-
- Remember user preference: save_memory(fact="User prefers TypeScript over JavaScript")
|
|
1717
|
-
- Remember project convention: save_memory(fact="Project uses kebab-case for component files")
|
|
1718
|
-
- Remember important context: save_memory(fact="API endpoint is https://api.example.com/v2")
|
|
1719
|
-
|
|
1720
|
-
# Best Practices
|
|
1721
|
-
- Save only when user explicitly requests or provides clear preference
|
|
1722
|
-
- Keep facts concise and specific
|
|
1723
|
-
- Remember project-specific conventions for consistency
|
|
2042
|
+
description = `Save specific information to long-term memory for future sessions. Useful for remembering user preferences, project conventions, or important facts.
|
|
2043
|
+
|
|
2044
|
+
# When to Use
|
|
2045
|
+
- User explicitly asks to "remember" something
|
|
2046
|
+
- User provides preferences or configuration details
|
|
2047
|
+
- Important project conventions or patterns to remember
|
|
2048
|
+
- Information that should persist across sessions
|
|
2049
|
+
|
|
2050
|
+
# When NOT to Use
|
|
2051
|
+
- For temporary information only needed in current session
|
|
2052
|
+
- For information already in project files or configuration
|
|
2053
|
+
- For obvious or trivial facts
|
|
2054
|
+
- When user doesn't explicitly want information saved
|
|
2055
|
+
|
|
2056
|
+
# Parameters
|
|
2057
|
+
- \`fact\`: The specific fact or information to remember
|
|
2058
|
+
|
|
2059
|
+
# Examples
|
|
2060
|
+
- Remember user preference: save_memory(fact="User prefers TypeScript over JavaScript")
|
|
2061
|
+
- Remember project convention: save_memory(fact="Project uses kebab-case for component files")
|
|
2062
|
+
- Remember important context: save_memory(fact="API endpoint is https://api.example.com/v2")
|
|
2063
|
+
|
|
2064
|
+
# Best Practices
|
|
2065
|
+
- Save only when user explicitly requests or provides clear preference
|
|
2066
|
+
- Keep facts concise and specific
|
|
2067
|
+
- Remember project-specific conventions for consistency
|
|
1724
2068
|
- This persists across sessions (global memory)`;
|
|
1725
2069
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
1726
2070
|
async execute(params) {
|
|
@@ -1741,31 +2085,31 @@ export class SaveMemoryTool {
|
|
|
1741
2085
|
}
|
|
1742
2086
|
export class ExitPlanModeTool {
|
|
1743
2087
|
name = 'exit_plan_mode';
|
|
1744
|
-
description = `Complete plan presentation in plan mode and transition to execution. This tool is used when you have finished planning and are ready to implement.
|
|
1745
|
-
|
|
1746
|
-
# When to Use
|
|
1747
|
-
- When you have completed creating a plan or design document
|
|
1748
|
-
- When the plan is ready for review and execution
|
|
1749
|
-
- After presenting the full implementation plan to the user
|
|
1750
|
-
- When ready to transition from planning to coding
|
|
1751
|
-
|
|
1752
|
-
# When NOT to Use
|
|
1753
|
-
- When still in the middle of planning (continue planning first)
|
|
1754
|
-
- When the plan needs revision based on feedback
|
|
1755
|
-
- When user hasn't reviewed the plan yet
|
|
1756
|
-
- In non-plan execution modes
|
|
1757
|
-
|
|
1758
|
-
# Parameters
|
|
1759
|
-
- \`plan\`: The complete plan text to be saved and executed
|
|
1760
|
-
|
|
1761
|
-
# Examples
|
|
1762
|
-
- Exit after creating implementation plan
|
|
1763
|
-
- Present final design and exit to implementation
|
|
1764
|
-
|
|
1765
|
-
# Best Practices
|
|
1766
|
-
- Ensure the plan is complete and comprehensive
|
|
1767
|
-
- Include all necessary steps and considerations
|
|
1768
|
-
- The plan will be saved for reference during execution
|
|
2088
|
+
description = `Complete plan presentation in plan mode and transition to execution. This tool is used when you have finished planning and are ready to implement.
|
|
2089
|
+
|
|
2090
|
+
# When to Use
|
|
2091
|
+
- When you have completed creating a plan or design document
|
|
2092
|
+
- When the plan is ready for review and execution
|
|
2093
|
+
- After presenting the full implementation plan to the user
|
|
2094
|
+
- When ready to transition from planning to coding
|
|
2095
|
+
|
|
2096
|
+
# When NOT to Use
|
|
2097
|
+
- When still in the middle of planning (continue planning first)
|
|
2098
|
+
- When the plan needs revision based on feedback
|
|
2099
|
+
- When user hasn't reviewed the plan yet
|
|
2100
|
+
- In non-plan execution modes
|
|
2101
|
+
|
|
2102
|
+
# Parameters
|
|
2103
|
+
- \`plan\`: The complete plan text to be saved and executed
|
|
2104
|
+
|
|
2105
|
+
# Examples
|
|
2106
|
+
- Exit after creating implementation plan
|
|
2107
|
+
- Present final design and exit to implementation
|
|
2108
|
+
|
|
2109
|
+
# Best Practices
|
|
2110
|
+
- Ensure the plan is complete and comprehensive
|
|
2111
|
+
- Include all necessary steps and considerations
|
|
2112
|
+
- The plan will be saved for reference during execution
|
|
1769
2113
|
- Use this only when truly ready to start coding`;
|
|
1770
2114
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
1771
2115
|
async execute(params) {
|
|
@@ -1784,28 +2128,28 @@ export class ExitPlanModeTool {
|
|
|
1784
2128
|
}
|
|
1785
2129
|
export class XmlEscapeTool {
|
|
1786
2130
|
name = 'xml_escape';
|
|
1787
|
-
description = `Automatically escape special characters in XML/HTML files to make them valid.
|
|
1788
|
-
|
|
1789
|
-
# When to Use
|
|
1790
|
-
- When content contains special XML characters (<, >, &, ", ')
|
|
1791
|
-
- When generating XML/HTML from raw content
|
|
1792
|
-
- When fixing encoding issues in markup files
|
|
1793
|
-
|
|
1794
|
-
# When NOT to Use
|
|
1795
|
-
- For files that should contain raw XML/HTML
|
|
1796
|
-
- For JavaScript, CSS, or other non-XML files
|
|
1797
|
-
- When escaping should be done manually
|
|
1798
|
-
|
|
1799
|
-
# Parameters
|
|
1800
|
-
- \`file_path\`: Path to the file to escape
|
|
1801
|
-
- \`escape_all\`: (Optional) Also escape additional entities (©, ®, €)
|
|
1802
|
-
|
|
1803
|
-
# Examples
|
|
1804
|
-
- Escape XML content in HTML file
|
|
1805
|
-
- Fix special characters in generated markup
|
|
1806
|
-
|
|
1807
|
-
# Best Practices
|
|
1808
|
-
- Backup files before escaping if unsure
|
|
2131
|
+
description = `Automatically escape special characters in XML/HTML files to make them valid.
|
|
2132
|
+
|
|
2133
|
+
# When to Use
|
|
2134
|
+
- When content contains special XML characters (<, >, &, ", ')
|
|
2135
|
+
- When generating XML/HTML from raw content
|
|
2136
|
+
- When fixing encoding issues in markup files
|
|
2137
|
+
|
|
2138
|
+
# When NOT to Use
|
|
2139
|
+
- For files that should contain raw XML/HTML
|
|
2140
|
+
- For JavaScript, CSS, or other non-XML files
|
|
2141
|
+
- When escaping should be done manually
|
|
2142
|
+
|
|
2143
|
+
# Parameters
|
|
2144
|
+
- \`file_path\`: Path to the file to escape
|
|
2145
|
+
- \`escape_all\`: (Optional) Also escape additional entities (©, ®, €)
|
|
2146
|
+
|
|
2147
|
+
# Examples
|
|
2148
|
+
- Escape XML content in HTML file
|
|
2149
|
+
- Fix special characters in generated markup
|
|
2150
|
+
|
|
2151
|
+
# Best Practices
|
|
2152
|
+
- Backup files before escaping if unsure
|
|
1809
2153
|
- escape_all=true adds common HTML entities`;
|
|
1810
2154
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.SMART];
|
|
1811
2155
|
async execute(params) {
|
|
@@ -1861,32 +2205,32 @@ export class XmlEscapeTool {
|
|
|
1861
2205
|
}
|
|
1862
2206
|
export class ImageReadTool {
|
|
1863
2207
|
name = 'image_read';
|
|
1864
|
-
description = `Read image files and generate detailed analysis using a vision-language model.
|
|
1865
|
-
|
|
1866
|
-
# When to Use
|
|
1867
|
-
- Analyzing UI designs or mockups
|
|
1868
|
-
- Examining screenshots or diagrams
|
|
1869
|
-
- Extracting information from images
|
|
1870
|
-
- Validating visual content or assets
|
|
1871
|
-
|
|
1872
|
-
# When NOT to Use
|
|
1873
|
-
- For text-based file analysis (use Read instead)
|
|
1874
|
-
- When the image is not relevant to the task
|
|
1875
|
-
- For very large images (may have size limits)
|
|
1876
|
-
|
|
1877
|
-
# Parameters
|
|
1878
|
-
- \`image_input\`: Path to image or base64 data
|
|
1879
|
-
- \`prompt\`: Instructions for what to analyze
|
|
1880
|
-
- \`input_type\`: (Optional) 'file_path' or 'base64'
|
|
1881
|
-
- \`task_brief\`: (Optional) Brief task description
|
|
1882
|
-
|
|
1883
|
-
# Examples
|
|
1884
|
-
- Analyze UI mockup: image_read(image_input="design.png", prompt="Describe the UI components")
|
|
1885
|
-
- Validate screenshot: image_read(image_input="screenshot.jpg", prompt="Check if login form is visible")
|
|
1886
|
-
|
|
1887
|
-
# Best Practices
|
|
1888
|
-
- Provide clear prompts for what to look for
|
|
1889
|
-
- Use task_brief for context
|
|
2208
|
+
description = `Read image files and generate detailed analysis using a vision-language model.
|
|
2209
|
+
|
|
2210
|
+
# When to Use
|
|
2211
|
+
- Analyzing UI designs or mockups
|
|
2212
|
+
- Examining screenshots or diagrams
|
|
2213
|
+
- Extracting information from images
|
|
2214
|
+
- Validating visual content or assets
|
|
2215
|
+
|
|
2216
|
+
# When NOT to Use
|
|
2217
|
+
- For text-based file analysis (use Read instead)
|
|
2218
|
+
- When the image is not relevant to the task
|
|
2219
|
+
- For very large images (may have size limits)
|
|
2220
|
+
|
|
2221
|
+
# Parameters
|
|
2222
|
+
- \`image_input\`: Path to image or base64 data
|
|
2223
|
+
- \`prompt\`: Instructions for what to analyze
|
|
2224
|
+
- \`input_type\`: (Optional) 'file_path' or 'base64'
|
|
2225
|
+
- \`task_brief\`: (Optional) Brief task description
|
|
2226
|
+
|
|
2227
|
+
# Examples
|
|
2228
|
+
- Analyze UI mockup: image_read(image_input="design.png", prompt="Describe the UI components")
|
|
2229
|
+
- Validate screenshot: image_read(image_input="screenshot.jpg", prompt="Check if login form is visible")
|
|
2230
|
+
|
|
2231
|
+
# Best Practices
|
|
2232
|
+
- Provide clear prompts for what to look for
|
|
2233
|
+
- Use task_brief for context
|
|
1890
2234
|
- Supports PNG, JPG, GIF, WEBP, SVG, BMP`;
|
|
1891
2235
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.PLAN, ExecutionMode.SMART];
|
|
1892
2236
|
async execute(params) {
|
|
@@ -1990,31 +2334,31 @@ export class ImageReadTool {
|
|
|
1990
2334
|
// }
|
|
1991
2335
|
export class InvokeSkillTool {
|
|
1992
2336
|
name = 'InvokeSkill';
|
|
1993
|
-
description = `Invoke a specialized skill to handle domain-specific tasks. Skills are AI-powered capabilities that understand complex requirements and generate high-quality outputs (see Available Skills section below for the list of skills).
|
|
1994
|
-
|
|
1995
|
-
# When to Use
|
|
1996
|
-
- When user requests involve document processing (Word, PDF, PowerPoint)
|
|
1997
|
-
- When user wants to create frontend interfaces or web applications
|
|
1998
|
-
- When user needs visual design, posters, or generative art
|
|
1999
|
-
- When user asks for documentation or internal communications
|
|
2000
|
-
- When the task matches a specific skill domain
|
|
2001
|
-
|
|
2002
|
-
# When NOT to Use
|
|
2003
|
-
- For simple file operations (use Read/Write instead)
|
|
2004
|
-
- For basic code changes (use
|
|
2005
|
-
- When a regular tool can accomplish the task
|
|
2006
|
-
|
|
2007
|
-
# Parameters
|
|
2008
|
-
- \`skillId\`: The skill identifier (see Available Skills section)
|
|
2009
|
-
- \`taskDescription\`: Detailed description of what to accomplish
|
|
2010
|
-
- \`inputFile\`: (Optional) Path to input file if applicable
|
|
2011
|
-
- \`outputFile\`: (Optional) Desired output file path
|
|
2012
|
-
- \`options\`: (Optional) Additional options for the skill
|
|
2013
|
-
|
|
2014
|
-
# Best Practices
|
|
2015
|
-
- Provide detailed task descriptions for better results
|
|
2016
|
-
- Include relevant file paths when working with existing files
|
|
2017
|
-
- Match the skill to the domain (e.g., don't use frontend-design for Word docs)
|
|
2337
|
+
description = `Invoke a specialized skill to handle domain-specific tasks. Skills are AI-powered capabilities that understand complex requirements and generate high-quality outputs (see Available Skills section below for the list of skills).
|
|
2338
|
+
|
|
2339
|
+
# When to Use
|
|
2340
|
+
- When user requests involve document processing (Word, PDF, PowerPoint)
|
|
2341
|
+
- When user wants to create frontend interfaces or web applications
|
|
2342
|
+
- When user needs visual design, posters, or generative art
|
|
2343
|
+
- When user asks for documentation or internal communications
|
|
2344
|
+
- When the task matches a specific skill domain
|
|
2345
|
+
|
|
2346
|
+
# When NOT to Use
|
|
2347
|
+
- For simple file operations (use Read/Write instead)
|
|
2348
|
+
- For basic code changes (use Edit/Write instead)
|
|
2349
|
+
- When a regular tool can accomplish the task
|
|
2350
|
+
|
|
2351
|
+
# Parameters
|
|
2352
|
+
- \`skillId\`: The skill identifier (see Available Skills section)
|
|
2353
|
+
- \`taskDescription\`: Detailed description of what to accomplish
|
|
2354
|
+
- \`inputFile\`: (Optional) Path to input file if applicable
|
|
2355
|
+
- \`outputFile\`: (Optional) Desired output file path
|
|
2356
|
+
- \`options\`: (Optional) Additional options for the skill
|
|
2357
|
+
|
|
2358
|
+
# Best Practices
|
|
2359
|
+
- Provide detailed task descriptions for better results
|
|
2360
|
+
- Include relevant file paths when working with existing files
|
|
2361
|
+
- Match the skill to the domain (e.g., don't use frontend-design for Word docs)
|
|
2018
2362
|
- Skills will guide you through their specific workflows`;
|
|
2019
2363
|
allowedModes = [ExecutionMode.YOLO, ExecutionMode.ACCEPT_EDITS, ExecutionMode.SMART];
|
|
2020
2364
|
async execute(params, _executionMode) {
|
|
@@ -2161,10 +2505,10 @@ export class ToolRegistry {
|
|
|
2161
2505
|
this.register(new GrepTool());
|
|
2162
2506
|
this.register(new BashTool());
|
|
2163
2507
|
this.register(new ListDirectoryTool());
|
|
2164
|
-
this.register(new
|
|
2508
|
+
this.register(new SearchFilesTool());
|
|
2165
2509
|
this.register(new DeleteFileTool());
|
|
2166
2510
|
this.register(new CreateDirectoryTool());
|
|
2167
|
-
this.register(new
|
|
2511
|
+
this.register(new EditTool());
|
|
2168
2512
|
this.register(new WebSearchTool());
|
|
2169
2513
|
this.register(this.todoWriteTool);
|
|
2170
2514
|
this.register(new TodoReadTool(this.todoWriteTool));
|
|
@@ -2393,7 +2737,7 @@ export class ToolRegistry {
|
|
|
2393
2737
|
required: []
|
|
2394
2738
|
};
|
|
2395
2739
|
break;
|
|
2396
|
-
case '
|
|
2740
|
+
case 'SearchFiles':
|
|
2397
2741
|
parameters = {
|
|
2398
2742
|
type: 'object',
|
|
2399
2743
|
properties: {
|
|
@@ -2404,6 +2748,10 @@ export class ToolRegistry {
|
|
|
2404
2748
|
path: {
|
|
2405
2749
|
type: 'string',
|
|
2406
2750
|
description: 'Optional: The path to search in (default: current directory)'
|
|
2751
|
+
},
|
|
2752
|
+
limit: {
|
|
2753
|
+
type: 'integer',
|
|
2754
|
+
description: 'Optional: Maximum number of results to return (default: 1000)'
|
|
2407
2755
|
}
|
|
2408
2756
|
},
|
|
2409
2757
|
required: ['pattern']
|
|
@@ -2437,13 +2785,13 @@ export class ToolRegistry {
|
|
|
2437
2785
|
required: ['dirPath']
|
|
2438
2786
|
};
|
|
2439
2787
|
break;
|
|
2440
|
-
case '
|
|
2788
|
+
case 'Edit':
|
|
2441
2789
|
parameters = {
|
|
2442
2790
|
type: 'object',
|
|
2443
2791
|
properties: {
|
|
2444
2792
|
file_path: {
|
|
2445
2793
|
type: 'string',
|
|
2446
|
-
description: 'The absolute path to the file'
|
|
2794
|
+
description: 'The absolute path to the file to edit'
|
|
2447
2795
|
},
|
|
2448
2796
|
instruction: {
|
|
2449
2797
|
type: 'string',
|
|
@@ -2451,11 +2799,11 @@ export class ToolRegistry {
|
|
|
2451
2799
|
},
|
|
2452
2800
|
old_string: {
|
|
2453
2801
|
type: 'string',
|
|
2454
|
-
description: 'The exact text to replace'
|
|
2802
|
+
description: 'The exact text to replace (supports fuzzy matching)'
|
|
2455
2803
|
},
|
|
2456
2804
|
new_string: {
|
|
2457
2805
|
type: 'string',
|
|
2458
|
-
description: 'The
|
|
2806
|
+
description: 'The new text to replace with'
|
|
2459
2807
|
}
|
|
2460
2808
|
},
|
|
2461
2809
|
required: ['file_path', 'instruction', 'old_string', 'new_string']
|