@prbe.ai/electron-sdk 0.1.3 → 0.1.5

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 (85) hide show
  1. package/dist/index.d.mts +332 -0
  2. package/dist/index.d.ts +331 -20
  3. package/dist/index.js +2471 -69
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +2402 -0
  6. package/dist/index.mjs.map +1 -0
  7. package/dist/types-DHT-JxMT.d.mts +401 -0
  8. package/dist/types-DHT-JxMT.d.ts +401 -0
  9. package/dist/types.d.mts +2 -0
  10. package/dist/types.d.ts +2 -14
  11. package/dist/types.js +160 -30
  12. package/dist/types.js.map +1 -1
  13. package/dist/types.mjs +125 -0
  14. package/dist/types.mjs.map +1 -0
  15. package/package.json +22 -12
  16. package/dist/agent.d.ts +0 -106
  17. package/dist/agent.d.ts.map +0 -1
  18. package/dist/agent.js +0 -878
  19. package/dist/agent.js.map +0 -1
  20. package/dist/assets/index.d.ts +0 -6
  21. package/dist/assets/index.d.ts.map +0 -1
  22. package/dist/assets/index.js +0 -13
  23. package/dist/assets/index.js.map +0 -1
  24. package/dist/electron/channels.d.ts +0 -21
  25. package/dist/electron/channels.d.ts.map +0 -1
  26. package/dist/electron/channels.js +0 -25
  27. package/dist/electron/channels.js.map +0 -1
  28. package/dist/electron/index.d.ts +0 -12
  29. package/dist/electron/index.d.ts.map +0 -1
  30. package/dist/electron/index.js +0 -22
  31. package/dist/electron/index.js.map +0 -1
  32. package/dist/electron/ipc-interaction-handler.d.ts +0 -21
  33. package/dist/electron/ipc-interaction-handler.d.ts.map +0 -1
  34. package/dist/electron/ipc-interaction-handler.js +0 -48
  35. package/dist/electron/ipc-interaction-handler.js.map +0 -1
  36. package/dist/electron/preload.d.ts +0 -20
  37. package/dist/electron/preload.d.ts.map +0 -1
  38. package/dist/electron/preload.js +0 -72
  39. package/dist/electron/preload.js.map +0 -1
  40. package/dist/electron/setup-handlers.d.ts +0 -30
  41. package/dist/electron/setup-handlers.d.ts.map +0 -1
  42. package/dist/electron/setup-handlers.js +0 -111
  43. package/dist/electron/setup-handlers.js.map +0 -1
  44. package/dist/electron/types.d.ts +0 -56
  45. package/dist/electron/types.d.ts.map +0 -1
  46. package/dist/electron/types.js +0 -9
  47. package/dist/electron/types.js.map +0 -1
  48. package/dist/index.d.ts.map +0 -1
  49. package/dist/interactions.d.ts +0 -63
  50. package/dist/interactions.d.ts.map +0 -1
  51. package/dist/interactions.js +0 -27
  52. package/dist/interactions.js.map +0 -1
  53. package/dist/models.d.ts +0 -218
  54. package/dist/models.d.ts.map +0 -1
  55. package/dist/models.js +0 -121
  56. package/dist/models.js.map +0 -1
  57. package/dist/serialization.d.ts +0 -51
  58. package/dist/serialization.d.ts.map +0 -1
  59. package/dist/serialization.js +0 -72
  60. package/dist/serialization.js.map +0 -1
  61. package/dist/state.d.ts +0 -70
  62. package/dist/state.d.ts.map +0 -1
  63. package/dist/state.js +0 -303
  64. package/dist/state.js.map +0 -1
  65. package/dist/tools/bash.d.ts +0 -30
  66. package/dist/tools/bash.d.ts.map +0 -1
  67. package/dist/tools/bash.js +0 -248
  68. package/dist/tools/bash.js.map +0 -1
  69. package/dist/tools/filesystem.d.ts +0 -63
  70. package/dist/tools/filesystem.d.ts.map +0 -1
  71. package/dist/tools/filesystem.js +0 -573
  72. package/dist/tools/filesystem.js.map +0 -1
  73. package/dist/tools/index.d.ts +0 -46
  74. package/dist/tools/index.d.ts.map +0 -1
  75. package/dist/tools/index.js +0 -171
  76. package/dist/tools/index.js.map +0 -1
  77. package/dist/tools/interactive.d.ts +0 -15
  78. package/dist/tools/interactive.d.ts.map +0 -1
  79. package/dist/tools/interactive.js +0 -58
  80. package/dist/tools/interactive.js.map +0 -1
  81. package/dist/tools/logs.d.ts +0 -72
  82. package/dist/tools/logs.d.ts.map +0 -1
  83. package/dist/tools/logs.js +0 -366
  84. package/dist/tools/logs.js.map +0 -1
  85. package/dist/types.d.ts.map +0 -1
