homegraph 1.1.3 → 1.4.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 (412) hide show
  1. package/README.md +43 -18
  2. package/dist/arkts/ohos-api-index.d.ts +15 -0
  3. package/dist/arkts/ohos-api-index.d.ts.map +1 -0
  4. package/dist/arkts/ohos-api-index.js +190 -0
  5. package/dist/arkts/ohos-api-index.js.map +1 -0
  6. package/dist/arkts/ohos-sdk-input.d.ts +36 -0
  7. package/dist/arkts/ohos-sdk-input.d.ts.map +1 -0
  8. package/dist/arkts/ohos-sdk-input.js +214 -0
  9. package/dist/arkts/ohos-sdk-input.js.map +1 -0
  10. package/dist/bin/command-supervision.d.ts +12 -0
  11. package/dist/bin/command-supervision.d.ts.map +1 -0
  12. package/dist/bin/command-supervision.js +86 -0
  13. package/dist/bin/command-supervision.js.map +1 -0
  14. package/dist/bin/homegraph.d.ts +1 -1
  15. package/dist/bin/homegraph.js +709 -168
  16. package/dist/bin/homegraph.js.map +1 -1
  17. package/dist/context/index.d.ts.map +1 -1
  18. package/dist/context/index.js +85 -0
  19. package/dist/context/index.js.map +1 -1
  20. package/dist/db/index.d.ts +84 -5
  21. package/dist/db/index.d.ts.map +1 -1
  22. package/dist/db/index.js +217 -14
  23. package/dist/db/index.js.map +1 -1
  24. package/dist/db/migrations.d.ts +1 -1
  25. package/dist/db/migrations.d.ts.map +1 -1
  26. package/dist/db/migrations.js +58 -1
  27. package/dist/db/migrations.js.map +1 -1
  28. package/dist/db/queries.d.ts +131 -2
  29. package/dist/db/queries.d.ts.map +1 -1
  30. package/dist/db/queries.js +473 -9
  31. package/dist/db/queries.js.map +1 -1
  32. package/dist/db/schema.sql +52 -1
  33. package/dist/db/wal-valve.d.ts +106 -0
  34. package/dist/db/wal-valve.d.ts.map +1 -0
  35. package/dist/db/wal-valve.js +208 -0
  36. package/dist/db/wal-valve.js.map +1 -0
  37. package/dist/directory.d.ts +36 -0
  38. package/dist/directory.d.ts.map +1 -1
  39. package/dist/directory.js +274 -0
  40. package/dist/directory.js.map +1 -1
  41. package/dist/extraction/arkts-batch-worker.d.ts +2 -0
  42. package/dist/extraction/arkts-batch-worker.d.ts.map +1 -0
  43. package/dist/extraction/arkts-batch-worker.js +28 -0
  44. package/dist/extraction/arkts-batch-worker.js.map +1 -0
  45. package/dist/extraction/cfml-extractor.d.ts +107 -0
  46. package/dist/extraction/cfml-extractor.d.ts.map +1 -0
  47. package/dist/extraction/cfml-extractor.js +494 -0
  48. package/dist/extraction/cfml-extractor.js.map +1 -0
  49. package/dist/extraction/context.d.ts +11 -0
  50. package/dist/extraction/context.d.ts.map +1 -1
  51. package/dist/extraction/context.js +20 -0
  52. package/dist/extraction/context.js.map +1 -1
  53. package/dist/extraction/grammars.d.ts +25 -1
  54. package/dist/extraction/grammars.d.ts.map +1 -1
  55. package/dist/extraction/grammars.js +177 -24
  56. package/dist/extraction/grammars.js.map +1 -1
  57. package/dist/extraction/index.d.ts +55 -2
  58. package/dist/extraction/index.d.ts.map +1 -1
  59. package/dist/extraction/index.js +923 -381
  60. package/dist/extraction/index.js.map +1 -1
  61. package/dist/extraction/languages/arkts-state-decorators.d.ts +13 -0
  62. package/dist/extraction/languages/arkts-state-decorators.d.ts.map +1 -0
  63. package/dist/extraction/languages/arkts-state-decorators.js +26 -0
  64. package/dist/extraction/languages/arkts-state-decorators.js.map +1 -0
  65. package/dist/extraction/languages/arkts-viewtree.d.ts +4 -2
  66. package/dist/extraction/languages/arkts-viewtree.d.ts.map +1 -1
  67. package/dist/extraction/languages/arkts-viewtree.js +21 -6
  68. package/dist/extraction/languages/arkts-viewtree.js.map +1 -1
  69. package/dist/extraction/languages/arkts.d.ts +98 -2
  70. package/dist/extraction/languages/arkts.d.ts.map +1 -1
  71. package/dist/extraction/languages/arkts.js +1290 -61
  72. package/dist/extraction/languages/arkts.js.map +1 -1
  73. package/dist/extraction/languages/c-cpp.d.ts +98 -0
  74. package/dist/extraction/languages/c-cpp.d.ts.map +1 -1
  75. package/dist/extraction/languages/c-cpp.js +563 -1
  76. package/dist/extraction/languages/c-cpp.js.map +1 -1
  77. package/dist/extraction/languages/cfquery.d.ts +12 -0
  78. package/dist/extraction/languages/cfquery.d.ts.map +1 -0
  79. package/dist/extraction/languages/cfquery.js +28 -0
  80. package/dist/extraction/languages/cfquery.js.map +1 -0
  81. package/dist/extraction/languages/cfscript.d.ts +3 -0
  82. package/dist/extraction/languages/cfscript.d.ts.map +1 -0
  83. package/dist/extraction/languages/cfscript.js +73 -0
  84. package/dist/extraction/languages/cfscript.js.map +1 -0
  85. package/dist/extraction/languages/cobol.d.ts +33 -0
  86. package/dist/extraction/languages/cobol.d.ts.map +1 -0
  87. package/dist/extraction/languages/cobol.js +499 -0
  88. package/dist/extraction/languages/cobol.js.map +1 -0
  89. package/dist/extraction/languages/erlang.d.ts +3 -0
  90. package/dist/extraction/languages/erlang.d.ts.map +1 -0
  91. package/dist/extraction/languages/erlang.js +350 -0
  92. package/dist/extraction/languages/erlang.js.map +1 -0
  93. package/dist/extraction/languages/index.d.ts.map +1 -1
  94. package/dist/extraction/languages/index.js +16 -0
  95. package/dist/extraction/languages/index.js.map +1 -1
  96. package/dist/extraction/languages/nix.d.ts +3 -0
  97. package/dist/extraction/languages/nix.d.ts.map +1 -0
  98. package/dist/extraction/languages/nix.js +294 -0
  99. package/dist/extraction/languages/nix.js.map +1 -0
  100. package/dist/extraction/languages/ohos-api-consumer.d.ts +34 -0
  101. package/dist/extraction/languages/ohos-api-consumer.d.ts.map +1 -0
  102. package/dist/extraction/languages/ohos-api-consumer.js +283 -0
  103. package/dist/extraction/languages/ohos-api-consumer.js.map +1 -0
  104. package/dist/extraction/languages/solidity.d.ts +3 -0
  105. package/dist/extraction/languages/solidity.d.ts.map +1 -0
  106. package/dist/extraction/languages/solidity.js +293 -0
  107. package/dist/extraction/languages/solidity.js.map +1 -0
  108. package/dist/extraction/languages/terraform.d.ts +3 -0
  109. package/dist/extraction/languages/terraform.d.ts.map +1 -0
  110. package/dist/extraction/languages/terraform.js +641 -0
  111. package/dist/extraction/languages/terraform.js.map +1 -0
  112. package/dist/extraction/languages/vbnet.d.ts +11 -0
  113. package/dist/extraction/languages/vbnet.d.ts.map +1 -0
  114. package/dist/extraction/languages/vbnet.js +141 -0
  115. package/dist/extraction/languages/vbnet.js.map +1 -0
  116. package/dist/extraction/mybatis-extractor.d.ts +30 -10
  117. package/dist/extraction/mybatis-extractor.d.ts.map +1 -1
  118. package/dist/extraction/mybatis-extractor.js +140 -38
  119. package/dist/extraction/mybatis-extractor.js.map +1 -1
  120. package/dist/extraction/parse-pool.d.ts +152 -0
  121. package/dist/extraction/parse-pool.d.ts.map +1 -0
  122. package/dist/extraction/parse-pool.js +387 -0
  123. package/dist/extraction/parse-pool.js.map +1 -0
  124. package/dist/extraction/parse-worker.js +9 -2
  125. package/dist/extraction/parse-worker.js.map +1 -1
  126. package/dist/extraction/tree-sitter-helpers.d.ts.map +1 -1
  127. package/dist/extraction/tree-sitter-helpers.js +1 -0
  128. package/dist/extraction/tree-sitter-helpers.js.map +1 -1
  129. package/dist/extraction/tree-sitter-types.d.ts +20 -1
  130. package/dist/extraction/tree-sitter-types.d.ts.map +1 -1
  131. package/dist/extraction/tree-sitter.d.ts +59 -0
  132. package/dist/extraction/tree-sitter.d.ts.map +1 -1
  133. package/dist/extraction/tree-sitter.js +952 -37
  134. package/dist/extraction/tree-sitter.js.map +1 -1
  135. package/dist/extraction/wasm/tree-sitter-arkts.wasm +0 -0
  136. package/dist/extraction/wasm/tree-sitter-cfml.wasm +0 -0
  137. package/dist/extraction/wasm/tree-sitter-cfquery.wasm +0 -0
  138. package/dist/extraction/wasm/tree-sitter-cfscript.wasm +0 -0
  139. package/dist/extraction/wasm/tree-sitter-cobol.wasm +0 -0
  140. package/dist/extraction/wasm/tree-sitter-erlang.wasm +0 -0
  141. package/dist/extraction/wasm/tree-sitter-nix.wasm +0 -0
  142. package/dist/extraction/wasm/tree-sitter-terraform.wasm +0 -0
  143. package/dist/extraction/wasm/tree-sitter-vbnet.wasm +0 -0
  144. package/dist/graph/traversal.d.ts.map +1 -1
  145. package/dist/graph/traversal.js +77 -18
  146. package/dist/graph/traversal.js.map +1 -1
  147. package/dist/index.d.ts +85 -2
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +426 -9
  150. package/dist/index.js.map +1 -1
  151. package/dist/installer/index.d.ts +42 -0
  152. package/dist/installer/index.d.ts.map +1 -1
  153. package/dist/installer/index.js +97 -2
  154. package/dist/installer/index.js.map +1 -1
  155. package/dist/mcp/daemon-paths.d.ts +30 -3
  156. package/dist/mcp/daemon-paths.d.ts.map +1 -1
  157. package/dist/mcp/daemon-paths.js +50 -10
  158. package/dist/mcp/daemon-paths.js.map +1 -1
  159. package/dist/mcp/daemon-registry.d.ts.map +1 -1
  160. package/dist/mcp/daemon-registry.js +7 -3
  161. package/dist/mcp/daemon-registry.js.map +1 -1
  162. package/dist/mcp/daemon.d.ts +73 -3
  163. package/dist/mcp/daemon.d.ts.map +1 -1
  164. package/dist/mcp/daemon.js +258 -40
  165. package/dist/mcp/daemon.js.map +1 -1
  166. package/dist/mcp/dynamic-boundaries.d.ts.map +1 -1
  167. package/dist/mcp/dynamic-boundaries.js +2 -1
  168. package/dist/mcp/dynamic-boundaries.js.map +1 -1
  169. package/dist/mcp/early-ppid.d.ts +26 -0
  170. package/dist/mcp/early-ppid.d.ts.map +1 -0
  171. package/dist/mcp/early-ppid.js +29 -0
  172. package/dist/mcp/early-ppid.js.map +1 -0
  173. package/dist/mcp/engine.d.ts +16 -0
  174. package/dist/mcp/engine.d.ts.map +1 -1
  175. package/dist/mcp/engine.js +100 -2
  176. package/dist/mcp/engine.js.map +1 -1
  177. package/dist/mcp/index.d.ts.map +1 -1
  178. package/dist/mcp/index.js +66 -49
  179. package/dist/mcp/index.js.map +1 -1
  180. package/dist/mcp/liveness-watchdog.d.ts +18 -1
  181. package/dist/mcp/liveness-watchdog.d.ts.map +1 -1
  182. package/dist/mcp/liveness-watchdog.js +73 -13
  183. package/dist/mcp/liveness-watchdog.js.map +1 -1
  184. package/dist/mcp/memory-budget.d.ts +30 -0
  185. package/dist/mcp/memory-budget.d.ts.map +1 -0
  186. package/dist/mcp/memory-budget.js +123 -0
  187. package/dist/mcp/memory-budget.js.map +1 -0
  188. package/dist/mcp/ppid-watchdog.d.ts +18 -0
  189. package/dist/mcp/ppid-watchdog.d.ts.map +1 -1
  190. package/dist/mcp/ppid-watchdog.js +37 -0
  191. package/dist/mcp/ppid-watchdog.js.map +1 -1
  192. package/dist/mcp/proxy.d.ts.map +1 -1
  193. package/dist/mcp/proxy.js +88 -4
  194. package/dist/mcp/proxy.js.map +1 -1
  195. package/dist/mcp/query-cache.d.ts +56 -0
  196. package/dist/mcp/query-cache.d.ts.map +1 -0
  197. package/dist/mcp/query-cache.js +261 -0
  198. package/dist/mcp/query-cache.js.map +1 -0
  199. package/dist/mcp/query-pool.d.ts +128 -0
  200. package/dist/mcp/query-pool.d.ts.map +1 -0
  201. package/dist/mcp/query-pool.js +374 -0
  202. package/dist/mcp/query-pool.js.map +1 -0
  203. package/dist/mcp/query-worker.d.ts +24 -0
  204. package/dist/mcp/query-worker.d.ts.map +1 -0
  205. package/dist/mcp/query-worker.js +87 -0
  206. package/dist/mcp/query-worker.js.map +1 -0
  207. package/dist/mcp/server-instructions.d.ts +4 -29
  208. package/dist/mcp/server-instructions.d.ts.map +1 -1
  209. package/dist/mcp/server-instructions.js +39 -86
  210. package/dist/mcp/server-instructions.js.map +1 -1
  211. package/dist/mcp/session.d.ts +14 -0
  212. package/dist/mcp/session.d.ts.map +1 -1
  213. package/dist/mcp/session.js +28 -1
  214. package/dist/mcp/session.js.map +1 -1
  215. package/dist/mcp/startup-handshake.d.ts +44 -0
  216. package/dist/mcp/startup-handshake.d.ts.map +1 -0
  217. package/dist/mcp/startup-handshake.js +73 -0
  218. package/dist/mcp/startup-handshake.js.map +1 -0
  219. package/dist/mcp/tools.d.ts +179 -2
  220. package/dist/mcp/tools.d.ts.map +1 -1
  221. package/dist/mcp/tools.js +3027 -192
  222. package/dist/mcp/tools.js.map +1 -1
  223. package/dist/mcp/transport.d.ts.map +1 -1
  224. package/dist/mcp/transport.js +18 -0
  225. package/dist/mcp/transport.js.map +1 -1
  226. package/dist/project-config.d.ts +58 -0
  227. package/dist/project-config.d.ts.map +1 -1
  228. package/dist/project-config.js +141 -2
  229. package/dist/project-config.js.map +1 -1
  230. package/dist/reasoning/login.js +1 -1
  231. package/dist/reasoning/login.js.map +1 -1
  232. package/dist/resolution/c-fnptr-synthesizer.d.ts +2 -29
  233. package/dist/resolution/c-fnptr-synthesizer.d.ts.map +1 -1
  234. package/dist/resolution/c-fnptr-synthesizer.js +866 -148
  235. package/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
  236. package/dist/resolution/callback-synthesizer.d.ts +9 -1
  237. package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  238. package/dist/resolution/callback-synthesizer.js +1232 -183
  239. package/dist/resolution/callback-synthesizer.js.map +1 -1
  240. package/dist/resolution/cooperative-yield.d.ts +32 -0
  241. package/dist/resolution/cooperative-yield.d.ts.map +1 -0
  242. package/dist/resolution/cooperative-yield.js +42 -0
  243. package/dist/resolution/cooperative-yield.js.map +1 -0
  244. package/dist/resolution/frameworks/cics.d.ts +20 -0
  245. package/dist/resolution/frameworks/cics.d.ts.map +1 -0
  246. package/dist/resolution/frameworks/cics.js +90 -0
  247. package/dist/resolution/frameworks/cics.js.map +1 -0
  248. package/dist/resolution/frameworks/index.d.ts.map +1 -1
  249. package/dist/resolution/frameworks/index.js +3 -0
  250. package/dist/resolution/frameworks/index.js.map +1 -1
  251. package/dist/resolution/frameworks/java.d.ts.map +1 -1
  252. package/dist/resolution/frameworks/java.js +14 -6
  253. package/dist/resolution/frameworks/java.js.map +1 -1
  254. package/dist/resolution/frameworks/terraform.d.ts +38 -0
  255. package/dist/resolution/frameworks/terraform.d.ts.map +1 -0
  256. package/dist/resolution/frameworks/terraform.js +277 -0
  257. package/dist/resolution/frameworks/terraform.js.map +1 -0
  258. package/dist/resolution/goframe-synthesizer.d.ts +2 -1
  259. package/dist/resolution/goframe-synthesizer.d.ts.map +1 -1
  260. package/dist/resolution/goframe-synthesizer.js +8 -3
  261. package/dist/resolution/goframe-synthesizer.js.map +1 -1
  262. package/dist/resolution/import-resolver.d.ts +7 -0
  263. package/dist/resolution/import-resolver.d.ts.map +1 -1
  264. package/dist/resolution/import-resolver.js +129 -4
  265. package/dist/resolution/import-resolver.js.map +1 -1
  266. package/dist/resolution/index.d.ts +65 -3
  267. package/dist/resolution/index.d.ts.map +1 -1
  268. package/dist/resolution/index.js +477 -59
  269. package/dist/resolution/index.js.map +1 -1
  270. package/dist/resolution/name-matcher.d.ts +22 -3
  271. package/dist/resolution/name-matcher.d.ts.map +1 -1
  272. package/dist/resolution/name-matcher.js +657 -39
  273. package/dist/resolution/name-matcher.js.map +1 -1
  274. package/dist/resolution/strip-comments.d.ts +1 -1
  275. package/dist/resolution/strip-comments.d.ts.map +1 -1
  276. package/dist/resolution/strip-comments.js +49 -0
  277. package/dist/resolution/strip-comments.js.map +1 -1
  278. package/dist/resolution/types.d.ts +29 -0
  279. package/dist/resolution/types.d.ts.map +1 -1
  280. package/dist/resolution/workspace-packages.d.ts +10 -0
  281. package/dist/resolution/workspace-packages.d.ts.map +1 -1
  282. package/dist/resolution/workspace-packages.js +142 -4
  283. package/dist/resolution/workspace-packages.js.map +1 -1
  284. package/dist/search/identifier-segments.d.ts +60 -0
  285. package/dist/search/identifier-segments.d.ts.map +1 -0
  286. package/dist/search/identifier-segments.js +176 -0
  287. package/dist/search/identifier-segments.js.map +1 -0
  288. package/dist/search/query-utils.d.ts +201 -0
  289. package/dist/search/query-utils.d.ts.map +1 -1
  290. package/dist/search/query-utils.js +919 -2
  291. package/dist/search/query-utils.js.map +1 -1
  292. package/dist/spec/config.d.ts +7 -11
  293. package/dist/spec/config.d.ts.map +1 -1
  294. package/dist/spec/config.js +77 -48
  295. package/dist/spec/config.js.map +1 -1
  296. package/dist/spec/db/fragment-node.d.ts +1 -0
  297. package/dist/spec/db/fragment-node.d.ts.map +1 -1
  298. package/dist/spec/db/fragment-node.js +8 -0
  299. package/dist/spec/db/fragment-node.js.map +1 -1
  300. package/dist/spec/db/fts.d.ts +14 -0
  301. package/dist/spec/db/fts.d.ts.map +1 -1
  302. package/dist/spec/db/fts.js +43 -4
  303. package/dist/spec/db/fts.js.map +1 -1
  304. package/dist/spec/db/schema.d.ts +6 -3
  305. package/dist/spec/db/schema.d.ts.map +1 -1
  306. package/dist/spec/db/schema.js +36 -4
  307. package/dist/spec/db/schema.js.map +1 -1
  308. package/dist/spec/db/schema.sql +11 -1
  309. package/dist/spec/evolve/logic-checker.d.ts +2 -2
  310. package/dist/spec/evolve/logic-checker.d.ts.map +1 -1
  311. package/dist/spec/evolve/logic-checker.js +3 -27
  312. package/dist/spec/evolve/logic-checker.js.map +1 -1
  313. package/dist/spec/evolve/pipeline.d.ts +21 -19
  314. package/dist/spec/evolve/pipeline.d.ts.map +1 -1
  315. package/dist/spec/evolve/pipeline.js +284 -31
  316. package/dist/spec/evolve/pipeline.js.map +1 -1
  317. package/dist/spec/evolve/spec-rewriter.d.ts +2 -2
  318. package/dist/spec/evolve/spec-rewriter.d.ts.map +1 -1
  319. package/dist/spec/evolve/spec-rewriter.js +7 -31
  320. package/dist/spec/evolve/spec-rewriter.js.map +1 -1
  321. package/dist/spec/graph/queries.d.ts +97 -0
  322. package/dist/spec/graph/queries.d.ts.map +1 -1
  323. package/dist/spec/graph/queries.js +225 -0
  324. package/dist/spec/graph/queries.js.map +1 -1
  325. package/dist/spec/llm/client.d.ts +29 -0
  326. package/dist/spec/llm/client.d.ts.map +1 -0
  327. package/dist/spec/llm/client.js +123 -0
  328. package/dist/spec/llm/client.js.map +1 -0
  329. package/dist/spec/llm/index.d.ts +3 -0
  330. package/dist/spec/llm/index.d.ts.map +1 -0
  331. package/dist/spec/llm/index.js +11 -0
  332. package/dist/spec/llm/index.js.map +1 -0
  333. package/dist/spec/llm/prompts.d.ts +13 -0
  334. package/dist/spec/llm/prompts.d.ts.map +1 -0
  335. package/dist/spec/llm/prompts.js +75 -0
  336. package/dist/spec/llm/prompts.js.map +1 -0
  337. package/dist/spec/mining/git-scanner.d.ts +12 -0
  338. package/dist/spec/mining/git-scanner.d.ts.map +1 -1
  339. package/dist/spec/mining/git-scanner.js +41 -0
  340. package/dist/spec/mining/git-scanner.js.map +1 -1
  341. package/dist/spec/mining/pipeline.d.ts.map +1 -1
  342. package/dist/spec/mining/pipeline.js +14 -1
  343. package/dist/spec/mining/pipeline.js.map +1 -1
  344. package/dist/spec/utils.d.ts +2 -1
  345. package/dist/spec/utils.d.ts.map +1 -1
  346. package/dist/spec/utils.js +3 -1
  347. package/dist/spec/utils.js.map +1 -1
  348. package/dist/sync/git-hooks.d.ts.map +1 -1
  349. package/dist/sync/git-hooks.js +2 -0
  350. package/dist/sync/git-hooks.js.map +1 -1
  351. package/dist/sync/watcher.d.ts +10 -5
  352. package/dist/sync/watcher.d.ts.map +1 -1
  353. package/dist/sync/watcher.js +51 -14
  354. package/dist/sync/watcher.js.map +1 -1
  355. package/dist/sync/worktree.d.ts +9 -0
  356. package/dist/sync/worktree.d.ts.map +1 -1
  357. package/dist/sync/worktree.js +45 -0
  358. package/dist/sync/worktree.js.map +1 -1
  359. package/dist/types.d.ts +25 -2
  360. package/dist/types.d.ts.map +1 -1
  361. package/dist/types.js +10 -0
  362. package/dist/types.js.map +1 -1
  363. package/dist/ui/shimmer-progress.d.ts +2 -0
  364. package/dist/ui/shimmer-progress.d.ts.map +1 -1
  365. package/dist/ui/shimmer-progress.js +19 -2
  366. package/dist/ui/shimmer-progress.js.map +1 -1
  367. package/dist/upgrade/index.d.ts +32 -0
  368. package/dist/upgrade/index.d.ts.map +1 -1
  369. package/dist/upgrade/index.js +163 -15
  370. package/dist/upgrade/index.js.map +1 -1
  371. package/dist/upgrade/remove-binary.d.ts +87 -0
  372. package/dist/upgrade/remove-binary.d.ts.map +1 -0
  373. package/dist/upgrade/remove-binary.js +289 -0
  374. package/dist/upgrade/remove-binary.js.map +1 -0
  375. package/dist/upgrade/update-check.d.ts +92 -0
  376. package/dist/upgrade/update-check.d.ts.map +1 -0
  377. package/dist/upgrade/update-check.js +258 -0
  378. package/dist/upgrade/update-check.js.map +1 -0
  379. package/package.json +4 -4
  380. package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -0
  381. package/scripts/agent-eval/repro-daemon-clients.mjs +125 -0
  382. package/scripts/agent-eval/run-all.sh +6 -0
  383. package/scripts/build-bundle.sh +5 -0
  384. package/scripts/exp_boundary_eval/README.md +247 -0
  385. package/scripts/exp_boundary_eval/_test_mcp_chain.py +78 -0
  386. package/scripts/exp_boundary_eval/_test_stdin.py +8 -0
  387. package/scripts/exp_boundary_eval/_utils.py +1116 -0
  388. package/scripts/exp_boundary_eval/analyze.py +1313 -0
  389. package/scripts/exp_boundary_eval/deveco_arm.py +519 -0
  390. package/scripts/exp_boundary_eval/run_all.py +378 -0
  391. package/scripts/exp_boundary_eval/run_one.py +165 -0
  392. package/scripts/exp_boundary_eval/run_session.py +158 -0
  393. package/scripts/exp_boundary_eval/setup.py +120 -0
  394. package/scripts/exp_boundary_eval/win_mcp_launcher.py +73 -0
  395. package/scripts/exp_boundary_eval/win_mcp_stdio_wrap.js +36 -0
  396. package/scripts/exp_boundary_eval/win_node_launcher.py +24 -0
  397. package/scripts/npm-shim.js +32 -3
  398. package/scripts/ohos-sdk-publish.mjs +133 -0
  399. package/scripts/qa_eval/README.md +0 -407
  400. package/scripts/qa_eval/_test_deveco_probe.py +0 -41
  401. package/scripts/qa_eval/agent_runner.py +0 -526
  402. package/scripts/qa_eval/data/.gitignore +0 -4
  403. package/scripts/qa_eval/data/test-set.jsonl +0 -2
  404. package/scripts/qa_eval/eval_metrics.py +0 -274
  405. package/scripts/qa_eval/external_agent.py +0 -976
  406. package/scripts/qa_eval/llm_config.py +0 -92
  407. package/scripts/qa_eval/memory_monitor.py +0 -132
  408. package/scripts/qa_eval/my_answer_accuracy.py +0 -187
  409. package/scripts/qa_eval/requirements.txt +0 -2
  410. package/scripts/qa_eval/run_pipeline.py +0 -804
  411. package/scripts/qa_eval/stats_efficiency.py +0 -279
  412. package/scripts/qa_eval/stats_scores.py +0 -207
