@jafreck/lore 0.2.4 → 0.3.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.
Files changed (200) hide show
  1. package/README.md +63 -35
  2. package/dist/cli.js +41 -38
  3. package/dist/cli.js.map +1 -1
  4. package/dist/index.d.ts +24 -5
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +23 -4
  7. package/dist/index.js.map +1 -1
  8. package/dist/indexer/call-graph.d.ts +29 -8
  9. package/dist/indexer/call-graph.d.ts.map +1 -1
  10. package/dist/indexer/call-graph.js +232 -31
  11. package/dist/indexer/call-graph.js.map +1 -1
  12. package/dist/indexer/config-parser.js +6 -1
  13. package/dist/indexer/config-parser.js.map +1 -1
  14. package/dist/indexer/coverage.js +3 -1
  15. package/dist/indexer/coverage.js.map +1 -1
  16. package/dist/indexer/db.d.ts.map +1 -1
  17. package/dist/indexer/db.js +70 -1
  18. package/dist/indexer/db.js.map +1 -1
  19. package/dist/indexer/docs.d.ts.map +1 -1
  20. package/dist/indexer/docs.js +4 -0
  21. package/dist/indexer/docs.js.map +1 -1
  22. package/dist/indexer/embedder.d.ts.map +1 -1
  23. package/dist/indexer/embedder.js +5 -0
  24. package/dist/indexer/embedder.js.map +1 -1
  25. package/dist/indexer/extractors/bash.d.ts.map +1 -1
  26. package/dist/indexer/extractors/bash.js +29 -1
  27. package/dist/indexer/extractors/bash.js.map +1 -1
  28. package/dist/indexer/extractors/c.d.ts +5 -2
  29. package/dist/indexer/extractors/c.d.ts.map +1 -1
  30. package/dist/indexer/extractors/c.js +277 -8
  31. package/dist/indexer/extractors/c.js.map +1 -1
  32. package/dist/indexer/extractors/cpp.d.ts +5 -2
  33. package/dist/indexer/extractors/cpp.d.ts.map +1 -1
  34. package/dist/indexer/extractors/cpp.js +349 -3
  35. package/dist/indexer/extractors/cpp.js.map +1 -1
  36. package/dist/indexer/extractors/csharp.d.ts.map +1 -1
  37. package/dist/indexer/extractors/csharp.js +166 -1
  38. package/dist/indexer/extractors/csharp.js.map +1 -1
  39. package/dist/indexer/extractors/dart.d.ts.map +1 -1
  40. package/dist/indexer/extractors/dart.js +134 -1
  41. package/dist/indexer/extractors/dart.js.map +1 -1
  42. package/dist/indexer/extractors/elixir.d.ts.map +1 -1
  43. package/dist/indexer/extractors/elixir.js +45 -0
  44. package/dist/indexer/extractors/elixir.js.map +1 -1
  45. package/dist/indexer/extractors/elm.d.ts.map +1 -1
  46. package/dist/indexer/extractors/elm.js +33 -0
  47. package/dist/indexer/extractors/elm.js.map +1 -1
  48. package/dist/indexer/extractors/go.d.ts.map +1 -1
  49. package/dist/indexer/extractors/go.js +206 -1
  50. package/dist/indexer/extractors/go.js.map +1 -1
  51. package/dist/indexer/extractors/haskell.d.ts.map +1 -1
  52. package/dist/indexer/extractors/haskell.js +29 -0
  53. package/dist/indexer/extractors/haskell.js.map +1 -1
  54. package/dist/indexer/extractors/java.d.ts.map +1 -1
  55. package/dist/indexer/extractors/java.js +170 -1
  56. package/dist/indexer/extractors/java.js.map +1 -1
  57. package/dist/indexer/extractors/javascript.d.ts.map +1 -1
  58. package/dist/indexer/extractors/javascript.js +24 -2
  59. package/dist/indexer/extractors/javascript.js.map +1 -1
  60. package/dist/indexer/extractors/julia.d.ts.map +1 -1
  61. package/dist/indexer/extractors/julia.js +23 -1
  62. package/dist/indexer/extractors/julia.js.map +1 -1
  63. package/dist/indexer/extractors/kotlin.d.ts.map +1 -1
  64. package/dist/indexer/extractors/kotlin.js +122 -1
  65. package/dist/indexer/extractors/kotlin.js.map +1 -1
  66. package/dist/indexer/extractors/lua.d.ts.map +1 -1
  67. package/dist/indexer/extractors/lua.js +19 -1
  68. package/dist/indexer/extractors/lua.js.map +1 -1
  69. package/dist/indexer/extractors/objc.d.ts.map +1 -1
  70. package/dist/indexer/extractors/objc.js +171 -1
  71. package/dist/indexer/extractors/objc.js.map +1 -1
  72. package/dist/indexer/extractors/ocaml.d.ts.map +1 -1
  73. package/dist/indexer/extractors/ocaml.js +29 -0
  74. package/dist/indexer/extractors/ocaml.js.map +1 -1
  75. package/dist/indexer/extractors/php.d.ts.map +1 -1
  76. package/dist/indexer/extractors/php.js +137 -1
  77. package/dist/indexer/extractors/php.js.map +1 -1
  78. package/dist/indexer/extractors/python.d.ts.map +1 -1
  79. package/dist/indexer/extractors/python.js +24 -3
  80. package/dist/indexer/extractors/python.js.map +1 -1
  81. package/dist/indexer/extractors/ruby.d.ts.map +1 -1
  82. package/dist/indexer/extractors/ruby.js +23 -1
  83. package/dist/indexer/extractors/ruby.js.map +1 -1
  84. package/dist/indexer/extractors/rust.d.ts.map +1 -1
  85. package/dist/indexer/extractors/rust.js +139 -2
  86. package/dist/indexer/extractors/rust.js.map +1 -1
  87. package/dist/indexer/extractors/scala.d.ts.map +1 -1
  88. package/dist/indexer/extractors/scala.js +24 -1
  89. package/dist/indexer/extractors/scala.js.map +1 -1
  90. package/dist/indexer/extractors/swift.d.ts.map +1 -1
  91. package/dist/indexer/extractors/swift.js +129 -1
  92. package/dist/indexer/extractors/swift.js.map +1 -1
  93. package/dist/indexer/extractors/types.d.ts +78 -2
  94. package/dist/indexer/extractors/types.d.ts.map +1 -1
  95. package/dist/indexer/extractors/types.js +167 -8
  96. package/dist/indexer/extractors/types.js.map +1 -1
  97. package/dist/indexer/extractors/typescript.d.ts.map +1 -1
  98. package/dist/indexer/extractors/typescript.js +217 -1
  99. package/dist/indexer/extractors/typescript.js.map +1 -1
  100. package/dist/indexer/extractors/zig.d.ts.map +1 -1
  101. package/dist/indexer/extractors/zig.js +30 -0
  102. package/dist/indexer/extractors/zig.js.map +1 -1
  103. package/dist/indexer/git-history.d.ts.map +1 -1
  104. package/dist/indexer/git-history.js +4 -8
  105. package/dist/indexer/git-history.js.map +1 -1
  106. package/dist/indexer/git-hooks.js +1 -1
  107. package/dist/indexer/git-hooks.js.map +1 -1
  108. package/dist/indexer/index.d.ts +27 -52
  109. package/dist/indexer/index.d.ts.map +1 -1
  110. package/dist/indexer/index.js +146 -773
  111. package/dist/indexer/index.js.map +1 -1
  112. package/dist/indexer/lsp/client.d.ts.map +1 -1
  113. package/dist/indexer/lsp/client.js +40 -15
  114. package/dist/indexer/lsp/client.js.map +1 -1
  115. package/dist/indexer/lsp/config.d.ts.map +1 -1
  116. package/dist/indexer/lsp/config.js +18 -4
  117. package/dist/indexer/lsp/config.js.map +1 -1
  118. package/dist/indexer/lsp/enrichment.d.ts +2 -0
  119. package/dist/indexer/lsp/enrichment.d.ts.map +1 -1
  120. package/dist/indexer/lsp/enrichment.js +67 -33
  121. package/dist/indexer/lsp/enrichment.js.map +1 -1
  122. package/dist/indexer/pipeline.d.ts +137 -0
  123. package/dist/indexer/pipeline.d.ts.map +1 -0
  124. package/dist/indexer/pipeline.js +84 -0
  125. package/dist/indexer/pipeline.js.map +1 -0
  126. package/dist/indexer/poller.d.ts +8 -0
  127. package/dist/indexer/poller.d.ts.map +1 -1
  128. package/dist/indexer/poller.js +3 -1
  129. package/dist/indexer/poller.js.map +1 -1
  130. package/dist/indexer/resolution-method.d.ts +40 -0
  131. package/dist/indexer/resolution-method.d.ts.map +1 -0
  132. package/dist/indexer/resolution-method.js +53 -0
  133. package/dist/indexer/resolution-method.js.map +1 -0
  134. package/dist/indexer/resolver.d.ts.map +1 -1
  135. package/dist/indexer/resolver.js +8 -4
  136. package/dist/indexer/resolver.js.map +1 -1
  137. package/dist/indexer/stages/dependency-api.d.ts +18 -0
  138. package/dist/indexer/stages/dependency-api.d.ts.map +1 -0
  139. package/dist/indexer/stages/dependency-api.js +174 -0
  140. package/dist/indexer/stages/dependency-api.js.map +1 -0
  141. package/dist/indexer/stages/docs-index.d.ts +20 -0
  142. package/dist/indexer/stages/docs-index.d.ts.map +1 -0
  143. package/dist/indexer/stages/docs-index.js +144 -0
  144. package/dist/indexer/stages/docs-index.js.map +1 -0
  145. package/dist/indexer/stages/embedding.d.ts +17 -0
  146. package/dist/indexer/stages/embedding.d.ts.map +1 -0
  147. package/dist/indexer/stages/embedding.js +217 -0
  148. package/dist/indexer/stages/embedding.js.map +1 -0
  149. package/dist/indexer/stages/import-resolution.d.ts +17 -0
  150. package/dist/indexer/stages/import-resolution.d.ts.map +1 -0
  151. package/dist/indexer/stages/import-resolution.js +47 -0
  152. package/dist/indexer/stages/import-resolution.js.map +1 -0
  153. package/dist/indexer/stages/index.d.ts +12 -0
  154. package/dist/indexer/stages/index.d.ts.map +1 -0
  155. package/dist/indexer/stages/index.js +12 -0
  156. package/dist/indexer/stages/index.js.map +1 -0
  157. package/dist/indexer/stages/lsp-enrichment.d.ts +48 -0
  158. package/dist/indexer/stages/lsp-enrichment.d.ts.map +1 -0
  159. package/dist/indexer/stages/lsp-enrichment.js +158 -0
  160. package/dist/indexer/stages/lsp-enrichment.js.map +1 -0
  161. package/dist/indexer/stages/source-index.d.ts +31 -0
  162. package/dist/indexer/stages/source-index.d.ts.map +1 -0
  163. package/dist/indexer/stages/source-index.js +314 -0
  164. package/dist/indexer/stages/source-index.js.map +1 -0
  165. package/dist/indexer/watcher.d.ts +8 -0
  166. package/dist/indexer/watcher.d.ts.map +1 -1
  167. package/dist/indexer/watcher.js +18 -1
  168. package/dist/indexer/watcher.js.map +1 -1
  169. package/dist/lore-server/db.d.ts +51 -4
  170. package/dist/lore-server/db.d.ts.map +1 -1
  171. package/dist/lore-server/db.js +102 -93
  172. package/dist/lore-server/db.js.map +1 -1
  173. package/dist/lore-server/server.d.ts +5 -0
  174. package/dist/lore-server/server.d.ts.map +1 -1
  175. package/dist/lore-server/server.js +52 -273
  176. package/dist/lore-server/server.js.map +1 -1
  177. package/dist/lore-server/tool-registry.d.ts +101 -0
  178. package/dist/lore-server/tool-registry.d.ts.map +1 -0
  179. package/dist/lore-server/tool-registry.js +227 -0
  180. package/dist/lore-server/tool-registry.js.map +1 -0
  181. package/dist/lore-server/tools/graph.d.ts +11 -3
  182. package/dist/lore-server/tools/graph.d.ts.map +1 -1
  183. package/dist/lore-server/tools/graph.js +108 -13
  184. package/dist/lore-server/tools/graph.js.map +1 -1
  185. package/dist/lore-server/tools/lookup.d.ts +9 -3
  186. package/dist/lore-server/tools/lookup.d.ts.map +1 -1
  187. package/dist/lore-server/tools/lookup.js +9 -4
  188. package/dist/lore-server/tools/lookup.js.map +1 -1
  189. package/dist/lore-server/tools/notes.d.ts.map +1 -1
  190. package/dist/lore-server/tools/notes.js +6 -2
  191. package/dist/lore-server/tools/notes.js.map +1 -1
  192. package/dist/lore-server/tools/search.d.ts +4 -0
  193. package/dist/lore-server/tools/search.d.ts.map +1 -1
  194. package/dist/lore-server/tools/search.js +50 -14
  195. package/dist/lore-server/tools/search.js.map +1 -1
  196. package/dist/runtime.d.ts +88 -0
  197. package/dist/runtime.d.ts.map +1 -0
  198. package/dist/runtime.js +153 -0
  199. package/dist/runtime.js.map +1 -0
  200. package/package.json +12 -12
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @module indexer/stages/import-resolution
3
+ *
4
+ * Pipeline stage: resolve raw import strings to file IDs (internal) or
5
+ * external package names. Populates `file_imports.resolved_id` and
6
+ * `external_deps` rows.
7
+ */
8
+ import { ImportResolver } from '../resolver.js';
9
+ // ─── Stage ────────────────────────────────────────────────────────────────────
10
+ /**
11
+ * Resolves raw imports in `file_imports` to internal file IDs (`resolved_id`)
12
+ * or external package names (`external_deps`).
13
+ */
14
+ export class ImportResolutionStage {
15
+ name = 'import-resolution';
16
+ async execute(context, _mode) {
17
+ const { db, branch, walkerConfig } = context;
18
+ const rootDir = walkerConfig.rootDir;
19
+ const resolver = new ImportResolver();
20
+ // Fetch all unresolved imports with their file's path, language, and file_id
21
+ const rows = db
22
+ .prepare(`SELECT fi.id, fi.file_id, fi.raw_import, f.path, f.language
23
+ FROM file_imports fi
24
+ JOIN files f ON f.id = fi.file_id
25
+ WHERE fi.resolved_id IS NULL AND f.branch = ?`)
26
+ .all(branch);
27
+ // P5: Build a bulk path→id map so we don't do N individual SELECT lookups.
28
+ const fileIdByPath = new Map(db.prepare('SELECT id, path FROM files WHERE branch = ?').all(branch)
29
+ .map(r => [r.path, r.id]));
30
+ const updateResolved = db.prepare('UPDATE file_imports SET resolved_id = ? WHERE id = ?');
31
+ const insertExternalDep = db.prepare('INSERT OR IGNORE INTO external_deps (file_id, package) VALUES (?, ?)');
32
+ for (const row of rows) {
33
+ const resolved = resolver.resolve({ source: row.raw_import, importedNames: [] }, row.path, rootDir, row.language);
34
+ if (resolved.resolvedPath) {
35
+ const targetId = fileIdByPath.get(resolved.resolvedPath);
36
+ if (targetId !== undefined) {
37
+ updateResolved.run(targetId, row.id);
38
+ }
39
+ }
40
+ else if (resolved.isExternal && resolved.externalName) {
41
+ insertExternalDep.run(row.file_id, resolved.externalName);
42
+ }
43
+ }
44
+ context.log.indexing('imports resolved', { totalUnresolved: rows.length });
45
+ }
46
+ }
47
+ //# sourceMappingURL=import-resolution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-resolution.js","sourceRoot":"","sources":["../../../src/indexer/stages/import-resolution.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,iFAAiF;AAEjF;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IACvB,IAAI,GAAG,mBAAmB,CAAC;IAEpC,KAAK,CAAC,OAAO,CAAC,OAAwB,EAAE,KAAyB;QAC/D,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;QAC7C,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;QAEtC,6EAA6E;QAC7E,MAAM,IAAI,GAAG,EAAE;aACZ,OAAO,CACN;;;uDAG+C,CAChD;aACA,GAAG,CAAC,MAAM,CAMT,CAAC;QAEL,2EAA2E;QAC3E,MAAM,YAAY,GAAG,IAAI,GAAG,CACzB,EAAE,CAAC,OAAO,CAAC,6CAA6C,CAAC,CAAC,GAAG,CAAC,MAAM,CAAyC;aAC3G,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAC5B,CAAC;QAEF,MAAM,cAAc,GAAG,EAAE,CAAC,OAAO,CAC/B,sDAAsD,CACvD,CAAC;QACF,MAAM,iBAAiB,GAAG,EAAE,CAAC,OAAO,CAClC,sEAAsE,CACvE,CAAC;QAEF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAC/B,EAAE,MAAM,EAAE,GAAG,CAAC,UAAU,EAAE,aAAa,EAAE,EAAE,EAAE,EAC7C,GAAG,CAAC,IAAI,EACR,OAAO,EACP,GAAG,CAAC,QAAQ,CACb,CAAC;YAEF,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;gBACzD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,cAAc,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBACvC,CAAC;YACH,CAAC;iBAAM,IAAI,QAAQ,CAAC,UAAU,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACxD,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,kBAAkB,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7E,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @module indexer/stages
3
+ *
4
+ * Concrete pipeline stages with real implementations.
5
+ */
6
+ export { SourceIndexStage } from './source-index.js';
7
+ export { DocsIndexStage } from './docs-index.js';
8
+ export { ImportResolutionStage } from './import-resolution.js';
9
+ export { DependencyApiStage } from './dependency-api.js';
10
+ export { LspEnrichmentStage } from './lsp-enrichment.js';
11
+ export { EmbeddingStage } from './embedding.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/indexer/stages/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @module indexer/stages
3
+ *
4
+ * Concrete pipeline stages with real implementations.
5
+ */
6
+ export { SourceIndexStage } from './source-index.js';
7
+ export { DocsIndexStage } from './docs-index.js';
8
+ export { ImportResolutionStage } from './import-resolution.js';
9
+ export { DependencyApiStage } from './dependency-api.js';
10
+ export { LspEnrichmentStage } from './lsp-enrichment.js';
11
+ export { EmbeddingStage } from './embedding.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/indexer/stages/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @module indexer/stages/lsp-enrichment
3
+ *
4
+ * Pipeline stage: enrich symbols, symbol_refs, type_refs, and
5
+ * symbol_relationships with LSP-derived metadata (definition_path,
6
+ * definition_line, resolved_type_signature, etc.).
7
+ *
8
+ * ## Data written
9
+ *
10
+ * - `symbols.resolved_type_signature`, `resolved_return_type`,
11
+ * `definition_uri`, `definition_path`
12
+ * - `symbol_refs.resolved_type_signature`, `resolved_return_type`,
13
+ * `definition_uri`, `definition_path`, `definition_line`, `definition_character`
14
+ * - `type_refs.resolved_type_signature`, `definition_uri`,
15
+ * `definition_path`, `definition_line`, `definition_character`
16
+ * - `symbol_relationships.definition_uri`, `definition_path`,
17
+ * `definition_line`, `definition_character`
18
+ *
19
+ * ## Data dependency
20
+ *
21
+ * **Must run before `ResolutionStage`.** The resolution stage reads
22
+ * `definition_path` / `definition_line` columns populated here to perform
23
+ * LSP-based containment resolution.
24
+ */
25
+ import type { PipelineContext, PipelineStage } from '../pipeline.js';
26
+ import type { Database } from '../db.js';
27
+ import { LspEnrichmentCoordinator } from '../lsp/enrichment.js';
28
+ /**
29
+ * Enriches indexed artefacts with LSP-derived metadata.
30
+ *
31
+ * Manages the lifecycle of an `LspEnrichmentCoordinator` per pipeline run.
32
+ * The coordinator is started during `execute()` and disposed in `dispose()`.
33
+ */
34
+ export declare class LspEnrichmentStage implements PipelineStage {
35
+ readonly name = "lsp-enrichment";
36
+ private coordinator;
37
+ execute(context: PipelineContext, _mode: 'build' | 'update'): Promise<void>;
38
+ dispose(): Promise<void>;
39
+ }
40
+ /**
41
+ * Enrich symbols, call refs, type refs, and relationships for every file in
42
+ * the context with LSP-derived metadata.
43
+ */
44
+ export declare function enrichProjectRefs(db: Database.Database, branch: string, files: Array<{
45
+ path: string;
46
+ language: string;
47
+ }>, coordinator: LspEnrichmentCoordinator): Promise<void>;
48
+ //# sourceMappingURL=lsp-enrichment.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsp-enrichment.d.ts","sourceRoot":"","sources":["../../../src/indexer/stages/lsp-enrichment.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAGhE;;;;;GAKG;AACH,qBAAa,kBAAmB,YAAW,aAAa;IACtD,QAAQ,CAAC,IAAI,oBAAoB;IAEjC,OAAO,CAAC,WAAW,CAAyC;IAEtD,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAa3E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAM/B;AAID;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,EAChD,WAAW,EAAE,wBAAwB,GACpC,OAAO,CAAC,IAAI,CAAC,CAiLf"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * @module indexer/stages/lsp-enrichment
3
+ *
4
+ * Pipeline stage: enrich symbols, symbol_refs, type_refs, and
5
+ * symbol_relationships with LSP-derived metadata (definition_path,
6
+ * definition_line, resolved_type_signature, etc.).
7
+ *
8
+ * ## Data written
9
+ *
10
+ * - `symbols.resolved_type_signature`, `resolved_return_type`,
11
+ * `definition_uri`, `definition_path`
12
+ * - `symbol_refs.resolved_type_signature`, `resolved_return_type`,
13
+ * `definition_uri`, `definition_path`, `definition_line`, `definition_character`
14
+ * - `type_refs.resolved_type_signature`, `definition_uri`,
15
+ * `definition_path`, `definition_line`, `definition_character`
16
+ * - `symbol_relationships.definition_uri`, `definition_path`,
17
+ * `definition_line`, `definition_character`
18
+ *
19
+ * ## Data dependency
20
+ *
21
+ * **Must run before `ResolutionStage`.** The resolution stage reads
22
+ * `definition_path` / `definition_line` columns populated here to perform
23
+ * LSP-based containment resolution.
24
+ */
25
+ import * as fs from 'node:fs';
26
+ import { LspEnrichmentCoordinator } from '../lsp/enrichment.js';
27
+ import { buildStructuralEmbeddingText } from '../embedder.js';
28
+ /**
29
+ * Enriches indexed artefacts with LSP-derived metadata.
30
+ *
31
+ * Manages the lifecycle of an `LspEnrichmentCoordinator` per pipeline run.
32
+ * The coordinator is started during `execute()` and disposed in `dispose()`.
33
+ */
34
+ export class LspEnrichmentStage {
35
+ name = 'lsp-enrichment';
36
+ coordinator = null;
37
+ async execute(context, _mode) {
38
+ if (!context.lsp?.enabled || context.files.length === 0)
39
+ return;
40
+ this.coordinator = new LspEnrichmentCoordinator(context.lsp, context.walkerConfig.rootDir);
41
+ // Start language servers for all languages seen in the file list.
42
+ const languages = new Set(context.files.map(f => f.language));
43
+ if (context.indexDependencies)
44
+ languages.add('typescript');
45
+ await this.coordinator.start(languages);
46
+ await enrichProjectRefs(context.db, context.branch, context.files, this.coordinator);
47
+ }
48
+ async dispose() {
49
+ if (this.coordinator) {
50
+ await this.coordinator.dispose();
51
+ this.coordinator = null;
52
+ }
53
+ }
54
+ }
55
+ // ─── Enrichment logic ─────────────────────────────────────────────────────────────────
56
+ /**
57
+ * Enrich symbols, call refs, type refs, and relationships for every file in
58
+ * the context with LSP-derived metadata.
59
+ */
60
+ export async function enrichProjectRefs(db, branch, files, coordinator) {
61
+ const selectSymbols = db.prepare(`SELECT s.id, s.name, s.signature, s.start_line
62
+ FROM symbols s
63
+ JOIN files f ON f.id = s.file_id
64
+ WHERE f.path = ? AND f.branch = ?
65
+ ORDER BY s.id`);
66
+ const selectCallRefs = db.prepare(`SELECT sr.id, sr.call_line, sr.call_character
67
+ FROM symbol_refs sr
68
+ JOIN symbols s ON s.id = sr.caller_id
69
+ JOIN files f ON f.id = s.file_id
70
+ WHERE f.path = ? AND f.branch = ?
71
+ ORDER BY sr.id`);
72
+ const selectTypeRefs = db.prepare(`SELECT tr.id, tr.ref_line, tr.ref_character
73
+ FROM type_refs tr
74
+ JOIN files f ON f.id = tr.file_id
75
+ WHERE f.path = ? AND f.branch = ?
76
+ ORDER BY tr.id`);
77
+ const selectRelationships = db.prepare(`SELECT sr.id, sr.line, sr.character
78
+ FROM symbol_relationships sr
79
+ JOIN files f ON f.id = sr.file_id
80
+ WHERE f.path = ? AND f.branch = ? AND sr.line IS NOT NULL
81
+ ORDER BY sr.id`);
82
+ const updateSymbol = db.prepare(`UPDATE symbols
83
+ SET resolved_type_signature = ?, resolved_return_type = ?, definition_uri = ?, definition_path = ?
84
+ WHERE id = ?`);
85
+ const updateSymbolFts = db.prepare('UPDATE symbols_fts SET signature = ? WHERE rowid = ?');
86
+ const updateCallRef = db.prepare(`UPDATE symbol_refs
87
+ SET resolved_type_signature = ?, resolved_return_type = ?, definition_uri = ?, definition_path = ?, definition_line = ?, definition_character = ?
88
+ WHERE id = ?`);
89
+ const updateTypeRef = db.prepare(`UPDATE type_refs
90
+ SET resolved_type_signature = ?, definition_uri = ?, definition_path = ?, definition_line = ?, definition_character = ?
91
+ WHERE id = ?`);
92
+ const updateRelationship = db.prepare(`UPDATE symbol_relationships
93
+ SET definition_uri = ?, definition_path = ?, definition_line = ?, definition_character = ?
94
+ WHERE id = ?`);
95
+ for (const file of files) {
96
+ if (!file || !fs.existsSync(file.path))
97
+ continue;
98
+ let source;
99
+ try {
100
+ source = fs.readFileSync(file.path, 'utf8');
101
+ }
102
+ catch {
103
+ continue;
104
+ }
105
+ const tagged = [];
106
+ const symbols = selectSymbols.all(file.path, branch);
107
+ for (const s of symbols) {
108
+ tagged.push({ table: 'symbol', rowId: s.id, line: s.start_line, character: 0, name: s.name, signature: s.signature });
109
+ }
110
+ const callRefs = selectCallRefs.all(file.path, branch);
111
+ for (const cr of callRefs) {
112
+ tagged.push({ table: 'callRef', rowId: cr.id, line: cr.call_line, character: cr.call_character ?? 0 });
113
+ }
114
+ const typeRefs = selectTypeRefs.all(file.path, branch);
115
+ for (const tr of typeRefs) {
116
+ tagged.push({ table: 'typeRef', rowId: tr.id, line: tr.ref_line, character: tr.ref_character ?? 0 });
117
+ }
118
+ const relationships = selectRelationships.all(file.path, branch);
119
+ for (const r of relationships) {
120
+ tagged.push({ table: 'relationship', rowId: r.id, line: r.line, character: r.character ?? 0 });
121
+ }
122
+ if (tagged.length === 0)
123
+ continue;
124
+ const metadata = await coordinator.enrich({
125
+ filePath: file.path,
126
+ language: file.language,
127
+ source,
128
+ targets: tagged.map(t => ({ line: t.line, character: t.character })),
129
+ });
130
+ for (let i = 0; i < tagged.length; i++) {
131
+ const tag = tagged[i];
132
+ const m = metadata[i];
133
+ if (!m)
134
+ continue;
135
+ switch (tag.table) {
136
+ case 'symbol':
137
+ updateSymbol.run(m.resolvedTypeSignature, m.resolvedReturnType, m.definitionUri, m.definitionPath, tag.rowId);
138
+ updateSymbolFts.run(buildStructuralEmbeddingText({
139
+ name: tag.name,
140
+ signature: tag.signature ?? null,
141
+ resolvedTypeSignature: m.resolvedTypeSignature,
142
+ resolvedReturnType: m.resolvedReturnType,
143
+ }), tag.rowId);
144
+ break;
145
+ case 'callRef':
146
+ updateCallRef.run(m.resolvedTypeSignature, m.resolvedReturnType, m.definitionUri, m.definitionPath, m.definitionLine, m.definitionCharacter, tag.rowId);
147
+ break;
148
+ case 'typeRef':
149
+ updateTypeRef.run(m.resolvedTypeSignature, m.definitionUri, m.definitionPath, m.definitionLine, m.definitionCharacter, tag.rowId);
150
+ break;
151
+ case 'relationship':
152
+ updateRelationship.run(m.definitionUri, m.definitionPath, m.definitionLine, m.definitionCharacter, tag.rowId);
153
+ break;
154
+ }
155
+ }
156
+ }
157
+ }
158
+ //# sourceMappingURL=lsp-enrichment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lsp-enrichment.js","sourceRoot":"","sources":["../../../src/indexer/stages/lsp-enrichment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @module indexer/stages/source-index
3
+ *
4
+ * Pipeline stage: walk, parse, extract, and insert symbols/imports/callRefs/
5
+ * typeRefs/relationships/routes/annotations for all source files.
6
+ *
7
+ * This is the first stage in the pipeline and populates `context.files`.
8
+ */
9
+ import type { PipelineContext, PipelineStage } from '../pipeline.js';
10
+ import type { Database } from '../db.js';
11
+ import { ParserPool } from '../parser.js';
12
+ /**
13
+ * Walk source files, parse with tree-sitter, extract symbols/imports/callRefs/
14
+ * typeRefs/relationships/routes/annotations, and persist to the database.
15
+ *
16
+ * Populates `context.files` for use by later stages.
17
+ */
18
+ export declare class SourceIndexStage implements PipelineStage {
19
+ readonly name = "source-index";
20
+ private pool;
21
+ execute(context: PipelineContext, mode: 'build' | 'update'): Promise<void>;
22
+ dispose(): Promise<void>;
23
+ private processBuild;
24
+ private processUpdate;
25
+ }
26
+ /**
27
+ * Parse one file, extract symbols/imports/callRefs/typeRefs/relationships/
28
+ * routes/annotations, and insert into the DB.
29
+ */
30
+ export declare function processFile(db: Database.Database, pool: ParserPool, filePath: string, language: string, branch: string): void;
31
+ //# sourceMappingURL=source-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-index.d.ts","sourceRoot":"","sources":["../../../src/indexer/stages/source-index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAOzC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAgF1C;;;;;GAKG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IACpD,QAAQ,CAAC,IAAI,kBAAkB;IAE/B,OAAO,CAAC,IAAI,CAA2B;IAEjC,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB1E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAMhB,YAAY;YA0BZ,aAAa;CAiD5B;AAID;;;GAGG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,IAAI,CAmCN"}
@@ -0,0 +1,314 @@
1
+ /**
2
+ * @module indexer/stages/source-index
3
+ *
4
+ * Pipeline stage: walk, parse, extract, and insert symbols/imports/callRefs/
5
+ * typeRefs/relationships/routes/annotations for all source files.
6
+ *
7
+ * This is the first stage in the pipeline and populates `context.files`.
8
+ */
9
+ import * as fs from 'node:fs';
10
+ import * as crypto from 'node:crypto';
11
+ import { setLoreMeta, getLoreMeta, LORE_META_INDEX_CHECKPOINT, } from '../db.js';
12
+ import { walkFiles, detectLanguageForPath } from '../walker.js';
13
+ import { ParserPool } from '../parser.js';
14
+ import { buildStructuralEmbeddingText } from '../embedder.js';
15
+ import { normalizeTypeName } from '../call-graph.js';
16
+ import { CExtractor } from '../extractors/c.js';
17
+ import { RustExtractor } from '../extractors/rust.js';
18
+ import { PythonExtractor } from '../extractors/python.js';
19
+ import { CppExtractor } from '../extractors/cpp.js';
20
+ import { TypeScriptExtractor } from '../extractors/typescript.js';
21
+ import { JavaScriptExtractor } from '../extractors/javascript.js';
22
+ import { GoExtractor } from '../extractors/go.js';
23
+ import { JavaExtractor } from '../extractors/java.js';
24
+ import { CSharpExtractor } from '../extractors/csharp.js';
25
+ import { RubyExtractor } from '../extractors/ruby.js';
26
+ import { PhpExtractor } from '../extractors/php.js';
27
+ import { SwiftExtractor } from '../extractors/swift.js';
28
+ import { KotlinExtractor } from '../extractors/kotlin.js';
29
+ import { ScalaExtractor } from '../extractors/scala.js';
30
+ import { LuaExtractor } from '../extractors/lua.js';
31
+ import { BashExtractor } from '../extractors/bash.js';
32
+ import { ElixirExtractor } from '../extractors/elixir.js';
33
+ import { ZigExtractor } from '../extractors/zig.js';
34
+ import { DartExtractor } from '../extractors/dart.js';
35
+ import { OcamlExtractor } from '../extractors/ocaml.js';
36
+ import { HaskellExtractor } from '../extractors/haskell.js';
37
+ import { JuliaExtractor } from '../extractors/julia.js';
38
+ import { ElmExtractor } from '../extractors/elm.js';
39
+ import { ObjcExtractor } from '../extractors/objc.js';
40
+ // ─── Extractor registry ───────────────────────────────────────────────────────
41
+ const EXTRACTORS = {
42
+ c: new CExtractor(),
43
+ rust: new RustExtractor(),
44
+ python: new PythonExtractor(),
45
+ cpp: new CppExtractor(),
46
+ typescript: new TypeScriptExtractor(),
47
+ javascript: new JavaScriptExtractor(),
48
+ go: new GoExtractor(),
49
+ java: new JavaExtractor(),
50
+ csharp: new CSharpExtractor(),
51
+ ruby: new RubyExtractor(),
52
+ php: new PhpExtractor(),
53
+ swift: new SwiftExtractor(),
54
+ kotlin: new KotlinExtractor(),
55
+ scala: new ScalaExtractor(),
56
+ lua: new LuaExtractor(),
57
+ bash: new BashExtractor(),
58
+ elixir: new ElixirExtractor(),
59
+ zig: new ZigExtractor(),
60
+ dart: new DartExtractor(),
61
+ ocaml: new OcamlExtractor(),
62
+ haskell: new HaskellExtractor(),
63
+ julia: new JuliaExtractor(),
64
+ elm: new ElmExtractor(),
65
+ objc: new ObjcExtractor(),
66
+ };
67
+ // ─── Stage ────────────────────────────────────────────────────────────────────
68
+ /**
69
+ * Walk source files, parse with tree-sitter, extract symbols/imports/callRefs/
70
+ * typeRefs/relationships/routes/annotations, and persist to the database.
71
+ *
72
+ * Populates `context.files` for use by later stages.
73
+ */
74
+ export class SourceIndexStage {
75
+ name = 'source-index';
76
+ pool = null;
77
+ async execute(context, mode) {
78
+ this.pool = new ParserPool();
79
+ // Save docs auto-notes setting.
80
+ setLoreMeta(context.db, 'docs_auto_notes', context.docsAutoNotes ? '1' : '0');
81
+ if (mode === 'build') {
82
+ const files = await walkFiles(context.walkerConfig);
83
+ context.files = files;
84
+ context.log.indexing('walk complete', { fileCount: files.length });
85
+ await this.processBuild(context, files);
86
+ }
87
+ else {
88
+ await this.processUpdate(context);
89
+ }
90
+ }
91
+ async dispose() {
92
+ this.pool = null;
93
+ }
94
+ // ─── Build mode ──────────────────────────────────────────────────────────
95
+ async processBuild(context, files) {
96
+ const { db, branch } = context;
97
+ const pool = this.pool;
98
+ const resumeAt = loadBuildCheckpoint(db, branch, context.walkerConfig.rootDir, files.length);
99
+ if (resumeAt > 0) {
100
+ context.log.indexing('resuming from checkpoint', { resumeAt, totalFiles: files.length });
101
+ }
102
+ db.transaction(() => {
103
+ for (let i = resumeAt; i < files.length; i++) {
104
+ const file = files[i];
105
+ if (!file)
106
+ continue;
107
+ processFile(db, pool, file.path, file.language, branch);
108
+ saveBuildCheckpoint(db, branch, context.walkerConfig.rootDir, i + 1, files.length);
109
+ }
110
+ })();
111
+ saveBuildCheckpoint(db, branch, context.walkerConfig.rootDir, files.length, files.length);
112
+ }
113
+ // ─── Update mode ─────────────────────────────────────────────────────────
114
+ async processUpdate(context) {
115
+ const { db, branch, walkerConfig } = context;
116
+ const changedFiles = context.changedFiles ?? [];
117
+ const pool = this.pool;
118
+ const enrichedFiles = [];
119
+ db.transaction(() => {
120
+ for (const filePath of changedFiles) {
121
+ // If the file no longer exists, remove it from the DB
122
+ if (!fs.existsSync(filePath)) {
123
+ const row = db.prepare('SELECT id FROM files WHERE path = ? AND branch = ?').get(filePath, branch);
124
+ if (row) {
125
+ const symRows = db.prepare('SELECT id FROM symbols WHERE file_id = ?').all(row.id);
126
+ for (const s of symRows)
127
+ context.staleSymbolIds.push(s.id);
128
+ db.prepare('UPDATE file_imports SET resolved_id = NULL WHERE resolved_id = ?').run(row.id);
129
+ db.prepare('DELETE FROM symbols_fts WHERE rowid IN (SELECT id FROM symbols WHERE file_id = ?)').run(row.id);
130
+ db.prepare('DELETE FROM files WHERE id = ?').run(row.id);
131
+ }
132
+ continue;
133
+ }
134
+ const language = detectLanguageForPath(filePath, walkerConfig);
135
+ if (language) {
136
+ enrichedFiles.push({ path: filePath, language });
137
+ context.changedSourcePaths.push(filePath);
138
+ const existingRow = db.prepare('SELECT id FROM files WHERE path = ? AND branch = ?').get(filePath, branch);
139
+ if (existingRow) {
140
+ const symRows = db.prepare('SELECT id FROM symbols WHERE file_id = ?').all(existingRow.id);
141
+ for (const s of symRows)
142
+ context.staleSymbolIds.push(s.id);
143
+ db.prepare('UPDATE file_imports SET resolved_id = NULL WHERE resolved_id = ?').run(existingRow.id);
144
+ db.prepare('UPDATE symbol_refs SET callee_id = NULL WHERE callee_id IN (SELECT id FROM symbols WHERE file_id = ?)').run(existingRow.id);
145
+ db.prepare('UPDATE type_refs SET type_id = NULL WHERE type_id IN (SELECT id FROM symbols WHERE file_id = ?)').run(existingRow.id);
146
+ db.prepare('UPDATE symbol_relationships SET target_symbol_id = NULL WHERE target_symbol_id IN (SELECT id FROM symbols WHERE file_id = ?)').run(existingRow.id);
147
+ db.prepare('DELETE FROM symbols_fts WHERE rowid IN (SELECT id FROM symbols WHERE file_id = ?)').run(existingRow.id);
148
+ }
149
+ db.prepare('DELETE FROM files WHERE path = ? AND branch = ?').run(filePath, branch);
150
+ processFile(db, pool, filePath, language, branch);
151
+ }
152
+ }
153
+ })();
154
+ // In update mode, context.files = only the changed/enriched files
155
+ context.files = enrichedFiles;
156
+ }
157
+ }
158
+ // ─── File processing (extracted from IndexBuilder.processFile) ────────────────
159
+ /**
160
+ * Parse one file, extract symbols/imports/callRefs/typeRefs/relationships/
161
+ * routes/annotations, and insert into the DB.
162
+ */
163
+ export function processFile(db, pool, filePath, language, branch) {
164
+ // P3: fast-path — check file size via stat before reading+hashing.
165
+ const existing = db.prepare('SELECT id, last_hash, size_bytes FROM files WHERE path = ? AND branch = ?').get(filePath, branch);
166
+ if (existing) {
167
+ try {
168
+ const stat = fs.statSync(filePath);
169
+ if (stat.size === existing.size_bytes && existing.last_hash !== null) {
170
+ // Size matches — read and hash to confirm.
171
+ let source;
172
+ try {
173
+ source = fs.readFileSync(filePath, 'utf8');
174
+ }
175
+ catch {
176
+ return;
177
+ }
178
+ const hash = crypto.createHash('sha256').update(source).digest('hex');
179
+ if (existing.last_hash === hash)
180
+ return;
181
+ processFileWithSource(db, pool, filePath, language, branch, source, hash, existing);
182
+ return;
183
+ }
184
+ }
185
+ catch {
186
+ return;
187
+ }
188
+ }
189
+ let source;
190
+ try {
191
+ source = fs.readFileSync(filePath, 'utf8');
192
+ }
193
+ catch {
194
+ return;
195
+ }
196
+ const hash = crypto.createHash('sha256').update(source).digest('hex');
197
+ if (existing?.last_hash === hash)
198
+ return;
199
+ processFileWithSource(db, pool, filePath, language, branch, source, hash, existing);
200
+ }
201
+ /** Core file processing after source has been read and hashed. */
202
+ function processFileWithSource(db, pool, filePath, language, branch, source, hash, existing) {
203
+ const sizeBytes = Buffer.byteLength(source, 'utf8');
204
+ // Upsert the file row
205
+ let fileId;
206
+ if (existing) {
207
+ db.prepare(`UPDATE files SET language = ?, size_bytes = ?, last_hash = ?, source = ?, indexed_at = unixepoch()
208
+ WHERE id = ?`).run(language, sizeBytes, hash, source, existing.id);
209
+ fileId = existing.id;
210
+ // Remove stale symbols / imports / external deps (also clean up FTS5 index)
211
+ db.prepare('DELETE FROM symbols_fts WHERE rowid IN (SELECT id FROM symbols WHERE file_id = ?)').run(fileId);
212
+ db.prepare('DELETE FROM symbol_relationships WHERE file_id = ?').run(fileId);
213
+ db.prepare('DELETE FROM type_refs WHERE file_id = ?').run(fileId);
214
+ // NULL out cross-file FK references that point to symbols in this file
215
+ db.prepare('UPDATE symbol_refs SET callee_id = NULL WHERE callee_id IN (SELECT id FROM symbols WHERE file_id = ?)').run(fileId);
216
+ db.prepare('UPDATE type_refs SET type_id = NULL WHERE type_id IN (SELECT id FROM symbols WHERE file_id = ?)').run(fileId);
217
+ db.prepare('UPDATE symbol_relationships SET target_symbol_id = NULL WHERE target_symbol_id IN (SELECT id FROM symbols WHERE file_id = ?)').run(fileId);
218
+ db.prepare('DELETE FROM symbols WHERE file_id = ?').run(fileId);
219
+ db.prepare('DELETE FROM file_imports WHERE file_id = ?').run(fileId);
220
+ db.prepare('DELETE FROM external_deps WHERE file_id = ?').run(fileId);
221
+ db.prepare('DELETE FROM api_routes WHERE file_id = ?').run(fileId);
222
+ db.prepare('DELETE FROM annotations WHERE file_id = ?').run(fileId);
223
+ }
224
+ else {
225
+ const info = db
226
+ .prepare(`INSERT INTO files (path, branch, language, size_bytes, last_hash, source)
227
+ VALUES (?, ?, ?, ?, ?, ?)`)
228
+ .run(filePath, branch, language, sizeBytes, hash, source);
229
+ fileId = Number(info.lastInsertRowid);
230
+ }
231
+ // Parse the source
232
+ const tree = pool.parse(language, source);
233
+ if (!tree)
234
+ return;
235
+ const extractor = EXTRACTORS[language];
236
+ if (!extractor)
237
+ return;
238
+ const result = extractor.extract(tree, source, filePath);
239
+ // Insert symbols and keep FTS5 index in sync
240
+ const insertSymbol = db.prepare(`INSERT INTO symbols (file_id, name, kind, start_line, end_line, signature, doc_comment)
241
+ VALUES (?, ?, ?, ?, ?, ?, ?)`);
242
+ const insertFts = db.prepare('INSERT INTO symbols_fts(rowid, name, signature, kind) VALUES (?, ?, ?, ?)');
243
+ const symbolIdMap = new Map();
244
+ for (const sym of result.symbols) {
245
+ const info = insertSymbol.run(fileId, sym.name, sym.kind, sym.startLine, sym.endLine, sym.signature ?? null, sym.docComment ?? null);
246
+ const symId = Number(info.lastInsertRowid);
247
+ symbolIdMap.set(sym.name, symId);
248
+ insertFts.run(symId, sym.name, buildStructuralEmbeddingText({
249
+ name: sym.name,
250
+ signature: sym.signature ?? null,
251
+ }), sym.kind);
252
+ }
253
+ // Insert API routes
254
+ const insertRoute = db.prepare(`INSERT INTO api_routes (file_id, method, path, handler_id, handler_name, framework, line, middleware)
255
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);
256
+ for (const route of result.routes) {
257
+ insertRoute.run(fileId, route.method, route.path, symbolIdMap.get(route.handler) ?? null, route.handler, route.framework, route.line, route.middleware ? JSON.stringify(route.middleware) : null);
258
+ }
259
+ // Insert raw imports
260
+ const insertImport = db.prepare('INSERT INTO file_imports (file_id, raw_import) VALUES (?, ?)');
261
+ for (const imp of result.imports) {
262
+ insertImport.run(fileId, imp.source);
263
+ }
264
+ // Insert call refs
265
+ const insertCallRef = db.prepare(`INSERT INTO symbol_refs (caller_id, file_id, callee_name, call_line, call_character, call_kind)
266
+ VALUES (?, ?, ?, ?, ?, ?)`);
267
+ for (const ref of result.callRefs) {
268
+ const callerId = symbolIdMap.get(ref.callerSymbol);
269
+ if (callerId !== undefined) {
270
+ insertCallRef.run(callerId, fileId, ref.calleeRaw, ref.line, ref.character ?? null, ref.callKind ?? 'direct');
271
+ }
272
+ }
273
+ // Insert relationships
274
+ const insertRelationship = db.prepare(`INSERT INTO symbol_relationships (file_id, source_symbol_id, target_symbol_name, relationship_type, line, character)
275
+ VALUES (?, ?, ?, ?, ?, ?)`);
276
+ for (const rel of result.relationships) {
277
+ const sourceId = symbolIdMap.get(rel.fromSymbol) ?? null;
278
+ insertRelationship.run(fileId, sourceId, rel.toSymbol, rel.kind, rel.line, rel.character ?? null);
279
+ }
280
+ // Insert type refs
281
+ const insertTypeRef = db.prepare(`INSERT INTO type_refs (file_id, symbol_id, type_name, type_name_bare, ref_kind, ref_line, ref_character)
282
+ VALUES (?, ?, ?, ?, ?, ?, ?)`);
283
+ for (const ref of result.typeRefs) {
284
+ const symId = symbolIdMap.get(ref.enclosingSymbol) ?? null;
285
+ insertTypeRef.run(fileId, symId, ref.typeRaw, normalizeTypeName(ref.typeRaw), ref.refKind, ref.line, ref.character ?? null);
286
+ }
287
+ }
288
+ // ─── Checkpoint helpers ───────────────────────────────────────────────────────
289
+ function loadBuildCheckpoint(db, branch, rootDir, totalFiles) {
290
+ const raw = getLoreMeta(db, LORE_META_INDEX_CHECKPOINT);
291
+ if (!raw)
292
+ return 0;
293
+ try {
294
+ const parsed = JSON.parse(raw);
295
+ if (parsed.branch !== branch || parsed.rootDir !== rootDir)
296
+ return 0;
297
+ const nextFileIndex = parsed.nextFileIndex ?? 0;
298
+ return Math.max(0, Math.min(totalFiles, nextFileIndex));
299
+ }
300
+ catch {
301
+ return 0;
302
+ }
303
+ }
304
+ function saveBuildCheckpoint(db, branch, rootDir, nextFileIndex, totalFiles) {
305
+ const checkpoint = {
306
+ branch,
307
+ rootDir,
308
+ totalFiles,
309
+ nextFileIndex,
310
+ updatedAt: Math.floor(Date.now() / 1000),
311
+ };
312
+ setLoreMeta(db, LORE_META_INDEX_CHECKPOINT, JSON.stringify(checkpoint));
313
+ }
314
+ //# sourceMappingURL=source-index.js.map