@compilr-dev/agents 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +188 -1
- package/dist/agent.js +284 -14
- package/dist/context/file-tracker.d.ts +156 -0
- package/dist/context/file-tracker.js +358 -0
- package/dist/context/file-tracking-hook.d.ts +29 -0
- package/dist/context/file-tracking-hook.js +103 -0
- package/dist/context/index.d.ts +5 -1
- package/dist/context/index.js +3 -0
- package/dist/context/manager.d.ts +69 -1
- package/dist/context/manager.js +304 -0
- package/dist/context/types.d.ts +95 -0
- package/dist/index.d.ts +13 -5
- package/dist/index.js +11 -3
- package/dist/messages/index.d.ts +13 -0
- package/dist/messages/index.js +51 -0
- package/dist/permissions/manager.js +6 -1
- package/dist/providers/gemini.d.ts +91 -0
- package/dist/providers/gemini.js +138 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.js +7 -3
- package/dist/providers/mock.js +8 -0
- package/dist/providers/ollama.d.ts +87 -0
- package/dist/providers/ollama.js +133 -0
- package/dist/providers/openai-compatible.d.ts +182 -0
- package/dist/providers/openai-compatible.js +357 -0
- package/dist/providers/openai.d.ts +93 -0
- package/dist/providers/openai.js +133 -0
- package/dist/skills/index.js +691 -0
- package/dist/tools/builtin/glob.d.ts +11 -0
- package/dist/tools/builtin/glob.js +44 -2
- package/dist/tools/builtin/grep.d.ts +11 -1
- package/dist/tools/builtin/grep.js +38 -2
- package/dist/tools/builtin/index.d.ts +6 -1
- package/dist/tools/builtin/index.js +7 -0
- package/dist/tools/builtin/suggest.d.ts +57 -0
- package/dist/tools/builtin/suggest.js +99 -0
- package/dist/tools/builtin/task.js +13 -8
- package/dist/tools/builtin/tool-names.d.ts +44 -0
- package/dist/tools/builtin/tool-names.js +51 -0
- package/dist/tools/index.d.ts +2 -2
- package/dist/tools/index.js +5 -1
- package/dist/tools/registry.d.ts +4 -0
- package/dist/tools/registry.js +9 -0
- package/package.json +2 -2
|
@@ -5,6 +5,29 @@ import { readdir } from 'node:fs/promises';
|
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import { defineTool, createSuccessResult, createErrorResult } from '../define.js';
|
|
7
7
|
import { isNodeError } from './utils.js';
|
|
8
|
+
/**
|
|
9
|
+
* Default directories to exclude from glob searches.
|
|
10
|
+
* These are typically large, generated, or not relevant for code search.
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_EXCLUDE_DIRS = [
|
|
13
|
+
'node_modules',
|
|
14
|
+
'.git',
|
|
15
|
+
'dist',
|
|
16
|
+
'build',
|
|
17
|
+
'.next',
|
|
18
|
+
'.nuxt',
|
|
19
|
+
'.output',
|
|
20
|
+
'coverage',
|
|
21
|
+
'.nyc_output',
|
|
22
|
+
'__pycache__',
|
|
23
|
+
'.pytest_cache',
|
|
24
|
+
'venv',
|
|
25
|
+
'.venv',
|
|
26
|
+
'target', // Rust/Java
|
|
27
|
+
'vendor', // Go/PHP
|
|
28
|
+
'.cargo',
|
|
29
|
+
'.cache',
|
|
30
|
+
];
|
|
8
31
|
/**
|
|
9
32
|
* Glob tool definition
|
|
10
33
|
*/
|
|
@@ -48,6 +71,11 @@ export const globTool = defineTool({
|
|
|
48
71
|
type: 'boolean',
|
|
49
72
|
description: 'Return absolute paths instead of relative',
|
|
50
73
|
},
|
|
74
|
+
excludeDirs: {
|
|
75
|
+
type: 'array',
|
|
76
|
+
items: { type: 'string' },
|
|
77
|
+
description: 'Directory names to exclude (default: node_modules, .git, dist, build, etc.)',
|
|
78
|
+
},
|
|
51
79
|
},
|
|
52
80
|
required: ['pattern'],
|
|
53
81
|
},
|
|
@@ -57,7 +85,7 @@ export const globTool = defineTool({
|
|
|
57
85
|
* Execute the glob tool
|
|
58
86
|
*/
|
|
59
87
|
async function executeGlob(input) {
|
|
60
|
-
const { pattern, path: basePath = '.', includeHidden = false, onlyDirectories = false, onlyFiles = !onlyDirectories, maxDepth, maxResults = 1000, absolute = false, } = input;
|
|
88
|
+
const { pattern, path: basePath = '.', includeHidden = false, onlyDirectories = false, onlyFiles = !onlyDirectories, maxDepth, maxResults = 1000, absolute = false, excludeDirs = DEFAULT_EXCLUDE_DIRS, } = input;
|
|
61
89
|
// Check if base path exists
|
|
62
90
|
try {
|
|
63
91
|
await readdir(basePath);
|
|
@@ -91,6 +119,7 @@ async function executeGlob(input) {
|
|
|
91
119
|
maxResults,
|
|
92
120
|
matches,
|
|
93
121
|
basePath,
|
|
122
|
+
excludeDirs,
|
|
94
123
|
});
|
|
95
124
|
// Format output
|
|
96
125
|
const results = absolute ? matches.map((m) => join(basePath, m)) : matches;
|
|
@@ -117,6 +146,7 @@ async function searchDirectory(basePath, relativePath, depth, options) {
|
|
|
117
146
|
return;
|
|
118
147
|
}
|
|
119
148
|
const currentPath = relativePath ? join(basePath, relativePath) : basePath;
|
|
149
|
+
const excludeSet = new Set(options.excludeDirs);
|
|
120
150
|
let entries;
|
|
121
151
|
try {
|
|
122
152
|
entries = await readdir(currentPath, { withFileTypes: true });
|
|
@@ -133,8 +163,12 @@ async function searchDirectory(basePath, relativePath, depth, options) {
|
|
|
133
163
|
if (!options.includeHidden && entry.name.startsWith('.')) {
|
|
134
164
|
continue;
|
|
135
165
|
}
|
|
136
|
-
const entryRelativePath = relativePath ? join(relativePath, entry.name) : entry.name;
|
|
137
166
|
const isDir = entry.isDirectory();
|
|
167
|
+
// Skip excluded directories
|
|
168
|
+
if (isDir && excludeSet.has(entry.name)) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const entryRelativePath = relativePath ? join(relativePath, entry.name) : entry.name;
|
|
138
172
|
const isFile = entry.isFile();
|
|
139
173
|
// Check if this entry matches the pattern
|
|
140
174
|
if (options.pattern.test(entryRelativePath)) {
|
|
@@ -226,6 +260,11 @@ export function createGlobTool(options) {
|
|
|
226
260
|
type: 'boolean',
|
|
227
261
|
description: 'Return absolute paths instead of relative',
|
|
228
262
|
},
|
|
263
|
+
excludeDirs: {
|
|
264
|
+
type: 'array',
|
|
265
|
+
items: { type: 'string' },
|
|
266
|
+
description: 'Directory names to exclude (default: node_modules, .git, dist, build, etc.)',
|
|
267
|
+
},
|
|
229
268
|
},
|
|
230
269
|
required: ['pattern'],
|
|
231
270
|
},
|
|
@@ -235,9 +274,12 @@ export function createGlobTool(options) {
|
|
|
235
274
|
if (options?.baseDir && !searchPath.startsWith('/')) {
|
|
236
275
|
searchPath = join(options.baseDir, searchPath);
|
|
237
276
|
}
|
|
277
|
+
// Apply custom excludeDirs from factory options if specified and input doesn't override
|
|
278
|
+
const excludeDirs = input.excludeDirs ?? options?.excludeDirs ?? DEFAULT_EXCLUDE_DIRS;
|
|
238
279
|
return executeGlob({
|
|
239
280
|
...input,
|
|
240
281
|
path: searchPath,
|
|
282
|
+
excludeDirs,
|
|
241
283
|
});
|
|
242
284
|
},
|
|
243
285
|
});
|
|
@@ -50,6 +50,12 @@ export interface GrepInput {
|
|
|
50
50
|
* Search recursively in directories (default: true)
|
|
51
51
|
*/
|
|
52
52
|
recursive?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Directory names to exclude from search.
|
|
55
|
+
* Default excludes: node_modules, .git, dist, build, etc.
|
|
56
|
+
* Set to empty array [] to include all directories.
|
|
57
|
+
*/
|
|
58
|
+
excludeDirs?: string[];
|
|
53
59
|
}
|
|
54
60
|
/**
|
|
55
61
|
* Grep tool definition
|
|
@@ -60,7 +66,6 @@ export declare const grepTool: Tool<GrepInput>;
|
|
|
60
66
|
*
|
|
61
67
|
* TODO: Future enhancements could include:
|
|
62
68
|
* - maxFileSize: Skip files larger than specified size
|
|
63
|
-
* - excludeDirs: Exclude directories by name (e.g., node_modules, .git)
|
|
64
69
|
*/
|
|
65
70
|
export declare function createGrepTool(options?: {
|
|
66
71
|
/**
|
|
@@ -71,4 +76,9 @@ export declare function createGrepTool(options?: {
|
|
|
71
76
|
* Default file extensions to search
|
|
72
77
|
*/
|
|
73
78
|
defaultExtensions?: string[];
|
|
79
|
+
/**
|
|
80
|
+
* Override default excluded directories.
|
|
81
|
+
* Defaults to: node_modules, .git, dist, build, etc.
|
|
82
|
+
*/
|
|
83
|
+
excludeDirs?: string[];
|
|
74
84
|
}): Tool<GrepInput>;
|
|
@@ -6,6 +6,29 @@ import { readdir, stat } from 'node:fs/promises';
|
|
|
6
6
|
import { join, relative } from 'node:path';
|
|
7
7
|
import { defineTool, createSuccessResult, createErrorResult } from '../define.js';
|
|
8
8
|
import { isNodeError, isExtensionAllowed } from './utils.js';
|
|
9
|
+
/**
|
|
10
|
+
* Default directories to exclude from grep searches.
|
|
11
|
+
* These are typically large, generated, or not relevant for code search.
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_EXCLUDE_DIRS = [
|
|
14
|
+
'node_modules',
|
|
15
|
+
'.git',
|
|
16
|
+
'dist',
|
|
17
|
+
'build',
|
|
18
|
+
'.next',
|
|
19
|
+
'.nuxt',
|
|
20
|
+
'.output',
|
|
21
|
+
'coverage',
|
|
22
|
+
'.nyc_output',
|
|
23
|
+
'__pycache__',
|
|
24
|
+
'.pytest_cache',
|
|
25
|
+
'venv',
|
|
26
|
+
'.venv',
|
|
27
|
+
'target', // Rust/Java
|
|
28
|
+
'vendor', // Go/PHP
|
|
29
|
+
'.cargo',
|
|
30
|
+
'.cache',
|
|
31
|
+
];
|
|
9
32
|
/**
|
|
10
33
|
* Grep tool definition
|
|
11
34
|
*/
|
|
@@ -103,7 +126,7 @@ function safeRegexTest(regex, text) {
|
|
|
103
126
|
*/
|
|
104
127
|
async function executeGrep(input) {
|
|
105
128
|
try {
|
|
106
|
-
const { pattern, path, ignoreCase = false, lineNumbers = true, before = 0, after = 0, filesOnly = false, includeHidden = false, extensions, maxMatches = 100, recursive = true, } = input;
|
|
129
|
+
const { pattern, path, ignoreCase = false, lineNumbers = true, before = 0, after = 0, filesOnly = false, includeHidden = false, extensions, maxMatches = 100, recursive = true, excludeDirs = DEFAULT_EXCLUDE_DIRS, } = input;
|
|
107
130
|
// Check for potentially dangerous regex patterns
|
|
108
131
|
if (isPotentiallyDangerousRegex(pattern)) {
|
|
109
132
|
return createErrorResult(`Potentially dangerous regex pattern detected (ReDoS risk). ` +
|
|
@@ -128,6 +151,7 @@ async function executeGrep(input) {
|
|
|
128
151
|
recursive,
|
|
129
152
|
includeHidden,
|
|
130
153
|
extensions,
|
|
154
|
+
excludeDirs,
|
|
131
155
|
});
|
|
132
156
|
}
|
|
133
157
|
else {
|
|
@@ -189,6 +213,7 @@ async function executeGrep(input) {
|
|
|
189
213
|
*/
|
|
190
214
|
async function collectFiles(dir, files, options) {
|
|
191
215
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
216
|
+
const excludeSet = new Set(options.excludeDirs ?? []);
|
|
192
217
|
for (const entry of entries) {
|
|
193
218
|
// Skip hidden files unless included
|
|
194
219
|
if (!options.includeHidden && entry.name.startsWith('.')) {
|
|
@@ -205,6 +230,10 @@ async function collectFiles(dir, files, options) {
|
|
|
205
230
|
files.push(fullPath);
|
|
206
231
|
}
|
|
207
232
|
else if (entry.isDirectory() && options.recursive) {
|
|
233
|
+
// Skip excluded directories
|
|
234
|
+
if (excludeSet.has(entry.name)) {
|
|
235
|
+
continue;
|
|
236
|
+
}
|
|
208
237
|
await collectFiles(fullPath, files, options);
|
|
209
238
|
}
|
|
210
239
|
}
|
|
@@ -286,7 +315,6 @@ function formatMatches(matches, options) {
|
|
|
286
315
|
*
|
|
287
316
|
* TODO: Future enhancements could include:
|
|
288
317
|
* - maxFileSize: Skip files larger than specified size
|
|
289
|
-
* - excludeDirs: Exclude directories by name (e.g., node_modules, .git)
|
|
290
318
|
*/
|
|
291
319
|
export function createGrepTool(options) {
|
|
292
320
|
return defineTool({
|
|
@@ -342,6 +370,11 @@ export function createGrepTool(options) {
|
|
|
342
370
|
type: 'boolean',
|
|
343
371
|
description: 'Search recursively in directories (default: true)',
|
|
344
372
|
},
|
|
373
|
+
excludeDirs: {
|
|
374
|
+
type: 'array',
|
|
375
|
+
items: { type: 'string' },
|
|
376
|
+
description: 'Directory names to exclude (default: node_modules, .git, dist, build, etc.)',
|
|
377
|
+
},
|
|
345
378
|
},
|
|
346
379
|
required: ['pattern', 'path'],
|
|
347
380
|
},
|
|
@@ -353,10 +386,13 @@ export function createGrepTool(options) {
|
|
|
353
386
|
}
|
|
354
387
|
// Apply default extensions if none specified
|
|
355
388
|
const extensions = input.extensions ?? options?.defaultExtensions;
|
|
389
|
+
// Apply custom excludeDirs from factory options if specified and input doesn't override
|
|
390
|
+
const excludeDirs = input.excludeDirs ?? options?.excludeDirs ?? DEFAULT_EXCLUDE_DIRS;
|
|
356
391
|
return executeGrep({
|
|
357
392
|
...input,
|
|
358
393
|
path: searchPath,
|
|
359
394
|
extensions,
|
|
395
|
+
excludeDirs,
|
|
360
396
|
});
|
|
361
397
|
},
|
|
362
398
|
});
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Built-in tools for common operations
|
|
3
3
|
*/
|
|
4
|
+
export { TOOL_NAMES, TOOL_SETS } from './tool-names.js';
|
|
5
|
+
export type { ToolName } from './tool-names.js';
|
|
4
6
|
export { readFileTool, createReadFileTool } from './read-file.js';
|
|
5
7
|
export type { ReadFileInput } from './read-file.js';
|
|
6
8
|
export { writeFileTool, createWriteFileTool } from './write-file.js';
|
|
@@ -25,6 +27,8 @@ export { createTaskTool, defaultAgentTypes } from './task.js';
|
|
|
25
27
|
export type { TaskInput, TaskResult, AgentTypeConfig, TaskToolOptions, ContextMode, ThoroughnessLevel, SubAgentEventInfo, } from './task.js';
|
|
26
28
|
export { webFetchTool, createWebFetchTool } from './web-fetch.js';
|
|
27
29
|
export type { WebFetchInput, WebFetchResult, WebFetchOptions } from './web-fetch.js';
|
|
30
|
+
export { suggestTool, createSuggestTool } from './suggest.js';
|
|
31
|
+
export type { SuggestInput, SuggestToolOptions } from './suggest.js';
|
|
28
32
|
export declare const builtinTools: {
|
|
29
33
|
readonly readFile: import("../types.js").Tool<import("./read-file.js").ReadFileInput>;
|
|
30
34
|
readonly writeFile: import("../types.js").Tool<import("./write-file.js").WriteFileInput>;
|
|
@@ -37,8 +41,9 @@ export declare const builtinTools: {
|
|
|
37
41
|
readonly todoWrite: import("../types.js").Tool<import("./todo.js").TodoWriteInput>;
|
|
38
42
|
readonly todoRead: import("../types.js").Tool<import("./todo.js").TodoReadInput>;
|
|
39
43
|
readonly webFetch: import("../types.js").Tool<import("./web-fetch.js").WebFetchInput>;
|
|
44
|
+
readonly suggest: import("../types.js").Tool<import("./suggest.js").SuggestInput>;
|
|
40
45
|
};
|
|
41
46
|
/**
|
|
42
47
|
* Array of all built-in tools
|
|
43
48
|
*/
|
|
44
|
-
export declare const allBuiltinTools: readonly [import("../types.js").Tool<import("./read-file.js").ReadFileInput>, import("../types.js").Tool<import("./write-file.js").WriteFileInput>, import("../types.js").Tool<import("./bash.js").BashInput>, import("../types.js").Tool<import("./bash-output.js").BashOutputInput>, import("../types.js").Tool<import("./kill-shell.js").KillShellInput>, import("../types.js").Tool<import("./grep.js").GrepInput>, import("../types.js").Tool<import("./glob.js").GlobInput>, import("../types.js").Tool<import("./edit.js").EditInput>, import("../types.js").Tool<import("./todo.js").TodoWriteInput>, import("../types.js").Tool<import("./todo.js").TodoReadInput>, import("../types.js").Tool<import("./web-fetch.js").WebFetchInput>];
|
|
49
|
+
export declare const allBuiltinTools: readonly [import("../types.js").Tool<import("./read-file.js").ReadFileInput>, import("../types.js").Tool<import("./write-file.js").WriteFileInput>, import("../types.js").Tool<import("./bash.js").BashInput>, import("../types.js").Tool<import("./bash-output.js").BashOutputInput>, import("../types.js").Tool<import("./kill-shell.js").KillShellInput>, import("../types.js").Tool<import("./grep.js").GrepInput>, import("../types.js").Tool<import("./glob.js").GlobInput>, import("../types.js").Tool<import("./edit.js").EditInput>, import("../types.js").Tool<import("./todo.js").TodoWriteInput>, import("../types.js").Tool<import("./todo.js").TodoReadInput>, import("../types.js").Tool<import("./web-fetch.js").WebFetchInput>, import("../types.js").Tool<import("./suggest.js").SuggestInput>];
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Built-in tools for common operations
|
|
3
3
|
*/
|
|
4
|
+
// Tool names - single source of truth
|
|
5
|
+
export { TOOL_NAMES, TOOL_SETS } from './tool-names.js';
|
|
4
6
|
// Read file tool
|
|
5
7
|
export { readFileTool, createReadFileTool } from './read-file.js';
|
|
6
8
|
// Write file tool
|
|
@@ -25,6 +27,8 @@ export { todoWriteTool, todoReadTool, createTodoTools, TodoStore, resetDefaultTo
|
|
|
25
27
|
export { createTaskTool, defaultAgentTypes } from './task.js';
|
|
26
28
|
// WebFetch tool
|
|
27
29
|
export { webFetchTool, createWebFetchTool } from './web-fetch.js';
|
|
30
|
+
// Suggest tool (next action suggestions)
|
|
31
|
+
export { suggestTool, createSuggestTool } from './suggest.js';
|
|
28
32
|
/**
|
|
29
33
|
* Collection of all built-in tools for easy registration
|
|
30
34
|
*/
|
|
@@ -38,6 +42,7 @@ import { globTool } from './glob.js';
|
|
|
38
42
|
import { editTool } from './edit.js';
|
|
39
43
|
import { todoWriteTool, todoReadTool } from './todo.js';
|
|
40
44
|
import { webFetchTool } from './web-fetch.js';
|
|
45
|
+
import { suggestTool } from './suggest.js';
|
|
41
46
|
export const builtinTools = {
|
|
42
47
|
readFile: readFileTool,
|
|
43
48
|
writeFile: writeFileTool,
|
|
@@ -50,6 +55,7 @@ export const builtinTools = {
|
|
|
50
55
|
todoWrite: todoWriteTool,
|
|
51
56
|
todoRead: todoReadTool,
|
|
52
57
|
webFetch: webFetchTool,
|
|
58
|
+
suggest: suggestTool,
|
|
53
59
|
};
|
|
54
60
|
/**
|
|
55
61
|
* Array of all built-in tools
|
|
@@ -66,4 +72,5 @@ export const allBuiltinTools = [
|
|
|
66
72
|
todoWriteTool,
|
|
67
73
|
todoReadTool,
|
|
68
74
|
webFetchTool,
|
|
75
|
+
suggestTool,
|
|
69
76
|
];
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suggest Tool - Suggest next action to the user
|
|
3
|
+
*
|
|
4
|
+
* This tool allows the agent to suggest a logical next action for the user.
|
|
5
|
+
* The suggestion appears as "ghost text" in the CLI input prompt.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Silent tool (produces no visible output in conversation)
|
|
9
|
+
* - Emits 'suggest' event for CLI to handle
|
|
10
|
+
* - Only the last suggestion per response is kept
|
|
11
|
+
*/
|
|
12
|
+
import type { Tool } from '../types.js';
|
|
13
|
+
import type { AgentEvent } from '../../agent.js';
|
|
14
|
+
/**
|
|
15
|
+
* Input parameters for suggest tool
|
|
16
|
+
*/
|
|
17
|
+
export interface SuggestInput {
|
|
18
|
+
/**
|
|
19
|
+
* The suggested action or command for the user to take next
|
|
20
|
+
*/
|
|
21
|
+
action: string;
|
|
22
|
+
/**
|
|
23
|
+
* Brief explanation of why this action is suggested (optional)
|
|
24
|
+
*/
|
|
25
|
+
reason?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Options for creating the suggest tool
|
|
29
|
+
*/
|
|
30
|
+
export interface SuggestToolOptions {
|
|
31
|
+
/**
|
|
32
|
+
* Callback to emit suggest event
|
|
33
|
+
* The CLI captures this to display the suggestion
|
|
34
|
+
*/
|
|
35
|
+
onSuggest?: (event: Extract<AgentEvent, {
|
|
36
|
+
type: 'suggest';
|
|
37
|
+
}>) => void;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Default suggest tool (no-op, for testing or when suggestions are disabled)
|
|
41
|
+
*/
|
|
42
|
+
export declare const suggestTool: Tool<SuggestInput>;
|
|
43
|
+
/**
|
|
44
|
+
* Create a suggest tool with event emission
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const suggestTool = createSuggestTool({
|
|
49
|
+
* onSuggest: (event) => {
|
|
50
|
+
* // Handle the suggestion (e.g., pass to CLI input prompt)
|
|
51
|
+
* console.log('Suggested action:', event.action);
|
|
52
|
+
* }
|
|
53
|
+
* });
|
|
54
|
+
* agent.registerTool(suggestTool);
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function createSuggestTool(options?: SuggestToolOptions): Tool<SuggestInput>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Suggest Tool - Suggest next action to the user
|
|
3
|
+
*
|
|
4
|
+
* This tool allows the agent to suggest a logical next action for the user.
|
|
5
|
+
* The suggestion appears as "ghost text" in the CLI input prompt.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Silent tool (produces no visible output in conversation)
|
|
9
|
+
* - Emits 'suggest' event for CLI to handle
|
|
10
|
+
* - Only the last suggestion per response is kept
|
|
11
|
+
*/
|
|
12
|
+
import { defineTool, createSuccessResult } from '../define.js';
|
|
13
|
+
/**
|
|
14
|
+
* Default suggest tool (no-op, for testing or when suggestions are disabled)
|
|
15
|
+
*/
|
|
16
|
+
export const suggestTool = defineTool({
|
|
17
|
+
name: 'suggest',
|
|
18
|
+
description: 'Suggest a next action for the user. The suggestion appears as ghost text in the input prompt. ' +
|
|
19
|
+
'Use this after completing a task to guide the user toward a logical next step. ' +
|
|
20
|
+
'Good suggestions are actionable, specific, and follow naturally from what you just did. ' +
|
|
21
|
+
'Examples: "run npm test to verify the fix", "review the changes in src/index.ts", ' +
|
|
22
|
+
'"commit the changes with git commit". Only suggest when there is a clear, helpful next step.',
|
|
23
|
+
inputSchema: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: {
|
|
26
|
+
action: {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: 'The suggested action or command for the user to take next',
|
|
29
|
+
},
|
|
30
|
+
reason: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: 'Brief explanation of why this action is suggested (optional)',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
required: ['action'],
|
|
36
|
+
},
|
|
37
|
+
execute: (_input) => {
|
|
38
|
+
// Default implementation - silent, no-op
|
|
39
|
+
// Real implementation uses createSuggestTool with onSuggest callback
|
|
40
|
+
return Promise.resolve(createSuccessResult({
|
|
41
|
+
suggested: true,
|
|
42
|
+
message: 'Suggestion noted (no handler configured)',
|
|
43
|
+
}));
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
/**
|
|
47
|
+
* Create a suggest tool with event emission
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const suggestTool = createSuggestTool({
|
|
52
|
+
* onSuggest: (event) => {
|
|
53
|
+
* // Handle the suggestion (e.g., pass to CLI input prompt)
|
|
54
|
+
* console.log('Suggested action:', event.action);
|
|
55
|
+
* }
|
|
56
|
+
* });
|
|
57
|
+
* agent.registerTool(suggestTool);
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function createSuggestTool(options = {}) {
|
|
61
|
+
const { onSuggest } = options;
|
|
62
|
+
return defineTool({
|
|
63
|
+
name: 'suggest',
|
|
64
|
+
description: 'Suggest a next action for the user. The suggestion appears as ghost text in the input prompt. ' +
|
|
65
|
+
'Use this after completing a task to guide the user toward a logical next step. ' +
|
|
66
|
+
'Good suggestions are actionable, specific, and follow naturally from what you just did. ' +
|
|
67
|
+
'Examples: "run npm test to verify the fix", "review the changes in src/index.ts", ' +
|
|
68
|
+
'"commit the changes with git commit". Only suggest when there is a clear, helpful next step.',
|
|
69
|
+
inputSchema: {
|
|
70
|
+
type: 'object',
|
|
71
|
+
properties: {
|
|
72
|
+
action: {
|
|
73
|
+
type: 'string',
|
|
74
|
+
description: 'The suggested action or command for the user to take next',
|
|
75
|
+
},
|
|
76
|
+
reason: {
|
|
77
|
+
type: 'string',
|
|
78
|
+
description: 'Brief explanation of why this action is suggested (optional)',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
required: ['action'],
|
|
82
|
+
},
|
|
83
|
+
execute: (input) => {
|
|
84
|
+
// Emit the suggest event if handler is configured
|
|
85
|
+
if (onSuggest) {
|
|
86
|
+
onSuggest({
|
|
87
|
+
type: 'suggest',
|
|
88
|
+
action: input.action,
|
|
89
|
+
reason: input.reason,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// Silent result - no visible output in conversation
|
|
93
|
+
return Promise.resolve(createSuccessResult({
|
|
94
|
+
suggested: true,
|
|
95
|
+
action: input.action,
|
|
96
|
+
}));
|
|
97
|
+
},
|
|
98
|
+
});
|
|
99
|
+
}
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* - Extended built-in agent types
|
|
14
14
|
*/
|
|
15
15
|
import { defineTool, createSuccessResult, createErrorResult } from '../define.js';
|
|
16
|
+
import { TOOL_NAMES, TOOL_SETS } from './tool-names.js';
|
|
16
17
|
/**
|
|
17
18
|
* Map our context mode to agent's context mode
|
|
18
19
|
*/
|
|
@@ -123,6 +124,7 @@ export function createTaskTool(options) {
|
|
|
123
124
|
const agentConfig = agentTypes[subagent_type];
|
|
124
125
|
// Check concurrent limit
|
|
125
126
|
if (activeCount >= maxConcurrent) {
|
|
127
|
+
console.error(`[task-tool] BLOCKED: activeCount=${String(activeCount)}, maxConcurrent=${String(maxConcurrent)}`);
|
|
126
128
|
return createErrorResult(`Maximum concurrent sub-agents (${String(maxConcurrent)}) reached. ` +
|
|
127
129
|
`Wait for existing tasks to complete.`);
|
|
128
130
|
}
|
|
@@ -131,6 +133,7 @@ export function createTaskTool(options) {
|
|
|
131
133
|
onSpawn(subagent_type, description);
|
|
132
134
|
}
|
|
133
135
|
activeCount++;
|
|
136
|
+
console.error(`[task-tool] SPAWN: ${subagent_type}, activeCount=${String(activeCount)}`);
|
|
134
137
|
try {
|
|
135
138
|
// Note: Sub-agents currently use the parent's provider
|
|
136
139
|
// Future enhancement: support model switching via providerFactory
|
|
@@ -198,10 +201,12 @@ export function createTaskTool(options) {
|
|
|
198
201
|
return createSuccessResult(taskResult);
|
|
199
202
|
}
|
|
200
203
|
catch (error) {
|
|
204
|
+
console.error(`[task-tool] ERROR: ${subagent_type}, error=${error instanceof Error ? error.message : String(error)}`);
|
|
201
205
|
return createErrorResult(`Sub-agent failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
202
206
|
}
|
|
203
207
|
finally {
|
|
204
208
|
activeCount--;
|
|
209
|
+
console.error(`[task-tool] DONE: ${subagent_type}, activeCount=${String(activeCount)}`);
|
|
205
210
|
}
|
|
206
211
|
},
|
|
207
212
|
});
|
|
@@ -222,7 +227,7 @@ export const defaultAgentTypes = {
|
|
|
222
227
|
contextMode: 'inherit-summary',
|
|
223
228
|
supportsThoroughness: true,
|
|
224
229
|
toolInheritance: 'filter',
|
|
225
|
-
allowedTools: [
|
|
230
|
+
allowedTools: [...TOOL_SETS.READ_ONLY],
|
|
226
231
|
},
|
|
227
232
|
'code-review': {
|
|
228
233
|
description: 'Agent specialized for reviewing code changes. Use after writing ' +
|
|
@@ -238,7 +243,7 @@ export const defaultAgentTypes = {
|
|
|
238
243
|
contextMode: 'inherit-summary',
|
|
239
244
|
supportsThoroughness: false,
|
|
240
245
|
toolInheritance: 'filter',
|
|
241
|
-
allowedTools: [
|
|
246
|
+
allowedTools: [...TOOL_SETS.READ_ONLY],
|
|
242
247
|
},
|
|
243
248
|
general: {
|
|
244
249
|
description: 'General-purpose agent for complex multi-step tasks. Use when ' +
|
|
@@ -262,7 +267,7 @@ export const defaultAgentTypes = {
|
|
|
262
267
|
contextMode: 'inherit-summary',
|
|
263
268
|
supportsThoroughness: false,
|
|
264
269
|
toolInheritance: 'filter',
|
|
265
|
-
allowedTools: [
|
|
270
|
+
allowedTools: [...TOOL_SETS.READ_ONLY],
|
|
266
271
|
},
|
|
267
272
|
'test-runner': {
|
|
268
273
|
description: 'Agent for running and analyzing tests. Use to run test suites, ' +
|
|
@@ -278,7 +283,7 @@ export const defaultAgentTypes = {
|
|
|
278
283
|
contextMode: 'inherit-summary',
|
|
279
284
|
supportsThoroughness: true,
|
|
280
285
|
toolInheritance: 'filter',
|
|
281
|
-
allowedTools: [
|
|
286
|
+
allowedTools: [...TOOL_SETS.READ_ONLY_WITH_BASH],
|
|
282
287
|
},
|
|
283
288
|
'doc-lookup': {
|
|
284
289
|
description: 'Agent for searching documentation and APIs. Use to find ' +
|
|
@@ -294,7 +299,7 @@ export const defaultAgentTypes = {
|
|
|
294
299
|
contextMode: 'isolated',
|
|
295
300
|
supportsThoroughness: true,
|
|
296
301
|
toolInheritance: 'filter',
|
|
297
|
-
allowedTools: [
|
|
302
|
+
allowedTools: [...TOOL_SETS.READ_ONLY_WITH_WEB],
|
|
298
303
|
},
|
|
299
304
|
refactor: {
|
|
300
305
|
description: 'Agent for refactoring code safely. Use for renaming, extracting, ' +
|
|
@@ -310,8 +315,8 @@ export const defaultAgentTypes = {
|
|
|
310
315
|
contextMode: 'inherit-summary',
|
|
311
316
|
supportsThoroughness: false,
|
|
312
317
|
toolInheritance: 'filter',
|
|
313
|
-
allowedTools: [
|
|
314
|
-
deniedTools: [
|
|
318
|
+
allowedTools: [...TOOL_SETS.REFACTOR],
|
|
319
|
+
deniedTools: [TOOL_NAMES.BASH],
|
|
315
320
|
},
|
|
316
321
|
'security-audit': {
|
|
317
322
|
description: 'Agent for security auditing code. Use to scan for vulnerabilities, ' +
|
|
@@ -329,7 +334,7 @@ export const defaultAgentTypes = {
|
|
|
329
334
|
contextMode: 'isolated',
|
|
330
335
|
supportsThoroughness: true,
|
|
331
336
|
toolInheritance: 'filter',
|
|
332
|
-
allowedTools: [
|
|
337
|
+
allowedTools: [...TOOL_SETS.SECURITY_AUDIT],
|
|
333
338
|
},
|
|
334
339
|
debug: {
|
|
335
340
|
description: 'Agent for debugging issues. Use to investigate bugs, analyze ' +
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Names - Single Source of Truth
|
|
3
|
+
*
|
|
4
|
+
* All tool names are defined here to avoid hardcoding them in multiple places.
|
|
5
|
+
* Import these constants wherever you need to reference tool names.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Built-in tool names as constants
|
|
9
|
+
*/
|
|
10
|
+
export declare const TOOL_NAMES: {
|
|
11
|
+
readonly READ_FILE: "read_file";
|
|
12
|
+
readonly WRITE_FILE: "write_file";
|
|
13
|
+
readonly BASH: "bash";
|
|
14
|
+
readonly BASH_OUTPUT: "bash_output";
|
|
15
|
+
readonly KILL_SHELL: "kill_shell";
|
|
16
|
+
readonly GREP: "grep";
|
|
17
|
+
readonly GLOB: "glob";
|
|
18
|
+
readonly EDIT: "edit";
|
|
19
|
+
readonly TODO_WRITE: "todo_write";
|
|
20
|
+
readonly TODO_READ: "todo_read";
|
|
21
|
+
readonly WEB_FETCH: "web_fetch";
|
|
22
|
+
readonly TASK: "task";
|
|
23
|
+
readonly SUGGEST: "suggest";
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Type for tool name values
|
|
27
|
+
*/
|
|
28
|
+
export type ToolName = (typeof TOOL_NAMES)[keyof typeof TOOL_NAMES];
|
|
29
|
+
/**
|
|
30
|
+
* Common tool sets for agent types
|
|
31
|
+
* Use these instead of hardcoding tool arrays
|
|
32
|
+
*/
|
|
33
|
+
export declare const TOOL_SETS: {
|
|
34
|
+
/** Read-only tools for exploration and code review */
|
|
35
|
+
readonly READ_ONLY: readonly ["glob", "grep", "read_file"];
|
|
36
|
+
/** Read-only tools plus bash for running commands */
|
|
37
|
+
readonly READ_ONLY_WITH_BASH: readonly ["bash", "glob", "grep", "read_file"];
|
|
38
|
+
/** Read-only tools plus web fetch for documentation lookup */
|
|
39
|
+
readonly READ_ONLY_WITH_WEB: readonly ["web_fetch", "glob", "grep", "read_file"];
|
|
40
|
+
/** Tools for refactoring (read + edit + write, no bash) */
|
|
41
|
+
readonly REFACTOR: readonly ["glob", "grep", "read_file", "edit", "write_file"];
|
|
42
|
+
/** Tools for security auditing (read + bash for dependency checks) */
|
|
43
|
+
readonly SECURITY_AUDIT: readonly ["glob", "grep", "read_file", "bash"];
|
|
44
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Names - Single Source of Truth
|
|
3
|
+
*
|
|
4
|
+
* All tool names are defined here to avoid hardcoding them in multiple places.
|
|
5
|
+
* Import these constants wherever you need to reference tool names.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Built-in tool names as constants
|
|
9
|
+
*/
|
|
10
|
+
export const TOOL_NAMES = {
|
|
11
|
+
READ_FILE: 'read_file',
|
|
12
|
+
WRITE_FILE: 'write_file',
|
|
13
|
+
BASH: 'bash',
|
|
14
|
+
BASH_OUTPUT: 'bash_output',
|
|
15
|
+
KILL_SHELL: 'kill_shell',
|
|
16
|
+
GREP: 'grep',
|
|
17
|
+
GLOB: 'glob',
|
|
18
|
+
EDIT: 'edit',
|
|
19
|
+
TODO_WRITE: 'todo_write',
|
|
20
|
+
TODO_READ: 'todo_read',
|
|
21
|
+
WEB_FETCH: 'web_fetch',
|
|
22
|
+
TASK: 'task',
|
|
23
|
+
SUGGEST: 'suggest',
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Common tool sets for agent types
|
|
27
|
+
* Use these instead of hardcoding tool arrays
|
|
28
|
+
*/
|
|
29
|
+
export const TOOL_SETS = {
|
|
30
|
+
/** Read-only tools for exploration and code review */
|
|
31
|
+
READ_ONLY: [TOOL_NAMES.GLOB, TOOL_NAMES.GREP, TOOL_NAMES.READ_FILE],
|
|
32
|
+
/** Read-only tools plus bash for running commands */
|
|
33
|
+
READ_ONLY_WITH_BASH: [TOOL_NAMES.BASH, TOOL_NAMES.GLOB, TOOL_NAMES.GREP, TOOL_NAMES.READ_FILE],
|
|
34
|
+
/** Read-only tools plus web fetch for documentation lookup */
|
|
35
|
+
READ_ONLY_WITH_WEB: [
|
|
36
|
+
TOOL_NAMES.WEB_FETCH,
|
|
37
|
+
TOOL_NAMES.GLOB,
|
|
38
|
+
TOOL_NAMES.GREP,
|
|
39
|
+
TOOL_NAMES.READ_FILE,
|
|
40
|
+
],
|
|
41
|
+
/** Tools for refactoring (read + edit + write, no bash) */
|
|
42
|
+
REFACTOR: [
|
|
43
|
+
TOOL_NAMES.GLOB,
|
|
44
|
+
TOOL_NAMES.GREP,
|
|
45
|
+
TOOL_NAMES.READ_FILE,
|
|
46
|
+
TOOL_NAMES.EDIT,
|
|
47
|
+
TOOL_NAMES.WRITE_FILE,
|
|
48
|
+
],
|
|
49
|
+
/** Tools for security auditing (read + bash for dependency checks) */
|
|
50
|
+
SECURITY_AUDIT: [TOOL_NAMES.GLOB, TOOL_NAMES.GREP, TOOL_NAMES.READ_FILE, TOOL_NAMES.BASH],
|
|
51
|
+
};
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ export { defineTool, createSuccessResult, createErrorResult, wrapToolExecute } f
|
|
|
6
6
|
export type { DefineToolOptions } from './define.js';
|
|
7
7
|
export { DefaultToolRegistry, createToolRegistry } from './registry.js';
|
|
8
8
|
export type { ToolRegistryOptions } from './registry.js';
|
|
9
|
-
export { readFileTool, createReadFileTool, writeFileTool, createWriteFileTool, bashTool, createBashTool, execStream, detectFifoUsage, bashOutputTool, createBashOutputTool, killShellTool, createKillShellTool, ShellManager, getDefaultShellManager, setDefaultShellManager, grepTool, createGrepTool, globTool, createGlobTool, editTool, createEditTool, todoWriteTool, todoReadTool, createTodoTools, TodoStore, resetDefaultTodoStore, getDefaultTodoStore, createIsolatedTodoStore, cleanupTodoContextMessages, getTodoContextStats, webFetchTool, createWebFetchTool, createTaskTool, defaultAgentTypes, builtinTools, allBuiltinTools, } from './builtin/index.js';
|
|
10
|
-
export type { ReadFileInput, WriteFileInput, BashInput, BashResult, FifoDetectionResult, BashOutputInput, BashOutputResult, KillShellInput, KillShellResult, ShellStatus, BackgroundShell, ShellOutput, ShellManagerOptions, GrepInput, GlobInput, EditInput, TodoWriteInput, TodoReadInput, TodoItem, TodoStatus, TodoContextCleanupOptions, WebFetchInput, WebFetchResult, WebFetchOptions, TaskInput, TaskResult, AgentTypeConfig, TaskToolOptions, ContextMode, ThoroughnessLevel, SubAgentEventInfo, } from './builtin/index.js';
|
|
9
|
+
export { readFileTool, createReadFileTool, writeFileTool, createWriteFileTool, bashTool, createBashTool, execStream, detectFifoUsage, bashOutputTool, createBashOutputTool, killShellTool, createKillShellTool, ShellManager, getDefaultShellManager, setDefaultShellManager, grepTool, createGrepTool, globTool, createGlobTool, editTool, createEditTool, todoWriteTool, todoReadTool, createTodoTools, TodoStore, resetDefaultTodoStore, getDefaultTodoStore, createIsolatedTodoStore, cleanupTodoContextMessages, getTodoContextStats, webFetchTool, createWebFetchTool, createTaskTool, defaultAgentTypes, suggestTool, createSuggestTool, builtinTools, allBuiltinTools, TOOL_NAMES, TOOL_SETS, } from './builtin/index.js';
|
|
10
|
+
export type { ReadFileInput, WriteFileInput, BashInput, BashResult, FifoDetectionResult, BashOutputInput, BashOutputResult, KillShellInput, KillShellResult, ShellStatus, BackgroundShell, ShellOutput, ShellManagerOptions, GrepInput, GlobInput, EditInput, TodoWriteInput, TodoReadInput, TodoItem, TodoStatus, TodoContextCleanupOptions, WebFetchInput, WebFetchResult, WebFetchOptions, TaskInput, TaskResult, AgentTypeConfig, TaskToolOptions, ContextMode, ThoroughnessLevel, SubAgentEventInfo, SuggestInput, SuggestToolOptions, } from './builtin/index.js';
|