@@ -4,12 +4,49 @@
4
4
  *
5
5
  * Prepared statements for CRUD operations on the knowledge graph.
6
6
  */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
7
40
  Object.defineProperty(exports, "__esModule", { value: true });
8
41
  exports.QueryBuilder = void 0;
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
9
44
  const utils_1 = require("../utils");
10
45
  const query_utils_1 = require("../search/query-utils");
11
46
  const query_parser_1 = require("../search/query-parser");
12
47
  const generated_detection_1 = require("../extraction/generated-detection");
48
+ const arkts_1 = require("../extraction/languages/arkts");
49
+ const identifier_segments_1 = require("../search/identifier-segments");
13
50
  /**
14
51
  * Path-only heuristic for files that should not be candidates for
15
52
  * "dominant file" detection: test/spec files and tool-generated files.
@@ -33,6 +70,14 @@ function isLowValueFile(filePath) {
33
70
  (0, generated_detection_1.isGeneratedFile)(filePath));
34
71
  }
35
72
  const SQLITE_PARAM_CHUNK_SIZE = 500;
73
+ /**
74
+ * Last segment of a (possibly dotted/qualified) reference name — the part a
75
+ * new symbol's plain node name could match: 'util.greet' → 'greet'.
76
+ */
77
+ function referenceNameTail(referenceName) {
78
+ const idx = Math.max(referenceName.lastIndexOf('.'), referenceName.lastIndexOf(':'));
79
+ return idx >= 0 ? referenceName.slice(idx + 1) : referenceName;
80
+ }
36
81
  /**
37
82
  * Convert database row to Node object
38
83
  */
