@zuvia-software-solutions/code-mapper 1.4.0 → 2.0.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.
Files changed (137) hide show
  1. package/dist/cli/ai-context.js +1 -1
  2. package/dist/cli/analyze.d.ts +1 -0
  3. package/dist/cli/analyze.js +73 -82
  4. package/dist/cli/augment.js +0 -2
  5. package/dist/cli/eval-server.d.ts +2 -2
  6. package/dist/cli/eval-server.js +6 -6
  7. package/dist/cli/index.js +6 -10
  8. package/dist/cli/mcp.d.ts +1 -3
  9. package/dist/cli/mcp.js +3 -3
  10. package/dist/cli/refresh.d.ts +2 -2
  11. package/dist/cli/refresh.js +24 -29
  12. package/dist/cli/status.js +4 -13
  13. package/dist/cli/tool.d.ts +5 -4
  14. package/dist/cli/tool.js +8 -10
  15. package/dist/config/ignore-service.js +14 -34
  16. package/dist/core/augmentation/engine.js +53 -83
  17. package/dist/core/db/adapter.d.ts +99 -0
  18. package/dist/core/db/adapter.js +402 -0
  19. package/dist/core/db/graph-loader.d.ts +27 -0
  20. package/dist/core/db/graph-loader.js +148 -0
  21. package/dist/core/db/queries.d.ts +160 -0
  22. package/dist/core/db/queries.js +441 -0
  23. package/dist/core/db/schema.d.ts +108 -0
  24. package/dist/core/db/schema.js +136 -0
  25. package/dist/core/embeddings/embedder.d.ts +21 -12
  26. package/dist/core/embeddings/embedder.js +104 -50
  27. package/dist/core/embeddings/embedding-pipeline.d.ts +48 -22
  28. package/dist/core/embeddings/embedding-pipeline.js +220 -262
  29. package/dist/core/embeddings/text-generator.js +4 -19
  30. package/dist/core/embeddings/types.d.ts +1 -1
  31. package/dist/core/graph/graph.d.ts +1 -1
  32. package/dist/core/graph/graph.js +1 -0
  33. package/dist/core/graph/types.d.ts +11 -9
  34. package/dist/core/graph/types.js +4 -1
  35. package/dist/core/incremental/refresh.d.ts +46 -0
  36. package/dist/core/incremental/refresh.js +503 -0
  37. package/dist/core/incremental/types.d.ts +2 -1
  38. package/dist/core/incremental/types.js +42 -44
  39. package/dist/core/ingestion/ast-cache.js +1 -0
  40. package/dist/core/ingestion/call-processor.d.ts +15 -3
  41. package/dist/core/ingestion/call-processor.js +448 -60
  42. package/dist/core/ingestion/cluster-enricher.d.ts +1 -1
  43. package/dist/core/ingestion/cluster-enricher.js +2 -0
  44. package/dist/core/ingestion/community-processor.d.ts +1 -1
  45. package/dist/core/ingestion/community-processor.js +8 -3
  46. package/dist/core/ingestion/export-detection.d.ts +1 -1
  47. package/dist/core/ingestion/export-detection.js +1 -1
  48. package/dist/core/ingestion/filesystem-walker.js +1 -1
  49. package/dist/core/ingestion/heritage-processor.d.ts +2 -2
  50. package/dist/core/ingestion/heritage-processor.js +22 -11
  51. package/dist/core/ingestion/import-processor.d.ts +2 -2
  52. package/dist/core/ingestion/import-processor.js +24 -9
  53. package/dist/core/ingestion/language-config.js +7 -4
  54. package/dist/core/ingestion/mro-processor.d.ts +1 -1
  55. package/dist/core/ingestion/mro-processor.js +23 -11
  56. package/dist/core/ingestion/named-binding-extraction.js +5 -5
  57. package/dist/core/ingestion/parsing-processor.d.ts +4 -4
  58. package/dist/core/ingestion/parsing-processor.js +26 -18
  59. package/dist/core/ingestion/pipeline.d.ts +4 -2
  60. package/dist/core/ingestion/pipeline.js +50 -20
  61. package/dist/core/ingestion/process-processor.d.ts +2 -2
  62. package/dist/core/ingestion/process-processor.js +28 -14
  63. package/dist/core/ingestion/resolution-context.d.ts +1 -1
  64. package/dist/core/ingestion/resolution-context.js +14 -4
  65. package/dist/core/ingestion/resolvers/csharp.js +4 -3
  66. package/dist/core/ingestion/resolvers/go.js +3 -1
  67. package/dist/core/ingestion/resolvers/jvm.js +13 -4
  68. package/dist/core/ingestion/resolvers/standard.js +2 -2
  69. package/dist/core/ingestion/resolvers/utils.js +6 -2
  70. package/dist/core/ingestion/route-stitcher.d.ts +15 -0
  71. package/dist/core/ingestion/route-stitcher.js +92 -0
  72. package/dist/core/ingestion/structure-processor.d.ts +1 -1
  73. package/dist/core/ingestion/structure-processor.js +3 -2
  74. package/dist/core/ingestion/symbol-table.d.ts +2 -0
  75. package/dist/core/ingestion/symbol-table.js +5 -1
  76. package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
  77. package/dist/core/ingestion/tree-sitter-queries.js +177 -0
  78. package/dist/core/ingestion/type-env.js +20 -0
  79. package/dist/core/ingestion/type-extractors/csharp.js +4 -3
  80. package/dist/core/ingestion/type-extractors/go.js +23 -12
  81. package/dist/core/ingestion/type-extractors/php.js +18 -10
  82. package/dist/core/ingestion/type-extractors/ruby.js +15 -3
  83. package/dist/core/ingestion/type-extractors/rust.js +3 -2
  84. package/dist/core/ingestion/type-extractors/shared.js +3 -2
  85. package/dist/core/ingestion/type-extractors/typescript.js +11 -5
  86. package/dist/core/ingestion/utils.d.ts +27 -4
  87. package/dist/core/ingestion/utils.js +145 -100
  88. package/dist/core/ingestion/workers/parse-worker.d.ts +1 -0
  89. package/dist/core/ingestion/workers/parse-worker.js +97 -29
  90. package/dist/core/ingestion/workers/worker-pool.js +3 -0
  91. package/dist/core/search/bm25-index.d.ts +15 -8
  92. package/dist/core/search/bm25-index.js +48 -98
  93. package/dist/core/search/hybrid-search.d.ts +9 -3
  94. package/dist/core/search/hybrid-search.js +30 -25
  95. package/dist/core/search/reranker.js +9 -7
  96. package/dist/core/search/types.d.ts +0 -4
  97. package/dist/core/semantic/tsgo-service.d.ts +7 -1
  98. package/dist/core/semantic/tsgo-service.js +165 -66
  99. package/dist/lib/tsgo-test.d.ts +2 -0
  100. package/dist/lib/tsgo-test.js +6 -0
  101. package/dist/lib/type-utils.d.ts +25 -0
  102. package/dist/lib/type-utils.js +22 -0
  103. package/dist/lib/utils.d.ts +3 -2
  104. package/dist/lib/utils.js +3 -2
  105. package/dist/mcp/compatible-stdio-transport.js +1 -1
  106. package/dist/mcp/local/local-backend.d.ts +29 -56
  107. package/dist/mcp/local/local-backend.js +808 -1118
  108. package/dist/mcp/resources.js +35 -25
  109. package/dist/mcp/server.d.ts +1 -1
  110. package/dist/mcp/server.js +5 -5
  111. package/dist/mcp/tools.js +24 -25
  112. package/dist/storage/repo-manager.d.ts +2 -12
  113. package/dist/storage/repo-manager.js +1 -47
  114. package/dist/types/pipeline.d.ts +8 -5
  115. package/dist/types/pipeline.js +5 -0
  116. package/package.json +18 -11
  117. package/dist/cli/serve.d.ts +0 -5
  118. package/dist/cli/serve.js +0 -8
  119. package/dist/core/incremental/child-process.d.ts +0 -8
  120. package/dist/core/incremental/child-process.js +0 -649
  121. package/dist/core/incremental/refresh-coordinator.d.ts +0 -32
  122. package/dist/core/incremental/refresh-coordinator.js +0 -147
  123. package/dist/core/lbug/csv-generator.d.ts +0 -28
  124. package/dist/core/lbug/csv-generator.js +0 -355
  125. package/dist/core/lbug/lbug-adapter.d.ts +0 -96
  126. package/dist/core/lbug/lbug-adapter.js +0 -753
  127. package/dist/core/lbug/schema.d.ts +0 -46
  128. package/dist/core/lbug/schema.js +0 -402
  129. package/dist/mcp/core/embedder.d.ts +0 -24
  130. package/dist/mcp/core/embedder.js +0 -168
  131. package/dist/mcp/core/lbug-adapter.d.ts +0 -29
  132. package/dist/mcp/core/lbug-adapter.js +0 -330
  133. package/dist/server/api.d.ts +0 -5
  134. package/dist/server/api.js +0 -340
  135. package/dist/server/mcp-http.d.ts +0 -7
  136. package/dist/server/mcp-http.js +0 -95
  137. package/models/mlx-embedder.py +0 -185
