@wrongstack/tools 0.267.0 → 0.269.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/batch-tool-use.ts"],"names":[],"mappings":";AAyBO,IAAM,gBAAA,GAAgE;AAAA,EAC3E,IAAA,EAAM,gBAAA;AAAA,EACN,QAAA,EAAU,MAAA;AAAA,EACV,WAAA,EACE,8GAAA;AAAA,EACF,SAAA,EACE,qWAAA;AAAA,EAKF,UAAA,EAAY,SAAA;AAAA,EACZ,QAAA,EAAU,IAAA;AAAA,EACV,SAAA,EAAW,IAAA;AAAA,EACX,YAAA,EAAc,CAAC,iBAAiB,CAAA;AAAA,EAChC,IAAA,EAAM,MAAA;AAAA,EACN,WAAA,EAAa;AAAA,IACX,IAAA,EAAM,QAAA;AAAA,IACN,UAAA,EAAY;AAAA,MACV,KAAA,EAAO;AAAA,QACL,IAAA,EAAM,OAAA;AAAA,QACN,KAAA,EAAO;AAAA,UACL,IAAA,EAAM,QAAA;AAAA,UACN,UAAA,EAAY;AAAA,YACV,IAAA,EAAM,EAAE,IAAA,EAAM,QAAA,EAAS;AAAA,YACvB,KAAA,EAAO,EAAE,IAAA,EAAM,QAAA;AAAS,WAC1B;AAAA,UACA,QAAA,EAAU,CAAC,MAAM;AAAA,SACnB;AAAA,QACA,WAAA,EAAa;AAAA,OACf;AAAA,MACA,aAAA,EAAe;AAAA,QACb,IAAA,EAAM,SAAA;AAAA,QACN,WAAA,EAAa;AAAA,OACf;AAAA,MACA,QAAA,EAAU;AAAA,QACR,IAAA,EAAM,SAAA;AAAA,QACN,WAAA,EAAa;AAAA;AACf,KACF;AAAA,IACA,QAAA,EAAU,CAAC,OAAO;AAAA,GACpB;AAAA,EACA,MAAM,OAAA,CAAQ,KAAA,EAAO,GAAA,EAAK,IAAA,EAAM;AAC9B,IAAA,IAAI,CAAC,KAAA,EAAO,KAAA,IAAS,KAAA,CAAM,KAAA,CAAM,WAAW,CAAA,EAAG;AAC7C,MAAA,OAAO;AAAA,QACL,SAAS,EAAC;AAAA,QACV,KAAA,EAAO,CAAA;AAAA,QACP,SAAA,EAAW,CAAA;AAAA,QACX,MAAA,EAAQ,CAAA;AAAA,QACR,aAAA,EAAe;AAAA,OACjB;AAAA,IACF;AAEA,IAAA,MAAM,UAAyC,EAAC;AAChD,IAAA,IAAI,SAAA,GAAY,CAAA;AAChB,IAAA,IAAI,MAAA,GAAS,CAAA;AAEb,IAAA,IAAI,KAAA,CAAM,aAAa,KAAA,EAAO;AAC5B,MAAA,MAAM,QAAA,GAAW,KAAA,CAAM,KAAA,CAAM,GAAA,CAAI,OAAO,SAAS,aAAA,CAAc,IAAA,EAAM,GAAA,EAAK,IAAI,CAAC,CAAA;AAC/E,MAAA,MAAM,UAAA,GAAa,MAAM,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA;AAC7C,MAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,UAAU,CAAA;AAC1B,MAAA,SAAA,GAAY,WAAW,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAA,CAAE,MAAA;AAChD,MAAA,MAAA,GAAS,WAAW,MAAA,CAAO,CAAC,MAAM,CAAC,CAAA,CAAE,OAAO,CAAA,CAAE,MAAA;AAAA,IAChD,CAAA,MAAO;AACL,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,KAAA,EAAO;AAC9B,QAAA,MAAM,MAAA,GAAS,MAAM,aAAA,CAAc,IAAA,EAAM,KAAK,IAAA,IAAQ,EAAE,MAAA,EAAQ,MAAA,EAAqC,CAAA;AACrG,QAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,QAAA,IAAI,OAAO,OAAA,EAAS;AAClB,UAAA,SAAA,EAAA;AAAA,QACF,CAAA,MAAO;AACL,UAAA,MAAA,EAAA;AACA,UAAA,IAAI,MAAM,aAAA,EAAe;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAO;AAAA,MACL,OAAA;AAAA,MACA,KAAA,EAAO,MAAM,KAAA,CAAM,MAAA;AAAA,MACnB,SAAA;AAAA,MACA,MAAA;AAAA,MACA,aAAA,EAAe,MAAM,aAAA,IAAiB;AAAA,KACxC;AAAA,EACF;AACF;AAEA,eAAe,aAAA,CACb,IAAA,EACA,GAAA,EACA,IAAA,EAC2C;AAC3C,EAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,EAAI;AACvB,EAAA,MAAM,IAAA,GAAO,IAAI,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAY,CAAA,CAAE,IAAA,KAAS,IAAA,CAAK,IAAI,CAAA;AAE7D,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,OAAA,EAAS,KAAA;AAAA,MACT,KAAA,EAAO,CAAA,MAAA,EAAS,IAAA,CAAK,IAAI,CAAA,WAAA,CAAA;AAAA,MACzB,WAAA,EAAa,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,KAC5B;AAAA,EACF;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,MAAM,IAAA,CAAK,QAAQ,IAAA,CAAK,KAAA,EAAO,KAAK,IAAI,CAAA;AACvD,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,OAAA,EAAS,IAAA;AAAA,MACT,MAAA;AAAA,MACA,WAAA,EAAa,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,KAC5B;AAAA,EACF,SAAS,CAAA,EAAG;AACV,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,OAAA,EAAS,KAAA;AAAA,MACT,OAAO,CAAA,YAAa,KAAA,GAAQ,CAAA,CAAE,OAAA,GAAU,OAAO,CAAC,CAAA;AAAA,MAChD,WAAA,EAAa,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,KAC5B;AAAA,EACF;AACF","file":"batch-tool-use.js","sourcesContent":["import type { Tool } from '@wrongstack/core';\n\ninterface BatchToolUseInput {\n calls: {\n tool: string;\n input: Record<string, unknown>;\n }[];\n stop_on_error?: boolean | undefined;\n parallel?: boolean | undefined;\n}\n\ninterface BatchToolUseOutput {\n results: {\n tool: string;\n success: boolean;\n result?: unknown | undefined;\n error?: string | undefined;\n executionMs: number;\n }[];\n total: number;\n succeeded: number;\n failed: number;\n stop_on_error: boolean;\n}\n\nexport const batchToolUseTool: Tool<BatchToolUseInput, BatchToolUseOutput> = {\n name: 'batch_tool_use',\n category: 'Meta',\n description:\n 'Execute a batch of tool calls either sequentially or in parallel. Returns structured results for every call.',\n usageHint:\n 'ADVANCED / POWER USER TOOL:\\n\\n' +\n '- Useful when you have a clear list of independent operations to perform.\\n' +\n '- `parallel: true` (default) runs them concurrently for speed.\\n' +\n '- `stop_on_error: true` makes it fail fast on the first error.\\n' +\n 'Use with care — batching many mutating operations can be risky. Prefer explicit sequential steps for important work.',\n permission: 'confirm',\n mutating: true,\n timeoutMs: 120_000,\n capabilities: ['tool.mutate.any'],\n icon: 'meta',\n inputSchema: {\n type: 'object',\n properties: {\n calls: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n tool: { type: 'string' },\n input: { type: 'object' },\n },\n required: ['tool'],\n },\n description: 'Array of tool calls to execute',\n },\n stop_on_error: {\n type: 'boolean',\n description: 'Stop execution on first error (default: false)',\n },\n parallel: {\n type: 'boolean',\n description: 'Execute calls in parallel (default: true)',\n },\n },\n required: ['calls'],\n },\n async execute(input, ctx, opts) {\n if (!input?.calls || input.calls.length === 0) {\n return {\n results: [],\n total: 0,\n succeeded: 0,\n failed: 0,\n stop_on_error: false,\n };\n }\n\n const results: BatchToolUseOutput['results'] = [];\n let succeeded = 0;\n let failed = 0;\n\n if (input.parallel !== false) {\n const promises = input.calls.map(async (call) => executeSingle(call, ctx, opts));\n const allResults = await Promise.all(promises);\n results.push(...allResults);\n succeeded = allResults.filter((r) => r.success).length;\n failed = allResults.filter((r) => !r.success).length;\n } else {\n for (const call of input.calls) {\n const result = await executeSingle(call, ctx, opts ?? { signal: undefined as unknown as AbortSignal });\n results.push(result);\n if (result.success) {\n succeeded++;\n } else {\n failed++;\n if (input.stop_on_error) break;\n }\n }\n }\n\n return {\n results,\n total: input.calls.length,\n succeeded,\n failed,\n stop_on_error: input.stop_on_error ?? false,\n };\n },\n};\n\nasync function executeSingle(\n call: { tool: string; input: Record<string, unknown> },\n ctx: import('@wrongstack/core').Context,\n opts: { signal: AbortSignal },\n): Promise<BatchToolUseOutput['results'][0]> {\n const start = Date.now();\n const tool = ctx.tools.find((t: Tool) => t.name === call.tool);\n\n if (!tool) {\n return {\n tool: call.tool,\n success: false,\n error: `tool \"${call.tool}\" not found`,\n executionMs: Date.now() - start,\n };\n }\n\n try {\n const result = await tool.execute(call.input, ctx, opts);\n return {\n tool: call.tool,\n success: true,\n result,\n executionMs: Date.now() - start,\n };\n } catch (e) {\n return {\n tool: call.tool,\n success: false,\n error: e instanceof Error ? e.message : String(e),\n executionMs: Date.now() - start,\n };\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/batch-tool-use.ts"],"names":[],"mappings":"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","file":"batch-tool-use.js","sourcesContent":["import type { Tool } from '@wrongstack/core';\n\ninterface BatchToolUseInput {\n calls: {\n tool: string;\n input: Record<string, unknown>;\n }[];\n stop_on_error?: boolean | undefined;\n parallel?: boolean | undefined;\n}\n\ninterface BatchToolUseOutput {\n results: {\n tool: string;\n success: boolean;\n result?: unknown | undefined;\n error?: string | undefined;\n executionMs: number;\n }[];\n total: number;\n succeeded: number;\n failed: number;\n stop_on_error: boolean;\n}\n\nexport const batchToolUseTool: Tool<BatchToolUseInput, BatchToolUseOutput> = {\n name: 'batch_tool_use',\n category: 'Meta',\n description:\n 'Execute a batch of tool calls either sequentially or in parallel. Returns structured results for every call.',\n usageHint:\n 'ADVANCED / POWER USER TOOL:\\n\\n' +\n '- Useful when you have a clear list of independent operations to perform.\\n' +\n '- `parallel: true` (default) runs them concurrently for speed.\\n' +\n '- `stop_on_error: true` makes it fail fast on the first error.\\n' +\n 'Use with care — batching many mutating operations can be risky. Prefer explicit sequential steps for important work.',\n permission: 'confirm',\n mutating: true,\n timeoutMs: 120_000,\n capabilities: ['tool.mutate.any'],\n icon: 'meta',\n inputSchema: {\n type: 'object',\n properties: {\n calls: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n tool: { type: 'string' },\n input: { type: 'object' },\n },\n required: ['tool'],\n },\n description: 'Array of tool calls to execute',\n },\n stop_on_error: {\n type: 'boolean',\n description: 'Stop execution on first error (default: false)',\n },\n parallel: {\n type: 'boolean',\n description: 'Execute calls in parallel (default: true)',\n },\n },\n required: ['calls'],\n },\n async execute(input, ctx, opts) {\n if (!input?.calls || input.calls.length === 0) {\n return {\n results: [],\n total: 0,\n succeeded: 0,\n failed: 0,\n stop_on_error: false,\n };\n }\n\n const results: BatchToolUseOutput['results'] = [];\n let succeeded = 0;\n let failed = 0;\n\n if (input.parallel !== false) {\n const promises = input.calls.map(async (call) => executeSingle(call, ctx, opts));\n const allResults = await Promise.all(promises);\n results.push(...allResults);\n succeeded = allResults.filter((r) => r.success).length;\n failed = allResults.filter((r) => !r.success).length;\n } else {\n for (const call of input.calls) {\n const result = await executeSingle(call, ctx, opts ?? { signal: undefined as never as AbortSignal });\n results.push(result);\n if (result.success) {\n succeeded++;\n } else {\n failed++;\n if (input.stop_on_error) break;\n }\n }\n }\n\n return {\n results,\n total: input.calls.length,\n succeeded,\n failed,\n stop_on_error: input.stop_on_error ?? false,\n };\n },\n};\n\nasync function executeSingle(\n call: { tool: string; input: Record<string, unknown> },\n ctx: import('@wrongstack/core').Context,\n opts: { signal: AbortSignal },\n): Promise<BatchToolUseOutput['results'][0]> {\n const start = Date.now();\n const tool = ctx.tools.find((t: Tool) => t.name === call.tool);\n\n if (!tool) {\n return {\n tool: call.tool,\n success: false,\n error: `tool \"${call.tool}\" not found`,\n executionMs: Date.now() - start,\n };\n }\n\n try {\n const result = await tool.execute(call.input, ctx, opts);\n return {\n tool: call.tool,\n success: true,\n result,\n executionMs: Date.now() - start,\n };\n } catch (e) {\n return {\n tool: call.tool,\n success: false,\n error: e instanceof Error ? e.message : String(e),\n executionMs: Date.now() - start,\n };\n }\n}\n"]}
package/dist/builtin.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 = () => {
@@ -1813,7 +1813,7 @@ var IndexStore = class {
1813
1813
  throw new LockError(`SQLite lock conflict after ${MAX_LOCK_RETRIES} retries: ${msg}`);
1814
1814
  }
1815
1815
  const delay = Math.min(
1816
- LOCK_RETRY_BASE_DELAY_MS * Math.pow(2, attempt),
1816
+ LOCK_RETRY_BASE_DELAY_MS * 2 ** attempt,
1817
1817
  LOCK_RETRY_MAX_DELAY_MS
1818
1818
  );
1819
1819
  sleepSync(delay);
@@ -2106,14 +2106,15 @@ var IndexStore = class {
2106
2106
  if (!query2.trim()) {
2107
2107
  return { results: candidates.slice(0, limit), total: candidates.length };
2108
2108
  }
2109
+ const candidateById = new Map(candidates.map((c) => [c.id, c]));
2109
2110
  const bm25 = buildBm25Index(
2110
2111
  candidates.map((c) => ({ id: c.id, text: buildIndexableText(c.name, c.signature, c.docComment) }))
2111
2112
  );
2112
- const scored = bm25.score(query2, (id) => candidates.some((c) => c.id === id));
2113
+ const scored = bm25.score(query2, (id) => candidateById.has(id));
2113
2114
  scored.sort((a, b) => b.score - a.score);
2114
2115
  const qTokens = tokenise(query2);
2115
2116
  const results = scored.slice(0, limit).map(({ id, score }) => {
2116
- const c = expectDefined(candidates.find((cand) => cand.id === id));
2117
+ const c = expectDefined(candidateById.get(id));
2117
2118
  return { ...c, score, snippet: bm25.extractSnippet(id, qTokens) };
2118
2119
  });
2119
2120
  return { results, total: candidates.length };
@@ -3530,8 +3531,9 @@ async function loadGitignoreMatcher(projectRoot) {
3530
3531
 
3531
3532
  // src/codebase-index/indexer.ts
3532
3533
  var YIELD_EVERY_N = 50;
3534
+ var PARALLEL_BATCH = 20;
3533
3535
  function yieldEventLoop() {
3534
- return new Promise((resolve7) => setImmediate(resolve7));
3536
+ return new Promise((resolve6) => setImmediate(resolve6));
3535
3537
  }
3536
3538
  function throwIfAborted(signal) {
3537
3539
  if (!signal?.aborted) return;
@@ -3663,97 +3665,111 @@ async function runIndexerWithStore(store, opts) {
3663
3665
  if (!force) {
3664
3666
  for (const meta of store.getAllFileMetas()) existingMeta.set(meta.file, meta);
3665
3667
  }
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) {
3668
+ for (let batchStart = 0; batchStart < files.length; batchStart += PARALLEL_BATCH) {
3669
+ const batchEnd = Math.min(batchStart + PARALLEL_BATCH, files.length);
3670
+ const batchFiles = files.slice(batchStart, batchEnd);
3671
+ opts.onProgress?.(batchEnd, files.length);
3672
+ if (batchStart > 0 && batchStart % YIELD_EVERY_N === 0) {
3670
3673
  await yieldEventLoop();
3671
3674
  throwIfAborted(signal);
3672
3675
  }
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);
3676
+ const statOpts = signal ? { signal } : {};
3677
+ const statReadParse = await Promise.allSettled(
3678
+ batchFiles.map(async (file) => {
3679
+ let stat11;
3680
+ try {
3681
+ stat11 = await fs14.stat(file, statOpts);
3682
+ } catch (e) {
3683
+ if (isAbortError(e)) throw e;
3684
+ return { file, stat: null, lang: "", parsed: null, error: `stat error: ${e instanceof Error ? e.message : String(e)}` };
3733
3685
  }
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
- }
3686
+ if (!stat11.isFile()) return { file, stat: stat11, lang: "", parsed: null };
3687
+ const lang = detectLang(file);
3688
+ if (!lang) return { file, stat: stat11, lang: "", parsed: null };
3689
+ const meta = existingMeta.get(file);
3690
+ if (!force && meta && meta.mtimeMs === Math.floor(stat11.mtimeMs)) {
3691
+ return { file, stat: stat11, lang, parsed: null, skippedMeta: meta };
3743
3692
  }
3693
+ let content;
3694
+ try {
3695
+ content = await fs14.readFile(file, { encoding: "utf8", signal });
3696
+ } catch (e) {
3697
+ if (isAbortError(e)) throw e;
3698
+ return { file, stat: stat11, lang, parsed: null, error: `read error: ${e instanceof Error ? e.message : String(e)}` };
3699
+ }
3700
+ let parsed;
3701
+ try {
3702
+ parsed = await parseFile(file, content, lang);
3703
+ } catch (e) {
3704
+ return { file, stat: stat11, lang, parsed: null, error: `parse error: ${e instanceof Error ? e.message : String(e)}` };
3705
+ }
3706
+ return { file, stat: stat11, lang, parsed, content };
3707
+ })
3708
+ );
3709
+ for (let fi = 0; fi < statReadParse.length; fi++) {
3710
+ const settled = statReadParse[fi];
3711
+ const file = expectDefined(batchFiles[fi]);
3712
+ if (settled.status === "rejected") {
3713
+ const err = settled.reason;
3714
+ if (err instanceof Error && isAbortError(err)) throw err;
3715
+ errors.push(`batch error: ${file}: ${err instanceof Error ? err.message : String(err)}`);
3716
+ continue;
3744
3717
  }
3745
- if (batch.length > 0) {
3746
- store.insertRefsBatch(batch);
3718
+ const result = settled.value;
3719
+ if (result.error) {
3720
+ if (result.stat) store.deleteFile(file);
3721
+ if (result.error.includes("error:")) errors.push(result.error);
3722
+ continue;
3747
3723
  }
3724
+ const { stat: stat11, lang, parsed } = result;
3725
+ if (result.skippedMeta) {
3726
+ langStats[lang] = (langStats[lang] ?? 0) + result.skippedMeta.symbolCount;
3727
+ symbolsIndexed += result.skippedMeta.symbolCount;
3728
+ filesIndexed++;
3729
+ continue;
3730
+ }
3731
+ if (!lang || !parsed) {
3732
+ if (lang) {
3733
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat11.mtimeMs), symbolCount: 0, lastIndexed: Date.now() });
3734
+ filesIndexed++;
3735
+ }
3736
+ continue;
3737
+ }
3738
+ store.deleteRefsForFile(file);
3739
+ store.deleteSymbolsForFile(file);
3740
+ if (parsed.symbols.length === 0) {
3741
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat11.mtimeMs), symbolCount: 0, lastIndexed: Date.now() });
3742
+ filesIndexed++;
3743
+ continue;
3744
+ }
3745
+ const nextId = store.getMaxSymbolId() + 1;
3746
+ const symbolsWithIds = parsed.symbols.map((s, i) => ({ ...s, id: nextId + i }));
3747
+ store.insertSymbols(symbolsWithIds, nextId);
3748
+ const count = symbolsWithIds.length;
3749
+ symbolsIndexed += count;
3750
+ langStats[lang] = (langStats[lang] ?? 0) + count;
3751
+ if (parsed.refs && parsed.refs.length > 0) {
3752
+ const refsByLine = /* @__PURE__ */ new Map();
3753
+ for (const r of parsed.refs) {
3754
+ let arr = refsByLine.get(r.line);
3755
+ if (!arr) {
3756
+ arr = [];
3757
+ refsByLine.set(r.line, arr);
3758
+ }
3759
+ arr.push(r);
3760
+ }
3761
+ const batch = [];
3762
+ for (const sym of symbolsWithIds) {
3763
+ const symRefs = refsByLine.get(sym.line);
3764
+ if (symRefs) {
3765
+ for (const r of symRefs) batch.push({ ...r, fromId: sym.id });
3766
+ }
3767
+ }
3768
+ if (batch.length > 0) store.insertRefsBatch(batch);
3769
+ }
3770
+ store.upsertFile({ file, lang, mtimeMs: Math.floor(stat11.mtimeMs), symbolCount: count, lastIndexed: Date.now() });
3771
+ filesIndexed++;
3748
3772
  }