@@ -100,14 +145,54 @@ class QueryBuilder {
100
145
  // whole project, not a symbol, so it carries no discriminative signal (#720).
101
146
  // Set once by the HomeGraph instance; empty by default (no down-weighting).
102
147
  projectNameTokens = new Set();
148
+ segmentedNames = new Set();
149
+ static MAX_SEGMENTED_NAMES = 65536;
103
150
  // Node cache for frequently accessed nodes (LRU-style, max 1000 entries)
104
151
  nodeCache = new Map();
105
152
  maxCacheSize = 1000;
153
+ /** Attached prebuilt OHOS API db (see arkts.ts). */
154
+ ohosApiDbPath = null;
106
155
  // Prepared statements (lazily initialized)
107
156
  stmts = {};
108
157
  constructor(db) {
109
158
  this.db = db;
110
159
  }
160
+ /** Attach a versioned OHOS API db for federated symbol lookup. */
161
+ attachOhosApiDb(dbPath) {
162
+ if (dbPath === this.ohosApiDbPath)
163
+ return;
164
+ if (this.ohosApiDbPath) {
165
+ try {
166
+ this.db.exec('DETACH DATABASE ohos_api');
167
+ }
168
+ catch {
169
+ /* already detached */
170
+ }
171
+ this.ohosApiDbPath = null;
172
+ }
173
+ if (!dbPath)
174
+ return;
175
+ const resolved = path.resolve(dbPath);
176
+ if (!fs.existsSync(resolved)) {
177
+ throw new Error(`OHOS API db not found: ${resolved}`);
178
+ }
179
+ const escaped = resolved.replace(/'/g, "''");
180
+ this.db.exec(`ATTACH DATABASE '${escaped}' AS ohos_api`);
181
+ this.ohosApiDbPath = resolved;
182
+ this.stmts = {};
183
+ this.nodeCache.clear();
184
+ }
185
+ getOhosApiDbPath() {
186
+ return this.ohosApiDbPath;
187
+ }
188
+ hasOhosApiAttached() {
189
+ return this.ohosApiDbPath != null;
190
+ }
191
+ mapOhosApiNodeRow(row) {
192
+ const node = rowToNode(row);
193
+ node.filePath = (0, arkts_1.markOhosApiFilePath)(node.filePath);
194
+ return node;
195
+ }
111
196
  /** Set the normalized project-name tokens used to down-weight non-discriminative
112
197
  * query words in path scoring (#720). Called once when the project opens. */
113
198
  setProjectNameTokens(tokens) {
@@ -180,6 +265,10 @@ class QueryBuilder {
180
265
  returnType: node.returnType ?? null,
181
266
  updatedAt: node.updatedAt ?? Date.now(),
182
267
  });
268
+ // Segment vocabulary rides the same write path so it never drifts ahead of
269
+ // the nodes it describes. File/import nodes are excluded (#1144).
270
+ if (this.isSegmentableKind(node.kind))
271
+ this.insertNameSegments(node.name);
183
272
  }
184
273
  /**
185
274
  * Insert multiple nodes in a transaction
@@ -251,6 +340,9 @@ class QueryBuilder {
251
340
  returnType: node.returnType ?? null,
252
341
  updatedAt: node.updatedAt ?? Date.now(),
253
342
  });
343
+ // Framework post-extract renames must reach the segment vocabulary (#1141).
344
+ if (this.isSegmentableKind(node.kind))
345
+ this.insertNameSegments(node.name);
254
346
  }
255
347
  /**
256
348
  * Delete a node by ID
@@ -278,6 +370,104 @@ class QueryBuilder {
278
370
  }
279
371
  this.stmts.deleteNodesByFile.run(filePath);
280
372
  }
373
+ /** Which node kinds contribute their name to the segment vocabulary. */
374
+ isSegmentableKind(kind) {
375
+ return kind !== 'file' && kind !== 'import';
376
+ }
377
+ /** Write `name`'s segments into name_segment_vocab (idempotent). */
378
+ insertNameSegments(name) {
379
+ if (this.segmentedNames.has(name))
380
+ return;
381
+ if (this.segmentedNames.size >= QueryBuilder.MAX_SEGMENTED_NAMES)
382
+ this.segmentedNames.clear();
383
+ this.segmentedNames.add(name);
384
+ if (!this.stmts.insertNameSegment) {
385
+ this.stmts.insertNameSegment = this.db.prepare('INSERT OR IGNORE INTO name_segment_vocab (segment, name) VALUES (?, ?)');
386
+ }
387
+ for (const segment of (0, identifier_segments_1.splitIdentifierSegments)(name)) {
388
+ this.stmts.insertNameSegment.run(segment, name);
389
+ }
390
+ }
391
+ // ===========================================================================
392
+ // Name-segment vocabulary (prompt-hook graph-derived gate)
393
+ // ===========================================================================
394
+ /** Wipe the segment vocabulary. A full index calls this at its start; the
395
+ * node write path repopulates it as files (re-)index, so the end state is
396
+ * exactly the current names with no orphan rows. */
397
+ clearNameSegmentVocab() {
398
+ this.db.exec('DELETE FROM name_segment_vocab');
399
+ this.segmentedNames.clear();
400
+ }
401
+ /** True when the vocab has no rows — an index built before the table existed.
402
+ * `sync` uses this to heal such databases (see rebuildNameSegmentVocabFrom). */
403
+ isNameSegmentVocabEmpty() {
404
+ const row = this.db.prepare('SELECT 1 FROM name_segment_vocab LIMIT 1').get();
405
+ return row === undefined;
406
+ }
407
+ /** One page of distinct segmentable node names, for batched vocab rebuilds
408
+ * (file basenames and import specifiers are excluded from the vocab — see
409
+ * insertNode). */
410
+ getDistinctNodeNames(limit, offset) {
411
+ const rows = this.db
412
+ .prepare("SELECT DISTINCT name FROM nodes WHERE kind NOT IN ('file', 'import') ORDER BY name LIMIT ? OFFSET ?")
413
+ .all(limit, offset);
414
+ return rows.map((r) => r.name);
415
+ }
416
+ /** Insert segments for a batch of names in one transaction (vocab heal path). */
417
+ insertNameSegmentsBatch(names) {
418
+ this.db.transaction(() => {
419
+ for (const name of names)
420
+ this.insertNameSegments(name);
421
+ })();
422
+ }
423
+ /**
424
+ * Names whose segments cover at least `minWords` distinct PROMPT WORDS —
425
+ * the co-occurrence probe behind the prompt hook's medium tier: the words
426
+ * "state" and "machine" both being segments of `OrderStateMachine` is strong
427
+ * evidence the prompt names that symbol in prose. Ordered by coverage.
428
+ *
429
+ * Takes (segment variant → original word) pairs and folds variants back to
430
+ * their word INSIDE the SQL: a name matching both `service` and `services`
431
+ * counts ONE word, not two. Counting raw variants let plural-variant pairs
432
+ * of a single word tie with genuine two-word matches and — because ORDER
433
+ * BY/LIMIT run here, before any JS-side re-check — crowd a real match past
434
+ * the LIMIT on vocab-heavy repos (#1146).
435
+ */
436
+ getSegmentCoOccurrence(variants, minWords, limit) {
437
+ if (variants.length === 0)
438
+ return [];
439
+ const placeholders = variants.map(() => '?').join(', ');
440
+ const whens = variants.map(() => 'WHEN ? THEN ?').join(' ');
441
+ const rows = this.db
442
+ .prepare(`SELECT name, COUNT(DISTINCT CASE segment ${whens} END) AS matches
443
+ FROM name_segment_vocab
444
+ WHERE segment IN (${placeholders})
445
+ GROUP BY name
446
+ HAVING matches >= ?
447
+ ORDER BY matches DESC, length(name) ASC
448
+ LIMIT ?`)
449
+ .all(...variants.flatMap((v) => [v.segment, v.word]), ...variants.map((v) => v.segment), minWords, limit);
450
+ return rows;
451
+ }
452
+ /** How many distinct names each segment appears in — the rarity signal that
453
+ * separates a discriminative word ("checkout") from a ubiquitous one ("state"). */
454
+ getSegmentNameCounts(segments) {
455
+ if (segments.length === 0)
456
+ return new Map();
457
+ const placeholders = segments.map(() => '?').join(', ');
458
+ const rows = this.db
459
+ .prepare(`SELECT segment, COUNT(*) AS n FROM name_segment_vocab
460
+ WHERE segment IN (${placeholders}) GROUP BY segment`)
461
+ .all(...segments);
462
+ return new Map(rows.map((r) => [r.segment, r.n]));
463
+ }
464
+ /** Names containing the given segment (rare-single-word tier). */
465
+ getNamesForSegment(segment, limit) {
466
+ const rows = this.db
467
+ .prepare('SELECT name FROM name_segment_vocab WHERE segment = ? ORDER BY length(name) ASC LIMIT ?')
468
+ .all(segment, limit);
469
+ return rows.map((r) => r.name);
470
+ }
281
471
  /**
282
472
  * Get a node by ID
283
473
  */
@@ -571,6 +761,33 @@ class QueryBuilder {
571
761
  yield rowToNode(row);
572
762
  }
573
763
  }
