amai 0.0.10 → 0.0.11

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 CHANGED
@@ -1,18 +1,18 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env bun
2
2
  'use strict';
3
3
 
4
4
  var pc5 = require('picocolors');
5
5
  var WebSocket = require('ws');
6
6
  var zod = require('zod');
7
- var fs5 = require('fs/promises');
8
7
  var path10 = require('path');
9
- var fs6 = require('fs');
8
+ var fs8 = require('fs');
10
9
  var os3 = require('os');
11
- var child_process = require('child_process');
12
- var util = require('util');
10
+ var fs7 = require('fs/promises');
13
11
  var hono = require('hono');
14
12
  var nodeServer = require('@hono/node-server');
15
13
  var cors = require('hono/cors');
14
+ var child_process = require('child_process');
15
+ var util = require('util');
16
16
  var url = require('url');
17
17
  var readline = require('readline');
18
18
 
@@ -21,10 +21,10 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
21
21
 
22
22
  var pc5__default = /*#__PURE__*/_interopDefault(pc5);
23
23
  var WebSocket__default = /*#__PURE__*/_interopDefault(WebSocket);
24
- var fs5__default = /*#__PURE__*/_interopDefault(fs5);
25
24
  var path10__default = /*#__PURE__*/_interopDefault(path10);
26
- var fs6__default = /*#__PURE__*/_interopDefault(fs6);
25
+ var fs8__default = /*#__PURE__*/_interopDefault(fs8);
27
26
  var os3__default = /*#__PURE__*/_interopDefault(os3);
27
+ var fs7__default = /*#__PURE__*/_interopDefault(fs7);
28
28
  var readline__default = /*#__PURE__*/_interopDefault(readline);
29
29
 
30
30
  var DEFAULT_SERVER_URL = "wss://ama-production-a628.up.railway.app";
@@ -42,14 +42,14 @@ var ProjectRegistry = class {
42
42
  }