3749
- store.upsertFile({
3750
- file,
3751
- lang,
3752
- mtimeMs: Math.floor(stat11.mtimeMs),
3753
- symbolCount: count,
3754
- lastIndexed: Date.now()
3755
- });
3756
- filesIndexed++;
3757
3773
  }
3758
3774
  for (const [file_] of existingMeta) {
3759
3775
  try {
@@ -3920,7 +3936,7 @@ function terminateWorker(reason) {
3920
3936
  function callIndexOp(op, args, opts) {
3921
3937
  const w = ensureWorker();
3922
3938
  if (!w) return callInline(op, args, opts);
3923
- return new Promise((resolve7, reject) => {
3939
+ return new Promise((resolve6, reject) => {
3924
3940
  const id = nextRpcId++;
3925
3941
  const timer = setTimeout(() => {
3926
3942
  pending.delete(id);
@@ -3943,7 +3959,7 @@ function callIndexOp(op, args, opts) {
3943
3959
  pending.set(id, {
3944
3960
  resolve: (v) => {
3945
3961
  cleanup();
3946
- resolve7(v);
3962
+ resolve6(v);
3947
3963
  },
3948
3964
  reject: (e) => {
3949
3965
  cleanup();
@@ -4369,7 +4385,7 @@ function findGitDir(cwd) {
4369
4385
  return null;
4370
4386
  }
4371
4387
  function runGit(args, cwd, signal) {
4372
- return new Promise((resolve7) => {
4388
+ return new Promise((resolve6) => {
4373
4389
  let stdout = "";
4374
4390
  let stderr = "";
4375
4391
  const child = spawn("git", args, {
@@ -4385,8 +4401,8 @@ function runGit(args, cwd, signal) {
4385
4401
  child.stderr?.on("data", (c) => {
4386
4402
  stderr += c.toString();
4387
4403
  });
4388
- child.on("close", (code) => resolve7({ stdout, stderr, exitCode: code ?? 0 }));
4389
- child.on("error", (e) => resolve7({ stdout: "", stderr: e.message, exitCode: 1 }));
4404
+ child.on("close", (code) => resolve6({ stdout, stderr, exitCode: code ?? 0 }));
4405
+ child.on("error", (e) => resolve6({ stdout: "", stderr: e.message, exitCode: 1 }));
4390
4406
  });
4391
4407
  }
4392
4408
  async function fileDiff(input, ctx, _signal) {
@@ -4877,26 +4893,26 @@ var execTool = {
4877
4893
  allowed: false
4878
4894
  };
4879
4895
  }
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)) {
4896
+ let cwd;
4897
+ try {
4898
+ cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : await safeResolveReal(ctx.cwd, ctx);
4899
+ } catch {
4883
4900
  return {
4884
4901
  command: cmd,
4885
4902
  args,
4886
4903
  stdout: "",
4887
- stderr: `cwd "${input.cwd}" resolves outside project root`,
4904
+ stderr: `cwd "${input.cwd ?? ctx.cwd}" resolves outside project root`,
4888
4905
  exitCode: 1,
4889
4906
  truncated: false,
4890
4907
  allowed: false
4891
4908
  };
4892
4909
  }
4893
- const cwd = requestedCwd;
4894
4910
  const signal = opts.signal;
4895
4911
  return runCommand(cmd, args, cwd, timeout, signal, ctx.session?.id);
4896
4912
  }
4897
4913
  };
4898
4914
  function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
4899
- return new Promise((resolve7) => {
4915
+ return new Promise((resolve6) => {
4900
4916
  let stdout = "";
4901
4917
  let stderr = "";
4902
4918
  let killed = false;
@@ -4951,7 +4967,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
4951
4967
  const exitCode = killed ? 124 : code ?? 1;
4952
4968
  registry.afterCall(durationMs, exitCode !== 0);
4953
4969
  const spooled = spool.finalize();
4954
- resolve7({
4970
+ resolve6({
4955
4971
  command: cmd,
4956
4972
  args,
4957
4973
  stdout: normalizeCommandOutput(stdout) + (spooled ? spoolNote(spooled) : ""),
@@ -4967,7 +4983,7 @@ function runCommand(cmd, args, cwd, timeout, signal, sessionId) {
4967
4983
  if (typeof pid === "number") registry.unregister(pid);
4968
4984
  registry.afterCall(Date.now() - startedAt, true);
4969
4985
  spool.finalize();
4970
- resolve7({
4986
+ resolve6({
4971
4987
  command: cmd,
4972
4988
  args,
4973
4989
  stdout: normalizeCommandOutput(stdout),
@@ -5571,7 +5587,7 @@ function buildArgs(input) {
5571
5587
  }
5572
5588
  }
5573
5589
  function runGit2(args, cwd, signal) {
5574
- return new Promise((resolve7) => {
5590
+ return new Promise((resolve6) => {
5575
5591
  let stdout = "";
5576
5592
  let stderr = "";
5577
5593
  const child = spawn("git", args, {
@@ -5592,7 +5608,7 @@ function runGit2(args, cwd, signal) {
5592
5608
  }
5593
5609
  });
5594
5610
  child.on("error", (err) => {
5595
- resolve7({
5611
+ resolve6({
5596
5612
  command: args[0],
5597
5613
  stdout: normalizeCommandOutput(stdout),
5598
5614
  stderr: err.message,
@@ -5601,7 +5617,7 @@ function runGit2(args, cwd, signal) {
5601
5617
  });
5602
5618
  });
5603
5619
  child.on("close", (code) => {
5604
- resolve7({
5620
+ resolve6({
5605
5621
  command: args[0],
5606
5622
  stdout: normalizeCommandOutput(stdout),
5607
5623
  stderr: normalizeCommandOutput(stderr),
@@ -5824,13 +5840,13 @@ var grepTool = {
5824
5840
  }
5825
5841
  };
5826
5842
  async function detectRg(signal) {
5827
- return new Promise((resolve7) => {
5843
+ return new Promise((resolve6) => {
5828
5844
  try {
5829
5845
  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));
5846
+ p.on("error", () => resolve6(false));
5847
+ p.on("close", (code) => resolve6(code === 0));
5832
5848
  } catch {
5833
- resolve7(false);
5849
+ resolve6(false);
5834
5850
  }
5835
5851
  });
5836
5852
  }
@@ -6245,8 +6261,8 @@ var jsonTool = {
6245
6261
  };
6246
6262
  }
6247
6263
  };
6248
- function query(data, path21) {
6249
- const parts = path21.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
6264
+ function query(data, path20) {
6265
+ const parts = path20.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean);
6250
6266
  let current = data;
6251
6267
  for (const part of parts) {
6252
6268
  if (current === null || current === void 0) return void 0;
@@ -6472,7 +6488,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
6472
6488
  };
6473
6489
  }
6474
6490
  args.push("--timestamps", service);
6475
- return new Promise((resolve7) => {
6491
+ return new Promise((resolve6) => {
6476
6492
  let stdout = "";
6477
6493
  let stderr = "";
6478
6494
  const MAX = 2e5;
@@ -6488,7 +6504,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
6488
6504
  if (settled) return;
6489
6505
  settled = true;
6490
6506
  clearTimeout(timer);
6491
- resolve7(result);
6507
+ resolve6(result);
6492
6508
  };
6493
6509
  const child = spawn("docker", args, { cwd, signal, env: buildChildEnv(), stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
6494
6510
  const timer = setTimeout(() => {
@@ -6523,7 +6539,7 @@ async function dockerLogs(service, lines, filterRe, cwd, signal, since) {
6523
6539
  }
6524
6540
  var DOCKER_LOGS_TIMEOUT_MS = 3e3;
6525
6541
  var MAX_TAIL_LINES = 1e5;
6526
- async function fileLogs(path21, lines, filterRe, stream) {
6542
+ async function fileLogs(path20, lines, filterRe, stream) {
6527
6543
  const { createInterface } = await import('node:readline');
6528
6544
  const { createReadStream } = await import('node:fs');
6529
6545
  const entries = [];
@@ -6532,7 +6548,7 @@ async function fileLogs(path21, lines, filterRe, stream) {
6532
6548
  let writeIdx = 0;
6533
6549
  let totalLines = 0;
6534
6550
  const rl = createInterface({
6535
- input: createReadStream(path21),
6551
+ input: createReadStream(path20),
6536
6552
  crlfDelay: Number.POSITIVE_INFINITY
6537
6553
  });
6538
6554
  for await (const line of rl) {
@@ -6553,7 +6569,7 @@ async function fileLogs(path21, lines, filterRe, stream) {
6553
6569
  if (parsed) entries.push(parsed);
6554
6570
  }
6555
6571
  return {
6556
- source: path21,
6572
+ source: path20,
6557
6573
  entries,
6558
6574
  total: entries.length,
6559
6575
  truncated: totalLines > effLines,
@@ -6650,7 +6666,7 @@ var outdatedTool = {
6650
6666
  }
6651
6667
  };
6652
6668
  function runOutdated(manager, args, cwd, signal) {
6653
- return new Promise((resolve7) => {
6669
+ return new Promise((resolve6) => {
6654
6670
  let stdout = "";
6655
6671
  let stderr = "";
6656
6672
  const MAX = 1e5;
@@ -6666,10 +6682,10 @@ function runOutdated(manager, args, cwd, signal) {
6666
6682
  });
6667
6683
  child.on("close", (code) => {
6668
6684
  const result = parseOutdatedOutput(stdout, code ?? 0);
6669
- resolve7(result);
6685
+ resolve6(result);
6670
6686
  });
6671
6687
  child.on("error", (e) => {
6672
- resolve7({
6688
+ resolve6({
6673
6689
  exit_code: 1,
6674
6690
  packages: [],
6675
6691
  total: 0,
@@ -6803,7 +6819,7 @@ function stripPathComponents(p, strip) {
6803
6819
  return parts.slice(strip).join("/");
6804
6820
  }
6805
6821
  function runPatch(args, cwd, signal) {
6806
- return new Promise((resolve7) => {
6822
+ return new Promise((resolve6) => {
6807
6823
  let stdout = "";
6808
6824
  let stderr = "";
6809
6825
  const env = { ...buildChildEnv(), LANG: "C", LC_ALL: "C" };
@@ -6814,8 +6830,8 @@ function runPatch(args, cwd, signal) {
6814
6830
  child.stderr?.on("data", (c) => {
6815
6831
  stderr += c.toString();
6816
6832
  });
6817
- child.on("close", (code) => resolve7({ exitCode: code ?? 1, stdout, stderr }));
6818
- child.on("error", (e) => resolve7({ exitCode: 1, stdout: "", stderr: e.message }));
6833
+ child.on("close", (code) => resolve6({ exitCode: code ?? 1, stdout, stderr }));
6834
+ child.on("error", (e) => resolve6({ exitCode: 1, stdout: "", stderr: e.message }));
6819
6835
  });
6820
6836
  }
6821
6837
  function extractPatchedFiles(output) {
@@ -7390,13 +7406,13 @@ async function globFiles(pattern, base, extraGlob) {
7390
7406
  return await globNative(pattern, base, extraGlob);
7391
7407
  }
7392
7408
  function checkRg() {
7393
- return new Promise((resolve7) => {
7409
+ return new Promise((resolve6) => {
7394
7410
  try {
7395
7411
  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));
7412
+ p.on("error", () => resolve6(false));
7413
+ p.on("close", (code) => resolve6(code === 0));
7398
7414
  } catch {
7399
- resolve7(false);
7415
+ resolve6(false);
7400
7416
  }
7401
7417
  });
7402
7418
  }
@@ -7413,10 +7429,10 @@ function spawnRgFind(pattern, base) {
7413
7429
  buf += chunk.toString();
7414
7430
  });
7415
7431
  return {
7416
- promise: new Promise((resolve7, reject) => {
7432
+ promise: new Promise((resolve6, reject) => {
7417
7433
  child.on("error", reject);
7418
7434
  child.on("close", () => {
7419
- resolve7(buf.split("\n").filter(Boolean));
7435
+ resolve6(buf.split("\n").filter(Boolean));
7420
7436
  });
7421
7437
  })
7422
7438
  };