@wrongstack/tools 0.303.0 → 0.305.1

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.
@@ -6,6 +6,12 @@ interface CodebaseIndexInput {
6
6
  }
7
7
  interface CodebaseIndexOutput {
8
8
  filesIndexed: number;
9
+ fileOutcomes?: {
10
+ parsed: number;
11
+ skipped: number;
12
+ empty: number;
13
+ failed: number;
14
+ } | undefined;
9
15
  symbolsIndexed: number;
10
16
  langStats: Record<string, number>;
11
17
  durationMs: number;
@@ -31,6 +31,7 @@ export { internalKindToLspKind, lspKindToInternalKind, } from './lsp-kind.js';
31
31
  export type { ProjectIndexServerClientHealth, ProjectIndexServerConnectionState, ProjectIndexServerConnectionStatus, } from './project-server-client.js';
32
32
  export type { ProjectIndexServerActivity, ProjectIndexServerHealth, } from './project-server-protocol.js';
33
33
  export type { CallSite, CodeMapGraph, FileMeta, FileSymbols, GraphEdge, GraphNode, IndexResult, IndexStats, SearchResult, Symbol, SymbolKind, SymbolLang, } from './schema.js';
34
+ export { projectIndexServerEndpoint, projectIndexServerMetadataPath, } from './project-server-endpoint.js';
34
35
  export { SCHEMA_VERSION } from './schema.js';
35
36
  export { codebaseIndexDirOverride, IndexStore, resolveIndexDir } from './writer.js';
36
37
  //# sourceMappingURL=index.d.ts.map
@@ -2815,7 +2815,6 @@ import * as fs4 from "node:fs";
2815
2815
  import * as os from "node:os";
2816
2816
  import * as path5 from "node:path";
2817
2817
  import { fileURLToPath } from "node:url";
2818
- import { assertUnixSocketPathWithinLimit } from "@wrongstack/core/utils";
2819
2818
 
2820
2819
  // src/codebase-index/writer.ts
2821
2820
  import { expectDefined } from "@wrongstack/core/utils";
@@ -4665,7 +4664,7 @@ var IndexStore = class _IndexStore {
4665
4664
  const ftsSchema = this.stmt(
4666
4665
  "SELECT sql FROM sqlite_master WHERE type='table' AND name='symbols_fts'"
4667
4666
  ).get();
4668
- if (ftsSchema?.sql && ftsSchema.sql.includes("unicode61")) {
4667
+ if (ftsSchema?.sql?.includes("unicode61")) {
4669
4668
  this.db.exec("DROP TABLE IF EXISTS symbols_fts");
4670
4669
  }
4671
4670
  this.db.exec(SYMBOLS_FTS_SQL);
@@ -5158,9 +5157,13 @@ var IndexStore = class _IndexStore {
5158
5157
  sim: cosineSimilarity(queryVec, decodeVector(r.vector))
5159
5158
  })).sort((a, b) => b.sim - a.sim);
5160
5159
  const bm25Rank = /* @__PURE__ */ new Map();
5161
- bm25Rows.forEach((r, i) => bm25Rank.set(r.id, i));
5160
+ bm25Rows.forEach((r, i) => {
5161
+ bm25Rank.set(r.id, i);
5162
+ });
5162
5163
  const vecRank = /* @__PURE__ */ new Map();
5163
- vecScores.forEach((r, i) => vecRank.set(r.id, i));
5164
+ vecScores.forEach((r, i) => {
5165
+ vecRank.set(r.id, i);
5166
+ });
5164
5167
  const fused = reciprocalRankFusion(bm25Rank, vecRank, 60);
5165
5168
  const fusedScore = new Map(fused);
5166
5169
  const sorted = [...bm25Rows].sort(
@@ -6563,6 +6566,86 @@ import {
6563
6566
  isFrugalPerf
6564
6567
  } from "@wrongstack/core/utils";
6565
6568
 
6569
+ // src/codebase-index/content-hash.ts
6570
+ var PRIME64_1 = 0x9e3779b185ebca87n;
6571
+ var PRIME64_2 = 0xc2b2ae3d27d4eb4fn;
6572
+ var PRIME64_3 = 0x165667b19e3779f9n;
6573
+ var PRIME64_4 = 0x85ebca77c2b2ae63n;
6574
+ var PRIME64_5 = 0x27d4eb2f165667c5n;
6575
+ var MASK64 = 0xffffffffffffffffn;
6576
+ function mul64(a, b) {
6577
+ return (a & MASK64) * (b & MASK64) & MASK64;
6578
+ }
6579
+ function rotl64(x, n) {
6580
+ const v = x & MASK64;
6581
+ return (v << BigInt(n) | v >> BigInt(64 - n)) & MASK64;
6582
+ }
6583
+ function readU64LE(buf, off) {
6584
+ let v = 0n;
6585
+ for (let i = 7; i >= 0; i--) {
6586
+ v = v << 8n | BigInt(buf[off + i] ?? 0);
6587
+ }
6588
+ return v & MASK64;
6589
+ }
6590
+ function readU32LE(buf, off) {
6591
+ return (BigInt(buf[off] ?? 0) | BigInt(buf[off + 1] ?? 0) << 8n | BigInt(buf[off + 2] ?? 0) << 16n | BigInt(buf[off + 3] ?? 0) << 24n) & MASK64;
6592
+ }
6593
+ function xxh64Round(acc, lane) {
6594
+ return mul64(rotl64(acc + mul64(lane, PRIME64_2) & MASK64, 31), PRIME64_1);
6595
+ }
6596
+ function xxh64MergeRound(acc, val) {
6597
+ return mul64(acc ^ xxh64Round(0n, val), PRIME64_1) + PRIME64_4 & MASK64;
6598
+ }
6599
+ function xxhash64Hex(buf, explicitLen) {
6600
+ const length = explicitLen ?? buf.length;
6601
+ let h;
6602
+ let off = 0;
6603
+ if (length >= 32) {
6604
+ let v1 = PRIME64_1 + PRIME64_2 & MASK64;
6605
+ let v2 = PRIME64_2;
6606
+ let v3 = 0n;
6607
+ let v4 = 0n - PRIME64_1 & MASK64;
6608
+ const end32 = length - 32;
6609
+ while (off <= end32) {
6610
+ v1 = xxh64Round(v1, readU64LE(buf, off));
6611
+ v2 = xxh64Round(v2, readU64LE(buf, off + 8));
6612
+ v3 = xxh64Round(v3, readU64LE(buf, off + 16));
6613
+ v4 = xxh64Round(v4, readU64LE(buf, off + 24));
6614
+ off += 32;
6615
+ }
6616
+ h = rotl64(v1, 1) + rotl64(v2, 7) + rotl64(v3, 12) + rotl64(v4, 18) & MASK64;
6617
+ h = xxh64MergeRound(h, v1);
6618
+ h = xxh64MergeRound(h, v2);
6619
+ h = xxh64MergeRound(h, v3);
6620
+ h = xxh64MergeRound(h, v4);
6621
+ } else {
6622
+ h = PRIME64_5;
6623
+ }
6624
+ h = h + BigInt(length) & MASK64;
6625
+ while (off + 8 <= length) {
6626
+ const k1 = xxh64Round(0n, readU64LE(buf, off));
6627
+ h = mul64(rotl64(h ^ k1, 27), PRIME64_1) + PRIME64_4 & MASK64;
6628
+ off += 8;
6629
+ }
6630
+ if (off + 4 <= length) {
6631
+ h = mul64(rotl64(h ^ mul64(readU32LE(buf, off), PRIME64_1), 23), PRIME64_2) + PRIME64_3 & MASK64;
6632
+ off += 4;
6633
+ }
6634
+ while (off < length) {
6635
+ h = mul64(rotl64(h ^ mul64(BigInt(buf[off] ?? 0), PRIME64_5), 11), PRIME64_1) & MASK64;
6636
+ off += 1;
6637
+ }
6638
+ h = (h ^ h >> 33n) & MASK64;
6639
+ h = mul64(h, PRIME64_2);
6640
+ h = (h ^ h >> 29n) & MASK64;
6641
+ h = mul64(h, PRIME64_3);
6642
+ h = (h ^ h >> 32n) & MASK64;
6643
+ return h.toString(16).padStart(16, "0");
6644
+ }
6645
+ function xxhash64String(content) {
6646
+ return xxhash64Hex(new TextEncoder().encode(content));
6647
+ }
6648
+
6566
6649
  // src/codebase-index/gitignore.ts
6567
6650
  import * as fs6 from "node:fs/promises";
6568
6651
  import * as path6 from "node:path";
@@ -7290,91 +7373,14 @@ function getParserPool() {
7290
7373
  return _pool;
7291
7374
  }
7292
7375
 
7293
- // src/codebase-index/content-hash.ts
7294
- var PRIME64_1 = 0x9e3779b185ebca87n;
7295
- var PRIME64_2 = 0xc2b2ae3d27d4eb4fn;
7296
- var PRIME64_3 = 0x165667b19e3779f9n;
7297
- var PRIME64_4 = 0x85ebca77c2b2ae63n;
7298
- var PRIME64_5 = 0x27d4eb2f165667c5n;
7299
- var MASK64 = 0xffffffffffffffffn;
7300
- function mul64(a, b) {
7301
- return (a & MASK64) * (b & MASK64) & MASK64;
7302
- }
7303
- function rotl64(x, n) {
7304
- const v = x & MASK64;
7305
- return (v << BigInt(n) | v >> BigInt(64 - n)) & MASK64;
7306
- }
7307
- function readU64LE(buf, off) {
7308
- let v = 0n;
7309
- for (let i = 7; i >= 0; i--) {
7310
- v = v << 8n | BigInt(buf[off + i] ?? 0);
7311
- }
7312
- return v & MASK64;
7313
- }
7314
- function readU32LE(buf, off) {
7315
- return (BigInt(buf[off] ?? 0) | BigInt(buf[off + 1] ?? 0) << 8n | BigInt(buf[off + 2] ?? 0) << 16n | BigInt(buf[off + 3] ?? 0) << 24n) & MASK64;
7316
- }
7317
- function xxh64Round(acc, lane) {
7318
- return mul64(rotl64(acc + mul64(lane, PRIME64_2) & MASK64, 31), PRIME64_1);
7319
- }
7320
- function xxh64MergeRound(acc, val) {
7321
- return mul64(acc ^ xxh64Round(0n, val), PRIME64_1) + PRIME64_4 & MASK64;
7322
- }
7323
- function xxhash64Hex(buf, explicitLen) {
7324
- const length = explicitLen ?? buf.length;
7325
- let h;
7326
- let off = 0;
7327
- if (length >= 32) {
7328
- let v1 = PRIME64_1 + PRIME64_2 & MASK64;
7329
- let v2 = PRIME64_2;
7330
- let v3 = 0n;
7331
- let v4 = 0n - PRIME64_1 & MASK64;
7332
- const end32 = length - 32;
7333
- while (off <= end32) {
7334
- v1 = xxh64Round(v1, readU64LE(buf, off));
7335
- v2 = xxh64Round(v2, readU64LE(buf, off + 8));
7336
- v3 = xxh64Round(v3, readU64LE(buf, off + 16));
7337
- v4 = xxh64Round(v4, readU64LE(buf, off + 24));
7338
- off += 32;
7339
- }
7340
- h = rotl64(v1, 1) + rotl64(v2, 7) + rotl64(v3, 12) + rotl64(v4, 18) & MASK64;
7341
- h = xxh64MergeRound(h, v1);
7342
- h = xxh64MergeRound(h, v2);
7343
- h = xxh64MergeRound(h, v3);
7344
- h = xxh64MergeRound(h, v4);
7345
- } else {
7346
- h = PRIME64_5;
7347
- }
7348
- h = h + BigInt(length) & MASK64;
7349
- while (off + 8 <= length) {
7350
- const k1 = xxh64Round(0n, readU64LE(buf, off));
7351
- h = mul64(rotl64(h ^ k1, 27), PRIME64_1) + PRIME64_4 & MASK64;
7352
- off += 8;
7353
- }
7354
- if (off + 4 <= length) {
7355
- h = mul64(rotl64(h ^ mul64(readU32LE(buf, off), PRIME64_1), 23), PRIME64_2) + PRIME64_3 & MASK64;
7356
- off += 4;
7357
- }
7358
- while (off < length) {
7359
- h = mul64(rotl64(h ^ mul64(BigInt(buf[off] ?? 0), PRIME64_5), 11), PRIME64_1) & MASK64;
7360
- off += 1;
7361
- }
7362
- h = (h ^ h >> 33n) & MASK64;
7363
- h = mul64(h, PRIME64_2);
7364
- h = (h ^ h >> 29n) & MASK64;
7365
- h = mul64(h, PRIME64_3);
7366
- h = (h ^ h >> 32n) & MASK64;
7367
- return h.toString(16).padStart(16, "0");
7368
- }
7369
- function xxhash64String(content) {
7370
- return xxhash64Hex(new TextEncoder().encode(content));
7371
- }
7372
-
7373
7376
  // src/codebase-index/indexer.ts
7374
7377
  var YIELD_EVERY_N = 50;
7375
7378
  function resolveParallelBatch() {
7376
7379
  return indexParallelBatchSize(availableParallelism());
7377
7380
  }
7381
+ function shouldUseParserWorkerPool(candidateFileCount, parseBatchCount) {
7382
+ return !isFrugalPerf() && candidateFileCount >= WORKER_POOL_THRESHOLD && parseBatchCount > 1;
7383
+ }
7378
7384
  function yieldEventLoop() {
7379
7385
  return new Promise((resolve4) => setImmediate(resolve4));
7380
7386
  }
@@ -7551,11 +7557,7 @@ async function resolveProjectRelations(store, projectRoot, opts) {
7551
7557
  const structure = await detectModuleRoots(projectRoot, indexedFiles);
7552
7558
  if (opts.signal?.aborted) return;
7553
7559
  store.setFilePackages(assignPackageLabels(structure, indexedFiles));
7554
- const resolver = new ModuleResolver(
7555
- structure,
7556
- indexedFiles,
7557
- store.getNamespaceDeclarations()
7558
- );
7560
+ const resolver = new ModuleResolver(structure, indexedFiles, store.getNamespaceDeclarations());
7559
7561
  const pending2 = store.getUnresolvedImports(opts.onlyFiles);
7560
7562
  const resolutions = [];
7561
7563
  for (const entry of pending2) {
@@ -7591,6 +7593,10 @@ async function runIndexerWithStore(store, opts) {
7591
7593
  const errors = [];
7592
7594
  const langStats = {};
7593
7595
  let filesIndexed = 0;
7596
+ let filesParsed = 0;
7597
+ let filesSkipped = 0;
7598
+ let filesEmpty = 0;
7599
+ let filesFailed = 0;
7594
7600
  let symbolsIndexed = 0;
7595
7601
  const isGitIgnored = await loadGitignoreMatcher(projectRoot);
7596
7602
  let files;
@@ -7632,12 +7638,14 @@ async function runIndexerWithStore(store, opts) {
7632
7638
  langStats[meta.lang] = (langStats[meta.lang] ?? 0) + meta.symbolCount;
7633
7639
  symbolsIndexed += meta.symbolCount;
7634
7640
  filesIndexed++;
7641
+ filesSkipped++;
7635
7642
  filesPreSkipped++;
7636
7643
  return false;
7637
7644
  });
7638
7645
  if (filesPreSkipped > 0) opts.onProgress?.(filesPreSkipped, totalFilesForProgress);
7639
7646
  }
7640
7647
  const parallelBatch = resolveParallelBatch();
7648
+ const parserPoolCandidateCount = files.length;
7641
7649
  let filesSinceLastYield = 0;
7642
7650
  for (let batchStart = 0; batchStart < files.length; batchStart += parallelBatch) {
7643
7651
  const batchEnd = Math.min(batchStart + parallelBatch, files.length);
@@ -7730,7 +7738,7 @@ async function runIndexerWithStore(store, opts) {
7730
7738
  });
7731
7739
  }
7732
7740
  if (toParse.length > 0) {
7733
- let pool = toParse.length >= WORKER_POOL_THRESHOLD ? getParserPool() : null;
7741
+ let pool = shouldUseParserWorkerPool(parserPoolCandidateCount, toParse.length) ? getParserPool() : null;
7734
7742
  if (pool) {
7735
7743
  try {
7736
7744
  await pool.ensureReady();
@@ -7780,12 +7788,14 @@ async function runIndexerWithStore(store, opts) {
7780
7788
  const err = settled.reason;
7781
7789
  if (err instanceof Error && isAbortError(err)) throw err;
7782
7790
  errors.push(`batch error: ${file}: ${err instanceof Error ? err.message : String(err)}`);
7791
+ filesFailed++;
7783
7792
  continue;
7784
7793
  }
7785
7794
  const result = settled.value;
7786
7795
  if (result.error) {
7787
7796
  if (result.missing) store.deleteFile(file);
7788
7797
  errors.push(`${file}: ${result.error}`);
7798
+ filesFailed++;
7789
7799
  continue;
7790
7800
  }
7791
7801
  const { stat: stat2, lang, parsed } = result;
@@ -7793,6 +7803,7 @@ async function runIndexerWithStore(store, opts) {
7793
7803
  langStats[lang] = (langStats[lang] ?? 0) + result.skippedMeta.symbolCount;
7794
7804
  symbolsIndexed += result.skippedMeta.symbolCount;
7795
7805
  filesIndexed++;
7806
+ filesSkipped++;
7796
7807
  const stored = existingMeta.get(file);
7797
7808
  if (stored && stored.mtimeMs !== result.skippedMeta.mtimeMs) {
7798
7809
  store.upsertFile({
@@ -7817,6 +7828,7 @@ async function runIndexerWithStore(store, opts) {
7817
7828
  contentHash: result.contentHash ?? ""
7818
7829
  });
7819
7830
  filesIndexed++;
7831
+ filesEmpty++;
7820
7832
  }
7821
7833
  continue;
7822
7834
  }
@@ -7830,6 +7842,7 @@ async function runIndexerWithStore(store, opts) {
7830
7842
  contentHash: result.contentHash ?? ""
7831
7843
  });
7832
7844
  filesIndexed++;
7845
+ filesEmpty++;
7833
7846
  continue;
7834
7847
  }
7835
7848
  batchEntries.push({
@@ -7851,6 +7864,7 @@ async function runIndexerWithStore(store, opts) {
7851
7864
  symbolsIndexed += count;
7852
7865
  langStats[entry.lang] = (langStats[entry.lang] ?? 0) + count;
7853
7866
  filesIndexed++;
7867
+ filesParsed++;
7854
7868
  }
7855
7869
  } catch (err) {
7856
7870
  const message = err instanceof Error ? err.message : String(err);
@@ -7863,6 +7877,7 @@ async function runIndexerWithStore(store, opts) {
7863
7877
  symbolsIndexed += symbolsWithIds.length;
7864
7878
  langStats[entry.lang] = (langStats[entry.lang] ?? 0) + symbolsWithIds.length;
7865
7879
  filesIndexed++;
7880
+ filesParsed++;
7866
7881
  if (entry.refs.length > 0 && symbolsWithIds.length > 0) {
7867
7882
  const fallbackBatch = assignRefsToSymbols2(entry.refs, symbolsWithIds);
7868
7883
  if (fallbackBatch.length > 0) store.insertRefsBatch(fallbackBatch);
@@ -7880,6 +7895,7 @@ async function runIndexerWithStore(store, opts) {
7880
7895
  contentHash: entry.contentHash
7881
7896
  });
7882
7897
  } catch (innerErr) {
7898
+ filesFailed++;
7883
7899
  errors.push(
7884
7900
  `fallback write failed: ${entry.file}: ${innerErr instanceof Error ? innerErr.message : String(innerErr)}`
7885
7901
  );
@@ -7912,6 +7928,12 @@ async function runIndexerWithStore(store, opts) {
7912
7928
  const durationMs = Date.now() - startMs;
7913
7929
  return {
7914
7930
  filesIndexed,
7931
+ fileOutcomes: {
7932
+ parsed: filesParsed,
7933
+ skipped: filesSkipped,
7934
+ empty: filesEmpty,
7935
+ failed: filesFailed
7936
+ },
7915
7937
  symbolsIndexed,
7916
7938
  langStats,
7917
7939
  durationMs,
@@ -9466,6 +9488,8 @@ export {
9466
9488
  onIndexStateChange,
9467
9489
  outgoingCallsService2 as outgoingCallsService,
9468
9490
  packageGraphService2 as packageGraphService,
9491
+ projectIndexServerEndpoint,
9492
+ projectIndexServerMetadataPath,
9469
9493
  resetIndexCircuitBreaker,
9470
9494
  resolveIndexDir,
9471
9495
  resolveProjectIndexDaemonAvailability,
@@ -6,6 +6,12 @@ import { IndexStore } from './writer.js';
6
6
  * Re-resolved at the start of each index run so env profile changes apply.
7
7
  */
8
8
  export declare function resolveParallelBatch(): number;
9
+ /**
10
+ * Pool startup is amortized across the complete index run, not one outer
11
+ * batch. Balanced batches are capped at 40 files, so comparing the per-batch
12
+ * parse count with the 500-file threshold made the worker path unreachable.
13
+ */
14
+ export declare function shouldUseParserWorkerPool(candidateFileCount: number, parseBatchCount: number): boolean;
9
15
  interface IndexerOptions {
10
16
  projectRoot: string;
11
17
  files?: string[] | undefined;
@@ -3,7 +3,7 @@ export declare const PROJECT_INDEX_SERVER_METADATA_FILE = "server.json";
3
3
  /**
4
4
  * Short directory name that owns the per-project Unix socket on Linux.
5
5
  *
6
- * The directory is created `0o700` by `ensureProjectIndexSocketDirectory`: on
6
+ * The directory is created `0o700` by `bindProjectEndpoint`: on
7
7
  * multi-user Linux `/tmp` the kernel's sticky bit otherwise lets a local
8
8
  * attacker pre-bind a predictable socket name (project paths are guessable
9
9
  * via the public `buildId` handshake), hijacking clients whose `bind()` hits
@@ -48,5 +48,4 @@ export declare function projectIndexServerKey(projectRoot: string, indexDir?: st
48
48
  */
49
49
  export declare function projectIndexServerEndpoint(projectRoot: string, indexDir?: string): string;
50
50
  export declare function projectIndexServerMetadataPath(projectRoot: string, indexDir?: string): string;
51
- export declare function ensureProjectIndexSocketDirectory(endpoint: string): void;
52
51
  //# sourceMappingURL=project-server-endpoint.d.ts.map