764
+ /**
765
+ * Stream nodes of a language whose `decorators` JSON array contains a
766
+ * quoted decorator name. LIKE is a substring filter (a decorator name can
767
+ * appear as a substring of another), so callers must still exact-check
768
+ * `node.decorators.includes(decorator)`. Exists so the kotlin expect/actual
769
+ * synthesizer never materializes the whole node table the way
770
+ * `getAllNodes().filter(...)` did — that array alone OOM'd Node's default
771
+ * heap on a 2M-node graph (#1212).
772
+ */
773
+ *iterateNodesByLanguageWithDecorator(language, decorator) {
774
+ // Fresh statement per call — an iterator holds an open cursor (see
775
+ // iterateNodesByKind).
776
+ const stmt = this.db.prepare("SELECT * FROM nodes WHERE language = ? AND decorators LIKE '%' || ? || '%'");
777
+ for (const row of stmt.iterate(language, `"${decorator}"`)) {
778
+ yield rowToNode(row);
779
+ }
780
+ }
781
+ /**
782
+ * Distinct languages present in the files table. One indexed aggregate —
783
+ * lets the dynamic-edge synthesizers skip passes for languages the project
784
+ * doesn't contain at all (a Kotlin pass has no work on a pure-C repo), so
785
+ * their cost is zero rather than a full-graph scan that finds nothing (#1212).
786
+ */
787
+ getDistinctFileLanguages() {
788
+ const rows = this.db.prepare('SELECT DISTINCT language FROM files').all();
789
+ return new Set(rows.map((r) => r.language));
790
+ }
574
791
  /**
575
792
  * Get all nodes in the database
576
793
  */