@@ -44,7 +44,7 @@ export function getResourceTemplates() {
44
44
  {
45
45
  uriTemplate: 'code-mapper://repo/{name}/schema',
46
46
  name: 'Graph Schema',
47
- description: 'Node/edge schema for Cypher queries',
47
+ description: 'Node/edge schema for SQL queries',
48
48
  mimeType: 'text/yaml',
49
49
  },
50
50
  {
@@ -70,8 +70,8 @@ function parseUri(uri) {
70
70
  // Repo-scoped: code-mapper://repo/{name}/context
71
71
  const repoMatch = uri.match(/^code-mapper:\/\/repo\/([^/]+)\/(.+)$/);
72
72
  if (repoMatch) {
73
- const repoName = decodeURIComponent(repoMatch[1]);
74
- const rest = repoMatch[2];
73
+ const repoName = decodeURIComponent(repoMatch[1] ?? '');
74
+ const rest = repoMatch[2] ?? '';
75
75
  if (rest.startsWith('cluster/')) {
76
76
  return { repoName, resourceType: 'cluster', param: decodeURIComponent(rest.replace('cluster/', '')) };
77
77
  }
@@ -133,7 +133,10 @@ async function getReposResource(backend) {
133
133
  if (repos.length > 1) {
134
134
  lines.push('');
135
135
  lines.push('# Multiple repos indexed. Use repo parameter in tool calls:');
136
- lines.push(`# code-mapper_search({query: "auth", repo: "${repos[0].name}"})`);
136
+ const firstRepo = repos[0];
137
+ if (firstRepo) {
138
+ lines.push(`# code-mapper_search({query: "auth", repo: "${firstRepo.name}"})`);
139
+ }
137
140
  }
138
141
  return lines.join('\n');
139
142
  }
@@ -168,7 +171,7 @@ async function getContextResource(backend, repoName) {
168
171
  lines.push(' - impact: Blast radius analysis (what breaks if you change a symbol)');
169
172
  lines.push(' - detect_changes: Git-diff impact analysis (what do your changes affect)');
170
173
  lines.push(' - rename: Multi-file coordinated rename with confidence tags');
171
- lines.push(' - cypher: Raw graph queries');
174
+ lines.push(' - sql: Raw SQL queries');
172
175
  lines.push(' - list_repos: Discover all indexed repositories');
173
176
  lines.push('');
174
177
  lines.push('re_index: Run `npx code-mapper analyze` in terminal if data is stale');
@@ -233,11 +236,16 @@ async function getProcessesResource(backend, repoName) {
233
236
  return `error: ${err.message}`;
234
237
  }
235
238
  }
236
- /** Graph schema reference for Cypher queries */
239
+ /** Graph schema reference for SQL queries */
237
240
  function getSchemaResource() {
238
- return `# Code Mapper Graph Schema
241
+ return `# Code Mapper Graph Schema (SQLite)
242
+
243
+ tables:
244
+ nodes: "id TEXT PK, label TEXT, name TEXT, filePath TEXT, startLine INT, endLine INT, isExported INT, content TEXT, description TEXT, heuristicLabel TEXT, cohesion REAL, symbolCount INT, keywords TEXT, enrichedBy TEXT, processType TEXT, stepCount INT, communities TEXT, entryPointId TEXT, terminalId TEXT, parameterCount INT, returnType TEXT"
245
+ edges: "id TEXT PK, sourceId TEXT, targetId TEXT, type TEXT, confidence REAL, reason TEXT, step INT, callLine INT"
246
+ embeddings: "nodeId TEXT PK, embedding BLOB"
239
247
 
240
- nodes:
248
+ node_labels:
241
249
  - File: Source code files
242
250
  - Folder: Directory containers
243
251
  - Function: Functions and arrow functions
@@ -248,9 +256,9 @@ nodes:
248
256
  - Community: Auto-detected functional area (Leiden algorithm)
249
257
  - Process: Execution flow trace
250
258
 
251
- additional_node_types: "Multi-language: Struct, Enum, Macro, Typedef, Union, Namespace, Trait, Impl, TypeAlias, Const, Static, Property, Record, Delegate, Annotation, Constructor, Template, Module (use backticks in queries: \`Struct\`, \`Enum\`, etc.)"
259
+ additional_node_labels: "Multi-language: Struct, Enum, Macro, Typedef, Union, Namespace, Trait, Impl, TypeAlias, Const, Static, Property, Record, Delegate, Annotation, Constructor, Template, Module"
252
260
 
253
- relationships:
261
+ edge_types:
254
262
  - CONTAINS: File/Folder contains child
255
263
  - DEFINES: File defines a symbol
256
264
  - CALLS: Function/method invocation
@@ -260,23 +268,25 @@ relationships:
260
268
  - MEMBER_OF: Symbol belongs to community
261
269
  - STEP_IN_PROCESS: Symbol is step N in process
262
270
 
263
- relationship_table: "All relationships use a single CodeRelation table with a 'type' property. Properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)"
264
-
265
271
  example_queries:
266
272
  find_callers: |
267
- MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "myFunc"})
268
- RETURN caller.name, caller.filePath
269
-
273
+ SELECT n.name, n.filePath FROM edges e
274
+ JOIN nodes n ON n.id = e.sourceId
275
+ JOIN nodes t ON t.id = e.targetId
276
+ WHERE t.name = 'myFunc' AND t.label = 'Function' AND e.type = 'CALLS'
277
+
270
278
  find_community_members: |
271
- MATCH (s)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community)
272
- WHERE c.heuristicLabel = "Auth"
273
- RETURN s.name, labels(s) AS type
274
-
279
+ SELECT n.name, n.label FROM edges e
280
+ JOIN nodes n ON n.id = e.sourceId
281
+ JOIN nodes c ON c.id = e.targetId
282
+ WHERE c.heuristicLabel = 'Auth' AND c.label = 'Community' AND e.type = 'MEMBER_OF'
283
+
275
284
  trace_process: |
276
- MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process)
277
- WHERE p.heuristicLabel = "LoginFlow"
278
- RETURN s.name, r.step
279
- ORDER BY r.step
285
+ SELECT n.name, e.step FROM edges e
286
+ JOIN nodes n ON n.id = e.sourceId
287
+ JOIN nodes p ON p.id = e.targetId
288
+ WHERE p.heuristicLabel = 'LoginFlow' AND p.label = 'Process' AND e.type = 'STEP_IN_PROCESS'
289
+ ORDER BY e.step
280
290
  `;
281
291
  }
282
292
  /** Deep dive into a specific functional area */
@@ -363,7 +373,7 @@ async function getSetupResource(backend) {
363
373
  '| `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |',
364
374
  '| `detect_changes` | Git-diff impact — what do your current changes affect |',
365
375
  '| `rename` | Multi-file coordinated rename with confidence-tagged edits |',
366
- '| `cypher` | Raw graph queries |',
376
+ '| `sql` | Raw SQL queries |',
367
377
  '| `list_repos` | Discover indexed repos |',
368
378
  '',
369
379
  '## Resources',
@@ -371,7 +381,7 @@ async function getSetupResource(backend) {
371
381
  `- \`code-mapper://repo/${repo.name}/context\` — Stats, staleness check`,
372
382
  `- \`code-mapper://repo/${repo.name}/clusters\` — All functional areas`,
373
383
  `- \`code-mapper://repo/${repo.name}/processes\` — All execution flows`,
374
- `- \`code-mapper://repo/${repo.name}/schema\` — Graph schema for Cypher`,
384
+ `- \`code-mapper://repo/${repo.name}/schema\` — Graph schema for SQL queries`,
375
385
  ];
376
386
  sections.push(lines.join('\n'));
377
387
  }
