@mariozechner/pi-coding-agent 0.26.0 → 0.27.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.
Files changed (101) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/dist/cli/file-processor.d.ts.map +1 -1
  3. package/dist/cli/file-processor.js +1 -1
  4. package/dist/cli/file-processor.js.map +1 -1
  5. package/dist/core/agent-session.d.ts +7 -5
  6. package/dist/core/agent-session.d.ts.map +1 -1
  7. package/dist/core/agent-session.js +49 -15
  8. package/dist/core/agent-session.js.map +1 -1
  9. package/dist/core/hooks/index.d.ts +1 -1
  10. package/dist/core/hooks/index.d.ts.map +1 -1
  11. package/dist/core/hooks/index.js.map +1 -1
  12. package/dist/core/hooks/runner.d.ts +3 -3
  13. package/dist/core/hooks/runner.d.ts.map +1 -1
  14. package/dist/core/hooks/runner.js +7 -3
  15. package/dist/core/hooks/runner.js.map +1 -1
  16. package/dist/core/hooks/types.d.ts +30 -24
  17. package/dist/core/hooks/types.d.ts.map +1 -1
  18. package/dist/core/hooks/types.js.map +1 -1
  19. package/dist/core/sdk.d.ts +2 -2
  20. package/dist/core/sdk.d.ts.map +1 -1
  21. package/dist/core/sdk.js +7 -3
  22. package/dist/core/sdk.js.map +1 -1
  23. package/dist/core/system-prompt.d.ts.map +1 -1
  24. package/dist/core/system-prompt.js +1 -1
  25. package/dist/core/system-prompt.js.map +1 -1
  26. package/dist/core/tools/bash.d.ts +6 -1
  27. package/dist/core/tools/bash.d.ts.map +1 -1
  28. package/dist/core/tools/bash.js +149 -144
  29. package/dist/core/tools/bash.js.map +1 -1
  30. package/dist/core/tools/edit.d.ts +7 -1
  31. package/dist/core/tools/edit.d.ts.map +1 -1
  32. package/dist/core/tools/edit.js +105 -102
  33. package/dist/core/tools/edit.js.map +1 -1
  34. package/dist/core/tools/find.d.ts +7 -1
  35. package/dist/core/tools/find.d.ts.map +1 -1
  36. package/dist/core/tools/find.js +128 -124
  37. package/dist/core/tools/find.js.map +1 -1
  38. package/dist/core/tools/grep.d.ts +11 -1
  39. package/dist/core/tools/grep.d.ts.map +1 -1
  40. package/dist/core/tools/grep.js +198 -194
  41. package/dist/core/tools/grep.js.map +1 -1
  42. package/dist/core/tools/index.d.ts +19 -7
  43. package/dist/core/tools/index.d.ts.map +1 -1
  44. package/dist/core/tools/index.js +43 -17
  45. package/dist/core/tools/index.js.map +1 -1
  46. package/dist/core/tools/ls.d.ts +6 -1
  47. package/dist/core/tools/ls.d.ts.map +1 -1
  48. package/dist/core/tools/ls.js +90 -86
  49. package/dist/core/tools/ls.js.map +1 -1
  50. package/dist/core/tools/path-utils.d.ts +6 -1
  51. package/dist/core/tools/path-utils.d.ts.map +1 -1
  52. package/dist/core/tools/path-utils.js +17 -5
  53. package/dist/core/tools/path-utils.js.map +1 -1
  54. package/dist/core/tools/read.d.ts +7 -1
  55. package/dist/core/tools/read.d.ts.map +1 -1
  56. package/dist/core/tools/read.js +118 -115
  57. package/dist/core/tools/read.js.map +1 -1
  58. package/dist/core/tools/write.d.ts +6 -1
  59. package/dist/core/tools/write.d.ts.map +1 -1
  60. package/dist/core/tools/write.js +63 -59
  61. package/dist/core/tools/write.js.map +1 -1
  62. package/dist/index.d.ts +2 -2
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +4 -2
  65. package/dist/index.js.map +1 -1
  66. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  67. package/dist/modes/interactive/components/bash-execution.js +5 -5
  68. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  69. package/dist/modes/interactive/components/tool-execution.d.ts +8 -3
  70. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  71. package/dist/modes/interactive/components/tool-execution.js +73 -47
  72. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  73. package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
  74. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
  75. package/dist/modes/interactive/components/visual-truncate.js +33 -0
  76. package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
  77. package/dist/modes/interactive/interactive-mode.d.ts +1 -0
  78. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  79. package/dist/modes/interactive/interactive-mode.js +26 -9
  80. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  81. package/dist/modes/rpc/rpc-client.d.ts +10 -2
  82. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  83. package/dist/modes/rpc/rpc-client.js +7 -2
  84. package/dist/modes/rpc/rpc-client.js.map +1 -1
  85. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  86. package/dist/modes/rpc/rpc-mode.js +5 -5
  87. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  88. package/dist/modes/rpc/rpc-types.d.ts +7 -0
  89. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  90. package/dist/modes/rpc/rpc-types.js.map +1 -1
  91. package/docs/hooks.md +42 -28
  92. package/docs/rpc.md +26 -6
  93. package/docs/sdk.md +47 -2
  94. package/examples/hooks/README.md +19 -3
  95. package/examples/hooks/auto-commit-on-exit.ts +50 -0
  96. package/examples/hooks/confirm-destructive.ts +62 -0
  97. package/examples/hooks/dirty-repo-guard.ts +59 -0
  98. package/examples/hooks/git-checkpoint.ts +6 -5
  99. package/examples/sdk/05-tools.ts +30 -4
  100. package/examples/sdk/12-full-control.ts +12 -4
  101. package/package.json +4 -4
@@ -4,7 +4,7 @@ import { spawn } from "child_process";
4
4
  import { readFileSync, statSync } from "fs";
5
5
  import path from "path";
6
6
  import { ensureTool } from "../../utils/tools-manager.js";
7
- import { expandPath } from "./path-utils.js";
7
+ import { resolveToCwd } from "./path-utils.js";
8
8
  import { DEFAULT_MAX_BYTES, formatSize, GREP_MAX_LINE_LENGTH, truncateHead, truncateLine, } from "./truncate.js";
