indusagi-coding-agent 0.1.25 → 0.1.26
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/CHANGELOG.md +60 -0
- package/dist/cli/file-processor.js +1 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/core/agent-session.d.ts +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +1 -1
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/bash-executor.d.ts +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/extensions/types.d.ts +1 -3
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/settings-manager.js +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/task-session-manager.d.ts.map +1 -1
- package/dist/core/task-session-manager.js +1 -7
- package/dist/core/task-session-manager.js.map +1 -1
- package/dist/core/tools/bg-process.d.ts +1 -1
- package/dist/core/tools/index.d.ts +57 -50
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +89 -21
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/todo.d.ts +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +1 -1
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +2 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/package.json +3 -3
- package/dist/core/tools/bash.d.ts +0 -428
- package/dist/core/tools/bash.d.ts.map +0 -1
- package/dist/core/tools/bash.js +0 -498
- package/dist/core/tools/bash.js.map +0 -1
- package/dist/core/tools/edit-diff.d.ts +0 -63
- package/dist/core/tools/edit-diff.d.ts.map +0 -1
- package/dist/core/tools/edit-diff.js +0 -243
- package/dist/core/tools/edit-diff.js.map +0 -1
- package/dist/core/tools/edit.d.ts +0 -315
- package/dist/core/tools/edit.d.ts.map +0 -1
- package/dist/core/tools/edit.js +0 -384
- package/dist/core/tools/edit.js.map +0 -1
- package/dist/core/tools/find.d.ts +0 -201
- package/dist/core/tools/find.d.ts.map +0 -1
- package/dist/core/tools/find.js +0 -342
- package/dist/core/tools/find.js.map +0 -1
- package/dist/core/tools/grep.d.ts +0 -323
- package/dist/core/tools/grep.d.ts.map +0 -1
- package/dist/core/tools/grep.js +0 -486
- package/dist/core/tools/grep.js.map +0 -1
- package/dist/core/tools/ls.d.ts +0 -44
- package/dist/core/tools/ls.d.ts.map +0 -1
- package/dist/core/tools/ls.js +0 -124
- package/dist/core/tools/ls.js.map +0 -1
- package/dist/core/tools/path-utils.d.ts +0 -8
- package/dist/core/tools/path-utils.d.ts.map +0 -1
- package/dist/core/tools/path-utils.js +0 -53
- package/dist/core/tools/path-utils.js.map +0 -1
- package/dist/core/tools/read.d.ts +0 -338
- package/dist/core/tools/read.d.ts.map +0 -1
- package/dist/core/tools/read.js +0 -397
- package/dist/core/tools/read.js.map +0 -1
- package/dist/core/tools/truncate.d.ts +0 -70
- package/dist/core/tools/truncate.d.ts.map +0 -1
- package/dist/core/tools/truncate.js +0 -205
- package/dist/core/tools/truncate.js.map +0 -1
- package/dist/core/tools/webfetch.d.ts +0 -174
- package/dist/core/tools/webfetch.d.ts.map +0 -1
- package/dist/core/tools/webfetch.js +0 -380
- package/dist/core/tools/webfetch.js.map +0 -1
- package/dist/core/tools/websearch.d.ts +0 -190
- package/dist/core/tools/websearch.d.ts.map +0 -1
- package/dist/core/tools/websearch.js +0 -267
- package/dist/core/tools/websearch.js.map +0 -1
- package/dist/core/tools/write.d.ts +0 -273
- package/dist/core/tools/write.d.ts.map +0 -1
- package/dist/core/tools/write.js +0 -288
- package/dist/core/tools/write.js.map +0 -1
package/dist/core/tools/grep.js
DELETED
|
@@ -1,486 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Grep Tool - Search file contents with regex or literal patterns
|
|
3
|
-
*
|
|
4
|
-
* @module core/tools/grep
|
|
5
|
-
* @description
|
|
6
|
-
* Implements the grep tool for the agent. Searches file contents with:
|
|
7
|
-
* - Regex or literal pattern matching
|
|
8
|
-
* - Case-insensitive search option
|
|
9
|
-
* - File filtering via glob patterns
|
|
10
|
-
* - Context line display
|
|
11
|
-
*
|
|
12
|
-
* Based on Unix grep and ripgrep (https://github.com/BurntSushi/ripgrep) utilities.
|
|
13
|
-
* Refactored for agent content search with glob filtering.
|
|
14
|
-
* - Match limiting
|
|
15
|
-
* - Output truncation for large results
|
|
16
|
-
* - Remote execution support (SSH, containers)
|
|
17
|
-
* - Fast grep using system grep if available
|
|
18
|
-
*
|
|
19
|
-
* ## Tool Interface
|
|
20
|
-
*
|
|
21
|
-
* **Input Parameters:**
|
|
22
|
-
* - `pattern` (required): Regex or literal string to search for
|
|
23
|
-
* - `path` (optional): Directory or file to search (default: cwd)
|
|
24
|
-
* - `glob` (optional): File filter pattern (e.g., "*.ts")
|
|
25
|
-
* - `ignoreCase` (optional): Case-insensitive search (default: false)
|
|
26
|
-
* - `literal` (optional): Treat pattern as literal string (default: false)
|
|
27
|
-
* - `context` (optional): Lines before/after match (default: 0)
|
|
28
|
-
* - `limit` (optional): Max matches (default: 100)
|
|
29
|
-
*
|
|
30
|
-
* **Output:**
|
|
31
|
-
* - Matching lines with file:line:content format
|
|
32
|
-
* - Context lines if requested
|
|
33
|
-
* - Match count and truncation info
|
|
34
|
-
* - Error if pattern invalid
|
|
35
|
-
*
|
|
36
|
-
* **Error Behavior:**
|
|
37
|
-
* - Invalid directory: Tool error "Path outside working directory"
|
|
38
|
-
* - Invalid regex: Tool error "Invalid regex pattern"
|
|
39
|
-
* - Permission errors: Tool error "EACCES: permission denied"
|
|
40
|
-
*
|
|
41
|
-
* ## Usage in Agent
|
|
42
|
-
*
|
|
43
|
-
* The agent uses this tool to:
|
|
44
|
-
* - Search for specific functions or imports
|
|
45
|
-
* - Find TODO/FIXME comments
|
|
46
|
-
* - Locate configuration values
|
|
47
|
-
* - Search for error messages
|
|
48
|
-
* - Find test cases
|
|
49
|
-
* - Refactor function usage
|
|
50
|
-
*
|
|
51
|
-
* ## Pattern Syntax
|
|
52
|
-
*
|
|
53
|
-
* **Regex patterns (default):**
|
|
54
|
-
* - `function\s+\w+`: Match function declarations
|
|
55
|
-
* - `import.*from`: Match import statements
|
|
56
|
-
* - `TODO|FIXME`: Match TODOs or FIXMEs
|
|
57
|
-
* - `(error|Error)`: Match error-related text
|
|
58
|
-
*
|
|
59
|
-
* **Literal patterns (with literal: true):**
|
|
60
|
-
* - `TODO:`: Match literal "TODO:" string
|
|
61
|
-
* - `const x =`: Match exact assignment
|
|
62
|
-
* - `function foo`: Match literal text
|
|
63
|
-
*
|
|
64
|
-
* **Case-insensitive (with ignoreCase: true):**
|
|
65
|
-
* - `TODO`: Matches "TODO", "todo", "Todo", etc.
|
|
66
|
-
* - `import`: Matches "import", "Import", etc.
|
|
67
|
-
*
|
|
68
|
-
* ## Features
|
|
69
|
-
*
|
|
70
|
-
* **Fast Searching:**
|
|
71
|
-
* - Uses system grep if available (much faster)
|
|
72
|
-
* - Falls back to JavaScript implementation
|
|
73
|
-
* - Respects .gitignore
|
|
74
|
-
*
|
|
75
|
-
* **Result Limiting:**
|
|
76
|
-
* - Default limit: 100 matches
|
|
77
|
-
* - Configurable per call
|
|
78
|
-
* - Prevents OOM for large results
|
|
79
|
-
* - Truncation info in output
|
|
80
|
-
*
|
|
81
|
-
* **Context Display:**
|
|
82
|
-
* - Show N lines before/after each match
|
|
83
|
-
* - Useful for understanding code context
|
|
84
|
-
* - Helps with refactoring decisions
|
|
85
|
-
*
|
|
86
|
-
* **File Filtering:**
|
|
87
|
-
* - Use glob patterns to limit search
|
|
88
|
-
* - E.g., search only *.ts files
|
|
89
|
-
* - E.g., search src/ but not tests/
|
|
90
|
-
*
|
|
91
|
-
* ## Security
|
|
92
|
-
*
|
|
93
|
-
* **Pattern validation:**
|
|
94
|
-
* - Invalid regex patterns error out
|
|
95
|
-
* - Literal patterns are safe
|
|
96
|
-
* - DoS patterns (catastrophic backtracking) possible but unlikely
|
|
97
|
-
*
|
|
98
|
-
* **Path safety:**
|
|
99
|
-
* - All paths resolved relative to cwd
|
|
100
|
-
* - Directory traversal prevented
|
|
101
|
-
* - Invalid paths caught
|
|
102
|
-
*
|
|
103
|
-
* **Result limiting:**
|
|
104
|
-
* - Max 100 matches by default
|
|
105
|
-
* - Prevents runaway searches
|
|
106
|
-
* - Truncation info provided
|
|
107
|
-
*
|
|
108
|
-
* ## Customization
|
|
109
|
-
*
|
|
110
|
-
* **Remote Execution (SSH):**
|
|
111
|
-
* ```typescript
|
|
112
|
-
* const sshTool = createGrepTool(cwd, {
|
|
113
|
-
* operations: {
|
|
114
|
-
* isDirectory: (path) => sshExec(`test -d ${path}`),
|
|
115
|
-
* readFile: (path) => sshExec(`cat ${path}`),
|
|
116
|
-
* },
|
|
117
|
-
* });
|
|
118
|
-
* ```
|
|
119
|
-
*
|
|
120
|
-
* ## Examples
|
|
121
|
-
*
|
|
122
|
-
* ### Find all imports
|
|
123
|
-
* ```typescript
|
|
124
|
-
* // Agent calls: grep {pattern: "^import .*from", glob: "*.ts"}
|
|
125
|
-
* // Returns: All import statements in TypeScript files
|
|
126
|
-
* ```
|
|
127
|
-
*
|
|
128
|
-
* ### Find TODOs with context
|
|
129
|
-
* ```typescript
|
|
130
|
-
* // Agent calls: grep {pattern: "TODO", context: 2}
|
|
131
|
-
* // Returns: TODO lines with 2 lines before/after
|
|
132
|
-
* ```
|
|
133
|
-
*
|
|
134
|
-
* ### Case-insensitive search
|
|
135
|
-
* ```typescript
|
|
136
|
-
* // Agent calls: grep {pattern: "error", ignoreCase: true}
|
|
137
|
-
* // Returns: "Error", "ERROR", "error", etc.
|
|
138
|
-
* ```
|
|
139
|
-
*
|
|
140
|
-
* ## Attribution
|
|
141
|
-
*
|
|
142
|
-
* Based on: indusagi-agent grep tool
|
|
143
|
-
* Modifications:
|
|
144
|
-
* - Added regex support
|
|
145
|
-
* - Added case-insensitive option
|
|
146
|
-
* - Added context lines
|
|
147
|
-
* - Added custom operations interface
|
|
148
|
-
* - Improved error handling
|
|
149
|
-
*/
|
|
150
|
-
import { createInterface } from "node:readline";
|
|
151
|
-
import { Type } from "@sinclair/typebox";
|
|
152
|
-
import { spawn } from "child_process";
|
|
153
|
-
import { readFileSync, statSync } from "fs";
|
|
154
|
-
import path from "path";
|
|
155
|
-
import { ensureTool } from "../../utils/tools-manager.js";
|
|
156
|
-
import { resolveToCwd } from "./path-utils.js";
|
|
157
|
-
import { DEFAULT_MAX_BYTES, formatSize, GREP_MAX_LINE_LENGTH, truncateHead, truncateLine, } from "./truncate.js";
|
|
158
|
-
// ============================================================================
|
|
159
|
-
// Schema & Types
|
|
160
|
-
// ============================================================================
|
|
161
|
-
/**
|
|
162
|
-
* JSON Schema for grep tool parameters
|
|
163
|
-
* @internal
|
|
164
|
-
*/
|
|
165
|
-
const grepSchema = Type.Object({
|
|
166
|
-
pattern: Type.String({ description: "Search pattern (regex or literal string)" }),
|
|
167
|
-
path: Type.Optional(Type.String({ description: "Directory or file to search (default: current directory)" })),
|
|
168
|
-
glob: Type.Optional(Type.String({ description: "Filter files by glob pattern, e.g. '*.ts' or '**/*.spec.ts'" })),
|
|
169
|
-
ignoreCase: Type.Optional(Type.Boolean({ description: "Case-insensitive search (default: false)" })),
|
|
170
|
-
literal: Type.Optional(Type.Boolean({ description: "Treat pattern as literal string instead of regex (default: false)" })),
|
|
171
|
-
context: Type.Optional(Type.Number({ description: "Number of lines to show before and after each match (default: 0)" })),
|
|
172
|
-
limit: Type.Optional(Type.Number({ description: "Maximum number of matches to return (default: 100)" })),
|
|
173
|
-
});
|
|
174
|
-
/**
|
|
175
|
-
* Default maximum matches for grep operations
|
|
176
|
-
* @internal
|
|
177
|
-
*/
|
|
178
|
-
const DEFAULT_LIMIT = 100;
|
|
179
|
-
const defaultGrepOperations = {
|
|
180
|
-
isDirectory: (p) => statSync(p).isDirectory(),
|
|
181
|
-
readFile: (p) => readFileSync(p, "utf-8"),
|
|
182
|
-
};
|
|
183
|
-
// ============================================================================
|
|
184
|
-
// Tool Factory & Exports
|
|
185
|
-
// ============================================================================
|
|
186
|
-
/**
|
|
187
|
-
* Create a grep tool with custom configuration
|
|
188
|
-
*
|
|
189
|
-
* Creates an AgentTool that can search file contents with:
|
|
190
|
-
* - Regex or literal pattern matching
|
|
191
|
-
* - Case-insensitive option
|
|
192
|
-
* - File filtering via glob
|
|
193
|
-
* - Context line display
|
|
194
|
-
* - Result limiting
|
|
195
|
-
* - Remote execution support
|
|
196
|
-
* - Fast system grep
|
|
197
|
-
*
|
|
198
|
-
* **Tool Behavior:**
|
|
199
|
-
* - Resolves paths relative to working directory
|
|
200
|
-
* - Prevents path traversal
|
|
201
|
-
* - Uses ripgrep, grep, or JavaScript fallback
|
|
202
|
-
* - Respects .gitignore
|
|
203
|
-
* - Limits matches (default: 100)
|
|
204
|
-
* - Truncates results if too many
|
|
205
|
-
*
|
|
206
|
-
* **Tool Parameters:**
|
|
207
|
-
* - `pattern` (required): Regex or literal string to search
|
|
208
|
-
* - `path` (optional): Search directory (default: cwd)
|
|
209
|
-
* - `glob` (optional): File filter pattern
|
|
210
|
-
* - `ignoreCase` (optional): Case-insensitive search
|
|
211
|
-
* - `literal` (optional): Treat pattern as literal
|
|
212
|
-
* - `context` (optional): Context lines before/after
|
|
213
|
-
* - `limit` (optional): Max matches (default: 100)
|
|
214
|
-
*
|
|
215
|
-
* **Tool Output:**
|
|
216
|
-
* - Matching lines with file:line:content
|
|
217
|
-
* - Context lines if requested
|
|
218
|
-
* - Match count and truncation info
|
|
219
|
-
* - Errors: Tool error with message
|
|
220
|
-
*
|
|
221
|
-
* **Error Handling:**
|
|
222
|
-
* - Invalid directory: Tool error "Path outside working directory"
|
|
223
|
-
* - Invalid regex: Tool error "Invalid regex pattern"
|
|
224
|
-
* - Search errors: Tool error with message
|
|
225
|
-
*
|
|
226
|
-
* @param cwd - Working directory for relative path resolution
|
|
227
|
-
* - All relative paths resolved from this directory
|
|
228
|
-
* - Prevents directory traversal attacks
|
|
229
|
-
*
|
|
230
|
-
* @param options - Optional configuration
|
|
231
|
-
* - operations: Custom search backend (default: local filesystem)
|
|
232
|
-
*
|
|
233
|
-
* @returns AgentTool instance ready to use
|
|
234
|
-
*
|
|
235
|
-
* @example
|
|
236
|
-
* ```typescript
|
|
237
|
-
* // Basic tool
|
|
238
|
-
* const tool = createGrepTool(process.cwd());
|
|
239
|
-
*
|
|
240
|
-
* // With remote backend (SSH)
|
|
241
|
-
* const remoteTool = createGrepTool(cwd, {
|
|
242
|
-
* operations: sshOperations,
|
|
243
|
-
* });
|
|
244
|
-
* ```
|
|
245
|
-
*
|
|
246
|
-
* @see GrepToolOptions for detailed configuration
|
|
247
|
-
* @see GrepOperations for custom backend interface
|
|
248
|
-
*/
|
|
249
|
-
export function createGrepTool(cwd, options) {
|
|
250
|
-
const customOps = options?.operations;
|
|
251
|
-
return {
|
|
252
|
-
name: "grep",
|
|
253
|
-
label: "grep",
|
|
254
|
-
description: `Search file contents for a pattern. Returns matching lines with file paths and line numbers. Respects .gitignore. Output is truncated to ${DEFAULT_LIMIT} matches or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Long lines are truncated to ${GREP_MAX_LINE_LENGTH} chars.`,
|
|
255
|
-
parameters: grepSchema,
|
|
256
|
-
execute: async (_toolCallId, { pattern, path: searchDir, glob, ignoreCase, literal, context, limit, }, signal) => {
|
|
257
|
-
return new Promise((resolve, reject) => {
|
|
258
|
-
if (signal?.aborted) {
|
|
259
|
-
reject(new Error("Operation aborted"));
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
let settled = false;
|
|
263
|
-
const settle = (fn) => {
|
|
264
|
-
if (!settled) {
|
|
265
|
-
settled = true;
|
|
266
|
-
fn();
|
|
267
|
-
}
|
|
268
|
-
};
|
|
269
|
-
(async () => {
|
|
270
|
-
try {
|
|
271
|
-
const rgPath = await ensureTool("rg", true);
|
|
272
|
-
if (!rgPath) {
|
|
273
|
-
settle(() => reject(new Error("ripgrep (rg) is not available and could not be downloaded")));
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
const searchPath = resolveToCwd(searchDir || ".", cwd);
|
|
277
|
-
const ops = customOps ?? defaultGrepOperations;
|
|
278
|
-
let isDirectory;
|
|
279
|
-
try {
|
|
280
|
-
isDirectory = await ops.isDirectory(searchPath);
|
|
281
|
-
}
|
|
282
|
-
catch (_err) {
|
|
283
|
-
settle(() => reject(new Error(`Path not found: ${searchPath}`)));
|
|
284
|
-
return;
|
|
285
|
-
}
|
|
286
|
-
const contextValue = context && context > 0 ? context : 0;
|
|
287
|
-
const effectiveLimit = Math.max(1, limit ?? DEFAULT_LIMIT);
|
|
288
|
-
const formatPath = (filePath) => {
|
|
289
|
-
if (isDirectory) {
|
|
290
|
-
const relative = path.relative(searchPath, filePath);
|
|
291
|
-
if (relative && !relative.startsWith("..")) {
|
|
292
|
-
return relative.replace(/\\/g, "/");
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
return path.basename(filePath);
|
|
296
|
-
};
|
|
297
|
-
const fileCache = new Map();
|
|
298
|
-
const getFileLines = async (filePath) => {
|
|
299
|
-
let lines = fileCache.get(filePath);
|
|
300
|
-
if (!lines) {
|
|
301
|
-
try {
|
|
302
|
-
const content = await ops.readFile(filePath);
|
|
303
|
-
lines = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
|
|
304
|
-
}
|
|
305
|
-
catch {
|
|
306
|
-
lines = [];
|
|
307
|
-
}
|
|
308
|
-
fileCache.set(filePath, lines);
|
|
309
|
-
}
|
|
310
|
-
return lines;
|
|
311
|
-
};
|
|
312
|
-
const args = ["--json", "--line-number", "--color=never", "--hidden"];
|
|
313
|
-
if (ignoreCase) {
|
|
314
|
-
args.push("--ignore-case");
|
|
315
|
-
}
|
|
316
|
-
if (literal) {
|
|
317
|
-
args.push("--fixed-strings");
|
|
318
|
-
}
|
|
319
|
-
if (glob) {
|
|
320
|
-
args.push("--glob", glob);
|
|
321
|
-
}
|
|
322
|
-
args.push(pattern, searchPath);
|
|
323
|
-
const child = spawn(rgPath, args, { stdio: ["ignore", "pipe", "pipe"] });
|
|
324
|
-
const rl = createInterface({ input: child.stdout });
|
|
325
|
-
let stderr = "";
|
|
326
|
-
let matchCount = 0;
|
|
327
|
-
let matchLimitReached = false;
|
|
328
|
-
let linesTruncated = false;
|
|
329
|
-
let aborted = false;
|
|
330
|
-
let killedDueToLimit = false;
|
|
331
|
-
const outputLines = [];
|
|
332
|
-
const cleanup = () => {
|
|
333
|
-
rl.close();
|
|
334
|
-
signal?.removeEventListener("abort", onAbort);
|
|
335
|
-
};
|
|
336
|
-
const stopChild = (dueToLimit = false) => {
|
|
337
|
-
if (!child.killed) {
|
|
338
|
-
killedDueToLimit = dueToLimit;
|
|
339
|
-
child.kill();
|
|
340
|
-
}
|
|
341
|
-
};
|
|
342
|
-
const onAbort = () => {
|
|
343
|
-
aborted = true;
|
|
344
|
-
stopChild();
|
|
345
|
-
};
|
|
346
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
347
|
-
child.stderr?.on("data", (chunk) => {
|
|
348
|
-
stderr += chunk.toString();
|
|
349
|
-
});
|
|
350
|
-
const formatBlock = async (filePath, lineNumber) => {
|
|
351
|
-
const relativePath = formatPath(filePath);
|
|
352
|
-
const lines = await getFileLines(filePath);
|
|
353
|
-
if (!lines.length) {
|
|
354
|
-
return [`${relativePath}:${lineNumber}: (unable to read file)`];
|
|
355
|
-
}
|
|
356
|
-
const block = [];
|
|
357
|
-
const start = contextValue > 0 ? Math.max(1, lineNumber - contextValue) : lineNumber;
|
|
358
|
-
const end = contextValue > 0 ? Math.min(lines.length, lineNumber + contextValue) : lineNumber;
|
|
359
|
-
for (let current = start; current <= end; current++) {
|
|
360
|
-
const lineText = lines[current - 1] ?? "";
|
|
361
|
-
const sanitized = lineText.replace(/\r/g, "");
|
|
362
|
-
const isMatchLine = current === lineNumber;
|
|
363
|
-
// Truncate long lines
|
|
364
|
-
const { text: truncatedText, wasTruncated } = truncateLine(sanitized);
|
|
365
|
-
if (wasTruncated) {
|
|
366
|
-
linesTruncated = true;
|
|
367
|
-
}
|
|
368
|
-
if (isMatchLine) {
|
|
369
|
-
block.push(`${relativePath}:${current}: ${truncatedText}`);
|
|
370
|
-
}
|
|
371
|
-
else {
|
|
372
|
-
block.push(`${relativePath}-${current}- ${truncatedText}`);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
return block;
|
|
376
|
-
};
|
|
377
|
-
// Collect matches during streaming, format after
|
|
378
|
-
const matches = [];
|
|
379
|
-
rl.on("line", (line) => {
|
|
380
|
-
if (!line.trim() || matchCount >= effectiveLimit) {
|
|
381
|
-
return;
|
|
382
|
-
}
|
|
383
|
-
let event;
|
|
384
|
-
try {
|
|
385
|
-
event = JSON.parse(line);
|
|
386
|
-
}
|
|
387
|
-
catch {
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
if (event.type === "match") {
|
|
391
|
-
matchCount++;
|
|
392
|
-
const filePath = event.data?.path?.text;
|
|
393
|
-
const lineNumber = event.data?.line_number;
|
|
394
|
-
if (filePath && typeof lineNumber === "number") {
|
|
395
|
-
matches.push({ filePath, lineNumber });
|
|
396
|
-
}
|
|
397
|
-
if (matchCount >= effectiveLimit) {
|
|
398
|
-
matchLimitReached = true;
|
|
399
|
-
stopChild(true);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
child.on("error", (error) => {
|
|
404
|
-
cleanup();
|
|
405
|
-
settle(() => reject(new Error(`Failed to run ripgrep: ${error.message}`)));
|
|
406
|
-
});
|
|
407
|
-
child.on("close", async (code) => {
|
|
408
|
-
cleanup();
|
|
409
|
-
if (aborted) {
|
|
410
|
-
settle(() => reject(new Error("Operation aborted")));
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
413
|
-
if (!killedDueToLimit && code !== 0 && code !== 1) {
|
|
414
|
-
const errorMsg = stderr.trim() || `ripgrep exited with code ${code}`;
|
|
415
|
-
settle(() => reject(new Error(errorMsg)));
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
if (matchCount === 0) {
|
|
419
|
-
settle(() => resolve({ content: [{ type: "text", text: "No matches found" }], details: undefined }));
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
// Format matches (async to support remote file reading)
|
|
423
|
-
for (const match of matches) {
|
|
424
|
-
const block = await formatBlock(match.filePath, match.lineNumber);
|
|
425
|
-
outputLines.push(...block);
|
|
426
|
-
}
|
|
427
|
-
// Apply byte truncation (no line limit since we already have match limit)
|
|
428
|
-
const rawOutput = outputLines.join("\n");
|
|
429
|
-
const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
|
|
430
|
-
let output = truncation.content;
|
|
431
|
-
const details = {};
|
|
432
|
-
// Build notices
|
|
433
|
-
const notices = [];
|
|
434
|
-
if (matchLimitReached) {
|
|
435
|
-
notices.push(`${effectiveLimit} matches limit reached. Use limit=${effectiveLimit * 2} for more, or refine pattern`);
|
|
436
|
-
details.matchLimitReached = effectiveLimit;
|
|
437
|
-
}
|
|
438
|
-
if (truncation.truncated) {
|
|
439
|
-
notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
|
|
440
|
-
details.truncation = truncation;
|
|
441
|
-
}
|
|
442
|
-
if (linesTruncated) {
|
|
443
|
-
notices.push(`Some lines truncated to ${GREP_MAX_LINE_LENGTH} chars. Use read tool to see full lines`);
|
|
444
|
-
details.linesTruncated = true;
|
|
445
|
-
}
|
|
446
|
-
if (notices.length > 0) {
|
|
447
|
-
output += `\n\n[${notices.join(". ")}]`;
|
|
448
|
-
}
|
|
449
|
-
settle(() => resolve({
|
|
450
|
-
content: [{ type: "text", text: output }],
|
|
451
|
-
details: Object.keys(details).length > 0 ? details : undefined,
|
|
452
|
-
}));
|
|
453
|
-
});
|
|
454
|
-
}
|
|
455
|
-
catch (err) {
|
|
456
|
-
settle(() => reject(err));
|
|
457
|
-
}
|
|
458
|
-
})();
|
|
459
|
-
});
|
|
460
|
-
},
|
|
461
|
-
};
|
|
462
|
-
}
|
|
463
|
-
/** Default grep tool using process.cwd() - for backwards compatibility */
|
|
464
|
-
/**
|
|
465
|
-
* Default grep tool instance
|
|
466
|
-
*
|
|
467
|
-
* Pre-created grep tool using current process working directory.
|
|
468
|
-
* Supports regex and literal pattern matching with result limiting.
|
|
469
|
-
*
|
|
470
|
-
* Equivalent to:
|
|
471
|
-
* ```typescript
|
|
472
|
-
* const grepTool = createGrepTool(process.cwd());
|
|
473
|
-
* ```
|
|
474
|
-
*
|
|
475
|
-
* For custom configuration or remote backends, use createGrepTool() directly.
|
|
476
|
-
*
|
|
477
|
-
* @example
|
|
478
|
-
* ```typescript
|
|
479
|
-
* import { grepTool } from "./tools/grep.js";
|
|
480
|
-
* const agent = new Agent({ tools: [grepTool] });
|
|
481
|
-
* ```
|
|
482
|
-
*
|
|
483
|
-
* @see createGrepTool for custom configuration
|
|
484
|
-
*/
|
|
485
|
-
export const grepTool = createGrepTool(process.cwd());
|
|
486
|
-
//# sourceMappingURL=grep.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../src/core/tools/grep.ts"],"names":[],"mappings":"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"}
|
package/dist/core/tools/ls.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ls Tool - List directory contents
|
|
3
|
-
*
|
|
4
|
-
* Based on Unix ls command and Node.js fs.readdirSync().
|
|
5
|
-
* Refactored for agent directory exploration.
|
|
6
|
-
*/
|
|
7
|
-
import type { AgentTool } from "indusagi/agent";
|
|
8
|
-
import { type TruncationResult } from "./truncate.js";
|
|
9
|
-
declare const lsSchema: import("@sinclair/typebox").TObject<{
|
|
10
|
-
path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
11
|
-
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
12
|
-
}>;
|
|
13
|
-
export interface LsToolDetails {
|
|
14
|
-
truncation?: TruncationResult;
|
|
15
|
-
entryLimitReached?: number;
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Pluggable operations for the ls tool.
|
|
19
|
-
* Override these to delegate directory listing to remote systems (e.g., SSH).
|
|
20
|
-
*/
|
|
21
|
-
export interface LsOperations {
|
|
22
|
-
/** Check if path exists */
|
|
23
|
-
exists: (absolutePath: string) => Promise<boolean> | boolean;
|
|
24
|
-
/** Get file/directory stats. Throws if not found. */
|
|
25
|
-
stat: (absolutePath: string) => Promise<{
|
|
26
|
-
isDirectory: () => boolean;
|
|
27
|
-
}> | {
|
|
28
|
-
isDirectory: () => boolean;
|
|
29
|
-
};
|
|
30
|
-
/** Read directory entries */
|
|
31
|
-
readdir: (absolutePath: string) => Promise<string[]> | string[];
|
|
32
|
-
}
|
|
33
|
-
export interface LsToolOptions {
|
|
34
|
-
/** Custom operations for directory listing. Default: local filesystem */
|
|
35
|
-
operations?: LsOperations;
|
|
36
|
-
}
|
|
37
|
-
export declare function createLsTool(cwd: string, options?: LsToolOptions): AgentTool<typeof lsSchema>;
|
|
38
|
-
/** Default ls tool using process.cwd() - for backwards compatibility */
|
|
39
|
-
export declare const lsTool: AgentTool<import("@sinclair/typebox").TObject<{
|
|
40
|
-
path: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
41
|
-
limit: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TNumber>;
|
|
42
|
-
}>, any>;
|
|
43
|
-
export {};
|
|
44
|
-
//# sourceMappingURL=ls.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../../src/core/tools/ls.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAKhD,OAAO,EAAiC,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEnG,QAAA,MAAM,QAAQ;;;EAGZ,CAAC;AAIH,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC5B,2BAA2B;IAC3B,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,qDAAqD;IACrD,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC,GAAG;QAAE,WAAW,EAAE,MAAM,OAAO,CAAA;KAAE,CAAC;IACzG,6BAA6B;IAC7B,OAAO,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;CAChE;AAQD,MAAM,WAAW,aAAa;IAC7B,yEAAyE;IACzE,UAAU,CAAC,EAAE,YAAY,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC,OAAO,QAAQ,CAAC,CAyH7F;AAED,wEAAwE;AACxE,eAAO,MAAM,MAAM;;;QAA8B,CAAC"}
|
package/dist/core/tools/ls.js
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Ls Tool - List directory contents
|
|
3
|
-
*
|
|
4
|
-
* Based on Unix ls command and Node.js fs.readdirSync().
|
|
5
|
-
* Refactored for agent directory exploration.
|
|
6
|
-
*/
|
|
7
|
-
import { Type } from "@sinclair/typebox";
|
|
8
|
-
import { existsSync, readdirSync, statSync } from "fs";
|
|
9
|
-
import nodePath from "path";
|
|
10
|
-
import { resolveToCwd } from "./path-utils.js";
|
|
11
|
-
import { DEFAULT_MAX_BYTES, formatSize, truncateHead } from "./truncate.js";
|
|
12
|
-
const lsSchema = Type.Object({
|
|
13
|
-
path: Type.Optional(Type.String({ description: "Directory to list (default: current directory)" })),
|
|
14
|
-
limit: Type.Optional(Type.Number({ description: "Maximum number of entries to return (default: 500)" })),
|
|
15
|
-
});
|
|
16
|
-
const DEFAULT_LIMIT = 500;
|
|
17
|
-
const defaultLsOperations = {
|
|
18
|
-
exists: existsSync,
|
|
19
|
-
stat: statSync,
|
|
20
|
-
readdir: readdirSync,
|
|
21
|
-
};
|
|
22
|
-
export function createLsTool(cwd, options) {
|
|
23
|
-
const ops = options?.operations ?? defaultLsOperations;
|
|
24
|
-
return {
|
|
25
|
-
name: "ls",
|
|
26
|
-
label: "ls",
|
|
27
|
-
description: `List directory contents. Returns entries sorted alphabetically, with '/' suffix for directories. Includes dotfiles. Output is truncated to ${DEFAULT_LIMIT} entries or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first).`,
|
|
28
|
-
parameters: lsSchema,
|
|
29
|
-
execute: async (_toolCallId, { path, limit }, signal) => {
|
|
30
|
-
return new Promise((resolve, reject) => {
|
|
31
|
-
if (signal?.aborted) {
|
|
32
|
-
reject(new Error("Operation aborted"));
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
const onAbort = () => reject(new Error("Operation aborted"));
|
|
36
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
37
|
-
(async () => {
|
|
38
|
-
try {
|
|
39
|
-
const dirPath = resolveToCwd(path || ".", cwd);
|
|
40
|
-
const effectiveLimit = limit ?? DEFAULT_LIMIT;
|
|
41
|
-
// Check if path exists
|
|
42
|
-
if (!(await ops.exists(dirPath))) {
|
|
43
|
-
reject(new Error(`Path not found: ${dirPath}`));
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
// Check if path is a directory
|
|
47
|
-
const stat = await ops.stat(dirPath);
|
|
48
|
-
if (!stat.isDirectory()) {
|
|
49
|
-
reject(new Error(`Not a directory: ${dirPath}`));
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
// Read directory entries
|
|
53
|
-
let entries;
|
|
54
|
-
try {
|
|
55
|
-
entries = await ops.readdir(dirPath);
|
|
56
|
-
}
|
|
57
|
-
catch (e) {
|
|
58
|
-
reject(new Error(`Cannot read directory: ${e.message}`));
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
// Sort alphabetically (case-insensitive)
|
|
62
|
-
entries.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase()));
|
|
63
|
-
// Format entries with directory indicators
|
|
64
|
-
const results = [];
|
|
65
|
-
let entryLimitReached = false;
|
|
66
|
-
for (const entry of entries) {
|
|
67
|
-
if (results.length >= effectiveLimit) {
|
|
68
|
-
entryLimitReached = true;
|
|
69
|
-
break;
|
|
70
|
-
}
|
|
71
|
-
const fullPath = nodePath.join(dirPath, entry);
|
|
72
|
-
let suffix = "";
|
|
73
|
-
try {
|
|
74
|
-
const entryStat = await ops.stat(fullPath);
|
|
75
|
-
if (entryStat.isDirectory()) {
|
|
76
|
-
suffix = "/";
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
catch {
|
|
80
|
-
// Skip entries we can't stat
|
|
81
|
-
continue;
|
|
82
|
-
}
|
|
83
|
-
results.push(entry + suffix);
|
|
84
|
-
}
|
|
85
|
-
signal?.removeEventListener("abort", onAbort);
|
|
86
|
-
if (results.length === 0) {
|
|
87
|
-
resolve({ content: [{ type: "text", text: "(empty directory)" }], details: undefined });
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
// Apply byte truncation (no line limit since we already have entry limit)
|
|
91
|
-
const rawOutput = results.join("\n");
|
|
92
|
-
const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
|
|
93
|
-
let output = truncation.content;
|
|
94
|
-
const details = {};
|
|
95
|
-
// Build notices
|
|
96
|
-
const notices = [];
|
|
97
|
-
if (entryLimitReached) {
|
|
98
|
-
notices.push(`${effectiveLimit} entries limit reached. Use limit=${effectiveLimit * 2} for more`);
|
|
99
|
-
details.entryLimitReached = effectiveLimit;
|
|
100
|
-
}
|
|
101
|
-
if (truncation.truncated) {
|
|
102
|
-
notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
|
|
103
|
-
details.truncation = truncation;
|
|
104
|
-
}
|
|
105
|
-
if (notices.length > 0) {
|
|
106
|
-
output += `\n\n[${notices.join(". ")}]`;
|
|
107
|
-
}
|
|
108
|
-
resolve({
|
|
109
|
-
content: [{ type: "text", text: output }],
|
|
110
|
-
details: Object.keys(details).length > 0 ? details : undefined,
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
catch (e) {
|
|
114
|
-
signal?.removeEventListener("abort", onAbort);
|
|
115
|
-
reject(e);
|
|
116
|
-
}
|
|
117
|
-
})();
|
|
118
|
-
});
|
|
119
|
-
},
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
/** Default ls tool using process.cwd() - for backwards compatibility */
|
|
123
|
-
export const lsTool = createLsTool(process.cwd());
|
|
124
|
-
//# sourceMappingURL=ls.js.map
|