@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/index.js CHANGED
@@ -711,13 +711,13 @@ async function globFiles(pattern, base, extraGlob) {
711
711
  return await globNative(pattern, base, extraGlob);
712
712
  }
713
713
  function checkRg() {
714
- return new Promise((resolve7) => {
714
+ return new Promise((resolve6) => {
715
715
  try {
716
716
  const p = spawn("rg", ["--version"], { env: buildChildEnv(), stdio: "ignore", windowsHide: true });
717
- p.on("error", () => resolve7(false));
718
- p.on("close", (code) => resolve7(code === 0));
717
+ p.on("error", () => resolve6(false));
718
+ p.on("close", (code) => resolve6(code === 0));
719
719
  } catch {
720
- resolve7(false);
720
+ resolve6(false);
721
721
  }
722
722
  });
723
723
  }
@@ -734,10 +734,10 @@ function spawnRgFind(pattern, base) {
734
734
  buf += chunk.toString();
735
735
  });
736
736
  return {
737
- promise: new Promise((resolve7, reject) => {
737
+ promise: new Promise((resolve6, reject) => {
738
738
  child.on("error", reject);
739
739
  child.on("close", () => {
740
- resolve7(buf.split("\n").filter(Boolean));
740
+ resolve6(buf.split("\n").filter(Boolean));
741
741
  });
742
742
  })
743
743
  };
@@ -943,13 +943,13 @@ var grepTool = {
943
943
  }
944
944
  };
945
945
  async function detectRg(signal) {
946
- return new Promise((resolve7) => {
946
+ return new Promise((resolve6) => {
947
947
  try {
948
948
  const p = spawn("rg", ["--version"], { env: buildChildEnv(), stdio: "ignore", signal, windowsHide: true });
949
- p.on("error", () => resolve7(false));
950
- p.on("close", (code) => resolve7(code === 0));
949
+ p.on("error", () => resolve6(false));
950
+ p.on("close", (code) => resolve6(code === 0));
951
951
  } catch {
952
- resolve7(false);
952
+ resolve6(false);
953
953
  }
954
954
  });
955
955
  }
@@ -2024,10 +2024,10 @@ var bashTool = {
2024
2024
  queue.push(c);
2025
2025
  }
2026
2026
  };
2027
- const next = () => new Promise((resolve7) => {
2027
+ const next = () => new Promise((resolve6) => {
2028
2028
  const c = queue.shift();
2029
- if (c) resolve7(c);
2030
- else resolveNext = resolve7;
2029
+ if (c) resolve6(c);
2030
+ else resolveNext = resolve6;
2031
2031
  });
2032
2032
  let lastFlush = Date.now();
2033
2033
  const flush = () => {
@@ -2323,26 +2323,26 @@ var execTool = {
2323
2323
  allowed: false
2324
2324
  };
2325
2325
  }
2326
- const requestedCwd = input.cwd ? path.resolve(ctx.projectRoot, input.cwd) : ctx.cwd;
2327
- const rel = path.relative(ctx.projectRoot, requestedCwd);
2328
- if (rel.startsWith("..") || path.isAbsolute(rel)) {
2326
+ let cwd;
2327
+ try {
2328
+ cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : await safeResolveReal(ctx.cwd, ctx);
2329
+ } catch {
2329
2330
  return {
2330
2331
  command: cmd,
2331
2332
  args,
2332
2333
  stdout: "",
2333
- stderr: `cwd "${input.cwd}" resolves outside project root`,
2334
+ stderr: `cwd "${input.cwd ?? ctx.cwd}" resolves outside project root`,
2334
2335
  exitCode: 1,
2335
2336
  truncated: false,
2336
2337
  allowed: false
2337
2338
  };
2338
2339
  }
2339
- const cwd = requestedCwd;
2340
2340
  const signal = opts.signal;
2341
2341
  return runCommand(cmd, args, cwd, timeout, signal, ctx.session?.id);
2342
2342
  }
2343
2343
  };
2344
2344
  function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
2345
- return new Promise((resolve7) => {
2345
+ return new Promise((resolve6) => {
2346
2346
  let stdout = "";
2347
2347
  let stderr = "";
2348
2348
  let killed = false;
@@ -2397,7 +2397,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
2397
2397
  const exitCode = killed ? 124 : code ?? 1;
2398
2398
  registry.afterCall(durationMs, exitCode !== 0);
2399
2399
  const spooled = spool.finalize();
2400
- resolve7({
2400
+ resolve6({
2401
2401
  command: cmd,
2402
2402
  args,
2403
2403
  stdout: normalizeCommandOutput(stdout) + (spooled ? spoolNote(spooled) : ""),
@@ -2413,7 +2413,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
2413
2413
  if (typeof pid === "number") registry.unregister(pid);
2414
2414
  registry.afterCall(Date.now() - startedAt, true);
2415
2415
  spool.finalize();
2416
- resolve7({
2416
+ resolve6({
2417
2417
  command: cmd,
2418
2418
  args,
2419
2419
  stdout: normalizeCommandOutput(stdout),
@@ -3499,7 +3499,7 @@ function buildArgs(input) {
3499
3499
  }
3500
3500
  }
3501
3501
  function runGit(args, cwd, signal) {
3502
- return new Promise((resolve7) => {
3502
+ return new Promise((resolve6) => {
3503
3503
  let stdout = "";
3504
3504
  let stderr = "";
3505
3505
  const child = spawn("git", args, {
@@ -3520,7 +3520,7 @@ function runGit(args, cwd, signal) {
3520
3520
  }
3521
3521
  });
3522
3522
  child.on("error", (err) => {
3523
- resolve7({
3523
+ resolve6({
3524
3524
  command: args[0],
3525
3525
  stdout: normalizeCommandOutput(stdout),
3526
3526
  stderr: err.message,
@@ -3529,7 +3529,7 @@ function runGit(args, cwd, signal) {
3529
3529
  });
3530
3530
  });
3531
3531
  child.on("close", (code) => {
3532
- resolve7({
3532
+ resolve6({
3533
3533
  command: args[0],
3534
3534
  stdout: normalizeCommandOutput(stdout),
3535
3535
  stderr: normalizeCommandOutput(stderr),
@@ -3629,7 +3629,7 @@ function stripPathComponents(p, strip) {
3629
3629
  return parts.slice(strip).join("/");
3630
3630
  }
3631
3631
  function runPatch(args, cwd, signal) {
3632
- return new Promise((resolve7) => {
3632
+ return new Promise((resolve6) => {
3633
3633
  let stdout = "";
3634
3634
  let stderr = "";
3635
3635
  const env = { ...buildChildEnv(), LANG: "C", LC_ALL: "C" };
@@ -3640,8 +3640,8 @@ function runPatch(args, cwd, signal) {
3640
3640
  child.stderr?.on("data", (c) => {
3641
3641
  stderr += c.toString();
3642
3642
  });
3643
- child.on("close", (code) => resolve7({ exitCode: code ?? 1, stdout, stderr }));
3644
- child.on("error", (e) => resolve7({ exitCode: 1, stdout: "", stderr: e.message }));
3643
+ child.on("close", (code) => resolve6({ exitCode: code ?? 1, stdout, stderr }));
3644
+ child.on("error", (e) => resolve6({ exitCode: 1, stdout: "", stderr: e.message }));
3645
3645
  });
3646
3646
  }
3647
3647
  function extractPatchedFiles(output) {
@@ -3727,8 +3727,8 @@ var jsonTool = {
3727
3727
  };
3728
3728
  }
3729
3729
  };
3730
- function query(data, path21) {
3731
- const parts = path21.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
3730
+ function query(data, path20) {
3731
+ const parts = path20.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
3732
3732
  let current = data;
3733
3733
  for (const part of parts) {
3734
3734
  if (current === null || current === void 0) return void 0;
@@ -3869,7 +3869,7 @@ function findGitDir2(cwd) {
3869
3869
  return null;
3870
3870
  }
3871
3871
  function runGit2(args, cwd, signal) {
3872
- return new Promise((resolve7) => {
3872
+ return new Promise((resolve6) => {
3873
3873
  let stdout = "";
3874
3874
  let stderr = "";
3875
3875
  const child = spawn("git", args, {
@@ -3885,8 +3885,8 @@ function runGit2(args, cwd, signal) {
3885
3885
  child.stderr?.on("data", (c) => {
3886
3886
  stderr += c.toString();
3887
3887
  });
3888
- child.on("close", (code) => resolve7({ stdout, stderr, exitCode: code ?? 0 }));
3889
- child.on("error", (e) => resolve7({ stdout: "", stderr: e.message, exitCode: 1 }));
3888
+ child.on("close", (code) => resolve6({ stdout, stderr, exitCode: code ?? 0 }));
3889
+ child.on("error", (e) => resolve6({ stdout: "", stderr: e.message, exitCode: 1 }));
3890
3890
  });
3891
3891
  }
3892
3892
  async function fileDiff(input, ctx, _signal) {
@@ -4204,8 +4204,8 @@ async function* spawnStream(opts) {
4204
4204
  try {
4205
4205
  for (; ; ) {
4206
4206
  while (queue.length === 0) {
4207
- await new Promise((resolve7) => {
4208
- waiter = resolve7;
4207
+ await new Promise((resolve6) => {
4208
+ waiter = resolve6;
4209
4209
  });
4210
4210
  }
4211
4211
  const chunk = queue.shift();
@@ -4997,7 +4997,7 @@ var outdatedTool = {
4997
4997
  }
4998
4998
  };
4999
4999
  function runOutdated(manager, args, cwd, signal) {
5000
- return new Promise((resolve7) => {
5000
+ return new Promise((resolve6) => {
5001
5001
  let stdout = "";
5002
5002
  let stderr = "";
5003
5003
  const MAX = 1e5;
@@ -5013,10 +5013,10 @@ function runOutdated(manager, args, cwd, signal) {
5013
5013
  });
5014
5014
  child.on("close", (code) => {
5015
5015
  const result = parseOutdatedOutput(stdout, code ?? 0);
5016
- resolve7(result);
5016
+ resolve6(result);
5017
5017
  });
5018
5018
  child.on("error", (e) => {
5019
- resolve7({
5019
+ resolve6({
5020
5020
  exit_code: 1,
5021
5021
  packages: [],
5022
5022
  total: 0,
@@ -5142,7 +5142,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
5142
5142
  };
5143
5143
  }
5144
5144
  args.push("--timestamps", service);
5145
- return new Promise((resolve7) => {
5145
+ return new Promise((resolve6) => {
5146
5146
  let stdout = "";
5147
5147
  let stderr = "";
5148
5148
  const MAX = 2e5;
@@ -5158,7 +5158,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
5158
5158
  if (settled) return;
5159
5159
  settled = true;
5160
5160
  clearTimeout(timer);
5161
- resolve7(result);
5161
+ resolve6(result);
5162
5162
  };
5163
5163
  const child = spawn("docker", args, { cwd, signal, env: buildChildEnv(), stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
5164
5164
  const timer = setTimeout(() => {
@@ -5193,7 +5193,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
5193
5193
  }
5194
5194
  var DOCKER_LOGS_TIMEOUT_MS = 3e3;
5195
5195
  var MAX_TAIL_LINES = 1e5;
5196
- async function fileLogs(path21, lines, filterRe, stream) {
5196
+ async function fileLogs(path20, lines, filterRe, stream) {
5197
5197
  const { createInterface } = await import('node:readline');
5198
5198
  const { createReadStream } = await import('node:fs');
5199
5199
  const entries = [];
@@ -5202,7 +5202,7 @@ async function fileLogs(path21, lines, filterRe, stream) {
5202
5202
  let writeIdx = 0;
5203
5203
  let totalLines = 0;
5204
5204
  const rl = createInterface({
5205
- input: createReadStream(path21),
5205
+ input: createReadStream(path20),
5206
5206
  crlfDelay: Number.POSITIVE_INFINITY
5207
5207
  });
5208
5208
  for await (const line of rl) {
@@ -5223,7 +5223,7 @@ async function fileLogs(path21, lines, filterRe, stream) {
5223
5223
  if (parsed) entries.push(parsed);
5224
5224
  }
5225
5225
  return {
5226
- source: path21,
5226
+ source: path20,
5227
5227
  entries,
5228
5228
  total: entries.length,
5229
5229
  truncated: totalLines > effLines,
@@ -8251,8 +8251,9 @@ async function loadGitignoreMatcher(projectRoot) {
8251
8251
 
8252
8252
  // src/codebase-index/indexer.ts
8253
8253
  var YIELD_EVERY_N = 50;
8254
+ var PARALLEL_BATCH = 20;
8254
8255
  function yieldEventLoop() {
8255
- return new Promise((resolve7) => setImmediate(resolve7));
8256
+ return new Promise((resolve6) => setImmediate(resolve6));
8256
8257
  }
8257
8258
  function throwIfAborted(signal) {
8258
8259
  if (!signal?.aborted) return;
@@ -8384,97 +8385,108 @@ async function runIndexerWithStore(store, opts) {
8384
8385
  if (!force) {
8385
8386
  for (const meta of store.getAllFileMetas()) existingMeta.set(meta.file, meta);
8386
8387
  }
8387
- for (let fi = 0; fi < files.length; fi++) {
8388
- const file = expectDefined(files[fi]);
8389
- opts.onProgress?.(fi + 1, files.length);
8390
- if (fi > 0 && fi % YIELD_EVERY_N === 0) {
8388
+ for (let batchStart = 0; batchStart < files.length; batchStart += PARALLEL_BATCH) {
8389
+ const batchEnd = Math.min(batchStart + PARALLEL_BATCH, files.length);
8390
+ const batchFiles = files.slice(batchStart, batchEnd);
8391
+ opts.onProgress?.(batchEnd, files.length);
8392
+ if (batchStart > 0 && batchStart % YIELD_EVERY_N === 0) {
8391
8393
  await yieldEventLoop();
8392
8394
  throwIfAborted(signal);
8393
8395
  }
8394
- let stat11;
8395
- try {
8396
- const statOpts = signal ? { signal } : {};
8397
- stat11 = await fs4.stat(file, statOpts);
8398
- } catch (e) {
8399
- if (isAbortError(e)) throw e;
8400
- store.deleteFile(file);
8401
- continue;
8402
- }
8403
- if (!stat11.isFile()) continue;
8404
- const lang = detectLang(file);
8405
- if (!lang) continue;
8406
- const meta = existingMeta.get(file);
8407
- if (!force && meta && meta.mtimeMs === Math.floor(stat11.mtimeMs)) {
8408
- langStats[lang] = (langStats[lang] ?? 0) + meta.symbolCount;
8409
- symbolsIndexed += meta.symbolCount;
8410
- filesIndexed++;
8411
- continue;
8412
- }
8413
- store.deleteRefsForFile(file);
8414
- store.deleteSymbolsForFile(file);
8415
- let content;
8416
- try {
8417
- content = await fs4.readFile(file, { encoding: "utf8", signal });
8418
- } catch (e) {
8419
- if (isAbortError(e)) throw e;
8420
- errors.push(`read error: ${file}: ${e instanceof Error ? e.message : String(e)}`);
8421
- continue;
8422
- }
8423
- let parsed;
8424
- try {
8425
- parsed = await parseFile(file, content, lang);
8426
- } catch (e) {
8427
- errors.push(`parse error: ${file}: ${e instanceof Error ? e.message : String(e)}`);
8428
- continue;
8429
- }
8430
- if (parsed.symbols.length === 0) {
8431
- store.upsertFile({
8432
- file,
8433
- lang,
8434
- mtimeMs: Math.floor(stat11.mtimeMs),
8435
- symbolCount: 0,
8436
- lastIndexed: Date.now()
8437
- });
8438
- filesIndexed++;
8439
- continue;
8440
- }
8441
- const nextId = store.getMaxSymbolId() + 1;
8442
- const symbolsWithIds = parsed.symbols.map((s, i) => ({ ...s, id: nextId + i }));
8443
- store.insertSymbols(symbolsWithIds, nextId);
8444
- const count = symbolsWithIds.length;
8445
- symbolsIndexed += count;
8446
- langStats[lang] = (langStats[lang] ?? 0) + count;
8447
- if (parsed.refs && parsed.refs.length > 0) {
8448
- const refsByLine = /* @__PURE__ */ new Map();
8449
- for (const r of parsed.refs) {
8450
- let arr = refsByLine.get(r.line);
8451
- if (!arr) {
8452
- arr = [];
8453
- refsByLine.set(r.line, arr);
8396
+ const statOpts = signal ? { signal } : {};
8397
+ const statReadParse = await Promise.allSettled(
8398
+ batchFiles.map(async (file) => {
8399
+ let stat11;
8400
+ try {
8401
+ stat11 = await fs4.stat(file, statOpts);
8402
+ } catch (e) {
8403
+ if (isAbortError(e)) throw e;
8404
+ return { file, stat: null, lang: "", parsed: null, error: `stat error: ${e instanceof Error ? e.message : String(e)}` };
8454
8405
  }
8455
- arr.push(r);
8456
- }
8457
- const batch = [];
8458
- for (const sym of symbolsWithIds) {
8459
- const symRefs = refsByLine.get(sym.line);
8460
- if (symRefs) {
8461
- for (const r of symRefs) {
8462
- batch.push({ ...r, fromId: sym.id });
8463
- }
8406
+ if (!stat11.isFile()) return { file, stat: stat11, lang: "", parsed: null };
8407
+ const lang = detectLang(file);
8408
+ if (!lang) return { file, stat: stat11, lang: "", parsed: null };
8409
+ let content;
8410
+ try {
8411
+ content = await fs4.readFile(file, { encoding: "utf8", signal });
8412
+ } catch (e) {
8413
+ if (isAbortError(e)) throw e;
8414
+ return { file, stat: stat11, lang, parsed: null, error: `read error: ${e instanceof Error ? e.message : String(e)}` };
8464
8415
  }
8416
+ let parsed;
8417
+ try {
8418
+ parsed = await parseFile(file, content, lang);
8419
+ } catch (e) {
8420
+ return { file, stat: stat11, lang, parsed: null, error: `parse error: ${e instanceof Error ? e.message : String(e)}` };
8421
+ }
8422
+ return { file, stat: stat11, lang, parsed, content };
8423
+ })
8424
+ );
8425
+ for (let fi = 0; fi < statReadParse.length; fi++) {
8426
+ const settled = statReadParse[fi];
8427
+ const file = expectDefined(batchFiles[fi]);
8428
+ if (settled.status === "rejected") {
8429
+ const err = settled.reason;
8430
+ if (err instanceof Error && isAbortError(err)) throw err;
8431
+ errors.push(`batch error: ${file}: ${err instanceof Error ? err.message : String(err)}`);
8432
+ continue;
8433
+ }
8434
+ const result = settled.value;
8435
+ if (result.error) {
8436
+ if (result.stat) store.deleteFile(file);
8437
+ if (result.error.includes("error:")) errors.push(result.error);
8438
+ continue;
8465
8439
  }
8466
- if (batch.length > 0) {
8467
- store.insertRefsBatch(batch);
8440
+ const { stat: stat11, lang, parsed } = result;
8441
+ if (!lang || !parsed) {
8442
+ if (lang) {
8443
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat11.mtimeMs), symbolCount: 0, lastIndexed: Date.now() });
8444
+ filesIndexed++;
8445
+ }
8446
+ continue;
8468
8447
  }
8448
+ const meta = existingMeta.get(file);
8449
+ if (!force && meta && meta.mtimeMs === Math.floor(stat11.mtimeMs)) {
8450
+ langStats[lang] = (langStats[lang] ?? 0) + meta.symbolCount;
8451
+ symbolsIndexed += meta.symbolCount;
8452
+ filesIndexed++;
8453
+ continue;
8454
+ }
8455
+ store.deleteRefsForFile(file);
8456
+ store.deleteSymbolsForFile(file);
8457
+ if (parsed.symbols.length === 0) {
8458
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat11.mtimeMs), symbolCount: 0, lastIndexed: Date.now() });
8459
+ filesIndexed++;
8460
+ continue;
8461
+ }
8462
+ const nextId = store.getMaxSymbolId() + 1;
8463
+ const symbolsWithIds = parsed.symbols.map((s, i) => ({ ...s, id: nextId + i }));
8464
+ store.insertSymbols(symbolsWithIds, nextId);
8465
+ const count = symbolsWithIds.length;
8466
+ symbolsIndexed += count;
8467
+ langStats[lang] = (langStats[lang] ?? 0) + count;
8468
+ if (parsed.refs && parsed.refs.length > 0) {
8469
+ const refsByLine = /* @__PURE__ */ new Map();
8470
+ for (const r of parsed.refs) {
8471
+ let arr = refsByLine.get(r.line);
8472
+ if (!arr) {
8473
+ arr = [];
8474
+ refsByLine.set(r.line, arr);
8475
+ }
8476
+ arr.push(r);
8477
+ }
8478
+ const batch = [];
8479
+ for (const sym of symbolsWithIds) {
8480
+ const symRefs = refsByLine.get(sym.line);
8481
+ if (symRefs) {
8482
+ for (const r of symRefs) batch.push({ ...r, fromId: sym.id });
8483
+ }
8484
+ }
8485
+ if (batch.length > 0) store.insertRefsBatch(batch);
8486
+ }
8487
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat11.mtimeMs), symbolCount: count, lastIndexed: Date.now() });
8488
+ filesIndexed++;
8469
8489
  }
8470
- store.upsertFile({
8471
- file,
8472
- lang,
8473
- mtimeMs: Math.floor(stat11.mtimeMs),
8474
- symbolCount: count,
8475
- lastIndexed: Date.now()
8476
- });
8477
- filesIndexed++;
8478
8490
  }
8479
8491
  for (const [file_] of existingMeta) {
8480
8492
  try {
@@ -8656,7 +8668,7 @@ function shutdownCodebaseIndexHost() {
8656
8668
  function callIndexOp(op, args, opts) {
8657
8669
  const w = ensureWorker();
8658
8670
  if (!w) return callInline(op, args, opts);
8659
- return new Promise((resolve7, reject) => {
8671
+ return new Promise((resolve6, reject) => {
8660
8672
  const id = nextRpcId++;
8661
8673
  const timer = setTimeout(() => {
8662
8674
  pending.delete(id);
@@ -8679,7 +8691,7 @@ function callIndexOp(op, args, opts) {
8679
8691
  pending.set(id, {
8680
8692
  resolve: (v) => {
8681
8693
  cleanup();
8682
- resolve7(v);
8694
+ resolve6(v);
8683
8695
  },
8684
8696
  reject: (e) => {
8685
8697
  cleanup();