amai 0.0.19 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +765 -218
- package/dist/cli.js +743 -213
- package/dist/lib/code-server.cjs +21 -8
- package/dist/lib/code-server.js +21 -8
- package/dist/lib/daemon-entry.cjs +742 -195
- package/dist/lib/daemon-entry.js +720 -190
- package/dist/server.cjs +700 -166
- package/dist/server.js +678 -161
- package/package.json +2 -3
package/dist/cli.cjs
CHANGED
|
@@ -5,9 +5,9 @@ var pc5 = require('picocolors');
|
|
|
5
5
|
var WebSocket = require('ws');
|
|
6
6
|
var zod = require('zod');
|
|
7
7
|
var path10 = require('path');
|
|
8
|
-
var
|
|
8
|
+
var fs11 = require('fs');
|
|
9
|
+
var fsp = require('fs/promises');
|
|
9
10
|
var os3 = require('os');
|
|
10
|
-
var fs8 = require('fs/promises');
|
|
11
11
|
var hono = require('hono');
|
|
12
12
|
var nodeServer = require('@hono/node-server');
|
|
13
13
|
var cors = require('hono/cors');
|
|
@@ -19,19 +19,37 @@ var readline = require('readline');
|
|
|
19
19
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
20
20
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
21
21
|
|
|
22
|
+
function _interopNamespace(e) {
|
|
23
|
+
if (e && e.__esModule) return e;
|
|
24
|
+
var n = Object.create(null);
|
|
25
|
+
if (e) {
|
|
26
|
+
Object.keys(e).forEach(function (k) {
|
|
27
|
+
if (k !== 'default') {
|
|
28
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
29
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
get: function () { return e[k]; }
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
n.default = e;
|
|
37
|
+
return Object.freeze(n);
|
|
38
|
+
}
|
|
39
|
+
|
|
22
40
|
var pc5__default = /*#__PURE__*/_interopDefault(pc5);
|
|
23
41
|
var WebSocket__default = /*#__PURE__*/_interopDefault(WebSocket);
|
|
24
42
|
var path10__default = /*#__PURE__*/_interopDefault(path10);
|
|
25
|
-
var
|
|
43
|
+
var fs11__default = /*#__PURE__*/_interopDefault(fs11);
|
|
44
|
+
var fsp__namespace = /*#__PURE__*/_interopNamespace(fsp);
|
|
26
45
|
var os3__default = /*#__PURE__*/_interopDefault(os3);
|
|
27
|
-
var fs8__default = /*#__PURE__*/_interopDefault(fs8);
|
|
28
46
|
var readline__default = /*#__PURE__*/_interopDefault(readline);
|
|
29
47
|
|
|
30
48
|
var MUTATING_TOOLS = /* @__PURE__ */ new Set([
|
|
31
49
|
"editFile",
|
|
32
50
|
"deleteFile",
|
|
33
51
|
"stringReplace",
|
|
34
|
-
"
|
|
52
|
+
"bash"
|
|
35
53
|
]);
|
|
36
54
|
function isMutatingTool(toolName) {
|
|
37
55
|
return MUTATING_TOOLS.has(toolName);
|
|
@@ -52,11 +70,11 @@ function isPathWithinProject(filePath, projectCwd) {
|
|
|
52
70
|
}
|
|
53
71
|
function safeRealpath(p) {
|
|
54
72
|
try {
|
|
55
|
-
return
|
|
73
|
+
return fs11__default.default.realpathSync(p);
|
|
56
74
|
} catch {
|
|
57
75
|
const parent = path10__default.default.dirname(p);
|
|
58
76
|
try {
|
|
59
|
-
const realParent =
|
|
77
|
+
const realParent = fs11__default.default.realpathSync(parent);
|
|
60
78
|
return path10__default.default.join(realParent, path10__default.default.basename(p));
|
|
61
79
|
} catch {
|
|
62
80
|
return path10__default.default.resolve(p);
|
|
@@ -105,77 +123,231 @@ function requireProjectCwd(toolName, projectCwd) {
|
|
|
105
123
|
|
|
106
124
|
// src/tools/read-file.ts
|
|
107
125
|
var MAX_FILE_SIZE = 10 * 1024 * 1024;
|
|
108
|
-
var MAX_LINES_RETURNED =
|
|
126
|
+
var MAX_LINES_RETURNED = 2e3;
|
|
127
|
+
var MAX_LINE_LENGTH = 2e3;
|
|
128
|
+
var MAX_LINE_SUFFIX = `... (line truncated to ${MAX_LINE_LENGTH} chars)`;
|
|
129
|
+
var MAX_BYTES = 50 * 1024;
|
|
130
|
+
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
131
|
+
".zip",
|
|
132
|
+
".tar",
|
|
133
|
+
".gz",
|
|
134
|
+
".exe",
|
|
135
|
+
".dll",
|
|
136
|
+
".so",
|
|
137
|
+
".class",
|
|
138
|
+
".jar",
|
|
139
|
+
".war",
|
|
140
|
+
".7z",
|
|
141
|
+
".doc",
|
|
142
|
+
".docx",
|
|
143
|
+
".xls",
|
|
144
|
+
".xlsx",
|
|
145
|
+
".ppt",
|
|
146
|
+
".pptx",
|
|
147
|
+
".odt",
|
|
148
|
+
".ods",
|
|
149
|
+
".odp",
|
|
150
|
+
".bin",
|
|
151
|
+
".dat",
|
|
152
|
+
".obj",
|
|
153
|
+
".o",
|
|
154
|
+
".a",
|
|
155
|
+
".lib",
|
|
156
|
+
".wasm",
|
|
157
|
+
".pyc",
|
|
158
|
+
".pyo",
|
|
159
|
+
".ico",
|
|
160
|
+
".bmp",
|
|
161
|
+
".ttf",
|
|
162
|
+
".woff",
|
|
163
|
+
".woff2",
|
|
164
|
+
".eot",
|
|
165
|
+
".mp3",
|
|
166
|
+
".mp4",
|
|
167
|
+
".avi",
|
|
168
|
+
".mov",
|
|
169
|
+
".flv"
|
|
170
|
+
]);
|
|
171
|
+
async function isBinaryFile(filepath, fileSize) {
|
|
172
|
+
const ext = path10__default.default.extname(filepath).toLowerCase();
|
|
173
|
+
if (BINARY_EXTENSIONS.has(ext)) return true;
|
|
174
|
+
if (fileSize === 0) return false;
|
|
175
|
+
try {
|
|
176
|
+
const fh = await fsp__namespace.open(filepath, "r");
|
|
177
|
+
try {
|
|
178
|
+
const sampleSize = Math.min(4096, fileSize);
|
|
179
|
+
const bytes = Buffer.alloc(sampleSize);
|
|
180
|
+
const result = await fh.read(bytes, 0, sampleSize, 0);
|
|
181
|
+
if (result.bytesRead === 0) return false;
|
|
182
|
+
let nonPrintableCount = 0;
|
|
183
|
+
for (let i = 0; i < result.bytesRead; i++) {
|
|
184
|
+
if (bytes[i] === 0) return true;
|
|
185
|
+
if (bytes[i] < 9 || bytes[i] > 13 && bytes[i] < 32) {
|
|
186
|
+
nonPrintableCount++;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return nonPrintableCount / result.bytesRead > 0.3;
|
|
190
|
+
} finally {
|
|
191
|
+
await fh.close();
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async function findSimilarFiles(filepath) {
|
|
198
|
+
const dir = path10__default.default.dirname(filepath);
|
|
199
|
+
const base = path10__default.default.basename(filepath).toLowerCase();
|
|
200
|
+
try {
|
|
201
|
+
const entries = await fsp__namespace.readdir(dir);
|
|
202
|
+
return entries.filter(
|
|
203
|
+
(entry) => entry.toLowerCase().includes(base) || base.includes(entry.toLowerCase())
|
|
204
|
+
).map((entry) => path10__default.default.join(dir, entry)).slice(0, 3);
|
|
205
|
+
} catch {
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
109
209
|
zod.z.object({
|
|
110
|
-
relative_file_path: zod.z.string().describe("The
|
|
111
|
-
should_read_entire_file: zod.z.boolean().describe("Whether to read the entire file."),
|
|
112
|
-
start_line_one_indexed: zod.z.number().optional().describe(
|
|
113
|
-
|
|
114
|
-
),
|
|
115
|
-
end_line_one_indexed: zod.z.number().optional().describe("The one-indexed line number to end reading at (inclusive).")
|
|
210
|
+
relative_file_path: zod.z.string().describe("The path to the file or directory to read."),
|
|
211
|
+
should_read_entire_file: zod.z.boolean().describe("Whether to read the entire file.").optional().default(true),
|
|
212
|
+
start_line_one_indexed: zod.z.number().optional().describe("The one-indexed line number to start reading from (inclusive). Alias: offset."),
|
|
213
|
+
end_line_one_indexed: zod.z.number().optional().describe("The one-indexed line number to end reading at (inclusive). Alias: offset + limit.")
|
|
116
214
|
});
|
|
117
215
|
async function readFileContent(absolute_file_path, relative_file_path, should_read_entire_file, start_line_one_indexed, end_line_one_indexed) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
216
|
+
let stat2;
|
|
217
|
+
try {
|
|
218
|
+
stat2 = fs11__default.default.statSync(absolute_file_path);
|
|
219
|
+
} catch {
|
|
220
|
+
const suggestions = await findSimilarFiles(absolute_file_path);
|
|
221
|
+
let message = `File not found: ${relative_file_path}`;
|
|
222
|
+
if (suggestions.length > 0) {
|
|
223
|
+
message += `
|
|
224
|
+
|
|
225
|
+
Did you mean one of these?
|
|
226
|
+
${suggestions.join("\n")}`;
|
|
227
|
+
}
|
|
121
228
|
return {
|
|
122
229
|
success: false,
|
|
123
|
-
message
|
|
230
|
+
message,
|
|
124
231
|
error: "FILE_NOT_FOUND"
|
|
125
232
|
};
|
|
126
233
|
}
|
|
234
|
+
if (stat2.isDirectory()) {
|
|
235
|
+
try {
|
|
236
|
+
const dirents = await fsp__namespace.readdir(absolute_file_path, { withFileTypes: true });
|
|
237
|
+
const entries = await Promise.all(
|
|
238
|
+
dirents.map(async (dirent) => {
|
|
239
|
+
if (dirent.isDirectory()) return dirent.name + "/";
|
|
240
|
+
if (dirent.isSymbolicLink()) {
|
|
241
|
+
const target = await fsp__namespace.stat(path10__default.default.join(absolute_file_path, dirent.name)).catch(() => void 0);
|
|
242
|
+
if (target?.isDirectory()) return dirent.name + "/";
|
|
243
|
+
}
|
|
244
|
+
return dirent.name;
|
|
245
|
+
})
|
|
246
|
+
);
|
|
247
|
+
entries.sort((a, b) => a.localeCompare(b));
|
|
248
|
+
const truncated = entries.length > MAX_LINES_RETURNED;
|
|
249
|
+
const sliced = entries.slice(0, MAX_LINES_RETURNED);
|
|
250
|
+
const output = [
|
|
251
|
+
`<path>${absolute_file_path}</path>`,
|
|
252
|
+
`<type>directory</type>`,
|
|
253
|
+
`<entries>`,
|
|
254
|
+
sliced.join("\n"),
|
|
255
|
+
truncated ? `
|
|
256
|
+
(Showing ${sliced.length} of ${entries.length} entries)` : `
|
|
257
|
+
(${entries.length} entries)`,
|
|
258
|
+
`</entries>`
|
|
259
|
+
].join("\n");
|
|
260
|
+
return {
|
|
261
|
+
success: true,
|
|
262
|
+
message: `Listed directory: ${relative_file_path} (${entries.length} entries)`,
|
|
263
|
+
content: output,
|
|
264
|
+
totalLines: entries.length,
|
|
265
|
+
truncated
|
|
266
|
+
};
|
|
267
|
+
} catch (err) {
|
|
268
|
+
return {
|
|
269
|
+
success: false,
|
|
270
|
+
message: `Failed to list directory: ${relative_file_path}`,
|
|
271
|
+
error: "READ_ERROR"
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
127
275
|
try {
|
|
128
|
-
|
|
129
|
-
if (stat.size > MAX_FILE_SIZE) {
|
|
276
|
+
if (stat2.size > MAX_FILE_SIZE) {
|
|
130
277
|
return {
|
|
131
278
|
success: false,
|
|
132
|
-
message: `File too large (${Math.round(
|
|
279
|
+
message: `File too large (${Math.round(stat2.size / 1024 / 1024)}MB). Maximum is ${MAX_FILE_SIZE / 1024 / 1024}MB. Use line ranges to read portions.`,
|
|
133
280
|
error: "FILE_TOO_LARGE"
|
|
134
281
|
};
|
|
135
282
|
}
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
const totalLines = lines.length;
|
|
139
|
-
if (should_read_entire_file) {
|
|
140
|
-
const cappedLines = lines.slice(0, MAX_LINES_RETURNED);
|
|
141
|
-
const truncated = totalLines > MAX_LINES_RETURNED;
|
|
142
|
-
const content = cappedLines.join("\n");
|
|
283
|
+
const binary = await isBinaryFile(absolute_file_path, stat2.size);
|
|
284
|
+
if (binary) {
|
|
143
285
|
return {
|
|
144
|
-
success:
|
|
145
|
-
message:
|
|
146
|
-
|
|
147
|
-
totalLines,
|
|
148
|
-
truncated
|
|
286
|
+
success: false,
|
|
287
|
+
message: `Cannot read binary file: ${relative_file_path}`,
|
|
288
|
+
error: "BINARY_FILE"
|
|
149
289
|
};
|
|
150
290
|
}
|
|
151
|
-
const
|
|
152
|
-
|
|
291
|
+
const fileContent = await Bun.file(absolute_file_path).text();
|
|
292
|
+
const lines = fileContent.split(/\r?\n/);
|
|
293
|
+
const totalLines = lines.length;
|
|
294
|
+
const start = should_read_entire_file ? 0 : (start_line_one_indexed ?? 1) - 1;
|
|
295
|
+
const end = should_read_entire_file ? Math.min(totalLines, MAX_LINES_RETURNED) : Math.min(end_line_one_indexed ?? totalLines, totalLines);
|
|
296
|
+
if (start >= totalLines && !(totalLines === 0 && start === 0)) {
|
|
153
297
|
return {
|
|
154
298
|
success: false,
|
|
155
|
-
message:
|
|
299
|
+
message: `Offset ${start + 1} is out of range for this file (${totalLines} lines)`,
|
|
156
300
|
error: "INVALID_LINE_RANGE"
|
|
157
301
|
};
|
|
158
302
|
}
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
303
|
+
const outputLines = [];
|
|
304
|
+
let bytes = 0;
|
|
305
|
+
let truncatedByBytes = false;
|
|
306
|
+
let actualEnd = start;
|
|
307
|
+
for (let i = start; i < end; i++) {
|
|
308
|
+
let line = lines[i];
|
|
309
|
+
if (line.length > MAX_LINE_LENGTH) {
|
|
310
|
+
line = line.substring(0, MAX_LINE_LENGTH) + MAX_LINE_SUFFIX;
|
|
311
|
+
}
|
|
312
|
+
const numberedLine = `${i + 1}: ${line}`;
|
|
313
|
+
const lineBytes = Buffer.byteLength(numberedLine, "utf-8") + (outputLines.length > 0 ? 1 : 0);
|
|
314
|
+
if (bytes + lineBytes > MAX_BYTES && outputLines.length > 0) {
|
|
315
|
+
truncatedByBytes = true;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
outputLines.push(numberedLine);
|
|
319
|
+
bytes += lineBytes;
|
|
320
|
+
actualEnd = i + 1;
|
|
321
|
+
}
|
|
322
|
+
const hasMoreLines = actualEnd < totalLines;
|
|
323
|
+
const truncated = truncatedByBytes || hasMoreLines || should_read_entire_file && totalLines > MAX_LINES_RETURNED;
|
|
324
|
+
let output = `<path>${absolute_file_path}</path>
|
|
325
|
+
<type>file</type>
|
|
326
|
+
<content>
|
|
327
|
+
`;
|
|
328
|
+
output += outputLines.join("\n");
|
|
329
|
+
if (truncatedByBytes) {
|
|
330
|
+
output += `
|
|
331
|
+
|
|
332
|
+
(Output capped at ${MAX_BYTES / 1024} KB. Showing lines ${start + 1}-${actualEnd}. Use start_line_one_indexed=${actualEnd + 1} to continue.)`;
|
|
333
|
+
} else if (hasMoreLines && !should_read_entire_file) {
|
|
334
|
+
output += `
|
|
335
|
+
|
|
336
|
+
(Showing lines ${start + 1}-${actualEnd} of ${totalLines}. Use start_line_one_indexed=${actualEnd + 1} to continue.)`;
|
|
337
|
+
} else {
|
|
338
|
+
output += `
|
|
339
|
+
|
|
340
|
+
(End of file - total ${totalLines} lines)`;
|
|
341
|
+
}
|
|
342
|
+
output += "\n</content>";
|
|
164
343
|
return {
|
|
165
344
|
success: true,
|
|
166
|
-
message: `
|
|
167
|
-
content:
|
|
345
|
+
message: truncated ? `Read lines ${start + 1}-${actualEnd} of ${totalLines} from: ${relative_file_path} (truncated)` : `Successfully read file: ${relative_file_path} (${totalLines} lines)`,
|
|
346
|
+
content: output,
|
|
168
347
|
totalLines,
|
|
169
|
-
truncated
|
|
348
|
+
truncated
|
|
170
349
|
};
|
|
171
350
|
} catch (error) {
|
|
172
|
-
if (error?.code === "EISDIR") {
|
|
173
|
-
return {
|
|
174
|
-
success: false,
|
|
175
|
-
message: `Path is not a file: ${relative_file_path}`,
|
|
176
|
-
error: "NOT_A_FILE"
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
351
|
return {
|
|
180
352
|
success: false,
|
|
181
353
|
message: `Failed to read file: ${relative_file_path}`,
|
|
@@ -184,12 +356,12 @@ async function readFileContent(absolute_file_path, relative_file_path, should_re
|
|
|
184
356
|
}
|
|
185
357
|
}
|
|
186
358
|
var read_file = async function(input, projectCwd) {
|
|
187
|
-
const { relative_file_path, should_read_entire_file, start_line_one_indexed, end_line_one_indexed } = input;
|
|
359
|
+
const { relative_file_path, should_read_entire_file = true, start_line_one_indexed, end_line_one_indexed } = input;
|
|
188
360
|
try {
|
|
189
361
|
if (!relative_file_path) {
|
|
190
362
|
return {
|
|
191
363
|
success: false,
|
|
192
|
-
message: "Missing required parameter:
|
|
364
|
+
message: "Missing required parameter: relative_file_path",
|
|
193
365
|
error: "MISSING_TARGET_FILE"
|
|
194
366
|
};
|
|
195
367
|
}
|
|
@@ -522,10 +694,310 @@ function calculateDiffStats(oldContent, newContent) {
|
|
|
522
694
|
zod.z.object({
|
|
523
695
|
file_path: zod.z.string().describe("The path to the file you want to search and replace in. You can use either a relative path in the workspace or an absolute path. If an absolute path is provided, it will be preserved as is"),
|
|
524
696
|
new_string: zod.z.string().describe("The edited text to replace the old_string (must be different from the old_string)"),
|
|
525
|
-
old_string: zod.z.string().describe("The text to replace (must be unique within the file, and must match the file contents exactly, including all whitespace and indentation)")
|
|
697
|
+
old_string: zod.z.string().describe("The text to replace (must be unique within the file, and must match the file contents exactly, including all whitespace and indentation)"),
|
|
698
|
+
replaceAll: zod.z.boolean().optional().describe("Replace all occurrences of old_string (default false)")
|
|
526
699
|
});
|
|
700
|
+
function levenshtein(a, b) {
|
|
701
|
+
if (a === "" || b === "") return Math.max(a.length, b.length);
|
|
702
|
+
const matrix = Array.from(
|
|
703
|
+
{ length: a.length + 1 },
|
|
704
|
+
(_, i) => Array.from({ length: b.length + 1 }, (_2, j) => i === 0 ? j : j === 0 ? i : 0)
|
|
705
|
+
);
|
|
706
|
+
for (let i = 1; i <= a.length; i++) {
|
|
707
|
+
for (let j = 1; j <= b.length; j++) {
|
|
708
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
709
|
+
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
return matrix[a.length][b.length];
|
|
713
|
+
}
|
|
714
|
+
var SINGLE_CANDIDATE_SIMILARITY_THRESHOLD = 0;
|
|
715
|
+
var MULTIPLE_CANDIDATES_SIMILARITY_THRESHOLD = 0.3;
|
|
716
|
+
var SimpleReplacer = function* (_content, find) {
|
|
717
|
+
yield find;
|
|
718
|
+
};
|
|
719
|
+
var LineTrimmedReplacer = function* (content, find) {
|
|
720
|
+
const originalLines = content.split("\n");
|
|
721
|
+
const searchLines = find.split("\n");
|
|
722
|
+
if (searchLines[searchLines.length - 1] === "") searchLines.pop();
|
|
723
|
+
for (let i = 0; i <= originalLines.length - searchLines.length; i++) {
|
|
724
|
+
let matches = true;
|
|
725
|
+
for (let j = 0; j < searchLines.length; j++) {
|
|
726
|
+
if (originalLines[i + j].trim() !== searchLines[j].trim()) {
|
|
727
|
+
matches = false;
|
|
728
|
+
break;
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
if (matches) {
|
|
732
|
+
let matchStartIndex = 0;
|
|
733
|
+
for (let k = 0; k < i; k++) matchStartIndex += originalLines[k].length + 1;
|
|
734
|
+
let matchEndIndex = matchStartIndex;
|
|
735
|
+
for (let k = 0; k < searchLines.length; k++) {
|
|
736
|
+
matchEndIndex += originalLines[i + k].length;
|
|
737
|
+
if (k < searchLines.length - 1) matchEndIndex += 1;
|
|
738
|
+
}
|
|
739
|
+
yield content.substring(matchStartIndex, matchEndIndex);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
var BlockAnchorReplacer = function* (content, find) {
|
|
744
|
+
const originalLines = content.split("\n");
|
|
745
|
+
const searchLines = find.split("\n");
|
|
746
|
+
if (searchLines.length < 3) return;
|
|
747
|
+
if (searchLines[searchLines.length - 1] === "") searchLines.pop();
|
|
748
|
+
const firstLineSearch = searchLines[0].trim();
|
|
749
|
+
const lastLineSearch = searchLines[searchLines.length - 1].trim();
|
|
750
|
+
const searchBlockSize = searchLines.length;
|
|
751
|
+
const candidates = [];
|
|
752
|
+
for (let i = 0; i < originalLines.length; i++) {
|
|
753
|
+
if (originalLines[i].trim() !== firstLineSearch) continue;
|
|
754
|
+
for (let j = i + 2; j < originalLines.length; j++) {
|
|
755
|
+
if (originalLines[j].trim() === lastLineSearch) {
|
|
756
|
+
candidates.push({ startLine: i, endLine: j });
|
|
757
|
+
break;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
if (candidates.length === 0) return;
|
|
762
|
+
const computeSimilarity = (startLine, endLine) => {
|
|
763
|
+
const actualBlockSize = endLine - startLine + 1;
|
|
764
|
+
const linesToCheck = Math.min(searchBlockSize - 2, actualBlockSize - 2);
|
|
765
|
+
if (linesToCheck <= 0) return 1;
|
|
766
|
+
let similarity = 0;
|
|
767
|
+
for (let j = 1; j < searchBlockSize - 1 && j < actualBlockSize - 1; j++) {
|
|
768
|
+
const originalLine = originalLines[startLine + j].trim();
|
|
769
|
+
const searchLine = searchLines[j].trim();
|
|
770
|
+
const maxLen = Math.max(originalLine.length, searchLine.length);
|
|
771
|
+
if (maxLen === 0) continue;
|
|
772
|
+
const distance = levenshtein(originalLine, searchLine);
|
|
773
|
+
similarity += (1 - distance / maxLen) / linesToCheck;
|
|
774
|
+
}
|
|
775
|
+
return similarity;
|
|
776
|
+
};
|
|
777
|
+
const extractBlock = (startLine, endLine) => {
|
|
778
|
+
let matchStartIndex = 0;
|
|
779
|
+
for (let k = 0; k < startLine; k++) matchStartIndex += originalLines[k].length + 1;
|
|
780
|
+
let matchEndIndex = matchStartIndex;
|
|
781
|
+
for (let k = startLine; k <= endLine; k++) {
|
|
782
|
+
matchEndIndex += originalLines[k].length;
|
|
783
|
+
if (k < endLine) matchEndIndex += 1;
|
|
784
|
+
}
|
|
785
|
+
return content.substring(matchStartIndex, matchEndIndex);
|
|
786
|
+
};
|
|
787
|
+
if (candidates.length === 1) {
|
|
788
|
+
const { startLine, endLine } = candidates[0];
|
|
789
|
+
if (computeSimilarity(startLine, endLine) >= SINGLE_CANDIDATE_SIMILARITY_THRESHOLD) {
|
|
790
|
+
yield extractBlock(startLine, endLine);
|
|
791
|
+
}
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
let bestMatch = null;
|
|
795
|
+
let maxSimilarity = -1;
|
|
796
|
+
for (const candidate of candidates) {
|
|
797
|
+
const similarity = computeSimilarity(candidate.startLine, candidate.endLine);
|
|
798
|
+
if (similarity > maxSimilarity) {
|
|
799
|
+
maxSimilarity = similarity;
|
|
800
|
+
bestMatch = candidate;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
if (maxSimilarity >= MULTIPLE_CANDIDATES_SIMILARITY_THRESHOLD && bestMatch) {
|
|
804
|
+
yield extractBlock(bestMatch.startLine, bestMatch.endLine);
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
var WhitespaceNormalizedReplacer = function* (content, find) {
|
|
808
|
+
const normalizeWhitespace = (text) => text.replace(/\s+/g, " ").trim();
|
|
809
|
+
const normalizedFind = normalizeWhitespace(find);
|
|
810
|
+
const lines = content.split("\n");
|
|
811
|
+
for (let i = 0; i < lines.length; i++) {
|
|
812
|
+
const line = lines[i];
|
|
813
|
+
if (normalizeWhitespace(line) === normalizedFind) {
|
|
814
|
+
yield line;
|
|
815
|
+
} else {
|
|
816
|
+
const normalizedLine = normalizeWhitespace(line);
|
|
817
|
+
if (normalizedLine.includes(normalizedFind)) {
|
|
818
|
+
const words = find.trim().split(/\s+/);
|
|
819
|
+
if (words.length > 0) {
|
|
820
|
+
const pattern = words.map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("\\s+");
|
|
821
|
+
try {
|
|
822
|
+
const regex = new RegExp(pattern);
|
|
823
|
+
const match = line.match(regex);
|
|
824
|
+
if (match) yield match[0];
|
|
825
|
+
} catch {
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
const findLines = find.split("\n");
|
|
832
|
+
if (findLines.length > 1) {
|
|
833
|
+
for (let i = 0; i <= lines.length - findLines.length; i++) {
|
|
834
|
+
const block = lines.slice(i, i + findLines.length);
|
|
835
|
+
if (normalizeWhitespace(block.join("\n")) === normalizedFind) {
|
|
836
|
+
yield block.join("\n");
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
var IndentationFlexibleReplacer = function* (content, find) {
|
|
842
|
+
const removeIndentation = (text) => {
|
|
843
|
+
const lines = text.split("\n");
|
|
844
|
+
const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
|
|
845
|
+
if (nonEmptyLines.length === 0) return text;
|
|
846
|
+
const minIndent = Math.min(
|
|
847
|
+
...nonEmptyLines.map((line) => {
|
|
848
|
+
const match = line.match(/^(\s*)/);
|
|
849
|
+
return match ? match[1].length : 0;
|
|
850
|
+
})
|
|
851
|
+
);
|
|
852
|
+
return lines.map((line) => line.trim().length === 0 ? line : line.slice(minIndent)).join("\n");
|
|
853
|
+
};
|
|
854
|
+
const normalizedFind = removeIndentation(find);
|
|
855
|
+
const contentLines = content.split("\n");
|
|
856
|
+
const findLines = find.split("\n");
|
|
857
|
+
for (let i = 0; i <= contentLines.length - findLines.length; i++) {
|
|
858
|
+
const block = contentLines.slice(i, i + findLines.length).join("\n");
|
|
859
|
+
if (removeIndentation(block) === normalizedFind) {
|
|
860
|
+
yield block;
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
var EscapeNormalizedReplacer = function* (content, find) {
|
|
865
|
+
const unescapeString = (str) => {
|
|
866
|
+
return str.replace(/\\(n|t|r|'|"|`|\\|\n|\$)/g, (match, capturedChar) => {
|
|
867
|
+
switch (capturedChar) {
|
|
868
|
+
case "n":
|
|
869
|
+
return "\n";
|
|
870
|
+
case "t":
|
|
871
|
+
return " ";
|
|
872
|
+
case "r":
|
|
873
|
+
return "\r";
|
|
874
|
+
case "'":
|
|
875
|
+
return "'";
|
|
876
|
+
case '"':
|
|
877
|
+
return '"';
|
|
878
|
+
case "`":
|
|
879
|
+
return "`";
|
|
880
|
+
case "\\":
|
|
881
|
+
return "\\";
|
|
882
|
+
case "\n":
|
|
883
|
+
return "\n";
|
|
884
|
+
case "$":
|
|
885
|
+
return "$";
|
|
886
|
+
default:
|
|
887
|
+
return match;
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
};
|
|
891
|
+
const unescapedFind = unescapeString(find);
|
|
892
|
+
if (content.includes(unescapedFind)) {
|
|
893
|
+
yield unescapedFind;
|
|
894
|
+
}
|
|
895
|
+
const lines = content.split("\n");
|
|
896
|
+
const findLines = unescapedFind.split("\n");
|
|
897
|
+
for (let i = 0; i <= lines.length - findLines.length; i++) {
|
|
898
|
+
const block = lines.slice(i, i + findLines.length).join("\n");
|
|
899
|
+
if (unescapeString(block) === unescapedFind) {
|
|
900
|
+
yield block;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
};
|
|
904
|
+
var TrimmedBoundaryReplacer = function* (content, find) {
|
|
905
|
+
const trimmedFind = find.trim();
|
|
906
|
+
if (trimmedFind === find) return;
|
|
907
|
+
if (content.includes(trimmedFind)) {
|
|
908
|
+
yield trimmedFind;
|
|
909
|
+
}
|
|
910
|
+
const lines = content.split("\n");
|
|
911
|
+
const findLines = find.split("\n");
|
|
912
|
+
for (let i = 0; i <= lines.length - findLines.length; i++) {
|
|
913
|
+
const block = lines.slice(i, i + findLines.length).join("\n");
|
|
914
|
+
if (block.trim() === trimmedFind) {
|
|
915
|
+
yield block;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
var ContextAwareReplacer = function* (content, find) {
|
|
920
|
+
const findLines = find.split("\n");
|
|
921
|
+
if (findLines.length < 3) return;
|
|
922
|
+
if (findLines[findLines.length - 1] === "") findLines.pop();
|
|
923
|
+
const contentLines = content.split("\n");
|
|
924
|
+
const firstLine = findLines[0].trim();
|
|
925
|
+
const lastLine = findLines[findLines.length - 1].trim();
|
|
926
|
+
for (let i = 0; i < contentLines.length; i++) {
|
|
927
|
+
if (contentLines[i].trim() !== firstLine) continue;
|
|
928
|
+
for (let j = i + 2; j < contentLines.length; j++) {
|
|
929
|
+
if (contentLines[j].trim() === lastLine) {
|
|
930
|
+
const blockLines = contentLines.slice(i, j + 1);
|
|
931
|
+
if (blockLines.length === findLines.length) {
|
|
932
|
+
let matchingLines = 0;
|
|
933
|
+
let totalNonEmptyLines = 0;
|
|
934
|
+
for (let k = 1; k < blockLines.length - 1; k++) {
|
|
935
|
+
const blockLine = blockLines[k].trim();
|
|
936
|
+
const findLine = findLines[k].trim();
|
|
937
|
+
if (blockLine.length > 0 || findLine.length > 0) {
|
|
938
|
+
totalNonEmptyLines++;
|
|
939
|
+
if (blockLine === findLine) matchingLines++;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
if (totalNonEmptyLines === 0 || matchingLines / totalNonEmptyLines >= 0.5) {
|
|
943
|
+
yield blockLines.join("\n");
|
|
944
|
+
break;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
break;
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
var MultiOccurrenceReplacer = function* (content, find) {
|
|
953
|
+
let startIndex = 0;
|
|
954
|
+
while (true) {
|
|
955
|
+
const index = content.indexOf(find, startIndex);
|
|
956
|
+
if (index === -1) break;
|
|
957
|
+
yield find;
|
|
958
|
+
startIndex = index + find.length;
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
var REPLACERS = [
|
|
962
|
+
SimpleReplacer,
|
|
963
|
+
LineTrimmedReplacer,
|
|
964
|
+
BlockAnchorReplacer,
|
|
965
|
+
WhitespaceNormalizedReplacer,
|
|
966
|
+
IndentationFlexibleReplacer,
|
|
967
|
+
EscapeNormalizedReplacer,
|
|
968
|
+
TrimmedBoundaryReplacer,
|
|
969
|
+
ContextAwareReplacer,
|
|
970
|
+
MultiOccurrenceReplacer
|
|
971
|
+
];
|
|
972
|
+
function smartReplace(content, oldString, newString, replaceAll = false) {
|
|
973
|
+
if (oldString === newString) {
|
|
974
|
+
throw new Error("No changes to apply: oldString and newString are identical.");
|
|
975
|
+
}
|
|
976
|
+
let notFound = true;
|
|
977
|
+
for (const replacer of REPLACERS) {
|
|
978
|
+
for (const search of replacer(content, oldString)) {
|
|
979
|
+
const index = content.indexOf(search);
|
|
980
|
+
if (index === -1) continue;
|
|
981
|
+
notFound = false;
|
|
982
|
+
if (replaceAll) {
|
|
983
|
+
return content.replaceAll(search, newString);
|
|
984
|
+
}
|
|
985
|
+
const lastIndex = content.lastIndexOf(search);
|
|
986
|
+
if (index !== lastIndex) continue;
|
|
987
|
+
return content.substring(0, index) + newString + content.substring(index + search.length);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
if (notFound) {
|
|
991
|
+
throw new Error(
|
|
992
|
+
"oldString not found in content. It must match the file contents exactly, including whitespace, indentation, and line endings."
|
|
993
|
+
);
|
|
994
|
+
}
|
|
995
|
+
throw new Error(
|
|
996
|
+
"Found multiple matches for oldString. Provide more surrounding lines in oldString to identify the correct match."
|
|
997
|
+
);
|
|
998
|
+
}
|
|
527
999
|
var apply_patch = async function(input, projectCwd) {
|
|
528
|
-
const { file_path, new_string, old_string } = input;
|
|
1000
|
+
const { file_path, new_string, old_string, replaceAll: shouldReplaceAll = false } = input;
|
|
529
1001
|
try {
|
|
530
1002
|
if (!file_path) {
|
|
531
1003
|
return {
|
|
@@ -570,6 +1042,22 @@ var apply_patch = async function(input, projectCwd) {
|
|
|
570
1042
|
const file = Bun.file(absolute_file_path);
|
|
571
1043
|
const exists = await file.exists();
|
|
572
1044
|
if (!exists) {
|
|
1045
|
+
if (old_string === "") {
|
|
1046
|
+
const { mkdir: mkdir2 } = await import('fs/promises');
|
|
1047
|
+
const path17 = await import('path');
|
|
1048
|
+
await mkdir2(path17.dirname(absolute_file_path), { recursive: true });
|
|
1049
|
+
await Bun.write(absolute_file_path, new_string);
|
|
1050
|
+
const diffStats = calculateDiffStats("", new_string);
|
|
1051
|
+
return {
|
|
1052
|
+
success: true,
|
|
1053
|
+
isNewFile: true,
|
|
1054
|
+
old_string: "",
|
|
1055
|
+
new_string,
|
|
1056
|
+
linesAdded: diffStats.linesAdded,
|
|
1057
|
+
linesRemoved: diffStats.linesRemoved,
|
|
1058
|
+
message: `Created new file: ${file_path}`
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
573
1061
|
return {
|
|
574
1062
|
success: false,
|
|
575
1063
|
message: `File not found: ${file_path}`,
|
|
@@ -586,22 +1074,31 @@ var apply_patch = async function(input, projectCwd) {
|
|
|
586
1074
|
error: "READ_ERROR"
|
|
587
1075
|
};
|
|
588
1076
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
1077
|
+
let newContent;
|
|
1078
|
+
try {
|
|
1079
|
+
newContent = smartReplace(fileContent, old_string, new_string, shouldReplaceAll);
|
|
1080
|
+
} catch (err) {
|
|
1081
|
+
if (err.message.includes("not found")) {
|
|
1082
|
+
return {
|
|
1083
|
+
success: false,
|
|
1084
|
+
message: `old_string not found in file: ${file_path}. Ensure it matches the file contents exactly, including whitespace and indentation.`,
|
|
1085
|
+
error: "STRING_NOT_FOUND"
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
if (err.message.includes("multiple matches")) {
|
|
1089
|
+
const occurrences = fileContent.split(old_string).length - 1;
|
|
1090
|
+
return {
|
|
1091
|
+
success: false,
|
|
1092
|
+
message: `old_string appears ${occurrences > 1 ? occurrences + " times" : "multiple times (via fuzzy match)"} in the file. Provide more surrounding context to make it unique, or set replaceAll to true.`,
|
|
1093
|
+
error: "STRING_NOT_UNIQUE"
|
|
1094
|
+
};
|
|
1095
|
+
}
|
|
598
1096
|
return {
|
|
599
1097
|
success: false,
|
|
600
|
-
message:
|
|
601
|
-
error: "
|
|
1098
|
+
message: err.message,
|
|
1099
|
+
error: "REPLACE_ERROR"
|
|
602
1100
|
};
|
|
603
1101
|
}
|
|
604
|
-
const newContent = fileContent.replace(old_string, new_string);
|
|
605
1102
|
try {
|
|
606
1103
|
await Bun.write(absolute_file_path, newContent);
|
|
607
1104
|
const diffStats = calculateDiffStats(fileContent, newContent);
|
|
@@ -635,11 +1132,18 @@ var CODE_DIR = path10__default.default.join(AMA_DIR, "code");
|
|
|
635
1132
|
var STORAGE_DIR = path10__default.default.join(AMA_DIR, "storage");
|
|
636
1133
|
zod.z.object({
|
|
637
1134
|
target_file: zod.z.string().describe("The relative path to the file to modify. The tool will create any directories in the path that don't exist"),
|
|
638
|
-
content: zod.z.string().describe("The content to write to the file"),
|
|
639
|
-
providedNewFile: zod.z.boolean().describe("
|
|
1135
|
+
content: zod.z.string().describe("The full content to write to the file"),
|
|
1136
|
+
providedNewFile: zod.z.boolean().describe("Whether this is a new file (true) or an edit to an existing file (false). Auto-detected if omitted.").optional()
|
|
640
1137
|
});
|
|
641
1138
|
var editFiles = async function(input, projectCwd) {
|
|
642
1139
|
const { target_file, content, providedNewFile } = input;
|
|
1140
|
+
if (!target_file) {
|
|
1141
|
+
return {
|
|
1142
|
+
success: false,
|
|
1143
|
+
error: "Missing required parameter: target_file",
|
|
1144
|
+
message: "target_file is required"
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
643
1147
|
try {
|
|
644
1148
|
if (projectCwd) {
|
|
645
1149
|
const validation = validatePath(target_file, projectCwd);
|
|
@@ -654,7 +1158,7 @@ var editFiles = async function(input, projectCwd) {
|
|
|
654
1158
|
const basePath = projectCwd || process.cwd();
|
|
655
1159
|
const filePath = resolveProjectPath(target_file, basePath);
|
|
656
1160
|
const dirPath = path10__default.default.dirname(filePath);
|
|
657
|
-
await
|
|
1161
|
+
await fsp.mkdir(dirPath, { recursive: true });
|
|
658
1162
|
let isNewFile = providedNewFile;
|
|
659
1163
|
let existingContent = "";
|
|
660
1164
|
const file = Bun.file(filePath);
|
|
@@ -674,6 +1178,15 @@ var editFiles = async function(input, projectCwd) {
|
|
|
674
1178
|
isNewFile = true;
|
|
675
1179
|
}
|
|
676
1180
|
}
|
|
1181
|
+
if (!isNewFile && existingContent === content) {
|
|
1182
|
+
return {
|
|
1183
|
+
success: true,
|
|
1184
|
+
isNewFile: false,
|
|
1185
|
+
message: `No changes needed: ${target_file} (content identical)`,
|
|
1186
|
+
linesAdded: 0,
|
|
1187
|
+
linesRemoved: 0
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
677
1190
|
await Bun.write(filePath, content);
|
|
678
1191
|
const diffStats = calculateDiffStats(existingContent, content);
|
|
679
1192
|
if (isNewFile) {
|
|
@@ -682,7 +1195,7 @@ var editFiles = async function(input, projectCwd) {
|
|
|
682
1195
|
isNewFile: true,
|
|
683
1196
|
old_string: "",
|
|
684
1197
|
new_string: content,
|
|
685
|
-
message: `Created new file: ${target_file}`,
|
|
1198
|
+
message: `Created new file: ${target_file} (+${diffStats.linesAdded} lines)`,
|
|
686
1199
|
linesAdded: diffStats.linesAdded,
|
|
687
1200
|
linesRemoved: diffStats.linesRemoved
|
|
688
1201
|
};
|
|
@@ -692,7 +1205,7 @@ var editFiles = async function(input, projectCwd) {
|
|
|
692
1205
|
isNewFile: false,
|
|
693
1206
|
old_string: existingContent,
|
|
694
1207
|
new_string: content,
|
|
695
|
-
message: `Modified file: ${target_file}`,
|
|
1208
|
+
message: `Modified file: ${target_file} (+${diffStats.linesAdded} -${diffStats.linesRemoved} lines)`,
|
|
696
1209
|
linesAdded: diffStats.linesAdded,
|
|
697
1210
|
linesRemoved: diffStats.linesRemoved
|
|
698
1211
|
};
|
|
@@ -757,7 +1270,7 @@ var deleteFile = async function(input, projectCwd) {
|
|
|
757
1270
|
};
|
|
758
1271
|
}
|
|
759
1272
|
try {
|
|
760
|
-
await
|
|
1273
|
+
await fsp.unlink(absolute_file_path);
|
|
761
1274
|
} catch {
|
|
762
1275
|
return {
|
|
763
1276
|
success: false,
|
|
@@ -780,7 +1293,8 @@ var deleteFile = async function(input, projectCwd) {
|
|
|
780
1293
|
};
|
|
781
1294
|
var GREP_LIMITS = {
|
|
782
1295
|
DEFAULT_MAX_MATCHES: 200,
|
|
783
|
-
MAX_LINE_LENGTH:
|
|
1296
|
+
MAX_LINE_LENGTH: 2e3,
|
|
1297
|
+
// aligned with OpenCode's 2000-char truncation
|
|
784
1298
|
MAX_TOTAL_OUTPUT_SIZE: 1 * 1024 * 1024,
|
|
785
1299
|
EXECUTION_TIMEOUT_MS: 15e3,
|
|
786
1300
|
TRUNCATION_MESSAGE: "\n[Results truncated due to size limits. Use more specific patterns or file filters to narrow your search.]"
|
|
@@ -788,11 +1302,11 @@ var GREP_LIMITS = {
|
|
|
788
1302
|
zod.z.object({
|
|
789
1303
|
query: zod.z.string().describe("The regex pattern to search for"),
|
|
790
1304
|
options: zod.z.object({
|
|
791
|
-
includePattern: zod.z.string().optional().describe('Glob pattern for files to include (e.g., "*.ts")'),
|
|
1305
|
+
includePattern: zod.z.string().optional().describe('Glob pattern for files to include (e.g., "*.ts", "*.{ts,tsx}")'),
|
|
792
1306
|
excludePattern: zod.z.string().optional().describe("Glob pattern for files to exclude"),
|
|
793
1307
|
caseSensitive: zod.z.boolean().optional().describe("Whether the search should be case sensitive"),
|
|
794
1308
|
path: zod.z.string().optional().describe("Subdirectory to search in"),
|
|
795
|
-
sortByMtime: zod.z.boolean().optional().describe("Sort results by file modification time (default:
|
|
1309
|
+
sortByMtime: zod.z.boolean().optional().describe("Sort results by file modification time (default: true)")
|
|
796
1310
|
}).optional()
|
|
797
1311
|
});
|
|
798
1312
|
var _cachedRgPath = null;
|
|
@@ -804,7 +1318,7 @@ async function getRipgrepPath() {
|
|
|
804
1318
|
"/usr/bin/rg"
|
|
805
1319
|
];
|
|
806
1320
|
for (const rgPath of paths) {
|
|
807
|
-
if (
|
|
1321
|
+
if (fs11__default.default.existsSync(rgPath)) {
|
|
808
1322
|
_cachedRgPath = rgPath;
|
|
809
1323
|
return rgPath;
|
|
810
1324
|
}
|
|
@@ -838,7 +1352,7 @@ var grepTool = async function(input, projectCwd) {
|
|
|
838
1352
|
};
|
|
839
1353
|
}
|
|
840
1354
|
try {
|
|
841
|
-
const { includePattern, excludePattern, caseSensitive, path: subPath, sortByMtime =
|
|
1355
|
+
const { includePattern, excludePattern, caseSensitive, path: subPath, sortByMtime = true } = options || {};
|
|
842
1356
|
let searchDir = projectCwd || process.cwd();
|
|
843
1357
|
if (subPath) {
|
|
844
1358
|
searchDir = path10__default.default.isAbsolute(subPath) ? subPath : path10__default.default.resolve(searchDir, subPath);
|
|
@@ -853,7 +1367,7 @@ var grepTool = async function(input, projectCwd) {
|
|
|
853
1367
|
}
|
|
854
1368
|
}
|
|
855
1369
|
}
|
|
856
|
-
if (!
|
|
1370
|
+
if (!fs11__default.default.existsSync(searchDir)) {
|
|
857
1371
|
return {
|
|
858
1372
|
success: false,
|
|
859
1373
|
message: `Directory not found: ${searchDir}`,
|
|
@@ -862,12 +1376,15 @@ var grepTool = async function(input, projectCwd) {
|
|
|
862
1376
|
}
|
|
863
1377
|
const rgPath = await getRipgrepPath();
|
|
864
1378
|
const args2 = [
|
|
865
|
-
"-
|
|
866
|
-
|
|
867
|
-
"--
|
|
1379
|
+
"-nH",
|
|
1380
|
+
// line numbers + filename (compact form, matching OpenCode)
|
|
1381
|
+
"--hidden",
|
|
1382
|
+
// search hidden files (aligned with OpenCode)
|
|
1383
|
+
"--no-messages",
|
|
1384
|
+
// suppress error messages for unreadable files
|
|
868
1385
|
"--color=never",
|
|
869
1386
|
"--max-count=100",
|
|
870
|
-
"--max-columns=
|
|
1387
|
+
"--max-columns=2000"
|
|
871
1388
|
];
|
|
872
1389
|
if (!caseSensitive) {
|
|
873
1390
|
args2.push("-i");
|
|
@@ -887,6 +1404,7 @@ var grepTool = async function(input, projectCwd) {
|
|
|
887
1404
|
args2.push("--glob", "!package-lock.json");
|
|
888
1405
|
args2.push("--glob", "!yarn.lock");
|
|
889
1406
|
args2.push("--glob", "!bun.lockb");
|
|
1407
|
+
args2.push("--glob", "!pnpm-lock.yaml");
|
|
890
1408
|
args2.push("--regexp", query);
|
|
891
1409
|
args2.push(searchDir);
|
|
892
1410
|
const proc = Bun.spawn([rgPath, ...args2], {
|
|
@@ -919,7 +1437,7 @@ var grepTool = async function(input, projectCwd) {
|
|
|
919
1437
|
message: `No matches found for pattern: ${query}`
|
|
920
1438
|
};
|
|
921
1439
|
}
|
|
922
|
-
if (exitCode !== 0) {
|
|
1440
|
+
if (exitCode !== 0 && exitCode !== 2) {
|
|
923
1441
|
return {
|
|
924
1442
|
success: false,
|
|
925
1443
|
message: `Ripgrep error: ${stderr || "Unknown error"}`,
|
|
@@ -1005,8 +1523,7 @@ var grepTool = async function(input, projectCwd) {
|
|
|
1005
1523
|
};
|
|
1006
1524
|
zod.z.object({
|
|
1007
1525
|
pattern: zod.z.string().describe('Glob pattern to match files (e.g., "**/*.js", "src/**/*.ts", "*.json"). Supports standard glob syntax with *, **, and ? wildcards'),
|
|
1008
|
-
path: zod.z.string().optional().describe("Optional
|
|
1009
|
-
sortByMtime: zod.z.boolean().optional().describe("Sort results by modification time (default: false \u2014 faster without I/O)")
|
|
1526
|
+
path: zod.z.string().optional().describe("Optional directory path to limit the search scope. If not provided, searches from the project root")
|
|
1010
1527
|
});
|
|
1011
1528
|
var RESULT_LIMIT = 100;
|
|
1012
1529
|
var MTIME_BATCH_SIZE = 50;
|
|
@@ -1025,7 +1542,7 @@ async function getMtimesBatched2(files) {
|
|
|
1025
1542
|
return results;
|
|
1026
1543
|
}
|
|
1027
1544
|
var globTool = async function(input, projectCwd) {
|
|
1028
|
-
const { pattern, path: inputPath
|
|
1545
|
+
const { pattern, path: inputPath } = input;
|
|
1029
1546
|
if (!pattern) {
|
|
1030
1547
|
return {
|
|
1031
1548
|
success: false,
|
|
@@ -1036,7 +1553,7 @@ var globTool = async function(input, projectCwd) {
|
|
|
1036
1553
|
try {
|
|
1037
1554
|
const basePath = projectCwd || process.cwd();
|
|
1038
1555
|
const searchPath = inputPath ? resolveProjectPath(inputPath, basePath) : basePath;
|
|
1039
|
-
if (!
|
|
1556
|
+
if (!fs11__default.default.existsSync(searchPath)) {
|
|
1040
1557
|
return {
|
|
1041
1558
|
success: false,
|
|
1042
1559
|
message: `Directory not found: ${searchPath}`,
|
|
@@ -1072,7 +1589,7 @@ var globTool = async function(input, projectCwd) {
|
|
|
1072
1589
|
files.push(match);
|
|
1073
1590
|
}
|
|
1074
1591
|
let sortedFiles;
|
|
1075
|
-
if (
|
|
1592
|
+
if (files.length > 0) {
|
|
1076
1593
|
const filesWithMtime = await getMtimesBatched2(files);
|
|
1077
1594
|
filesWithMtime.sort((a, b) => b.mtime - a.mtime);
|
|
1078
1595
|
sortedFiles = filesWithMtime.map((f) => f.path);
|
|
@@ -1109,7 +1626,7 @@ var globTool = async function(input, projectCwd) {
|
|
|
1109
1626
|
};
|
|
1110
1627
|
}
|
|
1111
1628
|
};
|
|
1112
|
-
var
|
|
1629
|
+
var DEFAULT_IGNORE_PATTERNS = [
|
|
1113
1630
|
"node_modules",
|
|
1114
1631
|
"__pycache__",
|
|
1115
1632
|
".git",
|
|
@@ -1141,18 +1658,19 @@ var IGNORE_PATTERNS = [
|
|
|
1141
1658
|
var RESULT_LIMIT2 = 500;
|
|
1142
1659
|
var MTIME_BATCH_SIZE2 = 50;
|
|
1143
1660
|
zod.z.object({
|
|
1144
|
-
path: zod.z.string().optional().describe("
|
|
1661
|
+
path: zod.z.string().optional().describe("Path to the directory to list"),
|
|
1145
1662
|
recursive: zod.z.boolean().optional().describe("Whether to list files recursively (default: true)"),
|
|
1146
1663
|
maxDepth: zod.z.number().optional().describe("Maximum recursion depth (default: 3)"),
|
|
1147
1664
|
pattern: zod.z.string().optional().describe("File extension (e.g., '.ts') or glob-like pattern"),
|
|
1148
1665
|
showHidden: zod.z.boolean().optional().describe("Whether to show hidden files (default: false)"),
|
|
1149
|
-
includeMetadata: zod.z.boolean().optional().describe("Whether to fetch file metadata like mtime (default: false
|
|
1666
|
+
includeMetadata: zod.z.boolean().optional().describe("Whether to fetch file metadata like mtime (default: false -- faster without I/O)"),
|
|
1667
|
+
ignore: zod.z.array(zod.z.string()).optional().describe("Additional glob patterns to ignore (added to default ignore list)")
|
|
1150
1668
|
});
|
|
1151
|
-
function shouldIgnore(name, showHidden) {
|
|
1669
|
+
function shouldIgnore(name, showHidden, ignoreSet) {
|
|
1152
1670
|
if (!showHidden && name.startsWith(".") && name !== ".") {
|
|
1153
1671
|
return true;
|
|
1154
1672
|
}
|
|
1155
|
-
return
|
|
1673
|
+
return ignoreSet.has(name);
|
|
1156
1674
|
}
|
|
1157
1675
|
function matchPattern(name, pattern) {
|
|
1158
1676
|
if (!pattern) return true;
|
|
@@ -1218,7 +1736,8 @@ var list = async function(input, projectCwd) {
|
|
|
1218
1736
|
maxDepth = 3,
|
|
1219
1737
|
pattern,
|
|
1220
1738
|
showHidden = false,
|
|
1221
|
-
includeMetadata = false
|
|
1739
|
+
includeMetadata = false,
|
|
1740
|
+
ignore: extraIgnore
|
|
1222
1741
|
} = input;
|
|
1223
1742
|
if (maxDepth !== void 0 && (!Number.isInteger(maxDepth) || maxDepth < 0)) {
|
|
1224
1743
|
return {
|
|
@@ -1240,14 +1759,14 @@ var list = async function(input, projectCwd) {
|
|
|
1240
1759
|
};
|
|
1241
1760
|
}
|
|
1242
1761
|
}
|
|
1243
|
-
if (!
|
|
1762
|
+
if (!fs11__default.default.existsSync(absolutePath)) {
|
|
1244
1763
|
return {
|
|
1245
1764
|
success: false,
|
|
1246
1765
|
message: `Directory not found: ${absolutePath}`,
|
|
1247
1766
|
error: "DIR_NOT_FOUND"
|
|
1248
1767
|
};
|
|
1249
1768
|
}
|
|
1250
|
-
const stats =
|
|
1769
|
+
const stats = fs11__default.default.statSync(absolutePath);
|
|
1251
1770
|
if (!stats.isDirectory()) {
|
|
1252
1771
|
return {
|
|
1253
1772
|
success: false,
|
|
@@ -1255,6 +1774,12 @@ var list = async function(input, projectCwd) {
|
|
|
1255
1774
|
error: "NOT_A_DIRECTORY"
|
|
1256
1775
|
};
|
|
1257
1776
|
}
|
|
1777
|
+
const ignoreSet = new Set(DEFAULT_IGNORE_PATTERNS);
|
|
1778
|
+
if (extraIgnore && extraIgnore.length > 0) {
|
|
1779
|
+
for (const pat of extraIgnore) {
|
|
1780
|
+
ignoreSet.add(pat);
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1258
1783
|
const collected = [];
|
|
1259
1784
|
let truncated = false;
|
|
1260
1785
|
const walk = async (currentDir, depth) => {
|
|
@@ -1264,7 +1789,7 @@ var list = async function(input, projectCwd) {
|
|
|
1264
1789
|
}
|
|
1265
1790
|
let entries;
|
|
1266
1791
|
try {
|
|
1267
|
-
entries =
|
|
1792
|
+
entries = fs11__default.default.readdirSync(currentDir, { withFileTypes: true });
|
|
1268
1793
|
} catch {
|
|
1269
1794
|
return;
|
|
1270
1795
|
}
|
|
@@ -1279,7 +1804,7 @@ var list = async function(input, projectCwd) {
|
|
|
1279
1804
|
truncated = true;
|
|
1280
1805
|
break;
|
|
1281
1806
|
}
|
|
1282
|
-
if (shouldIgnore(entry.name, showHidden)) {
|
|
1807
|
+
if (shouldIgnore(entry.name, showHidden, ignoreSet)) {
|
|
1283
1808
|
continue;
|
|
1284
1809
|
}
|
|
1285
1810
|
const entryAbsolutePath = path10__default.default.join(currentDir, entry.name);
|
|
@@ -1379,10 +1904,10 @@ var CREDENTIALS_DIR = path10__default.default.join(os3__default.default.homedir(
|
|
|
1379
1904
|
var CREDENTIALS_PATH = path10__default.default.join(CREDENTIALS_DIR, "credentials.json");
|
|
1380
1905
|
function isAuthenticated() {
|
|
1381
1906
|
try {
|
|
1382
|
-
if (!
|
|
1907
|
+
if (!fs11__default.default.existsSync(CREDENTIALS_PATH)) {
|
|
1383
1908
|
return false;
|
|
1384
1909
|
}
|
|
1385
|
-
const raw =
|
|
1910
|
+
const raw = fs11__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
|
|
1386
1911
|
const data = JSON.parse(raw);
|
|
1387
1912
|
return Boolean(data && data.access_token);
|
|
1388
1913
|
} catch {
|
|
@@ -1391,10 +1916,10 @@ function isAuthenticated() {
|
|
|
1391
1916
|
}
|
|
1392
1917
|
function saveTokens(tokens) {
|
|
1393
1918
|
try {
|
|
1394
|
-
if (!
|
|
1395
|
-
|
|
1919
|
+
if (!fs11__default.default.existsSync(CREDENTIALS_DIR)) {
|
|
1920
|
+
fs11__default.default.mkdirSync(CREDENTIALS_DIR, { recursive: true });
|
|
1396
1921
|
}
|
|
1397
|
-
|
|
1922
|
+
fs11__default.default.writeFileSync(
|
|
1398
1923
|
CREDENTIALS_PATH,
|
|
1399
1924
|
JSON.stringify(tokens, null, 2),
|
|
1400
1925
|
"utf8"
|
|
@@ -1405,18 +1930,18 @@ function saveTokens(tokens) {
|
|
|
1405
1930
|
}
|
|
1406
1931
|
function logout() {
|
|
1407
1932
|
try {
|
|
1408
|
-
if (
|
|
1409
|
-
|
|
1933
|
+
if (fs11__default.default.existsSync(CREDENTIALS_PATH)) {
|
|
1934
|
+
fs11__default.default.unlinkSync(CREDENTIALS_PATH);
|
|
1410
1935
|
}
|
|
1411
1936
|
} catch (error) {
|
|
1412
1937
|
console.error(pc5__default.default.red("Failed to logout"), error);
|
|
1413
1938
|
}
|
|
1414
1939
|
}
|
|
1415
1940
|
function getTokens() {
|
|
1416
|
-
if (!
|
|
1941
|
+
if (!fs11__default.default.existsSync(CREDENTIALS_PATH)) {
|
|
1417
1942
|
return null;
|
|
1418
1943
|
}
|
|
1419
|
-
const raw =
|
|
1944
|
+
const raw = fs11__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
|
|
1420
1945
|
const data = JSON.parse(raw);
|
|
1421
1946
|
return data;
|
|
1422
1947
|
}
|
|
@@ -1515,10 +2040,10 @@ async function login() {
|
|
|
1515
2040
|
}
|
|
1516
2041
|
var getUserId = () => {
|
|
1517
2042
|
try {
|
|
1518
|
-
if (!
|
|
2043
|
+
if (!fs11__default.default.existsSync(CREDENTIALS_PATH)) {
|
|
1519
2044
|
return;
|
|
1520
2045
|
}
|
|
1521
|
-
const raw =
|
|
2046
|
+
const raw = fs11__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
|
|
1522
2047
|
const data = JSON.parse(raw);
|
|
1523
2048
|
const fromUserObject = data.user?.id;
|
|
1524
2049
|
const fromTopLevel = data.sub ?? data.user_id;
|
|
@@ -1544,26 +2069,20 @@ var getUserId = () => {
|
|
|
1544
2069
|
}
|
|
1545
2070
|
};
|
|
1546
2071
|
var ExplanationSchema = zod.z.object({
|
|
1547
|
-
|
|
2072
|
+
description: zod.z.string().describe(
|
|
2073
|
+
"Clear, concise description of what this command does in 5-10 words. Examples:\nInput: ls\nOutput: Lists files in current directory\n\nInput: git status\nOutput: Shows working tree status\n\nInput: npm install\nOutput: Installs package dependencies\n\nInput: mkdir foo\nOutput: Creates directory 'foo'"
|
|
2074
|
+
)
|
|
1548
2075
|
});
|
|
1549
2076
|
var BLOCKED_PATTERNS = [
|
|
1550
|
-
// rm with -r/-f flags (combined or separate) targeting /, ~, $HOME, or *
|
|
1551
2077
|
/\brm\s+(-\w+\s+)*(\/ |\/\s*$|~|\/\*|\*)/,
|
|
1552
|
-
// Disk-wiping commands
|
|
1553
2078
|
/\bdd\s+.*of=\/dev\//,
|
|
1554
2079
|
/\bmkfs\b/,
|
|
1555
|
-
// Fork bomb
|
|
1556
2080
|
/:\(\)\{.*\|.*&\}\s*;?\s*:/,
|
|
1557
|
-
// Recursive chmod/chown on root
|
|
1558
2081
|
/\bchmod\s+.*-R.*\s+\/\s*$/,
|
|
1559
2082
|
/\bchown\s+.*-R.*\s+\/\s*$/,
|
|
1560
|
-
// Pipe from remote URL directly into shell
|
|
1561
2083
|
/\b(curl|wget)\s+.*\|\s*(ba)?sh/,
|
|
1562
|
-
// Move root filesystem
|
|
1563
2084
|
/\bmv\s+(\/|\*)\s/,
|
|
1564
|
-
// Write random data to disk device
|
|
1565
2085
|
/\bcat\s+\/dev\/(u?random|zero)\s*>\s*\/dev\//,
|
|
1566
|
-
// Windows-specific destructive
|
|
1567
2086
|
/\bformat\s+[A-Z]:/i,
|
|
1568
2087
|
/\bdiskpart\b/i,
|
|
1569
2088
|
/\bcipher\s+\/w:/i
|
|
@@ -1574,6 +2093,7 @@ var DANGEROUS_FLAGS = [
|
|
|
1574
2093
|
/\bgit\s+push\s+-f\b/
|
|
1575
2094
|
];
|
|
1576
2095
|
var MAX_OUTPUT_SIZE = 1 * 1024 * 1024;
|
|
2096
|
+
var DEFAULT_TIMEOUT = 12e4;
|
|
1577
2097
|
function evaluateCommandSafety(command) {
|
|
1578
2098
|
const trimmed = command.trim();
|
|
1579
2099
|
for (const pattern of BLOCKED_PATTERNS) {
|
|
@@ -1589,8 +2109,10 @@ function evaluateCommandSafety(command) {
|
|
|
1589
2109
|
return { safe: true };
|
|
1590
2110
|
}
|
|
1591
2111
|
zod.z.object({
|
|
1592
|
-
command: zod.z.string().describe("The terminal command to execute
|
|
1593
|
-
is_background: zod.z.boolean().describe("Whether the command should be run in the background")
|
|
2112
|
+
command: zod.z.string().describe("The terminal command to execute"),
|
|
2113
|
+
is_background: zod.z.boolean().optional().default(false).describe("Whether the command should be run in the background"),
|
|
2114
|
+
timeout: zod.z.number().optional().describe("Optional timeout in milliseconds. If not specified, commands will time out after 120000ms (2 minutes)."),
|
|
2115
|
+
workdir: zod.z.string().optional().describe("The working directory to run the command in. Defaults to the project directory. Use this instead of 'cd' commands.")
|
|
1594
2116
|
}).merge(ExplanationSchema);
|
|
1595
2117
|
var runSecureTerminalCommand = async (command, timeout, cwd) => {
|
|
1596
2118
|
try {
|
|
@@ -1647,7 +2169,7 @@ var runSecureTerminalCommand = async (command, timeout, cwd) => {
|
|
|
1647
2169
|
};
|
|
1648
2170
|
}
|
|
1649
2171
|
};
|
|
1650
|
-
var
|
|
2172
|
+
var bashTool = async (input, projectCwd) => {
|
|
1651
2173
|
try {
|
|
1652
2174
|
const safety = evaluateCommandSafety(input.command);
|
|
1653
2175
|
if (!safety.safe) {
|
|
@@ -1658,9 +2180,18 @@ var runTerminalCommand = async (input, projectCwd) => {
|
|
|
1658
2180
|
error: "BLOCKED_COMMAND"
|
|
1659
2181
|
};
|
|
1660
2182
|
}
|
|
2183
|
+
if (input.timeout !== void 0 && input.timeout < 0) {
|
|
2184
|
+
return {
|
|
2185
|
+
success: false,
|
|
2186
|
+
message: `Invalid timeout value: ${input.timeout}. Timeout must be a positive number.`,
|
|
2187
|
+
error: "INVALID_TIMEOUT"
|
|
2188
|
+
};
|
|
2189
|
+
}
|
|
2190
|
+
const cwd = input.workdir || projectCwd || process.cwd();
|
|
2191
|
+
const timeout = input.timeout ?? DEFAULT_TIMEOUT;
|
|
1661
2192
|
if (input?.is_background) {
|
|
1662
2193
|
const proc = Bun.spawn(["sh", "-c", input.command], {
|
|
1663
|
-
cwd
|
|
2194
|
+
cwd,
|
|
1664
2195
|
stdout: "ignore",
|
|
1665
2196
|
stderr: "ignore"
|
|
1666
2197
|
});
|
|
@@ -1674,8 +2205,8 @@ var runTerminalCommand = async (input, projectCwd) => {
|
|
|
1674
2205
|
} else {
|
|
1675
2206
|
const result = await runSecureTerminalCommand(
|
|
1676
2207
|
input.command,
|
|
1677
|
-
|
|
1678
|
-
|
|
2208
|
+
timeout,
|
|
2209
|
+
cwd
|
|
1679
2210
|
);
|
|
1680
2211
|
if (result?.error && !result?.exitCode) {
|
|
1681
2212
|
return result;
|
|
@@ -1706,14 +2237,14 @@ var ProjectRegistry = class {
|
|
|
1706
2237
|
}
|
|
1707
2238
|
load() {
|
|
1708
2239
|
try {
|
|
1709
|
-
if (
|
|
1710
|
-
const data =
|
|
2240
|
+
if (fs11__default.default.existsSync(REGISTRY_FILE)) {
|
|
2241
|
+
const data = fs11__default.default.readFileSync(REGISTRY_FILE, "utf8");
|
|
1711
2242
|
const parsed = JSON.parse(data);
|
|
1712
2243
|
if (!Array.isArray(parsed)) {
|
|
1713
2244
|
console.error("Invalid project registry format: expected array, got", typeof parsed);
|
|
1714
2245
|
const backupFile = REGISTRY_FILE + ".backup." + Date.now();
|
|
1715
|
-
|
|
1716
|
-
|
|
2246
|
+
fs11__default.default.copyFileSync(REGISTRY_FILE, backupFile);
|
|
2247
|
+
fs11__default.default.unlinkSync(REGISTRY_FILE);
|
|
1717
2248
|
return;
|
|
1718
2249
|
}
|
|
1719
2250
|
const projects = parsed;
|
|
@@ -1726,11 +2257,11 @@ var ProjectRegistry = class {
|
|
|
1726
2257
|
}
|
|
1727
2258
|
} catch (error) {
|
|
1728
2259
|
console.error("Failed to load project registry:", error);
|
|
1729
|
-
if (
|
|
2260
|
+
if (fs11__default.default.existsSync(REGISTRY_FILE)) {
|
|
1730
2261
|
try {
|
|
1731
2262
|
const backupFile = REGISTRY_FILE + ".backup." + Date.now();
|
|
1732
|
-
|
|
1733
|
-
|
|
2263
|
+
fs11__default.default.copyFileSync(REGISTRY_FILE, backupFile);
|
|
2264
|
+
fs11__default.default.unlinkSync(REGISTRY_FILE);
|
|
1734
2265
|
console.log("Corrupted registry file backed up and removed. Starting fresh.");
|
|
1735
2266
|
} catch (backupError) {
|
|
1736
2267
|
}
|
|
@@ -1739,11 +2270,11 @@ var ProjectRegistry = class {
|
|
|
1739
2270
|
}
|
|
1740
2271
|
save() {
|
|
1741
2272
|
try {
|
|
1742
|
-
if (!
|
|
1743
|
-
|
|
2273
|
+
if (!fs11__default.default.existsSync(AMA_DIR)) {
|
|
2274
|
+
fs11__default.default.mkdirSync(AMA_DIR, { recursive: true });
|
|
1744
2275
|
}
|
|
1745
2276
|
const projects = Array.from(this.projects.values());
|
|
1746
|
-
|
|
2277
|
+
fs11__default.default.writeFileSync(REGISTRY_FILE, JSON.stringify(projects, null, 2), "utf8");
|
|
1747
2278
|
} catch (error) {
|
|
1748
2279
|
console.error("Failed to save project registry:", error);
|
|
1749
2280
|
}
|
|
@@ -1783,7 +2314,7 @@ var ProjectRegistry = class {
|
|
|
1783
2314
|
var projectRegistry = new ProjectRegistry();
|
|
1784
2315
|
var ignoreFiles = ["node_modules", ".git", ".next", ".env", ".env.local", ".env.development.local", ".env.test.local", ".env.production.local", ".output", ".turbo", ".vercel", ".next", ".tanstack", ".nitro", ".wrangler", ".alchemy", ".coverage", ".nyc_output", ".cache", "tmp", "temp", ".idea", ".vscode", ".zig-cache", "zig-out", ".coverage", "coverage", "logs", ".venv", "venv", "env", ".next", ".turbo", ".vercel", ".output", ".tanstack", ".nitro", ".wrangler", ".alchemy", ".coverage", ".nyc_output", ".cache", "tmp", "temp", ".idea", ".vscode", ".zig-cache", "zig-out", ".coverage", "coverage", "logs", ".venv", "venv", "env"];
|
|
1785
2316
|
var getContext = (dir, base = dir, allFiles = []) => {
|
|
1786
|
-
const filePath =
|
|
2317
|
+
const filePath = fs11.readdirSync(dir, { withFileTypes: true });
|
|
1787
2318
|
for (const file of filePath) {
|
|
1788
2319
|
if (ignoreFiles.includes(file.name)) continue;
|
|
1789
2320
|
const fullPath = path10__default.default.join(dir, file.name);
|
|
@@ -1812,7 +2343,7 @@ function getWorkspaceStoragePath(ide) {
|
|
|
1812
2343
|
} else {
|
|
1813
2344
|
const capitalizedPath = path10__default.default.join(HOME, ".config", appName, "User", "workspaceStorage");
|
|
1814
2345
|
const lowercasePath = path10__default.default.join(HOME, ".config", appNameLower, "User", "workspaceStorage");
|
|
1815
|
-
if (
|
|
2346
|
+
if (fs11__default.default.existsSync(capitalizedPath)) {
|
|
1816
2347
|
return capitalizedPath;
|
|
1817
2348
|
}
|
|
1818
2349
|
return lowercasePath;
|
|
@@ -1821,16 +2352,16 @@ function getWorkspaceStoragePath(ide) {
|
|
|
1821
2352
|
function scanWorkspaceStorage(ide) {
|
|
1822
2353
|
const projects = [];
|
|
1823
2354
|
const storagePath = getWorkspaceStoragePath(ide);
|
|
1824
|
-
if (!
|
|
2355
|
+
if (!fs11__default.default.existsSync(storagePath)) {
|
|
1825
2356
|
return projects;
|
|
1826
2357
|
}
|
|
1827
2358
|
try {
|
|
1828
|
-
const workspaces =
|
|
2359
|
+
const workspaces = fs11__default.default.readdirSync(storagePath);
|
|
1829
2360
|
for (const workspace of workspaces) {
|
|
1830
2361
|
const workspaceJsonPath = path10__default.default.join(storagePath, workspace, "workspace.json");
|
|
1831
|
-
if (
|
|
2362
|
+
if (fs11__default.default.existsSync(workspaceJsonPath)) {
|
|
1832
2363
|
try {
|
|
1833
|
-
const content =
|
|
2364
|
+
const content = fs11__default.default.readFileSync(workspaceJsonPath, "utf-8");
|
|
1834
2365
|
const data = JSON.parse(content);
|
|
1835
2366
|
if (data.folder && typeof data.folder === "string") {
|
|
1836
2367
|
let projectPath = data.folder;
|
|
@@ -1838,7 +2369,7 @@ function scanWorkspaceStorage(ide) {
|
|
|
1838
2369
|
projectPath = projectPath.replace("file://", "");
|
|
1839
2370
|
projectPath = decodeURIComponent(projectPath);
|
|
1840
2371
|
}
|
|
1841
|
-
if (
|
|
2372
|
+
if (fs11__default.default.existsSync(projectPath) && fs11__default.default.statSync(projectPath).isDirectory()) {
|
|
1842
2373
|
projects.push({
|
|
1843
2374
|
name: path10__default.default.basename(projectPath),
|
|
1844
2375
|
path: projectPath,
|
|
@@ -1862,11 +2393,11 @@ var scanIdeProjects = async () => {
|
|
|
1862
2393
|
const seenPaths = /* @__PURE__ */ new Set();
|
|
1863
2394
|
const addProject = (projectPath, ide) => {
|
|
1864
2395
|
try {
|
|
1865
|
-
const resolvedPath =
|
|
1866
|
-
if (
|
|
2396
|
+
const resolvedPath = fs11__default.default.realpathSync(projectPath);
|
|
2397
|
+
if (fs11__default.default.existsSync(resolvedPath) && fs11__default.default.statSync(resolvedPath).isDirectory() && !seenPaths.has(resolvedPath)) {
|
|
1867
2398
|
const isIdeProjectsDir = Object.values(IDE_PROJECTS_PATHS).some((ideDir) => {
|
|
1868
2399
|
try {
|
|
1869
|
-
return
|
|
2400
|
+
return fs11__default.default.realpathSync(ideDir) === resolvedPath;
|
|
1870
2401
|
} catch {
|
|
1871
2402
|
return false;
|
|
1872
2403
|
}
|
|
@@ -1893,30 +2424,30 @@ var scanIdeProjects = async () => {
|
|
|
1893
2424
|
}
|
|
1894
2425
|
for (const [ide, dirPath] of Object.entries(IDE_PROJECTS_PATHS)) {
|
|
1895
2426
|
if (ide === "cursor" || ide === "vscode") continue;
|
|
1896
|
-
if (
|
|
1897
|
-
const projects =
|
|
2427
|
+
if (fs11__default.default.existsSync(dirPath)) {
|
|
2428
|
+
const projects = fs11__default.default.readdirSync(dirPath);
|
|
1898
2429
|
projects.forEach((project) => {
|
|
1899
2430
|
const projectPath = path10__default.default.join(dirPath, project);
|
|
1900
2431
|
try {
|
|
1901
|
-
const stats =
|
|
2432
|
+
const stats = fs11__default.default.lstatSync(projectPath);
|
|
1902
2433
|
let actualPath = null;
|
|
1903
2434
|
if (stats.isSymbolicLink()) {
|
|
1904
|
-
actualPath =
|
|
2435
|
+
actualPath = fs11__default.default.realpathSync(projectPath);
|
|
1905
2436
|
} else if (stats.isFile()) {
|
|
1906
2437
|
try {
|
|
1907
|
-
let content =
|
|
2438
|
+
let content = fs11__default.default.readFileSync(projectPath, "utf-8").trim();
|
|
1908
2439
|
if (content.startsWith("~/") || content === "~") {
|
|
1909
2440
|
content = content.replace(/^~/, HOME);
|
|
1910
2441
|
}
|
|
1911
2442
|
const resolvedContent = path10__default.default.isAbsolute(content) ? content : path10__default.default.resolve(path10__default.default.dirname(projectPath), content);
|
|
1912
|
-
if (
|
|
1913
|
-
actualPath =
|
|
2443
|
+
if (fs11__default.default.existsSync(resolvedContent) && fs11__default.default.statSync(resolvedContent).isDirectory()) {
|
|
2444
|
+
actualPath = fs11__default.default.realpathSync(resolvedContent);
|
|
1914
2445
|
}
|
|
1915
2446
|
} catch {
|
|
1916
2447
|
return;
|
|
1917
2448
|
}
|
|
1918
2449
|
} else if (stats.isDirectory()) {
|
|
1919
|
-
actualPath =
|
|
2450
|
+
actualPath = fs11__default.default.realpathSync(projectPath);
|
|
1920
2451
|
}
|
|
1921
2452
|
if (actualPath) {
|
|
1922
2453
|
addProject(actualPath, ide);
|
|
@@ -1974,8 +2505,8 @@ var Snapshot;
|
|
|
1974
2505
|
const worktree = project.cwd;
|
|
1975
2506
|
const git = gitdir(projectId);
|
|
1976
2507
|
try {
|
|
1977
|
-
await
|
|
1978
|
-
const gitExists = await
|
|
2508
|
+
await fsp__namespace.default.mkdir(git, { recursive: true });
|
|
2509
|
+
const gitExists = await fsp__namespace.default.access(path10__default.default.join(git, "HEAD")).then(() => true).catch(() => false);
|
|
1979
2510
|
if (!gitExists) {
|
|
1980
2511
|
await runGit(`git init`, {
|
|
1981
2512
|
env: { GIT_DIR: git, GIT_WORK_TREE: worktree }
|
|
@@ -2060,7 +2591,7 @@ var Snapshot;
|
|
|
2060
2591
|
for (const file of newFiles) {
|
|
2061
2592
|
const fullPath = path10__default.default.join(worktree, file);
|
|
2062
2593
|
try {
|
|
2063
|
-
await
|
|
2594
|
+
await fsp__namespace.default.unlink(fullPath);
|
|
2064
2595
|
log.info("deleted newly created file", { file: fullPath });
|
|
2065
2596
|
} catch {
|
|
2066
2597
|
}
|
|
@@ -2097,7 +2628,7 @@ var Snapshot;
|
|
|
2097
2628
|
log.info("file existed in snapshot but checkout failed, keeping", { file });
|
|
2098
2629
|
} else {
|
|
2099
2630
|
log.info("file did not exist in snapshot, deleting", { file });
|
|
2100
|
-
await
|
|
2631
|
+
await fsp__namespace.default.unlink(file).catch(() => {
|
|
2101
2632
|
});
|
|
2102
2633
|
}
|
|
2103
2634
|
}
|
|
@@ -2151,10 +2682,10 @@ var Snapshot;
|
|
|
2151
2682
|
const lines = numstatResult.stdout.trim().split("\n").filter(Boolean);
|
|
2152
2683
|
for (const line of lines) {
|
|
2153
2684
|
const [additions, deletions, file] = line.split(" ");
|
|
2154
|
-
const
|
|
2685
|
+
const isBinaryFile2 = additions === "-" && deletions === "-";
|
|
2155
2686
|
let before = "";
|
|
2156
2687
|
let after = "";
|
|
2157
|
-
if (!
|
|
2688
|
+
if (!isBinaryFile2) {
|
|
2158
2689
|
const beforeResult = await runGit(
|
|
2159
2690
|
`git -c core.autocrlf=false --git-dir "${git}" --work-tree "${worktree}" show ${from}:${file}`,
|
|
2160
2691
|
{ cwd: worktree }
|
|
@@ -2279,19 +2810,19 @@ var HTML_ERROR = (error) => `<!doctype html>
|
|
|
2279
2810
|
</body>
|
|
2280
2811
|
</html>`;
|
|
2281
2812
|
function ensureCredentialsDir() {
|
|
2282
|
-
if (!
|
|
2283
|
-
|
|
2813
|
+
if (!fs11__default.default.existsSync(AMA_DIR)) {
|
|
2814
|
+
fs11__default.default.mkdirSync(AMA_DIR, { recursive: true });
|
|
2284
2815
|
}
|
|
2285
2816
|
}
|
|
2286
2817
|
function saveCredentials(credentials) {
|
|
2287
2818
|
ensureCredentialsDir();
|
|
2288
|
-
|
|
2819
|
+
fs11__default.default.writeFileSync(CREDENTIALS_PATH2, JSON.stringify(credentials, null, 2), "utf8");
|
|
2289
2820
|
}
|
|
2290
2821
|
function readCredentials() {
|
|
2291
|
-
if (!
|
|
2822
|
+
if (!fs11__default.default.existsSync(CREDENTIALS_PATH2)) {
|
|
2292
2823
|
return null;
|
|
2293
2824
|
}
|
|
2294
|
-
const raw =
|
|
2825
|
+
const raw = fs11__default.default.readFileSync(CREDENTIALS_PATH2, "utf8");
|
|
2295
2826
|
const parsed = JSON.parse(raw);
|
|
2296
2827
|
if (typeof parsed.accessToken !== "string" || typeof parsed.refreshToken !== "string" || typeof parsed.accountId !== "string" || typeof parsed.expiresAt !== "number") {
|
|
2297
2828
|
return null;
|
|
@@ -2567,8 +3098,8 @@ async function getCodexStatus() {
|
|
|
2567
3098
|
async function codexLogout() {
|
|
2568
3099
|
pendingOAuth = void 0;
|
|
2569
3100
|
stopOAuthServer();
|
|
2570
|
-
if (
|
|
2571
|
-
|
|
3101
|
+
if (fs11__default.default.existsSync(CREDENTIALS_PATH2)) {
|
|
3102
|
+
fs11__default.default.unlinkSync(CREDENTIALS_PATH2);
|
|
2572
3103
|
}
|
|
2573
3104
|
}
|
|
2574
3105
|
|
|
@@ -2855,18 +3386,21 @@ var toolCallSchema = zod.z.object({
|
|
|
2855
3386
|
parameters: zod.z.record(zod.z.string(), zod.z.unknown()).describe("Parameters for the tool")
|
|
2856
3387
|
});
|
|
2857
3388
|
zod.z.object({
|
|
2858
|
-
tool_calls: zod.z.array(toolCallSchema).min(1, "Provide at least one tool call").max(
|
|
3389
|
+
tool_calls: zod.z.array(toolCallSchema).min(1, "Provide at least one tool call").max(25, "Maximum of 25 tools allowed in batch").describe("Array of tool calls to execute in parallel")
|
|
2859
3390
|
});
|
|
2860
3391
|
var DISALLOWED_TOOLS = /* @__PURE__ */ new Set(["batch"]);
|
|
2861
3392
|
var MAX_CONCURRENCY = 5;
|
|
2862
3393
|
var PER_CALL_TIMEOUT = 3e4;
|
|
3394
|
+
var MAX_BATCH_SIZE = 25;
|
|
2863
3395
|
var batchableToolExecutors = {
|
|
2864
3396
|
deleteFile,
|
|
2865
3397
|
grep: grepTool,
|
|
2866
3398
|
glob: globTool,
|
|
2867
3399
|
listDirectory: list,
|
|
2868
3400
|
readFile: read_file,
|
|
2869
|
-
|
|
3401
|
+
bash: bashTool,
|
|
3402
|
+
stringReplace: apply_patch,
|
|
3403
|
+
editFile: editFiles
|
|
2870
3404
|
};
|
|
2871
3405
|
function withTimeout(promise, ms) {
|
|
2872
3406
|
return new Promise((resolve, reject) => {
|
|
@@ -2897,8 +3431,8 @@ async function runWithConcurrencyLimit(tasks, limit) {
|
|
|
2897
3431
|
}
|
|
2898
3432
|
var batchTool = async function(input, projectCwd) {
|
|
2899
3433
|
const { tool_calls } = input;
|
|
2900
|
-
const callsToExecute = tool_calls.slice(0,
|
|
2901
|
-
const discardedCalls = tool_calls.slice(
|
|
3434
|
+
const callsToExecute = tool_calls.slice(0, MAX_BATCH_SIZE);
|
|
3435
|
+
const discardedCalls = tool_calls.slice(MAX_BATCH_SIZE);
|
|
2902
3436
|
const executeCall = async (call) => {
|
|
2903
3437
|
const start = performance.now();
|
|
2904
3438
|
try {
|
|
@@ -2948,7 +3482,7 @@ var batchTool = async function(input, projectCwd) {
|
|
|
2948
3482
|
results.push({
|
|
2949
3483
|
tool: call.tool,
|
|
2950
3484
|
success: false,
|
|
2951
|
-
error:
|
|
3485
|
+
error: `Maximum of ${MAX_BATCH_SIZE} tools allowed in batch`,
|
|
2952
3486
|
durationMs: 0
|
|
2953
3487
|
});
|
|
2954
3488
|
}
|
|
@@ -2983,7 +3517,7 @@ var TOOL_TIMEOUTS = {
|
|
|
2983
3517
|
editFile: 15e3,
|
|
2984
3518
|
deleteFile: 1e4,
|
|
2985
3519
|
stringReplace: 15e3,
|
|
2986
|
-
|
|
3520
|
+
bash: 6e4,
|
|
2987
3521
|
batch: 12e4
|
|
2988
3522
|
};
|
|
2989
3523
|
function getTimeoutForTool(tool) {
|
|
@@ -3096,7 +3630,7 @@ var toolExecutors = {
|
|
|
3096
3630
|
listDirectory: list,
|
|
3097
3631
|
readFile: read_file,
|
|
3098
3632
|
stringReplace: apply_patch,
|
|
3099
|
-
|
|
3633
|
+
bash: bashTool,
|
|
3100
3634
|
batch: batchTool
|
|
3101
3635
|
};
|
|
3102
3636
|
function connectToServer(serverUrl = DEFAULT_SERVER_URL) {
|
|
@@ -3232,20 +3766,20 @@ function getCodeServerBin() {
|
|
|
3232
3766
|
}
|
|
3233
3767
|
function isCodeServerInstalled() {
|
|
3234
3768
|
const binPath = getCodeServerBin();
|
|
3235
|
-
return
|
|
3769
|
+
return fs11__default.default.existsSync(binPath);
|
|
3236
3770
|
}
|
|
3237
3771
|
async function installCodeServer() {
|
|
3238
3772
|
const { ext } = getPlatformInfo();
|
|
3239
3773
|
const downloadUrl = getDownloadUrl();
|
|
3240
3774
|
const tarballPath = path10__default.default.join(AMA_DIR, `code-server.${ext}`);
|
|
3241
|
-
if (!
|
|
3242
|
-
|
|
3775
|
+
if (!fs11__default.default.existsSync(AMA_DIR)) {
|
|
3776
|
+
fs11__default.default.mkdirSync(AMA_DIR, { recursive: true });
|
|
3243
3777
|
}
|
|
3244
|
-
if (!
|
|
3245
|
-
|
|
3778
|
+
if (!fs11__default.default.existsSync(CODE_DIR)) {
|
|
3779
|
+
fs11__default.default.mkdirSync(CODE_DIR, { recursive: true });
|
|
3246
3780
|
}
|
|
3247
|
-
if (!
|
|
3248
|
-
|
|
3781
|
+
if (!fs11__default.default.existsSync(STORAGE_DIR)) {
|
|
3782
|
+
fs11__default.default.mkdirSync(STORAGE_DIR, { recursive: true });
|
|
3249
3783
|
}
|
|
3250
3784
|
console.log(pc5__default.default.cyan(`downloading code-server v${CODE_SERVER_VERSION}...`));
|
|
3251
3785
|
console.log(pc5__default.default.gray(downloadUrl));
|
|
@@ -3254,13 +3788,13 @@ async function installCodeServer() {
|
|
|
3254
3788
|
throw new Error(`Failed to download code-server: ${response.statusText}`);
|
|
3255
3789
|
}
|
|
3256
3790
|
const buffer = await response.arrayBuffer();
|
|
3257
|
-
await
|
|
3791
|
+
await fs11__default.default.promises.writeFile(tarballPath, Buffer.from(buffer));
|
|
3258
3792
|
console.log(pc5__default.default.cyan("Extracting code-server..."));
|
|
3259
3793
|
await execAsync2(`tar -xzf ${tarballPath} -C ${CODE_DIR}`);
|
|
3260
|
-
await
|
|
3794
|
+
await fs11__default.default.promises.unlink(tarballPath);
|
|
3261
3795
|
const binPath = getCodeServerBin();
|
|
3262
|
-
if (
|
|
3263
|
-
await
|
|
3796
|
+
if (fs11__default.default.existsSync(binPath)) {
|
|
3797
|
+
await fs11__default.default.promises.chmod(binPath, 493);
|
|
3264
3798
|
}
|
|
3265
3799
|
console.log(pc5__default.default.green("code-server installed successfully"));
|
|
3266
3800
|
}
|
|
@@ -3285,42 +3819,55 @@ async function killExistingCodeServer() {
|
|
|
3285
3819
|
async function setupDefaultSettings() {
|
|
3286
3820
|
const userDir = path10__default.default.join(STORAGE_DIR, "User");
|
|
3287
3821
|
const settingsPath = path10__default.default.join(userDir, "settings.json");
|
|
3288
|
-
if (!
|
|
3289
|
-
|
|
3822
|
+
if (!fs11__default.default.existsSync(userDir)) {
|
|
3823
|
+
fs11__default.default.mkdirSync(userDir, { recursive: true });
|
|
3290
3824
|
}
|
|
3291
3825
|
const defaultSettings = {
|
|
3292
3826
|
// Disable signature verification for Open VSX extensions
|
|
3293
3827
|
"extensions.verifySignature": false,
|
|
3294
|
-
// Theme
|
|
3295
|
-
"workbench.colorTheme": "
|
|
3828
|
+
// Theme
|
|
3829
|
+
"workbench.colorTheme": "Vesper",
|
|
3296
3830
|
"workbench.startupEditor": "none",
|
|
3297
|
-
// Editor
|
|
3831
|
+
// Editor
|
|
3298
3832
|
"editor.fontSize": 14,
|
|
3299
3833
|
"editor.fontFamily": "'JetBrains Mono', 'Fira Code', Menlo, Monaco, 'Courier New', monospace",
|
|
3300
3834
|
"editor.minimap.enabled": false,
|
|
3301
3835
|
"editor.wordWrap": "on",
|
|
3302
|
-
|
|
3303
|
-
"
|
|
3304
|
-
"
|
|
3836
|
+
"editor.renderLineHighlight": "gutter",
|
|
3837
|
+
"editor.scrollbar.vertical": "auto",
|
|
3838
|
+
"editor.scrollbar.horizontal": "auto",
|
|
3839
|
+
"editor.overviewRulerBorder": false,
|
|
3840
|
+
"editor.hideCursorInOverviewRuler": true,
|
|
3841
|
+
"editor.guides.indentation": false,
|
|
3842
|
+
// Minimal UI
|
|
3843
|
+
"window.menuBarVisibility": "hidden",
|
|
3844
|
+
"window.commandCenter": false,
|
|
3845
|
+
"workbench.layoutControl.enabled": false,
|
|
3846
|
+
"workbench.activityBar.location": "default",
|
|
3847
|
+
"workbench.sideBar.location": "right",
|
|
3848
|
+
"workbench.editor.showTabs": "single",
|
|
3849
|
+
"workbench.statusBar.visible": false,
|
|
3850
|
+
"breadcrumbs.enabled": false
|
|
3305
3851
|
};
|
|
3306
3852
|
let existingSettings = {};
|
|
3307
|
-
if (
|
|
3853
|
+
if (fs11__default.default.existsSync(settingsPath)) {
|
|
3308
3854
|
try {
|
|
3309
|
-
const content = await
|
|
3855
|
+
const content = await fs11__default.default.promises.readFile(settingsPath, "utf-8");
|
|
3310
3856
|
existingSettings = JSON.parse(content);
|
|
3311
3857
|
} catch {
|
|
3312
3858
|
}
|
|
3313
3859
|
}
|
|
3314
3860
|
const mergedSettings = { ...defaultSettings, ...existingSettings };
|
|
3315
|
-
mergedSettings["workbench.colorTheme"] = "
|
|
3861
|
+
mergedSettings["workbench.colorTheme"] = "Vesper";
|
|
3316
3862
|
mergedSettings["extensions.verifySignature"] = false;
|
|
3317
|
-
await
|
|
3863
|
+
await fs11__default.default.promises.writeFile(settingsPath, JSON.stringify(mergedSettings, null, 2));
|
|
3318
3864
|
console.log(pc5__default.default.green("ama code-server settings configured"));
|
|
3319
3865
|
}
|
|
3320
3866
|
async function installExtensions() {
|
|
3321
3867
|
const binPath = getCodeServerBin();
|
|
3322
3868
|
const extensions = [
|
|
3323
|
-
"
|
|
3869
|
+
"raunofreiberg.vesper",
|
|
3870
|
+
"ziterz.codesandbox-black-theme"
|
|
3324
3871
|
];
|
|
3325
3872
|
for (const ext of extensions) {
|
|
3326
3873
|
try {
|
|
@@ -3335,7 +3882,7 @@ async function installExtensions() {
|
|
|
3335
3882
|
async function startCodeServer(cwd) {
|
|
3336
3883
|
const binPath = getCodeServerBin();
|
|
3337
3884
|
const workDir = cwd || process.cwd();
|
|
3338
|
-
if (!
|
|
3885
|
+
if (!fs11__default.default.existsSync(binPath)) {
|
|
3339
3886
|
throw new Error("ama code-server is not installed. Run installCodeServer() first.");
|
|
3340
3887
|
}
|
|
3341
3888
|
await killExistingCodeServer();
|
|
@@ -3343,12 +3890,12 @@ async function startCodeServer(cwd) {
|
|
|
3343
3890
|
await installExtensions();
|
|
3344
3891
|
const workspaceStoragePath = path10__default.default.join(STORAGE_DIR, "User", "workspaceStorage");
|
|
3345
3892
|
try {
|
|
3346
|
-
if (
|
|
3347
|
-
await
|
|
3893
|
+
if (fs11__default.default.existsSync(workspaceStoragePath)) {
|
|
3894
|
+
await fs11__default.default.promises.rm(workspaceStoragePath, { recursive: true, force: true });
|
|
3348
3895
|
}
|
|
3349
3896
|
const stateDbPath = path10__default.default.join(STORAGE_DIR, "User", "globalStorage", "state.vscdb");
|
|
3350
|
-
if (
|
|
3351
|
-
await
|
|
3897
|
+
if (fs11__default.default.existsSync(stateDbPath)) {
|
|
3898
|
+
await fs11__default.default.promises.unlink(stateDbPath);
|
|
3352
3899
|
}
|
|
3353
3900
|
} catch {
|
|
3354
3901
|
}
|
|
@@ -3379,11 +3926,11 @@ var __dirname$1 = path10.dirname(__filename$1);
|
|
|
3379
3926
|
var DAEMON_PID_FILE = path10__default.default.join(AMA_DIR, "daemon.pid");
|
|
3380
3927
|
var DAEMON_LOG_FILE = path10__default.default.join(AMA_DIR, "daemon.log");
|
|
3381
3928
|
function isDaemonRunning() {
|
|
3382
|
-
if (!
|
|
3929
|
+
if (!fs11__default.default.existsSync(DAEMON_PID_FILE)) {
|
|
3383
3930
|
return false;
|
|
3384
3931
|
}
|
|
3385
3932
|
try {
|
|
3386
|
-
const pid = Number(
|
|
3933
|
+
const pid = Number(fs11__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
|
|
3387
3934
|
process.kill(pid, 0);
|
|
3388
3935
|
return true;
|
|
3389
3936
|
} catch {
|
|
@@ -3391,30 +3938,30 @@ function isDaemonRunning() {
|
|
|
3391
3938
|
}
|
|
3392
3939
|
}
|
|
3393
3940
|
function stopDaemon() {
|
|
3394
|
-
if (!
|
|
3941
|
+
if (!fs11__default.default.existsSync(DAEMON_PID_FILE)) {
|
|
3395
3942
|
return false;
|
|
3396
3943
|
}
|
|
3397
3944
|
try {
|
|
3398
|
-
const pid = Number(
|
|
3945
|
+
const pid = Number(fs11__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
|
|
3399
3946
|
process.kill(pid, "SIGTERM");
|
|
3400
|
-
|
|
3947
|
+
fs11__default.default.unlinkSync(DAEMON_PID_FILE);
|
|
3401
3948
|
return true;
|
|
3402
3949
|
} catch (error) {
|
|
3403
3950
|
return false;
|
|
3404
3951
|
}
|
|
3405
3952
|
}
|
|
3406
3953
|
function startDaemon() {
|
|
3407
|
-
if (!
|
|
3408
|
-
|
|
3954
|
+
if (!fs11__default.default.existsSync(AMA_DIR)) {
|
|
3955
|
+
fs11__default.default.mkdirSync(AMA_DIR, { recursive: true });
|
|
3409
3956
|
}
|
|
3410
3957
|
if (isDaemonRunning()) {
|
|
3411
3958
|
stopDaemon();
|
|
3412
3959
|
}
|
|
3413
3960
|
const daemonScript = path10__default.default.join(__dirname$1, "lib", "daemon-entry.js");
|
|
3414
|
-
if (!
|
|
3961
|
+
if (!fs11__default.default.existsSync(daemonScript)) {
|
|
3415
3962
|
throw new Error(`Daemon entry script not found at: ${daemonScript}. Please rebuild the project.`);
|
|
3416
3963
|
}
|
|
3417
|
-
const logFd =
|
|
3964
|
+
const logFd = fs11__default.default.openSync(DAEMON_LOG_FILE, "a");
|
|
3418
3965
|
const daemon = child_process.spawn(process.execPath, [daemonScript], {
|
|
3419
3966
|
detached: true,
|
|
3420
3967
|
stdio: ["ignore", logFd, logFd],
|
|
@@ -3422,20 +3969,20 @@ function startDaemon() {
|
|
|
3422
3969
|
cwd: process.cwd()
|
|
3423
3970
|
});
|
|
3424
3971
|
daemon.unref();
|
|
3425
|
-
|
|
3426
|
-
|
|
3972
|
+
fs11__default.default.writeFileSync(DAEMON_PID_FILE, String(daemon.pid));
|
|
3973
|
+
fs11__default.default.closeSync(logFd);
|
|
3427
3974
|
}
|
|
3428
3975
|
function getDaemonPid() {
|
|
3429
|
-
if (!
|
|
3976
|
+
if (!fs11__default.default.existsSync(DAEMON_PID_FILE)) {
|
|
3430
3977
|
return null;
|
|
3431
3978
|
}
|
|
3432
3979
|
try {
|
|
3433
|
-
return Number(
|
|
3980
|
+
return Number(fs11__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
|
|
3434
3981
|
} catch {
|
|
3435
3982
|
return null;
|
|
3436
3983
|
}
|
|
3437
3984
|
}
|
|
3438
|
-
var VERSION = "0.0.
|
|
3985
|
+
var VERSION = "0.0.21";
|
|
3439
3986
|
var PROJECT_DIR = process.cwd();
|
|
3440
3987
|
var LOGO = `
|
|
3441
3988
|
__ _ _ __ ___ __ _
|
|
@@ -3632,11 +4179,11 @@ if (args[0] === "update") {
|
|
|
3632
4179
|
process.exit(1);
|
|
3633
4180
|
}
|
|
3634
4181
|
const resolvedPath = path10__default.default.resolve(projectPath);
|
|
3635
|
-
if (!
|
|
4182
|
+
if (!fs11__default.default.existsSync(resolvedPath)) {
|
|
3636
4183
|
console.error(pc5__default.default.red(`path does not exist: ${resolvedPath}`));
|
|
3637
4184
|
process.exit(1);
|
|
3638
4185
|
}
|
|
3639
|
-
if (!
|
|
4186
|
+
if (!fs11__default.default.statSync(resolvedPath).isDirectory()) {
|
|
3640
4187
|
console.error(pc5__default.default.red(`path is not a directory: ${resolvedPath}`));
|
|
3641
4188
|
process.exit(1);
|
|
3642
4189
|
}
|