9
9
  const grepSchema = Type.Object({
10
10
  pattern: Type.String({ description: "Search pattern (regex or literal string)" }),
@@ -16,208 +16,212 @@ const grepSchema = Type.Object({
16
16
  limit: Type.Optional(Type.Number({ description: "Maximum number of matches to return (default: 100)" })),
17
17
  });
18
18
  const DEFAULT_LIMIT = 100;
19
- export const grepTool = {
20
- name: "grep",
21
- label: "grep",
22
- 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.`,
23
- parameters: grepSchema,
24
- execute: async (_toolCallId, { pattern, path: searchDir, glob, ignoreCase, literal, context, limit, }, signal) => {
25
- return new Promise((resolve, reject) => {
26
- if (signal?.aborted) {
27
- reject(new Error("Operation aborted"));
28
- return;
29
- }
30
- let settled = false;
31
- const settle = (fn) => {
32
- if (!settled) {
33
- settled = true;
34
- fn();
19
+ export function createGrepTool(cwd) {
20
+ return {
21
+ name: "grep",
22
+ label: "grep",
23
+ 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.`,
24
+ parameters: grepSchema,
25
+ execute: async (_toolCallId, { pattern, path: searchDir, glob, ignoreCase, literal, context, limit, }, signal) => {
26
+ return new Promise((resolve, reject) => {
27
+ if (signal?.aborted) {
28
+ reject(new Error("Operation aborted"));
29
+ return;
35
30
  }
36
- };
37
- (async () => {
38
- try {
39
- const rgPath = await ensureTool("rg", true);
40
- if (!rgPath) {
41
- settle(() => reject(new Error("ripgrep (rg) is not available and could not be downloaded")));
42
- return;
31
+ let settled = false;
32
+ const settle = (fn) => {
33
+ if (!settled) {
34
+ settled = true;
35
+ fn();
43
36
  }
44
- const searchPath = path.resolve(expandPath(searchDir || "."));
45
- let searchStat;
37
+ };
38
+ (async () => {
46
39
  try {
47
- searchStat = statSync(searchPath);
48
- }
49
- catch (_err) {
50
- settle(() => reject(new Error(`Path not found: ${searchPath}`)));
51
- return;
52
- }
53
- const isDirectory = searchStat.isDirectory();
54
- const contextValue = context && context > 0 ? context : 0;
55
- const effectiveLimit = Math.max(1, limit ?? DEFAULT_LIMIT);
56
- const formatPath = (filePath) => {
57
- if (isDirectory) {
58
- const relative = path.relative(searchPath, filePath);
59
- if (relative && !relative.startsWith("..")) {
60
- return relative.replace(/\\/g, "/");
61
- }
62
- }
63
- return path.basename(filePath);
64
- };
65
- const fileCache = new Map();
66
- const getFileLines = (filePath) => {
67
- let lines = fileCache.get(filePath);
68
- if (!lines) {
69
- try {
70
- const content = readFileSync(filePath, "utf-8");
71
- lines = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
72
- }
73
- catch {
74
- lines = [];
75
- }
76
- fileCache.set(filePath, lines);
77
- }
78
- return lines;
79
- };
80
- const args = ["--json", "--line-number", "--color=never", "--hidden"];
81
- if (ignoreCase) {
82
- args.push("--ignore-case");
83
- }
84
- if (literal) {
85
- args.push("--fixed-strings");
86
- }
87
- if (glob) {
88
- args.push("--glob", glob);
89
- }
90
- args.push(pattern, searchPath);
91
- const child = spawn(rgPath, args, { stdio: ["ignore", "pipe", "pipe"] });
92
- const rl = createInterface({ input: child.stdout });
93
- let stderr = "";
94
- let matchCount = 0;
95
- let matchLimitReached = false;
96
- let linesTruncated = false;
97
- let aborted = false;
98
- let killedDueToLimit = false;
99
- const outputLines = [];
100
- const cleanup = () => {
101
- rl.close();
102
- signal?.removeEventListener("abort", onAbort);
103
- };
104
- const stopChild = (dueToLimit = false) => {
105
- if (!child.killed) {
106
- killedDueToLimit = dueToLimit;
107
- child.kill();
108
- }
109
- };
110
- const onAbort = () => {
111
- aborted = true;
112
- stopChild();
113
- };
114
- signal?.addEventListener("abort", onAbort, { once: true });
115
- child.stderr?.on("data", (chunk) => {
116
- stderr += chunk.toString();
117
- });
118
- const formatBlock = (filePath, lineNumber) => {
119
- const relativePath = formatPath(filePath);
120
- const lines = getFileLines(filePath);
121
- if (!lines.length) {
122
- return [`${relativePath}:${lineNumber}: (unable to read file)`];
123
- }
124
- const block = [];
125
- const start = contextValue > 0 ? Math.max(1, lineNumber - contextValue) : lineNumber;
126
- const end = contextValue > 0 ? Math.min(lines.length, lineNumber + contextValue) : lineNumber;
127
- for (let current = start; current <= end; current++) {
128
- const lineText = lines[current - 1] ?? "";
129
- const sanitized = lineText.replace(/\r/g, "");
130
- const isMatchLine = current === lineNumber;
131
- // Truncate long lines
132
- const { text: truncatedText, wasTruncated } = truncateLine(sanitized);
133
- if (wasTruncated) {
134
- linesTruncated = true;
135
- }
136
- if (isMatchLine) {
137
- block.push(`${relativePath}:${current}: ${truncatedText}`);
138
- }
139
- else {
140
- block.push(`${relativePath}-${current}- ${truncatedText}`);
141
- }
142
- }
143
- return block;
144
- };
145
- rl.on("line", (line) => {
146
- if (!line.trim() || matchCount >= effectiveLimit) {
40
+ const rgPath = await ensureTool("rg", true);
41
+ if (!rgPath) {
42
+ settle(() => reject(new Error("ripgrep (rg) is not available and could not be downloaded")));
147
43
  return;
148
44
  }
149
- let event;
45
+ const searchPath = resolveToCwd(searchDir || ".", cwd);
46
+ let searchStat;
150
47
  try {
151
- event = JSON.parse(line);
48
+ searchStat = statSync(searchPath);
152
49
  }
153
- catch {
50
+ catch (_err) {
51
+ settle(() => reject(new Error(`Path not found: ${searchPath}`)));
154
52
  return;
155
53
  }
156
- if (event.type === "match") {
157
- matchCount++;
158
- const filePath = event.data?.path?.text;
159
- const lineNumber = event.data?.line_number;
160
- if (filePath && typeof lineNumber === "number") {
161
- outputLines.push(...formatBlock(filePath, lineNumber));
54
+ const isDirectory = searchStat.isDirectory();
55
+ const contextValue = context && context > 0 ? context : 0;
56
+ const effectiveLimit = Math.max(1, limit ?? DEFAULT_LIMIT);
57
+ const formatPath = (filePath) => {
58
+ if (isDirectory) {
59
+ const relative = path.relative(searchPath, filePath);
60
+ if (relative && !relative.startsWith("..")) {
61
+ return relative.replace(/\\/g, "/");
62
+ }
162
63
  }
163
- if (matchCount >= effectiveLimit) {
164
- matchLimitReached = true;
165
- stopChild(true);
64
+ return path.basename(filePath);
65
+ };
66
+ const fileCache = new Map();
67
+ const getFileLines = (filePath) => {
68
+ let lines = fileCache.get(filePath);
69
+ if (!lines) {
70
+ try {
71
+ const content = readFileSync(filePath, "utf-8");
72
+ lines = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n");
73
+ }
74
+ catch {
75
+ lines = [];
76
+ }
77
+ fileCache.set(filePath, lines);
166
78
  }
167
- }
168
- });
169
- child.on("error", (error) => {
170
- cleanup();
171
- settle(() => reject(new Error(`Failed to run ripgrep: ${error.message}`)));
172
- });
173
- child.on("close", (code) => {
174
- cleanup();
175
- if (aborted) {
176
- settle(() => reject(new Error("Operation aborted")));
177
- return;
178
- }
179
- if (!killedDueToLimit && code !== 0 && code !== 1) {
180
- const errorMsg = stderr.trim() || `ripgrep exited with code ${code}`;
181
- settle(() => reject(new Error(errorMsg)));
182
- return;
183
- }
184
- if (matchCount === 0) {
185
- settle(() => resolve({ content: [{ type: "text", text: "No matches found" }], details: undefined }));
186
- return;
187
- }
188
- // Apply byte truncation (no line limit since we already have match limit)
189
- const rawOutput = outputLines.join("\n");
190
- const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
191
- let output = truncation.content;
192
- const details = {};
193
- // Build notices
194
- const notices = [];
195
- if (matchLimitReached) {
196
- notices.push(`${effectiveLimit} matches limit reached. Use limit=${effectiveLimit * 2} for more, or refine pattern`);
197
- details.matchLimitReached = effectiveLimit;
198
- }
199
- if (truncation.truncated) {
200
- notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
201
- details.truncation = truncation;
202
- }
203
- if (linesTruncated) {
204
- notices.push(`Some lines truncated to ${GREP_MAX_LINE_LENGTH} chars. Use read tool to see full lines`);
205
- details.linesTruncated = true;
206
- }
207
- if (notices.length > 0) {
208
- output += `\n\n[${notices.join(". ")}]`;
209
- }
210
- settle(() => resolve({
211
- content: [{ type: "text", text: output }],
212
- details: Object.keys(details).length > 0 ? details : undefined,
213
- }));
214
- });
215
- }
216
- catch (err) {
217
- settle(() => reject(err));
218
- }
219
- })();
220
- });
221
- },
222
- };
79
+ return lines;
80
+ };
81
+ const args = ["--json", "--line-number", "--color=never", "--hidden"];
82
+ if (ignoreCase) {
83
+ args.push("--ignore-case");
84
+ }
85
+ if (literal) {
86
+ args.push("--fixed-strings");
87
+ }
88
+ if (glob) {
89
+ args.push("--glob", glob);
90
+ }
91
+ args.push(pattern, searchPath);
92
+ const child = spawn(rgPath, args, { stdio: ["ignore", "pipe", "pipe"] });
93
+ const rl = createInterface({ input: child.stdout });
94
+ let stderr = "";
95
+ let matchCount = 0;
96
+ let matchLimitReached = false;
97
+ let linesTruncated = false;
98
+ let aborted = false;
99
+ let killedDueToLimit = false;
100
+ const outputLines = [];
101
+ const cleanup = () => {
102
+ rl.close();
103
+ signal?.removeEventListener("abort", onAbort);
104
+ };
105
+ const stopChild = (dueToLimit = false) => {
106
+ if (!child.killed) {
107
+ killedDueToLimit = dueToLimit;
108
+ child.kill();
109
+ }
110
+ };
111
+ const onAbort = () => {
112
+ aborted = true;
113
+ stopChild();
114
+ };
115
+ signal?.addEventListener("abort", onAbort, { once: true });
116
+ child.stderr?.on("data", (chunk) => {
117
+ stderr += chunk.toString();
118
+ });
119
+ const formatBlock = (filePath, lineNumber) => {
120
+ const relativePath = formatPath(filePath);
121
+ const lines = getFileLines(filePath);
122
+ if (!lines.length) {
123
+ return [`${relativePath}:${lineNumber}: (unable to read file)`];
124
+ }
125
+ const block = [];
126
+ const start = contextValue > 0 ? Math.max(1, lineNumber - contextValue) : lineNumber;
127
+ const end = contextValue > 0 ? Math.min(lines.length, lineNumber + contextValue) : lineNumber;
128
+ for (let current = start; current <= end; current++) {
129
+ const lineText = lines[current - 1] ?? "";
130
+ const sanitized = lineText.replace(/\r/g, "");
131
+ const isMatchLine = current === lineNumber;
132
+ // Truncate long lines
133
+ const { text: truncatedText, wasTruncated } = truncateLine(sanitized);
134
+ if (wasTruncated) {
135
+ linesTruncated = true;
136
+ }
137
+ if (isMatchLine) {
138
+ block.push(`${relativePath}:${current}: ${truncatedText}`);
139
+ }
140
+ else {
141
+ block.push(`${relativePath}-${current}- ${truncatedText}`);
142
+ }
143
+ }
144
+ return block;
145
+ };
146
+ rl.on("line", (line) => {
147
+ if (!line.trim() || matchCount >= effectiveLimit) {
148
+ return;
149
+ }
150
+ let event;
151
+ try {
152
+ event = JSON.parse(line);
153
+ }
154
+ catch {
155
+ return;
156
+ }
157
+ if (event.type === "match") {
158
+ matchCount++;
159
+ const filePath = event.data?.path?.text;
160
+ const lineNumber = event.data?.line_number;
161
+ if (filePath && typeof lineNumber === "number") {
162
+ outputLines.push(...formatBlock(filePath, lineNumber));
163
+ }
164
+ if (matchCount >= effectiveLimit) {
165
+ matchLimitReached = true;
166
+ stopChild(true);
167
+ }
168
+ }
169
+ });
170
+ child.on("error", (error) => {
171
+ cleanup();
172
+ settle(() => reject(new Error(`Failed to run ripgrep: ${error.message}`)));
173
+ });
174
+ child.on("close", (code) => {
175
+ cleanup();
176
+ if (aborted) {
177
+ settle(() => reject(new Error("Operation aborted")));
178
+ return;
179
+ }
180
+ if (!killedDueToLimit && code !== 0 && code !== 1) {
181
+ const errorMsg = stderr.trim() || `ripgrep exited with code ${code}`;
182
+ settle(() => reject(new Error(errorMsg)));
183
+ return;
184
+ }
185
+ if (matchCount === 0) {
186
+ settle(() => resolve({ content: [{ type: "text", text: "No matches found" }], details: undefined }));
187
+ return;
188
+ }
189
+ // Apply byte truncation (no line limit since we already have match limit)
190
+ const rawOutput = outputLines.join("\n");
191
+ const truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });
192
+ let output = truncation.content;
193
+ const details = {};
194
+ // Build notices
195
+ const notices = [];
196
+ if (matchLimitReached) {
197
+ notices.push(`${effectiveLimit} matches limit reached. Use limit=${effectiveLimit * 2} for more, or refine pattern`);
198
+ details.matchLimitReached = effectiveLimit;
199
+ }
200
+ if (truncation.truncated) {
201
+ notices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);
202
+ details.truncation = truncation;
203
+ }
204
+ if (linesTruncated) {
205
+ notices.push(`Some lines truncated to ${GREP_MAX_LINE_LENGTH} chars. Use read tool to see full lines`);
206
+ details.linesTruncated = true;
207
+ }
208
+ if (notices.length > 0) {
209
+ output += `\n\n[${notices.join(". ")}]`;
210
+ }
211
+ settle(() => resolve({
212
+ content: [{ type: "text", text: output }],
213
+ details: Object.keys(details).length > 0 ? details : undefined,
214
+ }));
215
+ });
216
+ }
217
+ catch (err) {
218
+ settle(() => reject(err));
219
+ }
220
+ })();
221
+ });
222
+ },
223
+ };
224
+ }
225
+ /** Default grep tool using process.cwd() - for backwards compatibility */
226
+ export const grepTool = createGrepTool(process.cwd());
223
227
  //# sourceMappingURL=grep.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../src/core/tools/grep.ts"],"names":[],"mappings":"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","sourcesContent":["import { createInterface } from \"node:readline\";\nimport type { AgentTool } from \"@mariozechner/pi-ai\";\nimport { Type } from \"@sinclair/typebox\";\nimport { spawn } from \"child_process\";\nimport { readFileSync, type Stats, statSync } from \"fs\";\nimport path from \"path\";\nimport { ensureTool } from \"../../utils/tools-manager.js\";\nimport { expandPath } from \"./path-utils.js\";\nimport {\n\tDEFAULT_MAX_BYTES,\n\tformatSize,\n\tGREP_MAX_LINE_LENGTH,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n} from \"./truncate.js\";\n\nconst grepSchema = Type.Object({\n\tpattern: Type.String({ description: \"Search pattern (regex or literal string)\" }),\n\tpath: Type.Optional(Type.String({ description: \"Directory or file to search (default: current directory)\" })),\n\tglob: Type.Optional(Type.String({ description: \"Filter files by glob pattern, e.g. '*.ts' or '**/*.spec.ts'\" })),\n\tignoreCase: Type.Optional(Type.Boolean({ description: \"Case-insensitive search (default: false)\" })),\n\tliteral: Type.Optional(\n\t\tType.Boolean({ description: \"Treat pattern as literal string instead of regex (default: false)\" }),\n\t),\n\tcontext: Type.Optional(\n\t\tType.Number({ description: \"Number of lines to show before and after each match (default: 0)\" }),\n\t),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of matches to return (default: 100)\" })),\n});\n\nconst DEFAULT_LIMIT = 100;\n\nexport interface GrepToolDetails {\n\ttruncation?: TruncationResult;\n\tmatchLimitReached?: number;\n\tlinesTruncated?: boolean;\n}\n\nexport const grepTool: AgentTool<typeof grepSchema> = {\n\tname: \"grep\",\n\tlabel: \"grep\",\n\tdescription: `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.`,\n\tparameters: grepSchema,\n\texecute: async (\n\t\t_toolCallId: string,\n\t\t{\n\t\t\tpattern,\n\t\t\tpath: searchDir,\n\t\t\tglob,\n\t\t\tignoreCase,\n\t\t\tliteral,\n\t\t\tcontext,\n\t\t\tlimit,\n\t\t}: {\n\t\t\tpattern: string;\n\t\t\tpath?: string;\n\t\t\tglob?: string;\n\t\t\tignoreCase?: boolean;\n\t\t\tliteral?: boolean;\n\t\t\tcontext?: number;\n\t\t\tlimit?: number;\n\t\t},\n\t\tsignal?: AbortSignal,\n\t) => {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tif (signal?.aborted) {\n\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet settled = false;\n\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\tif (!settled) {\n\t\t\t\t\tsettled = true;\n\t\t\t\t\tfn();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\t(async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst rgPath = await ensureTool(\"rg\", true);\n\t\t\t\t\tif (!rgPath) {\n\t\t\t\t\t\tsettle(() => reject(new Error(\"ripgrep (rg) is not available and could not be downloaded\")));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst searchPath = path.resolve(expandPath(searchDir || \".\"));\n\t\t\t\t\tlet searchStat: Stats;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tsearchStat = statSync(searchPath);\n\t\t\t\t\t} catch (_err) {\n\t\t\t\t\t\tsettle(() => reject(new Error(`Path not found: ${searchPath}`)));\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst isDirectory = searchStat.isDirectory();\n\t\t\t\t\tconst contextValue = context && context > 0 ? context : 0;\n\t\t\t\t\tconst effectiveLimit = Math.max(1, limit ?? DEFAULT_LIMIT);\n\n\t\t\t\t\tconst formatPath = (filePath: string): string => {\n\t\t\t\t\t\tif (isDirectory) {\n\t\t\t\t\t\t\tconst relative = path.relative(searchPath, filePath);\n\t\t\t\t\t\t\tif (relative && !relative.startsWith(\"..\")) {\n\t\t\t\t\t\t\t\treturn relative.replace(/\\\\/g, \"/\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn path.basename(filePath);\n\t\t\t\t\t};\n\n\t\t\t\t\tconst fileCache = new Map<string, string[]>();\n\t\t\t\t\tconst getFileLines = (filePath: string): string[] => {\n\t\t\t\t\t\tlet lines = fileCache.get(filePath);\n\t\t\t\t\t\tif (!lines) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tconst content = readFileSync(filePath, \"utf-8\");\n\t\t\t\t\t\t\t\tlines = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").split(\"\\n\");\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\tlines = [];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfileCache.set(filePath, lines);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn lines;\n\t\t\t\t\t};\n\n\t\t\t\t\tconst args: string[] = [\"--json\", \"--line-number\", \"--color=never\", \"--hidden\"];\n\n\t\t\t\t\tif (ignoreCase) {\n\t\t\t\t\t\targs.push(\"--ignore-case\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (literal) {\n\t\t\t\t\t\targs.push(\"--fixed-strings\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (glob) {\n\t\t\t\t\t\targs.push(\"--glob\", glob);\n\t\t\t\t\t}\n\n\t\t\t\t\targs.push(pattern, searchPath);\n\n\t\t\t\t\tconst child = spawn(rgPath, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n\t\t\t\t\tconst rl = createInterface({ input: child.stdout });\n\t\t\t\t\tlet stderr = \"\";\n\t\t\t\t\tlet matchCount = 0;\n\t\t\t\t\tlet matchLimitReached = false;\n\t\t\t\t\tlet linesTruncated = false;\n\t\t\t\t\tlet aborted = false;\n\t\t\t\t\tlet killedDueToLimit = false;\n\t\t\t\t\tconst outputLines: string[] = [];\n\n\t\t\t\t\tconst cleanup = () => {\n\t\t\t\t\t\trl.close();\n\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t};\n\n\t\t\t\t\tconst stopChild = (dueToLimit: boolean = false) => {\n\t\t\t\t\t\tif (!child.killed) {\n\t\t\t\t\t\t\tkilledDueToLimit = dueToLimit;\n\t\t\t\t\t\t\tchild.kill();\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tconst onAbort = () => {\n\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\tstopChild();\n\t\t\t\t\t};\n\n\t\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t\tchild.stderr?.on(\"data\", (chunk) => {\n\t\t\t\t\t\tstderr += chunk.toString();\n\t\t\t\t\t});\n\n\t\t\t\t\tconst formatBlock = (filePath: string, lineNumber: number): string[] => {\n\t\t\t\t\t\tconst relativePath = formatPath(filePath);\n\t\t\t\t\t\tconst lines = getFileLines(filePath);\n\t\t\t\t\t\tif (!lines.length) {\n\t\t\t\t\t\t\treturn [`${relativePath}:${lineNumber}: (unable to read file)`];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst block: string[] = [];\n\t\t\t\t\t\tconst start = contextValue > 0 ? Math.max(1, lineNumber - contextValue) : lineNumber;\n\t\t\t\t\t\tconst end = contextValue > 0 ? Math.min(lines.length, lineNumber + contextValue) : lineNumber;\n\n\t\t\t\t\t\tfor (let current = start; current <= end; current++) {\n\t\t\t\t\t\t\tconst lineText = lines[current - 1] ?? \"\";\n\t\t\t\t\t\t\tconst sanitized = lineText.replace(/\\r/g, \"\");\n\t\t\t\t\t\t\tconst isMatchLine = current === lineNumber;\n\n\t\t\t\t\t\t\t// Truncate long lines\n\t\t\t\t\t\t\tconst { text: truncatedText, wasTruncated } = truncateLine(sanitized);\n\t\t\t\t\t\t\tif (wasTruncated) {\n\t\t\t\t\t\t\t\tlinesTruncated = true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (isMatchLine) {\n\t\t\t\t\t\t\t\tblock.push(`${relativePath}:${current}: ${truncatedText}`);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tblock.push(`${relativePath}-${current}- ${truncatedText}`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn block;\n\t\t\t\t\t};\n\n\t\t\t\t\trl.on(\"line\", (line) => {\n\t\t\t\t\t\tif (!line.trim() || matchCount >= effectiveLimit) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlet event: any;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tevent = JSON.parse(line);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (event.type === \"match\") {\n\t\t\t\t\t\t\tmatchCount++;\n\t\t\t\t\t\t\tconst filePath = event.data?.path?.text;\n\t\t\t\t\t\t\tconst lineNumber = event.data?.line_number;\n\n\t\t\t\t\t\t\tif (filePath && typeof lineNumber === \"number\") {\n\t\t\t\t\t\t\t\toutputLines.push(...formatBlock(filePath, lineNumber));\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (matchCount >= effectiveLimit) {\n\t\t\t\t\t\t\t\tmatchLimitReached = true;\n\t\t\t\t\t\t\t\tstopChild(true);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tchild.on(\"error\", (error) => {\n\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\tsettle(() => reject(new Error(`Failed to run ripgrep: ${error.message}`)));\n\t\t\t\t\t});\n\n\t\t\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\t\t\tcleanup();\n\n\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!killedDueToLimit && code !== 0 && code !== 1) {\n\t\t\t\t\t\t\tconst errorMsg = stderr.trim() || `ripgrep exited with code ${code}`;\n\t\t\t\t\t\t\tsettle(() => reject(new Error(errorMsg)));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (matchCount === 0) {\n\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\tresolve({ content: [{ type: \"text\", text: \"No matches found\" }], details: undefined }),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Apply byte truncation (no line limit since we already have match limit)\n\t\t\t\t\t\tconst rawOutput = outputLines.join(\"\\n\");\n\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\n\t\t\t\t\t\tlet output = truncation.content;\n\t\t\t\t\t\tconst details: GrepToolDetails = {};\n\n\t\t\t\t\t\t// Build notices\n\t\t\t\t\t\tconst notices: string[] = [];\n\n\t\t\t\t\t\tif (matchLimitReached) {\n\t\t\t\t\t\t\tnotices.push(\n\t\t\t\t\t\t\t\t`${effectiveLimit} matches limit reached. Use limit=${effectiveLimit * 2} for more, or refine pattern`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tdetails.matchLimitReached = effectiveLimit;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (linesTruncated) {\n\t\t\t\t\t\t\tnotices.push(\n\t\t\t\t\t\t\t\t`Some lines truncated to ${GREP_MAX_LINE_LENGTH} chars. Use read tool to see full lines`,\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tdetails.linesTruncated = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\toutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: output }],\n\t\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\t} catch (err) {\n\t\t\t\t\tsettle(() => reject(err as Error));\n\t\t\t\t}\n\t\t\t})();\n\t\t});\n\t},\n};\n"]}
