@zuvia-software-solutions/code-mapper 2.5.2 → 2.6.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.
@@ -12,7 +12,6 @@ import * as queries from '../../core/db/queries.js';
12
12
  import { refreshFiles, refreshEmbeddings } from '../../core/incremental/refresh.js';
13
13
  import { FileSystemWatcher } from '../../core/incremental/watcher.js';
14
14
  import { toRepoRoot, toRelativeFilePath } from '../../core/incremental/types.js';
15
- import { getTsgoService, stopTsgoService } from '../../core/semantic/tsgo-service.js';
16
15
  import {} from '../../core/search/types.js';
17
16
  import { listRegisteredRepos, } from '../../storage/repo-manager.js';
18
17
  /** Quick test-file detection for filtering impact results across all supported languages */
@@ -53,29 +52,10 @@ export class LocalBackend {
53
52
  /** Per-repo promise chain that serializes ensureFresh calls.
54
53
  * Prevents race: Call 2 skipping refresh while Call 1 is still writing. */
55
54
  refreshLocks = new Map();
56
- /** Per-repo tsgo LSP service instances for live semantic enrichment */
57
- tsgoServices = new Map();
58
55
  /** Per-repo in-memory embedding cache: nodeId → Float32Array (256-dim) */
59
56
  embeddingCaches = new Map();
60
57
  /** Per-repo in-memory NL embedding cache: includes source text for match_reason */
61
58
  nlEmbeddingCaches = new Map();
62
- /** Get (or lazily start) a tsgo LSP service for a repo. Returns null if unavailable. */
63
- async getTsgo(repo) {
64
- const existing = this.tsgoServices.get(repo.id);
65
- if (existing?.isReady())
66
- return existing;
67
- try {
68
- const service = getTsgoService(repo.repoPath);
69
- if (await service.start()) {
70
- this.tsgoServices.set(repo.id, service);
71
- return service;
72
- }
73
- }
74
- catch {
75
- // tsgo not available — completely fine, graph-only mode
76
- }
77
- return null;
78
- }
79
59
  /** Get (or lazily open) the SQLite database for a repo. */
80
60
  getDb(repoId) {
81
61
  const handle = this.repos.get(repoId);
@@ -491,7 +471,7 @@ export class LocalBackend {
491
471
  stats: h.stats,
492
472
  }));
493
473
  }