@@ -586,7 +803,15 @@ class QueryBuilder {
586
803
  this.stmts.getNodesByName = this.db.prepare('SELECT * FROM nodes WHERE name = ?');
587
804
  }
588
805
  const rows = this.stmts.getNodesByName.all(name);
589
- return rows.map(rowToNode);
806
+ const main = rows.map(rowToNode);
807
+ if (!this.hasOhosApiAttached())
808
+ return main;
809
+ const apiRows = this.db
810
+ .prepare('SELECT * FROM ohos_api.nodes WHERE name = ?')
811
+ .all(name);
812
+ const seen = new Set(main.map((n) => n.id));
813
+ const api = apiRows.map((r) => this.mapOhosApiNodeRow(r)).filter((n) => !seen.has(n.id));
814
+ return [...main, ...api];
590
815
  }
591
816
  /**
592
817
  * Get nodes by exact qualified name match (uses idx_nodes_qualified_name index)
@@ -722,8 +947,44 @@ class QueryBuilder {
722
947
  return lowered.some((n) => nm.includes(n));
723
948
  });
724
949
  }
950
+ if (this.hasOhosApiAttached() && text.length >= 2) {
951
+ results = this.mergeOhosApiTextSearch(text, { kinds, languages, limit }, results);
952
+ }
725
953
  return results;
726
954
  }
955
+ mergeOhosApiTextSearch(text, options, existing) {
956
+ const { kinds, languages, limit = 100 } = options;
957
+ const seen = new Set(existing.map((r) => r.node.id));
958
+ const merged = [...existing];
959
+ const apiLimit = Math.min(20, Math.max(5, Math.floor(limit / 4)));
960
+ let sql = `
961
+ SELECT nodes.*, 0.9 as score
962
+ FROM ohos_api.nodes
963
+ WHERE (name LIKE ? OR qualified_name LIKE ?)
964
+ `;
965
+ const pattern = `%${text}%`;
966
+ const params = [pattern, pattern];
967
+ if (kinds && kinds.length > 0) {
968
+ sql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
969
+ params.push(...kinds);
970
+ }
971
+ if (languages && languages.length > 0) {
972
+ sql += ` AND language IN (${languages.map(() => '?').join(',')})`;
973
+ params.push(...languages);
974
+ }
975
+ sql += ' LIMIT ?';
976
+ params.push(apiLimit);
977
+ const rows = this.db.prepare(sql).all(...params);
978
+ for (const row of rows) {
979
+ const node = this.mapOhosApiNodeRow(row);
980
+ if (seen.has(node.id))
981
+ continue;
982
+ seen.add(node.id);
983
+ merged.push({ node, score: row.score });
984
+ }
985
+ merged.sort((a, b) => b.score - a.score);
986
+ return merged.slice(0, limit);
987
+ }
727
988
  /**
728
989
  * Match-everything path used when the user supplied only field
729
990
  * filters (`kind:function lang:typescript`) with no text. Returns
@@ -994,6 +1255,32 @@ class QueryBuilder {
994
1255
  seenIds.add(r.node.id);
995
1256
  allResults.push(r);
996
1257
  }
1258
+ if (this.hasOhosApiAttached()) {
1259
+ let apiSql = `
1260
+ SELECT nodes.*, 0.95 as score
1261
+ FROM ohos_api.nodes
1262
+ WHERE name COLLATE NOCASE = ?
1263
+ `;
1264
+ const apiParams = [name];
1265
+ if (kinds && kinds.length > 0) {
1266
+ apiSql += ` AND kind IN (${kinds.map(() => '?').join(',')})`;
1267
+ apiParams.push(...kinds);
1268
+ }
1269
+ if (languages && languages.length > 0) {
1270
+ apiSql += ` AND language IN (${languages.map(() => '?').join(',')})`;
1271
+ apiParams.push(...languages);
1272
+ }
1273
+ apiSql += ' LIMIT ?';
1274
+ apiParams.push(perNameLimit);
1275
+ const apiRows = this.db.prepare(apiSql).all(...apiParams);
1276
+ for (const row of apiRows) {
1277
+ const node = this.mapOhosApiNodeRow(row);
1278
+ if (seenIds.has(node.id))
1279
+ continue;
1280
+ seenIds.add(node.id);
1281
+ allResults.push({ node, score: row.score });
1282
+ }
1283
+ }
997
1284
  }
998
1285
  // Sort all results by score so co-located results bubble up
999
1286
  allResults.sort((a, b) => b.score - a.score);
@@ -1115,12 +1402,23 @@ class QueryBuilder {
1115
1402
  /**
1116
1403
  * Get incoming edges to a node
1117
1404
  */