1
+ {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../src/core/tools/grep.ts"],"names":[],"mappings":"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","sourcesContent":["import { createInterface } from \"node:readline\";\nimport type { AgentTool } from \"@mariozechner/pi-ai\";\nimport { Type } from \"@sinclair/typebox\";\nimport { spawn } from \"child_process\";\nimport { readFileSync, type Stats, statSync } from \"fs\";\nimport path from \"path\";\nimport { ensureTool } from \"../../utils/tools-manager.js\";\nimport { resolveToCwd } from \"./path-utils.js\";\nimport {\n\tDEFAULT_MAX_BYTES,\n\tformatSize,\n\tGREP_MAX_LINE_LENGTH,\n\ttype TruncationResult,\n\ttruncateHead,\n\ttruncateLine,\n} from \"./truncate.js\";\n\nconst grepSchema = Type.Object({\n\tpattern: Type.String({ description: \"Search pattern (regex or literal string)\" }),\n\tpath: Type.Optional(Type.String({ description: \"Directory or file to search (default: current directory)\" })),\n\tglob: Type.Optional(Type.String({ description: \"Filter files by glob pattern, e.g. '*.ts' or '**/*.spec.ts'\" })),\n\tignoreCase: Type.Optional(Type.Boolean({ description: \"Case-insensitive search (default: false)\" })),\n\tliteral: Type.Optional(\n\t\tType.Boolean({ description: \"Treat pattern as literal string instead of regex (default: false)\" }),\n\t),\n\tcontext: Type.Optional(\n\t\tType.Number({ description: \"Number of lines to show before and after each match (default: 0)\" }),\n\t),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of matches to return (default: 100)\" })),\n});\n\nconst DEFAULT_LIMIT = 100;\n\nexport interface GrepToolDetails {\n\ttruncation?: TruncationResult;\n\tmatchLimitReached?: number;\n\tlinesTruncated?: boolean;\n}\n\nexport function createGrepTool(cwd: string): AgentTool<typeof grepSchema> {\n\treturn {\n\t\tname: \"grep\",\n\t\tlabel: \"grep\",\n\t\tdescription: `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.`,\n\t\tparameters: grepSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{\n\t\t\t\tpattern,\n\t\t\t\tpath: searchDir,\n\t\t\t\tglob,\n\t\t\t\tignoreCase,\n\t\t\t\tliteral,\n\t\t\t\tcontext,\n\t\t\t\tlimit,\n\t\t\t}: {\n\t\t\t\tpattern: string;\n\t\t\t\tpath?: string;\n\t\t\t\tglob?: string;\n\t\t\t\tignoreCase?: boolean;\n\t\t\t\tliteral?: boolean;\n\t\t\t\tcontext?: number;\n\t\t\t\tlimit?: number;\n\t\t\t},\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet settled = false;\n\t\t\t\tconst settle = (fn: () => void) => {\n\t\t\t\t\tif (!settled) {\n\t\t\t\t\t\tsettled = true;\n\t\t\t\t\t\tfn();\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst rgPath = await ensureTool(\"rg\", true);\n\t\t\t\t\t\tif (!rgPath) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(\"ripgrep (rg) is not available and could not be downloaded\")));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst searchPath = resolveToCwd(searchDir || \".\", cwd);\n\t\t\t\t\t\tlet searchStat: Stats;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsearchStat = statSync(searchPath);\n\t\t\t\t\t\t} catch (_err) {\n\t\t\t\t\t\t\tsettle(() => reject(new Error(`Path not found: ${searchPath}`)));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst isDirectory = searchStat.isDirectory();\n\t\t\t\t\t\tconst contextValue = context && context > 0 ? context : 0;\n\t\t\t\t\t\tconst effectiveLimit = Math.max(1, limit ?? DEFAULT_LIMIT);\n\n\t\t\t\t\t\tconst formatPath = (filePath: string): string => {\n\t\t\t\t\t\t\tif (isDirectory) {\n\t\t\t\t\t\t\t\tconst relative = path.relative(searchPath, filePath);\n\t\t\t\t\t\t\t\tif (relative && !relative.startsWith(\"..\")) {\n\t\t\t\t\t\t\t\t\treturn relative.replace(/\\\\/g, \"/\");\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn path.basename(filePath);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst fileCache = new Map<string, string[]>();\n\t\t\t\t\t\tconst getFileLines = (filePath: string): string[] => {\n\t\t\t\t\t\t\tlet lines = fileCache.get(filePath);\n\t\t\t\t\t\t\tif (!lines) {\n\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\tconst content = readFileSync(filePath, \"utf-8\");\n\t\t\t\t\t\t\t\t\tlines = content.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").split(\"\\n\");\n\t\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\t\tlines = [];\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tfileCache.set(filePath, lines);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn lines;\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst args: string[] = [\"--json\", \"--line-number\", \"--color=never\", \"--hidden\"];\n\n\t\t\t\t\t\tif (ignoreCase) {\n\t\t\t\t\t\t\targs.push(\"--ignore-case\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (literal) {\n\t\t\t\t\t\t\targs.push(\"--fixed-strings\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (glob) {\n\t\t\t\t\t\t\targs.push(\"--glob\", glob);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\targs.push(pattern, searchPath);\n\n\t\t\t\t\t\tconst child = spawn(rgPath, args, { stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n\t\t\t\t\t\tconst rl = createInterface({ input: child.stdout });\n\t\t\t\t\t\tlet stderr = \"\";\n\t\t\t\t\t\tlet matchCount = 0;\n\t\t\t\t\t\tlet matchLimitReached = false;\n\t\t\t\t\t\tlet linesTruncated = false;\n\t\t\t\t\t\tlet aborted = false;\n\t\t\t\t\t\tlet killedDueToLimit = false;\n\t\t\t\t\t\tconst outputLines: string[] = [];\n\n\t\t\t\t\t\tconst cleanup = () => {\n\t\t\t\t\t\t\trl.close();\n\t\t\t\t\t\t\tsignal?.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst stopChild = (dueToLimit: boolean = false) => {\n\t\t\t\t\t\t\tif (!child.killed) {\n\t\t\t\t\t\t\t\tkilledDueToLimit = dueToLimit;\n\t\t\t\t\t\t\t\tchild.kill();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tconst onAbort = () => {\n\t\t\t\t\t\t\taborted = true;\n\t\t\t\t\t\t\tstopChild();\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tsignal?.addEventListener(\"abort\", onAbort, { once: true });\n\n\t\t\t\t\t\tchild.stderr?.on(\"data\", (chunk) => {\n\t\t\t\t\t\t\tstderr += chunk.toString();\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tconst formatBlock = (filePath: string, lineNumber: number): string[] => {\n\t\t\t\t\t\t\tconst relativePath = formatPath(filePath);\n\t\t\t\t\t\t\tconst lines = getFileLines(filePath);\n\t\t\t\t\t\t\tif (!lines.length) {\n\t\t\t\t\t\t\t\treturn [`${relativePath}:${lineNumber}: (unable to read file)`];\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tconst block: string[] = [];\n\t\t\t\t\t\t\tconst start = contextValue > 0 ? Math.max(1, lineNumber - contextValue) : lineNumber;\n\t\t\t\t\t\t\tconst end = contextValue > 0 ? Math.min(lines.length, lineNumber + contextValue) : lineNumber;\n\n\t\t\t\t\t\t\tfor (let current = start; current <= end; current++) {\n\t\t\t\t\t\t\t\tconst lineText = lines[current - 1] ?? \"\";\n\t\t\t\t\t\t\t\tconst sanitized = lineText.replace(/\\r/g, \"\");\n\t\t\t\t\t\t\t\tconst isMatchLine = current === lineNumber;\n\n\t\t\t\t\t\t\t\t// Truncate long lines\n\t\t\t\t\t\t\t\tconst { text: truncatedText, wasTruncated } = truncateLine(sanitized);\n\t\t\t\t\t\t\t\tif (wasTruncated) {\n\t\t\t\t\t\t\t\t\tlinesTruncated = true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (isMatchLine) {\n\t\t\t\t\t\t\t\t\tblock.push(`${relativePath}:${current}: ${truncatedText}`);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tblock.push(`${relativePath}-${current}- ${truncatedText}`);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn block;\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\trl.on(\"line\", (line) => {\n\t\t\t\t\t\t\tif (!line.trim() || matchCount >= effectiveLimit) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tlet event: any;\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tevent = JSON.parse(line);\n\t\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (event.type === \"match\") {\n\t\t\t\t\t\t\t\tmatchCount++;\n\t\t\t\t\t\t\t\tconst filePath = event.data?.path?.text;\n\t\t\t\t\t\t\t\tconst lineNumber = event.data?.line_number;\n\n\t\t\t\t\t\t\t\tif (filePath && typeof lineNumber === \"number\") {\n\t\t\t\t\t\t\t\t\toutputLines.push(...formatBlock(filePath, lineNumber));\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (matchCount >= effectiveLimit) {\n\t\t\t\t\t\t\t\t\tmatchLimitReached = true;\n\t\t\t\t\t\t\t\t\tstopChild(true);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tchild.on(\"error\", (error) => {\n\t\t\t\t\t\t\tcleanup();\n\t\t\t\t\t\t\tsettle(() => reject(new Error(`Failed to run ripgrep: ${error.message}`)));\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\t\t\t\tcleanup();\n\n\t\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(\"Operation aborted\")));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!killedDueToLimit && code !== 0 && code !== 1) {\n\t\t\t\t\t\t\t\tconst errorMsg = stderr.trim() || `ripgrep exited with code ${code}`;\n\t\t\t\t\t\t\t\tsettle(() => reject(new Error(errorMsg)));\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (matchCount === 0) {\n\t\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\t\tresolve({ content: [{ type: \"text\", text: \"No matches found\" }], details: undefined }),\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Apply byte truncation (no line limit since we already have match limit)\n\t\t\t\t\t\t\tconst rawOutput = outputLines.join(\"\\n\");\n\t\t\t\t\t\t\tconst truncation = truncateHead(rawOutput, { maxLines: Number.MAX_SAFE_INTEGER });\n\n\t\t\t\t\t\t\tlet output = truncation.content;\n\t\t\t\t\t\t\tconst details: GrepToolDetails = {};\n\n\t\t\t\t\t\t\t// Build notices\n\t\t\t\t\t\t\tconst notices: string[] = [];\n\n\t\t\t\t\t\t\tif (matchLimitReached) {\n\t\t\t\t\t\t\t\tnotices.push(\n\t\t\t\t\t\t\t\t\t`${effectiveLimit} matches limit reached. Use limit=${effectiveLimit * 2} for more, or refine pattern`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tdetails.matchLimitReached = effectiveLimit;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\t\tnotices.push(`${formatSize(DEFAULT_MAX_BYTES)} limit reached`);\n\t\t\t\t\t\t\t\tdetails.truncation = truncation;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (linesTruncated) {\n\t\t\t\t\t\t\t\tnotices.push(\n\t\t\t\t\t\t\t\t\t`Some lines truncated to ${GREP_MAX_LINE_LENGTH} chars. Use read tool to see full lines`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\tdetails.linesTruncated = true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (notices.length > 0) {\n\t\t\t\t\t\t\t\toutput += `\\n\\n[${notices.join(\". \")}]`;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tsettle(() =>\n\t\t\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: output }],\n\t\t\t\t\t\t\t\t\tdetails: Object.keys(details).length > 0 ? details : undefined,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (err) {\n\t\t\t\t\t\tsettle(() => reject(err as Error));\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** Default grep tool using process.cwd() - for backwards compatibility */\nexport const grepTool = createGrepTool(process.cwd());\n"]}
@@ -1,12 +1,12 @@
1
1
  import type { AgentTool } from "@mariozechner/pi-ai";
