@wrongstack/tools 0.267.0 → 0.268.0

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/pack.js CHANGED
@@ -763,8 +763,8 @@ async function* spawnStream(opts) {
763
763
  try {
764
764
  for (; ; ) {
765
765
  while (queue.length === 0) {
766
- await new Promise((resolve7) => {
767
- waiter = resolve7;
766
+ await new Promise((resolve6) => {
767
+ waiter = resolve6;
768
768
  });
769
769
  }
770
770
  const chunk = queue.shift();
@@ -1319,10 +1319,10 @@ var bashTool = {
1319
1319
  queue.push(c);
1320
1320
  }
1321
1321
  };
1322
- const next = () => new Promise((resolve7) => {
1322
+ const next = () => new Promise((resolve6) => {
1323
1323
  const c = queue.shift();
1324
- if (c) resolve7(c);
1325
- else resolveNext = resolve7;
1324
+ if (c) resolve6(c);
1325
+ else resolveNext = resolve6;
1326
1326
  });
1327
1327
  let lastFlush = Date.now();
1328
1328
  const flush = () => {
@@ -3530,8 +3530,9 @@ async function loadGitignoreMatcher(projectRoot) {
3530
3530
 
3531
3531
  // src/codebase-index/indexer.ts
3532
3532
  var YIELD_EVERY_N = 50;
3533
+ var PARALLEL_BATCH = 20;
3533
3534
  function yieldEventLoop() {
3534
- return new Promise((resolve7) => setImmediate(resolve7));
3535
+ return new Promise((resolve6) => setImmediate(resolve6));
3535
3536
  }
3536
3537
  function throwIfAborted(signal) {
3537
3538
  if (!signal?.aborted) return;
@@ -3663,97 +3664,108 @@ async function runIndexerWithStore(store, opts) {
3663
3664
  if (!force) {
3664
3665
  for (const meta of store.getAllFileMetas()) existingMeta.set(meta.file, meta);
3665
3666
  }
3666
- for (let fi = 0; fi < files.length; fi++) {
3667
- const file = expectDefined(files[fi]);
3668
- opts.onProgress?.(fi + 1, files.length);
3669
- if (fi > 0 && fi % YIELD_EVERY_N === 0) {
3667
+ for (let batchStart = 0; batchStart < files.length; batchStart += PARALLEL_BATCH) {
3668
+ const batchEnd = Math.min(batchStart + PARALLEL_BATCH, files.length);
3669
+ const batchFiles = files.slice(batchStart, batchEnd);
3670
+ opts.onProgress?.(batchEnd, files.length);
3671
+ if (batchStart > 0 && batchStart % YIELD_EVERY_N === 0) {
3670
3672
  await yieldEventLoop();
3671
3673
  throwIfAborted(signal);
3672
3674
  }
3673
- let stat11;
3674
- try {
3675
- const statOpts = signal ? { signal } : {};
3676
- stat11 = await fs14.stat(file, statOpts);
3677
- } catch (e) {
3678
- if (isAbortError(e)) throw e;
3679
- store.deleteFile(file);
3680
- continue;
3681
- }
3682
- if (!stat11.isFile()) continue;
3683
- const lang = detectLang(file);
3684
- if (!lang) continue;
3685
- const meta = existingMeta.get(file);
3686
- if (!force && meta && meta.mtimeMs === Math.floor(stat11.mtimeMs)) {
3687
- langStats[lang] = (langStats[lang] ?? 0) + meta.symbolCount;
3688
- symbolsIndexed += meta.symbolCount;
3689
- filesIndexed++;
3690
- continue;
3691
- }
3692
- store.deleteRefsForFile(file);
3693
- store.deleteSymbolsForFile(file);
3694
- let content;
3695
- try {
3696
- content = await fs14.readFile(file, { encoding: "utf8", signal });
3697
- } catch (e) {
3698
- if (isAbortError(e)) throw e;
3699
- errors.push(`read error: ${file}: ${e instanceof Error ? e.message : String(e)}`);
3700
- continue;
3701
- }
3702
- let parsed;
3703
- try {
3704
- parsed = await parseFile(file, content, lang);
3705
- } catch (e) {
3706
- errors.push(`parse error: ${file}: ${e instanceof Error ? e.message : String(e)}`);
3707
- continue;
3708
- }
3709
- if (parsed.symbols.length === 0) {
3710
- store.upsertFile({
3711
- file,
3712
- lang,
3713
- mtimeMs: Math.floor(stat11.mtimeMs),
3714
- symbolCount: 0,
3715
- lastIndexed: Date.now()
3716
- });
3717
- filesIndexed++;
3718
- continue;
3719
- }
3720
- const nextId = store.getMaxSymbolId() + 1;
3721
- const symbolsWithIds = parsed.symbols.map((s, i) => ({ ...s, id: nextId + i }));
3722
- store.insertSymbols(symbolsWithIds, nextId);
3723
- const count = symbolsWithIds.length;
3724
- symbolsIndexed += count;
3725
- langStats[lang] = (langStats[lang] ?? 0) + count;
3726
- if (parsed.refs && parsed.refs.length > 0) {
3727
- const refsByLine = /* @__PURE__ */ new Map();
3728
- for (const r of parsed.refs) {
3729
- let arr = refsByLine.get(r.line);
3730
- if (!arr) {
3731
- arr = [];
3732
- refsByLine.set(r.line, arr);
3675
+ const statOpts = signal ? { signal } : {};
3676
+ const statReadParse = await Promise.allSettled(
3677
+ batchFiles.map(async (file) => {
3678
+ let stat11;
3679
+ try {
3680
+ stat11 = await fs14.stat(file, statOpts);
3681
+ } catch (e) {
3682
+ if (isAbortError(e)) throw e;
3683
+ return { file, stat: null, lang: "", parsed: null, error: `stat error: ${e instanceof Error ? e.message : String(e)}` };
3733
3684
  }
3734
- arr.push(r);
3735
- }
3736
- const batch = [];
3737
- for (const sym of symbolsWithIds) {
3738
- const symRefs = refsByLine.get(sym.line);
3739
- if (symRefs) {
3740
- for (const r of symRefs) {
3741
- batch.push({ ...r, fromId: sym.id });
3742
- }
3685
+ if (!stat11.isFile()) return { file, stat: stat11, lang: "", parsed: null };
3686
+ const lang = detectLang(file);
3687
+ if (!lang) return { file, stat: stat11, lang: "", parsed: null };
3688
+ let content;
3689
+ try {
3690
+ content = await fs14.readFile(file, { encoding: "utf8", signal });
3691
+ } catch (e) {
3692
+ if (isAbortError(e)) throw e;
3693
+ return { file, stat: stat11, lang, parsed: null, error: `read error: ${e instanceof Error ? e.message : String(e)}` };
3694
+ }
3695
+ let parsed;
3696
+ try {
3697
+ parsed = await parseFile(file, content, lang);
3698
+ } catch (e) {
3699
+ return { file, stat: stat11, lang, parsed: null, error: `parse error: ${e instanceof Error ? e.message : String(e)}` };
3743
3700
  }
3701
+ return { file, stat: stat11, lang, parsed, content };
3702
+ })
3703
+ );
3704
+ for (let fi = 0; fi < statReadParse.length; fi++) {
3705
+ const settled = statReadParse[fi];
3706
+ const file = expectDefined(batchFiles[fi]);
3707
+ if (settled.status === "rejected") {
3708
+ const err = settled.reason;
3709
+ if (err instanceof Error && isAbortError(err)) throw err;
3710
+ errors.push(`batch error: ${file}: ${err instanceof Error ? err.message : String(err)}`);
3711
+ continue;
3744
3712
  }
3745
- if (batch.length > 0) {
3746
- store.insertRefsBatch(batch);
3713
+ const result = settled.value;
3714
+ if (result.error) {
3715
+ if (result.stat) store.deleteFile(file);
3716
+ if (result.error.includes("error:")) errors.push(result.error);
3717
+ continue;
3747
3718
  }
3719
+ const { stat: stat11, lang, parsed } = result;
3720
+ if (!lang || !parsed) {
3721
+ if (lang) {
3722
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat11.mtimeMs), symbolCount: 0, lastIndexed: Date.now() });
3723
+ filesIndexed++;
3724
+ }
3725
+ continue;
3726
+ }
3727
+ const meta = existingMeta.get(file);
3728
+ if (!force && meta && meta.mtimeMs === Math.floor(stat11.mtimeMs)) {
3729
+ langStats[lang] = (langStats[lang] ?? 0) + meta.symbolCount;
3730
+ symbolsIndexed += meta.symbolCount;
3731
+ filesIndexed++;
3732
+ continue;
3733
+ }
3734
+ store.deleteRefsForFile(file);
3735
+ store.deleteSymbolsForFile(file);
3736
+ if (parsed.symbols.length === 0) {
3737
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat11.mtimeMs), symbolCount: 0, lastIndexed: Date.now() });
3738
+ filesIndexed++;
3739
+ continue;
3740
+ }
3741
+ const nextId = store.getMaxSymbolId() + 1;
3742
+ const symbolsWithIds = parsed.symbols.map((s, i) => ({ ...s, id: nextId + i }));
3743
+ store.insertSymbols(symbolsWithIds, nextId);
3744
+ const count = symbolsWithIds.length;
3745
+ symbolsIndexed += count;
3746
+ langStats[lang] = (langStats[lang] ?? 0) + count;
3747
+ if (parsed.refs && parsed.refs.length > 0) {
3748
+ const refsByLine = /* @__PURE__ */ new Map();
3749
+ for (const r of parsed.refs) {
3750
+ let arr = refsByLine.get(r.line);
3751
+ if (!arr) {
3752
+ arr = [];
3753
+ refsByLine.set(r.line, arr);
3754
+ }
3755
+ arr.push(r);
3756
+ }
3757
+ const batch = [];
3758
+ for (const sym of symbolsWithIds) {
3759
+ const symRefs = refsByLine.get(sym.line);
3760
+ if (symRefs) {
3761
+ for (const r of symRefs) batch.push({ ...r, fromId: sym.id });
3762
+ }
3763
+ }
3764
+ if (batch.length > 0) store.insertRefsBatch(batch);
3765
+ }
3766
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat11.mtimeMs), symbolCount: count, lastIndexed: Date.now() });
3767
+ filesIndexed++;
3748
3768
  }
3749
- store.upsertFile({
3750
- file,
3751
- lang,
3752
- mtimeMs: Math.floor(stat11.mtimeMs),
3753
- symbolCount: count,
3754
- lastIndexed: Date.now()
3755
- });
3756
- filesIndexed++;
3757
3769
  }
3758
3770
  for (const [file_] of existingMeta) {
3759
3771
  try {
@@ -3920,7 +3932,7 @@ function terminateWorker(reason) {
3920
3932
  function callIndexOp(op, args, opts) {
3921
3933
  const w = ensureWorker();
3922
3934
  if (!w) return callInline(op, args, opts);
3923
- return new Promise((resolve7, reject) => {
3935
+ return new Promise((resolve6, reject) => {
3924
3936
  const id = nextRpcId++;
3925
3937
  const timer = setTimeout(() => {
3926
3938
  pending.delete(id);
@@ -3943,7 +3955,7 @@ function callIndexOp(op, args, opts) {
3943
3955
  pending.set(id, {
3944
3956
  resolve: (v) => {
3945
3957
  cleanup();
3946
- resolve7(v);
3958
+ resolve6(v);
3947
3959
  },
3948
3960
  reject: (e) => {
3949
3961
  cleanup();
@@ -4369,7 +4381,7 @@ function findGitDir(cwd) {
4369
4381
  return null;
4370
4382
  }
4371
4383
  function runGit(args, cwd, signal) {
4372
- return new Promise((resolve7) => {
4384
+ return new Promise((resolve6) => {
4373
4385
  let stdout = "";
4374
4386
  let stderr = "";
4375
4387
  const child = spawn("git", args, {
@@ -4385,8 +4397,8 @@ function runGit(args, cwd, signal) {
4385
4397
  child.stderr?.on("data", (c) => {
4386
4398
  stderr += c.toString();
4387
4399
  });
4388
- child.on("close", (code) => resolve7({ stdout, stderr, exitCode: code ?? 0 }));
4389
- child.on("error", (e) => resolve7({ stdout: "", stderr: e.message, exitCode: 1 }));
4400
+ child.on("close", (code) => resolve6({ stdout, stderr, exitCode: code ?? 0 }));
4401
+ child.on("error", (e) => resolve6({ stdout: "", stderr: e.message, exitCode: 1 }));
4390
4402
  });
4391
4403
  }
4392
4404
  async function fileDiff(input, ctx, _signal) {
@@ -4877,26 +4889,26 @@ var execTool = {
4877
4889
  allowed: false
4878
4890
  };
4879
4891
  }
4880
- const requestedCwd = input.cwd ? path3.resolve(ctx.projectRoot, input.cwd) : ctx.cwd;
4881
- const rel = path3.relative(ctx.projectRoot, requestedCwd);
4882
- if (rel.startsWith("..") || path3.isAbsolute(rel)) {
4892
+ let cwd;
4893
+ try {
4894
+ cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : await safeResolveReal(ctx.cwd, ctx);
4895
+ } catch {
4883
4896
  return {
4884
4897
  command: cmd,
4885
4898
  args,
4886
4899
  stdout: "",
4887
- stderr: `cwd "${input.cwd}" resolves outside project root`,
4900
+ stderr: `cwd "${input.cwd ?? ctx.cwd}" resolves outside project root`,
4888
4901
  exitCode: 1,
4889
4902
  truncated: false,
4890
4903
  allowed: false
4891
4904
  };
4892
4905
  }
4893
- const cwd = requestedCwd;
4894
4906
  const signal = opts.signal;
4895
4907
  return runCommand(cmd, args, cwd, timeout, signal, ctx.session?.id);
4896
4908
  }
4897
4909
  };
4898
4910
  function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
4899
- return new Promise((resolve7) => {
4911
+ return new Promise((resolve6) => {
4900
4912
  let stdout = "";
4901
4913
  let stderr = "";
4902
4914
  let killed = false;
@@ -4951,7 +4963,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
4951
4963
  const exitCode = killed ? 124 : code ?? 1;
4952
4964
  registry.afterCall(durationMs, exitCode !== 0);
4953
4965
  const spooled = spool.finalize();
4954
- resolve7({
4966
+ resolve6({
4955
4967
  command: cmd,
4956
4968
  args,
4957
4969
  stdout: normalizeCommandOutput(stdout) + (spooled ? spoolNote(spooled) : ""),
@@ -4967,7 +4979,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
4967
4979
  if (typeof pid === "number") registry.unregister(pid);
4968
4980
  registry.afterCall(Date.now() - startedAt, true);
4969
4981
  spool.finalize();
4970
- resolve7({
4982
+ resolve6({
4971
4983
  command: cmd,
4972
4984
  args,
4973
4985
  stdout: normalizeCommandOutput(stdout),
@@ -5571,7 +5583,7 @@ function buildArgs(input) {
5571
5583
  }
5572
5584
  }
5573
5585
  function runGit2(args, cwd, signal) {
5574
- return new Promise((resolve7) => {
5586
+ return new Promise((resolve6) => {
5575
5587
  let stdout = "";
5576
5588
  let stderr = "";
5577
5589
  const child = spawn("git", args, {
@@ -5592,7 +5604,7 @@ function runGit2(args, cwd, signal) {
5592
5604
  }
5593
5605
  });
5594
5606
  child.on("error", (err) => {
5595
- resolve7({
5607
+ resolve6({
5596
5608
  command: args[0],
5597
5609
  stdout: normalizeCommandOutput(stdout),
5598
5610
  stderr: err.message,
@@ -5601,7 +5613,7 @@ function runGit2(args, cwd, signal) {
5601
5613
  });
5602
5614
  });
5603
5615
  child.on("close", (code) => {
5604
- resolve7({
5616
+ resolve6({
5605
5617
  command: args[0],
5606
5618
  stdout: normalizeCommandOutput(stdout),
5607
5619
  stderr: normalizeCommandOutput(stderr),
@@ -5824,13 +5836,13 @@ var grepTool = {
5824
5836
  }
5825
5837
  };
5826
5838
  async function detectRg(signal) {
5827
- return new Promise((resolve7) => {
5839
+ return new Promise((resolve6) => {
5828
5840
  try {
5829
5841
  const p = spawn("rg", ["--version"], { env: buildChildEnv(), stdio: "ignore", signal, windowsHide: true });
5830
- p.on("error", () => resolve7(false));
5831
- p.on("close", (code) => resolve7(code === 0));
5842
+ p.on("error", () => resolve6(false));
5843
+ p.on("close", (code) => resolve6(code === 0));
5832
5844
  } catch {
5833
- resolve7(false);
5845
+ resolve6(false);
5834
5846
  }
5835
5847
  });
5836
5848
  }
@@ -6245,8 +6257,8 @@ var jsonTool = {
6245
6257
  };
6246
6258
  }
6247
6259
  };
6248
- function query(data, path21) {
6249
- const parts = path21.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
6260
+ function query(data, path20) {
6261
+ const parts = path20.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
6250
6262
  let current = data;
6251
6263
  for (const part of parts) {
6252
6264
  if (current === null || current === void 0) return void 0;
@@ -6472,7 +6484,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
6472
6484
  };
6473
6485
  }
6474
6486
  args.push("--timestamps", service);
6475
- return new Promise((resolve7) => {
6487
+ return new Promise((resolve6) => {
6476
6488
  let stdout = "";
6477
6489
  let stderr = "";
6478
6490
  const MAX = 2e5;
@@ -6488,7 +6500,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
6488
6500
  if (settled) return;
6489
6501
  settled = true;
6490
6502
  clearTimeout(timer);
6491
- resolve7(result);
6503
+ resolve6(result);
6492
6504
  };
6493
6505
  const child = spawn("docker", args, { cwd, signal, env: buildChildEnv(), stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
6494
6506
  const timer = setTimeout(() => {
@@ -6523,7 +6535,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
6523
6535
  }
6524
6536
  var DOCKER_LOGS_TIMEOUT_MS = 3e3;
6525
6537
  var MAX_TAIL_LINES = 1e5;
6526
- async function fileLogs(path21, lines, filterRe, stream) {
6538
+ async function fileLogs(path20, lines, filterRe, stream) {
6527
6539
  const { createInterface } = await import('node:readline');
6528
6540
  const { createReadStream } = await import('node:fs');
6529
6541
  const entries = [];
@@ -6532,7 +6544,7 @@ async function fileLogs(path21, lines, filterRe, stream) {
6532
6544
  let writeIdx = 0;
6533
6545
  let totalLines = 0;
6534
6546
  const rl = createInterface({
6535
- input: createReadStream(path21),
6547
+ input: createReadStream(path20),
6536
6548
  crlfDelay: Number.POSITIVE_INFINITY
6537
6549
  });
6538
6550
  for await (const line of rl) {
@@ -6553,7 +6565,7 @@ async function fileLogs(path21, lines, filterRe, stream) {
6553
6565
  if (parsed) entries.push(parsed);
6554
6566
  }
6555
6567
  return {
6556
- source: path21,
6568
+ source: path20,
6557
6569
  entries,
6558
6570
  total: entries.length,
6559
6571
  truncated: totalLines > effLines,
@@ -6650,7 +6662,7 @@ var outdatedTool = {
6650
6662
  }
6651
6663
  };
6652
6664
  function runOutdated(manager, args, cwd, signal) {
6653
- return new Promise((resolve7) => {
6665
+ return new Promise((resolve6) => {
6654
6666
  let stdout = "";
6655
6667
  let stderr = "";
6656
6668
  const MAX = 1e5;
@@ -6666,10 +6678,10 @@ function runOutdated(manager, args, cwd, signal) {
6666
6678
  });
6667
6679
  child.on("close", (code) => {
6668
6680
  const result = parseOutdatedOutput(stdout, code ?? 0);
6669
- resolve7(result);
6681
+ resolve6(result);
6670
6682
  });
6671
6683
  child.on("error", (e) => {
6672
- resolve7({
6684
+ resolve6({
6673
6685
  exit_code: 1,
6674
6686
  packages: [],
6675
6687
  total: 0,
@@ -6803,7 +6815,7 @@ function stripPathComponents(p, strip) {
6803
6815
  return parts.slice(strip).join("/");
6804
6816
  }
6805
6817
  function runPatch(args, cwd, signal) {
6806
- return new Promise((resolve7) => {
6818
+ return new Promise((resolve6) => {
6807
6819
  let stdout = "";
6808
6820
  let stderr = "";
6809
6821
  const env = { ...buildChildEnv(), LANG: "C", LC_ALL: "C" };
@@ -6814,8 +6826,8 @@ function runPatch(args, cwd, signal) {
6814
6826
  child.stderr?.on("data", (c) => {
6815
6827
  stderr += c.toString();
6816
6828
  });
6817
- child.on("close", (code) => resolve7({ exitCode: code ?? 1, stdout, stderr }));
6818
- child.on("error", (e) => resolve7({ exitCode: 1, stdout: "", stderr: e.message }));
6829
+ child.on("close", (code) => resolve6({ exitCode: code ?? 1, stdout, stderr }));
6830
+ child.on("error", (e) => resolve6({ exitCode: 1, stdout: "", stderr: e.message }));
6819
6831
  });
6820
6832
  }
6821
6833
  function extractPatchedFiles(output) {
@@ -7390,13 +7402,13 @@ async function globFiles(pattern, base, extraGlob) {
7390
7402
  return await globNative(pattern, base, extraGlob);
7391
7403
  }
7392
7404
  function checkRg() {
7393
- return new Promise((resolve7) => {
7405
+ return new Promise((resolve6) => {
7394
7406
  try {
7395
7407
  const p = spawn("rg", ["--version"], { env: buildChildEnv(), stdio: "ignore", windowsHide: true });
7396
- p.on("error", () => resolve7(false));
7397
- p.on("close", (code) => resolve7(code === 0));
7408
+ p.on("error", () => resolve6(false));
7409
+ p.on("close", (code) => resolve6(code === 0));
7398
7410
  } catch {
7399
- resolve7(false);
7411
+ resolve6(false);
7400
7412
  }
7401
7413
  });
7402
7414
  }
@@ -7413,10 +7425,10 @@ function spawnRgFind(pattern, base) {
7413
7425
  buf += chunk.toString();
7414
7426
  });
7415
7427
  return {
7416
- promise: new Promise((resolve7, reject) => {
7428
+ promise: new Promise((resolve6, reject) => {
7417
7429
  child.on("error", reject);
7418
7430
  child.on("close", () => {
7419
- resolve7(buf.split("\n").filter(Boolean));
7431
+ resolve6(buf.split("\n").filter(Boolean));
7420
7432
  });
7421
7433
  })
7422
7434
  };