@@ -1,63 +0,0 @@
1
- /**
2
- * tools/filesystem.ts — Built-in filesystem tools
3
- *
4
- * Implements: client_list_directory, client_read_file, client_search_content,
5
- * client_find_files, client_flag_file
6
- *
7
- * Mirrors PRBEAgentTools.swift filesystem tool implementations.
8
- */
9
- import type { PRBEToolDeclaration, FlaggedFileIn } from "../models";
10
- import type { PRBEInteractionRequester } from "../interactions";
11
- import type { PRBETool } from "./index";
12
- export declare class ListDirectoryTool implements PRBETool {
13
- private readonly autoApprovedDirs;
14
- private readonly requester?;
15
- private readonly grantedPaths?;
16
- constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>);
17
- get declaration(): PRBEToolDeclaration;
18
- execute(args: Record<string, unknown>): Promise<string>;
19
- private static readonly MAX_ENTRIES;
20
- private listDir;
21
- }
22
- export declare class ReadFileTool implements PRBETool {
23
- private readonly autoApprovedDirs;
24
- private readonly requester?;
25
- private readonly grantedPaths?;
26
- constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>);
27
- get declaration(): PRBEToolDeclaration;
28
- execute(args: Record<string, unknown>): Promise<string>;
29
- }
30
- export declare class SearchContentTool implements PRBETool {
31
- private readonly autoApprovedDirs;
32
- private readonly requester?;
33
- private readonly grantedPaths?;
34
- constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>);
35
- get declaration(): PRBEToolDeclaration;
36
- execute(args: Record<string, unknown>): Promise<string>;
37
- private collectFiles;
38
- }
39
- export declare class FindFilesTool implements PRBETool {
40
- private readonly autoApprovedDirs;
41
- private readonly requester?;
42
- private readonly grantedPaths?;
43
- constructor(autoApprovedDirs: string[], requester?: PRBEInteractionRequester, grantedPaths?: Set<string>);
44
- get declaration(): PRBEToolDeclaration;
45
- execute(args: Record<string, unknown>): Promise<string>;
46
- private walkAndMatch;
47
- /**
48
- * Simple glob matching: supports *, ?, and character classes [...].
49
- * Converts glob to regex and tests against the filename.
50
- */
51
- private globMatch;
52
- }
53
- export declare class FlagFileTool implements PRBETool {
54
- private readonly autoApprovedDirs;
55
- private readonly onFlag;
56
- private readonly requester?;
57
- private readonly grantedPaths?;
58
- private static readonly MAX_BINARY_SIZE;
59
- constructor(autoApprovedDirs: string[], onFlag: (file: FlaggedFileIn) => void, requester?: PRBEInteractionRequester, grantedPaths?: Set<string>);
60
- get declaration(): PRBEToolDeclaration;
61
- execute(args: Record<string, unknown>): Promise<string>;
62
- }
63
- //# sourceMappingURL=filesystem.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../../src/tools/filesystem.ts"],"names":[],"mappings":"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"}
@@ -1,573 +0,0 @@
1
- "use strict";
2
- /**
3
- * tools/filesystem.ts — Built-in filesystem tools
4
- *
5
- * Implements: client_list_directory, client_read_file, client_search_content,
6
- * client_find_files, client_flag_file
7
- *
8
- * Mirrors PRBEAgentTools.swift filesystem tool implementations.
9
- */
10
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
11
- if (k2 === undefined) k2 = k;
12
- var desc = Object.getOwnPropertyDescriptor(m, k);
13
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
14
- desc = { enumerable: true, get: function() { return m[k]; } };
15
- }
16
- Object.defineProperty(o, k2, desc);
17
- }) : (function(o, m, k, k2) {
18
- if (k2 === undefined) k2 = k;
19
- o[k2] = m[k];
20
- }));
21
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
22
- Object.defineProperty(o, "default", { enumerable: true, value: v });
23
- }) : function(o, v) {
24
- o["default"] = v;
25
- });
26
- var __importStar = (this && this.__importStar) || (function () {
27
- var ownKeys = function(o) {
28
- ownKeys = Object.getOwnPropertyNames || function (o) {
29
- var ar = [];
30
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
31
- return ar;
32
- };
33
- return ownKeys(o);
34
- };
35
- return function (mod) {
36
- if (mod && mod.__esModule) return mod;
37
- var result = {};
38
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
39
- __setModuleDefault(result, mod);
40
- return result;
41
- };
42
- })();
43
- Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.FlagFileTool = exports.FindFilesTool = exports.SearchContentTool = exports.ReadFileTool = exports.ListDirectoryTool = void 0;
45
- const fs = __importStar(require("fs"));
46
- const path = __importStar(require("path"));
47
- const models_1 = require("../models");
48
- const index_1 = require("./index");
49
- /** Resolve a path using access request if available, else basic validation. Returns [resolved, error]. */
50
- async function resolvePath(pathStr, autoApprovedDirs, requester, grantedPaths) {
51
- if (requester && grantedPaths) {
52
- const result = await (0, index_1.resolveWithAccessRequest)(pathStr, autoApprovedDirs, grantedPaths, requester);
53
- if (result && "error" in result)
54
- return [null, result.error];
55
- if (result && "path" in result)
56
- return [result.path, null];
57
- }
58
- const resolved = (0, index_1.resolveAndValidate)(pathStr, autoApprovedDirs);
59
- return [resolved, resolved ? null : "path is outside auto-approved directories"];
60
- }
61
- // ---------------------------------------------------------------------------
62
- // ListDirectoryTool
63
- // ---------------------------------------------------------------------------
64
- class ListDirectoryTool {
65
- autoApprovedDirs;
66
- requester;
67
- grantedPaths;
68
- constructor(autoApprovedDirs, requester, grantedPaths) {
69
- this.autoApprovedDirs = autoApprovedDirs;
70
- this.requester = requester;
71
- this.grantedPaths = grantedPaths;
72
- }
73
- get declaration() {
74
- return {
75
- name: models_1.ToolName.CLIENT_LIST_DIRECTORY,
76
- description: "List directory contents",
77
- parameters: [
78
- { name: "path", type: models_1.ToolParamType.STRING, description: "Directory path", required: true },
79
- { name: "recursive", type: models_1.ToolParamType.BOOLEAN, description: "List recursively", required: false },
80
- { name: "max_depth", type: models_1.ToolParamType.INTEGER, description: "Max depth (default 3)", required: false },
81
- ],
82
- };
83
- }
84
- async execute(args) {
85
- const pathStr = args["path"];
86
- if (!pathStr)
87
- return "Error: 'path' parameter is required";
88
- const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);
89
- if (!resolved)
90
- return `Error: ${resolveErr}`;
91
- try {
92
- const stat = fs.statSync(resolved);
93
- if (!stat.isDirectory())
94
- return `Error: '${pathStr}' is not a directory`;
95
- }
96
- catch {
97
- return `Error: '${pathStr}' does not exist or is not accessible`;
98
- }
99
- const recursive = args["recursive"] === true;
100
- const maxDepth = typeof args["max_depth"] === "number" ? args["max_depth"] : 3;
101
- const lines = [];
102
- this.listDir(resolved, 0, recursive ? maxDepth : 1, lines);
103
- if (lines.length >= ListDirectoryTool.MAX_ENTRIES) {
104
- lines.push(`\n(truncated at ${ListDirectoryTool.MAX_ENTRIES} entries — use a more specific path)`);
105
- }
106
- return lines.join("\n") || "(empty directory)";
107
- }
108
- static MAX_ENTRIES = 1000;
109
- listDir(dirPath, depth, maxDepth, lines) {
110
- if (depth >= maxDepth)
111
- return;
112
- if (lines.length >= ListDirectoryTool.MAX_ENTRIES)
113
- return;
114
- const indent = " ".repeat(depth);
115
- let entries;
116
- try {
117
- entries = fs.readdirSync(dirPath, { withFileTypes: true });
118
- }
119
- catch {
120
- lines.push(`${indent}(access denied)`);
121
- return;
122
- }
123
- // Sort entries alphabetically, skip hidden files
124
- const sorted = entries
125
- .filter((e) => !e.name.startsWith("."))
126
- .sort((a, b) => a.name.localeCompare(b.name));
127
- for (const entry of sorted) {
128
- const fullPath = path.join(dirPath, entry.name);
129
- if (entry.isDirectory()) {
130
- lines.push(`${indent}${entry.name}/`);
131
- this.listDir(fullPath, depth + 1, maxDepth, lines);
132
- }
133
- else {
134
- try {
135
- const stat = fs.statSync(fullPath);
136
- lines.push(`${indent}${entry.name} (${(0, index_1.humanReadableSize)(stat.size)})`);
137
- }
138
- catch {
139
- lines.push(`${indent}${entry.name} (unknown size)`);
140
- }
141
- }
142
- }
143
- }
144
- }
145
- exports.ListDirectoryTool = ListDirectoryTool;
146
- // ---------------------------------------------------------------------------
147
- // ReadFileTool
148
- // ---------------------------------------------------------------------------
149
- class ReadFileTool {
150
- autoApprovedDirs;
151
- requester;
152
- grantedPaths;
153
- constructor(autoApprovedDirs, requester, grantedPaths) {
154
- this.autoApprovedDirs = autoApprovedDirs;
155
- this.requester = requester;
156
- this.grantedPaths = grantedPaths;
157
- }
158
- get declaration() {
159
- return {
160
- name: models_1.ToolName.CLIENT_READ_FILE,
161
- description: "Read file contents",
162
- parameters: [
163
- { name: "path", type: models_1.ToolParamType.STRING, description: "File path", required: true },
164
- { name: "offset", type: models_1.ToolParamType.INTEGER, description: "Line offset", required: false },
165
- { name: "limit", type: models_1.ToolParamType.INTEGER, description: "Max lines (default 200)", required: false },
166
- ],
167
- };
168
- }
169
- async execute(args) {
170
- const pathStr = args["path"];
171
- if (!pathStr)
172
- return "Error: 'path' parameter is required";
173
- const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);
174
- if (!resolved)
175
- return `Error: ${resolveErr}`;
176
- let content;
177
- try {
178
- content = fs.readFileSync(resolved, "utf-8");
179
- }
180
- catch {
181
- return `Error: could not read file at '${pathStr}'`;
182
- }
183
- const allLines = content.split(/\r?\n/);
184
- const totalLines = allLines.length;
185
- const limit = typeof args["limit"] === "number" ? args["limit"] : 200;
186
- const rawOffset = typeof args["offset"] === "number" ? args["offset"] : 0;
187
- let startIndex;
188
- if (rawOffset < 0) {
189
- startIndex = Math.max(0, totalLines + rawOffset);
190
- }
191
- else {
192
- startIndex = rawOffset;
193
- }
194
- const endIndex = Math.min(startIndex + limit, totalLines);
195
- if (startIndex >= totalLines) {
196
- return `File has ${totalLines} lines; offset ${rawOffset} is out of range.`;
197
- }
198
- let stat;
199
- try {
200
- stat = fs.statSync(resolved);
201
- }
202
- catch {
203
- stat = { size: 0 };
204
- }
205
- const sizeStr = (0, index_1.humanReadableSize)(stat.size);
206
- let result = `File: ${pathStr} (${totalLines} lines, ${sizeStr}, showing ${startIndex + 1}-${endIndex})\n`;
207
- for (let i = startIndex; i < endIndex; i++) {
208
- const lineNum = String(i + 1).padStart(4, " ");
209
- result += `${lineNum} | ${allLines[i]}\n`;
210
- }
211
- return result;
212
- }
213
- }
214
- exports.ReadFileTool = ReadFileTool;
215
- // ---------------------------------------------------------------------------
216
- // SearchContentTool
217
- // ---------------------------------------------------------------------------
218
- class SearchContentTool {
219
- autoApprovedDirs;
220
- requester;
221
- grantedPaths;
222
- constructor(autoApprovedDirs, requester, grantedPaths) {
223
- this.autoApprovedDirs = autoApprovedDirs;
224
- this.requester = requester;
225
- this.grantedPaths = grantedPaths;
226
- }
227
- get declaration() {
228
- return {
229
- name: models_1.ToolName.CLIENT_SEARCH_CONTENT,
230
- description: "Search file contents",
231
- parameters: [
232
- { name: "pattern", type: models_1.ToolParamType.STRING, description: "Regex pattern", required: true },
233
- { name: "path", type: models_1.ToolParamType.STRING, description: "File or directory to search", required: true },
234
- { name: "context_lines", type: models_1.ToolParamType.INTEGER, description: "Context lines (default 2)", required: false },
235
- { name: "max_results", type: models_1.ToolParamType.INTEGER, description: "Max results (default 50)", required: false },
236
- ],
237
- };
238
- }
239
- async execute(args) {
240
- const pattern = args["pattern"];
241
- if (!pattern)
242
- return "Error: 'pattern' parameter is required";
243
- const pathStr = args["path"];
244
- if (!pathStr)
245
- return "Error: 'path' parameter is required";
246
- const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);
247
- if (!resolved)
248
- return `Error: ${resolveErr}`;
249
- const contextLines = typeof args["context_lines"] === "number" ? args["context_lines"] : 2;
250
- const maxResults = typeof args["max_results"] === "number" ? args["max_results"] : 50;
251
- let regex;
252
- try {
253
- regex = new RegExp(pattern);
254
- }
255
- catch {
256
- return `Error: invalid regex pattern '${pattern}'`;
257
- }
258
- // Collect file paths to search
259
- const fileURLs = [];
260
- let isDirectory = false;
261
- try {
262
- const stat = fs.statSync(resolved);
263
- if (stat.isDirectory()) {
264
- isDirectory = true;
265
- this.collectFiles(resolved, fileURLs);
266
- }
267
- else {
268
- fileURLs.push(resolved);
269
- }
270
- }
271
- catch {
272
- return `Error: could not access '${pathStr}'`;
273
- }
274
- const results = [];
275
- for (const filePath of fileURLs) {
276
- if (results.length >= maxResults)
277
- break;
278
- let content;
279
- try {
280
- content = fs.readFileSync(filePath, "utf-8");
281
- }
282
- catch {
283
- continue;
284
- }
285
- const lines = content.split(/\r?\n/);
286
- const relativePath = isDirectory
287
- ? path.relative(resolved, filePath)
288
- : path.basename(filePath);
289
- for (let idx = 0; idx < lines.length; idx++) {
290
- if (results.length >= maxResults)
291
- break;
292
- if (!regex.test(lines[idx]))
293
- continue;
294
- let snippet;
295
- if (contextLines > 0) {
296
- const start = Math.max(0, idx - contextLines);
297
- const end = Math.min(lines.length - 1, idx + contextLines);
298
- snippet = "";
299
- for (let ci = start; ci <= end; ci++) {
300
- const marker = ci === idx ? ">" : " ";
301
- snippet += `${relativePath}:${ci + 1}:${marker} ${lines[ci]}\n`;
302
- }
303
- }
304
- else {
305
- snippet = `${relativePath}:${idx + 1}: ${lines[idx]}`;
306
- }
307
- results.push(snippet);
308
- }
309
- }
310
- if (results.length === 0) {
311
- return `No matches found for '${pattern}' in '${pathStr}'`;
312
- }
313
- return `Found ${results.length} match(es):\n\n${results.join("\n---\n")}`;
314
- }
315
- collectFiles(dirPath, fileURLs) {
316
- let entries;
317
- try {
318
- entries = fs.readdirSync(dirPath, { withFileTypes: true });
319
- }
320
- catch {
321
- return;
322
- }
323
- for (const entry of entries) {
324
- if (entry.name.startsWith("."))
325
- continue;
326
- const fullPath = path.join(dirPath, entry.name);
327
- if (entry.isDirectory()) {
328
- this.collectFiles(fullPath, fileURLs);
329
- }
330
- else if (entry.isFile()) {
331
- fileURLs.push(fullPath);
332
- }
333
- }
334
- }
335
- }
336
- exports.SearchContentTool = SearchContentTool;
337
- // ---------------------------------------------------------------------------
338
- // FindFilesTool
339
- // ---------------------------------------------------------------------------
340
- class FindFilesTool {
341
- autoApprovedDirs;
342
- requester;
343
- grantedPaths;
344
- constructor(autoApprovedDirs, requester, grantedPaths) {
345
- this.autoApprovedDirs = autoApprovedDirs;
346
- this.requester = requester;
347
- this.grantedPaths = grantedPaths;
348
- }
349
- get declaration() {
350
- return {
351
- name: models_1.ToolName.CLIENT_FIND_FILES,
352
- description: "Find files by name",
353
- parameters: [
354
- { name: "pattern", type: models_1.ToolParamType.STRING, description: "Glob pattern", required: true },
355
- { name: "path", type: models_1.ToolParamType.STRING, description: "Directory to search", required: true },
356
- { name: "max_results", type: models_1.ToolParamType.INTEGER, description: "Max results (default 50)", required: false },
357
- ],
358
- };
359
- }
360
- async execute(args) {
361
- const pattern = args["pattern"];
362
- if (!pattern)
363
- return "Error: 'pattern' parameter is required";
364
- const pathStr = args["path"];
365
- if (!pathStr)
366
- return "Error: 'path' parameter is required";
367
- const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);
368
- if (!resolved)
369
- return `Error: ${resolveErr}`;
370
- const maxResults = typeof args["max_results"] === "number" ? args["max_results"] : 50;
371
- const matches = [];
372
- this.walkAndMatch(resolved, pattern, matches);
373
- // Sort newest-first
374
- matches.sort((a, b) => b.modified.getTime() - a.modified.getTime());
375
- const limited = matches.slice(0, maxResults);
376
- if (limited.length === 0) {
377
- return `No files matching '${pattern}' found in '${pathStr}'`;
378
- }
379
- let result = `Found ${matches.length} file(s) matching '${pattern}':\n\n`;
380
- for (const m of limited) {
381
- const sizeStr = (0, index_1.humanReadableSize)(m.size);
382
- const dateStr = m.modified.toISOString();
383
- result += `${m.path} (${sizeStr}, ${dateStr})\n`;
384
- }
385
- return result;
386
- }
387
- walkAndMatch(dirPath, pattern, matches) {
388
- let entries;
389
- try {
390
- entries = fs.readdirSync(dirPath, { withFileTypes: true });
391
- }
392
- catch {
393
- return;
394
- }
395
- for (const entry of entries) {
396
- if (entry.name.startsWith("."))
397
- continue;
398
- const fullPath = path.join(dirPath, entry.name);
399
- if (entry.isDirectory()) {
400
- this.walkAndMatch(fullPath, pattern, matches);
401
- }
402
- else if (entry.isFile()) {
403
- if (this.globMatch(entry.name, pattern)) {
404
- try {
405
- const stat = fs.statSync(fullPath);
406
- matches.push({
407
- path: fullPath,
408
- size: stat.size,
409
- modified: stat.mtime,
410
- });
411
- }
412
- catch {
413
- // Skip files we can't stat
414
- }
415
- }
416
- }
417
- }
418
- }
419
- /**
420
- * Simple glob matching: supports *, ?, and character classes [...].
421
- * Converts glob to regex and tests against the filename.
422
- */
423
- globMatch(filename, pattern) {
424
- // Convert glob pattern to regex
425
- let regexStr = "^";
426
- for (let i = 0; i < pattern.length; i++) {
427
- const c = pattern[i];
428
- switch (c) {
429
- case "*":
430
- regexStr += ".*";
431
- break;
432
- case "?":
433
- regexStr += ".";
434
- break;
435
- case "[":
436
- // Find closing bracket
437
- const closeBracket = pattern.indexOf("]", i + 1);
438
- if (closeBracket === -1) {
439
- regexStr += "\\[";
440
- }
441
- else {
442
- regexStr += pattern.substring(i, closeBracket + 1);
443
- i = closeBracket;
444
- }
445
- break;
446
- case ".":
447
- case "(":
448
- case ")":
449
- case "+":
450
- case "^":
451
- case "$":
452
- case "|":
453
- case "{":
454
- case "}":
455
- case "\\":
456
- regexStr += `\\${c}`;
457
- break;
458
- default:
459
- regexStr += c;
460
- }
461
- }
462
- regexStr += "$";
463
- try {
464
- return new RegExp(regexStr).test(filename);
465
- }
466
- catch {
467
- return false;
468
- }
469
- }
470
- }
471
- exports.FindFilesTool = FindFilesTool;
472
- // ---------------------------------------------------------------------------
473
- // FlagFileTool
474
- // ---------------------------------------------------------------------------
475
- class FlagFileTool {
476
- autoApprovedDirs;
477
- onFlag;
478
- requester;
479
- grantedPaths;
480
- static MAX_BINARY_SIZE = 100 * 1024 * 1024; // 100MB
481
- constructor(autoApprovedDirs, onFlag, requester, grantedPaths) {
482
- this.autoApprovedDirs = autoApprovedDirs;
483
- this.onFlag = onFlag;
484
- this.requester = requester;
485
- this.grantedPaths = grantedPaths;
486
- }
487
- get declaration() {
488
- return {
489
- name: models_1.ToolName.CLIENT_FLAG_FILE,
490
- description: "Flag a file (or part of a text file) as evidence. For large text files, use offset and limit to flag only the relevant section. Binary files are flagged in full (up to 100MB).",
491
- parameters: [
492
- { name: "path", type: models_1.ToolParamType.STRING, description: "File path", required: true },
493
- { name: "reason", type: models_1.ToolParamType.STRING, description: "Reason for flagging", required: true },
494
- { name: "offset", type: models_1.ToolParamType.INTEGER, description: "Starting line number (1-based, text files only). Negative = from end.", required: false },
495
- { name: "limit", type: models_1.ToolParamType.INTEGER, description: "Max number of lines to include (text files only).", required: false },
496
- ],
497
- };
498
- }
499
- async execute(args) {
500
- const pathStr = args["path"];
501
- if (!pathStr)
502
- return "Error: 'path' parameter is required";
503
- const reason = args["reason"];
504
- if (!reason)
505
- return "Error: 'reason' parameter is required";
506
- const [resolved, resolveErr] = await resolvePath(pathStr, this.autoApprovedDirs, this.requester, this.grantedPaths);
507
- if (!resolved)
508
- return `Error: ${resolveErr}`;
509
- if (!fs.existsSync(resolved)) {
510
- return `Error: file does not exist at '${pathStr}'`;
511
- }
512
- const offset = typeof args["offset"] === "number" ? args["offset"] : undefined;
513
- const limit = typeof args["limit"] === "number" ? args["limit"] : undefined;
514
- // Try reading as text first
515
- let textContent = null;
516
- try {
517
- textContent = fs.readFileSync(resolved, "utf-8");
518
- }
519
- catch {
520
- // Not readable as text
521
- }
522
- if (textContent !== null) {
523
- let content = textContent;
524
- if (offset !== undefined || limit !== undefined) {
525
- let lines = content.split(/\r?\n/);
526
- const totalLines = lines.length;
527
- let startIdx = 0;
528
- if (offset !== undefined) {
529
- startIdx = offset < 0 ? Math.max(0, totalLines + offset) : Math.max(0, offset - 1);
530
- }
531
- lines = lines.slice(startIdx);
532
- if (limit !== undefined && limit > 0) {
533
- lines = lines.slice(0, limit);
534
- }
535
- const rangeDesc = `lines ${startIdx + 1}-${startIdx + lines.length} of ${totalLines}`;
536
- content = `[${rangeDesc}]\n${lines.join("\n")}`;
537
- }
538
- const redacted = (0, models_1.redactPII)(content);
539
- this.onFlag({
540
- originalPath: resolved,
541
- reason,
542
- data: Buffer.from(redacted, "utf-8"),
543
- isText: true,
544
- });
545
- const sizeDesc = offset !== undefined || limit !== undefined ? " (partial)" : "";
546
- return `Flagged '${pathStr}'${sizeDesc} — reason: ${reason}`;
547
- }
548
- // Binary file — flag in full, no partial support
549
- if (offset !== undefined || limit !== undefined) {
550
- return "Error: offset/limit not supported for binary files. Flag the full file instead.";
551
- }
552
- let data;
553
- try {
554
- data = fs.readFileSync(resolved);
555
- }
556
- catch {
557
- return `Error: could not read file at '${pathStr}'`;
558
- }
559
- if (data.length > FlagFileTool.MAX_BINARY_SIZE) {
560
- const sizeMB = Math.floor(data.length / (1024 * 1024));
561
- return `Error: file is ${sizeMB}MB — exceeds 100MB limit`;
562
- }
563
- this.onFlag({
564
- originalPath: resolved,
565
- reason,
566
- data,
567
- isText: false,
568
- });
569
- return `Flagged '${pathStr}' (binary, ${data.length} bytes) — reason: ${reason}`;
570
- }
571
- }
572
- exports.FlagFileTool = FlagFileTool;
573
- //# sourceMappingURL=filesystem.js.map