amai 0.0.26 → 0.0.28

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/server.cjs CHANGED
@@ -10,10 +10,9 @@ var nodeServer = require('@hono/node-server');
10
10
  var cors = require('hono/cors');
11
11
  var fs4 = require('fs');
12
12
  var child_process = require('child_process');
13
- var util = require('util');
14
- var fsp = require('fs/promises');
15
- var zod = require('zod');
16
13
  var http = require('http');
14
+ var zod = require('zod');
15
+ var promises = require('fs/promises');
17
16
  var url = require('url');
18
17
  var events = require('events');
19
18
  var Stream = require('stream');
@@ -44,10 +43,9 @@ var path6__default = /*#__PURE__*/_interopDefault(path6);
44
43
  var os3__default = /*#__PURE__*/_interopDefault(os3);
45
44
  var pc3__default = /*#__PURE__*/_interopDefault(pc3);
46
45
  var fs4__namespace = /*#__PURE__*/_interopNamespace(fs4);
47
- var fsp__namespace = /*#__PURE__*/_interopNamespace(fsp);
48
46
  var Stream__default = /*#__PURE__*/_interopDefault(Stream);
49
47
 
50
- var DEFAULT_SERVER_URL = "wss://bridge.ama.shujan.xyz";
48
+ var DEFAULT_SERVER_URL = "wss://ama-bridge.shujanshaikh05.workers.dev";
51
49
  var AMA_DIR = path6__default.default.join(os3__default.default.homedir(), ".amai");
52
50
  path6__default.default.join(AMA_DIR, "code");
53
51
  path6__default.default.join(AMA_DIR, "storage");
@@ -106,12 +104,7 @@ var getUserId = () => {
106
104
  throw new Error("Error while getting userId");
107
105
  }
108
106
  };
109
- var MUTATING_TOOLS = /* @__PURE__ */ new Set([
110
- "editFile",
111
- "deleteFile",
112
- "stringReplace",
113
- "bash"
114
- ]);
107
+ var MUTATING_TOOLS = /* @__PURE__ */ new Set(["edit", "write", "bash"]);
115
108
  function isMutatingTool(toolName) {
116
109
  return MUTATING_TOOLS.has(toolName);
117
110
  }
@@ -121,9 +114,7 @@ function isPathWithinProject(filePath, projectCwd) {
121
114
  const resolved = path6__default.default.resolve(resolvedCwd, filePath);
122
115
  const resolvedTarget = safeRealpath(resolved);
123
116
  const rel = path6__default.default.relative(resolvedCwd, resolvedTarget);
124
- if (rel.startsWith("..") || path6__default.default.isAbsolute(rel)) {
125
- return false;
126
- }
117
+ if (rel.startsWith("..") || path6__default.default.isAbsolute(rel)) return false;
127
118
  return true;
128
119
  } catch {
129
120
  return false;
@@ -387,255 +378,6 @@ var scanIdeProjects = async () => {
387
378
  return [];
388
379
  }
389
380
  };
390
- var Global;
391
- ((Global2) => {
392
- ((Path3) => {
393
- Path3.data = path6__default.default.join(AMA_DIR, "data");
394
- })(Global2.Path || (Global2.Path = {}));
395
- })(Global || (Global = {}));
396
-
397
- // src/snapshot/snapshot.ts
398
- var execAsync = util.promisify(child_process.exec);
399
- var Snapshot;
400
- ((Snapshot2) => {
401
- const log = {
402
- info: (msg, data) => console.log(`[snapshot] ${msg}`, data || ""),
403
- warn: (msg, data) => console.warn(`[snapshot] ${msg}`, data || ""),
404
- error: (msg, data) => console.error(`[snapshot] ${msg}`, data || "")
405
- };
406
- async function runGit(command, options = {}) {
407
- try {
408
- const { stdout, stderr } = await execAsync(command, {
409
- cwd: options.cwd,
410
- env: { ...process.env, ...options.env },
411
- encoding: "utf-8",
412
- maxBuffer: 50 * 1024 * 1024
413
- });
414
- return { stdout: stdout || "", stderr: stderr || "", exitCode: 0 };
415
- } catch (error) {
416
- return {
417
- stdout: error.stdout || "",
418
- stderr: error.stderr || "",
419
- exitCode: error.code || 1
420
- };
421
- }
422
- }
423
- async function track(projectId) {
424
- const project = projectRegistry.getProject(projectId);
425
- if (!project) {
426
- log.warn("project not found", { projectId });
427
- return void 0;
428
- }
429
- const worktree = project.cwd;
430
- const git = gitdir(projectId);
431
- try {
432
- await fsp__namespace.default.mkdir(git, { recursive: true });
433
- const gitExists = await fsp__namespace.default.access(path6__default.default.join(git, "HEAD")).then(() => true).catch(() => false);
434
- if (!gitExists) {
435
- await runGit(`git init`, {
436
- env: { GIT_DIR: git, GIT_WORK_TREE: worktree }
437
- });
438
- await runGit(`git --git-dir "${git}" config core.autocrlf false`);
439
- log.info("initialized", { projectId, git });
440
- }
441
- } catch (error) {
442
- log.warn("failed to initialize git", { error });
443
- }
444
- await runGit(`git --git-dir "${git}" --work-tree "${worktree}" add .`, { cwd: worktree });
445
- const result = await runGit(`git --git-dir "${git}" --work-tree "${worktree}" write-tree`, { cwd: worktree });
446
- const hash = result.stdout.trim();
447
- log.info("tracking", { hash, cwd: worktree, git });
448
- return hash;
449
- }
450
- Snapshot2.track = track;
451
- Snapshot2.Patch = zod.z.object({
452
- hash: zod.z.string(),
453
- files: zod.z.string().array()
454
- });
455
- async function patch(projectId, hash) {
456
- const project = projectRegistry.getProject(projectId);
457
- if (!project) {
458
- return { hash, files: [] };
459
- }
460
- const worktree = project.cwd;
461
- const git = gitdir(projectId);
462
- await runGit(`git --git-dir "${git}" --work-tree "${worktree}" add .`, { cwd: worktree });
463
- const result = await runGit(
464
- `git -c core.autocrlf=false --git-dir "${git}" --work-tree "${worktree}" diff --no-ext-diff --name-only ${hash} -- .`,
465
- { cwd: worktree }
466
- );
467
- if (result.exitCode !== 0) {
468
- log.warn("failed to get diff", { hash, exitCode: result.exitCode });
469
- return { hash, files: [] };
470
- }
471
- const files = result.stdout;
472
- return {
473
- hash,
474
- files: files.trim().split("\n").map((x2) => x2.trim()).filter(Boolean).map((x2) => path6__default.default.join(worktree, x2))
475
- };
476
- }
477
- Snapshot2.patch = patch;
478
- async function restore(projectId, snapshot) {
479
- const project = projectRegistry.getProject(projectId);
480
- if (!project) {
481
- log.error("project not found", { projectId });
482
- return false;
483
- }
484
- log.info("restore", { projectId, snapshot });
485
- const worktree = project.cwd;
486
- const git = gitdir(projectId);
487
- const readResult = await runGit(
488
- `git --git-dir "${git}" --work-tree "${worktree}" read-tree ${snapshot}`,
489
- { cwd: worktree }
490
- );
491
- if (readResult.exitCode !== 0) {
492
- log.error("failed to read-tree", { snapshot, stderr: readResult.stderr });
493
- return false;
494
- }
495
- const checkoutResult = await runGit(
496
- `git --git-dir "${git}" --work-tree "${worktree}" checkout-index -a -f`,
497
- { cwd: worktree }
498
- );
499
- if (checkoutResult.exitCode !== 0) {
500
- log.error("failed to checkout-index", { snapshot, stderr: checkoutResult.stderr });
501
- return false;
502
- }
503
- await runGit(`git --git-dir "${git}" --work-tree "${worktree}" add .`, { cwd: worktree });
504
- const currentTree = await runGit(
505
- `git --git-dir "${git}" --work-tree "${worktree}" write-tree`,
506
- { cwd: worktree }
507
- );
508
- if (currentTree.exitCode === 0 && currentTree.stdout.trim()) {
509
- const diffResult = await runGit(
510
- `git --git-dir "${git}" diff-tree -r --name-only --diff-filter=A ${snapshot} ${currentTree.stdout.trim()}`,
511
- { cwd: worktree }
512
- );
513
- if (diffResult.exitCode === 0 && diffResult.stdout.trim()) {
514
- const newFiles = diffResult.stdout.trim().split("\n").filter(Boolean);
515
- for (const file of newFiles) {
516
- const fullPath = path6__default.default.join(worktree, file);
517
- try {
518
- await fsp__namespace.default.unlink(fullPath);
519
- log.info("deleted newly created file", { file: fullPath });
520
- } catch {
521
- }
522
- }
523
- }
524
- }
525
- return true;
526
- }
527
- Snapshot2.restore = restore;
528
- async function revert(projectId, patches) {
529
- const project = projectRegistry.getProject(projectId);
530
- if (!project) {
531
- log.error("project not found", { projectId });
532
- return false;
533
- }
534
- const worktree = project.cwd;
535
- const git = gitdir(projectId);
536
- const files = /* @__PURE__ */ new Set();
537
- for (const item of patches) {
538
- for (const file of item.files) {
539
- if (files.has(file)) continue;
540
- log.info("reverting", { file, hash: item.hash });
541
- const result = await runGit(
542
- `git --git-dir "${git}" --work-tree "${worktree}" checkout ${item.hash} -- "${file}"`,
543
- { cwd: worktree }
544
- );
545
- if (result.exitCode !== 0) {
546
- const relativePath = path6__default.default.relative(worktree, file);
547
- const checkTree = await runGit(
548
- `git --git-dir "${git}" --work-tree "${worktree}" ls-tree ${item.hash} -- "${relativePath}"`,
549
- { cwd: worktree }
550
- );
551
- if (checkTree.exitCode === 0 && checkTree.stdout.trim()) {
552
- log.info("file existed in snapshot but checkout failed, keeping", { file });
553
- } else {
554
- log.info("file did not exist in snapshot, deleting", { file });
555
- await fsp__namespace.default.unlink(file).catch(() => {
556
- });
557
- }
558
- }
559
- files.add(file);
560
- }
561
- }
562
- return true;
563
- }
564
- Snapshot2.revert = revert;
565
- async function diff(projectId, hash) {
566
- const project = projectRegistry.getProject(projectId);
567
- if (!project) {
568
- return "";
569
- }
570
- const worktree = project.cwd;
571
- const git = gitdir(projectId);
572
- await runGit(`git --git-dir "${git}" --work-tree "${worktree}" add .`, { cwd: worktree });
573
- const result = await runGit(
574
- `git -c core.autocrlf=false --git-dir "${git}" --work-tree "${worktree}" diff --no-ext-diff ${hash} -- .`,
575
- { cwd: worktree }
576
- );
577
- if (result.exitCode !== 0) {
578
- log.warn("failed to get diff", { hash, exitCode: result.exitCode, stderr: result.stderr });
579
- return "";
580
- }
581
- return result.stdout.trim();
582
- }
583
- Snapshot2.diff = diff;
584
- Snapshot2.FileDiff = zod.z.object({
585
- file: zod.z.string(),
586
- before: zod.z.string(),
587
- after: zod.z.string(),
588
- additions: zod.z.number(),
589
- deletions: zod.z.number()
590
- });
591
- async function diffFull(projectId, from, to) {
592
- const project = projectRegistry.getProject(projectId);
593
- if (!project) {
594
- return [];
595
- }
596
- const worktree = project.cwd;
597
- const git = gitdir(projectId);
598
- const result = [];
599
- const numstatResult = await runGit(
600
- `git -c core.autocrlf=false --git-dir "${git}" --work-tree "${worktree}" diff --no-ext-diff --no-renames --numstat ${from} ${to} -- .`,
601
- { cwd: worktree }
602
- );
603
- if (numstatResult.exitCode !== 0) {
604
- return [];
605
- }
606
- const lines = numstatResult.stdout.trim().split("\n").filter(Boolean);
607
- for (const line of lines) {
608
- const [additions, deletions, file] = line.split(" ");
609
- const isBinaryFile2 = additions === "-" && deletions === "-";
610
- let before = "";
611
- let after = "";
612
- if (!isBinaryFile2) {
613
- const beforeResult = await runGit(
614
- `git -c core.autocrlf=false --git-dir "${git}" --work-tree "${worktree}" show ${from}:${file}`,
615
- { cwd: worktree }
616
- );
617
- before = beforeResult.stdout;
618
- const afterResult = await runGit(
619
- `git -c core.autocrlf=false --git-dir "${git}" --work-tree "${worktree}" show ${to}:${file}`,
620
- { cwd: worktree }
621
- );
622
- after = afterResult.stdout;
623
- }
624
- result.push({
625
- file,
626
- before,
627
- after,
628
- additions: parseInt(additions) || 0,
629
- deletions: parseInt(deletions) || 0
630
- });
631
- }
632
- return result;
633
- }
634
- Snapshot2.diffFull = diffFull;
635
- function gitdir(projectId) {
636
- return path6__default.default.join(Global.Path.data, "snapshot", projectId);
637
- }
638
- })(Snapshot || (Snapshot = {}));
639
381
  var CLIENT_ID2 = "app_EMoamEEZ73f0CkXaXp7hrann";
640
382
  var ISSUER = "https://auth.openai.com";
641
383
  var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
@@ -1154,62 +896,6 @@ var rpcHandlers = {
1154
896
  arch: process.arch
1155
897
  };
1156
898
  },