2
- export { type BashToolDetails, bashTool } from "./bash.js";
3
- export { editTool } from "./edit.js";
4
- export { type FindToolDetails, findTool } from "./find.js";
5
- export { type GrepToolDetails, grepTool } from "./grep.js";
6
- export { type LsToolDetails, lsTool } from "./ls.js";
7
- export { type ReadToolDetails, readTool } from "./read.js";
2
+ export { type BashToolDetails, bashTool, createBashTool } from "./bash.js";
3
+ export { createEditTool, editTool } from "./edit.js";
4
+ export { createFindTool, type FindToolDetails, findTool } from "./find.js";
5
+ export { createGrepTool, type GrepToolDetails, grepTool } from "./grep.js";
6
+ export { createLsTool, type LsToolDetails, lsTool } from "./ls.js";
7
+ export { createReadTool, type ReadToolDetails, readTool } from "./read.js";
8
8
  export type { TruncationResult } from "./truncate.js";
9
- export { writeTool } from "./write.js";
9
+ export { createWriteTool, writeTool } from "./write.js";
10
10
  /** Tool type (AgentTool from pi-ai) */
11
11
  export type Tool = AgentTool<any>;
12
12
  export declare const codingTools: Tool[];
@@ -50,4 +50,16 @@ export declare const allTools: {
50
50
  }>, any>;
