@xandout/libra-harness 0.1.12 → 0.1.14

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 (53) hide show
  1. package/dist/agent.d.ts.map +1 -1
  2. package/dist/agent.js +48 -11
  3. package/dist/agent.js.map +1 -1
  4. package/dist/extras/extensions/code-tools/extension.d.ts +83 -0
  5. package/dist/extras/extensions/code-tools/extension.d.ts.map +1 -0
  6. package/dist/extras/extensions/code-tools/extension.js +93 -0
  7. package/dist/extras/extensions/code-tools/extension.js.map +1 -0
  8. package/dist/extras/extensions/code-tools/extension.json +7 -0
  9. package/dist/extras/extensions/code-tools/extension.test.d.ts +2 -0
  10. package/dist/extras/extensions/code-tools/extension.test.d.ts.map +1 -0
  11. package/dist/extras/extensions/code-tools/extension.test.js +656 -0
  12. package/dist/extras/extensions/code-tools/extension.test.js.map +1 -0
  13. package/dist/extras/extensions/code-tools/index.d.ts +3 -0
  14. package/dist/extras/extensions/code-tools/index.d.ts.map +1 -0
  15. package/dist/extras/extensions/code-tools/index.js +2 -0
  16. package/dist/extras/extensions/code-tools/index.js.map +1 -0
  17. package/dist/extras/extensions/code-tools/tools/code-search.d.ts +12 -0
  18. package/dist/extras/extensions/code-tools/tools/code-search.d.ts.map +1 -0
  19. package/dist/extras/extensions/code-tools/tools/code-search.js +86 -0
  20. package/dist/extras/extensions/code-tools/tools/code-search.js.map +1 -0
  21. package/dist/extras/extensions/code-tools/tools/find.d.ts +3 -0
  22. package/dist/extras/extensions/code-tools/tools/find.d.ts.map +1 -0
  23. package/dist/extras/extensions/code-tools/tools/find.js +160 -0
  24. package/dist/extras/extensions/code-tools/tools/find.js.map +1 -0
  25. package/dist/extras/extensions/code-tools/tools/grep.d.ts +3 -0
  26. package/dist/extras/extensions/code-tools/tools/grep.d.ts.map +1 -0
  27. package/dist/extras/extensions/code-tools/tools/grep.js +306 -0
  28. package/dist/extras/extensions/code-tools/tools/grep.js.map +1 -0
  29. package/dist/extras/extensions/code-tools/tools/read.d.ts +3 -0
  30. package/dist/extras/extensions/code-tools/tools/read.d.ts.map +1 -0
  31. package/dist/extras/extensions/code-tools/tools/read.js +97 -0
  32. package/dist/extras/extensions/code-tools/tools/read.js.map +1 -0
  33. package/dist/extras/extensions/code-tools/tools/shared.d.ts +14 -0
  34. package/dist/extras/extensions/code-tools/tools/shared.d.ts.map +1 -0
  35. package/dist/extras/extensions/code-tools/tools/shared.js +53 -0
  36. package/dist/extras/extensions/code-tools/tools/shared.js.map +1 -0
  37. package/dist/extras/extensions/code-tools/tools/shell.d.ts +49 -0
  38. package/dist/extras/extensions/code-tools/tools/shell.d.ts.map +1 -0
  39. package/dist/extras/extensions/code-tools/tools/shell.js +623 -0
  40. package/dist/extras/extensions/code-tools/tools/shell.js.map +1 -0
  41. package/dist/extras/extensions/code-tools/tools/todo.d.ts +24 -0
  42. package/dist/extras/extensions/code-tools/tools/todo.d.ts.map +1 -0
  43. package/dist/extras/extensions/code-tools/tools/todo.js +131 -0
  44. package/dist/extras/extensions/code-tools/tools/todo.js.map +1 -0
  45. package/dist/extras/extensions/code-tools/tools/write.d.ts +4 -0
  46. package/dist/extras/extensions/code-tools/tools/write.d.ts.map +1 -0
  47. package/dist/extras/extensions/code-tools/tools/write.js +179 -0
  48. package/dist/extras/extensions/code-tools/tools/write.js.map +1 -0
  49. package/dist/extras/extensions/disk-session/extension.d.ts +5 -0
  50. package/dist/extras/extensions/disk-session/extension.d.ts.map +1 -1
  51. package/dist/extras/extensions/disk-session/extension.js +148 -20
  52. package/dist/extras/extensions/disk-session/extension.js.map +1 -1
  53. package/package.json +5 -1
