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