51
51
  };
52
52
  export type ToolName = keyof typeof allTools;
53
+ /**
54
+ * Create coding tools configured for a specific working directory.
55
+ */
56
+ export declare function createCodingTools(cwd: string): Tool[];
57
+ /**
58
+ * Create read-only tools configured for a specific working directory.
59
+ */
60
+ export declare function createReadOnlyTools(cwd: string): Tool[];
61
+ /**
62
+ * Create all tools configured for a specific working directory.
63
+ */
64
+ export declare function createAllTools(cwd: string): Record<ToolName, Tool>;
53
65
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrC,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3D,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAUvC,uCAAuC;AACvC,MAAM,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;AAGlC,eAAO,MAAM,WAAW,EAAE,IAAI,EAA8C,CAAC;AAG7E,eAAO,MAAM,aAAa,EAAE,IAAI,EAA2C,CAAC;AAG5E,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQpB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,QAAQ,CAAC","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-ai\";\n\nexport { type BashToolDetails, bashTool } from \"./bash.js\";\nexport { editTool } from \"./edit.js\";\nexport { type FindToolDetails, findTool } from \"./find.js\";\nexport { type GrepToolDetails, grepTool } from \"./grep.js\";\nexport { type LsToolDetails, lsTool } from \"./ls.js\";\nexport { type ReadToolDetails, readTool } from \"./read.js\";\nexport type { TruncationResult } from \"./truncate.js\";\nexport { writeTool } from \"./write.js\";\n\nimport { bashTool } from \"./bash.js\";\nimport { editTool } from \"./edit.js\";\nimport { findTool } from \"./find.js\";\nimport { grepTool } from \"./grep.js\";\nimport { lsTool } from \"./ls.js\";\nimport { readTool } from \"./read.js\";\nimport { writeTool } from \"./write.js\";\n\n/** Tool type (AgentTool from pi-ai) */\nexport type Tool = AgentTool<any>;\n\n// Default tools for full access mode\nexport const codingTools: Tool[] = [readTool, bashTool, editTool, writeTool];\n\n// Read-only tools for exploration without modification\nexport const readOnlyTools: Tool[] = [readTool, grepTool, findTool, lsTool];\n\n// All available tools (including read-only exploration tools)\nexport const allTools = {\n\tread: readTool,\n\tbash: bashTool,\n\tedit: editTool,\n\twrite: writeTool,\n\tgrep: grepTool,\n\tfind: findTool,\n\tls: lsTool,\n};\n\nexport type ToolName = keyof typeof allTools;\n"]}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3E,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAUxD,uCAAuC;AACvC,MAAM,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;AAGlC,eAAO,MAAM,WAAW,EAAE,IAAI,EAA8C,CAAC;AAG7E,eAAO,MAAM,aAAa,EAAE,IAAI,EAA2C,CAAC;AAG5E,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQpB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,QAAQ,CAAC;AAE7C;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,CAErD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,EAAE,CAEvD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAUlE","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-ai\";\n\nexport { type BashToolDetails, bashTool, createBashTool } from \"./bash.js\";\nexport { createEditTool, editTool } from \"./edit.js\";\nexport { createFindTool, type FindToolDetails, findTool } from \"./find.js\";\nexport { createGrepTool, type GrepToolDetails, grepTool } from \"./grep.js\";\nexport { createLsTool, type LsToolDetails, lsTool } from \"./ls.js\";\nexport { createReadTool, type ReadToolDetails, readTool } from \"./read.js\";\nexport type { TruncationResult } from \"./truncate.js\";\nexport { createWriteTool, writeTool } from \"./write.js\";\n\nimport { bashTool, createBashTool } from \"./bash.js\";\nimport { createEditTool, editTool } from \"./edit.js\";\nimport { createFindTool, findTool } from \"./find.js\";\nimport { createGrepTool, grepTool } from \"./grep.js\";\nimport { createLsTool, lsTool } from \"./ls.js\";\nimport { createReadTool, readTool } from \"./read.js\";\nimport { createWriteTool, writeTool } from \"./write.js\";\n\n/** Tool type (AgentTool from pi-ai) */\nexport type Tool = AgentTool<any>;\n\n// Default tools for full access mode (using process.cwd())\nexport const codingTools: Tool[] = [readTool, bashTool, editTool, writeTool];\n\n// Read-only tools for exploration without modification (using process.cwd())\nexport const readOnlyTools: Tool[] = [readTool, grepTool, findTool, lsTool];\n\n// All available tools (using process.cwd())\nexport const allTools = {\n\tread: readTool,\n\tbash: bashTool,\n\tedit: editTool,\n\twrite: writeTool,\n\tgrep: grepTool,\n\tfind: findTool,\n\tls: lsTool,\n};\n\nexport type ToolName = keyof typeof allTools;\n\n/**\n * Create coding tools configured for a specific working directory.\n */\nexport function createCodingTools(cwd: string): Tool[] {\n\treturn [createReadTool(cwd), createBashTool(cwd), createEditTool(cwd), createWriteTool(cwd)];\n}\n\n/**\n * Create read-only tools configured for a specific working directory.\n */\nexport function createReadOnlyTools(cwd: string): Tool[] {\n\treturn [createReadTool(cwd), createGrepTool(cwd), createFindTool(cwd), createLsTool(cwd)];\n}\n\n/**\n * Create all tools configured for a specific working directory.\n */\nexport function createAllTools(cwd: string): Record<ToolName, Tool> {\n\treturn {\n\t\tread: createReadTool(cwd),\n\t\tbash: createBashTool(cwd),\n\t\tedit: createEditTool(cwd),\n\t\twrite: createWriteTool(cwd),\n\t\tgrep: createGrepTool(cwd),\n\t\tfind: createFindTool(cwd),\n\t\tls: createLsTool(cwd),\n\t};\n}\n"]}