@@ -0,0 +1,306 @@
1
+ import { readdirSync, readFileSync, existsSync, statSync } from 'node:fs';
2
+ import { join, relative } from 'node:path';
3
+ import { makeToolName } from './shared.js';
4
+ // ── Grep implementation ──────────────────────────────────────────────
5
+ // Pure-JS content search. Supports:
6
+ // - Rust regex syntax (via JS RegExp, with look-around not supported)
7
+ // - Glob pattern filtering (e.g. "*.ts", "src/**/*.py")
8
+ // - Output modes: content, files_with_matches, count
9
+ // - Context lines before/after matches
10
+ // - Case-insensitive matching
11
+ // - Max file size (skips files > 4MB, matching ripgrep behavior)
12
+ // - Max results limit
13
+ const MAX_FILE_SIZE = 4 * 1024 * 1024; // 4MB
14
+ function isNoiseDir(name) {
15
+ return name === 'node_modules' || name === '.git' || name === 'dist' || name === '.next' || name === 'coverage';
16
+ }
17
+ // Simple glob to regex (same minimal implementation as find.ts)
18
+ function globToRegex(pattern) {
19
+ let i = 0;
20
+ let regex = '';
21
+ while (i < pattern.length) {
22
+ const c = pattern[i];
23
+ if (c === '*' && pattern[i + 1] === '*') {
24
+ regex += '.*';
25
+ i += 2;
26
+ if (pattern[i] === '/')
27
+ i++;
28
+ }
29
+ else if (c === '*') {
30
+ regex += '[^/]*';
31
+ i++;
32
+ }
33
+ else if (c === '?') {
34
+ regex += '[^/]';
35
+ i++;
36
+ }
37
+ else if (c === '{') {
38
+ const end = pattern.indexOf('}', i);
39
+ if (end === -1) {
40
+ regex += '\\{';
41
+ i++;
42
+ }
43
+ else {
44
+ const options = pattern.slice(i + 1, end).split(',').map((s) => escapeRegex(s));
45
+ regex += `(?:${options.join('|')})`;
46
+ i = end + 1;
47
+ }
48
+ }
49
+ else if (c === '.') {
50
+ regex += '\\.';
51
+ i++;
52
+ }
53
+ else if ('+()|^$\\'.includes(c)) {
54
+ regex += '\\' + c;
55
+ i++;
56
+ }
57
+ else {
58
+ regex += c;
59
+ i++;
60
+ }
61
+ }
62
+ return new RegExp(`^${regex}$`);
63
+ }
64
+ function escapeRegex(s) {
65
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
66
+ }
67
+ function shouldSearchFile(filePath, globPattern) {
68
+ if (globPattern) {
69
+ const base = filePath.split('/').pop() ?? filePath;
70
+ // Try matching against full relative path and just the filename
71
+ if (!globPattern.test(filePath) && !globPattern.test(base))
72
+ return false;
73
+ }
74
+ try {
75
+ const stat = statSync(filePath);
76
+ if (stat.size > MAX_FILE_SIZE)
77
+ return false;
78
+ return true;
79
+ }
80
+ catch {
81
+ return false;
82
+ }
83
+ }
84
+ function searchFile(filePath, regex) {
85
+ const matches = [];
86
+ let content;
87
+ try {
88
+ content = readFileSync(filePath, 'utf-8');
89
+ }
90
+ catch {
91
+ return { file: filePath, matches: [], count: 0 };
92
+ }
93
+ const lines = content.split('\n');
94
+ for (let i = 0; i < lines.length; i++) {
95
+ // Reset lastIndex — the regex has the global flag, so test() advances it.
96
+ regex.lastIndex = 0;
97
+ if (regex.test(lines[i])) {
98
+ matches.push({ file: filePath, lineNum: i + 1, line: lines[i] });
99
+ }
100
+ }
101
+ return { file: filePath, matches, count: matches.length };
102
+ }
103
+ function walkDir(dir, globPattern, baseDir) {
104
+ const files = [];
105
+ function walk(d) {
106
+ let entries;
107
+ try {
108
+ entries = readdirSync(d, { withFileTypes: true });
109
+ }
110
+ catch {
111
+ return;
112
+ }
113
+ for (const entry of entries) {
114
+ if (entry.isDirectory() && isNoiseDir(entry.name))
115
+ continue;
116
+ const fullPath = join(d, entry.name);
117
+ if (entry.isDirectory()) {
118
+ walk(fullPath);
119
+ }
120
+ else {
121
+ const relPath = relative(baseDir, fullPath);
122
+ if (shouldSearchFile(relPath, globPattern) || shouldSearchFile(fullPath, globPattern)) {
123
+ files.push(fullPath);
124
+ }
125
+ }
126
+ }
127
+ }
128
+ walk(dir);
129
+ return files;
130
+ }
131
+ // ── grep tool ────────────────────────────────────────────────────────
132
+ export const grepTool = (cfg) => ({
133
+ name: makeToolName(cfg.toolPrefix, 'grep'),
134
+ description: 'Search file contents using regex. Uses JS RegExp syntax (no look-ahead/look-behind or backreferences). ' +
135
+ 'Files larger than 4MB are skipped. ' +
136
+ 'Output modes: "content" (matching lines with line numbers), "files_with_matches" (just file paths), "count" (match counts per file). ' +
137
+ 'Use context_lines to show lines before/after each match. ' +
138
+ 'Automatically skips node_modules, .git, dist, coverage directories.',
139
+ parameters: {
140
+ type: 'object',
141
+ properties: {
142
+ pattern: {
143
+ type: 'string',
144
+ description: 'Regular expression pattern to search for (JS RegExp syntax).',
145
+ },
146
+ path: {
147
+ type: 'string',
148
+ description: 'Directory or file to search in. Default: current working directory.',
149
+ },
150
+ glob_pattern: {
151
+ type: 'string',
152
+ description: 'Glob pattern to filter files (e.g. "*.ts", "src/**/*.py"). Default: search all files.',
153
+ },
154
+ output_mode: {
155
+ type: 'string',
156
+ enum: ['content', 'files_with_matches', 'count'],
157
+ description: 'How to format results. Default: "content".',
158
+ },
159
+ context_lines: {
160
+ type: 'integer',
161
+ description: 'Number of lines to show before and after each match. Default: 0.',
162
+ },
163
+ case_insensitive: {
164
+ type: 'boolean',
165
+ description: 'If true, perform case-insensitive matching. Default: false.',
166
+ },
167
+ max_results: {
168
+ type: 'integer',
169
+ description: 'Maximum number of matching lines to return. Default: 100.',
170
+ },
171
+ },
172
+ required: ['pattern'],
173
+ },
174
+ async execute(args) {
175
+ const pattern = String(args.pattern ?? '');
176
+ if (!pattern) {
177
+ return { toolCallId: '', content: 'Error: pattern is required' };
178
+ }
179
+ const searchPath = String(args.path ?? process.cwd());
180
+ const outputMode = String(args.output_mode ?? 'content');
181
+ const contextLines = Math.max(0, Number(args.context_lines ?? 0));
182
+ const caseInsensitive = args.case_insensitive === true;
183
+ const maxResults = Math.min(Math.max(1, Number(args.max_results ?? 100)), 10000);
184
+ const globPattern = args.glob_pattern ? String(args.glob_pattern) : undefined;
185
+ // Compile the regex.
186
+ let regex;
187
+ try {
188
+ regex = new RegExp(pattern, caseInsensitive ? 'gi' : 'g');
189
+ }
190
+ catch (err) {
191
+ return {
192
+ toolCallId: '',
193
+ content: `Error: invalid regex pattern: ${err instanceof Error ? err.message : String(err)}`,
194
+ };
195
+ }
196
+ // Compile glob filter if provided.
197
+ let globRegex;
198
+ if (globPattern) {
199
+ try {
200
+ globRegex = globToRegex(globPattern);
201
+ }
202
+ catch (err) {
203
+ return {
204
+ toolCallId: '',
205
+ content: `Error: invalid glob_pattern: ${err instanceof Error ? err.message : String(err)}`,
206
+ };
207
+ }
208
+ }
209
+ // Determine search scope — single file or directory.
210
+ if (!existsSync(searchPath)) {
211
+ return { toolCallId: '', content: `Path not found: ${searchPath}` };
212
+ }
213
+ const stat = statSync(searchPath);
214
+ let files;
215
+ if (stat.isFile()) {
216
+ files = [searchPath];
217
+ }
218
+ else if (stat.isDirectory()) {
219
+ files = walkDir(searchPath, globRegex, searchPath);
220
+ }
221
+ else {
222
+ return { toolCallId: '', content: `Path is not a file or directory: ${searchPath}` };
223
+ }
224
+ // Search all files.
225
+ const results = [];
226
+ let totalMatches = 0;
227
+ for (const file of files) {
228
+ // Reset regex lastIndex between files (it has the global flag).
229
+ regex.lastIndex = 0;
230
+ const result = searchFile(file, regex);
231
+ if (result.count > 0) {
232
+ results.push(result);
233
+ totalMatches += result.count;
234
+ }
235
+ }
236
+ if (totalMatches === 0) {
237
+ return { toolCallId: '', content: `No matches found for "${pattern}" in ${searchPath}` };
238
+ }
239
+ // Format output based on mode.
240
+ const baseDir = stat.isDirectory() ? searchPath : '';
241
+ if (outputMode === 'files_with_matches') {
242
+ const fileList = results.map((r) => relative(baseDir, r.file) || r.file);
243
+ const truncated = fileList.length > maxResults;
244
+ const displayed = fileList.slice(0, maxResults);
245
+ return {
246
+ toolCallId: '',
247
+ content: `${displayed.join('\n')}${truncated ? `\n\n[showing first ${maxResults} of ${fileList.length} files]` : ''}`,
248
+ };
249
+ }
250
+ if (outputMode === 'count') {
251
+ const lines = results.map((r) => {
252
+ const rel = relative(baseDir, r.file) || r.file;
253
+ return `${rel}:${r.count}`;
254
+ });
255
+ return {
256
+ toolCallId: '',
257
+ content: `${lines.join('\n')}\n\nTotal: ${totalMatches} match${totalMatches === 1 ? '' : 'es'} in ${results.length} file${results.length === 1 ? '' : 's'}`,
258
+ };
259
+ }
260
+ // content mode — show matching lines with line numbers and context.
261
+ const allMatches = [];
262
+ for (const r of results) {
263
+ for (const m of r.matches) {
264
+ allMatches.push(m);
265
+ }
266
+ }
267
+ const truncated = allMatches.length > maxResults;
268
+ const displayed = allMatches.slice(0, maxResults);
269
+ // Read context lines for each match.
270
+ const outputLines = [];
271
+ const fileCache = new Map();
272
+ for (const m of displayed) {
273
+ if (contextLines > 0) {
274
+ let fileLines = fileCache.get(m.file);
275
+ if (!fileLines) {
276
+ try {
277
+ fileLines = readFileSync(m.file, 'utf-8').split('\n');
278
+ fileCache.set(m.file, fileLines);
279
+ }
280
+ catch {
281
+ fileLines = [];
282
+ }
283
+ }
284
+ const rel = relative(baseDir, m.file) || m.file;
285
+ const start = Math.max(0, m.lineNum - 1 - contextLines);
286
+ const end = Math.min(fileLines.length - 1, m.lineNum - 1 + contextLines);
287
+ for (let i = start; i <= end; i++) {
288
+ const prefix = i === m.lineNum - 1 ? '>' : ' ';
289
+ outputLines.push(`${rel}:${i + 1}:${prefix} ${fileLines[i]}`);
290
+ }
291
+ outputLines.push('');
292
+ }
293
+ else {
294
+ const rel = relative(baseDir, m.file) || m.file;
295
+ outputLines.push(`${rel}:${m.lineNum}: ${m.line}`);
296
+ }
297
+ }
298
+ const header = `Found ${totalMatches} match${totalMatches === 1 ? '' : 'es'} in ${results.length} file${results.length === 1 ? '' : 's'}:`;
299
+ const footer = truncated ? `\n\n[showing first ${maxResults} of ${totalMatches} matches]` : '';
300
+ return {
301
+ toolCallId: '',
302
+ content: `${header}\n${outputLines.join('\n')}${footer}`,
303
+ };
304
+ },
305
+ });
306
+ //# sourceMappingURL=grep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grep.js","sourceRoot":"","sources":["../../../../../src/extras/extensions/code-tools/tools/grep.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { type ToolFactory } from './shared.js';
2
+ export declare const readTool: ToolFactory;
3
+ //# sourceMappingURL=read.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../../../../src/extras/extensions/code-tools/tools/read.ts"],"names":[],"mappings":"AACA,OAAO,EAAgE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7G,eAAO,MAAM,QAAQ,EAAE,WA2GrB,CAAC"}
@@ -0,0 +1,97 @@
1
+ import { readFileSync, statSync, existsSync } from 'node:fs';
2
+ import { makeToolName, getReadSet, isTextFile, isImageFile, imageMime } from './shared.js';
3
+ export const readTool = (cfg) => ({
4
+ name: makeToolName(cfg.toolPrefix, 'read'),
5
+ description: 'Read a file from the local filesystem. Returns file contents with line numbers. ' +
6
+ 'Text files are returned as text; binary files as base64; images are returned as base64 data URLs. ' +
7
+ 'You MUST read a file before editing or overwriting it. ' +
8
+ 'Use absolute paths. For large files, use offset (1-based line number) and limit (line count) to read a portion.',
9
+ parameters: {
10
+ type: 'object',
11
+ properties: {
12
+ file_path: {
13
+ type: 'string',
14
+ description: 'The absolute path to the file to read.',
15
+ },
16
+ offset: {
17
+ type: 'integer',
18
+ description: 'The line number to start reading from (1-based). Default: 1.',
19
+ },
20
+ limit: {
21
+ type: 'integer',
22
+ description: 'Maximum number of lines to read. Default: 2000.',
23
+ },
24
+ },
25
+ required: ['file_path'],
26
+ },
27
+ async execute(args, ctx) {
28
+ const filePath = String(args.file_path ?? '');
29
+ if (!filePath) {
30
+ return { toolCallId: '', content: 'Error: file_path is required' };
31
+ }
32
+ if (!existsSync(filePath)) {
33
+ return { toolCallId: '', content: `File not found: ${filePath}` };
34
+ }
35
+ const stat = statSync(filePath);
36
+ if (stat.isDirectory()) {
37
+ return {
38
+ toolCallId: '',
39
+ content: `Path is a directory, not a file: ${filePath}. Use find_file_by_name or exec with ls to list directory contents.`,
40
+ };
41
+ }
42
+ if (stat.size > cfg.maxReadSize) {
43
+ return {
44
+ toolCallId: '',
45
+ content: `File is too large (${stat.size} bytes, max ${cfg.maxReadSize}). Use offset and limit to read a portion, or use exec with head/tail.`,
46
+ };
47
+ }
48
+ // Track that this file was read — edit and write require it.
49
+ getReadSet(ctx.metadata).add(filePath);
50
+ const buf = readFileSync(filePath);
51
+ // ── Image files: return as base64 data URL ──────────────────────
52
+ if (isImageFile(filePath)) {
53
+ const mime = imageMime(filePath);
54
+ const base64 = buf.toString('base64');
55
+ return {
56
+ toolCallId: '',
57
+ content: `File: ${filePath} (${stat.size}b, ${mime})\ndata:${mime};base64,${base64}`,
58
+ };
59
+ }
60
+ // ── Binary files: return as base64 ──────────────────────────────
61
+ if (!isTextFile(filePath)) {
62
+ const base64 = buf.toString('base64');
63
+ return {
64
+ toolCallId: '',
65
+ content: `File: ${filePath} (${stat.size}b, binary)\nbase64: ${base64}`,
66
+ };
67
+ }
68
+ // ── Text files: return with line numbers ────────────────────────
69
+ const text = buf.toString('utf-8');
70
+ const allLines = text.split('\n');
71
+ // Apply offset (1-based)
72
+ const offset = Math.max(1, Number(args.offset ?? 1));
73
+ const startIdx = offset - 1;
74
+ let lines = allLines.slice(startIdx);
75
+ // Apply limit
76
+ const limit = Math.min(Number(args.limit ?? cfg.maxReadLines), cfg.maxReadLines);
77
+ const truncated = lines.length > limit;
78
+ lines = lines.slice(0, limit);
79
+ // Format with line numbers, truncating long lines
80
+ const formatted = lines.map((line, i) => {
81
+ const lineNum = startIdx + i + 1;
82
+ const truncatedLine = line.length > cfg.maxLineLength
83
+ ? line.slice(0, cfg.maxLineLength) + ' [...truncated]'
84
+ : line;
85
+ return `${String(lineNum).padStart(6)}\t${truncatedLine}`;
86
+ }).join('\n');
87
+ const header = `File: ${filePath} (${stat.size}b)`;
88
+ const footer = truncated
89
+ ? `\n\n[showing lines ${offset}-${offset + limit - 1} of ${allLines.length} total]`
90
+ : '';
91
+ return {
92
+ toolCallId: '',
93
+ content: `${header}\n${formatted}${footer}`,
94
+ };
95
+ },
96
+ });
97
+ //# sourceMappingURL=read.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"read.js","sourceRoot":"","sources":["../../../../../src/extras/extensions/code-tools/tools/read.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Tool } from '../../../../tool.js';
2
+ export declare function makeToolName(prefix: string, name: string): string;
3
+ export declare function getReadSet(metadata: Record<string, unknown>): Set<string>;
4
+ export declare function isTextFile(path: string): boolean;
5
+ export declare function isImageFile(path: string): boolean;
6
+ export declare function imageMime(path: string): string;
7
+ export interface ResolvedConfig {
8
+ toolPrefix: string;
9
+ maxReadSize: number;
10
+ maxReadLines: number;
11
+ maxLineLength: number;
12
+ }
13
+ export type ToolFactory = (cfg: ResolvedConfig) => Tool;
14
+ //# sourceMappingURL=shared.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../../../src/extras/extensions/code-tools/tools/shared.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAGhD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjE;AAOD,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAOzE;AAaD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMhD;AAKD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAWD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAGD,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { extname, basename } from 'node:path';
2
+ // ── Tool naming helper ───────────────────────────────────────────────
3
+ export function makeToolName(prefix, name) {
4
+ return prefix ? `${prefix}_${name}` : name;
5
+ }
6
+ // ── Read tracking ────────────────────────────────────────────────────
7
+ // The edit and write tools require that a file was read first in the
8
+ // current turn. We track read paths per turn via the metadata bag.
9
+ const READ_KEY = '__codeToolsReadPaths';
10
+ export function getReadSet(metadata) {
11
+ let set = metadata[READ_KEY];
12
+ if (!set) {
13
+ set = new Set();
14
+ metadata[READ_KEY] = set;
15
+ }
16
+ return set;
17
+ }
18
+ // ── Text/binary detection ────────────────────────────────────────────
19
+ const TEXT_EXTENSIONS = new Set([
20
+ '.txt', '.csv', '.json', '.xml', '.yaml', '.yml', '.md', '.markdown',
21
+ '.js', '.ts', '.tsx', '.jsx', '.mjs', '.cjs', '.py', '.java', '.c',
22
+ '.cpp', '.h', '.hpp', '.go', '.rs', '.rb', '.php', '.sql', '.html',
23
+ '.htm', '.css', '.scss', '.less', '.sh', '.bash', '.zsh', '.ini',
24
+ '.conf', '.log', '.env', '.toml', '.graphql', '.gql', '.svg', '.srt',
25
+ '.vtt', '.properties', '.dockerfile', '.gitignore', '.editorconfig',
26
+ '.lock', '.map', '.d.ts', '.d.ts.map',
27
+ ]);
28
+ export function isTextFile(path) {
29
+ const ext = extname(path).toLowerCase();
30
+ if (TEXT_EXTENSIONS.has(ext))
31
+ return true;
32
+ const name = basename(path).toLowerCase();
33
+ if (['dockerfile', '.gitignore', '.editorconfig', '.env', '.npmrc'].includes(name))
34
+ return true;
35
+ return false;
36
+ }
37
+ // ── Image detection ──────────────────────────────────────────────────
38
+ const IMAGE_EXTENSIONS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.webp', '.bmp']);
39
+ export function isImageFile(path) {
40
+ return IMAGE_EXTENSIONS.has(extname(path).toLowerCase());
41
+ }
42
+ const MIME_MAP = {
43
+ '.png': 'image/png',
44
+ '.jpg': 'image/jpeg',
45
+ '.jpeg': 'image/jpeg',
46
+ '.gif': 'image/gif',
47
+ '.webp': 'image/webp',
48
+ '.bmp': 'image/bmp',
49
+ };
50
+ export function imageMime(path) {
51
+ return MIME_MAP[extname(path).toLowerCase()] ?? 'application/octet-stream';
52
+ }
53
+ //# sourceMappingURL=shared.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared.js","sourceRoot":"","sources":["../../../../../src/extras/extensions/code-tools/tools/shared.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG9C,wEAAwE;AACxE,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,IAAY;IACvD,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED,wEAAwE;AACxE,qEAAqE;AACrE,mEAAmE;AACnE,MAAM,QAAQ,GAAG,sBAAsB,CAAC;AAExC,MAAM,UAAU,UAAU,CAAC,QAAiC;IAC1D,IAAI,GAAG,GAAG,QAAQ,CAAC,QAAQ,CAA4B,CAAC;IACxD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC;QAChB,QAAQ,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;IAC3B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,wEAAwE;AACxE,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW;IACpE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI;IAClE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO;IAClE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM;IAChE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IACpE,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe;IACnE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW;CACtC,CAAC,CAAC;AAEH,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACxC,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,CAAC,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAChG,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wEAAwE;AACxE,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AAErF,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,QAAQ,GAA2B;IACvC,MAAM,EAAE,WAAW;IACnB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;CACpB,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,IAAI,0BAA0B,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ import type { Tool } from '../../../../tool.js';
3
+ export interface ShellEntry {
4
+ id: string;
5
+ process?: ChildProcess;
6
+ pid: number;
7
+ output: string;
8
+ done: boolean;
9
+ exitCode: number | null;
10
+ startedAt: number;
11
+ command: string;
12
+ cwd: string;
13
+ outputFile?: string;
14
+ inputFifo?: string;
15
+ detached: boolean;
16
+ readOffset?: number;
17
+ }
18
+ export declare class ShellRegistry {
19
+ private shells;
20
+ private counter;
21
+ private shellsDir;
22
+ constructor(shellsDir?: string);
23
+ private nextId;
24
+ private metaPath;
25
+ /**
26
+ * Create a foreground shell (pipes connected, parent waits).
27
+ * If background is true, the process is detached and output goes
28
+ * to a file. Metadata is persisted to disk so a future process
29
+ * can reconnect.
30
+ */
31
+ create(command: string, cwd: string, env: Record<string, string>, background: boolean): Promise<ShellEntry>;
32
+ /**
33
+ * Get a shell by ID. If it's not in the in-memory map, try to
34
+ * reconnect from persisted metadata on disk.
35
+ */
36
+ get(id: string): ShellEntry | undefined;
37
+ delete(id: string): boolean;
38
+ /** Kill all in-memory backgrounded shells. Called on extension close. */
39
+ close(): void;
40
+ }
41
+ export type ShellToolFactory = (cfg: {
42
+ toolPrefix: string;
43
+ registry: ShellRegistry;
44
+ }) => Tool;
45
+ export declare const execTool: ShellToolFactory;
46
+ export declare const getOutputTool: ShellToolFactory;
47
+ export declare const killShellTool: ShellToolFactory;
48
+ export declare const writeToProcessTool: ShellToolFactory;
49
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../../../../src/extras/extensions/code-tools/tools/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAI5E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAYhD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAaD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,SAAS,CAAC,EAAE,MAAM,EAE7B;IAED,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,QAAQ;IAIhB;;;;;OAKG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CA4JhH;IAED;;;OAGG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CA6DtC;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAa1B;IAED,yEAAyE;IACzE,KAAK,IAAI,IAAI,CAgBZ;CACF;AAGD,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,aAAa,CAAA;CAAE,KAAK,IAAI,CAAC;AAG9F,eAAO,MAAM,QAAQ,EAAE,gBAkGrB,CAAC;AAGH,eAAO,MAAM,aAAa,EAAE,gBA0F1B,CAAC;AAGH,eAAO,MAAM,aAAa,EAAE,gBAoD1B,CAAC;AAGH,eAAO,MAAM,kBAAkB,EAAE,gBAiH/B,CAAC"}