1118
- getIncomingEdges(targetId, kinds) {
1405
+ getIncomingEdges(targetId, kinds, limit) {
1406
+ const cap = typeof limit === 'number' && Number.isFinite(limit)
1407
+ ? Math.max(1, Math.min(Math.floor(limit), 2000))
1408
+ : undefined;
1119
1409
  if (kinds && kinds.length > 0) {
1120
- const sql = `SELECT * FROM edges WHERE target = ? AND kind IN (${kinds.map(() => '?').join(',')})`;
1410
+ let sql = `SELECT * FROM edges WHERE target = ? AND kind IN (${kinds.map(() => '?').join(',')})`;
1411
+ if (cap !== undefined)
1412
+ sql += ` LIMIT ${cap}`;
1121
1413
  const rows = this.db.prepare(sql).all(targetId, ...kinds);
1122
1414
  return rows.map(rowToEdge);
1123
1415
  }
1416
+ if (cap !== undefined) {
1417
+ const rows = this.db
1418
+ .prepare('SELECT * FROM edges WHERE target = ? LIMIT ?')
1419
+ .all(targetId, cap);
1420
+ return rows.map(rowToEdge);
1421
+ }
1124
1422
  if (!this.stmts.getEdgesByTarget) {
1125
1423
  this.stmts.getEdgesByTarget = this.db.prepare('SELECT * FROM edges WHERE target = ?');
1126
1424
  }
@@ -1199,7 +1497,8 @@ class QueryBuilder {
1199
1497
  * {@link getDependentFilePaths}: all kinds except `contains`.
1200
1498
  */
1201
1499
  getCrossFileIncomingEdgesWithTarget(filePath) {
1202
- const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind
1500
+ const sql = `SELECT e.*, tgt.name AS target_name, tgt.kind AS target_kind,
1501
+ src.file_path AS source_file_path, src.language AS source_language
1203
1502
  FROM edges e
1204
1503
  JOIN nodes tgt ON tgt.id = e.target
1205
1504
  JOIN nodes src ON src.id = e.source
@@ -1211,6 +1510,8 @@ class QueryBuilder {
1211
1510
  ...rowToEdge(row),
1212
1511
  targetName: row.target_name,
1213
1512
  targetKind: row.target_kind,
1513
+ sourceFilePath: row.source_file_path,
1514
+ sourceLanguage: row.source_language,
1214
1515
  }));
1215
1516
  }
1216
1517
  /**
@@ -1397,7 +1698,7 @@ class QueryBuilder {
1397
1698
  */
1398
1699
  getUnresolvedReferencesCount() {
1399
1700
  if (!this.stmts.getUnresolvedCount) {
1400
- this.stmts.getUnresolvedCount = this.db.prepare('SELECT COUNT(*) as count FROM unresolved_refs');
1701
+ this.stmts.getUnresolvedCount = this.db.prepare("SELECT COUNT(*) as count FROM unresolved_refs WHERE status = 'pending'");
1401
1702
  }
1402
1703
  const row = this.stmts.getUnresolvedCount.get();
1403
1704
  return row.count;
@@ -1408,7 +1709,7 @@ class QueryBuilder {
1408
1709
  */
1409
1710
  getUnresolvedReferencesBatch(offset, limit) {
1410
1711
  if (!this.stmts.getUnresolvedBatch) {
1411
- this.stmts.getUnresolvedBatch = this.db.prepare('SELECT * FROM unresolved_refs LIMIT ? OFFSET ?');
1712
+ this.stmts.getUnresolvedBatch = this.db.prepare("SELECT * FROM unresolved_refs WHERE status = 'pending' LIMIT ? OFFSET ?");
1412
1713
  }
1413
1714
  const rows = this.stmts.getUnresolvedBatch.all(limit, offset);
1414
1715
  return rows.map((row) => ({
@@ -1442,6 +1743,135 @@ class QueryBuilder {
1442
1743
  const rows = this.stmts.getAllNodeNames.all();
1443
1744
  return rows.map((r) => r.name);
1444
1745
  }
1746
+ /**
1747
+ * Stream distinct node names one row at a time — for resolver cache warm-up
1748
+ * that needs to yield to the event loop mid-scan.
1749
+ */
1750
+ *iterateNodeNames() {
1751
+ const stmt = this.db.prepare('SELECT DISTINCT name FROM nodes');
1752
+ for (const row of stmt.iterate()) {
1753
+ yield row.name;
1754
+ }
1755
+ }
1756
+ /**
1757
+ * Park refs as status='failed' so drain loops skip them while sync can retry
1758
+ * when a later file change introduces a matching symbol.
1759
+ */
1760
+ markReferencesFailed(refs) {
1761
+ if (refs.length === 0)
1762
+ return;
1763
+ const stmt = this.db.prepare("UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE from_node_id = ? AND reference_name = ? AND reference_kind = ?");
1764
+ const markMany = this.db.transaction((items) => {
1765
+ for (const ref of items) {
1766
+ stmt.run(referenceNameTail(ref.referenceName), ref.fromNodeId, ref.referenceName, ref.referenceKind);
1767
+ }
1768
+ });
1769
+ markMany(refs);
1770
+ }
1771
+ /**
1772
+ * Delete unresolved-ref rows by row id — the precise cleanup for refs a
1773
+ * resolution pass actually processed. The key-tuple variant above also
1774
+ * deletes SIBLING rows (same caller calling the same callee at other lines)
1775
+ * that a later batch hasn't attempted yet, so when a batch boundary split a
1776
+ * caller's same-named call sites, the later sites' edges were silently never
1777
+ * created (#1269).
1778
+ */
1779
+ deleteReferencesByRowIds(rowIds) {
1780
+ if (rowIds.length === 0)
1781
+ return;
1782
+ for (let i = 0; i < rowIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1783
+ const chunk = rowIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1784
+ const placeholders = chunk.map(() => '?').join(',');
1785
+ this.db.prepare(`DELETE FROM unresolved_refs WHERE id IN (${placeholders})`).run(...chunk);
1786
+ }
1787
+ }
1788
+ /**
1789
+ * Park refs as status='failed' by row id — the precise counterpart of
1790
+ * markReferencesFailed, for the same reason as deleteReferencesByRowIds:
1791
+ * the key-tuple variant also flips same-key sibling rows in later batches
1792
+ * to 'failed' before they were ever attempted (#1269). Resolution outcome
1793
+ * can differ per call site (receiver-type inference reads the ref's line),
1794
+ * so a sibling must not inherit this row's failure.
1795
+ */
1796
+ markReferencesFailedByRowIds(refs) {
1797
+ if (refs.length === 0)
1798
+ return;
1799
+ const stmt = this.db.prepare("UPDATE unresolved_refs SET status = 'failed', name_tail = ? WHERE id = ?");
1800
+ const markMany = this.db.transaction((items) => {
1801
+ for (const ref of items) {
1802
+ stmt.run(referenceNameTail(ref.referenceName), ref.rowId);
1803
+ }
1804
+ });
1805
+ markMany(refs);
1806
+ }
1807
+ /**
1808
+ * Failed refs whose name tail matches one of the given symbol names — the
1809
+ * candidates a sync should retry after files carrying those names changed
1810
+ * (#1240). Names matching more than `perNameCeiling` failed refs are
1811
+ * skipped entirely: at that population a name is external/builtin noise
1812
+ * (`get`, `map`, …) that one new definition won't resolve — the same
1813
+ * rationale as resolution's AMBIGUOUS_NAME_CEILING (#999) — and retrying an
1814
+ * arbitrary subset would be both wasted work and incoherent coverage.
1815
+ */
1816
+ getRetryableFailedReferences(names, perNameCeiling = 500) {
1817
+ if (names.length === 0)
1818
+ return [];
1819
+ // Pass 1: per-tail counts, chunked under the SQLite parameter limit.
1820
+ const retryNames = [];
1821
+ for (let i = 0; i < names.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1822
+ const chunk = names.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1823
+ const placeholders = chunk.map(() => '?').join(',');
1824
+ const counts = this.db
1825
+ .prepare(`SELECT name_tail, COUNT(*) as count FROM unresolved_refs WHERE status = 'failed' AND name_tail IN (${placeholders}) GROUP BY name_tail`)
1826
+ .all(...chunk);
1827
+ for (const row of counts) {
1828
+ if (row.count <= perNameCeiling)
1829
+ retryNames.push(row.name_tail);
1830
+ }
1831
+ }
1832
+ if (retryNames.length === 0)
1833
+ return [];
1834
+ // Pass 2: load the surviving rows.
1835
+ const rows = [];
1836
+ for (let i = 0; i < retryNames.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1837
+ const chunk = retryNames.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1838
+ const placeholders = chunk.map(() => '?').join(',');
1839
+ const chunkRows = this.db
1840
+ .prepare(`SELECT * FROM unresolved_refs WHERE status = 'failed' AND name_tail IN (${placeholders})`)
1841
+ .all(...chunk);
1842
+ rows.push(...chunkRows);
1843
+ }
1844
+ return rows.map((row) => ({
1845
+ fromNodeId: row.from_node_id,
1846
+ referenceName: row.reference_name,
1847
+ referenceKind: row.reference_kind,
1848
+ line: row.line,
1849
+ column: row.col,
1850
+ candidates: row.candidates ? (0, utils_1.safeJsonParse)(row.candidates, undefined) : undefined,
1851
+ filePath: row.file_path,
1852
+ language: row.language,
1853
+ rowId: row.id,
1854
+ }));
1855
+ }
1856
+ /**
1857
+ * Distinct node names present in the given files — the symbol names a sync
1858
+ * pass uses to look up retryable failed refs after those files changed.
1859
+ */
1860
+ getNodeNamesByFiles(filePaths) {
1861
+ if (filePaths.length === 0)
1862
+ return [];
1863
+ const names = new Set();
1864
+ for (let i = 0; i < filePaths.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1865
+ const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1866
+ const placeholders = chunk.map(() => '?').join(',');
1867
+ const rows = this.db
1868
+ .prepare(`SELECT DISTINCT name FROM nodes WHERE file_path IN (${placeholders})`)
1869
+ .all(...chunk);
1870
+ for (const row of rows)
1871
+ names.add(row.name);
1872
+ }
1873
+ return [...names];
1874
+ }
1445
1875
  /**
1446
1876
  * Get unresolved references scoped to specific file paths.
1447
1877
  * Uses the idx_unresolved_file_path index for efficient lookup.
@@ -1458,7 +1888,7 @@ class QueryBuilder {
1458
1888
  const chunk = filePaths.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1459
1889
  const placeholders = chunk.map(() => '?').join(',');
1460
1890
  const chunkRows = this.db
1461
- .prepare(`SELECT * FROM unresolved_refs WHERE file_path IN (${placeholders})`)
1891
+ .prepare(`SELECT * FROM unresolved_refs WHERE status = 'pending' AND file_path IN (${placeholders})`)
1462
1892
  .all(...chunk);
1463
1893
  rows.push(...chunkRows);
1464
1894
  }
@@ -1485,8 +1915,16 @@ class QueryBuilder {
1485
1915
  deleteResolvedReferences(fromNodeIds) {
1486
1916
  if (fromNodeIds.length === 0)
1487
1917
  return;
1488
- const placeholders = fromNodeIds.map(() => '?').join(',');
1489
- this.db.prepare(`DELETE FROM unresolved_refs WHERE from_node_id IN (${placeholders})`).run(...fromNodeIds);
1918
+ // Chunk under SQLite's parameter limit, matching every other IN-list in
1919
+ // this file. The internal resolution path uses deleteSpecificResolvedReferences
1920
+ // instead, but QueryBuilder is part of the public API, so a library consumer
1921
+ // passing more ids than SQLITE_MAX_VARIABLE_NUMBER (32766 on the bundled
1922
+ // node:sqlite) would otherwise hit "too many SQL variables". (#540, #1001)
1923
+ for (let i = 0; i < fromNodeIds.length; i += SQLITE_PARAM_CHUNK_SIZE) {
1924
+ const chunk = fromNodeIds.slice(i, i + SQLITE_PARAM_CHUNK_SIZE);
1925
+ const placeholders = chunk.map(() => '?').join(',');
1926
+ this.db.prepare(`DELETE FROM unresolved_refs WHERE from_node_id IN (${placeholders})`).run(...chunk);
1927
+ }
1490
1928
  }
1491
1929
  /**
1492
1930
  * Delete specific resolved references by (fromNodeId, referenceName, referenceKind) tuples.
@@ -1588,12 +2026,38 @@ class QueryBuilder {
1588
2026
  }
1589
2027
  return result;
1590
2028
  }
2029
+ // ===========================================================================
2030
+ // MCP Query Cache
2031
+ // ===========================================================================
2032
+ clearMcpQueryCache() {
2033
+ this.db.exec('DELETE FROM mcp_query_cache');
2034
+ }
2035
+ getMcpQueryCache(cacheKey) {
2036
+ const row = this.db
2037
+ .prepare('SELECT tool, response FROM mcp_query_cache WHERE cache_key = ?')
2038
+ .get(cacheKey);
2039
+ return row ?? null;
2040
+ }
2041
+ /** All cache keys — used to warm the in-memory key index after daemon restart. */
2042
+ listMcpQueryCacheKeys() {
2043
+ const rows = this.db
2044
+ .prepare('SELECT cache_key FROM mcp_query_cache')
2045
+ .all();
2046
+ return rows.map((r) => r.cache_key);
2047
+ }
2048
+ setMcpQueryCache(cacheKey, tool, response, createdAt) {
2049
+ this.db
2050
+ .prepare('INSERT INTO mcp_query_cache (cache_key, tool, response, created_at) VALUES (?, ?, ?, ?) ' +
2051
+ 'ON CONFLICT(cache_key) DO UPDATE SET tool = excluded.tool, response = excluded.response, created_at = excluded.created_at')
2052
+ .run(cacheKey, tool, response, createdAt);
2053
+ }
1591
2054
  /**
1592
2055
  * Clear all data from the database
1593
2056
  */
1594
2057
  clear() {
1595
2058
  this.nodeCache.clear();
1596
2059
  this.db.transaction(() => {
2060
+ this.db.exec('DELETE FROM mcp_query_cache');
1597
2061
  this.db.exec('DELETE FROM unresolved_refs');
1598
2062
  this.db.exec('DELETE FROM edges');
1599
2063
  this.db.exec('DELETE FROM nodes');