494
- /** Find the narrowest symbol node enclosing a given file position (for tsgo ref merging) */
474
+ /** Find the narrowest symbol node enclosing a given file position */
495
475
  findNodeAtPosition(db, filePath, line) {
496
476
  try {
497
477
  const rows = rawQuery(db, `SELECT name, label, filePath FROM nodes
@@ -968,11 +948,6 @@ export class LocalBackend {
968
948
  }
969
949
  }
970
950
  catch { }
971
- // Warn if tsgo is unavailable — agents should know call resolution is heuristic-only
972
- const tsgo = this.tsgoServices.get(repo.id);
973
- if (!tsgo?.isReady()) {
974
- warnings.push('⚠ tsgo unavailable — call resolution uses heuristic matching (install @typescript/native-preview for compiler-verified accuracy)');
975
- }
976
951
  return warnings.length > 0 ? warnings.join('\n') + '\n\n' : '';
977
952
  }
978
953
  // ── Tool Dispatch ─────────────────────────────────────────────────
@@ -983,11 +958,6 @@ export class LocalBackend {
983
958
  // Resolve repo from optional param (re-reads registry on miss)
984
959
  const repo = await this.resolveRepo(params?.repo);
985
960
  await this.ensureFresh(repo);
986
- // Eagerly attempt tsgo start so the staleness warning is accurate
987
- // Agents can opt out with tsgo: false for faster responses
988
- if (params?.tsgo !== false) {
989
- await this.getTsgo(repo);
990
- }
991
961
  // C3: Prepend staleness warning to all tool responses
992
962
  const staleWarning = this.getStalenessWarning(repo);
993
963
  switch (method) {
@@ -1933,7 +1903,7 @@ export class LocalBackend {
1933
1903
  * File overview: list all symbols in a file with signatures and caller/callee counts.
1934
1904
  * Triggered when context() is called with file_path only (no name/uid).
1935
1905
  */
1936
- async fileOverview(repo, filePath, includeContent, enableTsgo) {
1906
+ async fileOverview(repo, filePath, includeContent) {
1937
1907
  const db = this.getDb(repo.id);
1938
1908
  // Find the file node and all symbols in it
1939
1909
  const fileNodes = findNodesByFile(db, filePath);
@@ -1955,7 +1925,7 @@ export class LocalBackend {
1955
1925
  };
1956
1926
  }
1957
1927
  // Exact single match — re-query
1958
- return this.fileOverview(repo, allFiles[0].filePath, includeContent, enableTsgo);
1928
+ return this.fileOverview(repo, allFiles[0].filePath, includeContent);
1959
1929
  }
1960
1930
  const symbols = fileNodes.filter(n => n.label !== 'File' && n.label !== 'Folder');
1961
1931
  // Fallback: file has no extractable symbols (e.g., imperative entry points, config files)
@@ -2004,23 +1974,13 @@ export class LocalBackend {
2004
1974
  for (const r of memberRows)
2005
1975
  communityMap.set(r.sourceId, r.heuristicLabel);
2006
1976
  }
2007
- // Optionally enrich with tsgo hover for real type signatures
1977
+ // Extract signatures from stored content using regex-based extraction
2008
1978
  const signatures = new Map();
2009
- if (enableTsgo !== false) {
2010
- const tsgo = await this.getTsgo(repo);
2011
- if (tsgo) {
2012
- const absBase = repo.repoPath;
2013
- for (const sym of symbols.slice(0, 30)) { // cap to avoid slow
2014
- if (sym.startLine != null && /\.(ts|tsx|js|jsx|mts|mjs)$/.test(sym.filePath)) {
2015
- try {
2016
- const hover = await tsgo.getHover(path.resolve(absBase, sym.filePath), sym.startLine - 1, 0);
2017
- if (hover) {
2018
- const clean = hover.replace(/```\w*\n?/g, '').replace(/```/g, '').trim();
2019
- signatures.set(sym.id, clean);
2020
- }
2021
- }
2022
- catch { }
2023
- }
1979
+ for (const sym of symbols) {
1980
+ if (sym.content) {
1981
+ const sig = this.extractSignature(String(sym.content), sym.name, sym.label);
1982
+ if (sig && sig !== sym.name) {
1983
+ signatures.set(sym.id, sig);
2024
1984
  }
2025
1985
  }
2026
1986
  }
@@ -2061,7 +2021,7 @@ export class LocalBackend {
2061
2021
  const { name, uid, file_path, include_content } = params;
2062
2022
  // File overview mode: file_path only, no symbol name
2063
2023
  if (file_path && !name && !uid) {
2064
- return this.fileOverview(repo, file_path, include_content, params.tsgo);
2024
+ return this.fileOverview(repo, file_path, include_content);
2065
2025
  }
2066
2026
  if (!name && !uid) {
2067
2027
  return { error: 'Either "name", "uid", or "file_path" parameter is required.' };
@@ -2088,47 +2048,7 @@ export class LocalBackend {
2088
2048
  }
2089
2049
  symbols = matchedNodes.map(n => ({ id: n.id, name: n.name, type: n.label, filePath: n.filePath, startLine: n.startLine, endLine: n.endLine, content: n.content }));
2090
2050
  }
2091
- // Symbol not found in graph — try tsgo live lookup for recently created symbols
2092
2051
  if (symbols.length === 0) {
2093
- try {
2094
- const tsgoFallback = params?.tsgo !== false ? await this.getTsgo(repo) : null;
2095
- if (tsgoFallback && name) {
2096
- // Search FTS for files that mention this symbol, then ask tsgo for the type
2097
- const searchResults = searchFTS(db, name, 5);
2098
- for (const sr of searchResults) {
2099
- if (sr.filePath && /\.(ts|tsx|js|jsx|mts|mjs)$/.test(sr.filePath)) {
2100
- // Look up the full node to get startLine/endLine
2101
- const fullNode = getNode(db, sr.id);
2102
- const startLine = fullNode?.startLine ?? 1;
2103
- const absPath = path.resolve(repo.repoPath, sr.filePath);
2104
- const hover = await tsgoFallback.getHover(absPath, startLine - 1, 0);
2105
- if (hover) {
2106
- // Found it via tsgo — return a minimal context with live data
2107
- const cleaned = hover.replace(/^```\w*\n?/, '').replace(/\n?```$/, '').trim();
2108
- return {
2109
- status: 'found',
2110
- symbol: {
2111
- uid: sr.id,
2112
- name: sr.name ?? name,
2113
- kind: sr.label ?? 'Symbol',
2114
- filePath: sr.filePath,
2115
- startLine: fullNode?.startLine ?? null,
2116
- endLine: fullNode?.endLine ?? null,
2117
- signature: cleaned || name,
2118
- _source: 'tsgo-live',
2119
- },
2120
- incoming: {},
2121
- outgoing: {},
2122
- processes: [],
2123
- };
2124
- }
2125
- }
2126
- }
2127
- }
2128
- }
2129
- catch {
2130
- // tsgo fallback lookup failed — return normal not-found error
2131
- }
2132
2052
  return { error: `Symbol '${name || uid}' not found` };
2133
2053
  }
2134
2054
  // Step 2: Disambiguation
@@ -2160,41 +2080,6 @@ export class LocalBackend {
2160
2080
  });
2161
2081
  }
2162
2082
  }
2163
- // Enrich incoming refs with tsgo live references (supplements stale graph)
2164
- // Agents can disable with tsgo: false for faster responses
2165
- const tsgo = params?.tsgo !== false ? await this.getTsgo(repo) : null;
2166
- if (tsgo && sym.filePath && /\.(ts|tsx|js|jsx|mts|mjs)$/.test(sym.filePath)) {
2167
- try {
2168
- const absPath = path.resolve(repo.repoPath, sym.filePath);
2169
- const liveRefs = await tsgo.findReferences(absPath, (sym.startLine ?? 1) - 1, 0);
2170
- // Merge live refs with graph refs — live refs may contain callers not in the graph
2171
- for (const ref of liveRefs) {
2172
- // Skip self-references (same file, same line as the symbol definition)
2173
- if (ref.filePath === sym.filePath && Math.abs(ref.line - ((sym.startLine ?? 1) - 1)) <= 1)
2174
- continue;
2175
- // Check if this reference is already known from the graph
2176
- const alreadyKnown = incomingRows.some(row => row.filePath === ref.filePath && Math.abs((row.startLine ?? 0) - (ref.line + 1)) <= 2);
2177
- if (!alreadyKnown) {
2178
- // Find the enclosing function at this reference location
2179
- const refNode = this.findNodeAtPosition(db, ref.filePath, ref.line);
2180
- if (refNode) {
2181
- incomingRows.push({
2182
- relType: 'CALLS',
2183
- uid: '',
2184
- name: refNode.name,
2185
- filePath: ref.filePath,
2186
- kind: refNode.label,
2187
- startLine: ref.line + 1,
2188
- reason: 'tsgo-live',
2189
- });
2190
- }
2191
- }
2192
- }
2193
- }
2194
- catch {
2195
- // tsgo reference lookup failed — non-fatal, graph results still available
2196
- }
2197
- }
2198
2083
  // Supplement callers from refs table (catches callers the graph missed)
2199
2084
  try {
2200
2085
  const refCallers = findRefsBySymbol(db, sym.name, 200);
@@ -2266,25 +2151,9 @@ export class LocalBackend {
2266
2151
  }
2267
2152
  return cats;
2268
2153
  };
2269
- // Always extract signature for compact display
2154
+ // Extract signature for compact display
2270
2155
  const rawContent = sym.content || '';
2271
- let signature = rawContent ? this.extractSignature(String(rawContent), sym.name, sym.type) : sym.name;
2272
- // Enrich with tsgo for live type information (TS/JS files only)
2273
- if (tsgo && sym.filePath && /\.(ts|tsx|js|jsx|mts|mjs)$/.test(sym.filePath)) {
2274
- try {
2275
- const absPath = path.resolve(repo.repoPath, sym.filePath);
2276
- const hover = await tsgo.getHover(absPath, (sym.startLine ?? 1) - 1, 0);
2277
- if (hover) {
2278
- // Strip markdown code fences if present (```typescript ... ```)
2279
- const cleaned = hover.replace(/^```\w*\n?/, '').replace(/\n?```$/, '').trim();
2280
- if (cleaned)
2281
- signature = cleaned;
2282
- }
2283
- }
2284
- catch {
2285
- // tsgo hover failed — non-fatal, use regex-based signature
2286
- }
2287
- }
2156
+ const signature = rawContent ? this.extractSignature(String(rawContent), sym.name, sym.type) : sym.name;
2288
2157
  return {
2289
2158
  status: 'found',
2290
2159
  symbol: {
@@ -2954,12 +2823,6 @@ export class LocalBackend {
2954
2823
  for (const watcher of this.watchers.values())
2955
2824
  watcher.stop();
2956
2825
  this.watchers.clear();
2957
- // Stop all per-repo tsgo LSP services
2958
- for (const service of this.tsgoServices.values()) {
2959
- service.stop();
2960
- }
2961
- this.tsgoServices.clear();
2962
- stopTsgoService(); // also stop the global singleton
2963
2826
  closeDb(); // close all SQLite connections
2964
2827
  // Note: we intentionally do NOT call disposeEmbedder() here.
2965
2828
  // ONNX Runtime's native cleanup segfaults on macOS and some Linux configs,
package/dist/mcp/tools.js CHANGED
@@ -113,7 +113,6 @@ Handles disambiguation: if multiple symbols share the same name, returns candida
113
113
  uid: { type: 'string', description: 'Direct symbol UID from prior tool results (zero-ambiguity lookup)' },
114
114
  file_path: { type: 'string', description: 'File path to disambiguate common names' },
115
115
  include_content: { type: 'boolean', description: 'Include full symbol source code (default: false)', default: false },
116
- tsgo: { type: 'boolean', description: 'Enable tsgo LSP for live compiler-verified callers and type signatures. More accurate but adds ~1-2s latency. Default: true. Set false for speed.', default: true },
117
116
  repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
118
117
  },
119
118
  required: [],
@@ -24,8 +24,6 @@ export interface PipelineResult {
24
24
  totalFileCount: number;
25
25
  communityResult?: CommunityDetectionResult;
26
26
  processResult?: ProcessDetectionResult;
27
- /** Whether tsgo LSP was used for high-confidence call resolution */
28
- tsgoEnabled: boolean;
29
27
  }
30
28
  export interface SerializablePipelineResult {
31
29
  nodes: GraphNode[];
@@ -20,6 +20,5 @@ export const deserializePipelineResult = (serialized, createGraph) => {
20
20
  graph,
21
21
  repoPath: serialized.repoPath,
22
22
  totalFileCount: serialized.totalFileCount,
23
- tsgoEnabled: false,
24
23
  };
25
24
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuvia-software-solutions/code-mapper",
3
- "version": "2.5.2",
3
+ "version": "2.6.1",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": "Abhigyan Patwari",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",