1157
- // Snapshot handlers for undo functionality
1158
- "daemon:snapshot_track": async ({ projectId }) => {
1159
- if (!projectId) {
1160
- const error = {
1161
- _tag: "ValidationError",
1162
- message: "projectId is required"
1163
- };
1164
- throw error;
1165
- }
1166
- const hash = await Snapshot.track(projectId);
1167
- return { success: true, hash };
1168
- },
1169
- "daemon:snapshot_patch": async ({ projectId, hash }) => {
1170
- if (!projectId || !hash) {
1171
- const error = {
1172
- _tag: "ValidationError",
1173
- message: "projectId and hash are required"
1174
- };
1175
- throw error;
1176
- }
1177
- const patch = await Snapshot.patch(projectId, hash);
1178
- return { success: true, patch };
1179
- },
1180
- "daemon:snapshot_revert": async ({ projectId, patches }) => {
1181
- if (!projectId || !patches) {
1182
- const error = {
1183
- _tag: "ValidationError",
1184
- message: "projectId and patches are required"
1185
- };
1186
- throw error;
1187
- }
1188
- const success = await Snapshot.revert(projectId, patches);
1189
- return { success };
1190
- },
1191
- "daemon:snapshot_restore": async ({ projectId, snapshot }) => {
1192
- if (!projectId || !snapshot) {
1193
- const error = {
1194
- _tag: "ValidationError",
1195
- message: "projectId and snapshot are required"
1196
- };
1197
- throw error;
1198
- }
1199
- const success = await Snapshot.restore(projectId, snapshot);
1200
- return { success };
1201
- },
1202
- "daemon:snapshot_diff": async ({ projectId, hash }) => {
1203
- if (!projectId || !hash) {
1204
- const error = {
1205
- _tag: "ValidationError",
1206
- message: "projectId and hash are required"
1207
- };
1208
- throw error;
1209
- }
1210
- const diff = await Snapshot.diff(projectId, hash);
1211
- return { success: true, diff };
1212
- },
1213
899
  "daemon:codex_start_auth": async () => {
1214
900
  const { authUrl, waitForCallback } = await startCodexOAuth();
1215
901
  void waitForCallback().catch((error) => {
@@ -1370,1092 +1056,271 @@ var connectToUserStreams = async (serverUrl) => {
1370
1056
  });
1371
1057
  return ws;
1372
1058
  };
1373
- var ExplanationSchema = zod.z.object({
1374
- description: zod.z.string().describe(
1375
- "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'"
1376
- )
1377
- });
1378
- var BLOCKED_PATTERNS = [
1379
- /\brm\s+(-\w+\s+)*(\/ |\/\s*$|~|\/\*|\*)/,
1380
- /\bdd\s+.*of=\/dev\//,
1381
- /\bmkfs\b/,
1382
- /:\(\)\{.*\|.*&\}\s*;?\s*:/,
1383
- /\bchmod\s+.*-R.*\s+\/\s*$/,
1384
- /\bchown\s+.*-R.*\s+\/\s*$/,
1385
- /\b(curl|wget)\s+.*\|\s*(ba)?sh/,
1386
- /\bmv\s+(\/|\*)\s/,
1387
- /\bcat\s+\/dev\/(u?random|zero)\s*>\s*\/dev\//,
1388
- /\bformat\s+[A-Z]:/i,
1389
- /\bdiskpart\b/i,
1390
- /\bcipher\s+\/w:/i
1391
- ];
1392
- var DANGEROUS_FLAGS = [
1393
- /--no-preserve-root/,
1394
- /\bgit\s+push\s+.*--force\b/,
1395
- /\bgit\s+push\s+-f\b/
1396
- ];
1397
- var MAX_OUTPUT_SIZE = 1 * 1024 * 1024;
1398
- var DEFAULT_TIMEOUT = 12e4;
1399
- function evaluateCommandSafety(command) {
1400
- const trimmed = command.trim();
1401
- for (const pattern of BLOCKED_PATTERNS) {
1402
- if (pattern.test(trimmed)) {
1403
- return { safe: false, reason: `Blocked by safety policy: matches destructive pattern` };
1404
- }
1405
- }
1406
- for (const flag of DANGEROUS_FLAGS) {
1407
- if (flag.test(trimmed)) {
1408
- return { safe: false, reason: `Blocked by safety policy: dangerous flag detected` };
1409
- }
1410
- }
1411
- return { safe: true };
1412
- }
1413
1059
  zod.z.object({
1414
- command: zod.z.string().describe("The terminal command to execute"),
1415
- is_background: zod.z.boolean().optional().default(false).describe("Whether the command should be run in the background"),
1416
- timeout: zod.z.number().optional().describe("Optional timeout in milliseconds. If not specified, commands will time out after 120000ms (2 minutes)."),
1417
- 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.")
1418
- }).merge(ExplanationSchema);
1419
- var runSecureTerminalCommand = async (command, timeout, cwd) => {
1420
- try {
1421
- const safety = evaluateCommandSafety(command);
1422
- if (!safety.safe) {
1423
- console.log(`[CLI] Blocked command: ${command} \u2014 ${safety.reason}`);
1424
- return {
1425
- success: false,
1426
- message: safety.reason,
1427
- error: "BLOCKED_COMMAND"
1428
- };
1429
- }
1430
- const proc2 = child_process.spawn("sh", ["-c", command], {
1431
- cwd: cwd || process.cwd(),
1432
- stdio: ["ignore", "pipe", "pipe"]
1433
- });
1434
- let timedOut = false;
1435
- let timeoutId = null;
1060
+ command: zod.z.string().describe("Bash command to execute"),
1061
+ timeout: zod.z.number().optional().describe("Timeout in seconds (optional, no default timeout)")
1062
+ });
1063
+ async function bashTool(input, projectCwd) {
1064
+ const cwd = projectCwd || process.cwd();
1065
+ const timeoutMs = input.timeout && input.timeout > 0 ? input.timeout * 1e3 : 0;
1066
+ return new Promise((resolve) => {
1067
+ const proc2 = child_process.spawn("sh", ["-c", input.command], { cwd, stdio: ["ignore", "pipe", "pipe"] });
1436
1068
  let stdout = "";
1437
1069
  let stderr = "";
1438
- if (timeout > 0) {
1439
- timeoutId = setTimeout(() => {
1440
- timedOut = true;
1441
- proc2.kill("SIGTERM");
1442
- }, timeout);
1443
- }
1444
- if (proc2.stdout) {
1445
- proc2.stdout.on("data", (chunk) => {
1446
- stdout += chunk.toString();
1447
- });
1448
- }
1449
- if (proc2.stderr) {
1450
- proc2.stderr.on("data", (chunk) => {
1451
- stderr += chunk.toString();
1070
+ let timedOut = false;
1071
+ const timer = timeoutMs ? setTimeout(() => {
1072
+ timedOut = true;
1073
+ proc2.kill("SIGTERM");
1074
+ }, timeoutMs) : void 0;
1075
+ proc2.stdout?.on("data", (d) => stdout += d.toString());
1076
+ proc2.stderr?.on("data", (d) => stderr += d.toString());
1077
+ proc2.on("close", (code) => {
1078
+ if (timer) clearTimeout(timer);
1079
+ if (timedOut) {
1080
+ resolve({ success: false, error: "TIMEOUT", message: `Command timed out after ${input.timeout}s` });
1081
+ return;
1082
+ }
1083
+ resolve({
1084
+ success: code === 0,
1085
+ exitCode: code ?? 1,
1086
+ stdout: stdout.trim(),
1087
+ stderr: stderr.trim(),
1088
+ message: code === 0 ? "Command executed" : "Command failed"
1452
1089
  });
1453
- }
1454
- const exitCode = await new Promise((resolve, reject) => {
1455
- proc2.once("error", reject);
1456
- proc2.once("close", (code) => resolve(code));
1457
1090
  });
1458
- if (timeoutId) {
1459
- clearTimeout(timeoutId);
1460
- }
1461
- if (timedOut) {
1462
- return {
1463
- success: false,
1464
- message: `Command timed out after ${timeout}ms`,
1465
- error: "TIMEOUT",
1466
- stdout: stdout.slice(0, MAX_OUTPUT_SIZE),
1467
- stderr: stderr.slice(0, MAX_OUTPUT_SIZE)
1468
- };
1469
- }
1470
- return {
1471
- stdout: stdout.slice(0, MAX_OUTPUT_SIZE),
1472
- stderr: stderr.slice(0, MAX_OUTPUT_SIZE),
1473
- exitCode: exitCode ?? 1
1474
- };
1475
- } catch (error) {
1476
- console.error("Error while executing the securedShell command", error);
1477
- return {
1478
- success: false,
1479
- message: "Error while executing the securedShell command",
1480
- error: error.message
1481
- };
1482
- }
1091
+ proc2.on("error", (error) => {
1092
+ if (timer) clearTimeout(timer);
1093
+ resolve({ success: false, error: "EXEC_ERROR", message: error.message });
1094
+ });
1095
+ });
1096
+ }
1097
+ var ReplaceEditSchema = zod.z.object({
1098
+ oldText: zod.z.string().describe("Exact text for one targeted replacement."),
1099
+ newText: zod.z.string().describe("Replacement text for this targeted edit.")
1100
+ });
1101
+ zod.z.object({
1102
+ path: zod.z.string().describe("Path to the file to edit (relative or absolute)"),
1103
+ edits: zod.z.array(ReplaceEditSchema).describe("One or more targeted replacements.")
1104
+ });
1105
+ async function editTool(input, projectCwd) {
1106
+ const absolute = path6__default.default.isAbsolute(input.path) ? input.path : path6__default.default.resolve(projectCwd || process.cwd(), input.path);
1107
+ let content = await promises.readFile(absolute, "utf8");
1108
+ for (const e of input.edits) {
1109
+ const count = content.split(e.oldText).length - 1;
1110
+ if (count !== 1) {
1111
+ return { success: false, error: count === 0 ? "STRING_NOT_FOUND" : "STRING_NOT_UNIQUE" };
1112
+ }
1113
+ content = content.replace(e.oldText, e.newText);
1114
+ }
1115
+ await promises.writeFile(absolute, content, "utf8");
1116
+ return { success: true, message: `Edited ${input.path}` };
1117
+ }
1118
+
1119
+ // ../../node_modules/.bun/balanced-match@4.0.3/node_modules/balanced-match/dist/esm/index.js
1120
+ var balanced = (a3, b, str) => {
1121
+ const ma = a3 instanceof RegExp ? maybeMatch(a3, str) : a3;
1122
+ const mb = b instanceof RegExp ? maybeMatch(b, str) : b;
1123
+ const r = ma !== null && mb != null && range(ma, mb, str);
1124
+ return r && {
1125
+ start: r[0],
1126
+ end: r[1],
1127
+ pre: str.slice(0, r[0]),
1128
+ body: str.slice(r[0] + ma.length, r[1]),
1129
+ post: str.slice(r[1] + mb.length)
1130
+ };
1483
1131
  };
1484
- var bashTool = async (input, projectCwd) => {
1485
- try {
1486
- const safety = evaluateCommandSafety(input.command);
1487
- if (!safety.safe) {
1488
- console.log(`[CLI] Blocked command: ${input.command} \u2014 ${safety.reason}`);
1489
- return {
1490
- success: false,
1491
- message: safety.reason,
1492
- error: "BLOCKED_COMMAND"
1493
- };
1132
+ var maybeMatch = (reg, str) => {
1133
+ const m = str.match(reg);
1134
+ return m ? m[0] : null;
1135
+ };
1136
+ var range = (a3, b, str) => {
1137
+ let begs, beg, left, right = void 0, result;
1138
+ let ai = str.indexOf(a3);
1139
+ let bi = str.indexOf(b, ai + 1);
1140
+ let i = ai;
1141
+ if (ai >= 0 && bi > 0) {
1142
+ if (a3 === b) {
1143
+ return [ai, bi];
1494
1144
  }
1495
- if (input.timeout !== void 0 && input.timeout < 0) {
1496
- return {
1497
- success: false,
1498
- message: `Invalid timeout value: ${input.timeout}. Timeout must be a positive number.`,
1499
- error: "INVALID_TIMEOUT"
1500
- };
1145
+ begs = [];
1146
+ left = str.length;
1147
+ while (i >= 0 && !result) {
1148
+ if (i === ai) {
1149
+ begs.push(i);
1150
+ ai = str.indexOf(a3, i + 1);
1151
+ } else if (begs.length === 1) {
1152
+ const r = begs.pop();
1153
+ if (r !== void 0)
1154
+ result = [r, bi];
1155
+ } else {
1156
+ beg = begs.pop();
1157
+ if (beg !== void 0 && beg < left) {
1158
+ left = beg;
1159
+ right = bi;
1160
+ }
1161
+ bi = str.indexOf(b, i + 1);
1162
+ }
1163
+ i = ai < bi && ai >= 0 ? ai : bi;
1501
1164
  }
1502
- const cwd = input.workdir || projectCwd || process.cwd();
1503
- const timeout = input.timeout ?? DEFAULT_TIMEOUT;
1504
- if (input?.is_background) {
1505
- const proc2 = child_process.spawn("sh", ["-c", input.command], {
1506
- cwd,
1507
- stdio: "ignore",
1508
- detached: true
1509
- });
1510
- proc2.unref();
1511
- console.log(`[LOCAL] Background command started: ${input.command}`);
1512
- return {
1513
- success: true,
1514
- message: `Background command started: ${input.command}`,
1515
- isBackground: true
1516
- };
1517
- } else {
1518
- const result = await runSecureTerminalCommand(
1519
- input.command,
1520
- timeout,
1521
- cwd
1522
- );
1523
- if (result?.error && !result?.exitCode) {
1524
- return result;
1525
- }
1526
- const success = result?.exitCode === 0;
1527
- return {
1528
- success,
1529
- stdout: result?.stdout?.trim(),
1530
- stderr: result?.stderr?.trim(),
1531
- exitCode: result?.exitCode,
1532
- message: success ? `Command executed successfully: ${input.command}` : `Command failed with exit code ${result?.exitCode}: ${input.command}`
1533
- };
1165
+ if (begs.length && right !== void 0) {
1166
+ result = [left, right];
1534
1167
  }
1535
- } catch (error) {
1536
- console.error("Error while executing the terminal command", error);
1537
- return {
1538
- success: false,
1539
- message: "Error while executing the terminal command",
1540
- error: error.message
1541
- };
1542
1168
  }
1169
+ return result;
1543
1170
  };
1544
- function isPathWithinProject2(filePath, projectCwd) {
1545
- try {
1546
- const resolvedCwd = safeRealpath2(projectCwd);
1547
- const resolved = path6__default.default.resolve(resolvedCwd, filePath);
1548
- const resolvedTarget = safeRealpath2(resolved);
1549
- const rel = path6__default.default.relative(resolvedCwd, resolvedTarget);
1550
- if (rel.startsWith("..") || path6__default.default.isAbsolute(rel)) {
1551
- return false;
1552
- }
1553
- return true;
1554
- } catch {
1555
- return false;
1556
- }
1171
+
1172
+ // ../../node_modules/.bun/brace-expansion@5.0.2/node_modules/brace-expansion/dist/esm/index.js
1173
+ var escSlash = "\0SLASH" + Math.random() + "\0";
1174
+ var escOpen = "\0OPEN" + Math.random() + "\0";
1175
+ var escClose = "\0CLOSE" + Math.random() + "\0";
1176
+ var escComma = "\0COMMA" + Math.random() + "\0";
1177
+ var escPeriod = "\0PERIOD" + Math.random() + "\0";
1178
+ var escSlashPattern = new RegExp(escSlash, "g");
1179
+ var escOpenPattern = new RegExp(escOpen, "g");
1180
+ var escClosePattern = new RegExp(escClose, "g");
1181
+ var escCommaPattern = new RegExp(escComma, "g");
1182
+ var escPeriodPattern = new RegExp(escPeriod, "g");
1183
+ var slashPattern = /\\\\/g;
1184
+ var openPattern = /\\{/g;
1185
+ var closePattern = /\\}/g;
1186
+ var commaPattern = /\\,/g;
1187
+ var periodPattern = /\\./g;
1188
+ var EXPANSION_MAX = 1e5;
1189
+ function numeric(str) {
1190
+ return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
1557
1191
  }
1558
- function safeRealpath2(p) {
1559
- try {
1560
- return fs4__namespace.default.realpathSync(p);
1561
- } catch {
1562
- const parent = path6__default.default.dirname(p);
1563
- try {
1564
- const realParent = fs4__namespace.default.realpathSync(parent);
1565
- return path6__default.default.join(realParent, path6__default.default.basename(p));
1566
- } catch {
1567
- return path6__default.default.resolve(p);
1568
- }
1569
- }
1192
+ function escapeBraces(str) {
1193
+ return str.replace(slashPattern, escSlash).replace(openPattern, escOpen).replace(closePattern, escClose).replace(commaPattern, escComma).replace(periodPattern, escPeriod);
1570
1194
  }
1571
- function validatePath(filePath, projectCwd) {
1572
- if (!projectCwd) {
1573
- return {
1574
- valid: false,
1575
- error: "ACCESS_DENIED: No project context provided"
1576
- };
1195
+ function unescapeBraces(str) {
1196
+ return str.replace(escSlashPattern, "\\").replace(escOpenPattern, "{").replace(escClosePattern, "}").replace(escCommaPattern, ",").replace(escPeriodPattern, ".");
1197
+ }
1198
+ function parseCommaParts(str) {
1199
+ if (!str) {
1200
+ return [""];
1577
1201
  }
1578
- try {
1579
- if (!isPathWithinProject2(filePath, projectCwd)) {
1580
- return {
1581
- valid: false,
1582
- error: `ACCESS_DENIED: Path "${filePath}" is outside project directory "${projectCwd}"`
1583
- };
1584
- }
1585
- const resolvedCwd = safeRealpath2(projectCwd);
1586
- const resolvedPath = path6__default.default.resolve(resolvedCwd, filePath);
1587
- return {
1588
- valid: true,
1589
- resolvedPath
1590
- };
1591
- } catch (error) {
1592
- return {
1593
- valid: false,
1594
- error: `ACCESS_DENIED: Invalid path "${filePath}"`
1595
- };
1202
+ const parts = [];
1203
+ const m = balanced("{", "}", str);
1204
+ if (!m) {
1205
+ return str.split(",");
1596
1206
  }
1597
- }
1598
- function resolveProjectPath(filePath, projectCwd) {
1599
- return path6__default.default.resolve(projectCwd, filePath);
1600
- }
1601
-
1602
- // ../agent/src/tools/read-file.ts
1603
- var MAX_FILE_SIZE = 10 * 1024 * 1024;
1604
- var MAX_LINES_RETURNED = 2e3;
1605
- var MAX_LINE_LENGTH = 2e3;
1606
- var MAX_LINE_SUFFIX = `... (line truncated to ${MAX_LINE_LENGTH} chars)`;
1607
- var MAX_BYTES = 50 * 1024;
1608
- var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
1609
- ".zip",
1610
- ".tar",
1611
- ".gz",
1612
- ".exe",
1613
- ".dll",
1614
- ".so",
1615
- ".class",
1616
- ".jar",
1617
- ".war",
1618
- ".7z",
1619
- ".doc",
1620
- ".docx",
1621
- ".xls",
1622
- ".xlsx",
1623
- ".ppt",
1624
- ".pptx",
1625
- ".odt",
1626
- ".ods",
1627
- ".odp",
1628
- ".bin",
1629
- ".dat",
1630
- ".obj",
1631
- ".o",
1632
- ".a",
1633
- ".lib",
1634
- ".wasm",
1635
- ".pyc",
1636
- ".pyo",
1637
- ".ico",
1638
- ".bmp",
1639
- ".ttf",
1640
- ".woff",
1641
- ".woff2",
1642
- ".eot",
1643
- ".mp3",
1644
- ".mp4",
1645
- ".avi",
1646
- ".mov",
1647
- ".flv"
1648
- ]);
1649
- async function isBinaryFile(filepath, fileSize) {
1650
- const ext2 = path6__default.default.extname(filepath).toLowerCase();
1651
- if (BINARY_EXTENSIONS.has(ext2)) return true;
1652
- if (fileSize === 0) return false;
1653
- try {
1654
- const fh = await fsp__namespace.open(filepath, "r");
1655
- try {
1656
- const sampleSize = Math.min(4096, fileSize);
1657
- const bytes = Buffer.alloc(sampleSize);
1658
- const result = await fh.read(bytes, 0, sampleSize, 0);
1659
- if (result.bytesRead === 0) return false;
1660
- let nonPrintableCount = 0;
1661
- for (let i = 0; i < result.bytesRead; i++) {
1662
- if (bytes[i] === 0) return true;
1663
- if (bytes[i] < 9 || bytes[i] > 13 && bytes[i] < 32) {
1664
- nonPrintableCount++;
1665
- }
1666
- }
1667
- return nonPrintableCount / result.bytesRead > 0.3;
1668
- } finally {
1669
- await fh.close();
1670
- }
1671
- } catch {
1672
- return false;
1207
+ const { pre, body, post } = m;
1208
+ const p = pre.split(",");
1209
+ p[p.length - 1] += "{" + body + "}";
1210
+ const postParts = parseCommaParts(post);
1211
+ if (post.length) {
1212
+ p[p.length - 1] += postParts.shift();
1213
+ p.push.apply(p, postParts);
1673
1214
  }
1215
+ parts.push.apply(parts, p);
1216
+ return parts;
1674
1217
  }
1675
- async function findSimilarFiles(filepath) {
1676
- const dir = path6__default.default.dirname(filepath);
1677
- const base = path6__default.default.basename(filepath).toLowerCase();
1678
- try {
1679
- const entries = await fsp__namespace.readdir(dir);
1680
- return entries.filter(
1681
- (entry) => entry.toLowerCase().includes(base) || base.includes(entry.toLowerCase())
1682
- ).map((entry) => path6__default.default.join(dir, entry)).slice(0, 3);
1683
- } catch {
1218
+ function expand(str, options = {}) {
1219
+ if (!str) {
1684
1220
  return [];
1685
1221
  }
1686
- }
1687
- zod.z.object({
1688
- relative_file_path: zod.z.string().describe("The path to the file or directory to read."),
1689
- should_read_entire_file: zod.z.boolean().describe("Whether to read the entire file.").optional().default(true),
1690
- start_line_one_indexed: zod.z.number().optional().describe("The one-indexed line number to start reading from (inclusive). Alias: offset."),
1691
- end_line_one_indexed: zod.z.number().optional().describe("The one-indexed line number to end reading at (inclusive). Alias: offset + limit.")
1692
- });
1693
- async function readFileContent(absolute_file_path, relative_file_path, should_read_entire_file, start_line_one_indexed, end_line_one_indexed) {
1694
- let stat2;
1695
- try {
1696
- stat2 = fs4__namespace.default.statSync(absolute_file_path);
1697
- } catch {
1698
- const suggestions = await findSimilarFiles(absolute_file_path);
1699
- let message = `File not found: ${relative_file_path}`;
1700
- if (suggestions.length > 0) {
1701
- message += `
1702
-
1703
- Did you mean one of these?
1704
- ${suggestions.join("\n")}`;
1705
- }
1706
- return {
1707
- success: false,
1708
- message,
1709
- error: "FILE_NOT_FOUND"
1710
- };
1711
- }
1712
- if (stat2.isDirectory()) {
1713
- try {
1714
- const dirents = await fsp__namespace.readdir(absolute_file_path, { withFileTypes: true });
1715
- const entries = await Promise.all(
1716
- dirents.map(async (dirent) => {
1717
- if (dirent.isDirectory()) return dirent.name + "/";
1718
- if (dirent.isSymbolicLink()) {
1719
- const target = await fsp__namespace.stat(path6__default.default.join(absolute_file_path, dirent.name)).catch(() => void 0);
1720
- if (target?.isDirectory()) return dirent.name + "/";
1721
- }
1722
- return dirent.name;
1723
- })
1724
- );
1725
- entries.sort((a3, b) => a3.localeCompare(b));
1726
- const truncated = entries.length > MAX_LINES_RETURNED;
1727
- const sliced = entries.slice(0, MAX_LINES_RETURNED);
1728
- const output = [
1729
- `<path>${absolute_file_path}</path>`,
1730
- `<type>directory</type>`,
1731
- `<entries>`,
1732
- sliced.join("\n"),
1733
- truncated ? `
1734
- (Showing ${sliced.length} of ${entries.length} entries)` : `
1735
- (${entries.length} entries)`,
1736
- `</entries>`
1737
- ].join("\n");
1738
- return {
1739
- success: true,
1740
- message: `Listed directory: ${relative_file_path} (${entries.length} entries)`,
1741
- content: output,
1742
- totalLines: entries.length,
1743
- truncated
1744
- };
1745
- } catch (err) {
1746
- return {
1747
- success: false,
1748
- message: `Failed to list directory: ${relative_file_path}`,
1749
- error: "READ_ERROR"
1750
- };
1751
- }
1752
- }
1753
- try {
1754
- if (stat2.size > MAX_FILE_SIZE) {
1755
- return {
1756
- success: false,
1757
- 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.`,
1758
- error: "FILE_TOO_LARGE"
1759
- };
1760
- }
1761
- const binary = await isBinaryFile(absolute_file_path, stat2.size);
1762
- if (binary) {
1763
- return {
1764
- success: false,
1765
- message: `Cannot read binary file: ${relative_file_path}`,
1766
- error: "BINARY_FILE"
1767
- };
1768
- }
1769
- const fileContent = await fsp__namespace.readFile(absolute_file_path, "utf8");
1770
- const lines = fileContent.split(/\r?\n/);
1771
- const totalLines = lines.length;
1772
- const start = should_read_entire_file ? 0 : (start_line_one_indexed ?? 1) - 1;
1773
- const end = should_read_entire_file ? Math.min(totalLines, MAX_LINES_RETURNED) : Math.min(end_line_one_indexed ?? totalLines, totalLines);
1774
- if (start >= totalLines && !(totalLines === 0 && start === 0)) {
1775
- return {
1776
- success: false,
1777
- message: `Offset ${start + 1} is out of range for this file (${totalLines} lines)`,
1778
- error: "INVALID_LINE_RANGE"
1779
- };
1780
- }
1781
- const outputLines = [];
1782
- let bytes = 0;
1783
- let truncatedByBytes = false;
1784
- let actualEnd = start;
1785
- for (let i = start; i < end; i++) {
1786
- let line = lines[i];
1787
- if (line.length > MAX_LINE_LENGTH) {
1788
- line = line.substring(0, MAX_LINE_LENGTH) + MAX_LINE_SUFFIX;
1789
- }
1790
- const numberedLine = `${i + 1}: ${line}`;
1791
- const lineBytes = Buffer.byteLength(numberedLine, "utf-8") + (outputLines.length > 0 ? 1 : 0);
1792
- if (bytes + lineBytes > MAX_BYTES && outputLines.length > 0) {
1793
- truncatedByBytes = true;
1794
- break;
1795
- }
1796
- outputLines.push(numberedLine);
1797
- bytes += lineBytes;
1798
- actualEnd = i + 1;
1799
- }
1800
- const hasMoreLines = actualEnd < totalLines;
1801
- const truncated = truncatedByBytes || hasMoreLines || should_read_entire_file && totalLines > MAX_LINES_RETURNED;
1802
- let output = `<path>${absolute_file_path}</path>
1803
- <type>file</type>
1804
- <content>
1805
- `;
1806
- output += outputLines.join("\n");
1807
- if (truncatedByBytes) {
1808
- output += `
1809
-
1810
- (Output capped at ${MAX_BYTES / 1024} KB. Showing lines ${start + 1}-${actualEnd}. Use start_line_one_indexed=${actualEnd + 1} to continue.)`;
1811
- } else if (hasMoreLines && !should_read_entire_file) {
1812
- output += `
1813
-
1814
- (Showing lines ${start + 1}-${actualEnd} of ${totalLines}. Use start_line_one_indexed=${actualEnd + 1} to continue.)`;
1815
- } else {
1816
- output += `
1817
-
1818
- (End of file - total ${totalLines} lines)`;
1819
- }
1820
- output += "\n</content>";
1821
- return {
1822
- success: true,
1823
- message: truncated ? `Read lines ${start + 1}-${actualEnd} of ${totalLines} from: ${relative_file_path} (truncated)` : `Successfully read file: ${relative_file_path} (${totalLines} lines)`,
1824
- content: output,
1825
- totalLines,
1826
- truncated
1827
- };
1828
- } catch (error) {
1829
- return {
1830
- success: false,
1831
- message: `Failed to read file: ${relative_file_path}`,
1832
- error: "READ_ERROR"
1833
- };
1222
+ const { max = EXPANSION_MAX } = options;
1223
+ if (str.slice(0, 2) === "{}") {
1224
+ str = "\\{\\}" + str.slice(2);
1834
1225
  }
1226
+ return expand_(escapeBraces(str), max, true).map(unescapeBraces);
1835
1227
  }
1836
- var read_file = async function(input, projectCwd) {
1837
- const { relative_file_path, should_read_entire_file = true, start_line_one_indexed, end_line_one_indexed } = input;
1838
- try {
1839
- if (!relative_file_path) {
1840
- return {
1841
- success: false,
1842
- message: "Missing required parameter: relative_file_path",
1843
- error: "MISSING_TARGET_FILE"
1844
- };
1228
+ function embrace(str) {
1229
+ return "{" + str + "}";
1230
+ }
1231
+ function isPadded(el) {
1232
+ return /^-?0\d/.test(el);
1233
+ }
1234
+ function lte(i, y2) {
1235
+ return i <= y2;
1236
+ }
1237
+ function gte(i, y2) {
1238
+ return i >= y2;
1239
+ }
1240
+ function expand_(str, max, isTop) {
1241
+ const expansions = [];
1242
+ const m = balanced("{", "}", str);
1243
+ if (!m)
1244
+ return [str];
1245
+ const pre = m.pre;
1246
+ const post = m.post.length ? expand_(m.post, max, false) : [""];
1247
+ if (/\$$/.test(m.pre)) {
1248
+ for (let k = 0; k < post.length && k < max; k++) {
1249
+ const expansion = pre + "{" + m.body + "}" + post[k];
1250
+ expansions.push(expansion);
1845
1251
  }
1846
- if (!should_read_entire_file) {
1847
- if (start_line_one_indexed === void 0 || end_line_one_indexed === void 0) {
1848
- return {
1849
- success: false,
1850
- message: "start_line_one_indexed and end_line_one_indexed are required when should_read_entire_file is false",
1851
- error: "MISSING_LINE_RANGE"
1852
- };
1853
- }
1854
- if (!Number.isInteger(start_line_one_indexed) || start_line_one_indexed < 1) {
1855
- return {
1856
- success: false,
1857
- message: "start_line_one_indexed must be a positive integer (1-indexed)",
1858
- error: "INVALID_START_LINE"
1859
- };
1860
- }
1861
- if (!Number.isInteger(end_line_one_indexed) || end_line_one_indexed < 1) {
1862
- return {
1863
- success: false,
1864
- message: "end_line_one_indexed must be a positive integer (1-indexed)",
1865
- error: "INVALID_END_LINE"
1866
- };
1867
- }
1868
- if (end_line_one_indexed < start_line_one_indexed) {
1869
- return {
1870
- success: false,
1871
- message: "end_line_one_indexed must be greater than or equal to start_line_one_indexed",
1872
- error: "INVALID_LINE_RANGE"
1873
- };
1252
+ } else {
1253
+ const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
1254
+ const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
1255
+ const isSequence = isNumericSequence || isAlphaSequence;
1256
+ const isOptions = m.body.indexOf(",") >= 0;
1257
+ if (!isSequence && !isOptions) {
1258
+ if (m.post.match(/,(?!,).*\}/)) {
1259
+ str = m.pre + "{" + m.body + escClose + m.post;
1260
+ return expand_(str, max, true);
1874
1261
  }
1262
+ return [str];
1875
1263
  }
1876
- let absolute_file_path;
1877
- if (projectCwd) {
1878
- const validation = validatePath(relative_file_path, projectCwd);
1879
- if (!validation.valid) {
1880
- return {
1881
- success: false,
1882
- message: validation.error || "Path validation failed",
1883
- error: "ACCESS_DENIED"
1884
- };
1885
- }
1886
- absolute_file_path = validation.resolvedPath;
1264
+ let n;
1265
+ if (isSequence) {
1266
+ n = m.body.split(/\.\./);
1887
1267
  } else {
1888
- absolute_file_path = path6__default.default.resolve(relative_file_path);
1889
- }
1890
- return await readFileContent(
1891
- absolute_file_path,
1892
- relative_file_path,
1893
- should_read_entire_file,
1894
- start_line_one_indexed,
1895
- end_line_one_indexed
1896
- );
1897
- } catch {
1898
- return {
1899
- success: false,
1900
- message: `Failed to read file: ${relative_file_path}`,
1901
- error: "READ_ERROR"
1902
- };
1903
- }
1904
- };
1905
- zod.z.object({
1906
- path: zod.z.string().describe("Relative file path to delete")
1907
- });
1908
- var deleteFile = async function(input, projectCwd) {
1909
- const { path: realPath } = input;
1910
- if (!realPath) {
1911
- return {
1912
- success: false,
1913
- message: "Missing required parameter: path",
1914
- error: "MISSING_PATH"
1915
- };
1916
- }
1917
- if (projectCwd) {
1918
- const validation = validatePath(realPath, projectCwd);
1919
- if (!validation.valid) {
1920
- return {
1921
- success: false,
1922
- message: validation.error || "Path validation failed",
1923
- error: "ACCESS_DENIED"
1924
- };
1925
- }
1926
- }
1927
- try {
1928
- const basePath = projectCwd || process.cwd();
1929
- const absolute_file_path = resolveProjectPath(realPath, basePath);
1930
- if (!absolute_file_path) {
1931
- return {
1932
- success: false,
1933
- message: "Invalid file path",
1934
- error: "INVALID_FILE_PATH"
1935
- };
1936
- }
1937
- let exists = true;
1938
- try {
1939
- await fsp.access(absolute_file_path, fs4.constants.F_OK);
1940
- } catch {
1941
- exists = false;
1942
- }
1943
- if (!exists) {
1944
- return {
1945
- success: false,
1946
- message: `File not found: ${realPath}`,
1947
- error: "FILE_NOT_FOUND"
1948
- };
1949
- }
1950
- let originalContent;
1951
- try {
1952
- originalContent = await fsp.readFile(absolute_file_path, "utf8");
1953
- } catch {
1954
- return {
1955
- success: false,
1956
- message: `Failed to read file before deletion: ${realPath}`,
1957
- error: "READ_ERROR"
1958
- };
1959
- }
1960
- try {
1961
- await fsp.unlink(absolute_file_path);
1962
- } catch {
1963
- return {
1964
- success: false,
1965
- message: `Failed to delete file: ${realPath}`,
1966
- error: "DELETE_ERROR"
1967
- };
1968
- }
1969
- return {
1970
- success: true,
1971
- message: `Successfully deleted file: ${realPath}`,
1972
- content: originalContent
1973
- };
1974
- } catch (error) {
1975
- return {
1976
- success: false,
1977
- message: `Failed to delete file: ${realPath}`,
1978
- error: "DELETE_ERROR"
1979
- };
1980
- }
1981
- };
1982
- var GREP_LIMITS = {
1983
- DEFAULT_MAX_MATCHES: 200,
1984
- MAX_LINE_LENGTH: 2e3,
1985
- // aligned with OpenCode's 2000-char truncation
1986
- MAX_TOTAL_OUTPUT_SIZE: 1 * 1024 * 1024,
1987
- EXECUTION_TIMEOUT_MS: 15e3,
1988
- TRUNCATION_MESSAGE: "\n[Results truncated due to size limits. Use more specific patterns or file filters to narrow your search.]"
1989
- };
1990
- zod.z.object({
1991
- query: zod.z.string().describe("The regex pattern to search for"),
1992
- options: zod.z.object({
1993
- includePattern: zod.z.string().optional().describe('Glob pattern for files to include (e.g., "*.ts", "*.{ts,tsx}")'),
1994
- excludePattern: zod.z.string().optional().describe("Glob pattern for files to exclude"),
1995
- caseSensitive: zod.z.boolean().optional().describe("Whether the search should be case sensitive"),
1996
- path: zod.z.string().optional().describe("Subdirectory to search in"),
1997
- sortByMtime: zod.z.boolean().optional().describe("Sort results by file modification time (default: true)")
1998
- }).optional()
1999
- });
2000
- var _cachedRgPath = null;
2001
- var _cachedRgChecked = false;
2002
- async function getRipgrepPath() {
2003
- if (_cachedRgChecked) return _cachedRgPath;
2004
- const candidates = [];
2005
- if (process.env.RG_PATH) {
2006
- candidates.push(process.env.RG_PATH);
2007
- }
2008
- candidates.push("/opt/homebrew/bin/rg", "/usr/local/bin/rg", "/usr/bin/rg");
2009
- const pathEntries = process.env.PATH?.split(path6__default.default.delimiter) ?? [];
2010
- const rgNames = process.platform === "win32" ? ["rg.exe", "rg"] : ["rg"];
2011
- for (const entry of pathEntries) {
2012
- for (const name of rgNames) {
2013
- candidates.push(path6__default.default.join(entry, name));
2014
- }
2015
- }
2016
- for (const rgPath of candidates) {
2017
- if (rgPath && fs4__namespace.default.existsSync(rgPath)) {
2018
- _cachedRgPath = rgPath;
2019
- _cachedRgChecked = true;
2020
- return rgPath;
2021
- }
2022
- }
2023
- _cachedRgChecked = true;
2024
- _cachedRgPath = null;
2025
- return null;
2026
- }
2027
- getRipgrepPath();
2028
- async function getMtimesBatched(files) {
2029
- const mtimeMap = /* @__PURE__ */ new Map();
2030
- const BATCH_SIZE = 50;
2031
- for (let i = 0; i < files.length; i += BATCH_SIZE) {
2032
- const batch = files.slice(i, i + BATCH_SIZE);
2033
- const results = await Promise.all(
2034
- batch.map(async (filePath) => {
2035
- const mtime = await fsp__namespace.default.stat(filePath).then((stats) => stats.mtimeMs).catch(() => 0);
2036
- return { path: filePath, mtime };
2037
- })
2038
- );
2039
- results.forEach(({ path: path17, mtime }) => mtimeMap.set(path17, mtime));
2040
- }
2041
- return mtimeMap;
2042
- }
2043
- var grepTool = async function(input, projectCwd) {
2044
- const { query, options } = input;
2045
- if (!query || query.trim() === "") {
2046
- return {
2047
- success: false,
2048
- message: "Missing required parameter: query",
2049
- error: "MISSING_QUERY"
2050
- };
2051
- }
2052
- try {
2053
- const { includePattern, excludePattern, caseSensitive, path: subPath, sortByMtime = true } = options || {};
2054
- let searchDir = projectCwd || process.cwd();
2055
- if (subPath) {
2056
- searchDir = path6__default.default.isAbsolute(subPath) ? subPath : path6__default.default.resolve(searchDir, subPath);
2057
- if (projectCwd) {
2058
- const validation = validatePath(subPath, projectCwd);
2059
- if (!validation.valid) {
2060
- return {
2061
- success: false,
2062
- message: validation.error || "Path validation failed",
2063
- error: "ACCESS_DENIED"
2064
- };
1268
+ n = parseCommaParts(m.body);
1269
+ if (n.length === 1 && n[0] !== void 0) {
1270
+ n = expand_(n[0], max, false).map(embrace);
1271
+ if (n.length === 1) {
1272
+ return post.map((p) => m.pre + n[0] + p);
2065
1273
  }
2066
1274
  }
2067
1275
  }
2068
- if (!fs4__namespace.default.existsSync(searchDir)) {
2069
- return {
2070
- success: false,
2071
- message: `Directory not found: ${searchDir}`,
2072
- error: "DIR_NOT_FOUND"
2073
- };
2074
- }
2075
- const rgPath = await getRipgrepPath();
2076
- if (!rgPath) {
2077
- return {
2078
- success: false,
2079
- message: "Ripgrep (rg) not found on PATH. Install ripgrep to use this tool.",
2080
- error: "GREP_NOT_FOUND"
2081
- };
2082
- }
2083
- const args = [
2084
- "-nH",
2085
- // line numbers + filename (compact form, matching OpenCode)
2086
- "--hidden",
2087
- // search hidden files (aligned with OpenCode)
2088
- "--no-messages",
2089
- // suppress error messages for unreadable files
2090
- "--color=never",
2091
- `--max-count=${GREP_LIMITS.DEFAULT_MAX_MATCHES}`,
2092
- "--max-columns=2000"
2093
- ];
2094
- if (!caseSensitive) {
2095
- args.push("-i");
2096
- }
2097
- if (includePattern) {
2098
- args.push("--glob", includePattern);
2099
- }
2100
- if (excludePattern) {
2101
- args.push("--glob", `!${excludePattern}`);
2102
- }
2103
- args.push("--glob", "!node_modules/**");
2104
- args.push("--glob", "!.git/**");
2105
- args.push("--glob", "!dist/**");
2106
- args.push("--glob", "!build/**");
2107
- args.push("--glob", "!*.min.js");
2108
- args.push("--glob", "!*.min.css");
2109
- args.push("--glob", "!package-lock.json");
2110
- args.push("--glob", "!yarn.lock");
2111
- args.push("--glob", "!bun.lockb");
2112
- args.push("--glob", "!pnpm-lock.yaml");
2113
- args.push("--regexp", query);
2114
- args.push(searchDir);
2115
- const proc2 = child_process.spawn(rgPath, args, {
2116
- stdio: ["ignore", "pipe", "pipe"]
2117
- });
2118
- let timedOut = false;
2119
- let stdout = "";
2120
- let stderr = "";
2121
- let outputTruncated = false;
2122
- const timeoutId = setTimeout(() => {
2123
- timedOut = true;
2124
- proc2.kill("SIGTERM");
2125
- }, GREP_LIMITS.EXECUTION_TIMEOUT_MS);
2126
- if (proc2.stdout) {
2127
- proc2.stdout.on("data", (chunk) => {
2128
- const text = chunk.toString();
2129
- if (stdout.length >= GREP_LIMITS.MAX_TOTAL_OUTPUT_SIZE) {
2130
- outputTruncated = true;
2131
- return;
2132
- }
2133
- const remaining = GREP_LIMITS.MAX_TOTAL_OUTPUT_SIZE - stdout.length;
2134
- if (text.length > remaining) {
2135
- stdout += text.slice(0, remaining);
2136
- outputTruncated = true;
2137
- return;
2138
- }
2139
- stdout += text;
2140
- });
2141
- }
2142
- if (proc2.stderr) {
2143
- proc2.stderr.on("data", (chunk) => {
2144
- stderr += chunk.toString();
2145
- });
2146
- }
2147
- const exitCode = await new Promise((resolve, reject) => {
2148
- proc2.once("error", reject);
2149
- proc2.once("close", (code) => resolve(code));
2150
- });
2151
- clearTimeout(timeoutId);
2152
- if (timedOut) {
2153
- return {
2154
- success: false,
2155
- message: `Search timed out after ${GREP_LIMITS.EXECUTION_TIMEOUT_MS}ms. Use more specific patterns.`,
2156
- error: "GREP_TIMEOUT"
2157
- };
2158
- }
2159
- if (exitCode === 1) {
2160
- return {
2161
- success: true,
2162
- matches: [],
2163
- detailedMatches: [],
2164
- query,
2165
- matchCount: 0,
2166
- message: `No matches found for pattern: ${query}`
2167
- };
2168
- }
2169
- if (exitCode !== 0 && exitCode !== 2) {
2170
- return {
2171
- success: false,
2172
- message: `Ripgrep error: ${stderr || "Unknown error"}`,
2173
- error: "GREP_EXEC_ERROR"
2174
- };
2175
- }
2176
- const lines = stdout.trim().split("\n").filter((line) => line.length > 0);
2177
- const rawMatches = [];
2178
- const uniqueFiles = /* @__PURE__ */ new Set();
2179
- for (const line of lines) {
2180
- const firstColon = line.indexOf(":");
2181
- const secondColon = line.indexOf(":", firstColon + 1);
2182
- if (firstColon > 0 && secondColon > firstColon) {
2183
- const file = line.substring(0, firstColon);
2184
- const lineNumber = parseInt(line.substring(firstColon + 1, secondColon), 10);
2185
- let content = line.substring(secondColon + 1);
2186
- if (content.length > GREP_LIMITS.MAX_LINE_LENGTH) {
2187
- content = content.substring(0, GREP_LIMITS.MAX_LINE_LENGTH) + "...";
1276
+ let N;
1277
+ if (isSequence && n[0] !== void 0 && n[1] !== void 0) {
1278
+ const x2 = numeric(n[0]);
1279
+ const y2 = numeric(n[1]);
1280
+ const width = Math.max(n[0].length, n[1].length);
1281
+ let incr = n.length === 3 && n[2] !== void 0 ? Math.abs(numeric(n[2])) : 1;
1282
+ let test = lte;
1283
+ const reverse = y2 < x2;
1284
+ if (reverse) {
1285
+ incr *= -1;
1286
+ test = gte;
1287
+ }
1288
+ const pad = n.some(isPadded);
1289
+ N = [];
1290
+ for (let i = x2; test(i, y2); i += incr) {
1291
+ let c;
1292
+ if (isAlphaSequence) {
1293
+ c = String.fromCharCode(i);
1294
+ if (c === "\\") {
1295
+ c = "";
1296
+ }
1297
+ } else {
1298
+ c = String(i);
1299
+ if (pad) {
1300
+ const need = width - c.length;
1301
+ if (need > 0) {
1302
+ const z10 = new Array(need + 1).join("0");
1303
+ if (i < 0) {
1304
+ c = "-" + z10 + c.slice(1);
1305
+ } else {
1306
+ c = z10 + c;
1307
+ }
1308
+ }
1309
+ }
2188
1310
  }
2189
- rawMatches.push({
2190
- file,
2191
- lineNumber,
2192
- content: content.trim(),
2193
- mtime: 0
2194
- });
2195
- uniqueFiles.add(file);
1311
+ N.push(c);
2196
1312
  }
2197
- }
2198
- if (sortByMtime && uniqueFiles.size > 0) {
2199
- const mtimeMap = await getMtimesBatched(Array.from(uniqueFiles));
2200
- for (const match2 of rawMatches) {
2201
- match2.mtime = mtimeMap.get(match2.file) || 0;
1313
+ } else {
1314
+ N = [];
1315
+ for (let j = 0; j < n.length; j++) {
1316
+ N.push.apply(N, expand_(n[j], max, false));
2202
1317
  }
2203
- rawMatches.sort((a3, b) => {
2204
- if (b.mtime !== a3.mtime) return b.mtime - a3.mtime;
2205
- return a3.file.localeCompare(b.file);
2206
- });
2207
1318
  }
2208
- const truncated = rawMatches.length > GREP_LIMITS.DEFAULT_MAX_MATCHES || outputTruncated;
2209
- const finalMatches = truncated ? rawMatches.slice(0, GREP_LIMITS.DEFAULT_MAX_MATCHES) : rawMatches;
2210
- const detailedMatches = finalMatches.map((m) => ({
2211
- file: m.file,
2212
- lineNumber: m.lineNumber,
2213
- content: m.content
2214
- }));
2215
- const matches = finalMatches.map(
2216
- (m) => `${m.file}:${m.lineNumber}:${m.content}`
2217
- );
2218
- const groupedOutput = [`Found ${finalMatches.length} matches`];
2219
- let currentFile = "";
2220
- for (const match2 of finalMatches) {
2221
- if (currentFile !== match2.file) {
2222
- if (currentFile !== "") {
2223
- groupedOutput.push("");
2224
- }
2225
- currentFile = match2.file;
2226
- groupedOutput.push(`${match2.file}:`);
2227
- }
2228
- groupedOutput.push(` Line ${match2.lineNumber}: ${match2.content}`);
2229
- }
2230
- if (truncated) {
2231
- groupedOutput.push("");
2232
- groupedOutput.push(GREP_LIMITS.TRUNCATION_MESSAGE);
2233
- }
2234
- return {
2235
- success: true,
2236
- matches,
2237
- detailedMatches,
2238
- query,
2239
- matchCount: finalMatches.length,
2240
- truncated,
2241
- message: `Found ${finalMatches.length} matches for pattern: ${query}`,
2242
- content: groupedOutput.join("\n")
2243
- };
2244
- } catch (error) {
2245
- console.error("[grep] error:", error);
2246
- return {
2247
- success: false,
2248
- message: error?.message || String(error),
2249
- error: "GREP_EXEC_ERROR"
2250
- };
2251
- }
2252
- };
2253
-
2254
- // ../../node_modules/.bun/balanced-match@4.0.3/node_modules/balanced-match/dist/esm/index.js
2255
- var balanced = (a3, b, str) => {
2256
- const ma = a3 instanceof RegExp ? maybeMatch(a3, str) : a3;
2257
- const mb = b instanceof RegExp ? maybeMatch(b, str) : b;
2258
- const r = ma !== null && mb != null && range(ma, mb, str);
2259
- return r && {
2260
- start: r[0],
2261
- end: r[1],
2262
- pre: str.slice(0, r[0]),
2263
- body: str.slice(r[0] + ma.length, r[1]),
2264
- post: str.slice(r[1] + mb.length)
2265
- };
2266
- };
2267
- var maybeMatch = (reg, str) => {
2268
- const m = str.match(reg);
2269
- return m ? m[0] : null;
2270
- };
2271
- var range = (a3, b, str) => {
2272
- let begs, beg, left, right = void 0, result;
2273
- let ai = str.indexOf(a3);
2274
- let bi = str.indexOf(b, ai + 1);
2275
- let i = ai;
2276
- if (ai >= 0 && bi > 0) {
2277
- if (a3 === b) {
2278
- return [ai, bi];
2279
- }
2280
- begs = [];
2281
- left = str.length;
2282
- while (i >= 0 && !result) {
2283
- if (i === ai) {
2284
- begs.push(i);
2285
- ai = str.indexOf(a3, i + 1);
2286
- } else if (begs.length === 1) {
2287
- const r = begs.pop();
2288
- if (r !== void 0)
2289
- result = [r, bi];
2290
- } else {
2291
- beg = begs.pop();
2292
- if (beg !== void 0 && beg < left) {
2293
- left = beg;
2294
- right = bi;
2295
- }
2296
- bi = str.indexOf(b, i + 1);
2297
- }
2298
- i = ai < bi && ai >= 0 ? ai : bi;
2299
- }
2300
- if (begs.length && right !== void 0) {
2301
- result = [left, right];
2302
- }
2303
- }
2304
- return result;
2305
- };
2306
-
2307
- // ../../node_modules/.bun/brace-expansion@5.0.2/node_modules/brace-expansion/dist/esm/index.js
2308
- var escSlash = "\0SLASH" + Math.random() + "\0";
2309
- var escOpen = "\0OPEN" + Math.random() + "\0";
2310
- var escClose = "\0CLOSE" + Math.random() + "\0";
2311
- var escComma = "\0COMMA" + Math.random() + "\0";
2312
- var escPeriod = "\0PERIOD" + Math.random() + "\0";
2313
- var escSlashPattern = new RegExp(escSlash, "g");
2314
- var escOpenPattern = new RegExp(escOpen, "g");
2315
- var escClosePattern = new RegExp(escClose, "g");
2316
- var escCommaPattern = new RegExp(escComma, "g");
2317
- var escPeriodPattern = new RegExp(escPeriod, "g");
2318
- var slashPattern = /\\\\/g;
2319
- var openPattern = /\\{/g;
2320
- var closePattern = /\\}/g;
2321
- var commaPattern = /\\,/g;
2322
- var periodPattern = /\\./g;
2323
- var EXPANSION_MAX = 1e5;
2324
- function numeric(str) {
2325
- return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
2326
- }
2327
- function escapeBraces(str) {
2328
- return str.replace(slashPattern, escSlash).replace(openPattern, escOpen).replace(closePattern, escClose).replace(commaPattern, escComma).replace(periodPattern, escPeriod);
2329
- }
2330
- function unescapeBraces(str) {
2331
- return str.replace(escSlashPattern, "\\").replace(escOpenPattern, "{").replace(escClosePattern, "}").replace(escCommaPattern, ",").replace(escPeriodPattern, ".");
2332
- }
2333
- function parseCommaParts(str) {
2334
- if (!str) {
2335
- return [""];
2336
- }
2337
- const parts = [];
2338
- const m = balanced("{", "}", str);
2339
- if (!m) {
2340
- return str.split(",");
2341
- }
2342
- const { pre, body, post } = m;
2343
- const p = pre.split(",");
2344
- p[p.length - 1] += "{" + body + "}";
2345
- const postParts = parseCommaParts(post);
2346
- if (post.length) {
2347
- p[p.length - 1] += postParts.shift();
2348
- p.push.apply(p, postParts);
2349
- }
2350
- parts.push.apply(parts, p);
2351
- return parts;
2352
- }
2353
- function expand(str, options = {}) {
2354
- if (!str) {
2355
- return [];
2356
- }
2357
- const { max = EXPANSION_MAX } = options;
2358
- if (str.slice(0, 2) === "{}") {
2359
- str = "\\{\\}" + str.slice(2);
2360
- }
2361
- return expand_(escapeBraces(str), max, true).map(unescapeBraces);
2362
- }
2363
- function embrace(str) {
2364
- return "{" + str + "}";
2365
- }
2366
- function isPadded(el) {
2367
- return /^-?0\d/.test(el);
2368
- }
2369
- function lte(i, y2) {
2370
- return i <= y2;
2371
- }
2372
- function gte(i, y2) {
2373
- return i >= y2;
2374
- }
2375
- function expand_(str, max, isTop) {
2376
- const expansions = [];
2377
- const m = balanced("{", "}", str);
2378
- if (!m)
2379
- return [str];
2380
- const pre = m.pre;
2381
- const post = m.post.length ? expand_(m.post, max, false) : [""];
2382
- if (/\$$/.test(m.pre)) {
2383
- for (let k = 0; k < post.length && k < max; k++) {
2384
- const expansion = pre + "{" + m.body + "}" + post[k];
2385
- expansions.push(expansion);
2386
- }
2387
- } else {
2388
- const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
2389
- const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
2390
- const isSequence = isNumericSequence || isAlphaSequence;
2391
- const isOptions = m.body.indexOf(",") >= 0;
2392
- if (!isSequence && !isOptions) {
2393
- if (m.post.match(/,(?!,).*\}/)) {
2394
- str = m.pre + "{" + m.body + escClose + m.post;
2395
- return expand_(str, max, true);
2396
- }
2397
- return [str];
2398
- }
2399
- let n;
2400
- if (isSequence) {
2401
- n = m.body.split(/\.\./);
2402
- } else {
2403
- n = parseCommaParts(m.body);
2404
- if (n.length === 1 && n[0] !== void 0) {
2405
- n = expand_(n[0], max, false).map(embrace);
2406
- if (n.length === 1) {
2407
- return post.map((p) => m.pre + n[0] + p);
2408
- }
2409
- }
2410
- }
2411
- let N;
2412
- if (isSequence && n[0] !== void 0 && n[1] !== void 0) {
2413
- const x2 = numeric(n[0]);
2414
- const y2 = numeric(n[1]);
2415
- const width = Math.max(n[0].length, n[1].length);
2416
- let incr = n.length === 3 && n[2] !== void 0 ? Math.abs(numeric(n[2])) : 1;
2417
- let test = lte;
2418
- const reverse = y2 < x2;
2419
- if (reverse) {
2420
- incr *= -1;
2421
- test = gte;
2422
- }
2423
- const pad = n.some(isPadded);
2424
- N = [];
2425
- for (let i = x2; test(i, y2); i += incr) {
2426
- let c;
2427
- if (isAlphaSequence) {
2428
- c = String.fromCharCode(i);
2429
- if (c === "\\") {
2430
- c = "";
2431
- }
2432
- } else {
2433
- c = String(i);
2434
- if (pad) {
2435
- const need = width - c.length;
2436
- if (need > 0) {
2437
- const z13 = new Array(need + 1).join("0");
2438
- if (i < 0) {
2439
- c = "-" + z13 + c.slice(1);
2440
- } else {
2441
- c = z13 + c;
2442
- }
2443
- }
2444
- }
2445
- }
2446
- N.push(c);
2447
- }
2448
- } else {
2449
- N = [];
2450
- for (let j = 0; j < n.length; j++) {
2451
- N.push.apply(N, expand_(n[j], max, false));
2452
- }
2453
- }
2454
- for (let j = 0; j < N.length; j++) {
2455
- for (let k = 0; k < post.length && expansions.length < max; k++) {
2456
- const expansion = pre + N[j] + post[k];
2457
- if (!isTop || isSequence || expansion) {
2458
- expansions.push(expansion);
1319
+ for (let j = 0; j < N.length; j++) {
1320
+ for (let k = 0; k < post.length && expansions.length < max; k++) {
1321
+ const expansion = pre + N[j] + post[k];
1322
+ if (!isTop || isSequence || expansion) {
1323
+ expansions.push(expansion);
2459
1324
  }
2460
1325
  }
2461
1326
  }
@@ -3140,11 +2005,11 @@ var qmarksTestNoExtDot = ([$0]) => {
3140
2005
  return (f) => f.length === len && f !== "." && f !== "..";
3141
2006
  };
3142
2007
  var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
3143
- var path13 = {
2008
+ var path9 = {
3144
2009
  win32: { sep: "\\" },
3145
2010
  posix: { sep: "/" }
3146
2011
  };
3147
- var sep = defaultPlatform === "win32" ? path13.win32.sep : path13.posix.sep;
2012
+ var sep = defaultPlatform === "win32" ? path9.win32.sep : path9.posix.sep;
3148
2013
  minimatch.sep = sep;
3149
2014
  var GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
3150
2015
  minimatch.GLOBSTAR = GLOBSTAR;
@@ -3186,7 +2051,7 @@ var defaults = (def) => {
3186
2051
  defaults: (options) => orig.defaults(ext(def, options)),
3187
2052
  makeRe: (pattern, options = {}) => orig.makeRe(pattern, ext(def, options)),
3188
2053
  braceExpand: (pattern, options = {}) => orig.braceExpand(pattern, ext(def, options)),
3189
- match: (list2, pattern, options = {}) => orig.match(list2, pattern, ext(def, options)),
2054
+ match: (list, pattern, options = {}) => orig.match(list, pattern, ext(def, options)),
3190
2055
  sep: orig.sep,
3191
2056
  GLOBSTAR
3192
2057
  });
@@ -3202,13 +2067,13 @@ var braceExpand = (pattern, options = {}) => {
3202
2067
  minimatch.braceExpand = braceExpand;
3203
2068
  var makeRe = (pattern, options = {}) => new Minimatch(pattern, options).makeRe();
3204
2069
  minimatch.makeRe = makeRe;
3205
- var match = (list2, pattern, options = {}) => {
2070
+ var match = (list, pattern, options = {}) => {
3206
2071
  const mm = new Minimatch(pattern, options);
3207
- list2 = list2.filter((f) => mm.match(f));
3208
- if (mm.options.nonull && !list2.length) {
3209
- list2.push(pattern);
2072
+ list = list.filter((f) => mm.match(f));
2073
+ if (mm.options.nonull && !list.length) {
2074
+ list.push(pattern);
3210
2075
  }
3211
- return list2;
2076
+ return list;
3212
2077
  };
3213
2078
  minimatch.match = match;
3214
2079
  var globMagic = /[?*]|[+@!]\(.*?\)|\[|\]/;
@@ -3741,10 +2606,10 @@ var Minimatch = class {
3741
2606
  }
3742
2607
  return filtered.join("/");
3743
2608
  }).join("|");
3744
- const [open2, close] = set.length > 1 ? ["(?:", ")"] : ["", ""];
3745
- re = "^" + open2 + re + close + "$";
2609
+ const [open, close] = set.length > 1 ? ["(?:", ")"] : ["", ""];
2610
+ re = "^" + open + re + close + "$";
3746
2611
  if (this.partial) {
3747
- re = "^(?:\\/|" + open2 + re.slice(1, -1) + close + ")$";
2612
+ re = "^(?:\\/|" + open + re.slice(1, -1) + close + ")$";
3748
2613
  }
3749
2614
  if (this.negate)
3750
2615
  re = "^(?!" + re + ").+$";
@@ -3854,8 +2719,8 @@ if (typeof C > "u") {
3854
2719
  }
3855
2720
  var G = (a3) => !I.has(a3);
3856
2721
  var y = (a3) => a3 && a3 === Math.floor(a3) && a3 > 0 && isFinite(a3);
3857
- var U = (a3) => y(a3) ? a3 <= Math.pow(2, 8) ? Uint8Array : a3 <= Math.pow(2, 16) ? Uint16Array : a3 <= Math.pow(2, 32) ? Uint32Array : a3 <= Number.MAX_SAFE_INTEGER ? z6 : null : null;
3858
- var z6 = class extends Array {
2722
+ var U = (a3) => y(a3) ? a3 <= Math.pow(2, 8) ? Uint8Array : a3 <= Math.pow(2, 16) ? Uint16Array : a3 <= Math.pow(2, 32) ? Uint32Array : a3 <= Number.MAX_SAFE_INTEGER ? z3 : null : null;
2723
+ var z3 = class extends Array {
3859
2724
  constructor(t) {
3860
2725
  super(t), this.fill(0);
3861
2726
  }
@@ -3993,7 +2858,7 @@ var L = class a2 {
3993
2858
  return this.#s.has(t) ? 1 / 0 : 0;
3994
2859
  }
3995
2860
  #j() {
3996
- let t = new z6(this.#o), e = new z6(this.#o);
2861
+ let t = new z3(this.#o), e = new z3(this.#o);
3997
2862
  this.#d = t, this.#A = e;
3998
2863
  let i = this.ttlAutopurge ? new Array(this.#o) : void 0;
3999
2864
  this.#g = i, this.#N = (n, o, r = this.#m.now()) => {
@@ -4043,7 +2908,7 @@ var L = class a2 {
4043
2908
  };
4044
2909
  #p = () => false;
4045
2910
  #B() {
4046
- let t = new z6(this.#o);
2911
+ let t = new z3(this.#o);
4047
2912
  this.#_ = 0, this.#y = t, this.#W = (e) => {
4048
2913
  this.#_ -= t[e], t[e] = 0;
4049
2914
  }, this.#P = (e, i, s, h) => {
@@ -5246,10 +4111,10 @@ var defaultFS = {
5246
4111
  readlinkSync: fs4.readlinkSync,
5247
4112
  realpathSync,
5248
4113
  promises: {
5249
- lstat: fsp.lstat,
5250
- readdir: fsp.readdir,
5251
- readlink: fsp.readlink,
5252
- realpath: fsp.realpath
4114
+ lstat: promises.lstat,
4115
+ readdir: promises.readdir,
4116
+ readlink: promises.readlink,
4117
+ realpath: promises.realpath
5253
4118
  }
5254
4119
  };
5255
4120
  var fsFromOption = (fsOption) => !fsOption || fsOption === defaultFS || fsOption === fs4__namespace ? defaultFS : {
@@ -5504,12 +4369,12 @@ var PathBase = class {
5504
4369
  /**
5505
4370
  * Get the Path object referenced by the string path, resolved from this Path
5506
4371
  */
5507
- resolve(path17) {
5508
- if (!path17) {
4372
+ resolve(path15) {
4373
+ if (!path15) {
5509
4374
  return this;
5510
4375
  }
5511
- const rootPath = this.getRootString(path17);
5512
- const dir = path17.substring(rootPath.length);
4376
+ const rootPath = this.getRootString(path15);
4377
+ const dir = path15.substring(rootPath.length);
5513
4378
  const dirParts = dir.split(this.splitSep);
5514
4379
  const result = rootPath ? this.getRoot(rootPath).#resolveParts(dirParts) : this.#resolveParts(dirParts);
5515
4380
  return result;
@@ -6261,8 +5126,8 @@ var PathWin32 = class _PathWin32 extends PathBase {
6261
5126
  /**
6262
5127
  * @internal
6263
5128
  */
6264
- getRootString(path17) {
6265
- return path6.win32.parse(path17).root;
5129
+ getRootString(path15) {
5130
+ return path6.win32.parse(path15).root;
6266
5131
  }
6267
5132
  /**
6268
5133
  * @internal
@@ -6308,8 +5173,8 @@ var PathPosix = class _PathPosix extends PathBase {
6308
5173
  /**
6309
5174
  * @internal
6310
5175
  */
6311
- getRootString(path17) {
6312
- return path17.startsWith("/") ? "/" : "";
5176
+ getRootString(path15) {
5177
+ return path15.startsWith("/") ? "/" : "";
6313
5178
  }
6314
5179
  /**
6315
5180
  * @internal
@@ -6358,8 +5223,8 @@ var PathScurryBase = class {
6358
5223
  *
6359
5224
  * @internal
6360
5225
  */
6361
- constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs: fs12 = defaultFS } = {}) {
6362
- this.#fs = fsFromOption(fs12);
5226
+ constructor(cwd = process.cwd(), pathImpl, sep2, { nocase, childrenCacheSize = 16 * 1024, fs: fs6 = defaultFS } = {}) {
5227
+ this.#fs = fsFromOption(fs6);
6363
5228
  if (cwd instanceof URL || cwd.startsWith("file://")) {
6364
5229
  cwd = url.fileURLToPath(cwd);
6365
5230
  }
@@ -6398,11 +5263,11 @@ var PathScurryBase = class {
6398
5263
  /**
6399
5264
  * Get the depth of a provided path, string, or the cwd
6400
5265
  */
6401
- depth(path17 = this.cwd) {
6402
- if (typeof path17 === "string") {
6403
- path17 = this.cwd.resolve(path17);
5266
+ depth(path15 = this.cwd) {
5267
+ if (typeof path15 === "string") {
5268
+ path15 = this.cwd.resolve(path15);
6404
5269
  }
6405
- return path17.depth();
5270
+ return path15.depth();
6406
5271
  }
6407
5272
  /**
6408
5273
  * Return the cache of child entries. Exposed so subclasses can create
@@ -6889,9 +5754,9 @@ var PathScurryBase = class {
6889
5754
  process2();
6890
5755
  return results;
6891
5756
  }
6892
- chdir(path17 = this.cwd) {
5757
+ chdir(path15 = this.cwd) {
6893
5758
  const oldCwd = this.cwd;
6894
- this.cwd = typeof path17 === "string" ? this.cwd.resolve(path17) : path17;
5759
+ this.cwd = typeof path15 === "string" ? this.cwd.resolve(path15) : path15;
6895
5760
  this.cwd[setAsCwd](oldCwd);
6896
5761
  }
6897
5762
  };
@@ -6917,8 +5782,8 @@ var PathScurryWin32 = class extends PathScurryBase {
6917
5782
  /**
6918
5783
  * @internal
6919
5784
  */
6920
- newRoot(fs12) {
6921
- return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs12 });
5785
+ newRoot(fs6) {
5786
+ return new PathWin32(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs6 });
6922
5787
  }
6923
5788
  /**
6924
5789
  * Return true if the provided path string is an absolute path
@@ -6946,8 +5811,8 @@ var PathScurryPosix = class extends PathScurryBase {
6946
5811
  /**
6947
5812
  * @internal
6948
5813
  */
6949
- newRoot(fs12) {
6950
- return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs12 });
5814
+ newRoot(fs6) {
5815
+ return new PathPosix(this.rootPath, IFDIR, void 0, this.roots, this.nocase, this.childrenCache(), { fs: fs6 });
6951
5816
  }
6952
5817
  /**
6953
5818
  * Return true if the provided path string is an absolute path
@@ -7247,8 +6112,8 @@ var MatchRecord = class {
7247
6112
  }
7248
6113
  // match, absolute, ifdir
7249
6114
  entries() {
7250
- return [...this.store.entries()].map(([path17, n]) => [
7251
- path17,
6115
+ return [...this.store.entries()].map(([path15, n]) => [
6116
+ path15,
7252
6117
  !!(n & 2),
7253
6118
  !!(n & 1)
7254
6119
  ]);
@@ -7453,9 +6318,9 @@ var GlobUtil = class {
7453
6318
  signal;
7454
6319
  maxDepth;
7455
6320
  includeChildMatches;
7456
- constructor(patterns, path17, opts) {
6321
+ constructor(patterns, path15, opts) {
7457
6322
  this.patterns = patterns;
7458
- this.path = path17;
6323
+ this.path = path15;
7459
6324
  this.opts = opts;
7460
6325
  this.#sep = !opts.posix && opts.platform === "win32" ? "\\" : "/";
7461
6326
  this.includeChildMatches = opts.includeChildMatches !== false;
@@ -7474,11 +6339,11 @@ var GlobUtil = class {
7474
6339
  });
7475
6340
  }
7476
6341
  }
7477
- #ignored(path17) {
7478
- return this.seen.has(path17) || !!this.#ignore?.ignored?.(path17);
6342
+ #ignored(path15) {
6343
+ return this.seen.has(path15) || !!this.#ignore?.ignored?.(path15);
7479
6344
  }
7480
- #childrenIgnored(path17) {
7481
- return !!this.#ignore?.childrenIgnored?.(path17);
6345
+ #childrenIgnored(path15) {
6346
+ return !!this.#ignore?.childrenIgnored?.(path15);
7482
6347
  }
7483
6348
  // backpressure mechanism
7484
6349
  pause() {
@@ -7493,1813 +6358,631 @@ var GlobUtil = class {
7493
6358
  fn();
7494
6359
  }
7495
6360
  }
7496
- onResume(fn) {
7497
- if (this.signal?.aborted)
7498
- return;
7499
- if (!this.paused) {
7500
- fn();
7501
- } else {
7502
- this.#onResume.push(fn);
7503
- }
7504
- }
7505
- // do the requisite realpath/stat checking, and return the path
7506
- // to add or undefined to filter it out.
7507
- async matchCheck(e, ifDir) {
7508
- if (ifDir && this.opts.nodir)
7509
- return void 0;
7510
- let rpc;
7511
- if (this.opts.realpath) {
7512
- rpc = e.realpathCached() || await e.realpath();
7513
- if (!rpc)
7514
- return void 0;
7515
- e = rpc;
7516
- }
7517
- const needStat = e.isUnknown() || this.opts.stat;
7518
- const s = needStat ? await e.lstat() : e;
7519
- if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
7520
- const target = await s.realpath();
7521
- if (target && (target.isUnknown() || this.opts.stat)) {
7522
- await target.lstat();
7523
- }
7524
- }
7525
- return this.matchCheckTest(s, ifDir);
7526
- }
7527
- matchCheckTest(e, ifDir) {
7528
- return e && (this.maxDepth === Infinity || e.depth() <= this.maxDepth) && (!ifDir || e.canReaddir()) && (!this.opts.nodir || !e.isDirectory()) && (!this.opts.nodir || !this.opts.follow || !e.isSymbolicLink() || !e.realpathCached()?.isDirectory()) && !this.#ignored(e) ? e : void 0;
7529
- }
7530
- matchCheckSync(e, ifDir) {
7531
- if (ifDir && this.opts.nodir)
7532
- return void 0;
7533
- let rpc;
7534
- if (this.opts.realpath) {
7535
- rpc = e.realpathCached() || e.realpathSync();
7536
- if (!rpc)
7537
- return void 0;
7538
- e = rpc;
7539
- }
7540
- const needStat = e.isUnknown() || this.opts.stat;
7541
- const s = needStat ? e.lstatSync() : e;
7542
- if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
7543
- const target = s.realpathSync();
7544
- if (target && (target?.isUnknown() || this.opts.stat)) {
7545
- target.lstatSync();
7546
- }
7547
- }
7548
- return this.matchCheckTest(s, ifDir);
7549
- }
7550
- matchFinish(e, absolute) {
7551
- if (this.#ignored(e))
7552
- return;
7553
- if (!this.includeChildMatches && this.#ignore?.add) {
7554
- const ign = `${e.relativePosix()}/**`;
7555
- this.#ignore.add(ign);
7556
- }
7557
- const abs = this.opts.absolute === void 0 ? absolute : this.opts.absolute;
7558
- this.seen.add(e);
7559
- const mark = this.opts.mark && e.isDirectory() ? this.#sep : "";
7560
- if (this.opts.withFileTypes) {
7561
- this.matchEmit(e);
7562
- } else if (abs) {
7563
- const abs2 = this.opts.posix ? e.fullpathPosix() : e.fullpath();
7564
- this.matchEmit(abs2 + mark);
7565
- } else {
7566
- const rel = this.opts.posix ? e.relativePosix() : e.relative();
7567
- const pre = this.opts.dotRelative && !rel.startsWith(".." + this.#sep) ? "." + this.#sep : "";
7568
- this.matchEmit(!rel ? "." + mark : pre + rel + mark);
7569
- }
7570
- }
7571
- async match(e, absolute, ifDir) {
7572
- const p = await this.matchCheck(e, ifDir);
7573
- if (p)
7574
- this.matchFinish(p, absolute);
7575
- }
7576
- matchSync(e, absolute, ifDir) {
7577
- const p = this.matchCheckSync(e, ifDir);
7578
- if (p)
7579
- this.matchFinish(p, absolute);
7580
- }
7581
- walkCB(target, patterns, cb) {
7582
- if (this.signal?.aborted)
7583
- cb();
7584
- this.walkCB2(target, patterns, new Processor(this.opts), cb);
7585
- }
7586
- walkCB2(target, patterns, processor, cb) {
7587
- if (this.#childrenIgnored(target))
7588
- return cb();
7589
- if (this.signal?.aborted)
7590
- cb();
7591
- if (this.paused) {
7592
- this.onResume(() => this.walkCB2(target, patterns, processor, cb));
7593
- return;
7594
- }
7595
- processor.processPatterns(target, patterns);
7596
- let tasks = 1;
7597
- const next = () => {
7598
- if (--tasks === 0)
7599
- cb();
7600
- };
7601
- for (const [m, absolute, ifDir] of processor.matches.entries()) {
7602
- if (this.#ignored(m))
7603
- continue;
7604
- tasks++;
7605
- this.match(m, absolute, ifDir).then(() => next());
7606
- }
7607
- for (const t of processor.subwalkTargets()) {
7608
- if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
7609
- continue;
7610
- }
7611
- tasks++;
7612
- const childrenCached = t.readdirCached();
7613
- if (t.calledReaddir())
7614
- this.walkCB3(t, childrenCached, processor, next);
7615
- else {
7616
- t.readdirCB((_, entries) => this.walkCB3(t, entries, processor, next), true);
7617
- }
7618
- }
7619
- next();
7620
- }
7621
- walkCB3(target, entries, processor, cb) {
7622
- processor = processor.filterEntries(target, entries);
7623
- let tasks = 1;
7624
- const next = () => {
7625
- if (--tasks === 0)
7626
- cb();
7627
- };
7628
- for (const [m, absolute, ifDir] of processor.matches.entries()) {
7629
- if (this.#ignored(m))
7630
- continue;
7631
- tasks++;
7632
- this.match(m, absolute, ifDir).then(() => next());
7633
- }
7634
- for (const [target2, patterns] of processor.subwalks.entries()) {
7635
- tasks++;
7636
- this.walkCB2(target2, patterns, processor.child(), next);
7637
- }
7638
- next();
7639
- }
7640
- walkCBSync(target, patterns, cb) {
7641
- if (this.signal?.aborted)
7642
- cb();
7643
- this.walkCB2Sync(target, patterns, new Processor(this.opts), cb);
7644
- }
7645
- walkCB2Sync(target, patterns, processor, cb) {
7646
- if (this.#childrenIgnored(target))
7647
- return cb();
7648
- if (this.signal?.aborted)
7649
- cb();
7650
- if (this.paused) {
7651
- this.onResume(() => this.walkCB2Sync(target, patterns, processor, cb));
7652
- return;
7653
- }
7654
- processor.processPatterns(target, patterns);
7655
- let tasks = 1;
7656
- const next = () => {
7657
- if (--tasks === 0)
7658
- cb();
7659
- };
7660
- for (const [m, absolute, ifDir] of processor.matches.entries()) {
7661
- if (this.#ignored(m))
7662
- continue;
7663
- this.matchSync(m, absolute, ifDir);
7664
- }
7665
- for (const t of processor.subwalkTargets()) {
7666
- if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
7667
- continue;
7668
- }
7669
- tasks++;
7670
- const children = t.readdirSync();
7671
- this.walkCB3Sync(t, children, processor, next);
7672
- }
7673
- next();
7674
- }
7675
- walkCB3Sync(target, entries, processor, cb) {
7676
- processor = processor.filterEntries(target, entries);
7677
- let tasks = 1;
7678
- const next = () => {
7679
- if (--tasks === 0)
7680
- cb();
7681
- };
7682
- for (const [m, absolute, ifDir] of processor.matches.entries()) {
7683
- if (this.#ignored(m))
7684
- continue;
7685
- this.matchSync(m, absolute, ifDir);
7686
- }
7687
- for (const [target2, patterns] of processor.subwalks.entries()) {
7688
- tasks++;
7689
- this.walkCB2Sync(target2, patterns, processor.child(), next);
7690
- }
7691
- next();
7692
- }
7693
- };
7694
- var GlobWalker = class extends GlobUtil {
7695
- matches = /* @__PURE__ */ new Set();
7696
- constructor(patterns, path17, opts) {
7697
- super(patterns, path17, opts);
7698
- }
7699
- matchEmit(e) {
7700
- this.matches.add(e);
7701
- }
7702
- async walk() {
7703
- if (this.signal?.aborted)
7704
- throw this.signal.reason;
7705
- if (this.path.isUnknown()) {
7706
- await this.path.lstat();
7707
- }
7708
- await new Promise((res, rej) => {
7709
- this.walkCB(this.path, this.patterns, () => {
7710
- if (this.signal?.aborted) {
7711
- rej(this.signal.reason);
7712
- } else {
7713
- res(this.matches);
7714
- }
7715
- });
7716
- });
7717
- return this.matches;
7718
- }
7719
- walkSync() {
7720
- if (this.signal?.aborted)
7721
- throw this.signal.reason;
7722
- if (this.path.isUnknown()) {
7723
- this.path.lstatSync();
7724
- }
7725
- this.walkCBSync(this.path, this.patterns, () => {
7726
- if (this.signal?.aborted)
7727
- throw this.signal.reason;
7728
- });
7729
- return this.matches;
7730
- }
7731
- };
7732
- var GlobStream = class extends GlobUtil {
7733
- results;
7734
- constructor(patterns, path17, opts) {
7735
- super(patterns, path17, opts);
7736
- this.results = new Minipass({
7737
- signal: this.signal,
7738
- objectMode: true
7739
- });
7740
- this.results.on("drain", () => this.resume());
7741
- this.results.on("resume", () => this.resume());
7742
- }
7743
- matchEmit(e) {
7744
- this.results.write(e);
7745
- if (!this.results.flowing)
7746
- this.pause();
7747
- }
7748
- stream() {
7749
- const target = this.path;
7750
- if (target.isUnknown()) {
7751
- target.lstat().then(() => {
7752
- this.walkCB(target, this.patterns, () => this.results.end());
7753
- });
7754
- } else {
7755
- this.walkCB(target, this.patterns, () => this.results.end());
7756
- }
7757
- return this.results;
7758
- }
7759
- streamSync() {
7760
- if (this.path.isUnknown()) {
7761
- this.path.lstatSync();
7762
- }
7763
- this.walkCBSync(this.path, this.patterns, () => this.results.end());
7764
- return this.results;
7765
- }
7766
- };
7767
-
7768
- // ../../node_modules/.bun/glob@11.1.0/node_modules/glob/dist/esm/glob.js
7769
- var defaultPlatform3 = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
7770
- var Glob = class {
7771
- absolute;
7772
- cwd;
7773
- root;
7774
- dot;
7775
- dotRelative;
7776
- follow;
7777
- ignore;
7778
- magicalBraces;
7779
- mark;
7780
- matchBase;
7781
- maxDepth;
7782
- nobrace;
7783
- nocase;
7784
- nodir;
7785
- noext;
7786
- noglobstar;
7787
- pattern;
7788
- platform;
7789
- realpath;
7790
- scurry;
7791
- stat;
7792
- signal;
7793
- windowsPathsNoEscape;
7794
- withFileTypes;
7795
- includeChildMatches;
7796
- /**
7797
- * The options provided to the constructor.
7798
- */
7799
- opts;
7800
- /**
7801
- * An array of parsed immutable {@link Pattern} objects.
7802
- */
7803
- patterns;
7804
- /**
7805
- * All options are stored as properties on the `Glob` object.
7806
- *
7807
- * See {@link GlobOptions} for full options descriptions.
7808
- *
7809
- * Note that a previous `Glob` object can be passed as the
7810
- * `GlobOptions` to another `Glob` instantiation to re-use settings
7811
- * and caches with a new pattern.
7812
- *
7813
- * Traversal functions can be called multiple times to run the walk
7814
- * again.
7815
- */
7816
- constructor(pattern, opts) {
7817
- if (!opts)
7818
- throw new TypeError("glob options required");
7819
- this.withFileTypes = !!opts.withFileTypes;
7820
- this.signal = opts.signal;
7821
- this.follow = !!opts.follow;
7822
- this.dot = !!opts.dot;
7823
- this.dotRelative = !!opts.dotRelative;
7824
- this.nodir = !!opts.nodir;
7825
- this.mark = !!opts.mark;
7826
- if (!opts.cwd) {
7827
- this.cwd = "";
7828
- } else if (opts.cwd instanceof URL || opts.cwd.startsWith("file://")) {
7829
- opts.cwd = url.fileURLToPath(opts.cwd);
7830
- }
7831
- this.cwd = opts.cwd || "";
7832
- this.root = opts.root;
7833
- this.magicalBraces = !!opts.magicalBraces;
7834
- this.nobrace = !!opts.nobrace;
7835
- this.noext = !!opts.noext;
7836
- this.realpath = !!opts.realpath;
7837
- this.absolute = opts.absolute;
7838
- this.includeChildMatches = opts.includeChildMatches !== false;
7839
- this.noglobstar = !!opts.noglobstar;
7840
- this.matchBase = !!opts.matchBase;
7841
- this.maxDepth = typeof opts.maxDepth === "number" ? opts.maxDepth : Infinity;
7842
- this.stat = !!opts.stat;
7843
- this.ignore = opts.ignore;
7844
- if (this.withFileTypes && this.absolute !== void 0) {
7845
- throw new Error("cannot set absolute and withFileTypes:true");
7846
- }
7847
- if (typeof pattern === "string") {
7848
- pattern = [pattern];
7849
- }
7850
- this.windowsPathsNoEscape = !!opts.windowsPathsNoEscape || opts.allowWindowsEscape === false;
7851
- if (this.windowsPathsNoEscape) {
7852
- pattern = pattern.map((p) => p.replace(/\\/g, "/"));
7853
- }
7854
- if (this.matchBase) {
7855
- if (opts.noglobstar) {
7856
- throw new TypeError("base matching requires globstar");
7857
- }
7858
- pattern = pattern.map((p) => p.includes("/") ? p : `./**/${p}`);
7859
- }
7860
- this.pattern = pattern;
7861
- this.platform = opts.platform || defaultPlatform3;
7862
- this.opts = { ...opts, platform: this.platform };
7863
- if (opts.scurry) {
7864
- this.scurry = opts.scurry;
7865
- if (opts.nocase !== void 0 && opts.nocase !== opts.scurry.nocase) {
7866
- throw new Error("nocase option contradicts provided scurry option");
7867
- }
7868
- } else {
7869
- const Scurry = opts.platform === "win32" ? PathScurryWin32 : opts.platform === "darwin" ? PathScurryDarwin : opts.platform ? PathScurryPosix : PathScurry;
7870
- this.scurry = new Scurry(this.cwd, {
7871
- nocase: opts.nocase,
7872
- fs: opts.fs
7873
- });
7874
- }
7875
- this.nocase = this.scurry.nocase;
7876
- const nocaseMagicOnly = this.platform === "darwin" || this.platform === "win32";
7877
- const mmo = {
7878
- // default nocase based on platform
7879
- ...opts,
7880
- dot: this.dot,
7881
- matchBase: this.matchBase,
7882
- nobrace: this.nobrace,
7883
- nocase: this.nocase,
7884
- nocaseMagicOnly,
7885
- nocomment: true,
7886
- noext: this.noext,
7887
- nonegate: true,
7888
- optimizationLevel: 2,
7889
- platform: this.platform,
7890
- windowsPathsNoEscape: this.windowsPathsNoEscape,
7891
- debug: !!this.opts.debug
7892
- };
7893
- const mms = this.pattern.map((p) => new Minimatch(p, mmo));
7894
- const [matchSet, globParts] = mms.reduce((set, m) => {
7895
- set[0].push(...m.set);
7896
- set[1].push(...m.globParts);
7897
- return set;
7898
- }, [[], []]);
7899
- this.patterns = matchSet.map((set, i) => {
7900
- const g = globParts[i];
7901
- if (!g)
7902
- throw new Error("invalid pattern object");
7903
- return new Pattern(set, g, 0, this.platform);
7904
- });
7905
- }
7906
- async walk() {
7907
- return [
7908
- ...await new GlobWalker(this.patterns, this.scurry.cwd, {
7909
- ...this.opts,
7910
- maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
7911
- platform: this.platform,
7912
- nocase: this.nocase,
7913
- includeChildMatches: this.includeChildMatches
7914
- }).walk()
7915
- ];
7916
- }
7917
- walkSync() {
7918
- return [
7919
- ...new GlobWalker(this.patterns, this.scurry.cwd, {
7920
- ...this.opts,
7921
- maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
7922
- platform: this.platform,
7923
- nocase: this.nocase,
7924
- includeChildMatches: this.includeChildMatches
7925
- }).walkSync()
7926
- ];
7927
- }
7928
- stream() {
7929
- return new GlobStream(this.patterns, this.scurry.cwd, {
7930
- ...this.opts,
7931
- maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
7932
- platform: this.platform,
7933
- nocase: this.nocase,
7934
- includeChildMatches: this.includeChildMatches
7935
- }).stream();
7936
- }
7937
- streamSync() {
7938
- return new GlobStream(this.patterns, this.scurry.cwd, {
7939
- ...this.opts,
7940
- maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
7941
- platform: this.platform,
7942
- nocase: this.nocase,
7943
- includeChildMatches: this.includeChildMatches
7944
- }).streamSync();
7945
- }
7946
- /**
7947
- * Default sync iteration function. Returns a Generator that
7948
- * iterates over the results.
7949
- */
7950
- iterateSync() {
7951
- return this.streamSync()[Symbol.iterator]();
7952
- }
7953
- [Symbol.iterator]() {
7954
- return this.iterateSync();
7955
- }
7956
- /**
7957
- * Default async iteration function. Returns an AsyncGenerator that
7958
- * iterates over the results.
7959
- */
7960
- iterate() {
7961
- return this.stream()[Symbol.asyncIterator]();
7962
- }
7963
- [Symbol.asyncIterator]() {
7964
- return this.iterate();
7965
- }
7966
- };
7967
-
7968
- // ../../node_modules/.bun/glob@11.1.0/node_modules/glob/dist/esm/has-magic.js
7969
- var hasMagic = (pattern, options = {}) => {
7970
- if (!Array.isArray(pattern)) {
7971
- pattern = [pattern];
7972
- }
7973
- for (const p of pattern) {
7974
- if (new Minimatch(p, options).hasMagic())
7975
- return true;
7976
- }
7977
- return false;
7978
- };
7979
-
7980
- // ../../node_modules/.bun/glob@11.1.0/node_modules/glob/dist/esm/index.js
7981
- function globStreamSync(pattern, options = {}) {
7982
- return new Glob(pattern, options).streamSync();
7983
- }
7984
- function globStream(pattern, options = {}) {
7985
- return new Glob(pattern, options).stream();
7986
- }
7987
- function globSync(pattern, options = {}) {
7988
- return new Glob(pattern, options).walkSync();
7989
- }
7990
- async function glob_(pattern, options = {}) {
7991
- return new Glob(pattern, options).walk();
7992
- }
7993
- function globIterateSync(pattern, options = {}) {
7994
- return new Glob(pattern, options).iterateSync();
7995
- }
7996
- function globIterate(pattern, options = {}) {
7997
- return new Glob(pattern, options).iterate();
7998
- }
7999
- var streamSync = globStreamSync;
8000
- var stream = Object.assign(globStream, { sync: globStreamSync });
8001
- var iterateSync = globIterateSync;
8002
- var iterate = Object.assign(globIterate, {
8003
- sync: globIterateSync
8004
- });
8005
- var sync = Object.assign(globSync, {
8006
- stream: globStreamSync,
8007
- iterate: globIterateSync
8008
- });
8009
- var glob = Object.assign(glob_, {
8010
- glob: glob_,
8011
- globSync,
8012
- sync,
8013
- globStream,
8014
- stream,
8015
- globStreamSync,
8016
- streamSync,
8017
- globIterate,
8018
- iterate,
8019
- globIterateSync,
8020
- iterateSync,
8021
- Glob,
8022
- hasMagic,
8023
- escape,
8024
- unescape
8025
- });
8026
- glob.glob = glob;
8027
-
8028
- // ../agent/src/tools/glob.ts
8029
- zod.z.object({
8030
- pattern: zod.z.string().describe('Glob pattern to match files (e.g., "**/*.js", "src/**/*.ts", "*.json"). Supports standard glob syntax with *, **, and ? wildcards'),
8031
- path: zod.z.string().optional().describe("Optional directory path to limit the search scope. If not provided, searches from the project root")
8032
- });
8033
- var RESULT_LIMIT = 100;
8034
- var MTIME_BATCH_SIZE = 50;
8035
- async function getMtimesBatched2(files) {
8036
- const results = [];
8037
- for (let i = 0; i < files.length; i += MTIME_BATCH_SIZE) {
8038
- const batch = files.slice(i, i + MTIME_BATCH_SIZE);
8039
- const batchResults = await Promise.all(
8040
- batch.map(async (filePath) => {
8041
- const mtime = await fsp__namespace.default.stat(filePath).then((stats) => stats.mtimeMs).catch(() => 0);
8042
- return { path: filePath, mtime };
8043
- })
8044
- );
8045
- results.push(...batchResults);
8046
- }
8047
- return results;
8048
- }
8049
- var globTool = async function(input, projectCwd) {
8050
- const { pattern, path: inputPath } = input;
8051
- if (!pattern) {
8052
- return {
8053
- success: false,
8054
- message: "Missing required parameter: pattern",
8055
- error: "MISSING_PATTERN"
8056
- };
6361
+ onResume(fn) {
6362
+ if (this.signal?.aborted)
6363
+ return;
6364
+ if (!this.paused) {
6365
+ fn();
6366
+ } else {
6367
+ this.#onResume.push(fn);
6368
+ }
8057
6369
  }
8058
- try {
8059
- const basePath = projectCwd || process.cwd();
8060
- const searchPath = inputPath ? resolveProjectPath(inputPath, basePath) : basePath;
8061
- if (!fs4__namespace.default.existsSync(searchPath)) {
8062
- return {
8063
- success: false,
8064
- message: `Directory not found: ${searchPath}`,
8065
- error: "DIR_NOT_FOUND"
8066
- };
6370
+ // do the requisite realpath/stat checking, and return the path
6371
+ // to add or undefined to filter it out.
6372
+ async matchCheck(e, ifDir) {
6373
+ if (ifDir && this.opts.nodir)
6374
+ return void 0;
6375
+ let rpc;
6376
+ if (this.opts.realpath) {
6377
+ rpc = e.realpathCached() || await e.realpath();
6378
+ if (!rpc)
6379
+ return void 0;
6380
+ e = rpc;
8067
6381
  }
8068
- if (projectCwd && inputPath) {
8069
- const validation = validatePath(inputPath, projectCwd);
8070
- if (!validation.valid) {
8071
- return {
8072
- success: false,
8073
- message: validation.error || "Path validation failed",
8074
- error: "ACCESS_DENIED"
8075
- };
6382
+ const needStat = e.isUnknown() || this.opts.stat;
6383
+ const s = needStat ? await e.lstat() : e;
6384
+ if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
6385
+ const target = await s.realpath();
6386
+ if (target && (target.isUnknown() || this.opts.stat)) {
6387
+ await target.lstat();
8076
6388
  }
8077
6389
  }
8078
- const matches = await glob(pattern, {
8079
- cwd: searchPath,
8080
- absolute: true,
8081
- nodir: true,
8082
- follow: false,
8083
- ignore: ["**/node_modules/**", "**/.git/**"]
8084
- });
8085
- const truncated = matches.length > RESULT_LIMIT;
8086
- const files = truncated ? matches.slice(0, RESULT_LIMIT) : matches;
8087
- let sortedFiles;
8088
- if (files.length > 0) {
8089
- const filesWithMtime = await getMtimesBatched2(files);
8090
- filesWithMtime.sort((a3, b) => b.mtime - a3.mtime);
8091
- sortedFiles = filesWithMtime.map((f) => f.path);
8092
- } else {
8093
- sortedFiles = files;
6390
+ return this.matchCheckTest(s, ifDir);
6391
+ }
6392
+ matchCheckTest(e, ifDir) {
6393
+ return e && (this.maxDepth === Infinity || e.depth() <= this.maxDepth) && (!ifDir || e.canReaddir()) && (!this.opts.nodir || !e.isDirectory()) && (!this.opts.nodir || !this.opts.follow || !e.isSymbolicLink() || !e.realpathCached()?.isDirectory()) && !this.#ignored(e) ? e : void 0;
6394
+ }
6395
+ matchCheckSync(e, ifDir) {
6396
+ if (ifDir && this.opts.nodir)
6397
+ return void 0;
6398
+ let rpc;
6399
+ if (this.opts.realpath) {
6400
+ rpc = e.realpathCached() || e.realpathSync();
6401
+ if (!rpc)
6402
+ return void 0;
6403
+ e = rpc;
8094
6404
  }
8095
- const output = [];
8096
- if (sortedFiles.length === 0) {
8097
- output.push("No files found");
8098
- } else {
8099
- output.push(...sortedFiles);
8100
- if (truncated) {
8101
- output.push("");
8102
- output.push("(Results are truncated. Consider using a more specific path or pattern.)");
6405
+ const needStat = e.isUnknown() || this.opts.stat;
6406
+ const s = needStat ? e.lstatSync() : e;
6407
+ if (this.opts.follow && this.opts.nodir && s?.isSymbolicLink()) {
6408
+ const target = s.realpathSync();
6409
+ if (target && (target?.isUnknown() || this.opts.stat)) {
6410
+ target.lstatSync();
8103
6411
  }
8104
6412
  }
8105
- const searchLocation = inputPath ? ` in "${inputPath}"` : " in current directory";
8106
- const message = `Found ${sortedFiles.length} matches for pattern "${pattern}"${searchLocation}`;
8107
- return {
8108
- success: true,
8109
- message,
8110
- metadata: {
8111
- count: sortedFiles.length,
8112
- truncated
8113
- },
8114
- content: output.join("\n")
8115
- };
8116
- } catch (error) {
8117
- console.error("[glob] error:", error);
8118
- return {
8119
- success: false,
8120
- message: `Failed to find files matching pattern: ${pattern}`,
8121
- error: "GLOB_ERROR"
8122
- };
8123
- }
8124
- };
8125
- var DEFAULT_IGNORE_PATTERNS = [
8126
- "node_modules",
8127
- "__pycache__",
8128
- ".git",
8129
- "dist",
8130
- "build",
8131
- "target",
8132
- "vendor",
8133
- "bin",
8134
- "obj",
8135
- ".idea",
8136
- ".vscode",
8137
- ".zig-cache",
8138
- "zig-out",
8139
- ".coverage",
8140
- "coverage",
8141
- "tmp",
8142
- "temp",
8143
- ".cache",
8144
- "cache",
8145
- "logs",
8146
- ".venv",
8147
- "venv",
8148
- "env",
8149
- ".next",
8150
- ".turbo",
8151
- ".vercel",
8152
- ".output"
8153
- ];
8154
- var RESULT_LIMIT2 = 500;
8155
- var MTIME_BATCH_SIZE2 = 50;
8156
- zod.z.object({
8157
- path: zod.z.string().optional().describe("Path to the directory to list"),
8158
- recursive: zod.z.boolean().optional().describe("Whether to list files recursively (default: true)"),
8159
- maxDepth: zod.z.number().optional().describe("Maximum recursion depth (default: 3)"),
8160
- pattern: zod.z.string().optional().describe("File extension (e.g., '.ts') or glob-like pattern"),
8161
- showHidden: zod.z.boolean().optional().describe("Whether to show hidden files (default: false)"),
8162
- includeMetadata: zod.z.boolean().optional().describe("Whether to fetch file metadata like mtime (default: false -- faster without I/O)"),
8163
- ignore: zod.z.array(zod.z.string()).optional().describe("Additional glob patterns to ignore (added to default ignore list)")
8164
- });
8165
- function shouldIgnore(name, showHidden, ignoreSet) {
8166
- if (!showHidden && name.startsWith(".") && name !== ".") {
8167
- return true;
6413
+ return this.matchCheckTest(s, ifDir);
8168
6414
  }
8169
- return ignoreSet.has(name);
8170
- }
8171
- function matchPattern(name, pattern) {
8172
- if (!pattern) return true;
8173
- if (pattern.startsWith(".") && !pattern.includes("*")) {
8174
- return name.endsWith(pattern);
8175
- }
8176
- const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
8177
- const regex = new RegExp(`^${escaped}$`, "i");
8178
- return regex.test(name);
8179
- }
8180
- async function getMtimesBatched3(entries) {
8181
- for (let i = 0; i < entries.length; i += MTIME_BATCH_SIZE2) {
8182
- const batch = entries.slice(i, i + MTIME_BATCH_SIZE2);
8183
- await Promise.all(
8184
- batch.map(async (entry) => {
8185
- entry.mtime = await fsp__namespace.default.stat(entry.absolutePath).then((stats) => stats.mtimeMs).catch(() => 0);
8186
- })
8187
- );
6415
+ matchFinish(e, absolute) {
6416
+ if (this.#ignored(e))
6417
+ return;
6418
+ if (!this.includeChildMatches && this.#ignore?.add) {
6419
+ const ign = `${e.relativePosix()}/**`;
6420
+ this.#ignore.add(ign);
6421
+ }
6422
+ const abs = this.opts.absolute === void 0 ? absolute : this.opts.absolute;
6423
+ this.seen.add(e);
6424
+ const mark = this.opts.mark && e.isDirectory() ? this.#sep : "";
6425
+ if (this.opts.withFileTypes) {
6426
+ this.matchEmit(e);
6427
+ } else if (abs) {
6428
+ const abs2 = this.opts.posix ? e.fullpathPosix() : e.fullpath();
6429
+ this.matchEmit(abs2 + mark);
6430
+ } else {
6431
+ const rel = this.opts.posix ? e.relativePosix() : e.relative();
6432
+ const pre = this.opts.dotRelative && !rel.startsWith(".." + this.#sep) ? "." + this.#sep : "";
6433
+ this.matchEmit(!rel ? "." + mark : pre + rel + mark);
6434
+ }
8188
6435
  }
8189
- }
8190
- function buildTreeOutput(entries, basePath) {
8191
- const tree = /* @__PURE__ */ new Map();
8192
- for (const entry of entries) {
8193
- const dir = path6__default.default.dirname(entry.relativePath);
8194
- const dirKey = dir === "." ? "" : dir;
8195
- if (!tree.has(dirKey)) {
8196
- tree.set(dirKey, []);
8197
- }
8198
- tree.get(dirKey).push(entry);
8199
- }
8200
- for (const [, items] of tree) {
8201
- items.sort((a3, b) => {
8202
- if (a3.type !== b.type) {
8203
- return a3.type === "directory" ? -1 : 1;
8204
- }
8205
- return a3.name.localeCompare(b.name);
8206
- });
6436
+ async match(e, absolute, ifDir) {
6437
+ const p = await this.matchCheck(e, ifDir);
6438
+ if (p)
6439
+ this.matchFinish(p, absolute);
8207
6440
  }
8208
- const lines = [`${basePath}/`];
8209
- function renderLevel(dirPath, indent) {
8210
- const items = tree.get(dirPath) || [];
8211
- for (let i = 0; i < items.length; i++) {
8212
- const item = items[i];
8213
- const isLast = i === items.length - 1;
8214
- const prefix = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
8215
- const childIndent = indent + (isLast ? " " : "\u2502 ");
8216
- if (item.type === "directory") {
8217
- lines.push(`${indent}${prefix}${item.name}/`);
8218
- const childPath = dirPath ? `${dirPath}/${item.name}` : item.name;
8219
- renderLevel(childPath, childIndent);
8220
- } else {
8221
- lines.push(`${indent}${prefix}${item.name}`);
8222
- }
8223
- }
6441
+ matchSync(e, absolute, ifDir) {
6442
+ const p = this.matchCheckSync(e, ifDir);
6443
+ if (p)
6444
+ this.matchFinish(p, absolute);
8224
6445
  }
8225
- renderLevel("", "");
8226
- return lines.join("\n");
8227
- }
8228
- var list = async function(input, projectCwd) {
8229
- const {
8230
- path: relativePath,
8231
- recursive = true,
8232
- maxDepth = 3,
8233
- pattern,
8234
- showHidden = false,
8235
- includeMetadata = false,
8236
- ignore: extraIgnore
8237
- } = input;
8238
- if (maxDepth !== void 0 && (!Number.isInteger(maxDepth) || maxDepth < 0)) {
8239
- return {
8240
- success: false,
8241
- message: "maxDepth must be a non-negative integer",
8242
- error: "INVALID_MAX_DEPTH"
8243
- };
6446
+ walkCB(target, patterns, cb) {
6447
+ if (this.signal?.aborted)
6448
+ cb();
6449
+ this.walkCB2(target, patterns, new Processor(this.opts), cb);
8244
6450
  }
8245
- try {
8246
- const basePath = projectCwd || process.cwd();
8247
- const absolutePath = relativePath ? resolveProjectPath(relativePath, basePath) : basePath;
8248
- if (projectCwd && relativePath) {
8249
- const validation = validatePath(relativePath, projectCwd);
8250
- if (!validation.valid) {
8251
- return {
8252
- success: false,
8253
- message: validation.error || "Path validation failed",
8254
- error: "ACCESS_DENIED"
8255
- };
8256
- }
8257
- }
8258
- if (!fs4__namespace.default.existsSync(absolutePath)) {
8259
- return {
8260
- success: false,
8261
- message: `Directory not found: ${absolutePath}`,
8262
- error: "DIR_NOT_FOUND"
8263
- };
8264
- }
8265
- const stats = fs4__namespace.default.statSync(absolutePath);
8266
- if (!stats.isDirectory()) {
8267
- return {
8268
- success: false,
8269
- message: `Path is not a directory: ${absolutePath}`,
8270
- error: "NOT_A_DIRECTORY"
8271
- };
6451
+ walkCB2(target, patterns, processor, cb) {
6452
+ if (this.#childrenIgnored(target))
6453
+ return cb();
6454
+ if (this.signal?.aborted)
6455
+ cb();
6456
+ if (this.paused) {
6457
+ this.onResume(() => this.walkCB2(target, patterns, processor, cb));
6458
+ return;
8272
6459
  }
8273
- const ignoreSet = new Set(DEFAULT_IGNORE_PATTERNS);
8274
- if (extraIgnore && extraIgnore.length > 0) {
8275
- for (const pat of extraIgnore) {
8276
- ignoreSet.add(pat);
8277
- }
6460
+ processor.processPatterns(target, patterns);
6461
+ let tasks = 1;
6462
+ const next = () => {
6463
+ if (--tasks === 0)
6464
+ cb();
6465
+ };
6466
+ for (const [m, absolute, ifDir] of processor.matches.entries()) {
6467
+ if (this.#ignored(m))
6468
+ continue;
6469
+ tasks++;
6470
+ this.match(m, absolute, ifDir).then(() => next());
8278
6471
  }
8279
- const collected = [];
8280
- let truncated = false;
8281
- const walk = async (currentDir, depth) => {
8282
- if (collected.length >= RESULT_LIMIT2) {
8283
- truncated = true;
8284
- return;
8285
- }
8286
- let entries;
8287
- try {
8288
- entries = fs4__namespace.default.readdirSync(currentDir, { withFileTypes: true });
8289
- } catch {
8290
- return;
6472
+ for (const t of processor.subwalkTargets()) {
6473
+ if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
6474
+ continue;
8291
6475
  }
8292
- entries.sort((a3, b) => {
8293
- if (a3.isDirectory() !== b.isDirectory()) {
8294
- return a3.isDirectory() ? -1 : 1;
8295
- }
8296
- return a3.name.localeCompare(b.name);
8297
- });
8298
- for (const entry of entries) {
8299
- if (collected.length >= RESULT_LIMIT2) {
8300
- truncated = true;
8301
- break;
8302
- }
8303
- if (shouldIgnore(entry.name, showHidden, ignoreSet)) {
8304
- continue;
8305
- }
8306
- const entryAbsolutePath = path6__default.default.join(currentDir, entry.name);
8307
- const entryRelativePath = path6__default.default.relative(absolutePath, entryAbsolutePath);
8308
- if (entry.isDirectory()) {
8309
- collected.push({
8310
- name: entry.name,
8311
- absolutePath: entryAbsolutePath,
8312
- relativePath: entryRelativePath,
8313
- type: "directory",
8314
- mtime: 0,
8315
- depth
8316
- });
8317
- if (recursive && depth < maxDepth) {
8318
- await walk(entryAbsolutePath, depth + 1);
8319
- }
8320
- } else if (entry.isFile()) {
8321
- if (matchPattern(entry.name, pattern)) {
8322
- collected.push({
8323
- name: entry.name,
8324
- absolutePath: entryAbsolutePath,
8325
- relativePath: entryRelativePath,
8326
- type: "file",
8327
- mtime: 0,
8328
- depth
8329
- });
8330
- }
8331
- }
6476
+ tasks++;
6477
+ const childrenCached = t.readdirCached();
6478
+ if (t.calledReaddir())
6479
+ this.walkCB3(t, childrenCached, processor, next);
6480
+ else {
6481
+ t.readdirCB((_, entries) => this.walkCB3(t, entries, processor, next), true);
8332
6482
  }
8333
- };
8334
- await walk(absolutePath, 0);
8335
- if (includeMetadata) {
8336
- await getMtimesBatched3(collected);
8337
- }
8338
- const totalFiles = collected.filter((item) => item.type === "file").length;
8339
- const totalDirectories = collected.filter((item) => item.type === "directory").length;
8340
- const treeOutput = buildTreeOutput(collected, relativePath || path6__default.default.basename(absolutePath));
8341
- let message = `Listed ${collected.length} items`;
8342
- if (relativePath) {
8343
- message += ` in "${relativePath}"`;
8344
- }
8345
- message += ` (${totalFiles} files, ${totalDirectories} directories)`;
8346
- if (recursive) {
8347
- message += ` [depth: ${maxDepth}]`;
8348
- }
8349
- if (pattern) {
8350
- message += ` [filter: ${pattern}]`;
8351
- }
8352
- if (truncated) {
8353
- message += ` [TRUNCATED at ${RESULT_LIMIT2} items]`;
8354
- }
8355
- const files = collected.map((item) => ({
8356
- name: item.name,
8357
- path: item.relativePath,
8358
- type: item.type
8359
- }));
8360
- return {
8361
- success: true,
8362
- message,
8363
- metadata: {
8364
- totalFiles,
8365
- totalDirectories,
8366
- totalItems: collected.length,
8367
- truncated,
8368
- maxDepth,
8369
- recursive
8370
- },
8371
- files,
8372
- content: treeOutput
8373
- };
8374
- } catch (error) {
8375
- console.error("[list] error:", error);
8376
- return {
8377
- success: false,
8378
- message: `Failed to list directory: ${error}`,
8379
- error: "LIST_ERROR"
8380
- };
6483
+ }
6484
+ next();
8381
6485
  }
8382
- };
8383
-
8384
- // ../../node_modules/.bun/diff@8.0.3/node_modules/diff/libesm/diff/base.js
8385
- var Diff = class {
8386
- diff(oldStr, newStr, options = {}) {
8387
- let callback;
8388
- if (typeof options === "function") {
8389
- callback = options;
8390
- options = {};
8391
- } else if ("callback" in options) {
8392
- callback = options.callback;
8393
- }
8394
- const oldString = this.castInput(oldStr, options);
8395
- const newString = this.castInput(newStr, options);
8396
- const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
8397
- const newTokens = this.removeEmpty(this.tokenize(newString, options));
8398
- return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
8399
- }
8400
- diffWithOptionsObj(oldTokens, newTokens, options, callback) {
8401
- var _a;
8402
- const done = (value) => {
8403
- value = this.postProcess(value, options);
8404
- if (callback) {
8405
- setTimeout(function() {
8406
- callback(value);
8407
- }, 0);
8408
- return void 0;
8409
- } else {
8410
- return value;
8411
- }
8412
- };
8413
- const newLen = newTokens.length, oldLen = oldTokens.length;
8414
- let editLength = 1;
8415
- let maxEditLength = newLen + oldLen;
8416
- if (options.maxEditLength != null) {
8417
- maxEditLength = Math.min(maxEditLength, options.maxEditLength);
8418
- }
8419
- const maxExecutionTime = (_a = options.timeout) !== null && _a !== void 0 ? _a : Infinity;
8420
- const abortAfterTimestamp = Date.now() + maxExecutionTime;
8421
- const bestPath = [{ oldPos: -1, lastComponent: void 0 }];
8422
- let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
8423
- if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
8424
- return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
8425
- }
8426
- let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
8427
- const execEditLength = () => {
8428
- for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
8429
- let basePath;
8430
- const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
8431
- if (removePath) {
8432
- bestPath[diagonalPath - 1] = void 0;
8433
- }
8434
- let canAdd = false;
8435
- if (addPath) {
8436
- const addPathNewPos = addPath.oldPos - diagonalPath;
8437
- canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
8438
- }
8439
- const canRemove = removePath && removePath.oldPos + 1 < oldLen;
8440
- if (!canAdd && !canRemove) {
8441
- bestPath[diagonalPath] = void 0;
8442
- continue;
8443
- }
8444
- if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
8445
- basePath = this.addToPath(addPath, true, false, 0, options);
8446
- } else {
8447
- basePath = this.addToPath(removePath, false, true, 1, options);
8448
- }
8449
- newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
8450
- if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
8451
- return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
8452
- } else {
8453
- bestPath[diagonalPath] = basePath;
8454
- if (basePath.oldPos + 1 >= oldLen) {
8455
- maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
8456
- }
8457
- if (newPos + 1 >= newLen) {
8458
- minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
8459
- }
8460
- }
8461
- }
8462
- editLength++;
6486
+ walkCB3(target, entries, processor, cb) {
6487
+ processor = processor.filterEntries(target, entries);
6488
+ let tasks = 1;
6489
+ const next = () => {
6490
+ if (--tasks === 0)
6491
+ cb();
8463
6492
  };
8464
- if (callback) {
8465
- (function exec2() {
8466
- setTimeout(function() {
8467
- if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
8468
- return callback(void 0);
8469
- }
8470
- if (!execEditLength()) {
8471
- exec2();
8472
- }
8473
- }, 0);
8474
- })();
8475
- } else {
8476
- while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
8477
- const ret = execEditLength();
8478
- if (ret) {
8479
- return ret;
8480
- }
8481
- }
6493
+ for (const [m, absolute, ifDir] of processor.matches.entries()) {
6494
+ if (this.#ignored(m))
6495
+ continue;
6496
+ tasks++;
6497
+ this.match(m, absolute, ifDir).then(() => next());
8482
6498
  }
8483
- }
8484
- addToPath(path17, added, removed, oldPosInc, options) {
8485
- const last = path17.lastComponent;
8486
- if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
8487
- return {
8488
- oldPos: path17.oldPos + oldPosInc,
8489
- lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
8490
- };
8491
- } else {
8492
- return {
8493
- oldPos: path17.oldPos + oldPosInc,
8494
- lastComponent: { count: 1, added, removed, previousComponent: last }
8495
- };
6499
+ for (const [target2, patterns] of processor.subwalks.entries()) {
6500
+ tasks++;
6501
+ this.walkCB2(target2, patterns, processor.child(), next);
8496
6502
  }
6503
+ next();
8497
6504
  }
8498
- extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
8499
- const newLen = newTokens.length, oldLen = oldTokens.length;
8500
- let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
8501
- while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
8502
- newPos++;
8503
- oldPos++;
8504
- commonCount++;
8505
- if (options.oneChangePerToken) {
8506
- basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
8507
- }
6505
+ walkCBSync(target, patterns, cb) {
6506
+ if (this.signal?.aborted)
6507
+ cb();
6508
+ this.walkCB2Sync(target, patterns, new Processor(this.opts), cb);
6509
+ }
6510
+ walkCB2Sync(target, patterns, processor, cb) {
6511
+ if (this.#childrenIgnored(target))
6512
+ return cb();
6513
+ if (this.signal?.aborted)
6514
+ cb();
6515
+ if (this.paused) {
6516
+ this.onResume(() => this.walkCB2Sync(target, patterns, processor, cb));
6517
+ return;
6518
+ }
6519
+ processor.processPatterns(target, patterns);
6520
+ let tasks = 1;
6521
+ const next = () => {
6522
+ if (--tasks === 0)
6523
+ cb();
6524
+ };
6525
+ for (const [m, absolute, ifDir] of processor.matches.entries()) {
6526
+ if (this.#ignored(m))
6527
+ continue;
6528
+ this.matchSync(m, absolute, ifDir);
8508
6529
  }
8509
- if (commonCount && !options.oneChangePerToken) {
8510
- basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
6530
+ for (const t of processor.subwalkTargets()) {
6531
+ if (this.maxDepth !== Infinity && t.depth() >= this.maxDepth) {
6532
+ continue;
6533
+ }
6534
+ tasks++;
6535
+ const children = t.readdirSync();
6536
+ this.walkCB3Sync(t, children, processor, next);
8511
6537
  }
8512
- basePath.oldPos = oldPos;
8513
- return newPos;
6538
+ next();
8514
6539
  }
8515
- equals(left, right, options) {
8516
- if (options.comparator) {
8517
- return options.comparator(left, right);
8518
- } else {
8519
- return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
6540
+ walkCB3Sync(target, entries, processor, cb) {
6541
+ processor = processor.filterEntries(target, entries);
6542
+ let tasks = 1;
6543
+ const next = () => {
6544
+ if (--tasks === 0)
6545
+ cb();
6546
+ };
6547
+ for (const [m, absolute, ifDir] of processor.matches.entries()) {
6548
+ if (this.#ignored(m))
6549
+ continue;
6550
+ this.matchSync(m, absolute, ifDir);
8520
6551
  }
8521
- }
8522
- removeEmpty(array) {
8523
- const ret = [];
8524
- for (let i = 0; i < array.length; i++) {
8525
- if (array[i]) {
8526
- ret.push(array[i]);
8527
- }
6552
+ for (const [target2, patterns] of processor.subwalks.entries()) {
6553
+ tasks++;
6554
+ this.walkCB2Sync(target2, patterns, processor.child(), next);
8528
6555
  }
8529
- return ret;
8530
- }
8531
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
8532
- castInput(value, options) {
8533
- return value;
8534
- }
8535
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
8536
- tokenize(value, options) {
8537
- return Array.from(value);
8538
- }
8539
- join(chars) {
8540
- return chars.join("");
6556
+ next();
8541
6557
  }
8542
- postProcess(changeObjects, options) {
8543
- return changeObjects;
6558
+ };
6559
+ var GlobWalker = class extends GlobUtil {
6560
+ matches = /* @__PURE__ */ new Set();
6561
+ constructor(patterns, path15, opts) {
6562
+ super(patterns, path15, opts);
8544
6563
  }
8545
- get useLongestToken() {
8546
- return false;
6564
+ matchEmit(e) {
6565
+ this.matches.add(e);
8547
6566
  }
8548
- buildValues(lastComponent, newTokens, oldTokens) {
8549
- const components = [];
8550
- let nextComponent;
8551
- while (lastComponent) {
8552
- components.push(lastComponent);
8553
- nextComponent = lastComponent.previousComponent;
8554
- delete lastComponent.previousComponent;
8555
- lastComponent = nextComponent;
8556
- }
8557
- components.reverse();
8558
- const componentLen = components.length;
8559
- let componentPos = 0, newPos = 0, oldPos = 0;
8560
- for (; componentPos < componentLen; componentPos++) {
8561
- const component = components[componentPos];
8562
- if (!component.removed) {
8563
- if (!component.added && this.useLongestToken) {
8564
- let value = newTokens.slice(newPos, newPos + component.count);
8565
- value = value.map(function(value2, i) {
8566
- const oldValue = oldTokens[oldPos + i];
8567
- return oldValue.length > value2.length ? oldValue : value2;
8568
- });
8569
- component.value = this.join(value);
6567
+ async walk() {
6568
+ if (this.signal?.aborted)
6569
+ throw this.signal.reason;
6570
+ if (this.path.isUnknown()) {
6571
+ await this.path.lstat();
6572
+ }
6573
+ await new Promise((res, rej) => {
6574
+ this.walkCB(this.path, this.patterns, () => {
6575
+ if (this.signal?.aborted) {
6576
+ rej(this.signal.reason);
8570
6577
  } else {
8571
- component.value = this.join(newTokens.slice(newPos, newPos + component.count));
8572
- }
8573
- newPos += component.count;
8574
- if (!component.added) {
8575
- oldPos += component.count;
6578
+ res(this.matches);
8576
6579
  }
8577
- } else {
8578
- component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
8579
- oldPos += component.count;
8580
- }
6580
+ });
6581
+ });
6582
+ return this.matches;
6583
+ }
6584
+ walkSync() {
6585
+ if (this.signal?.aborted)
6586
+ throw this.signal.reason;
6587
+ if (this.path.isUnknown()) {
6588
+ this.path.lstatSync();
8581
6589
  }
8582
- return components;
6590
+ this.walkCBSync(this.path, this.patterns, () => {
6591
+ if (this.signal?.aborted)
6592
+ throw this.signal.reason;
6593
+ });
6594
+ return this.matches;
8583
6595
  }
8584
6596
  };
8585
-
8586
- // ../../node_modules/.bun/diff@8.0.3/node_modules/diff/libesm/diff/line.js
8587
- var LineDiff = class extends Diff {
8588
- constructor() {
8589
- super(...arguments);
8590
- this.tokenize = tokenize;
6597
+ var GlobStream = class extends GlobUtil {
6598
+ results;
6599
+ constructor(patterns, path15, opts) {
6600
+ super(patterns, path15, opts);
6601
+ this.results = new Minipass({
6602
+ signal: this.signal,
6603
+ objectMode: true
6604
+ });
6605
+ this.results.on("drain", () => this.resume());
6606
+ this.results.on("resume", () => this.resume());
8591
6607
  }
8592
- equals(left, right, options) {
8593
- if (options.ignoreWhitespace) {
8594
- if (!options.newlineIsToken || !left.includes("\n")) {
8595
- left = left.trim();
8596
- }
8597
- if (!options.newlineIsToken || !right.includes("\n")) {
8598
- right = right.trim();
8599
- }
8600
- } else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
8601
- if (left.endsWith("\n")) {
8602
- left = left.slice(0, -1);
8603
- }
8604
- if (right.endsWith("\n")) {
8605
- right = right.slice(0, -1);
8606
- }
8607
- }
8608
- return super.equals(left, right, options);
6608
+ matchEmit(e) {
6609
+ this.results.write(e);
6610
+ if (!this.results.flowing)
6611
+ this.pause();
8609
6612
  }
8610
- };
8611
- var lineDiff = new LineDiff();
8612
- function diffLines(oldStr, newStr, options) {
8613
- return lineDiff.diff(oldStr, newStr, options);
8614
- }
8615
- function tokenize(value, options) {
8616
- if (options.stripTrailingCr) {
8617
- value = value.replace(/\r\n/g, "\n");
8618
- }
8619
- const retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
8620
- if (!linesAndNewlines[linesAndNewlines.length - 1]) {
8621
- linesAndNewlines.pop();
8622
- }
8623
- for (let i = 0; i < linesAndNewlines.length; i++) {
8624
- const line = linesAndNewlines[i];
8625
- if (i % 2 && !options.newlineIsToken) {
8626
- retLines[retLines.length - 1] += line;
6613
+ stream() {
6614
+ const target = this.path;
6615
+ if (target.isUnknown()) {
6616
+ target.lstat().then(() => {
6617
+ this.walkCB(target, this.patterns, () => this.results.end());
6618
+ });
8627
6619
  } else {
8628
- retLines.push(line);
6620
+ this.walkCB(target, this.patterns, () => this.results.end());
8629
6621
  }
6622
+ return this.results;
8630
6623
  }
8631
- return retLines;
8632
- }
8633
-
8634
- // ../agent/src/lib/diff.ts
8635
- function calculateDiffStats(oldContent, newContent) {
8636
- const changes = diffLines(oldContent, newContent);
8637
- let linesAdded = 0;
8638
- let linesRemoved = 0;
8639
- for (const change of changes) {
8640
- if (change.added) {
8641
- linesAdded += change.count || 0;
8642
- } else if (change.removed) {
8643
- linesRemoved += change.count || 0;
8644
- }
8645
- }
8646
- return { linesAdded, linesRemoved };
8647
- }
8648
-
8649
- // ../agent/src/tools/stringReplace.ts
8650
- zod.z.object({
8651
- 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"),
8652
- new_string: zod.z.string().describe("The edited text to replace the old_string (must be different from the old_string)"),
8653
- 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)"),
8654
- replaceAll: zod.z.boolean().optional().describe("Replace all occurrences of old_string (default false)")
8655
- });
8656
- function levenshtein(a3, b) {
8657
- if (a3 === "" || b === "") return Math.max(a3.length, b.length);
8658
- const matrix = Array.from(
8659
- { length: a3.length + 1 },
8660
- (_, i) => Array.from({ length: b.length + 1 }, (_2, j) => i === 0 ? j : j === 0 ? i : 0)
8661
- );
8662
- for (let i = 1; i <= a3.length; i++) {
8663
- for (let j = 1; j <= b.length; j++) {
8664
- const cost = a3[i - 1] === b[j - 1] ? 0 : 1;
8665
- matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
6624
+ streamSync() {
6625
+ if (this.path.isUnknown()) {
6626
+ this.path.lstatSync();
8666
6627
  }
6628
+ this.walkCBSync(this.path, this.patterns, () => this.results.end());
6629
+ return this.results;
8667
6630
  }
8668
- return matrix[a3.length][b.length];
8669
- }
8670
- var SINGLE_CANDIDATE_SIMILARITY_THRESHOLD = 0;
8671
- var MULTIPLE_CANDIDATES_SIMILARITY_THRESHOLD = 0.3;
8672
- var SimpleReplacer = function* (_content, find) {
8673
- yield find;
8674
6631
  };
8675
- var LineTrimmedReplacer = function* (content, find) {
8676
- const originalLines = content.split("\n");
8677
- const searchLines = find.split("\n");
8678
- if (searchLines[searchLines.length - 1] === "") searchLines.pop();
8679
- for (let i = 0; i <= originalLines.length - searchLines.length; i++) {
8680
- let matches = true;
8681
- for (let j = 0; j < searchLines.length; j++) {
8682
- if (originalLines[i + j].trim() !== searchLines[j].trim()) {
8683
- matches = false;
8684
- break;
8685
- }
6632
+
6633
+ // ../../node_modules/.bun/glob@11.1.0/node_modules/glob/dist/esm/glob.js
6634
+ var defaultPlatform3 = typeof process === "object" && process && typeof process.platform === "string" ? process.platform : "linux";
6635
+ var Glob = class {
6636
+ absolute;
6637
+ cwd;
6638
+ root;
6639
+ dot;
6640
+ dotRelative;
6641
+ follow;
6642
+ ignore;
6643
+ magicalBraces;
6644
+ mark;
6645
+ matchBase;
6646
+ maxDepth;
6647
+ nobrace;
6648
+ nocase;
6649
+ nodir;
6650
+ noext;
6651
+ noglobstar;
6652
+ pattern;
6653
+ platform;
6654
+ realpath;
6655
+ scurry;
6656
+ stat;
6657
+ signal;
6658
+ windowsPathsNoEscape;
6659
+ withFileTypes;
6660
+ includeChildMatches;
6661
+ /**
6662
+ * The options provided to the constructor.
6663
+ */
6664
+ opts;
6665
+ /**
6666
+ * An array of parsed immutable {@link Pattern} objects.
6667
+ */
6668
+ patterns;
6669
+ /**
6670
+ * All options are stored as properties on the `Glob` object.
6671
+ *
6672
+ * See {@link GlobOptions} for full options descriptions.
6673
+ *
6674
+ * Note that a previous `Glob` object can be passed as the
6675
+ * `GlobOptions` to another `Glob` instantiation to re-use settings
6676
+ * and caches with a new pattern.
6677
+ *
6678
+ * Traversal functions can be called multiple times to run the walk
6679
+ * again.
6680
+ */
6681
+ constructor(pattern, opts) {
6682
+ if (!opts)
6683
+ throw new TypeError("glob options required");
6684
+ this.withFileTypes = !!opts.withFileTypes;
6685
+ this.signal = opts.signal;
6686
+ this.follow = !!opts.follow;
6687
+ this.dot = !!opts.dot;
6688
+ this.dotRelative = !!opts.dotRelative;
6689
+ this.nodir = !!opts.nodir;
6690
+ this.mark = !!opts.mark;
6691
+ if (!opts.cwd) {
6692
+ this.cwd = "";
6693
+ } else if (opts.cwd instanceof URL || opts.cwd.startsWith("file://")) {
6694
+ opts.cwd = url.fileURLToPath(opts.cwd);
8686
6695
  }
8687
- if (matches) {
8688
- let matchStartIndex = 0;
8689
- for (let k = 0; k < i; k++) matchStartIndex += originalLines[k].length + 1;
8690
- let matchEndIndex = matchStartIndex;
8691
- for (let k = 0; k < searchLines.length; k++) {
8692
- matchEndIndex += originalLines[i + k].length;
8693
- if (k < searchLines.length - 1) matchEndIndex += 1;
8694
- }
8695
- yield content.substring(matchStartIndex, matchEndIndex);
6696
+ this.cwd = opts.cwd || "";
6697
+ this.root = opts.root;
6698
+ this.magicalBraces = !!opts.magicalBraces;
6699
+ this.nobrace = !!opts.nobrace;
6700
+ this.noext = !!opts.noext;
6701
+ this.realpath = !!opts.realpath;
6702
+ this.absolute = opts.absolute;
6703
+ this.includeChildMatches = opts.includeChildMatches !== false;
6704
+ this.noglobstar = !!opts.noglobstar;
6705
+ this.matchBase = !!opts.matchBase;
6706
+ this.maxDepth = typeof opts.maxDepth === "number" ? opts.maxDepth : Infinity;
6707
+ this.stat = !!opts.stat;
6708
+ this.ignore = opts.ignore;
6709
+ if (this.withFileTypes && this.absolute !== void 0) {
6710
+ throw new Error("cannot set absolute and withFileTypes:true");
8696
6711
  }
8697
- }
8698
- };
8699
- var BlockAnchorReplacer = function* (content, find) {
8700
- const originalLines = content.split("\n");
8701
- const searchLines = find.split("\n");
8702
- if (searchLines.length < 3) return;
8703
- if (searchLines[searchLines.length - 1] === "") searchLines.pop();
8704
- const firstLineSearch = searchLines[0].trim();
8705
- const lastLineSearch = searchLines[searchLines.length - 1].trim();
8706
- const searchBlockSize = searchLines.length;
8707
- const candidates = [];
8708
- for (let i = 0; i < originalLines.length; i++) {
8709
- if (originalLines[i].trim() !== firstLineSearch) continue;
8710
- for (let j = i + 2; j < originalLines.length; j++) {
8711
- if (originalLines[j].trim() === lastLineSearch) {
8712
- candidates.push({ startLine: i, endLine: j });
8713
- break;
8714
- }
6712
+ if (typeof pattern === "string") {
6713
+ pattern = [pattern];
8715
6714
  }
8716
- }
8717
- if (candidates.length === 0) return;
8718
- const computeSimilarity = (startLine, endLine) => {
8719
- const actualBlockSize = endLine - startLine + 1;
8720
- const linesToCheck = Math.min(searchBlockSize - 2, actualBlockSize - 2);
8721
- if (linesToCheck <= 0) return 1;
8722
- let similarity = 0;
8723
- for (let j = 1; j < searchBlockSize - 1 && j < actualBlockSize - 1; j++) {
8724
- const originalLine = originalLines[startLine + j].trim();
8725
- const searchLine = searchLines[j].trim();
8726
- const maxLen = Math.max(originalLine.length, searchLine.length);
8727
- if (maxLen === 0) continue;
8728
- const distance = levenshtein(originalLine, searchLine);
8729
- similarity += (1 - distance / maxLen) / linesToCheck;
6715
+ this.windowsPathsNoEscape = !!opts.windowsPathsNoEscape || opts.allowWindowsEscape === false;
6716
+ if (this.windowsPathsNoEscape) {
6717
+ pattern = pattern.map((p) => p.replace(/\\/g, "/"));
8730
6718
  }
8731
- return similarity;
8732
- };
8733
- const extractBlock = (startLine, endLine) => {
8734
- let matchStartIndex = 0;
8735
- for (let k = 0; k < startLine; k++) matchStartIndex += originalLines[k].length + 1;
8736
- let matchEndIndex = matchStartIndex;
8737
- for (let k = startLine; k <= endLine; k++) {
8738
- matchEndIndex += originalLines[k].length;
8739
- if (k < endLine) matchEndIndex += 1;
8740
- }
8741
- return content.substring(matchStartIndex, matchEndIndex);
8742
- };
8743
- if (candidates.length === 1) {
8744
- const { startLine, endLine } = candidates[0];
8745
- if (computeSimilarity(startLine, endLine) >= SINGLE_CANDIDATE_SIMILARITY_THRESHOLD) {
8746
- yield extractBlock(startLine, endLine);
6719
+ if (this.matchBase) {
6720
+ if (opts.noglobstar) {
6721
+ throw new TypeError("base matching requires globstar");
6722
+ }
6723
+ pattern = pattern.map((p) => p.includes("/") ? p : `./**/${p}`);
8747
6724
  }
8748
- return;
8749
- }
8750
- let bestMatch = null;
8751
- let maxSimilarity = -1;
8752
- for (const candidate of candidates) {
8753
- const similarity = computeSimilarity(candidate.startLine, candidate.endLine);
8754
- if (similarity > maxSimilarity) {
8755
- maxSimilarity = similarity;
8756
- bestMatch = candidate;
6725
+ this.pattern = pattern;
6726
+ this.platform = opts.platform || defaultPlatform3;
6727
+ this.opts = { ...opts, platform: this.platform };
6728
+ if (opts.scurry) {
6729
+ this.scurry = opts.scurry;
6730
+ if (opts.nocase !== void 0 && opts.nocase !== opts.scurry.nocase) {
6731
+ throw new Error("nocase option contradicts provided scurry option");
6732
+ }
6733
+ } else {
6734
+ const Scurry = opts.platform === "win32" ? PathScurryWin32 : opts.platform === "darwin" ? PathScurryDarwin : opts.platform ? PathScurryPosix : PathScurry;
6735
+ this.scurry = new Scurry(this.cwd, {
6736
+ nocase: opts.nocase,
6737
+ fs: opts.fs
6738
+ });
8757
6739
  }
6740
+ this.nocase = this.scurry.nocase;
6741
+ const nocaseMagicOnly = this.platform === "darwin" || this.platform === "win32";
6742
+ const mmo = {
6743
+ // default nocase based on platform
6744
+ ...opts,
6745
+ dot: this.dot,
6746
+ matchBase: this.matchBase,
6747
+ nobrace: this.nobrace,
6748
+ nocase: this.nocase,
6749
+ nocaseMagicOnly,
6750
+ nocomment: true,
6751
+ noext: this.noext,
6752
+ nonegate: true,
6753
+ optimizationLevel: 2,
6754
+ platform: this.platform,
6755
+ windowsPathsNoEscape: this.windowsPathsNoEscape,
6756
+ debug: !!this.opts.debug
6757
+ };
6758
+ const mms = this.pattern.map((p) => new Minimatch(p, mmo));
6759
+ const [matchSet, globParts] = mms.reduce((set, m) => {
6760
+ set[0].push(...m.set);
6761
+ set[1].push(...m.globParts);
6762
+ return set;
6763
+ }, [[], []]);
6764
+ this.patterns = matchSet.map((set, i) => {
6765
+ const g = globParts[i];
6766
+ if (!g)
6767
+ throw new Error("invalid pattern object");
6768
+ return new Pattern(set, g, 0, this.platform);
6769
+ });
8758
6770
  }
8759
- if (maxSimilarity >= MULTIPLE_CANDIDATES_SIMILARITY_THRESHOLD && bestMatch) {
8760
- yield extractBlock(bestMatch.startLine, bestMatch.endLine);
6771
+ async walk() {
6772
+ return [
6773
+ ...await new GlobWalker(this.patterns, this.scurry.cwd, {
6774
+ ...this.opts,
6775
+ maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
6776
+ platform: this.platform,
6777
+ nocase: this.nocase,
6778
+ includeChildMatches: this.includeChildMatches
6779
+ }).walk()
6780
+ ];
8761
6781
  }
8762
- };
8763
- var WhitespaceNormalizedReplacer = function* (content, find) {
8764
- const normalizeWhitespace = (text) => text.replace(/\s+/g, " ").trim();
8765
- const normalizedFind = normalizeWhitespace(find);
8766
- const lines = content.split("\n");
8767
- for (let i = 0; i < lines.length; i++) {
8768
- const line = lines[i];
8769
- if (normalizeWhitespace(line) === normalizedFind) {
8770
- yield line;
8771
- } else {
8772
- const normalizedLine = normalizeWhitespace(line);
8773
- if (normalizedLine.includes(normalizedFind)) {
8774
- const words = find.trim().split(/\s+/);
8775
- if (words.length > 0) {
8776
- const pattern = words.map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("\\s+");
8777
- try {
8778
- const regex = new RegExp(pattern);
8779
- const match2 = line.match(regex);
8780
- if (match2) yield match2[0];
8781
- } catch {
8782
- }
8783
- }
8784
- }
8785
- }
6782
+ walkSync() {
6783
+ return [
6784
+ ...new GlobWalker(this.patterns, this.scurry.cwd, {
6785
+ ...this.opts,
6786
+ maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
6787
+ platform: this.platform,
6788
+ nocase: this.nocase,
6789
+ includeChildMatches: this.includeChildMatches
6790
+ }).walkSync()
6791
+ ];
8786
6792
  }
8787
- const findLines = find.split("\n");
8788
- if (findLines.length > 1) {
8789
- for (let i = 0; i <= lines.length - findLines.length; i++) {
8790
- const block = lines.slice(i, i + findLines.length);
8791
- if (normalizeWhitespace(block.join("\n")) === normalizedFind) {
8792
- yield block.join("\n");
8793
- }
8794
- }
6793
+ stream() {
6794
+ return new GlobStream(this.patterns, this.scurry.cwd, {
6795
+ ...this.opts,
6796
+ maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
6797
+ platform: this.platform,
6798
+ nocase: this.nocase,
6799
+ includeChildMatches: this.includeChildMatches
6800
+ }).stream();
8795
6801
  }
8796
- };
8797
- var IndentationFlexibleReplacer = function* (content, find) {
8798
- const removeIndentation = (text) => {
8799
- const lines = text.split("\n");
8800
- const nonEmptyLines = lines.filter((line) => line.trim().length > 0);
8801
- if (nonEmptyLines.length === 0) return text;
8802
- const minIndent = Math.min(
8803
- ...nonEmptyLines.map((line) => {
8804
- const match2 = line.match(/^(\s*)/);
8805
- return match2 ? match2[1].length : 0;
8806
- })
8807
- );
8808
- return lines.map((line) => line.trim().length === 0 ? line : line.slice(minIndent)).join("\n");
8809
- };
8810
- const normalizedFind = removeIndentation(find);
8811
- const contentLines = content.split("\n");
8812
- const findLines = find.split("\n");
8813
- for (let i = 0; i <= contentLines.length - findLines.length; i++) {
8814
- const block = contentLines.slice(i, i + findLines.length).join("\n");
8815
- if (removeIndentation(block) === normalizedFind) {
8816
- yield block;
8817
- }
6802
+ streamSync() {
6803
+ return new GlobStream(this.patterns, this.scurry.cwd, {
6804
+ ...this.opts,
6805
+ maxDepth: this.maxDepth !== Infinity ? this.maxDepth + this.scurry.cwd.depth() : Infinity,
6806
+ platform: this.platform,
6807
+ nocase: this.nocase,
6808
+ includeChildMatches: this.includeChildMatches
6809
+ }).streamSync();
8818
6810
  }
8819
- };
8820
- var EscapeNormalizedReplacer = function* (content, find) {
8821
- const unescapeString = (str) => {
8822
- return str.replace(/\\(n|t|r|'|"|`|\\|\n|\$)/g, (match2, capturedChar) => {
8823
- switch (capturedChar) {
8824
- case "n":
8825
- return "\n";
8826
- case "t":
8827
- return " ";
8828
- case "r":
8829
- return "\r";
8830
- case "'":
8831
- return "'";
8832
- case '"':
8833
- return '"';
8834
- case "`":
8835
- return "`";
8836
- case "\\":
8837
- return "\\";
8838
- case "\n":
8839
- return "\n";
8840
- case "$":
8841
- return "$";
8842
- default:
8843
- return match2;
8844
- }
8845
- });
8846
- };
8847
- const unescapedFind = unescapeString(find);
8848
- if (content.includes(unescapedFind)) {
8849
- yield unescapedFind;
6811
+ /**
6812
+ * Default sync iteration function. Returns a Generator that
6813
+ * iterates over the results.
6814
+ */
6815
+ iterateSync() {
6816
+ return this.streamSync()[Symbol.iterator]();
8850
6817
  }
8851
- const lines = content.split("\n");
8852
- const findLines = unescapedFind.split("\n");
8853
- for (let i = 0; i <= lines.length - findLines.length; i++) {
8854
- const block = lines.slice(i, i + findLines.length).join("\n");
8855
- if (unescapeString(block) === unescapedFind) {
8856
- yield block;
8857
- }
6818
+ [Symbol.iterator]() {
6819
+ return this.iterateSync();
8858
6820
  }
8859
- };
8860
- var TrimmedBoundaryReplacer = function* (content, find) {
8861
- const trimmedFind = find.trim();
8862
- if (trimmedFind === find) return;
8863
- if (content.includes(trimmedFind)) {
8864
- yield trimmedFind;
6821
+ /**
6822
+ * Default async iteration function. Returns an AsyncGenerator that
6823
+ * iterates over the results.
6824
+ */
6825
+ iterate() {
6826
+ return this.stream()[Symbol.asyncIterator]();
8865
6827
  }
8866
- const lines = content.split("\n");
8867
- const findLines = find.split("\n");
8868
- for (let i = 0; i <= lines.length - findLines.length; i++) {
8869
- const block = lines.slice(i, i + findLines.length).join("\n");
8870
- if (block.trim() === trimmedFind) {
8871
- yield block;
8872
- }
6828
+ [Symbol.asyncIterator]() {
6829
+ return this.iterate();
8873
6830
  }
8874
6831
  };
8875
- var ContextAwareReplacer = function* (content, find) {
8876
- const findLines = find.split("\n");
8877
- if (findLines.length < 3) return;
8878
- if (findLines[findLines.length - 1] === "") findLines.pop();
8879
- const contentLines = content.split("\n");
8880
- const firstLine = findLines[0].trim();
8881
- const lastLine = findLines[findLines.length - 1].trim();
8882
- for (let i = 0; i < contentLines.length; i++) {
8883
- if (contentLines[i].trim() !== firstLine) continue;
8884
- for (let j = i + 2; j < contentLines.length; j++) {
8885
- if (contentLines[j].trim() === lastLine) {
8886
- const blockLines = contentLines.slice(i, j + 1);
8887
- if (blockLines.length === findLines.length) {
8888
- let matchingLines = 0;
8889
- let totalNonEmptyLines = 0;
8890
- for (let k = 1; k < blockLines.length - 1; k++) {
8891
- const blockLine = blockLines[k].trim();
8892
- const findLine = findLines[k].trim();
8893
- if (blockLine.length > 0 || findLine.length > 0) {
8894
- totalNonEmptyLines++;
8895
- if (blockLine === findLine) matchingLines++;
8896
- }
8897
- }
8898
- if (totalNonEmptyLines === 0 || matchingLines / totalNonEmptyLines >= 0.5) {
8899
- yield blockLines.join("\n");
8900
- break;
8901
- }
8902
- }
8903
- break;
8904
- }
8905
- }
6832
+
6833
+ // ../../node_modules/.bun/glob@11.1.0/node_modules/glob/dist/esm/has-magic.js
6834
+ var hasMagic = (pattern, options = {}) => {
6835
+ if (!Array.isArray(pattern)) {
6836
+ pattern = [pattern];
8906
6837
  }
8907
- };
8908
- var MultiOccurrenceReplacer = function* (content, find) {
8909
- let startIndex = 0;
8910
- while (true) {
8911
- const index = content.indexOf(find, startIndex);
8912
- if (index === -1) break;
8913
- yield find;
8914
- startIndex = index + find.length;
6838
+ for (const p of pattern) {
6839
+ if (new Minimatch(p, options).hasMagic())
6840
+ return true;
8915
6841
  }
6842
+ return false;
8916
6843
  };
8917
- var REPLACERS = [
8918
- SimpleReplacer,
8919
- LineTrimmedReplacer,
8920
- BlockAnchorReplacer,
8921
- WhitespaceNormalizedReplacer,
8922
- IndentationFlexibleReplacer,
8923
- EscapeNormalizedReplacer,
8924
- TrimmedBoundaryReplacer,
8925
- ContextAwareReplacer,
8926
- MultiOccurrenceReplacer
8927
- ];
8928
- function smartReplace(content, oldString, newString, replaceAll = false) {
8929
- if (oldString === newString) {
8930
- throw new Error("No changes to apply: oldString and newString are identical.");
8931
- }
8932
- let notFound = true;
8933
- for (const replacer of REPLACERS) {
8934
- for (const search of replacer(content, oldString)) {
8935
- const index = content.indexOf(search);
8936
- if (index === -1) continue;
8937
- notFound = false;
8938
- if (replaceAll) {
8939
- return content.replaceAll(search, newString);
8940
- }
8941
- const lastIndex = content.lastIndexOf(search);
8942
- if (index !== lastIndex) continue;
8943
- return content.substring(0, index) + newString + content.substring(index + search.length);
8944
- }
8945
- }
8946
- if (notFound) {
8947
- throw new Error(
8948
- "oldString not found in content. It must match the file contents exactly, including whitespace, indentation, and line endings."
8949
- );
8950
- }
8951
- throw new Error(
8952
- "Found multiple matches for oldString. Provide more surrounding lines in oldString to identify the correct match."
8953
- );
6844
+
6845
+ // ../../node_modules/.bun/glob@11.1.0/node_modules/glob/dist/esm/index.js
6846
+ function globStreamSync(pattern, options = {}) {
6847
+ return new Glob(pattern, options).streamSync();
8954
6848
  }
8955
- var apply_patch = async function(input, projectCwd) {
8956
- const { file_path, new_string, old_string, replaceAll: shouldReplaceAll = false } = input;
8957
- try {
8958
- if (!file_path) {
8959
- return {
8960
- success: false,
8961
- message: "Missing required parameter: file_path",
8962
- error: "MISSING_FILE_PATH"
8963
- };
8964
- }
8965
- if (old_string === void 0 || old_string === null) {
8966
- return {
8967
- success: false,
8968
- message: "Missing required parameter: old_string",
8969
- error: "MISSING_OLD_STRING"
8970
- };
8971
- }
8972
- if (new_string === void 0 || new_string === null) {
8973
- return {
8974
- success: false,
8975
- message: "Missing required parameter: new_string",
8976
- error: "MISSING_NEW_STRING"
8977
- };
8978
- }
8979
- if (old_string === new_string) {
8980
- return {
8981
- success: false,
8982
- message: "old_string and new_string must be different",
8983
- error: "STRINGS_IDENTICAL"
8984
- };
8985
- }
8986
- if (projectCwd) {
8987
- const validation = validatePath(file_path, projectCwd);
8988
- if (!validation.valid) {
8989
- return {
8990
- success: false,
8991
- message: validation.error || "Path validation failed",
8992
- error: "ACCESS_DENIED"
8993
- };
8994
- }
8995
- }
8996
- const basePath = projectCwd || process.cwd();
8997
- const absolute_file_path = resolveProjectPath(file_path, basePath);
8998
- let exists = true;
8999
- try {
9000
- await fsp.access(absolute_file_path, fs4.constants.F_OK);
9001
- } catch {
9002
- exists = false;
9003
- }
9004
- if (!exists) {
9005
- if (old_string === "") {
9006
- await fsp.mkdir(path6__default.default.dirname(absolute_file_path), { recursive: true });
9007
- await fsp.writeFile(absolute_file_path, new_string, "utf8");
9008
- const diffStats = calculateDiffStats("", new_string);
9009
- return {
9010
- success: true,
9011
- isNewFile: true,
9012
- old_string: "",
9013
- new_string,
9014
- linesAdded: diffStats.linesAdded,
9015
- linesRemoved: diffStats.linesRemoved,
9016
- message: `Created new file: ${file_path}`
9017
- };
9018
- }
9019
- return {
9020
- success: false,
9021
- message: `File not found: ${file_path}`,
9022
- error: "FILE_NOT_FOUND"
9023
- };
9024
- }
9025
- let fileContent;
9026
- try {
9027
- fileContent = await fsp.readFile(absolute_file_path, "utf8");
9028
- } catch (error) {
9029
- return {
9030
- success: false,
9031
- message: `Failed to read file: ${file_path}`,
9032
- error: "READ_ERROR"
9033
- };
9034
- }
9035
- let newContent;
9036
- try {
9037
- newContent = smartReplace(fileContent, old_string, new_string, shouldReplaceAll);
9038
- } catch (err) {
9039
- if (err.message.includes("not found")) {
9040
- return {
9041
- success: false,
9042
- message: `old_string not found in file: ${file_path}. Ensure it matches the file contents exactly, including whitespace and indentation.`,
9043
- error: "STRING_NOT_FOUND"
9044
- };
9045
- }
9046
- if (err.message.includes("multiple matches")) {
9047
- const occurrences = fileContent.split(old_string).length - 1;
9048
- return {
9049
- success: false,
9050
- 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.`,
9051
- error: "STRING_NOT_UNIQUE"
9052
- };
9053
- }
9054
- return {
9055
- success: false,
9056
- message: err.message,
9057
- error: "REPLACE_ERROR"
9058
- };
9059
- }
9060
- try {
9061
- await fsp.writeFile(absolute_file_path, newContent, "utf8");
9062
- const diffStats = calculateDiffStats(fileContent, newContent);
9063
- return {
9064
- success: true,
9065
- old_string,
9066
- new_string,
9067
- linesAdded: diffStats.linesAdded,
9068
- linesRemoved: diffStats.linesRemoved,
9069
- message: `Successfully replaced string in file: ${file_path}`
9070
- };
9071
- } catch (error) {
9072
- return {
9073
- success: false,
9074
- message: `Failed to write to file: ${file_path}`,
9075
- error: "WRITE_ERROR"
9076
- };
9077
- }
9078
- } catch (error) {
9079
- return {
9080
- success: false,
9081
- message: `Unexpected error: ${error.message}`,
9082
- error: "UNEXPECTED_ERROR"
9083
- };
9084
- }
9085
- };
6849
+ function globStream(pattern, options = {}) {
6850
+ return new Glob(pattern, options).stream();
6851
+ }
6852
+ function globSync(pattern, options = {}) {
6853
+ return new Glob(pattern, options).walkSync();
6854
+ }
6855
+ async function glob_(pattern, options = {}) {
6856
+ return new Glob(pattern, options).walk();
6857
+ }
6858
+ function globIterateSync(pattern, options = {}) {
6859
+ return new Glob(pattern, options).iterateSync();
6860
+ }
6861
+ function globIterate(pattern, options = {}) {
6862
+ return new Glob(pattern, options).iterate();
6863
+ }
6864
+ var streamSync = globStreamSync;
6865
+ var stream = Object.assign(globStream, { sync: globStreamSync });
6866
+ var iterateSync = globIterateSync;
6867
+ var iterate = Object.assign(globIterate, {
6868
+ sync: globIterateSync
6869
+ });
6870
+ var sync = Object.assign(globSync, {
6871
+ stream: globStreamSync,
6872
+ iterate: globIterateSync
6873
+ });
6874
+ var glob = Object.assign(glob_, {
6875
+ glob: glob_,
6876
+ globSync,
6877
+ sync,
6878
+ globStream,
6879
+ stream,
6880
+ globStreamSync,
6881
+ streamSync,
6882
+ globIterate,
6883
+ iterate,
6884
+ globIterateSync,
6885
+ iterateSync,
6886
+ Glob,
6887
+ hasMagic,
6888
+ escape,
6889
+ unescape
6890
+ });
6891
+ glob.glob = glob;
9086
6892
  zod.z.object({
9087
- 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"),
9088
- content: zod.z.string().describe("The full content to write to the file"),
9089
- 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()
6893
+ pattern: zod.z.string().describe("Glob pattern to match files, e.g. '*.ts', '**/*.json', or 'src/**/*.spec.ts'"),
6894
+ path: zod.z.string().optional().describe("Directory to search in (default: current directory)"),
6895
+ limit: zod.z.number().optional().describe("Maximum number of results (default: 1000)")
9090
6896
  });
9091
- var editFiles = async function(input, projectCwd) {
9092
- const { target_file, content, providedNewFile } = input;
9093
- if (!target_file) {
9094
- return {
9095
- success: false,
9096
- error: "Missing required parameter: target_file",
9097
- message: "target_file is required"
9098
- };
9099
- }
9100
- try {
9101
- if (projectCwd) {
9102
- const validation = validatePath(target_file, projectCwd);
9103
- if (!validation.valid) {
9104
- return {
9105
- success: false,
9106
- error: validation.error || "Path validation failed",
9107
- message: `Failed to edit file: ${target_file}`
9108
- };
9109
- }
9110
- }
9111
- const basePath = projectCwd || process.cwd();
9112
- const filePath = resolveProjectPath(target_file, basePath);
9113
- const dirPath = path6__default.default.dirname(filePath);
9114
- await fsp.mkdir(dirPath, { recursive: true });
9115
- let isNewFile = providedNewFile;
9116
- let existingContent = "";
9117
- const fileExists = async () => {
9118
- try {
9119
- await fsp.access(filePath, fs4.constants.F_OK);
9120
- return true;
9121
- } catch {
9122
- return false;
9123
- }
9124
- };
9125
- if (isNewFile === void 0) {
9126
- const exists = await fileExists();
9127
- if (exists) {
9128
- existingContent = await fsp.readFile(filePath, "utf8");
9129
- isNewFile = false;
9130
- } else {
9131
- isNewFile = true;
6897
+ async function findTool(input, projectCwd) {
6898
+ const cwd = input.path ? path6__default.default.resolve(projectCwd || process.cwd(), input.path) : projectCwd || process.cwd();
6899
+ const limit = input.limit ?? 1e3;
6900
+ const matches = await glob(input.pattern, { cwd, nodir: false, absolute: false, dot: true, ignore: ["**/.git/**", "**/node_modules/**"] });
6901
+ const out = matches.slice(0, limit);
6902
+ return { success: true, content: out.join("\n") || "No files found matching pattern" };
6903
+ }
6904
+ zod.z.object({
6905
+ pattern: zod.z.string().describe("Search pattern (regex or literal string)"),
6906
+ path: zod.z.string().optional().describe("Directory or file to search (default: current directory)"),
6907
+ glob: zod.z.string().optional().describe("Filter files by glob pattern, e.g. '*.ts' or '**/*.spec.ts'"),
6908
+ ignoreCase: zod.z.boolean().optional().describe("Case-insensitive search (default: false)"),
6909
+ literal: zod.z.boolean().optional().describe("Treat pattern as literal string instead of regex (default: false)"),
6910
+ context: zod.z.number().optional().describe("Number of lines to show before and after each match (default: 0)"),
6911
+ limit: zod.z.number().optional().describe("Maximum number of matches to return (default: 100)")
6912
+ });
6913
+ async function grepTool(input, projectCwd) {
6914
+ const searchPath = input.path ? path6__default.default.resolve(projectCwd || process.cwd(), input.path) : projectCwd || process.cwd();
6915
+ const args = ["-nH", "--color=never", "--hidden", "--max-count", String(input.limit ?? 100)];
6916
+ if (input.ignoreCase) args.push("-i");
6917
+ if (input.literal) args.push("-F");
6918
+ if (input.glob) args.push("--glob", input.glob);
6919
+ if (input.context && input.context > 0) args.push("-C", String(input.context));
6920
+ args.push("--", input.pattern, searchPath);
6921
+ return new Promise((resolve) => {
6922
+ const proc2 = child_process.spawn("rg", args, { stdio: ["ignore", "pipe", "pipe"] });
6923
+ let stdout = "";
6924
+ let stderr = "";
6925
+ proc2.stdout?.on("data", (d) => stdout += d.toString());
6926
+ proc2.stderr?.on("data", (d) => stderr += d.toString());
6927
+ proc2.on("close", (code) => {
6928
+ if (code === 1) {
6929
+ resolve({ success: true, content: "No matches found" });
6930
+ return;
9132
6931
  }
9133
- } else if (!isNewFile) {
9134
- const exists = await fileExists();
9135
- if (exists) {
9136
- existingContent = await fsp.readFile(filePath, "utf8");
9137
- } else {
9138
- isNewFile = true;
6932
+ if (code !== 0) {
6933
+ resolve({ success: false, error: "GREP_ERROR", message: stderr || `rg exited ${code}` });
6934
+ return;
9139
6935
  }
9140
- }
9141
- if (!isNewFile && existingContent === content) {
9142
- return {
9143
- success: true,
9144
- isNewFile: false,
9145
- message: `No changes needed: ${target_file} (content identical)`,
9146
- linesAdded: 0,
9147
- linesRemoved: 0
9148
- };
9149
- }
9150
- await fsp.writeFile(filePath, content, "utf8");
9151
- const diffStats = calculateDiffStats(existingContent, content);
9152
- if (isNewFile) {
9153
- return {
9154
- success: true,
9155
- isNewFile: true,
9156
- old_string: "",
9157
- new_string: content,
9158
- message: `Created new file: ${target_file} (+${diffStats.linesAdded} lines)`,
9159
- linesAdded: diffStats.linesAdded,
9160
- linesRemoved: diffStats.linesRemoved
9161
- };
9162
- } else {
9163
- return {
9164
- success: true,
9165
- isNewFile: false,
9166
- old_string: existingContent,
9167
- new_string: content,
9168
- message: `Modified file: ${target_file} (+${diffStats.linesAdded} -${diffStats.linesRemoved} lines)`,
9169
- linesAdded: diffStats.linesAdded,
9170
- linesRemoved: diffStats.linesRemoved
9171
- };
9172
- }
9173
- } catch (error) {
9174
- return {
9175
- success: false,
9176
- error: error instanceof Error ? error.message : "Unknown error",
9177
- message: `Failed to edit file: ${target_file}`
9178
- };
9179
- }
9180
- };
9181
-
9182
- // ../agent/src/tools/batch.ts
9183
- var toolCallSchema = zod.z.object({
9184
- tool: zod.z.string().describe("The name of the tool to execute"),
9185
- parameters: zod.z.record(zod.z.string(), zod.z.unknown()).describe("Parameters for the tool")
6936
+ resolve({ success: true, content: stdout.trim() });
6937
+ });
6938
+ proc2.on("error", (error) => resolve({ success: false, error: "GREP_ERROR", message: error.message }));
6939
+ });
6940
+ }
6941
+ zod.z.object({
6942
+ path: zod.z.string().optional().describe("Directory to list (default: current directory)"),
6943
+ limit: zod.z.number().optional().describe("Maximum number of entries to return (default: 500)")
9186
6944
  });
6945
+ async function lsTool(input, projectCwd) {
6946
+ const dir = input.path ? path6__default.default.resolve(projectCwd || process.cwd(), input.path) : projectCwd || process.cwd();
6947
+ const names = (await promises.readdir(dir)).sort((a3, b) => a3.localeCompare(b));
6948
+ const limit = input.limit ?? 500;
6949
+ const out = [];
6950
+ for (const n of names.slice(0, limit)) {
6951
+ const s = await promises.stat(path6__default.default.join(dir, n));
6952
+ out.push(s.isDirectory() ? `${n}/` : n);
6953
+ }
6954
+ return { success: true, content: out.join("\n") || "(empty directory)" };
6955
+ }
9187
6956
  zod.z.object({
9188
- 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")
6957
+ path: zod.z.string().describe("Path to the file to read (relative or absolute)"),
6958
+ offset: zod.z.number().optional().describe("Line number to start reading from (1-indexed)"),
6959
+ limit: zod.z.number().optional().describe("Maximum number of lines to read")
9189
6960
  });
9190
- var DISALLOWED_TOOLS = /* @__PURE__ */ new Set(["batch"]);
9191
- var MAX_CONCURRENCY = 5;
9192
- var PER_CALL_TIMEOUT = 3e4;
9193
- var MAX_BATCH_SIZE = 25;
9194
- var batchableToolExecutors = {
9195
- deleteFile,
9196
- grep: grepTool,
9197
- glob: globTool,
9198
- listDirectory: list,
9199
- readFile: read_file,
9200
- bash: bashTool,
9201
- stringReplace: apply_patch,
9202
- editFile: editFiles
9203
- };
9204
- function withTimeout(promise, ms) {
9205
- return new Promise((resolve, reject) => {
9206
- const timer = setTimeout(() => {
9207
- reject(new Error(`BATCH_CALL_TIMEOUT: exceeded ${ms}ms`));
9208
- }, ms);
9209
- promise.then((v) => {
9210
- clearTimeout(timer);
9211
- resolve(v);
9212
- }).catch((e) => {
9213
- clearTimeout(timer);
9214
- reject(e);
9215
- });
9216
- });
6961
+ async function readTool(input, projectCwd) {
6962
+ const absolute = path6__default.default.isAbsolute(input.path) ? input.path : path6__default.default.resolve(projectCwd || process.cwd(), input.path);
6963
+ const s = await promises.stat(absolute);
6964
+ if (s.isDirectory()) {
6965
+ const entries = (await promises.readdir(absolute)).sort();
6966
+ return { success: true, content: entries.join("\n") || "(empty directory)" };
6967
+ }
6968
+ const content = await promises.readFile(absolute, "utf8");
6969
+ const lines = content.split(/\r?\n/);
6970
+ const start = input.offset ? Math.max(1, input.offset) : 1;
6971
+ const end = input.limit ? start + input.limit - 1 : lines.length;
6972
+ const slice = lines.slice(start - 1, end);
6973
+ return { success: true, content: slice.map((l, i) => `${start + i}: ${l}`).join("\n") };
9217
6974
  }
9218
- async function runWithConcurrencyLimit(tasks, limit) {
9219
- const results = new Array(tasks.length);
9220
- let nextIndex = 0;
9221
- async function worker() {
9222
- while (nextIndex < tasks.length) {
9223
- const idx = nextIndex++;
9224
- results[idx] = await tasks[idx]();
9225
- }
9226
- }
9227
- const workers = Array.from({ length: Math.min(limit, tasks.length) }, () => worker());
9228
- await Promise.all(workers);
9229
- return results;
6975
+ zod.z.object({
6976
+ path: zod.z.string().describe("Path to the file to write (relative or absolute)"),
6977
+ content: zod.z.string().describe("Content to write to the file")
6978
+ });
6979
+ async function writeTool(input, projectCwd) {
6980
+ const absolute = path6__default.default.isAbsolute(input.path) ? input.path : path6__default.default.resolve(projectCwd || process.cwd(), input.path);
6981
+ await promises.mkdir(path6__default.default.dirname(absolute), { recursive: true });
6982
+ await promises.writeFile(absolute, input.content, "utf8");
6983
+ return { success: true, message: `Wrote ${input.path}` };
9230
6984
  }
9231
- var batchTool = async function(input, projectCwd) {
9232
- const { tool_calls } = input;
9233
- const callsToExecute = tool_calls.slice(0, MAX_BATCH_SIZE);
9234
- const discardedCalls = tool_calls.slice(MAX_BATCH_SIZE);
9235
- const executeCall = async (call) => {
9236
- const start = performance.now();
9237
- try {
9238
- if (DISALLOWED_TOOLS.has(call.tool)) {
9239
- return {
9240
- tool: call.tool,
9241
- success: false,
9242
- error: `Tool '${call.tool}' is not allowed in batch. Disallowed tools: ${Array.from(DISALLOWED_TOOLS).join(", ")}`,
9243
- durationMs: 0
9244
- };
9245
- }
9246
- const executor = batchableToolExecutors[call.tool];
9247
- if (!executor) {
9248
- const availableTools = Object.keys(batchableToolExecutors).join(", ");
9249
- return {
9250
- tool: call.tool,
9251
- success: false,
9252
- error: `Tool '${call.tool}' not found. Available tools for batching: ${availableTools}`,
9253
- durationMs: 0
9254
- };
9255
- }
9256
- const result = await withTimeout(executor(call.parameters, projectCwd), PER_CALL_TIMEOUT);
9257
- const durationMs = Math.round(performance.now() - start);
9258
- return {
9259
- tool: call.tool,
9260
- success: result.success !== false,
9261
- result,
9262
- durationMs
9263
- };
9264
- } catch (error) {
9265
- const durationMs = Math.round(performance.now() - start);
9266
- const timedOut = error.message?.includes("BATCH_CALL_TIMEOUT");
9267
- return {
9268
- tool: call.tool,
9269
- success: false,
9270
- error: error.message || String(error),
9271
- durationMs,
9272
- timedOut
9273
- };
9274
- }
9275
- };
9276
- const tasks = callsToExecute.map(
9277
- (call) => () => executeCall(call)
9278
- );
9279
- const results = await runWithConcurrencyLimit(tasks, MAX_CONCURRENCY);
9280
- for (const call of discardedCalls) {
9281
- results.push({
9282
- tool: call.tool,
9283
- success: false,
9284
- error: `Maximum of ${MAX_BATCH_SIZE} tools allowed in batch`,
9285
- durationMs: 0
9286
- });
9287
- }
9288
- const successfulCalls = results.filter((r) => r.success).length;
9289
- const failedCalls = results.length - successfulCalls;
9290
- const outputMessage = failedCalls > 0 ? `Executed ${successfulCalls}/${results.length} tools successfully. ${failedCalls} failed.` : `All ${successfulCalls} tools executed successfully.
9291
-
9292
- Keep using the batch tool for optimal performance in your next response!`;
9293
- return {
9294
- success: failedCalls === 0,
9295
- message: outputMessage,
9296
- totalCalls: results.length,
9297
- successful: successfulCalls,
9298
- failed: failedCalls,
9299
- results
9300
- };
9301
- };
9302
- var toolCallSchema2 = zod.z.object({
6985
+ var toolCallSchema = zod.z.object({
9303
6986
  type: zod.z.literal("tool_call"),
9304
6987
  id: zod.z.string(),
9305
6988
  tool: zod.z.string(),
@@ -9309,24 +6992,20 @@ var toolCallSchema2 = zod.z.object({
9309
6992
  });
9310
6993
  var DEFAULT_TIMEOUT_MS = 3e4;
9311
6994
  var TOOL_TIMEOUTS = {
9312
- readFile: 1e4,
9313
- glob: 15e3,
9314
- grep: 2e4,
9315
- listDirectory: 15e3,
9316
- editFile: 15e3,
9317
- deleteFile: 1e4,
9318
- stringReplace: 15e3,
6995
+ read: 1e4,
9319
6996
  bash: 6e4,
9320
- batch: 12e4
6997
+ edit: 2e4,
6998
+ write: 2e4,
6999
+ grep: 2e4,
7000
+ find: 2e4,
7001
+ ls: 15e3
9321
7002
  };
9322
7003
  function getTimeoutForTool(tool) {
9323
7004
  return TOOL_TIMEOUTS[tool] ?? DEFAULT_TIMEOUT_MS;
9324
7005
  }
9325
- function withTimeout2(promise, ms, tool) {
7006
+ function withTimeout(promise, ms, tool) {
9326
7007
  return new Promise((resolve, reject) => {
9327
- const timer = setTimeout(() => {
9328
- reject(new ToolTimeoutError(tool, ms));
9329
- }, ms);
7008
+ const timer = setTimeout(() => reject(new ToolTimeoutError(tool, ms)), ms);
9330
7009
  promise.then((result) => {
9331
7010
  clearTimeout(timer);
9332
7011
  resolve(result);
@@ -9356,54 +7035,32 @@ async function executeTool(toolName, args, projectCwd, executors) {
9356
7035
  const start = performance.now();
9357
7036
  const executor = executors[toolName];
9358
7037
  if (!executor) {
9359
- return {
9360
- success: false,
9361
- error: { code: "UNKNOWN_TOOL", message: `Unknown tool: ${toolName}` },
9362
- metadata: { tool: toolName, durationMs: 0 }
9363
- };
7038
+ return { success: false, error: { code: "UNKNOWN_TOOL", message: `Unknown tool: ${toolName}` }, metadata: { tool: toolName, durationMs: 0 } };
9364
7039
  }
9365
7040
  const cwdCheck = requireProjectCwd(toolName, projectCwd);
9366
7041
  if (!cwdCheck.allowed) {
9367
- return {
9368
- success: false,
9369
- error: { code: "ACCESS_DENIED", message: cwdCheck.error },
9370
- metadata: { tool: toolName, durationMs: 0 }
9371
- };
7042
+ return { success: false, error: { code: "ACCESS_DENIED", message: cwdCheck.error }, metadata: { tool: toolName, durationMs: 0 } };
9372
7043
  }
9373
7044
  try {
9374
- const timeoutMs = getTimeoutForTool(toolName);
9375
- const result = await withTimeout2(executor(args, projectCwd), timeoutMs, toolName);
7045
+ const result = await withTimeout(executor(args, projectCwd), getTimeoutForTool(toolName), toolName);
9376
7046
  const durationMs = Math.round(performance.now() - start);
9377
- return {
9378
- success: result?.success !== false,
9379
- data: result,
9380
- metadata: { tool: toolName, durationMs }
9381
- };
7047
+ return { success: result?.success !== false, data: result, metadata: { tool: toolName, durationMs } };
9382
7048
  } catch (err) {
9383
7049
  const durationMs = Math.round(performance.now() - start);
9384
7050
  if (err instanceof ToolTimeoutError) {
9385
- return {
9386
- success: false,
9387
- error: { code: "TOOL_TIMEOUT", message: err.message },
9388
- metadata: { tool: toolName, durationMs, timedOut: true }
9389
- };
7051
+ return { success: false, error: { code: "TOOL_TIMEOUT", message: err.message }, metadata: { tool: toolName, durationMs, timedOut: true } };
9390
7052
  }
9391
7053
  return {
9392
7054
  success: false,
9393
- error: {
9394
- code: err.code ?? "TOOL_EXECUTION_ERROR",
9395
- message: err.message ?? String(err)
9396
- },
7055
+ error: { code: err.code ?? "TOOL_EXECUTION_ERROR", message: err.message ?? String(err) },
9397
7056
  metadata: { tool: toolName, durationMs }
9398
7057
  };
9399
7058
  }
9400
7059
  }
9401
7060
  function parseToolCall(raw) {
9402
- const result = toolCallSchema2.safeParse(raw);
7061
+ const result = toolCallSchema.safeParse(raw);
9403
7062
  if (!result.success) {
9404
- return new ValidationError(
9405
- `Invalid tool_call payload: ${result.error.issues.map((i) => i.message).join(", ")}`
9406
- );
7063
+ return new ValidationError(`Invalid tool_call payload: ${result.error.issues.map((i) => i.message).join(", ")}`);
9407
7064
  }
9408
7065
  return result.data;
9409
7066
  }
@@ -9422,30 +7079,22 @@ function getReconnectDelay2() {
9422
7079
  return Math.floor(delay + jitter);
9423
7080
  }
9424
7081
  var toolExecutors = {
9425
- editFile: editFiles,
9426
- deleteFile,
9427
- grep: grepTool,
9428
- glob: globTool,
9429
- listDirectory: list,
9430
- readFile: read_file,
9431
- stringReplace: apply_patch,
7082
+ read: readTool,
9432
7083
  bash: bashTool,
9433
- batch: batchTool
7084
+ edit: editTool,
7085
+ write: writeTool,
7086
+ grep: grepTool,
7087
+ find: findTool,
7088
+ ls: lsTool
9434
7089
  };
9435
7090
  function getConnectionStatus(ws) {
9436
7091
  return ws.readyState === WebSocket2__default.default.CONNECTING ? "connecting" : ws.readyState === WebSocket2__default.default.OPEN ? "open" : ws.readyState === WebSocket2__default.default.CLOSING ? "closing" : "closed";
9437
7092
  }
9438
7093
  function connectToServer(serverUrl = DEFAULT_SERVER_URL) {
9439
7094
  const tokens = getTokens();
9440
- if (!tokens) {
9441
- throw new Error("No tokens found");
9442
- }
7095
+ if (!tokens) throw new Error("No tokens found");
9443
7096
  const wsUrl = `${serverUrl}/agent-streams`;
9444
- const ws = new WebSocket2__default.default(wsUrl, {
9445
- headers: {
9446
- "Authorization": `Bearer ${tokens.access_token}`
9447
- }
9448
- });
7097
+ const ws = new WebSocket2__default.default(wsUrl, { headers: { "Authorization": `Bearer ${tokens.access_token}` } });
9449
7098
  ws.on("open", () => {
9450
7099
  reconnectAttempts2 = 0;
9451
7100
  console.log(pc3__default.default.cyan("connected to server"));
@@ -9461,33 +7110,16 @@ function connectToServer(serverUrl = DEFAULT_SERVER_URL) {
9461
7110
  if (message.type === "tool_call") {
9462
7111
  const validated = parseToolCall(message);
9463
7112
  if (validated instanceof ValidationError) {
9464
- ws.send(JSON.stringify({
9465
- type: "tool_result",
9466
- id: message.id ?? "unknown",
9467
- error: validated.message
9468
- }));
7113
+ ws.send(JSON.stringify({ type: "tool_result", id: message.id ?? "unknown", error: validated.message }));
9469
7114
  console.error(pc3__default.default.red(` validation error: ${validated.message}`));
9470
7115
  return;
9471
7116
  }
9472
7117
  console.log(pc3__default.default.gray(`> ${validated.tool}`));
9473
- const response = await executeTool(
9474
- validated.tool,
9475
- validated.args,
9476
- validated.projectCwd,
9477
- toolExecutors
9478
- );
7118
+ const response = await executeTool(validated.tool, validated.args, validated.projectCwd, toolExecutors);
9479
7119
  if (response.success) {
9480
- ws.send(JSON.stringify({
9481
- type: "tool_result",
9482
- id: validated.id,
9483
- result: response.data
9484
- }));
7120
+ ws.send(JSON.stringify({ type: "tool_result", id: validated.id, result: response.data }));
9485
7121
  } else {
9486
- ws.send(JSON.stringify({
9487
- type: "tool_result",
9488
- id: validated.id,
9489
- error: response.error?.message ?? "Unknown error"
9490
- }));
7122
+ ws.send(JSON.stringify({ type: "tool_result", id: validated.id, error: response.error?.message ?? "Unknown error" }));
9491
7123
  console.error(pc3__default.default.red(` ${validated.tool} failed: ${response.error?.message}`));
9492
7124
  }
9493
7125
  if (response.metadata?.durationMs && response.metadata.durationMs > 5e3) {
@@ -9497,21 +7129,11 @@ function connectToServer(serverUrl = DEFAULT_SERVER_URL) {
9497
7129
  console.log(pc3__default.default.gray(`> rpc: ${message.method}`));
9498
7130
  try {
9499
7131
  const handler = rpcHandlers[message.method];
9500
- if (!handler) {
9501
- throw new Error(`Unknown RPC method: ${message.method}`);
9502
- }
7132
+ if (!handler) throw new Error(`Unknown RPC method: ${message.method}`);
9503
7133
  const result = await handler(message.args);
9504
- ws.send(JSON.stringify({
9505
- type: "tool_result",
9506
- id: message.id,
9507
- result
9508
- }));
7134
+ ws.send(JSON.stringify({ type: "tool_result", id: message.id, result }));
9509
7135
  } catch (error) {
9510
- ws.send(JSON.stringify({
9511
- type: "tool_result",
9512
- id: message.id,
9513
- error: error.message
9514
- }));
7136
+ ws.send(JSON.stringify({ type: "tool_result", id: message.id, error: error.message }));
9515
7137
  console.error(pc3__default.default.red(` rpc failed: ${message.method}`));
9516
7138
  }
9517
7139
  }