@wrongstack/tools 0.307.0 → 0.307.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.
@@ -54,7 +54,7 @@ export type WriterSymbolGraphRow = {
54
54
  signature: string;
55
55
  scope: string;
56
56
  };
57
- export declare function buildSymbolGraphNodes(symById: Map<number, WriterSymbolGraphRow>, relatedIds: Set<number>, fileFilter: string, packageOf: (file: string) => string): GraphNode[];
57
+ export declare function buildSymbolGraphNodes(symById: Map<number, WriterSymbolGraphRow>, relatedIds: Set<number>, localFiles: ReadonlySet<string> | string, packageOf: (file: string) => string): GraphNode[];
58
58
  export type WeightedEdgeAccumulator = {
59
59
  weight: number;
60
60
  types: Map<string, number>;
@@ -1,5 +1,17 @@
1
1
  import type { Ref, Symbol as IndexSymbol } from './schema.js';
2
2
  export declare function escapeLike(value: string): string;
3
+ /** Normalize an indexed or user-supplied file path for comparison. */
4
+ export declare function posixIndexPath(file: string): string;
5
+ /**
6
+ * SQL predicate that matches a stored `file` column against a user-supplied
7
+ * path. Agents pass project-relative paths (`src/calc.ts`); the index stores
8
+ * absolute OS paths. Exact, slash-normalized, and suffix matches are accepted.
9
+ */
10
+ export declare function indexedFileMatchSql(column?: string): string;
11
+ /** Bind values for {@link indexedFileMatchSql}: exact, posix, suffix-LIKE. */
12
+ export declare function indexedFileMatchArgs(file: string): [string, string, string];
13
+ /** True when a stored file path belongs to a package name or path fragment. */
14
+ export declare function matchesIndexedPackageFilter(storedFile: string, packageLabel: string, filter: string): boolean;
3
15
  export declare function assignRefsToSymbols(refs: Ref[], symbols: IndexSymbol[]): Ref[];
4
16
  /**
5
17
  * Resolve the per-project index directory. By default it lives under the
package/dist/edit.js CHANGED
@@ -4755,10 +4755,16 @@ function buildFileGraphNodeState(pkgSyms, localFiles, packageOf) {
4755
4755
  }
4756
4756
  return { fileNodes, symToFile, fileStats, ensureFileNode };
4757
4757
  }
4758
- function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
4758
+ function buildSymbolGraphNodes(symById, relatedIds, localFiles, packageOf) {
4759
+ const local = new Set(
4760
+ [...typeof localFiles === "string" ? [localFiles] : localFiles].map(
4761
+ (file) => file.replace(/\\/g, "/")
4762
+ )
4763
+ );
4764
+ const isLocal = (file) => local.has(file.replace(/\\/g, "/"));
4759
4765
  return [...relatedIds].map((id) => symById.get(id)).filter((symbol) => symbol !== void 0).sort((a, b) => {
4760
- const aExternal = a.file === fileFilter ? 0 : 1;
4761
- const bExternal = b.file === fileFilter ? 0 : 1;
4766
+ const aExternal = isLocal(a.file) ? 0 : 1;
4767
+ const bExternal = isLocal(b.file) ? 0 : 1;
4762
4768
  return aExternal - bExternal || a.file.localeCompare(b.file) || a.line - b.line || a.id - b.id;
4763
4769
  }).map((s) => ({
4764
4770
  id: `sym:${s.id}`,
@@ -4772,7 +4778,7 @@ function buildSymbolGraphNodes(symById, relatedIds, fileFilter, packageOf) {
4772
4778
  line: s.line,
4773
4779
  signature: s.signature,
4774
4780
  scope: s.scope,
4775
- external: s.file !== fileFilter
4781
+ external: !isLocal(s.file)
4776
4782
  }));
4777
4783
  }
4778
4784
  function addWeightedEdge(edgeMap, source, target, callType, weight) {
@@ -4807,6 +4813,52 @@ function materializeWeightedEdges(edgeMap, idPrefix) {
4807
4813
  return edges;
4808
4814
  }
4809
4815
 
4816
+ // src/codebase-index/writer-helpers.ts
4817
+ import { resolveWstackPaths } from "@wrongstack/core/utils";
4818
+ function escapeLike(value) {
4819
+ return value.replace(/[\\%_]/g, (char) => `\\${char}`);
4820
+ }
4821
+ function posixIndexPath(file) {
4822
+ return file.replace(/\\/g, "/").replace(/^\.\//, "");
4823
+ }
4824
+ function indexedFileMatchSql(column = "file") {
4825
+ return `(${column} = ? OR replace(${column}, '\\', '/') = ? OR replace(${column}, '\\', '/') LIKE ? ESCAPE '\\')`;
4826
+ }
4827
+ function indexedFileMatchArgs(file) {
4828
+ const posix4 = posixIndexPath(file.trim());
4829
+ return [file, posix4, `%/${escapeLike(posix4)}`];
4830
+ }
4831
+ function matchesIndexedPackageFilter(storedFile, packageLabel, filter) {
4832
+ if (packageLabel === filter) return true;
4833
+ const posixFile = posixIndexPath(storedFile);
4834
+ const posixFilter = posixIndexPath(filter.trim());
4835
+ if (!posixFilter) return false;
4836
+ return posixFile === posixFilter || posixFile.endsWith(`/${posixFilter}`) || posixFile.includes(`/${posixFilter}/`);
4837
+ }
4838
+ function assignRefsToSymbols(refs, symbols) {
4839
+ if (refs.length === 0 || symbols.length === 0) return [];
4840
+ const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
4841
+ const seen = /* @__PURE__ */ new Set();
4842
+ const assigned = [];
4843
+ for (const ref of refs) {
4844
+ let owner;
4845
+ for (const symbol of ordered) {
4846
+ if (symbol.line > ref.line) break;
4847
+ owner = symbol;
4848
+ }
4849
+ if (!owner && ref.callType === "import") owner = ordered[0];
4850
+ if (!owner || owner.id <= 0) continue;
4851
+ const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
4852
+ if (seen.has(key)) continue;
4853
+ seen.add(key);
4854
+ assigned.push({ ...ref, fromId: owner.id });
4855
+ }
4856
+ return assigned;
4857
+ }
4858
+ function resolveIndexDir(projectRoot, override) {
4859
+ return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
4860
+ }
4861
+
4810
4862
  // src/codebase-index/writer-ref-mapper.ts