@@ -1,7 +1,7 @@
1
1
  /** @file server.ts
2
2
  * @description Model Context Protocol server for multi-repo code intelligence
3
3
  * Runs on stdio for external AI tools (Cursor, Claude) via MCP protocol
4
- * Tools: list_repos, query, cypher, context, impact, detect_changes, rename */
4
+ * Tools: list_repos, query, sql, context, impact, detect_changes, rename */
5
5
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
6
6
  import type { LocalBackend } from './local/local-backend.js';
7
7
  /** Create a configured MCP Server with all handlers registered (transport-agnostic) */
@@ -2,7 +2,7 @@
2
2
  /** @file server.ts
3
3
  * @description Model Context Protocol server for multi-repo code intelligence
4
4
  * Runs on stdio for external AI tools (Cursor, Claude) via MCP protocol
5
- * Tools: list_repos, query, cypher, context, impact, detect_changes, rename */
5
+ * Tools: list_repos, query, sql, context, impact, detect_changes, rename */
6
6
  import { createRequire } from 'module';
7
7
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
8
8
  import { CompatibleStdioServerTransport } from './compatible-stdio-transport.js';
@@ -14,7 +14,7 @@ import { getResourceDefinitions, getResourceTemplates, readResource } from './re
14
14
  /** Create a configured MCP Server with all handlers registered (transport-agnostic) */