43
43
  load() {
44
44
  try {
45
- if (fs6__default.default.existsSync(REGISTRY_FILE)) {
46
- const data = fs6__default.default.readFileSync(REGISTRY_FILE, "utf8");
45
+ if (fs8__default.default.existsSync(REGISTRY_FILE)) {
46
+ const data = fs8__default.default.readFileSync(REGISTRY_FILE, "utf8");
47
47
  const parsed = JSON.parse(data);
48
48
  if (!Array.isArray(parsed)) {
49
49
  console.error("Invalid project registry format: expected array, got", typeof parsed);
50
50
  const backupFile = REGISTRY_FILE + ".backup." + Date.now();
51
- fs6__default.default.copyFileSync(REGISTRY_FILE, backupFile);
52
- fs6__default.default.unlinkSync(REGISTRY_FILE);
51
+ fs8__default.default.copyFileSync(REGISTRY_FILE, backupFile);
52
+ fs8__default.default.unlinkSync(REGISTRY_FILE);
53
53
  return;
54
54
  }
55
55
  const projects = parsed;
@@ -62,11 +62,11 @@ var ProjectRegistry = class {
62
62
  }
63
63
  } catch (error) {
64
64
  console.error("Failed to load project registry:", error);
65
- if (fs6__default.default.existsSync(REGISTRY_FILE)) {
65
+ if (fs8__default.default.existsSync(REGISTRY_FILE)) {
66
66
  try {
67
67
  const backupFile = REGISTRY_FILE + ".backup." + Date.now();
68
- fs6__default.default.copyFileSync(REGISTRY_FILE, backupFile);
69
- fs6__default.default.unlinkSync(REGISTRY_FILE);
68
+ fs8__default.default.copyFileSync(REGISTRY_FILE, backupFile);
69
+ fs8__default.default.unlinkSync(REGISTRY_FILE);
70
70
  console.log("Corrupted registry file backed up and removed. Starting fresh.");
71
71
  } catch (backupError) {
72
72
  }
@@ -75,11 +75,11 @@ var ProjectRegistry = class {
75
75
  }
76
76
  save() {
77
77
  try {
78
- if (!fs6__default.default.existsSync(AMA_DIR)) {
79
- fs6__default.default.mkdirSync(AMA_DIR, { recursive: true });
78
+ if (!fs8__default.default.existsSync(AMA_DIR)) {
79
+ fs8__default.default.mkdirSync(AMA_DIR, { recursive: true });
80
80
  }
81
81
  const projects = Array.from(this.projects.values());
82
- fs6__default.default.writeFileSync(REGISTRY_FILE, JSON.stringify(projects, null, 2), "utf8");
82
+ fs8__default.default.writeFileSync(REGISTRY_FILE, JSON.stringify(projects, null, 2), "utf8");
83
83
  } catch (error) {
84
84
  console.error("Failed to save project registry:", error);
85
85
  }
@@ -168,6 +168,60 @@ zod.z.object({
168
168
  ),
169
169
  end_line_one_indexed: zod.z.number().optional().describe("The one-indexed line number to end reading at (inclusive).")
170
170
  });
171
+ async function readFileContent(absolute_file_path, relative_file_path, should_read_entire_file, start_line_one_indexed, end_line_one_indexed) {
172
+ const file = Bun.file(absolute_file_path);
173
+ const exists = await file.exists();
174
+ if (!exists) {
175
+ return {
176
+ success: false,
177
+ message: `File not found: ${relative_file_path}`,
178
+ error: "FILE_NOT_FOUND"
179
+ };
180
+ }
181
+ try {
182
+ const fileContent = await file.text();
183
+ const lines = fileContent.split(/\r?\n/);
184
+ const totalLines = lines.length;
185
+ if (should_read_entire_file) {
186
+ return {
187
+ success: true,
188
+ message: `Successfully read entire file: ${relative_file_path} (${totalLines} lines)`,
189
+ content: fileContent,
190
+ totalLines
191
+ };
192
+ }
193
+ const startIndex = start_line_one_indexed - 1;
194
+ if (startIndex >= totalLines) {
195
+ return {
196
+ success: false,
197
+ message: "start_line_one_indexed must be less than or equal to the total number of lines in the file",
198
+ error: "INVALID_LINE_RANGE"
199
+ };
200
+ }
201
+ const normalizedEnd = Math.min(end_line_one_indexed, totalLines);
202
+ const selectedLines = lines.slice(startIndex, normalizedEnd).join("\n");
203
+ const linesRead = normalizedEnd - start_line_one_indexed + 1;
204
+ return {
205
+ success: true,
206
+ message: `Successfully read lines ${start_line_one_indexed}-${normalizedEnd} from file: ${relative_file_path} (${linesRead} lines of ${totalLines} total)`,
207
+ content: selectedLines,
208
+ totalLines
209
+ };
210
+ } catch (error) {
211
+ if (error?.code === "EISDIR") {
212
+ return {
213
+ success: false,
214
+ message: `Path is not a file: ${relative_file_path}`,
215
+ error: "NOT_A_FILE"
216
+ };
217
+ }
218
+ return {
219
+ success: false,
220
+ message: `Failed to read file: ${relative_file_path}`,
221
+ error: "READ_ERROR"
222
+ };
223
+ }
224
+ }
171
225
  var read_file = async function(input, projectCwd) {
172
226
  const { relative_file_path, should_read_entire_file, start_line_one_indexed, end_line_one_indexed } = input;
173
227
  try {
@@ -208,6 +262,7 @@ var read_file = async function(input, projectCwd) {
208
262
  };
209
263
  }
210
264
  }
265
+ let absolute_file_path;
211
266
  if (projectCwd) {
212
267
  const validation = validatePath(relative_file_path, projectCwd);
213
268
  if (!validation.valid) {
@@ -217,128 +272,17 @@ var read_file = async function(input, projectCwd) {
217
272
  error: "ACCESS_DENIED"
218
273
  };
219
274
  }
220
- const absolute_file_path = validation.resolvedPath;
221
- try {
222
- const fileStats = await fs5.stat(absolute_file_path);
223
- if (!fileStats.isFile()) {
224
- return {
225
- success: false,
226
- message: `Path is not a file: ${relative_file_path}`,
227
- error: "NOT_A_FILE"
228
- };
229
- }
230
- } catch (error) {
231
- if (error?.code === "ENOENT") {
232
- return {
233
- success: false,
234
- message: `File not found: ${relative_file_path}`,
235
- error: "FILE_NOT_FOUND"
236
- };
237
- }
238
- return {
239
- success: false,
240
- message: `Failed to access file: ${relative_file_path}`,
241
- error: "READ_ERROR"
242
- };
243
- }
244
- try {
245
- const fileContent = await fs5.readFile(absolute_file_path, "utf-8");
246
- const lines = fileContent.split(/\r?\n/);
247
- const totalLines = lines.length;
248
- if (should_read_entire_file) {
249
- return {
250
- success: true,
251
- message: `Successfully read entire file: ${relative_file_path} (${totalLines} lines)`,
252
- content: fileContent,
253
- totalLines
254
- };
255
- }
256
- const startIndex = start_line_one_indexed - 1;
257
- if (startIndex >= totalLines) {
258
- return {
259
- success: false,
260
- message: "start_line_one_indexed must be less than or equal to the total number of lines in the file",
261
- error: "INVALID_LINE_RANGE"
262
- };
263
- }
264
- const normalizedEnd = Math.min(end_line_one_indexed, totalLines);
265
- const selectedLines = lines.slice(startIndex, normalizedEnd).join("\n");
266
- const linesRead = normalizedEnd - start_line_one_indexed + 1;
267
- return {
268
- success: true,
269
- message: `Successfully read lines ${start_line_one_indexed}-${normalizedEnd} from file: ${relative_file_path} (${linesRead} lines of ${totalLines} total)`,
270
- content: selectedLines,
271
- totalLines
272
- };
273
- } catch {
274
- return {
275
- success: false,
276
- message: `Failed to read file: ${relative_file_path}`,
277
- error: "READ_ERROR"
278
- };
279
- }
275
+ absolute_file_path = validation.resolvedPath;
280
276
  } else {
281
- const absolute_file_path = path10__default.default.resolve(relative_file_path);
282
- try {
283
- const fileStats = await fs5.stat(absolute_file_path);
284
- if (!fileStats.isFile()) {
285
- return {
286
- success: false,
287
- message: `Path is not a file: ${relative_file_path}`,
288
- error: "NOT_A_FILE"
289
- };
290
- }
291
- } catch (error) {
292
- if (error?.code === "ENOENT") {
293
- return {
294
- success: false,
295
- message: `File not found: ${relative_file_path}`,
296
- error: "FILE_NOT_FOUND"
297
- };
298
- }
299
- return {
300
- success: false,
301
- message: `Failed to access file: ${relative_file_path}`,
302
- error: "READ_ERROR"
303
- };
304
- }
305
- try {
306
- const fileContent = await fs5.readFile(absolute_file_path, "utf-8");
307
- const lines = fileContent.split(/\r?\n/);
308
- const totalLines = lines.length;
309
- if (should_read_entire_file) {
310
- return {
311
- success: true,
312
- message: `Successfully read entire file: ${relative_file_path} (${totalLines} lines)`,
313
- content: fileContent,
314
- totalLines
315
- };
316
- }
317
- const startIndex = start_line_one_indexed - 1;
318
- if (startIndex >= totalLines) {
319
- return {
320
- success: false,
321
- message: "start_line_one_indexed must be less than or equal to the total number of lines in the file",
322
- error: "INVALID_LINE_RANGE"
323
- };
324
- }
325
- const normalizedEnd = Math.min(end_line_one_indexed, totalLines);
326
- const selectedLines = lines.slice(startIndex, normalizedEnd).join("\n");
327
- const linesRead = normalizedEnd - start_line_one_indexed + 1;
328
- return {
329
- success: true,
330
- message: `Successfully read lines ${start_line_one_indexed}-${normalizedEnd} from file: ${relative_file_path} (${linesRead} lines of ${totalLines} total)`,
331
- content: selectedLines,
332
- totalLines
333
- };
334
- } catch {
335
- return {
336
- success: false,
337
- message: `Failed to read file: ${relative_file_path}`,
338
- error: "READ_ERROR"
339
- };
340
- }
341
- }
277
+ absolute_file_path = path10__default.default.resolve(relative_file_path);
278
+ }
279
+ return await readFileContent(
280
+ absolute_file_path,
281
+ relative_file_path,
282
+ should_read_entire_file,
283
+ start_line_one_indexed,
284
+ end_line_one_indexed
285
+ );
342
286
  } catch {
343
287
  return {
344
288
  success: false,
@@ -429,13 +373,13 @@ var Diff = class {
429
373
  editLength++;
430
374
  };
431
375
  if (callback) {
432
- (function exec4() {
376
+ (function exec3() {
433
377
  setTimeout(function() {
434
378
  if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
435
379
  return callback(void 0);
436
380
  }
437
381
  if (!execEditLength()) {
438
- exec4();
382
+ exec3();
439
383
  }
440
384
  }, 0);
441
385
  })();
@@ -662,17 +606,19 @@ var apply_patch = async function(input, projectCwd) {
662
606
  }
663
607
  const basePath = projectCwd || process.cwd();
664
608
  const absolute_file_path = resolveProjectPath(file_path, basePath);
609
+ const file = Bun.file(absolute_file_path);
610
+ const exists = await file.exists();
611
+ if (!exists) {
612
+ return {
613
+ success: false,
614
+ message: `File not found: ${file_path}`,
615
+ error: "FILE_NOT_FOUND"
616
+ };
617
+ }
665
618
  let fileContent;
666
619
  try {
667
- fileContent = await fs5.readFile(absolute_file_path, "utf-8");
620
+ fileContent = await file.text();
668
621
  } catch (error) {
669
- if (error?.code === "ENOENT") {
670
- return {
671
- success: false,
672
- message: `File not found: ${file_path}`,
673
- error: "FILE_NOT_FOUND"
674
- };
675
- }
676
622
  return {
677
623
  success: false,
678
624
  message: `Failed to read file: ${file_path}`,
@@ -696,7 +642,7 @@ var apply_patch = async function(input, projectCwd) {
696
642
  }
697
643
  const newContent = fileContent.replace(old_string, new_string);
698
644
  try {
699
- await fs5.writeFile(absolute_file_path, newContent, "utf-8");
645
+ await Bun.write(absolute_file_path, newContent);
700
646
  const diffStats = calculateDiffStats(fileContent, newContent);
701
647
  return {
702
648
  success: true,
@@ -742,28 +688,27 @@ var editFiles = async function(input, projectCwd) {
742
688
  const basePath = projectCwd || process.cwd();
743
689
  const filePath = resolveProjectPath(target_file, basePath);
744
690
  const dirPath = path10__default.default.dirname(filePath);
745
- await fs5.mkdir(dirPath, { recursive: true });
691
+ await fs7.mkdir(dirPath, { recursive: true });
746
692
  let isNewFile = providedNewFile;
747
693
  let existingContent = "";
694
+ const file = Bun.file(filePath);
748
695
  if (isNewFile === void 0) {
749
- try {
750
- existingContent = await fs6__default.default.promises.readFile(filePath, "utf-8");
696
+ const exists = await file.exists();
697
+ if (exists) {
698
+ existingContent = await file.text();
751
699
  isNewFile = false;
752
- } catch (error) {
700
+ } else {
753
701
  isNewFile = true;
754
702
  }
755
703
  } else if (!isNewFile) {
756
- try {
757
- existingContent = await fs6__default.default.promises.readFile(filePath, "utf-8");
758
- } catch (error) {
704
+ const exists = await file.exists();
705
+ if (exists) {
706
+ existingContent = await file.text();
707
+ } else {
759
708
  isNewFile = true;
760
709
  }
761
710
  }
762
- try {
763
- await fs6__default.default.promises.writeFile(filePath, content);
764
- } catch (writeError) {
765
- throw writeError;
766
- }
711
+ await Bun.write(filePath, content);
767
712
  const diffStats = calculateDiffStats(existingContent, content);
768
713
  if (isNewFile) {
769
714
  return {
@@ -826,25 +771,31 @@ var deleteFile = async function(input, projectCwd) {
826
771
  error: "INVALID_FILE_PATH"
827
772
  };
828
773
  }
829
- const originalContent = await fs5.readFile(absolute_file_path);
830
- if (originalContent === void 0) {
774
+ const file = Bun.file(absolute_file_path);
775
+ const exists = await file.exists();
776
+ if (!exists) {
831
777
  return {
832
778
  success: false,
833
- message: `Failed to read file before deletion: ${realPath}`,
834
- error: "READ_ERROR"
779
+ message: `File not found: ${realPath}`,
780
+ error: "FILE_NOT_FOUND"
835
781
  };
836
782
  }
837
- const deleteResult = await fs5.unlink(absolute_file_path).catch(() => {
783
+ let originalContent;
784
+ try {
785
+ originalContent = await file.text();
786
+ } catch {
838
787
  return {
839
788
  success: false,
840
789
  message: `Failed to read file before deletion: ${realPath}`,
841
- error: "DELETE_ERROR"
790
+ error: "READ_ERROR"
842
791
  };
843
- });
844
- if (!deleteResult?.success) {
792
+ }
793
+ try {
794
+ await fs7.unlink(absolute_file_path);
795
+ } catch {
845
796
  return {
846
797
  success: false,
847
- message: `Failed to delete file before deletion: ${realPath}`,
798
+ message: `Failed to delete file: ${realPath}`,
848
799
  error: "DELETE_ERROR"
849
800
  };
850
801
  }
@@ -861,72 +812,218 @@ var deleteFile = async function(input, projectCwd) {
861
812
  };
862
813
  }
863
814
  };
815
+ var GREP_LIMITS = {
816
+ DEFAULT_MAX_MATCHES: 200,
817
+ MAX_LINE_LENGTH: 500,
818
+ MAX_TOTAL_OUTPUT_SIZE: 1 * 1024 * 1024,
819
+ TRUNCATION_MESSAGE: "\n[Results truncated due to size limits. Use more specific patterns or file filters to narrow your search.]"
820
+ };
864
821
  zod.z.object({
865
822
  query: zod.z.string().describe("The regex pattern to search for"),
866
823
  options: zod.z.object({
867
824
  includePattern: zod.z.string().optional().describe('Glob pattern for files to include (e.g., "*.ts")'),
868
825
  excludePattern: zod.z.string().optional().describe("Glob pattern for files to exclude"),
869
- caseSensitive: zod.z.boolean().optional().describe("Whether the search should be case sensitive")
870
- })
826
+ caseSensitive: zod.z.boolean().optional().describe("Whether the search should be case sensitive"),
827
+ path: zod.z.string().optional().describe("Subdirectory to search in")
828
+ }).optional()
871
829
  });
872
- var execAsync = util.promisify(child_process.exec);
830
+ async function getRipgrepPath() {
831
+ const paths = [
832
+ "/opt/homebrew/bin/rg",
833
+ "/usr/local/bin/rg",
834
+ "/usr/bin/rg",
835
+ "rg"
836
+ // Fallback to PATH
837
+ ];
838
+ for (const rgPath of paths) {
839
+ try {
840
+ const proc = Bun.spawn(["which", rgPath], { stdout: "pipe", stderr: "pipe" });
841
+ await proc.exited;
842
+ if (proc.exitCode === 0) {
843
+ return rgPath;
844
+ }
845
+ } catch {
846
+ continue;
847
+ }
848
+ }
849
+ return "rg";
850
+ }
851
+ async function getMtimesBatched(files) {
852
+ const mtimeMap = /* @__PURE__ */ new Map();
853
+ const BATCH_SIZE = 50;
854
+ for (let i = 0; i < files.length; i += BATCH_SIZE) {
855
+ const batch = files.slice(i, i + BATCH_SIZE);
856
+ const results = await Promise.all(
857
+ batch.map(async (filePath) => {
858
+ const mtime = await Bun.file(filePath).stat().then((stats) => stats.mtime.getTime()).catch(() => 0);
859
+ return { path: filePath, mtime };
860
+ })
861
+ );
862
+ results.forEach(({ path: path16, mtime }) => mtimeMap.set(path16, mtime));
863
+ }
864
+ return mtimeMap;
865
+ }
873
866
  var grepTool = async function(input, projectCwd) {
874
867
  const { query, options } = input;
868
+ if (!query || query.trim() === "") {
869
+ return {
870
+ success: false,
871
+ message: "Missing required parameter: query",
872
+ error: "MISSING_QUERY"
873
+ };
874
+ }
875
875
  try {
876
- const { includePattern, excludePattern: excludePattern2, caseSensitive } = options || {};
877
- const searchDir = projectCwd || process.cwd();
878
- if (projectCwd && !path10__default.default.isAbsolute(projectCwd)) {
876
+ const { includePattern, excludePattern, caseSensitive, path: subPath } = options || {};
877
+ let searchDir = projectCwd || process.cwd();
878
+ if (subPath) {
879
+ searchDir = path10__default.default.isAbsolute(subPath) ? subPath : path10__default.default.resolve(searchDir, subPath);
880
+ if (projectCwd) {
881
+ const validation = validatePath(subPath, projectCwd);
882
+ if (!validation.valid) {
883
+ return {
884
+ success: false,
885
+ message: validation.error || "Path validation failed",
886
+ error: "ACCESS_DENIED"
887
+ };
888
+ }
889
+ }
890
+ }
891
+ if (!fs8__default.default.existsSync(searchDir)) {
879
892
  return {
880
893
  success: false,
881
- message: "Invalid project directory",
882
- error: "INVALID_PROJECT_DIR"
894
+ message: `Directory not found: ${searchDir}`,
895
+ error: "DIR_NOT_FOUND"
883
896
  };
884
897
  }
885
- let command = `rg -n --with-filename "${query}"`;
886
- if (caseSensitive) {
887
- command += " -i";
898
+ const rgPath = await getRipgrepPath();
899
+ const args2 = [
900
+ "-n",
901
+ // Line numbers
902
+ "--with-filename",
903
+ // Always show filename
904
+ "--no-heading",
905
+ // Don't group by file
906
+ "--color=never",
907
+ // No ANSI colors
908
+ "--max-count=100",
909
+ // Max matches per file
910
+ "--max-columns=1000"
911
+ // Truncate long lines
912
+ ];
913
+ if (!caseSensitive) {
914
+ args2.push("-i");
888
915
  }
889
916
  if (includePattern) {
890
- command += ` --glob "${includePattern}"`;
891
- }
892
- if (excludePattern2) {
893
- command += ` --glob "!${excludePattern2}"`;
894
- }
895
- command += ` --max-count 50`;
896
- command += ` "${searchDir}"`;
897
- const { stdout } = await execAsync(command);
898
- const rawMatches = stdout.trim().split("\n").filter((line) => line.length > 0);
899
- const detailedMatches = [];
900
- const matches = [];
901
- for (const rawMatch of rawMatches) {
902
- const colonIndex = rawMatch.indexOf(":");
903
- const secondColonIndex = rawMatch.indexOf(":", colonIndex + 1);
904
- if (colonIndex > 0 && secondColonIndex > colonIndex) {
905
- const file = rawMatch.substring(0, colonIndex);
906
- const lineNumber = parseInt(rawMatch.substring(colonIndex + 1, secondColonIndex), 10);
907
- let content = rawMatch.substring(secondColonIndex + 1);
908
- if (content.length > 250) {
909
- content = content.substring(0, 250) + "...";
917
+ args2.push("--glob", includePattern);
918
+ }
919
+ if (excludePattern) {
920
+ args2.push("--glob", `!${excludePattern}`);
921
+ }
922
+ args2.push("--glob", "!node_modules/**");
923
+ args2.push("--glob", "!.git/**");
924
+ args2.push("--glob", "!dist/**");
925
+ args2.push("--glob", "!build/**");
926
+ args2.push("--glob", "!*.min.js");
927
+ args2.push("--glob", "!*.min.css");
928
+ args2.push("--glob", "!package-lock.json");
929
+ args2.push("--glob", "!yarn.lock");
930
+ args2.push("--glob", "!bun.lockb");
931
+ args2.push("--regexp", query);
932
+ args2.push(searchDir);
933
+ const proc = Bun.spawn([rgPath, ...args2], {
934
+ stdout: "pipe",
935
+ stderr: "pipe"
936
+ });
937
+ const stdout = await new Response(proc.stdout).text();
938
+ const stderr = await new Response(proc.stderr).text();
939
+ const exitCode = await proc.exited;
940
+ if (exitCode === 1) {
941
+ return {
942
+ success: true,
943
+ matches: [],
944
+ detailedMatches: [],
945
+ query,
946
+ matchCount: 0,
947
+ message: `No matches found for pattern: ${query}`
948
+ };
949
+ }
950
+ if (exitCode !== 0) {
951
+ return {
952
+ success: false,
953
+ message: `Ripgrep error: ${stderr || "Unknown error"}`,
954
+ error: "GREP_EXEC_ERROR"
955
+ };
956
+ }
957
+ const lines = stdout.trim().split("\n").filter((line) => line.length > 0);
958
+ const rawMatches = [];
959
+ const uniqueFiles = /* @__PURE__ */ new Set();
960
+ for (const line of lines) {
961
+ const firstColon = line.indexOf(":");
962
+ const secondColon = line.indexOf(":", firstColon + 1);
963
+ if (firstColon > 0 && secondColon > firstColon) {
964
+ const file = line.substring(0, firstColon);
965
+ const lineNumber = parseInt(line.substring(firstColon + 1, secondColon), 10);
966
+ let content = line.substring(secondColon + 1);
967
+ if (content.length > GREP_LIMITS.MAX_LINE_LENGTH) {
968
+ content = content.substring(0, GREP_LIMITS.MAX_LINE_LENGTH) + "...";
910
969
  }
911
- detailedMatches.push({
970
+ rawMatches.push({
912
971
  file,
913
972
  lineNumber,
914
- content
973
+ content: content.trim(),
974
+ mtime: 0
915
975
  });
916
- matches.push(`${file}:${lineNumber}:${content}`);
917
- } else {
918
- matches.push(rawMatch);
976
+ uniqueFiles.add(file);
919
977
  }
920
978
  }
979
+ const mtimeMap = await getMtimesBatched(Array.from(uniqueFiles));
980
+ for (const match of rawMatches) {
981
+ match.mtime = mtimeMap.get(match.file) || 0;
982
+ }
983
+ rawMatches.sort((a, b) => {
984
+ if (b.mtime !== a.mtime) {
985
+ return b.mtime - a.mtime;
986
+ }
987
+ return a.file.localeCompare(b.file);
988
+ });
989
+ const truncated = rawMatches.length > GREP_LIMITS.DEFAULT_MAX_MATCHES;
990
+ const finalMatches = truncated ? rawMatches.slice(0, GREP_LIMITS.DEFAULT_MAX_MATCHES) : rawMatches;
991
+ const detailedMatches = finalMatches.map((m) => ({
992
+ file: m.file,
993
+ lineNumber: m.lineNumber,
994
+ content: m.content
995
+ }));
996
+ const matches = finalMatches.map(
997
+ (m) => `${m.file}:${m.lineNumber}:${m.content}`
998
+ );
999
+ const groupedOutput = [`Found ${finalMatches.length} matches`];
1000
+ let currentFile = "";
1001
+ for (const match of finalMatches) {
1002
+ if (currentFile !== match.file) {
1003
+ if (currentFile !== "") {
1004
+ groupedOutput.push("");
1005
+ }
1006
+ currentFile = match.file;
1007
+ groupedOutput.push(`${match.file}:`);
1008
+ }
1009
+ groupedOutput.push(` Line ${match.lineNumber}: ${match.content}`);
1010
+ }
1011
+ if (truncated) {
1012
+ groupedOutput.push("");
1013
+ groupedOutput.push(GREP_LIMITS.TRUNCATION_MESSAGE);
1014
+ }
921
1015
  return {
922
1016
  success: true,
923
1017
  matches,
924
1018
  detailedMatches,
925
1019
  query,
926
- matchCount: matches.length,
927
- message: `Found ${matches.length} matches for pattern: ${query}`
1020
+ matchCount: finalMatches.length,
1021
+ truncated,
1022
+ message: `Found ${finalMatches.length} matches for pattern: ${query}`,
1023
+ content: groupedOutput.join("\n")
928
1024
  };
929
1025
  } catch (error) {
1026
+ console.error("[grep] error:", error);
930
1027
  return {
931
1028
  success: false,
932
1029
  message: error?.message || String(error),
@@ -935,9 +1032,25 @@ var grepTool = async function(input, projectCwd) {
935
1032
  }
936
1033
  };
937
1034
  zod.z.object({
938
- pattern: zod.z.string().describe('Glob pattern (e.g., "**/*.js")'),
939
- path: zod.z.string().optional().describe("Relative directory path to search in")
1035
+ pattern: zod.z.string().describe('Glob pattern to match files (e.g., "**/*.js", "src/**/*.ts", "*.json"). Supports standard glob syntax with *, **, and ? wildcards'),
1036
+ path: zod.z.string().optional().describe("Optional relative directory path within the project to limit the search scope. If not provided, searches from the project root")
940
1037
  });
1038
+ var RESULT_LIMIT = 100;
1039
+ var MTIME_BATCH_SIZE = 50;
1040
+ async function getMtimesBatched2(files) {
1041
+ const results = [];
1042
+ for (let i = 0; i < files.length; i += MTIME_BATCH_SIZE) {
1043
+ const batch = files.slice(i, i + MTIME_BATCH_SIZE);
1044
+ const batchResults = await Promise.all(
1045
+ batch.map(async (filePath) => {
1046
+ const mtime = await Bun.file(filePath).stat().then((stats) => stats.mtime.getTime()).catch(() => 0);
1047
+ return { path: filePath, mtime };
1048
+ })
1049
+ );
1050
+ results.push(...batchResults);
1051
+ }
1052
+ return results;
1053
+ }
941
1054
  var globTool = async function(input, projectCwd) {
942
1055
  const { pattern, path: inputPath } = input;
943
1056
  if (!pattern) {
@@ -950,6 +1063,13 @@ var globTool = async function(input, projectCwd) {
950
1063
  try {
951
1064
  const basePath = projectCwd || process.cwd();
952
1065
  const searchPath = inputPath ? resolveProjectPath(inputPath, basePath) : basePath;
1066
+ if (!fs8__default.default.existsSync(searchPath)) {
1067
+ return {
1068
+ success: false,
1069
+ message: `Directory not found: ${searchPath}`,
1070
+ error: "DIR_NOT_FOUND"
1071
+ };
1072
+ }
953
1073
  if (projectCwd && inputPath) {
954
1074
  const validation = validatePath(inputPath, projectCwd);
955
1075
  if (!validation.valid) {
@@ -960,21 +1080,49 @@ var globTool = async function(input, projectCwd) {
960
1080
  };
961
1081
  }
962
1082
  }
963
- const filesGenerator = fs5.glob(pattern, {
964
- cwd: searchPath
965
- });
1083
+ const glob = new Bun.Glob(pattern);
966
1084
  const files = [];
967
- for await (const file of filesGenerator) {
968
- files.push(file);
1085
+ let truncated = false;
1086
+ for await (const match of glob.scan({
1087
+ cwd: searchPath,
1088
+ absolute: true,
1089
+ onlyFiles: true,
1090
+ followSymlinks: false
1091
+ })) {
1092
+ if (match.includes("/node_modules/") || match.includes("/.git/")) {
1093
+ continue;
1094
+ }
1095
+ if (files.length >= RESULT_LIMIT) {
1096
+ truncated = true;
1097
+ break;
1098
+ }
1099
+ files.push(match);
1100
+ }
1101
+ const filesWithMtime = await getMtimesBatched2(files);
1102
+ filesWithMtime.sort((a, b) => b.mtime - a.mtime);
1103
+ const output = [];
1104
+ if (filesWithMtime.length === 0) {
1105
+ output.push("No files found");
1106
+ } else {
1107
+ output.push(...filesWithMtime.map((f) => f.path));
1108
+ if (truncated) {
1109
+ output.push("");
1110
+ output.push("(Results are truncated. Consider using a more specific path or pattern.)");
1111
+ }
969
1112
  }
970
1113
  const searchLocation = inputPath ? ` in "${inputPath}"` : " in current directory";
971
- const message = `Found ${files.length} matches for pattern "${pattern}"${searchLocation}`;
1114
+ const message = `Found ${filesWithMtime.length} matches for pattern "${pattern}"${searchLocation}`;
972
1115
  return {
973
1116
  success: true,
974
1117
  message,
975
- content: files
1118
+ metadata: {
1119
+ count: filesWithMtime.length,
1120
+ truncated
1121
+ },
1122
+ content: output.join("\n")
976
1123
  };
977
1124
  } catch (error) {
1125
+ console.error("[glob] error:", error);
978
1126
  return {
979
1127
  success: false,
980
1128
  message: `Failed to find files matching pattern: ${pattern}`,
@@ -982,59 +1130,120 @@ var globTool = async function(input, projectCwd) {
982
1130
  };
983
1131
  }
984
1132
  };
985
- var excludePatterns = [
986
- "node_modules/",
987
- "__pycache__/",
988
- ".git/",
989
- "dist/",
990
- "build/",
991
- "target/",
992
- "vendor/",
993
- "bin/",
994
- "obj/",
995
- ".idea/",
996
- ".vscode/",
997
- ".zig-cache/",
1133
+ var IGNORE_PATTERNS = [
1134
+ "node_modules",
1135
+ "__pycache__",
1136
+ ".git",
1137
+ "dist",
1138
+ "build",
1139
+ "target",
1140
+ "vendor",
1141
+ "bin",
1142
+ "obj",
1143
+ ".idea",
1144
+ ".vscode",
1145
+ ".zig-cache",
998
1146
  "zig-out",
999
1147
  ".coverage",
1000
- "coverage/",
1001
- "vendor/",
1002
- "tmp/",
1003
- "temp/",
1004
- ".cache/",
1005
- "cache/",
1006
- "logs/",
1007
- ".venv/",
1008
- "venv/",
1009
- "env/"
1148
+ "coverage",
1149
+ "tmp",
1150
+ "temp",
1151
+ ".cache",
1152
+ "cache",
1153
+ "logs",
1154
+ ".venv",
1155
+ "venv",
1156
+ "env",
1157
+ ".next",
1158
+ ".turbo",
1159
+ ".vercel",
1160
+ ".output"
1010
1161
  ];
1011
- var excludePattern = excludePatterns.join("|");
1162
+ var RESULT_LIMIT2 = 500;
1163
+ var MTIME_BATCH_SIZE2 = 50;
1012
1164
  zod.z.object({
1013
- path: zod.z.string().optional(),
1014
- recursive: zod.z.boolean().optional().describe("Whether to list files recursively"),
1015
- maxDepth: zod.z.number().optional().describe("Maximum recursion depth (default: unlimited)"),
1165
+ path: zod.z.string().optional().describe("Relative path to the directory to list"),
1166
+ recursive: zod.z.boolean().optional().describe("Whether to list files recursively (default: true)"),
1167
+ maxDepth: zod.z.number().optional().describe("Maximum recursion depth (default: 3)"),
1016
1168
  pattern: zod.z.string().optional().describe("File extension (e.g., '.ts') or glob-like pattern"),
1017
- includeDirectories: zod.z.boolean().optional().describe("Whether to include directories in results (default: true)"),
1018
- includeFiles: zod.z.boolean().optional().describe("Whether to include files in results (default: true)")
1169
+ showHidden: zod.z.boolean().optional().describe("Whether to show hidden files (default: false)")
1019
1170
  });
1020
- var list = async function(input, projectCwd) {
1021
- const { path: relativePath, recursive, maxDepth, pattern, includeDirectories, includeFiles } = input;
1022
- if (maxDepth !== void 0) {
1023
- if (!Number.isInteger(maxDepth) || maxDepth < 0) {
1024
- return {
1025
- success: false,
1026
- message: "maxDepth must be a non-negative integer",
1027
- error: "INVALID_MAX_DEPTH"
1028
- };
1171
+ function shouldIgnore(name, showHidden) {
1172
+ if (!showHidden && name.startsWith(".") && name !== ".") {
1173
+ return true;
1174
+ }
1175
+ return IGNORE_PATTERNS.includes(name);
1176
+ }
1177
+ function matchPattern(name, pattern) {
1178
+ if (!pattern) return true;
1179
+ if (pattern.startsWith(".") && !pattern.includes("*")) {
1180
+ return name.endsWith(pattern);
1181
+ }
1182
+ const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
1183
+ const regex = new RegExp(`^${escaped}$`, "i");
1184
+ return regex.test(name);
1185
+ }
1186
+ async function getMtimesBatched3(entries) {
1187
+ for (let i = 0; i < entries.length; i += MTIME_BATCH_SIZE2) {
1188
+ const batch = entries.slice(i, i + MTIME_BATCH_SIZE2);
1189
+ await Promise.all(
1190
+ batch.map(async (entry) => {
1191
+ entry.mtime = await Bun.file(entry.absolutePath).stat().then((stats) => stats.mtime.getTime()).catch(() => 0);
1192
+ })
1193
+ );
1194
+ }
1195
+ }
1196
+ function buildTreeOutput(entries, basePath) {
1197
+ const tree = /* @__PURE__ */ new Map();
1198
+ for (const entry of entries) {
1199
+ const dir = path10__default.default.dirname(entry.relativePath);
1200
+ const dirKey = dir === "." ? "" : dir;
1201
+ if (!tree.has(dirKey)) {
1202
+ tree.set(dirKey, []);
1203
+ }
1204
+ tree.get(dirKey).push(entry);
1205
+ }
1206
+ for (const [, items] of tree) {
1207
+ items.sort((a, b) => {
1208
+ if (a.type !== b.type) {
1209
+ return a.type === "directory" ? -1 : 1;
1210
+ }
1211
+ return a.name.localeCompare(b.name);
1212
+ });
1213
+ }
1214
+ const lines = [`${basePath}/`];
1215
+ function renderLevel(dirPath, indent) {
1216
+ const items = tree.get(dirPath) || [];
1217
+ for (let i = 0; i < items.length; i++) {
1218
+ const item = items[i];
1219
+ const isLast = i === items.length - 1;
1220
+ const prefix = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
1221
+ const childIndent = indent + (isLast ? " " : "\u2502 ");
1222
+ if (item.type === "directory") {
1223
+ lines.push(`${indent}${prefix}${item.name}/`);
1224
+ const childPath = dirPath ? `${dirPath}/${item.name}` : item.name;
1225
+ renderLevel(childPath, childIndent);
1226
+ } else {
1227
+ lines.push(`${indent}${prefix}${item.name}`);
1228
+ }
1029
1229
  }
1030
1230
  }
1031
- const includeFilesNormalized = includeFiles ?? true;
1032
- const includeDirectoriesNormalized = includeDirectories ?? true;
1033
- if (!includeFilesNormalized && !includeDirectoriesNormalized) {
1231
+ renderLevel("", "");
1232
+ return lines.join("\n");
1233
+ }
1234
+ var list = async function(input, projectCwd) {
1235
+ const {
1236
+ path: relativePath,
1237
+ recursive = true,
1238
+ maxDepth = 3,
1239
+ pattern,
1240
+ showHidden = false
1241
+ } = input;
1242
+ if (maxDepth !== void 0 && (!Number.isInteger(maxDepth) || maxDepth < 0)) {
1034
1243
  return {
1035
1244
  success: false,
1036
- message: "At least one of includeFiles or includeDirectories must be true",
1037
- error: "INVALID_INCLUDE_OPTIONS"
1245
+ message: "maxDepth must be a non-negative integer",
1246
+ error: "INVALID_MAX_DEPTH"
1038
1247
  };
1039
1248
  }
1040
1249
  try {
@@ -1050,88 +1259,119 @@ var list = async function(input, projectCwd) {
1050
1259
  };
1051
1260
  }
1052
1261
  }
1053
- try {
1054
- await fs5.access(absolutePath);
1055
- } catch {
1262
+ if (!fs8__default.default.existsSync(absolutePath)) {
1056
1263
  return {
1057
1264
  success: false,
1058
- message: `File does not exist: ${absolutePath}`,
1059
- error: "FILE_DOES_NOT_EXIST"
1265
+ message: `Directory not found: ${absolutePath}`,
1266
+ error: "DIR_NOT_FOUND"
1060
1267
  };
1061
1268
  }
1062
- const isDir = (await fs5.stat(absolutePath)).isDirectory();
1063
- if (!isDir) {
1269
+ const stats = fs8__default.default.statSync(absolutePath);
1270
+ if (!stats.isDirectory()) {
1064
1271
  return {
1065
1272
  success: false,
1066
- message: `File is not a directory: ${absolutePath}`,
1067
- error: "FILE_IS_NOT_A_DIRECTORY"
1273
+ message: `Path is not a directory: ${absolutePath}`,
1274
+ error: "NOT_A_DIRECTORY"
1068
1275
  };
1069
1276
  }
1070
1277
  const collected = [];
1071
- const patternMatcher = (() => {
1072
- if (!pattern) return null;
1073
- if (pattern.startsWith(".") && !pattern.includes("*") && !pattern.includes("?")) {
1074
- return (entryName) => entryName.endsWith(pattern);
1075
- }
1076
- const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
1077
- const regex = new RegExp(`^${escaped}$`);
1078
- return (entryName) => regex.test(entryName);
1079
- })();
1080
- const matchPattern = (entryName) => {
1081
- if (!patternMatcher) return true;
1082
- return patternMatcher(entryName);
1083
- };
1084
- const maxDepthNormalized = recursive ? maxDepth ?? Infinity : 0;
1278
+ let truncated = false;
1085
1279
  const walk = async (currentDir, depth) => {
1086
- const entries = await fs5.readdir(currentDir, { withFileTypes: true });
1280
+ if (collected.length >= RESULT_LIMIT2) {
1281
+ truncated = true;
1282
+ return;
1283
+ }
1284
+ let entries;
1285
+ try {
1286
+ entries = fs8__default.default.readdirSync(currentDir, { withFileTypes: true });
1287
+ } catch {
1288
+ return;
1289
+ }
1290
+ entries.sort((a, b) => {
1291
+ if (a.isDirectory() !== b.isDirectory()) {
1292
+ return a.isDirectory() ? -1 : 1;
1293
+ }
1294
+ return a.name.localeCompare(b.name);
1295
+ });
1087
1296
  for (const entry of entries) {
1297
+ if (collected.length >= RESULT_LIMIT2) {
1298
+ truncated = true;
1299
+ break;
1300
+ }
1301
+ if (shouldIgnore(entry.name, showHidden)) {
1302
+ continue;
1303
+ }
1088
1304
  const entryAbsolutePath = path10__default.default.join(currentDir, entry.name);
1089
- const entryRelativePath = path10__default.default.relative(absolutePath, entryAbsolutePath) || ".";
1305
+ const entryRelativePath = path10__default.default.relative(absolutePath, entryAbsolutePath);
1090
1306
  if (entry.isDirectory()) {
1091
- const isExcluded = entry.name.match(excludePattern);
1092
- if (includeDirectoriesNormalized && matchPattern(entry.name) && !isExcluded) {
1093
- collected.push({
1094
- name: entry.name,
1095
- absolutePath: entryAbsolutePath,
1096
- relativePath: entryRelativePath,
1097
- type: "directory"
1098
- });
1099
- }
1100
- if (recursive && depth < maxDepthNormalized && !isExcluded) {
1307
+ collected.push({
1308
+ name: entry.name,
1309
+ absolutePath: entryAbsolutePath,
1310
+ relativePath: entryRelativePath,
1311
+ type: "directory",
1312
+ mtime: 0,
1313
+ depth
1314
+ });
1315
+ if (recursive && depth < maxDepth) {
1101
1316
  await walk(entryAbsolutePath, depth + 1);
1102
1317
  }
1103
1318
  } else if (entry.isFile()) {
1104
- if (includeFilesNormalized && matchPattern(entry.name) && !entry.name.match(excludePattern)) {
1319
+ if (matchPattern(entry.name, pattern)) {
1105
1320
  collected.push({
1106
1321
  name: entry.name,
1107
1322
  absolutePath: entryAbsolutePath,
1108
1323
  relativePath: entryRelativePath,
1109
- type: "file"
1324
+ type: "file",
1325
+ mtime: 0,
1326
+ depth
1110
1327
  });
1111
1328
  }
1112
1329
  }
1113
1330
  }
1114
1331
  };
1115
1332
  await walk(absolutePath, 0);
1333
+ await getMtimesBatched3(collected);
1116
1334
  const totalFiles = collected.filter((item) => item.type === "file").length;
1117
1335
  const totalDirectories = collected.filter((item) => item.type === "directory").length;
1118
- let message = `Successfully listed ${collected.length} items in: ${relativePath ?? absolutePath}`;
1336
+ const treeOutput = buildTreeOutput(collected, relativePath || path10__default.default.basename(absolutePath));
1337
+ let message = `Listed ${collected.length} items`;
1338
+ if (relativePath) {
1339
+ message += ` in "${relativePath}"`;
1340
+ }
1341
+ message += ` (${totalFiles} files, ${totalDirectories} directories)`;
1119
1342
  if (recursive) {
1120
- message += ` (recursive${maxDepth !== void 0 ? `, max depth ${maxDepth}` : ""})`;
1343
+ message += ` [depth: ${maxDepth}]`;
1121
1344
  }
1122
1345
  if (pattern) {
1123
- message += ` (filtered by pattern: ${pattern})`;
1346
+ message += ` [filter: ${pattern}]`;
1124
1347
  }
1125
- message += ` - ${totalFiles} files, ${totalDirectories} directories`;
1348
+ if (truncated) {
1349
+ message += ` [TRUNCATED at ${RESULT_LIMIT2} items]`;
1350
+ }
1351
+ const files = collected.map((item) => ({
1352
+ name: item.name,
1353
+ path: item.relativePath,
1354
+ type: item.type
1355
+ }));
1126
1356
  return {
1127
1357
  success: true,
1128
1358
  message,
1129
- files: collected
1359
+ metadata: {
1360
+ totalFiles,
1361
+ totalDirectories,
1362
+ totalItems: collected.length,
1363
+ truncated,
1364
+ maxDepth,
1365
+ recursive
1366
+ },
1367
+ files,
1368
+ content: treeOutput
1130
1369
  };
1131
1370
  } catch (error) {
1371
+ console.error("[list] error:", error);
1132
1372
  return {
1133
1373
  success: false,
1134
- message: `Failed to list files: ${error}`,
1374
+ message: `Failed to list directory: ${error}`,
1135
1375
  error: "LIST_ERROR"
1136
1376
  };
1137
1377
  }
@@ -1149,10 +1389,10 @@ var CREDENTIALS_DIR = path10__default.default.join(os3__default.default.homedir(
1149
1389
  var CREDENTIALS_PATH = path10__default.default.join(CREDENTIALS_DIR, "credentials.json");
1150
1390
  function isAuthenticated() {
1151
1391
  try {
1152
- if (!fs6__default.default.existsSync(CREDENTIALS_PATH)) {
1392
+ if (!fs8__default.default.existsSync(CREDENTIALS_PATH)) {
1153
1393
  return false;
1154
1394
  }
1155
- const raw = fs6__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1395
+ const raw = fs8__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1156
1396
  const data = JSON.parse(raw);
1157
1397
  return Boolean(data && data.access_token);
1158
1398
  } catch {
@@ -1161,10 +1401,10 @@ function isAuthenticated() {
1161
1401
  }
1162
1402
  function saveTokens(tokens) {
1163
1403
  try {
1164
- if (!fs6__default.default.existsSync(CREDENTIALS_DIR)) {
1165
- fs6__default.default.mkdirSync(CREDENTIALS_DIR, { recursive: true });
1404
+ if (!fs8__default.default.existsSync(CREDENTIALS_DIR)) {
1405
+ fs8__default.default.mkdirSync(CREDENTIALS_DIR, { recursive: true });
1166
1406
  }
1167
- fs6__default.default.writeFileSync(
1407
+ fs8__default.default.writeFileSync(
1168
1408
  CREDENTIALS_PATH,
1169
1409
  JSON.stringify(tokens, null, 2),
1170
1410
  "utf8"
@@ -1175,18 +1415,18 @@ function saveTokens(tokens) {
1175
1415
  }
1176
1416
  function logout() {
1177
1417
  try {
1178
- if (fs6__default.default.existsSync(CREDENTIALS_PATH)) {
1179
- fs6__default.default.unlinkSync(CREDENTIALS_PATH);
1418
+ if (fs8__default.default.existsSync(CREDENTIALS_PATH)) {
1419
+ fs8__default.default.unlinkSync(CREDENTIALS_PATH);
1180
1420
  }
1181
1421
  } catch (error) {
1182
1422
  console.error(pc5__default.default.red("Failed to logout"), error);
1183
1423
  }
1184
1424
  }
1185
1425
  function getTokens() {
1186
- if (!fs6__default.default.existsSync(CREDENTIALS_PATH)) {
1426
+ if (!fs8__default.default.existsSync(CREDENTIALS_PATH)) {
1187
1427
  return null;
1188
1428
  }
1189
- const raw = fs6__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1429
+ const raw = fs8__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1190
1430
  const data = JSON.parse(raw);
1191
1431
  return data;
1192
1432
  }
@@ -1285,10 +1525,10 @@ async function login() {
1285
1525
  }
1286
1526
  var getUserId = () => {
1287
1527
  try {
1288
- if (!fs6__default.default.existsSync(CREDENTIALS_PATH)) {
1528
+ if (!fs8__default.default.existsSync(CREDENTIALS_PATH)) {
1289
1529
  return;
1290
1530
  }
1291
- const raw = fs6__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1531
+ const raw = fs8__default.default.readFileSync(CREDENTIALS_PATH, "utf8");
1292
1532
  const data = JSON.parse(raw);
1293
1533
  return {
1294
1534
  userId: data.user.id
@@ -1337,7 +1577,7 @@ zod.z.object({
1337
1577
  command: zod.z.string().describe("The terminal command to execute (e.g., 'ls -la', 'pwd', 'echo $HOME')"),
1338
1578
  is_background: zod.z.boolean().describe("Whether the command should be run in the background")
1339
1579
  }).merge(ExplanationSchema);
1340
- var runSecureTerminalCommand = async (command, timeout) => {
1580
+ var runSecureTerminalCommand = async (command, timeout, cwd) => {
1341
1581
  try {
1342
1582
  if (isHarmfulCommand(command)) {
1343
1583
  console.log(`[CLI] Harmful command detected: ${command}`);
@@ -1347,42 +1587,44 @@ var runSecureTerminalCommand = async (command, timeout) => {
1347
1587
  error: "HARMFUL_COMMAND_DETECTED"
1348
1588
  };
1349
1589
  }
1350
- return new Promise((resolve, reject) => {
1351
- const child = child_process.spawn(command, {
1352
- cwd: process.cwd(),
1353
- stdio: ["pipe", "pipe", "pipe"],
1354
- shell: true
1355
- });
1356
- let stdout = "";
1357
- let stderr = "";
1358
- let timeoutId = null;
1359
- if (timeoutId > 0) {
1360
- timeoutId = setTimeout(() => {
1361
- child.kill("SIGKILL");
1362
- reject(new Error(`Command timed out after ${timeout}ms`));
1363
- }, timeout);
1364
- }
1365
- child.stdout?.on("data", (data) => {
1366
- stdout += data.toString();
1367
- });
1368
- child.stderr?.on("data", (data) => {
1369
- stderr += data.toString();
1370
- });
1371
- child.stdout.on("close", (code) => {
1372
- if (timeoutId) {
1373
- clearTimeout(timeoutId);
1374
- }
1375
- resolve({ stdout, stderr, exitCode: code || 0 });
1376
- });
1377
- child.stderr.on("error", (error) => {
1378
- if (timeoutId) {
1379
- clearTimeout(timeoutId);
1380
- }
1381
- reject(error);
1382
- });
1590
+ const proc = Bun.spawn(["sh", "-c", command], {
1591
+ cwd: cwd || process.cwd(),
1592
+ stdout: "pipe",
1593
+ stderr: "pipe"
1383
1594
  });
1384
- } catch {
1385
- console.error("Error while ecexuting the securedShell command");
1595
+ let timedOut = false;
1596
+ let timeoutId = null;
1597
+ if (timeout > 0) {
1598
+ timeoutId = setTimeout(() => {
1599
+ timedOut = true;
1600
+ proc.kill();
1601
+ }, timeout);
1602
+ }
1603
+ const [stdout, stderr, exitCode] = await Promise.all([
1604
+ new Response(proc.stdout).text(),
1605
+ new Response(proc.stderr).text(),
1606
+ proc.exited
1607
+ ]);
1608
+ if (timeoutId) {
1609
+ clearTimeout(timeoutId);
1610
+ }
1611
+ if (timedOut) {
1612
+ return {
1613
+ success: false,
1614
+ message: `Command timed out after ${timeout}ms`,
1615
+ error: "TIMEOUT",
1616
+ stdout,
1617
+ stderr
1618
+ };
1619
+ }
1620
+ return { stdout, stderr, exitCode };
1621
+ } catch (error) {
1622
+ console.error("Error while executing the securedShell command", error);
1623
+ return {
1624
+ success: false,
1625
+ message: "Error while executing the securedShell command",
1626
+ error: error.message
1627
+ };
1386
1628
  }
1387
1629
  };
1388
1630
  var runTerminalCommand = async (input, projectCwd) => {
@@ -1396,13 +1638,12 @@ var runTerminalCommand = async (input, projectCwd) => {
1396
1638
  error: "HARMFUL_COMMAND_DETECTED"
1397
1639
  };
1398
1640
  }
1399
- const child = child_process.spawn(input.command, {
1400
- cwd: projectCwd,
1401
- detached: true,
1402
- stdio: "ignore",
1403
- shell: true
1641
+ const proc = Bun.spawn(["sh", "-c", input.command], {
1642
+ cwd: projectCwd || process.cwd(),
1643
+ stdout: "ignore",
1644
+ stderr: "ignore"
1404
1645
  });
1405
- child.unref();
1646
+ proc.unref();
1406
1647
  console.log(`[LOCAL] Background command started: ${input.command}`);
1407
1648
  return {
1408
1649
  success: true,
@@ -1412,9 +1653,13 @@ var runTerminalCommand = async (input, projectCwd) => {
1412
1653
  } else {
1413
1654
  const result = await runSecureTerminalCommand(
1414
1655
  input.command,
1415
- 3e4
1656
+ 3e4,
1416
1657
  // 30 second timeout
1658
+ projectCwd
1417
1659
  );
1660
+ if (result?.error && !result?.exitCode) {
1661
+ return result;
1662
+ }
1418
1663
  const success = result?.exitCode === 0;
1419
1664
  return {
1420
1665
  success,
@@ -1433,9 +1678,9 @@ var runTerminalCommand = async (input, projectCwd) => {
1433
1678
  };
1434
1679
  }
1435
1680
  };
1436
- var ignoreFiles = ["node_modules", ".git", ".next", ".env", ".env.local", ".env.development.local", ".env.test.local", ".env.production.local"];
1681
+ 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"];
1437
1682
  var getContext = (dir, base = dir, allFiles = []) => {
1438
- const filePath = fs6.readdirSync(dir, { withFileTypes: true });
1683
+ const filePath = fs8.readdirSync(dir, { withFileTypes: true });
1439
1684
  for (const file of filePath) {
1440
1685
  if (ignoreFiles.includes(file.name)) continue;
1441
1686
  const fullPath = path10__default.default.join(dir, file.name);
@@ -1455,28 +1700,34 @@ var IDE_PROJECTS_PATHS = {
1455
1700
  };
1456
1701
  function getWorkspaceStoragePath(ide) {
1457
1702
  const platform = os3__default.default.platform();
1458
- const appName = "Cursor" ;
1703
+ const appName = ide === "cursor" ? "Cursor" : "Code";
1704
+ const appNameLower = appName.toLowerCase();
1459
1705
  if (platform === "darwin") {
1460
1706
  return path10__default.default.join(HOME, "Library", "Application Support", appName, "User", "workspaceStorage");
1461
1707
  } else if (platform === "win32") {
1462
1708
  return path10__default.default.join(process.env.APPDATA || "", appName, "User", "workspaceStorage");
1463
1709
  } else {
1464
- return path10__default.default.join(HOME, ".config", appName, "User", "workspaceStorage");
1710
+ const capitalizedPath = path10__default.default.join(HOME, ".config", appName, "User", "workspaceStorage");
1711
+ const lowercasePath = path10__default.default.join(HOME, ".config", appNameLower, "User", "workspaceStorage");
1712
+ if (fs8__default.default.existsSync(capitalizedPath)) {
1713
+ return capitalizedPath;
1714
+ }
1715
+ return lowercasePath;
1465
1716
  }
1466
1717
  }
1467
1718
  function scanWorkspaceStorage(ide) {
1468
1719
  const projects = [];
1469
- const storagePath = getWorkspaceStoragePath();
1470
- if (!fs6__default.default.existsSync(storagePath)) {
1720
+ const storagePath = getWorkspaceStoragePath(ide);
1721
+ if (!fs8__default.default.existsSync(storagePath)) {
1471
1722
  return projects;
1472
1723
  }
1473
1724
  try {
1474
- const workspaces = fs6__default.default.readdirSync(storagePath);
1725
+ const workspaces = fs8__default.default.readdirSync(storagePath);
1475
1726
  for (const workspace of workspaces) {
1476
1727
  const workspaceJsonPath = path10__default.default.join(storagePath, workspace, "workspace.json");
1477
- if (fs6__default.default.existsSync(workspaceJsonPath)) {
1728
+ if (fs8__default.default.existsSync(workspaceJsonPath)) {
1478
1729
  try {
1479
- const content = fs6__default.default.readFileSync(workspaceJsonPath, "utf-8");
1730
+ const content = fs8__default.default.readFileSync(workspaceJsonPath, "utf-8");
1480
1731
  const data = JSON.parse(content);
1481
1732
  if (data.folder && typeof data.folder === "string") {
1482
1733
  let projectPath = data.folder;
@@ -1484,7 +1735,7 @@ function scanWorkspaceStorage(ide) {
1484
1735
  projectPath = projectPath.replace("file://", "");
1485
1736
  projectPath = decodeURIComponent(projectPath);
1486
1737
  }
1487
- if (fs6__default.default.existsSync(projectPath) && fs6__default.default.statSync(projectPath).isDirectory()) {
1738
+ if (fs8__default.default.existsSync(projectPath) && fs8__default.default.statSync(projectPath).isDirectory()) {
1488
1739
  projects.push({
1489
1740
  name: path10__default.default.basename(projectPath),
1490
1741
  path: projectPath,
@@ -1508,11 +1759,11 @@ var scanIdeProjects = async () => {
1508
1759
  const seenPaths = /* @__PURE__ */ new Set();
1509
1760
  const addProject = (projectPath, ide) => {
1510
1761
  try {
1511
- const resolvedPath = fs6__default.default.realpathSync(projectPath);
1512
- if (fs6__default.default.existsSync(resolvedPath) && fs6__default.default.statSync(resolvedPath).isDirectory() && !seenPaths.has(resolvedPath)) {
1762
+ const resolvedPath = fs8__default.default.realpathSync(projectPath);
1763
+ if (fs8__default.default.existsSync(resolvedPath) && fs8__default.default.statSync(resolvedPath).isDirectory() && !seenPaths.has(resolvedPath)) {
1513
1764
  const isIdeProjectsDir = Object.values(IDE_PROJECTS_PATHS).some((ideDir) => {
1514
1765
  try {
1515
- return fs6__default.default.realpathSync(ideDir) === resolvedPath;
1766
+ return fs8__default.default.realpathSync(ideDir) === resolvedPath;
1516
1767
  } catch {
1517
1768
  return false;
1518
1769
  }
@@ -1533,32 +1784,36 @@ var scanIdeProjects = async () => {
1533
1784
  for (const project of cursorProjects) {
1534
1785
  addProject(project.path, "cursor");
1535
1786
  }
1787
+ const vscodeProjects = scanWorkspaceStorage("vscode");
1788
+ for (const project of vscodeProjects) {
1789
+ addProject(project.path, "vscode");
1790
+ }
1536
1791
  for (const [ide, dirPath] of Object.entries(IDE_PROJECTS_PATHS)) {
1537
- if (ide === "cursor") continue;
1538
- if (fs6__default.default.existsSync(dirPath)) {
1539
- const projects = fs6__default.default.readdirSync(dirPath);
1792
+ if (ide === "cursor" || ide === "vscode") continue;
1793
+ if (fs8__default.default.existsSync(dirPath)) {
1794
+ const projects = fs8__default.default.readdirSync(dirPath);
1540
1795
  projects.forEach((project) => {
1541
1796
  const projectPath = path10__default.default.join(dirPath, project);
1542
1797
  try {
1543
- const stats = fs6__default.default.lstatSync(projectPath);
1798
+ const stats = fs8__default.default.lstatSync(projectPath);
1544
1799
  let actualPath = null;
1545
1800
  if (stats.isSymbolicLink()) {
1546
- actualPath = fs6__default.default.realpathSync(projectPath);
1801
+ actualPath = fs8__default.default.realpathSync(projectPath);
1547
1802
  } else if (stats.isFile()) {
1548
1803
  try {
1549
- let content = fs6__default.default.readFileSync(projectPath, "utf-8").trim();
1804
+ let content = fs8__default.default.readFileSync(projectPath, "utf-8").trim();
1550
1805
  if (content.startsWith("~/") || content === "~") {
1551
1806
  content = content.replace(/^~/, HOME);
1552
1807
  }
1553
1808
  const resolvedContent = path10__default.default.isAbsolute(content) ? content : path10__default.default.resolve(path10__default.default.dirname(projectPath), content);
1554
- if (fs6__default.default.existsSync(resolvedContent) && fs6__default.default.statSync(resolvedContent).isDirectory()) {
1555
- actualPath = fs6__default.default.realpathSync(resolvedContent);
1809
+ if (fs8__default.default.existsSync(resolvedContent) && fs8__default.default.statSync(resolvedContent).isDirectory()) {
1810
+ actualPath = fs8__default.default.realpathSync(resolvedContent);
1556
1811
  }
1557
1812
  } catch {
1558
1813
  return;
1559
1814
  }
1560
1815
  } else if (stats.isDirectory()) {
1561
- actualPath = fs6__default.default.realpathSync(projectPath);
1816
+ actualPath = fs8__default.default.realpathSync(projectPath);
1562
1817
  }
1563
1818
  if (actualPath) {
1564
1819
  addProject(actualPath, ide);
@@ -1582,7 +1837,7 @@ var Global;
1582
1837
  })(Global || (Global = {}));
1583
1838
 
1584
1839
  // src/snapshot/snapshot.ts
1585
- var execAsync2 = util.promisify(child_process.exec);
1840
+ var execAsync = util.promisify(child_process.exec);
1586
1841
  var Snapshot;
1587
1842
  ((Snapshot2) => {
1588
1843
  const log = {
@@ -1592,7 +1847,7 @@ var Snapshot;
1592
1847
  };
1593
1848
  async function runGit(command, options = {}) {
1594
1849
  try {
1595
- const { stdout, stderr } = await execAsync2(command, {
1850
+ const { stdout, stderr } = await execAsync(command, {
1596
1851
  cwd: options.cwd,
1597
1852
  env: { ...process.env, ...options.env },
1598
1853
  encoding: "utf-8",
@@ -1616,8 +1871,8 @@ var Snapshot;
1616
1871
  const worktree = project.cwd;
1617
1872
  const git = gitdir(projectId);
1618
1873
  try {
1619
- await fs5__default.default.mkdir(git, { recursive: true });
1620
- const gitExists = await fs5__default.default.access(path10__default.default.join(git, "HEAD")).then(() => true).catch(() => false);
1874
+ await fs7__default.default.mkdir(git, { recursive: true });
1875
+ const gitExists = await fs7__default.default.access(path10__default.default.join(git, "HEAD")).then(() => true).catch(() => false);
1621
1876
  if (!gitExists) {
1622
1877
  await runGit(`git init`, {
1623
1878
  env: { GIT_DIR: git, GIT_WORK_TREE: worktree }
@@ -1702,7 +1957,7 @@ var Snapshot;
1702
1957
  for (const file of newFiles) {
1703
1958
  const fullPath = path10__default.default.join(worktree, file);
1704
1959
  try {
1705
- await fs5__default.default.unlink(fullPath);
1960
+ await fs7__default.default.unlink(fullPath);
1706
1961
  log.info("deleted newly created file", { file: fullPath });
1707
1962
  } catch {
1708
1963
  }
@@ -1739,7 +1994,7 @@ var Snapshot;
1739
1994
  log.info("file existed in snapshot but checkout failed, keeping", { file });
1740
1995
  } else {
1741
1996
  log.info("file did not exist in snapshot, deleting", { file });
1742
- await fs5__default.default.unlink(file).catch(() => {
1997
+ await fs7__default.default.unlink(file).catch(() => {
1743
1998
  });
1744
1999
  }
1745
2000
  }
@@ -2188,7 +2443,7 @@ async function main() {
2188
2443
  await connectToUserStreams(serverUrl);
2189
2444
  startHttpServer();
2190
2445
  }
2191
- var execAsync3 = util.promisify(child_process.exec);
2446
+ var execAsync2 = util.promisify(child_process.exec);
2192
2447
  var CODE_SERVER_VERSION = "4.96.4";
2193
2448
  function getPlatformInfo() {
2194
2449
  const platform = process.platform;
@@ -2222,50 +2477,50 @@ function getCodeServerBin() {
2222
2477
  }
2223
2478
  function isCodeServerInstalled() {
2224
2479
  const binPath = getCodeServerBin();
2225
- return fs6__default.default.existsSync(binPath);
2480
+ return fs8__default.default.existsSync(binPath);
2226
2481
  }
2227
2482
  async function installCodeServer() {
2228
2483
  const { ext } = getPlatformInfo();
2229
2484
  const downloadUrl = getDownloadUrl();
2230
2485
  const tarballPath = path10__default.default.join(AMA_DIR, `code-server.${ext}`);
2231
- if (!fs6__default.default.existsSync(AMA_DIR)) {
2232
- fs6__default.default.mkdirSync(AMA_DIR, { recursive: true });
2486
+ if (!fs8__default.default.existsSync(AMA_DIR)) {
2487
+ fs8__default.default.mkdirSync(AMA_DIR, { recursive: true });
2233
2488
  }
2234
- if (!fs6__default.default.existsSync(CODE_DIR)) {
2235
- fs6__default.default.mkdirSync(CODE_DIR, { recursive: true });
2489
+ if (!fs8__default.default.existsSync(CODE_DIR)) {
2490
+ fs8__default.default.mkdirSync(CODE_DIR, { recursive: true });
2236
2491
  }
2237
- if (!fs6__default.default.existsSync(STORAGE_DIR)) {
2238
- fs6__default.default.mkdirSync(STORAGE_DIR, { recursive: true });
2492
+ if (!fs8__default.default.existsSync(STORAGE_DIR)) {
2493
+ fs8__default.default.mkdirSync(STORAGE_DIR, { recursive: true });
2239
2494
  }
2240
- console.log(pc5__default.default.cyan(`Downloading code-server v${CODE_SERVER_VERSION}...`));
2495
+ console.log(pc5__default.default.cyan(`downloading code-server v${CODE_SERVER_VERSION}...`));
2241
2496
  console.log(pc5__default.default.gray(downloadUrl));
2242
2497
  const response = await fetch(downloadUrl);
2243
2498
  if (!response.ok) {
2244
2499
  throw new Error(`Failed to download code-server: ${response.statusText}`);
2245
2500
  }
2246
2501
  const buffer = await response.arrayBuffer();
2247
- await fs6__default.default.promises.writeFile(tarballPath, Buffer.from(buffer));
2502
+ await fs8__default.default.promises.writeFile(tarballPath, Buffer.from(buffer));
2248
2503
  console.log(pc5__default.default.cyan("Extracting code-server..."));
2249
- await execAsync3(`tar -xzf ${tarballPath} -C ${CODE_DIR}`);
2250
- await fs6__default.default.promises.unlink(tarballPath);
2504
+ await execAsync2(`tar -xzf ${tarballPath} -C ${CODE_DIR}`);
2505
+ await fs8__default.default.promises.unlink(tarballPath);
2251
2506
  const binPath = getCodeServerBin();
2252
- if (fs6__default.default.existsSync(binPath)) {
2253
- await fs6__default.default.promises.chmod(binPath, 493);
2507
+ if (fs8__default.default.existsSync(binPath)) {
2508
+ await fs8__default.default.promises.chmod(binPath, 493);
2254
2509
  }
2255
- console.log(pc5__default.default.green("\u2713 code-server installed successfully"));
2510
+ console.log(pc5__default.default.green("code-server installed successfully"));
2256
2511
  }
2257
2512
  async function killExistingCodeServer() {
2258
2513
  try {
2259
2514
  if (process.platform === "win32") {
2260
- await execAsync3("netstat -ano | findstr :8081 | findstr LISTENING").then(async ({ stdout }) => {
2515
+ await execAsync2("netstat -ano | findstr :8081 | findstr LISTENING").then(async ({ stdout }) => {
2261
2516
  const pid = stdout.trim().split(/\s+/).pop();
2262
- if (pid) await execAsync3(`taskkill /PID ${pid} /F`);
2517
+ if (pid) await execAsync2(`taskkill /PID ${pid} /F`);
2263
2518
  }).catch(() => {
2264
2519
  });
2265
2520
  } else {
2266
- await execAsync3("lsof -ti:8081").then(async ({ stdout }) => {
2521
+ await execAsync2("lsof -ti:8081").then(async ({ stdout }) => {
2267
2522
  const pid = stdout.trim();
2268
- if (pid) await execAsync3(`kill -9 ${pid}`);
2523
+ if (pid) await execAsync2(`kill -9 ${pid}`);
2269
2524
  }).catch(() => {
2270
2525
  });
2271
2526
  }
@@ -2275,8 +2530,8 @@ async function killExistingCodeServer() {
2275
2530
  async function setupDefaultSettings() {
2276
2531
  const userDir = path10__default.default.join(STORAGE_DIR, "User");
2277
2532
  const settingsPath = path10__default.default.join(userDir, "settings.json");
2278
- if (!fs6__default.default.existsSync(userDir)) {
2279
- fs6__default.default.mkdirSync(userDir, { recursive: true });
2533
+ if (!fs8__default.default.existsSync(userDir)) {
2534
+ fs8__default.default.mkdirSync(userDir, { recursive: true });
2280
2535
  }
2281
2536
  const defaultSettings = {
2282
2537
  // Disable signature verification for Open VSX extensions
@@ -2294,9 +2549,9 @@ async function setupDefaultSettings() {
2294
2549
  "workbench.activityBar.location": "top"
2295
2550
  };
2296
2551
  let existingSettings = {};
2297
- if (fs6__default.default.existsSync(settingsPath)) {
2552
+ if (fs8__default.default.existsSync(settingsPath)) {
2298
2553
  try {
2299
- const content = await fs6__default.default.promises.readFile(settingsPath, "utf-8");
2554
+ const content = await fs8__default.default.promises.readFile(settingsPath, "utf-8");
2300
2555
  existingSettings = JSON.parse(content);
2301
2556
  } catch {
2302
2557
  }
@@ -2304,7 +2559,7 @@ async function setupDefaultSettings() {
2304
2559
  const mergedSettings = { ...defaultSettings, ...existingSettings };
2305
2560
  mergedSettings["workbench.colorTheme"] = "Min Dark";
2306
2561
  mergedSettings["extensions.verifySignature"] = false;
2307
- await fs6__default.default.promises.writeFile(settingsPath, JSON.stringify(mergedSettings, null, 2));
2562
+ await fs8__default.default.promises.writeFile(settingsPath, JSON.stringify(mergedSettings, null, 2));
2308
2563
  console.log(pc5__default.default.green("ama code-server settings configured"));
2309
2564
  }
2310
2565
  async function installExtensions() {
@@ -2315,7 +2570,7 @@ async function installExtensions() {
2315
2570
  for (const ext of extensions) {
2316
2571
  try {
2317
2572
  console.log(pc5__default.default.cyan(`ama installing extension: ${ext}...`));
2318
- await execAsync3(`"${binPath}" --user-data-dir "${STORAGE_DIR}" --install-extension ${ext}`);
2573
+ await execAsync2(`"${binPath}" --user-data-dir "${STORAGE_DIR}" --install-extension ${ext}`);
2319
2574
  console.log(pc5__default.default.green(`ama extension ${ext} installed`));
2320
2575
  } catch (error) {
2321
2576
  console.log(pc5__default.default.yellow(`ama failed to install extension ${ext}`), error);
@@ -2325,7 +2580,7 @@ async function installExtensions() {
2325
2580
  async function startCodeServer(cwd) {
2326
2581
  const binPath = getCodeServerBin();
2327
2582
  const workDir = cwd || process.cwd();
2328
- if (!fs6__default.default.existsSync(binPath)) {
2583
+ if (!fs8__default.default.existsSync(binPath)) {
2329
2584
  throw new Error("ama code-server is not installed. Run installCodeServer() first.");
2330
2585
  }
2331
2586
  await killExistingCodeServer();
@@ -2333,12 +2588,12 @@ async function startCodeServer(cwd) {
2333
2588
  await installExtensions();
2334
2589
  const workspaceStoragePath = path10__default.default.join(STORAGE_DIR, "User", "workspaceStorage");
2335
2590
  try {
2336
- if (fs6__default.default.existsSync(workspaceStoragePath)) {
2337
- await fs6__default.default.promises.rm(workspaceStoragePath, { recursive: true, force: true });
2591
+ if (fs8__default.default.existsSync(workspaceStoragePath)) {
2592
+ await fs8__default.default.promises.rm(workspaceStoragePath, { recursive: true, force: true });
2338
2593
  }
2339
2594
  const stateDbPath = path10__default.default.join(STORAGE_DIR, "User", "globalStorage", "state.vscdb");
2340
- if (fs6__default.default.existsSync(stateDbPath)) {
2341
- await fs6__default.default.promises.unlink(stateDbPath);
2595
+ if (fs8__default.default.existsSync(stateDbPath)) {
2596
+ await fs8__default.default.promises.unlink(stateDbPath);
2342
2597
  }
2343
2598
  } catch {
2344
2599
  }
@@ -2369,11 +2624,11 @@ var __dirname$1 = path10.dirname(__filename$1);
2369
2624
  var DAEMON_PID_FILE = path10__default.default.join(AMA_DIR, "daemon.pid");
2370
2625
  var DAEMON_LOG_FILE = path10__default.default.join(AMA_DIR, "daemon.log");
2371
2626
  function isDaemonRunning() {
2372
- if (!fs6__default.default.existsSync(DAEMON_PID_FILE)) {
2627
+ if (!fs8__default.default.existsSync(DAEMON_PID_FILE)) {
2373
2628
  return false;
2374
2629
  }
2375
2630
  try {
2376
- const pid = Number(fs6__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
2631
+ const pid = Number(fs8__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
2377
2632
  process.kill(pid, 0);
2378
2633
  return true;
2379
2634
  } catch {
@@ -2381,30 +2636,30 @@ function isDaemonRunning() {
2381
2636
  }
2382
2637
  }
2383
2638
  function stopDaemon() {
2384
- if (!fs6__default.default.existsSync(DAEMON_PID_FILE)) {
2639
+ if (!fs8__default.default.existsSync(DAEMON_PID_FILE)) {
2385
2640
  return false;
2386
2641
  }
2387
2642
  try {
2388
- const pid = Number(fs6__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
2643
+ const pid = Number(fs8__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
2389
2644
  process.kill(pid, "SIGTERM");
2390
- fs6__default.default.unlinkSync(DAEMON_PID_FILE);
2645
+ fs8__default.default.unlinkSync(DAEMON_PID_FILE);
2391
2646
  return true;
2392
2647
  } catch (error) {
2393
2648
  return false;
2394
2649
  }
2395
2650
  }
2396
2651
  function startDaemon() {
2397
- if (!fs6__default.default.existsSync(AMA_DIR)) {
2398
- fs6__default.default.mkdirSync(AMA_DIR, { recursive: true });
2652
+ if (!fs8__default.default.existsSync(AMA_DIR)) {
2653
+ fs8__default.default.mkdirSync(AMA_DIR, { recursive: true });
2399
2654
  }
2400
2655
  if (isDaemonRunning()) {
2401
2656
  stopDaemon();
2402
2657
  }
2403
2658
  const daemonScript = path10__default.default.join(__dirname$1, "lib", "daemon-entry.js");
2404
- if (!fs6__default.default.existsSync(daemonScript)) {
2659
+ if (!fs8__default.default.existsSync(daemonScript)) {
2405
2660
  throw new Error(`Daemon entry script not found at: ${daemonScript}. Please rebuild the project.`);
2406
2661
  }
2407
- const logFd = fs6__default.default.openSync(DAEMON_LOG_FILE, "a");
2662
+ const logFd = fs8__default.default.openSync(DAEMON_LOG_FILE, "a");
2408
2663
  const daemon = child_process.spawn(process.execPath, [daemonScript], {
2409
2664
  detached: true,
2410
2665
  stdio: ["ignore", logFd, logFd],
@@ -2412,20 +2667,20 @@ function startDaemon() {
2412
2667
  cwd: process.cwd()
2413
2668
  });
2414
2669
  daemon.unref();
2415
- fs6__default.default.writeFileSync(DAEMON_PID_FILE, String(daemon.pid));
2416
- fs6__default.default.closeSync(logFd);
2670
+ fs8__default.default.writeFileSync(DAEMON_PID_FILE, String(daemon.pid));
2671
+ fs8__default.default.closeSync(logFd);
2417
2672
  }
2418
2673
  function getDaemonPid() {
2419
- if (!fs6__default.default.existsSync(DAEMON_PID_FILE)) {
2674
+ if (!fs8__default.default.existsSync(DAEMON_PID_FILE)) {
2420
2675
  return null;
2421
2676
  }
2422
2677
  try {
2423
- return Number(fs6__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
2678
+ return Number(fs8__default.default.readFileSync(DAEMON_PID_FILE, "utf8"));
2424
2679
  } catch {
2425
2680
  return null;
2426
2681
  }
2427
2682
  }
2428
- var VERSION = "0.0.10";
2683
+ var VERSION = "0.0.11";
2429
2684
  var PROJECT_DIR = process.cwd();
2430
2685
  var LOGO = `
2431
2686
  __ _ _ __ ___ __ _
@@ -2480,13 +2735,13 @@ async function checkForUpdates() {
2480
2735
  }
2481
2736
  function runNpmInstall() {
2482
2737
  return new Promise((resolve, reject) => {
2483
- const child = child_process.spawn("npm", ["install", "-g", "amai@latest"], {
2738
+ const child = child_process.spawn("bun", ["add", "-g", "amai@latest"], {
2484
2739
  stdio: "inherit",
2485
2740
  shell: true
2486
2741
  });
2487
2742
  child.on("close", (code) => {
2488
2743
  if (code === 0) resolve();
2489
- else reject(new Error(`npm install exited with code ${code}`));
2744
+ else reject(new Error(`bun add exited with code ${code}`));
2490
2745
  });
2491
2746
  child.on("error", reject);
2492
2747
  });
@@ -2592,11 +2847,11 @@ if (args[0] === "update") {
2592
2847
  process.exit(1);
2593
2848
  }
2594
2849
  const resolvedPath = path10__default.default.resolve(projectPath);
2595
- if (!fs6__default.default.existsSync(resolvedPath)) {
2850
+ if (!fs8__default.default.existsSync(resolvedPath)) {
2596
2851
  console.error(pc5__default.default.red(`path does not exist: ${resolvedPath}`));
2597
2852
  process.exit(1);
2598
2853
  }
2599
- if (!fs6__default.default.statSync(resolvedPath).isDirectory()) {
2854
+ if (!fs8__default.default.statSync(resolvedPath).isDirectory()) {
2600
2855
  console.error(pc5__default.default.red(`path is not a directory: ${resolvedPath}`));
2601
2856
  process.exit(1);
2602
2857
  }