4811
4863
  function mapWriterRefRow(row) {
4812
4864
  return {
@@ -4862,10 +4914,23 @@ function mapCallSiteRow(row) {
4862
4914
  line: row.ref_line
4863
4915
  };
4864
4916
  }
4917
+ function resolveIndexedFiles(stmt, file) {
4918
+ const rows = stmt(
4919
+ `SELECT DISTINCT file FROM symbols WHERE ${indexedFileMatchSql("file")} ORDER BY length(file), file`
4920
+ ).all(...indexedFileMatchArgs(file));
4921
+ return rows.map((row) => row.file);
4922
+ }
4865
4923
  function resolveSymbolIds(stmt, symbolName, file) {
4866
- const baseSql = file ? `SELECT id FROM symbols WHERE name = ? AND file = ? ORDER BY id` : `SELECT id FROM symbols WHERE name = ? ORDER BY id`;
4867
- const args = file ? [symbolName, file] : [symbolName];
4868
- const rows = stmt(baseSql).all(...args);
4924
+ if (!file) {
4925
+ const rows2 = stmt("SELECT id FROM symbols WHERE name = ? ORDER BY id").all(symbolName);
4926
+ return rows2.map((r) => r.id);
4927
+ }
4928
+ const indexedFiles = resolveIndexedFiles(stmt, file);
4929
+ if (indexedFiles.length === 0) return [];
4930
+ const placeholders = indexedFiles.map(() => "?").join(",");
4931
+ const rows = stmt(
4932
+ `SELECT id FROM symbols WHERE name = ? AND file IN (${placeholders}) ORDER BY id`
4933
+ ).all(symbolName, ...indexedFiles);
4869
4934
  return rows.map((r) => r.id);
4870
4935
  }
4871
4936
  function findIncomingCallsByName(stmt, symbolName, file, limit) {
@@ -5187,7 +5252,7 @@ function getFileGraphWithStatement(stmt, packageFilter) {
5187
5252
  const allFiles = stmt("SELECT DISTINCT file FROM symbols").all();
5188
5253
  const packageOf = readPackageLabeller(stmt);
5189
5254
  const langOf = (file) => detectLang(file) ?? "other";
5190
- const pkgFilePaths = allFiles.filter((f) => packageOf(f.file) === packageFilter).map((f) => f.file);
5255
+ const pkgFilePaths = allFiles.filter((f) => matchesIndexedPackageFilter(f.file, packageOf(f.file), packageFilter)).map((f) => f.file);
5191
5256
  const localFiles = new Set(pkgFilePaths);
5192
5257
  if (localFiles.size === 0) return { nodes: [], edges: [] };
5193
5258
  const filePlaceholders = [...localFiles].map(() => "?").join(",");
@@ -5263,9 +5328,12 @@ function getFileGraphWithStatement(stmt, packageFilter) {
5263
5328
  return { nodes: [...fileNodes.values()], edges };
5264
5329
  }
5265
5330
  function getSymbolGraphWithStatement(stmt, fileFilter) {
5331
+ const indexedFiles = resolveIndexedFiles(stmt, fileFilter);
5332
+ if (indexedFiles.length === 0) return { nodes: [], edges: [] };
5333
+ const filePlaceholders = indexedFiles.map(() => "?").join(",");
5266
5334
  const syms = stmt(
5267
- "SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file = ? ORDER BY line, id"
5268
- ).all(fileFilter);
5335
+ `SELECT id, name, kind, lang, file, line, signature, scope FROM symbols WHERE file IN (${filePlaceholders}) ORDER BY line, id`
5336
+ ).all(...indexedFiles);
5269
5337
  if (syms.length === 0) return { nodes: [], edges: [] };
5270
5338
  const symById = new Map(syms.map((symbol) => [symbol.id, symbol]));
5271
5339
  const relatedIds = new Set(syms.map((symbol) => symbol.id));
@@ -5275,16 +5343,16 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
5275
5343
  SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
5276
5344
  FROM refs r
5277
5345
  JOIN symbols s ON s.id = r.from_id
5278
- WHERE s.file = ?
5346
+ WHERE s.file IN (${filePlaceholders})
5279
5347
  UNION
5280
5348
  SELECT r.from_id, r.to_id, r.to_name, r.call_type, r.line
5281
5349
  FROM refs r
5282
5350
  JOIN symbols s ON s.id = r.to_id
5283
- WHERE s.file = ?
5351
+ WHERE s.file IN (${filePlaceholders})
5284
5352
  )
5285
5353
  WHERE to_id IS NOT NULL
5286
5354
  GROUP BY from_id, to_id, call_type`
5287
- ).all(fileFilter, fileFilter);
5355
+ ).all(...indexedFiles, ...indexedFiles);
5288
5356
  const edgeMap = /* @__PURE__ */ new Map();
5289
5357
  for (const r of refRows) {
5290
5358
  if (r.to_id == null) continue;
@@ -5303,39 +5371,15 @@ function getSymbolGraphWithStatement(stmt, fileFilter) {
5303
5371
  ).all(...missingIds);
5304
5372
  for (const s of extras) symById.set(s.id, s);
5305
5373
  }
5306
- const nodes = buildSymbolGraphNodes(symById, relatedIds, fileFilter, readPackageLabeller(stmt));
5374
+ const nodes = buildSymbolGraphNodes(
5375
+ symById,
5376
+ relatedIds,
5377
+ new Set(syms.map((symbol) => symbol.file)),
5378
+ readPackageLabeller(stmt)
5379
+ );
5307
5380
  return { nodes, edges };
5308
5381
  }
5309
5382
 
5310
- // src/codebase-index/writer-helpers.ts
5311
- import { resolveWstackPaths } from "@wrongstack/core/utils";
5312
- function escapeLike(value) {
5313
- return value.replace(/[\\%_]/g, (char) => `\\${char}`);
5314
- }
5315
- function assignRefsToSymbols(refs, symbols) {
5316
- if (refs.length === 0 || symbols.length === 0) return [];
5317
- const ordered = [...symbols].sort((a, b) => a.line - b.line || a.col - b.col || a.id - b.id);
5318
- const seen = /* @__PURE__ */ new Set();
5319
- const assigned = [];
5320
- for (const ref of refs) {
5321
- let owner;
5322
- for (const symbol of ordered) {
5323
- if (symbol.line > ref.line) break;
5324
- owner = symbol;
5325
- }
5326
- if (!owner && ref.callType === "import") owner = ordered[0];
5327
- if (!owner || owner.id <= 0) continue;
5328
- const key = `${owner.id}:${ref.toName}:${ref.callType}:${ref.module ?? ""}`;
5329
- if (seen.has(key)) continue;
5330
- seen.add(key);
5331
- assigned.push({ ...ref, fromId: owner.id });
5332
- }
5333
- return assigned;
5334
- }
5335
- function resolveIndexDir(projectRoot, override) {
5336
- return override ?? resolveWstackPaths({ projectRoot }).projectCodebaseIndex;
5337
- }
5338
-
5339
5383
  // src/codebase-index/vector-search.ts
5340
5384
  var RRF_K = 60;
5341
5385
  var VECTOR_DIMENSIONS = 384;
package/dist/index.d.ts CHANGED
@@ -9,7 +9,7 @@ export { builtinTools, OFF_ONLY_TOOLS, OPTIONAL_TOOLS, TIER1_TOOLS, TIER2_TOOLS,
9
9
  export { CircuitBreaker, type CircuitBreakerConfig, type CircuitBreakerSnapshot, } from './circuit-breaker.js';
10
10
  export type { CircuitSnapshot, CircuitState, CodeMapGraph, DeadCodeScanInput, DeadCodeScanOutput, DeadFile, DeadPackage, DeadSymbol, GraphEdge, GraphNode, ProjectIndexDaemonAvailability, ProjectIndexServerActivity, ProjectIndexServerClientHealth, ProjectIndexServerConnectionState, ProjectIndexServerConnectionStatus, ProjectIndexServerHealth, } from './codebase-index/index.js';
11
11
  export { clarifyTool, type ClarifyQuestionInput, type ClarifyOutput, } from './clarify.js';
12
- export { CircuitOpenError, cancelPendingReindexes, checkCodebaseIndexServerHealth, codebaseAstReplaceTool, codebaseImpactAnalysisTool, codebaseIndexStats, codebaseIndexTool, codebaseRepoMapTool, codebaseSearchTool, codebaseSkeletonTool, codebaseStatsTool, codebaseTargetedTestTool, deadCodeScanTool, enqueueReindex, ensureCodebaseIndexServer, extractDirectorySkeleton, extractFileSkeleton, generateRepoMap, replaceSymbolInFile, type FileSkeletonResult, type MutateSymbolOptions, type MutateSymbolResult, type RepoMapOptions, type RepoMapResult, type SkeletonOptions, type SkeletonSymbolRange, fileGraphService, getIndexState, IndexCircuitBreaker, IndexTimeoutError, indexCircuitBreaker, isIndexableFile, isIndexing, isIndexReady, onIndexStateChange, packageGraphService, resetIndexCircuitBreaker, resolveProjectIndexDaemonAvailability, runDeadCodeScan, runStartupIndex, searchCodebaseIndex, shutdownCodebaseIndexHost, shutdownCodebaseIndexServer, symbolGraphService, } from './codebase-index/index.js';
12
+ export { CircuitOpenError, cancelPendingReindexes, checkCodebaseIndexServerHealth, codebaseAstReplaceTool, codebaseImpactAnalysisTool, codebaseIndexStats, codebaseIndexTool, codebaseInvariantCheckTool, codebaseRepoMapTool, codebaseSearchTool, codebaseSkeletonTool, codebaseStatsTool, codebaseTargetedTestTool, deadCodeScanTool, enqueueReindex, ensureCodebaseIndexServer, extractDirectorySkeleton, extractFileSkeleton, generateRepoMap, replaceSymbolInFile, type FileSkeletonResult, type MutateSymbolOptions, type MutateSymbolResult, type RepoMapOptions, type RepoMapResult, type SkeletonOptions, type SkeletonSymbolRange, fileGraphService, getIndexState, IndexCircuitBreaker, IndexTimeoutError, indexCircuitBreaker, isIndexableFile, isIndexing, isIndexReady, onIndexStateChange, packageGraphService, resetIndexCircuitBreaker, resolveProjectIndexDaemonAvailability, runDeadCodeScan, runStartupIndex, searchCodebaseIndex, shutdownCodebaseIndexHost, shutdownCodebaseIndexServer, symbolGraphService, } from './codebase-index/index.js';
13
13
  export { designTool } from './design.js';
14
14
  export { diffTool } from './diff.js';
15
15
  export { documentTool } from './document.js';