15
15
  export function createMCPServer(backend) {
16
16
  // Preload embedding model in background so first query doesn't pay cold-start cost
17
- import('./core/embedder.js').then(m => m.initEmbedder()).catch(() => { });
17
+ import('../core/embeddings/embedder.js').then(m => m.initEmbedder()).catch(() => { });
18
18
  const require = createRequire(import.meta.url);
19
19
  const pkgVersion = require('../../package.json').version;
20
20
  const server = new Server({
@@ -138,8 +138,8 @@ export function createMCPServer(backend) {
138
138
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
139
139
  const { name, arguments: args } = request.params;
140
140
  if (name === 'detect_impact') {
141
- const scope = args?.scope || 'all';
142
- const baseRef = args?.base_ref || '';
141
+ const scope = args?.['scope'] || 'all';
142
+ const baseRef = args?.['base_ref'] || '';
143
143
  return {
144
144
  messages: [
145
145
  {
@@ -161,7 +161,7 @@ Present the analysis as a clear risk report.`,
161
161
  };
162
162
  }
163
163
  if (name === 'generate_map') {
164
- const repo = args?.repo || '';
164
+ const repo = args?.['repo'] || '';
165
165
  return {
166
166
  messages: [
167
167
  {
package/dist/mcp/tools.js CHANGED
@@ -50,49 +50,40 @@ Hybrid ranking: BM25 keyword + semantic vector search, ranked by Reciprocal Rank
50
50
  },
51
51
  },
52
52
  {
53
- name: 'cypher',
54
- description: `Execute Cypher query against the code knowledge graph.
53
+ name: 'sql',
54
+ description: `Execute a SQL query against the code knowledge graph (SQLite).
55
55
 
56
56
  WHEN TO USE: Complex structural queries that search/explore can't answer. READ code-mapper://repo/{name}/schema first for the full schema.
57
57
  AFTER THIS: Use context() on result symbols for deeper context.
58
58
 
59
- SCHEMA:
60
- - Nodes: File, Folder, Function, Class, Interface, Method, CodeElement, Community, Process
61
- - Multi-language nodes (use backticks): \`Struct\`, \`Enum\`, \`Trait\`, \`Impl\`, etc.
62
- - All edges via single CodeRelation table with 'type' property
59
+ SCHEMA (SQLite tables):
60
+ - nodes: id, label, name, filePath, startLine, endLine, isExported, content, description, heuristicLabel, cohesion, symbolCount, keywords, enrichedBy, processType, stepCount, communities, entryPointId, terminalId, parameterCount, returnType
61
+ - edges: id, sourceId, targetId, type, confidence, reason, step, callLine
62
+ - embeddings: nodeId, embedding (BLOB)
63
+ - Node labels: File, Folder, Function, Class, Interface, Method, CodeElement, Community, Process, Struct, Enum, Trait, Impl, TypeAlias, Const, Static, Property, Record, Delegate, Annotation, Constructor, Template, Module, Namespace, Macro, Typedef, Union
63
64
  - Edge types: CONTAINS, DEFINES, CALLS, IMPORTS, EXTENDS, IMPLEMENTS, HAS_METHOD, OVERRIDES, MEMBER_OF, STEP_IN_PROCESS
64
- - Edge properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)
65
65
 
66
66
  EXAMPLES:
67
67
  • Find callers of a function:
68
- MATCH (a)-[:CodeRelation {type: 'CALLS'}]->(b:Function {name: "validateUser"}) RETURN a.name, a.filePath
68
+ SELECT n.name, n.filePath FROM edges e JOIN nodes n ON n.id = e.sourceId JOIN nodes t ON t.id = e.targetId WHERE t.name = 'validateUser' AND t.label = 'Function' AND e.type = 'CALLS'
69
69
 
70
70
  • Find community members:
71
- MATCH (f)-[:CodeRelation {type: 'MEMBER_OF'}]->(c:Community) WHERE c.heuristicLabel = "Auth" RETURN f.name
71
+ SELECT n.name FROM edges e JOIN nodes n ON n.id = e.sourceId JOIN nodes c ON c.id = e.targetId WHERE c.heuristicLabel = 'Auth' AND c.label = 'Community' AND e.type = 'MEMBER_OF'
72
72
 
73
73
  • Trace a process:
74
- MATCH (s)-[r:CodeRelation {type: 'STEP_IN_PROCESS'}]->(p:Process) WHERE p.heuristicLabel = "UserLogin" RETURN s.name, r.step ORDER BY r.step
75
-
76
- • Find all methods of a class:
77
- MATCH (c:Class {name: "UserService"})-[r:CodeRelation {type: 'HAS_METHOD'}]->(m:Method) RETURN m.name, m.parameterCount, m.returnType
78
-
79
- • Find method overrides (MRO resolution):
80
- MATCH (winner:Method)-[r:CodeRelation {type: 'OVERRIDES'}]->(loser:Method) RETURN winner.name, winner.filePath, loser.filePath, r.reason
81
-
82
- • Detect diamond inheritance:
83
- MATCH (d:Class)-[:CodeRelation {type: 'EXTENDS'}]->(b1), (d)-[:CodeRelation {type: 'EXTENDS'}]->(b2), (b1)-[:CodeRelation {type: 'EXTENDS'}]->(a), (b2)-[:CodeRelation {type: 'EXTENDS'}]->(a) WHERE b1 <> b2 RETURN d.name, b1.name, b2.name, a.name
74
+ SELECT n.name, e.step FROM edges e JOIN nodes n ON n.id = e.sourceId JOIN nodes p ON p.id = e.targetId WHERE p.heuristicLabel = 'UserLogin' AND p.label = 'Process' AND e.type = 'STEP_IN_PROCESS' ORDER BY e.step
84
75
 
85
76
  OUTPUT: Returns { markdown, row_count } — results formatted as a Markdown table for easy reading.
86
77
 
87
78
  TIPS:
88
- - All relationships use single CodeRelation table filter with {type: 'CALLS'} etc.
79
+ - Filter nodes by label column, edges by type column
89
80
  - Community = auto-detected functional area (Leiden algorithm)
90
81
  - Process = execution flow trace from entry point to terminal
91
82
  - Use heuristicLabel (not label) for human-readable community/process names`,
92
83
  inputSchema: {
93
84
  type: 'object',
94
85
  properties: {
95
- query: { type: 'string', description: 'Cypher query to execute' },
86
+ query: { type: 'string', description: 'SQL query to execute (read-only)' },
96
87
  repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
97
88
  },
98
89
  required: ['query'],
@@ -100,10 +91,16 @@ TIPS:
100
91
  },
101
92
  {
102
93
  name: 'context',
103
- description: `360-degree view of a single code symbol.
104
- Shows categorized incoming/outgoing references (calls, imports, extends, implements), process participation, and file location.
94
+ description: `360-degree view of a code symbol, or file-level overview.
95
+
96
+ TWO MODES:
97
+ 1. Symbol mode (name or uid): callers, callees, execution flows, type signature
98
+ 2. File mode (file_path only, no name): all symbols in the file with signatures, caller/callee counts, module membership
105
99
 
106
- WHEN TO USE: After query() to understand a specific symbol in depth. When you need to know all callers, callees, and what execution flows a symbol participates in.
100
+ WHEN TO USE:
101
+ - After query() to understand a specific symbol in depth
102
+ - When opening a file for the first time — pass file_path only to see everything in it
103
+ - When you need to know all callers, callees, and what execution flows a symbol participates in
107
104
  AFTER THIS: Use impact() if planning changes, or READ code-mapper://repo/{name}/process/{processName} for full execution trace.
108
105
 
109
106
  Handles disambiguation: if multiple symbols share the same name, returns candidates for you to pick from. Use uid param for zero-ambiguity lookup from prior results.`,
@@ -115,6 +112,7 @@ Handles disambiguation: if multiple symbols share the same name, returns candida
115
112
  uid: { type: 'string', description: 'Direct symbol UID from prior tool results (zero-ambiguity lookup)' },
116
113
  file_path: { type: 'string', description: 'File path to disambiguate common names' },
117
114
  include_content: { type: 'boolean', description: 'Include full symbol source code (default: false)', default: false },
115
+ 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 },
118
116
  repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
119
117
  },
120
118
  required: [],
@@ -189,10 +187,11 @@ Confidence: 1.0 = certain, <0.8 = fuzzy match`,
189
187
  type: 'object',
190
188
  properties: {
191
189
  target: { type: 'string', description: 'Name of function, class, or file to analyze' },
190
+ file_path: { type: 'string', description: 'File path to disambiguate when multiple symbols share the same name (substring match)' },
192
191
  direction: { type: 'string', description: 'upstream (what depends on this) or downstream (what this depends on)' },
193
192
  maxDepth: { type: 'number', description: 'Max relationship depth (default: 3)', default: 3 },
194
193
  relationTypes: { type: 'array', items: { type: 'string' }, description: 'Filter: CALLS, IMPORTS, EXTENDS, IMPLEMENTS, HAS_METHOD, OVERRIDES (default: usage-based)' },
195
- includeTests: { type: 'boolean', description: 'Include test files (default: false)' },
194
+ includeTests: { type: 'boolean', description: 'Include test files (default: true — all code is treated equally)' },
196
195
  minConfidence: { type: 'number', description: 'Minimum confidence 0-1 (default: 0.7)' },
197
196
  repo: { type: 'string', description: 'Repository name or path. Omit if only one repo is indexed.' },
198
197
  },
@@ -17,7 +17,7 @@ export interface RepoMeta {
17
17
  export interface IndexedRepo {
18
18
  repoPath: string;
19
19
  storagePath: string;
20
- lbugPath: string;
20
+ dbPath: string;
21
21
  metaPath: string;
22
22
  meta: RepoMeta;
23
23
  }
@@ -35,19 +35,9 @@ export declare const getStoragePath: (repoPath: string) => string;
35
35
  /** Get paths to key storage files */
36
36
  export declare const getStoragePaths: (repoPath: string) => {
37
37
  storagePath: string;
38
- lbugPath: string;
38
+ dbPath: string;
39
39
  metaPath: string;
40
40
  };
41
- /** Check whether a KuzuDB index exists (non-destructive, safe for status commands) */
42
- export declare const hasKuzuIndex: (storagePath: string) => Promise<boolean>;
43
- /**
44
- * Clean up stale KuzuDB files after migration to LadybugDB
45
- * @returns found (kuzu existed and was deleted), needsReindex (kuzu existed but lbug does not)
46
- */
47
- export declare const cleanupOldKuzuFiles: (storagePath: string) => Promise<{
48
- found: boolean;
49
- needsReindex: boolean;
50
- }>;
51
41
  /** Load metadata from an indexed repo */
52
42
  export declare const loadMeta: (storagePath: string) => Promise<RepoMeta | null>;
53
43
  /** Save metadata to storage */
@@ -16,56 +16,10 @@ export const getStoragePaths = (repoPath) => {
16
16
  const storagePath = getStoragePath(repoPath);
17
17
  return {
18
18
  storagePath,
19
- lbugPath: path.join(storagePath, 'lbug'),
19
+ dbPath: path.join(storagePath, 'index.db'),
20
20
  metaPath: path.join(storagePath, 'meta.json'),
21
21
  };
22
22
  };
23
- /** Check whether a KuzuDB index exists (non-destructive, safe for status commands) */
24
- export const hasKuzuIndex = async (storagePath) => {
25
- try {
26
- await fs.stat(path.join(storagePath, 'kuzu'));
27
- return true;
28
- }
29
- catch {
30
- return false;
31
- }
32
- };
33
- /**
34
- * Clean up stale KuzuDB files after migration to LadybugDB
35
- * @returns found (kuzu existed and was deleted), needsReindex (kuzu existed but lbug does not)
36
- */
37
- export const cleanupOldKuzuFiles = async (storagePath) => {
38
- const oldPath = path.join(storagePath, 'kuzu');
39
- const newPath = path.join(storagePath, 'lbug');
40
- try {
41
- await fs.stat(oldPath);
42
- // Old kuzu file/dir exists — determine if lbug is already present
43
- let needsReindex = false;
44
- try {
45
- await fs.stat(newPath);
46
- }
47
- catch {
48
- needsReindex = true;
49
- }
50
- // Delete kuzu database file and its sidecars (.wal, .lock)
51
- for (const suffix of ['', '.wal', '.lock']) {
52
- try {
53
- await fs.unlink(oldPath + suffix);
54
- }
55
- catch { }
56
- }
57
- // Also handle the case where kuzu was stored as a directory
58
- try {
59
- await fs.rm(oldPath, { recursive: true, force: true });
60
- }
61
- catch { }
62
- return { found: true, needsReindex };
63
- }
64
- catch {
65
- // Old path doesn't exist — nothing to do
66
- return { found: false, needsReindex: false };
67
- }
68
- };
69
23
  /** Load metadata from an indexed repo */
70
24
  export const loadMeta = async (storagePath) => {
71
25
  try {
@@ -1,8 +1,9 @@
1
1
  /** @file pipeline.ts @description Types for the ingestion pipeline: phases, progress, results, and serialization helpers */
2
- import { GraphNode, GraphRelationship, KnowledgeGraph } from '../core/graph/types.js';
3
- import { CommunityDetectionResult } from '../core/ingestion/community-processor.js';
4
- import { ProcessDetectionResult } from '../core/ingestion/process-processor.js';
5
- export type PipelinePhase = 'idle' | 'extracting' | 'structure' | 'parsing' | 'imports' | 'calls' | 'heritage' | 'communities' | 'processes' | 'enriching' | 'complete' | 'error';
2
+ import type { GraphNode, GraphRelationship, KnowledgeGraph } from '../core/graph/types.js';
3
+ import type { CommunityDetectionResult } from '../core/ingestion/community-processor.js';
4
+ import type { ProcessDetectionResult } from '../core/ingestion/process-processor.js';
5
+ export declare const PIPELINE_PHASES: readonly ["idle", "extracting", "structure", "parsing", "imports", "calls", "heritage", "communities", "processes", "enriching", "complete", "error"];
6
+ export type PipelinePhase = typeof PIPELINE_PHASES[number];
6
7
  export interface PipelineProgress {
7
8
  phase: PipelinePhase;
8
9
  percent: number;
@@ -16,12 +17,14 @@ export interface PipelineProgress {
16
17
  }
17
18
  export interface PipelineResult {
18
19
  graph: KnowledgeGraph;
19
- /** Absolute path to the repo root, used for lazy file reads during LadybugDB loading */
20
+ /** Absolute path to the repo root, used for lazy file reads during database loading */
20
21
  repoPath: string;
21
22
  /** Total files scanned */
22
23
  totalFileCount: number;
23
24
  communityResult?: CommunityDetectionResult;
24
25
  processResult?: ProcessDetectionResult;
26
+ /** Whether tsgo LSP was used for high-confidence call resolution */
27
+ tsgoEnabled: boolean;
25
28
  }
26
29
  export interface SerializablePipelineResult {
27
30
  nodes: GraphNode[];
@@ -1,5 +1,9 @@
1
1
  // code-mapper/src/types/pipeline.ts
2
2
  /** @file pipeline.ts @description Types for the ingestion pipeline: phases, progress, results, and serialization helpers */
3
+ export const PIPELINE_PHASES = [
4
+ 'idle', 'extracting', 'structure', 'parsing', 'imports', 'calls',
5
+ 'heritage', 'communities', 'processes', 'enriching', 'complete', 'error',
6
+ ];
3
7
  /** Convert PipelineResult to a serializable format for postMessage */
4
8
  export const serializePipelineResult = (result) => ({
5
9
  nodes: [...result.graph.iterNodes()],
@@ -16,5 +20,6 @@ export const deserializePipelineResult = (serialized, createGraph) => {
16
20
  graph,
17
21
  repoPath: serialized.repoPath,
18
22
  totalFileCount: serialized.totalFileCount,
23
+ tsgoEnabled: false,
19
24
  };
20
25
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuvia-software-solutions/code-mapper",
3
- "version": "1.4.0",
3
+ "version": "2.0.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",
@@ -34,8 +34,7 @@
34
34
  "hooks",
35
35
  "scripts",
36
36
  "skills",
37
- "vendor",
38
- "models/mlx-embedder.py"
37
+ "vendor"
39
38
  ],
40
39
  "scripts": {
41
40
  "build": "tsc",
@@ -45,25 +44,28 @@
45
44
  "test:all": "vitest run",
46
45
  "test:watch": "vitest",
47
46
  "test:coverage": "vitest run --coverage",
47
+ "lint": "eslint src/",
48
+ "lint:fix": "eslint src/ --fix",
49
+ "typecheck": "tsc --noEmit",
50
+ "typecheck:fast": "tsgo --noEmit",
48
51
  "prepare": "npm run build",
49
52
  "postinstall": "node scripts/patch-tree-sitter-swift.cjs"
50
53
  },
51
54
  "dependencies": {
52
55
  "@huggingface/transformers": "^3.8.1",
53
- "@ladybugdb/core": "^0.15.1",
54
56
  "@modelcontextprotocol/sdk": "^1.0.0",
57
+ "@types/better-sqlite3": "^7.6.13",
58
+ "better-sqlite3": "^12.8.0",
55
59
  "cli-progress": "^3.12.0",
56
60
  "commander": "^12.0.0",
57
- "cors": "^2.8.5",
58
- "express": "^4.19.2",
59
61
  "glob": "^11.0.0",
60
62
  "graphology": "^0.25.4",
61
63
  "graphology-indices": "^0.17.0",
62
- "graphology-utils": "^2.3.0",
64
+ "graphology-utils": "^2.5.2",
63
65
  "ignore": "^7.0.5",
64
66
  "lru-cache": "^11.0.0",
65
- "mnemonist": "^0.39.0",
66
- "pandemonium": "^2.4.0",
67
+ "mnemonist": "^0.40.3",
68
+ "pandemonium": "^2.4.1",
67
69
  "tree-sitter": "^0.21.0",
68
70
  "tree-sitter-c": "^0.21.0",
69
71
  "tree-sitter-c-sharp": "^0.21.0",
@@ -83,15 +85,20 @@
83
85
  "tree-sitter-swift": "^0.6.0"
84
86
  },
85
87
  "devDependencies": {
88
+ "@eslint/js": "^10.0.1",
86
89
  "@types/cli-progress": "^3.11.6",
87
- "@types/cors": "^2.8.17",
88
- "@types/express": "^4.17.21",
89
90
  "@types/node": "^20.0.0",
90
91
  "@types/uuid": "^10.0.0",
91
92
  "@typescript/native-preview": "^7.0.0-dev.20260317.1",
92
93
  "@vitest/coverage-v8": "^4.0.18",
94
+ "eslint": "^10.0.3",
95
+ "eslint-plugin-import-x": "^4.16.2",
96
+ "eslint-plugin-no-secrets": "^2.3.3",
97
+ "eslint-plugin-sonarjs": "^4.0.2",
98
+ "eslint-plugin-unicorn": "^63.0.0",
93
99
  "tsx": "^4.0.0",
94
100
  "typescript": "^5.4.5",
101
+ "typescript-eslint": "^8.57.1",
95
102
  "vitest": "^4.0.18"
96
103
  },
97
104
  "engines": {
@@ -1,5 +0,0 @@
1
- /** @file serve.ts @description Starts the HTTP REST API server for browser-based access */
2
- export declare const serveCommand: (options?: {
3
- port?: string;
4
- host?: string;
5
- }) => Promise<void>;
package/dist/cli/serve.js DELETED
@@ -1,8 +0,0 @@
1
- // code-mapper/src/cli/serve.ts
2
- /** @file serve.ts @description Starts the HTTP REST API server for browser-based access */
3
- import { createServer } from '../server/api.js';
4
- export const serveCommand = async (options) => {
5
- const port = Number(options?.port ?? 4747);
6
- const host = options?.host ?? '127.0.0.1';
7
- await createServer(port, host);
8
- };
@@ -1,8 +0,0 @@
1
- /**
2
- * @file child-process.ts
3
- * @description Forked child process entry point for incremental DB updates. Opens
4
- * LadybugDB in READ-WRITE mode, deletes stale nodes for changed files, re-parses
5
- * them with tree-sitter, inserts new nodes/edges, resolves imports/calls/heritage,
6
- * and rebuilds FTS indexes. Communicates with the parent via structured IPC messages
7
- */
8
- export {};