@rkarim08/sia 1.0.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 (355) hide show
  1. package/.claude-plugin/marketplace.json +35 -0
  2. package/.claude-plugin/plugin.json +27 -0
  3. package/.mcp.json +13 -0
  4. package/CLAUDE.md +226 -0
  5. package/LICENSE +202 -0
  6. package/PLUGIN_README.md +253 -0
  7. package/README.md +1013 -0
  8. package/agents/sia-changelog-writer.md +89 -0
  9. package/agents/sia-code-reviewer.md +86 -0
  10. package/agents/sia-conflict-resolver.md +100 -0
  11. package/agents/sia-convention-enforcer.md +69 -0
  12. package/agents/sia-debug.md +106 -0
  13. package/agents/sia-decision-reviewer.md +101 -0
  14. package/agents/sia-dependency-tracker.md +80 -0
  15. package/agents/sia-explain.md +126 -0
  16. package/agents/sia-feature.md +116 -0
  17. package/agents/sia-knowledge-capture.md +117 -0
  18. package/agents/sia-lead-architecture-advisor.md +93 -0
  19. package/agents/sia-lead-team-health.md +107 -0
  20. package/agents/sia-migration.md +100 -0
  21. package/agents/sia-onboarding.md +115 -0
  22. package/agents/sia-orientation.md +99 -0
  23. package/agents/sia-pm-briefing.md +106 -0
  24. package/agents/sia-pm-risk-advisor.md +82 -0
  25. package/agents/sia-qa-analyst.md +116 -0
  26. package/agents/sia-qa-regression-map.md +94 -0
  27. package/agents/sia-refactor.md +115 -0
  28. package/agents/sia-regression.md +112 -0
  29. package/agents/sia-security-audit.md +125 -0
  30. package/agents/sia-test-advisor.md +91 -0
  31. package/hooks/hooks.json +98 -0
  32. package/migrations/bridge/001_initial.sql +34 -0
  33. package/migrations/episodic/001_initial.sql +35 -0
  34. package/migrations/meta/001_initial.sql +68 -0
  35. package/migrations/semantic/001_initial.sql +292 -0
  36. package/migrations/semantic/002_ontology.sql +89 -0
  37. package/migrations/semantic/003_freshness.sql +63 -0
  38. package/migrations/semantic/004_v5_unified_schema.sql +194 -0
  39. package/migrations/semantic/005_backfill_event_kinds.sql +8 -0
  40. package/migrations/semantic/006_tree_sitter.sql +6 -0
  41. package/migrations/semantic/007_branch_snapshots.sql +22 -0
  42. package/package.json +110 -0
  43. package/scripts/branch-switch.sh +13 -0
  44. package/scripts/build-wasm-grammars.sh +81 -0
  45. package/scripts/post-compact.sh +8 -0
  46. package/scripts/post-tool-use.sh +10 -0
  47. package/scripts/pre-compact.sh +8 -0
  48. package/scripts/session-end.sh +8 -0
  49. package/scripts/session-start.sh +8 -0
  50. package/scripts/start-mcp.ts +45 -0
  51. package/scripts/stop-hook.sh +8 -0
  52. package/scripts/user-prompt-submit.sh +8 -0
  53. package/scripts/viz-server.ts +152 -0
  54. package/skills/sia-brainstorm/SKILL.md +156 -0
  55. package/skills/sia-brainstorm/scripts/frame-template.html +214 -0
  56. package/skills/sia-brainstorm/scripts/helper.js +95 -0
  57. package/skills/sia-brainstorm/scripts/server.cjs +338 -0
  58. package/skills/sia-brainstorm/scripts/start-server.sh +153 -0
  59. package/skills/sia-brainstorm/scripts/stop-server.sh +55 -0
  60. package/skills/sia-brainstorm/spec-document-reviewer-prompt.md +49 -0
  61. package/skills/sia-brainstorm/visual-companion.md +286 -0
  62. package/skills/sia-capture/SKILL.md +64 -0
  63. package/skills/sia-compare/SKILL.md +33 -0
  64. package/skills/sia-conflicts/SKILL.md +38 -0
  65. package/skills/sia-debug-workflow/SKILL.md +120 -0
  66. package/skills/sia-debug-workflow/root-cause-tracing.md +70 -0
  67. package/skills/sia-debug-workflow/scripts/find-polluter.sh +64 -0
  68. package/skills/sia-debug-workflow/temporal-investigation.md +72 -0
  69. package/skills/sia-digest/SKILL.md +23 -0
  70. package/skills/sia-dispatch/SKILL.md +69 -0
  71. package/skills/sia-dispatch/agent-task-template.md +99 -0
  72. package/skills/sia-doctor/SKILL.md +39 -0
  73. package/skills/sia-execute/SKILL.md +70 -0
  74. package/skills/sia-execute-plan/SKILL.md +85 -0
  75. package/skills/sia-export-import/SKILL.md +49 -0
  76. package/skills/sia-export-knowledge/SKILL.md +46 -0
  77. package/skills/sia-finish/SKILL.md +100 -0
  78. package/skills/sia-finish/pr-summary-template.md +54 -0
  79. package/skills/sia-freshness/SKILL.md +38 -0
  80. package/skills/sia-history/SKILL.md +42 -0
  81. package/skills/sia-impact/SKILL.md +70 -0
  82. package/skills/sia-index/SKILL.md +54 -0
  83. package/skills/sia-install/SKILL.md +39 -0
  84. package/skills/sia-lead-compliance/SKILL.md +16 -0
  85. package/skills/sia-lead-drift-report/SKILL.md +16 -0
  86. package/skills/sia-lead-knowledge-map/SKILL.md +16 -0
  87. package/skills/sia-learn/SKILL.md +58 -0
  88. package/skills/sia-plan/SKILL.md +68 -0
  89. package/skills/sia-plan/plan-reviewer-prompt.md +63 -0
  90. package/skills/sia-playbooks/SKILL.md +29 -0
  91. package/skills/sia-playbooks/reference-feature.md +100 -0
  92. package/skills/sia-playbooks/reference-flagging.md +50 -0
  93. package/skills/sia-playbooks/reference-orientation.md +92 -0
  94. package/skills/sia-playbooks/reference-regression.md +115 -0
  95. package/skills/sia-playbooks/reference-review.md +64 -0
  96. package/skills/sia-playbooks/reference-tools.md +239 -0
  97. package/skills/sia-pm-decision-log/SKILL.md +28 -0
  98. package/skills/sia-pm-risk-dashboard/SKILL.md +24 -0
  99. package/skills/sia-pm-sprint-summary/SKILL.md +27 -0
  100. package/skills/sia-prune/SKILL.md +45 -0
  101. package/skills/sia-qa-coverage/SKILL.md +28 -0
  102. package/skills/sia-qa-flaky/SKILL.md +20 -0
  103. package/skills/sia-qa-report/SKILL.md +26 -0
  104. package/skills/sia-reindex/SKILL.md +30 -0
  105. package/skills/sia-review-respond/SKILL.md +88 -0
  106. package/skills/sia-review-respond/pushback-patterns.md +90 -0
  107. package/skills/sia-search/SKILL.md +47 -0
  108. package/skills/sia-setup/SKILL.md +82 -0
  109. package/skills/sia-setup/setup-checklist.md +97 -0
  110. package/skills/sia-stats/SKILL.md +36 -0
  111. package/skills/sia-status/SKILL.md +44 -0
  112. package/skills/sia-sync/SKILL.md +46 -0
  113. package/skills/sia-team/SKILL.md +64 -0
  114. package/skills/sia-test/SKILL.md +92 -0
  115. package/skills/sia-test/testing-anti-patterns.md +104 -0
  116. package/skills/sia-tour/SKILL.md +29 -0
  117. package/skills/sia-upgrade/SKILL.md +43 -0
  118. package/skills/sia-verify/SKILL.md +81 -0
  119. package/skills/sia-visualize/SKILL.md +28 -0
  120. package/skills/sia-visualize-live/SKILL.md +55 -0
  121. package/skills/sia-visualize-live/scripts/graph-template.html +389 -0
  122. package/skills/sia-visualize-live/scripts/start-visualizer.sh +161 -0
  123. package/skills/sia-visualize-live/scripts/stop-visualizer.sh +55 -0
  124. package/skills/sia-visualize-live/scripts/visualizer-server.cjs +264 -0
  125. package/skills/sia-workspace/SKILL.md +57 -0
  126. package/src/agent/claude-md-template-flagging.md +219 -0
  127. package/src/agent/claude-md-template.md +213 -0
  128. package/src/agent/modules/sia-feature.md +100 -0
  129. package/src/agent/modules/sia-flagging.md +50 -0
  130. package/src/agent/modules/sia-orientation.md +92 -0
  131. package/src/agent/modules/sia-regression.md +115 -0
  132. package/src/agent/modules/sia-review.md +64 -0
  133. package/src/agent/modules/sia-tools.md +239 -0
  134. package/src/ast/extractors/c-include.ts +189 -0
  135. package/src/ast/extractors/csharp-project.ts +260 -0
  136. package/src/ast/extractors/prisma-schema.ts +44 -0
  137. package/src/ast/extractors/project-manifest.ts +111 -0
  138. package/src/ast/extractors/sql-schema.ts +67 -0
  139. package/src/ast/extractors/tier-a.ts +423 -0
  140. package/src/ast/extractors/tier-b.ts +289 -0
  141. package/src/ast/extractors/tier-dispatch.ts +247 -0
  142. package/src/ast/index-worker.ts +108 -0
  143. package/src/ast/indexer.ts +484 -0
  144. package/src/ast/languages.ts +408 -0
  145. package/src/ast/pagerank-builder.ts +125 -0
  146. package/src/ast/path-utils.ts +137 -0
  147. package/src/ast/tree-sitter/backends/native.ts +57 -0
  148. package/src/ast/tree-sitter/backends/wasm.ts +39 -0
  149. package/src/ast/tree-sitter/call-walker.ts +44 -0
  150. package/src/ast/tree-sitter/edit-computer.ts +55 -0
  151. package/src/ast/tree-sitter/query-runner.ts +46 -0
  152. package/src/ast/tree-sitter/service.ts +174 -0
  153. package/src/ast/tree-sitter/tree-cache.ts +39 -0
  154. package/src/ast/tree-sitter/types.ts +79 -0
  155. package/src/ast/watcher.ts +322 -0
  156. package/src/capture/chunker.ts +169 -0
  157. package/src/capture/consolidate.ts +127 -0
  158. package/src/capture/edge-inferrer.ts +161 -0
  159. package/src/capture/embedder.ts +166 -0
  160. package/src/capture/embedding-cache.ts +73 -0
  161. package/src/capture/flag-processor.ts +64 -0
  162. package/src/capture/hook.ts +67 -0
  163. package/src/capture/pipeline.ts +450 -0
  164. package/src/capture/prompts/consolidate.ts +25 -0
  165. package/src/capture/prompts/edge-infer.ts +29 -0
  166. package/src/capture/prompts/extract-flagged.ts +36 -0
  167. package/src/capture/prompts/extract.ts +42 -0
  168. package/src/capture/tokenizer.ts +147 -0
  169. package/src/capture/track-a-ast.ts +93 -0
  170. package/src/capture/track-b-llm.ts +149 -0
  171. package/src/capture/types.ts +64 -0
  172. package/src/cli/commands/community.ts +137 -0
  173. package/src/cli/commands/compare.ts +123 -0
  174. package/src/cli/commands/conflicts.ts +41 -0
  175. package/src/cli/commands/digest.ts +197 -0
  176. package/src/cli/commands/disable-flagging.ts +34 -0
  177. package/src/cli/commands/doctor.ts +240 -0
  178. package/src/cli/commands/download-model.ts +161 -0
  179. package/src/cli/commands/enable-flagging.ts +34 -0
  180. package/src/cli/commands/export-knowledge.ts +208 -0
  181. package/src/cli/commands/export.ts +85 -0
  182. package/src/cli/commands/freshness.ts +164 -0
  183. package/src/cli/commands/graph.ts +51 -0
  184. package/src/cli/commands/history.ts +139 -0
  185. package/src/cli/commands/import.ts +335 -0
  186. package/src/cli/commands/install.ts +156 -0
  187. package/src/cli/commands/lead-report.ts +241 -0
  188. package/src/cli/commands/learn.ts +321 -0
  189. package/src/cli/commands/pm-report.ts +413 -0
  190. package/src/cli/commands/prune.ts +75 -0
  191. package/src/cli/commands/qa-report.ts +278 -0
  192. package/src/cli/commands/reindex.ts +104 -0
  193. package/src/cli/commands/rollback.ts +70 -0
  194. package/src/cli/commands/search.ts +103 -0
  195. package/src/cli/commands/server.ts +91 -0
  196. package/src/cli/commands/share.ts +33 -0
  197. package/src/cli/commands/stats.ts +79 -0
  198. package/src/cli/commands/status.ts +176 -0
  199. package/src/cli/commands/sync.ts +96 -0
  200. package/src/cli/commands/team.ts +118 -0
  201. package/src/cli/commands/tour.ts +157 -0
  202. package/src/cli/commands/visualize-live.ts +162 -0
  203. package/src/cli/commands/workspace.ts +117 -0
  204. package/src/cli/index.ts +424 -0
  205. package/src/cli/learn-progress.ts +87 -0
  206. package/src/community/detection-bridge.ts +344 -0
  207. package/src/community/leiden.ts +462 -0
  208. package/src/community/raptor.ts +210 -0
  209. package/src/community/scheduler.ts +74 -0
  210. package/src/community/summarize.ts +115 -0
  211. package/src/decay/archiver.ts +73 -0
  212. package/src/decay/bridge-orphan-cleanup.ts +212 -0
  213. package/src/decay/consolidation-sweep.ts +112 -0
  214. package/src/decay/decay.ts +116 -0
  215. package/src/decay/deep-validator.ts +62 -0
  216. package/src/decay/episodic-promoter.ts +132 -0
  217. package/src/decay/maintenance-scheduler.ts +326 -0
  218. package/src/decay/scheduler.ts +6 -0
  219. package/src/decay/session-sweeper.ts +79 -0
  220. package/src/decay/types.ts +17 -0
  221. package/src/freshness/confidence-decay.ts +122 -0
  222. package/src/freshness/cuckoo-filter.ts +176 -0
  223. package/src/freshness/deep-validation.ts +345 -0
  224. package/src/freshness/dirty-tracker.ts +237 -0
  225. package/src/freshness/file-watcher-layer.ts +119 -0
  226. package/src/freshness/firewall.ts +64 -0
  227. package/src/freshness/git-reconcile-layer.ts +161 -0
  228. package/src/freshness/inverted-index.ts +158 -0
  229. package/src/freshness/stale-read-layer.ts +222 -0
  230. package/src/graph/audit.ts +69 -0
  231. package/src/graph/bridge-db.ts +141 -0
  232. package/src/graph/communities.ts +195 -0
  233. package/src/graph/db-interface.ts +259 -0
  234. package/src/graph/edges.ts +163 -0
  235. package/src/graph/entities.ts +327 -0
  236. package/src/graph/episodic-db.ts +113 -0
  237. package/src/graph/flags.ts +31 -0
  238. package/src/graph/meta-db.ts +200 -0
  239. package/src/graph/semantic-db.ts +101 -0
  240. package/src/graph/session-resume.ts +56 -0
  241. package/src/graph/snapshots.ts +342 -0
  242. package/src/graph/staging.ts +151 -0
  243. package/src/graph/types.ts +128 -0
  244. package/src/hooks/adapters/claude-code.ts +21 -0
  245. package/src/hooks/adapters/cline.ts +43 -0
  246. package/src/hooks/adapters/cursor.ts +65 -0
  247. package/src/hooks/adapters/generic.ts +12 -0
  248. package/src/hooks/agent-detect.ts +34 -0
  249. package/src/hooks/claude-md-directives.ts +32 -0
  250. package/src/hooks/event-router.ts +182 -0
  251. package/src/hooks/extractors/pattern-detector.ts +111 -0
  252. package/src/hooks/handlers/post-compact.ts +30 -0
  253. package/src/hooks/handlers/post-tool-use.ts +403 -0
  254. package/src/hooks/handlers/pre-compact.ts +100 -0
  255. package/src/hooks/handlers/session-end.ts +47 -0
  256. package/src/hooks/handlers/session-start.ts +154 -0
  257. package/src/hooks/handlers/stop.ts +128 -0
  258. package/src/hooks/handlers/user-prompt-submit.ts +68 -0
  259. package/src/hooks/plugin-branch-switch.ts +68 -0
  260. package/src/hooks/plugin-common.ts +47 -0
  261. package/src/hooks/plugin-post-compact.ts +28 -0
  262. package/src/hooks/plugin-post-tool-use.ts +38 -0
  263. package/src/hooks/plugin-pre-compact.ts +37 -0
  264. package/src/hooks/plugin-session-end.ts +37 -0
  265. package/src/hooks/plugin-session-start.ts +75 -0
  266. package/src/hooks/plugin-stop.ts +61 -0
  267. package/src/hooks/plugin-user-prompt-submit.ts +47 -0
  268. package/src/hooks/types.ts +43 -0
  269. package/src/knowledge/discovery.ts +238 -0
  270. package/src/knowledge/external-refs.ts +98 -0
  271. package/src/knowledge/freshness.ts +221 -0
  272. package/src/knowledge/ingest.ts +330 -0
  273. package/src/knowledge/markdown-export.ts +229 -0
  274. package/src/knowledge/markdown-import.ts +359 -0
  275. package/src/knowledge/patterns.ts +74 -0
  276. package/src/knowledge/templates.ts +307 -0
  277. package/src/llm/ai-sdk-adapter.ts +46 -0
  278. package/src/llm/config.ts +88 -0
  279. package/src/llm/cost-tracker.ts +110 -0
  280. package/src/llm/prompts/extraction.ts +55 -0
  281. package/src/llm/prompts/summarization.ts +36 -0
  282. package/src/llm/prompts/validation.ts +37 -0
  283. package/src/llm/provider-registry.ts +68 -0
  284. package/src/llm/reliability.ts +179 -0
  285. package/src/llm/schemas.ts +52 -0
  286. package/src/mcp/freshness-annotator.ts +69 -0
  287. package/src/mcp/server.ts +949 -0
  288. package/src/mcp/tools/sia-ast-query.ts +225 -0
  289. package/src/mcp/tools/sia-at-time.ts +151 -0
  290. package/src/mcp/tools/sia-backlinks.ts +87 -0
  291. package/src/mcp/tools/sia-batch-execute.ts +169 -0
  292. package/src/mcp/tools/sia-by-file.ts +89 -0
  293. package/src/mcp/tools/sia-community.ts +113 -0
  294. package/src/mcp/tools/sia-doctor.ts +73 -0
  295. package/src/mcp/tools/sia-execute-file.ts +122 -0
  296. package/src/mcp/tools/sia-execute.ts +104 -0
  297. package/src/mcp/tools/sia-expand.ts +158 -0
  298. package/src/mcp/tools/sia-fetch-and-index.ts +241 -0
  299. package/src/mcp/tools/sia-flag.ts +65 -0
  300. package/src/mcp/tools/sia-index.ts +111 -0
  301. package/src/mcp/tools/sia-note.ts +134 -0
  302. package/src/mcp/tools/sia-search.ts +105 -0
  303. package/src/mcp/tools/sia-stats.ts +63 -0
  304. package/src/mcp/tools/sia-sync-status.ts +44 -0
  305. package/src/mcp/tools/sia-upgrade.ts +247 -0
  306. package/src/mcp/truncate.ts +231 -0
  307. package/src/native/bridge.ts +167 -0
  308. package/src/native/fallback-ast-diff.ts +144 -0
  309. package/src/native/fallback-graph.ts +325 -0
  310. package/src/ontology/constraints.ts +56 -0
  311. package/src/ontology/errors.ts +8 -0
  312. package/src/ontology/middleware.ts +266 -0
  313. package/src/retrieval/bm25-search.ts +151 -0
  314. package/src/retrieval/context-assembly.ts +76 -0
  315. package/src/retrieval/graph-traversal.ts +168 -0
  316. package/src/retrieval/pagerank.ts +40 -0
  317. package/src/retrieval/query-classifier.ts +106 -0
  318. package/src/retrieval/reranker.ts +156 -0
  319. package/src/retrieval/search.ts +236 -0
  320. package/src/retrieval/throttle.ts +102 -0
  321. package/src/retrieval/vector-search.ts +203 -0
  322. package/src/retrieval/workspace-search.ts +130 -0
  323. package/src/sandbox/context-mode.ts +285 -0
  324. package/src/sandbox/credential-pass.ts +55 -0
  325. package/src/sandbox/executor.ts +235 -0
  326. package/src/security/pattern-detector.ts +127 -0
  327. package/src/security/rule-of-two.ts +50 -0
  328. package/src/security/sanitize.ts +46 -0
  329. package/src/security/semantic-consistency.ts +93 -0
  330. package/src/security/staging-promoter.ts +154 -0
  331. package/src/shared/config.ts +302 -0
  332. package/src/shared/diagnostics.ts +210 -0
  333. package/src/shared/errors.ts +48 -0
  334. package/src/shared/git-utils.ts +143 -0
  335. package/src/shared/llm-client.ts +120 -0
  336. package/src/shared/logger.ts +99 -0
  337. package/src/shared/types.ts +79 -0
  338. package/src/sync/client.ts +43 -0
  339. package/src/sync/conflict.ts +106 -0
  340. package/src/sync/dedup.ts +183 -0
  341. package/src/sync/hlc.ts +117 -0
  342. package/src/sync/keychain.ts +144 -0
  343. package/src/sync/pull.ts +232 -0
  344. package/src/sync/push.ts +131 -0
  345. package/src/types/chokidar.d.ts +23 -0
  346. package/src/visualization/graph-renderer.ts +312 -0
  347. package/src/visualization/subgraph-extract.ts +208 -0
  348. package/src/visualization/views/community-clusters.ts +246 -0
  349. package/src/visualization/views/dependency-map.ts +189 -0
  350. package/src/visualization/views/graph-explorer.ts +364 -0
  351. package/src/visualization/views/timeline.ts +247 -0
  352. package/src/workspace/api-contracts.ts +226 -0
  353. package/src/workspace/cross-repo.ts +61 -0
  354. package/src/workspace/detector.ts +190 -0
  355. package/src/workspace/manifest.ts +141 -0
@@ -0,0 +1,57 @@
1
+ export interface ParserBackend {
2
+ type: "native" | "wasm";
3
+ createParser(): unknown;
4
+ loadLanguage(grammarPackage: string, entrypoint?: string): Promise<unknown>;
5
+ setTimeoutMicros(parser: unknown, micros: number): void;
6
+ parse(parser: unknown, source: string, language: unknown, previousTree?: unknown): unknown | null;
7
+ query(language: unknown, querySource: string): unknown;
8
+ getChangedRanges(
9
+ oldTree: unknown,
10
+ newTree: unknown,
11
+ ): Array<{
12
+ startPosition: { row: number; column: number };
13
+ endPosition: { row: number; column: number };
14
+ startIndex: number;
15
+ endIndex: number;
16
+ }>;
17
+ }
18
+
19
+ export async function tryLoadNativeBackend(): Promise<ParserBackend | null> {
20
+ try {
21
+ const Parser = (await import("tree-sitter")).default;
22
+
23
+ return {
24
+ type: "native",
25
+ createParser() {
26
+ return new Parser();
27
+ },
28
+ async loadLanguage(grammarPackage: string, entrypoint?: string) {
29
+ const mod = await import(grammarPackage);
30
+ const lang = entrypoint ? (mod[entrypoint] ?? mod.default) : (mod.default ?? mod);
31
+ return lang;
32
+ },
33
+ setTimeoutMicros(parser: any, micros: number) {
34
+ if (typeof parser.setTimeoutMicros === "function") {
35
+ parser.setTimeoutMicros(micros);
36
+ }
37
+ },
38
+ parse(parser: any, source: string, language: unknown, previousTree?: unknown) {
39
+ parser.setLanguage(language);
40
+ return parser.parse(source, previousTree as any) ?? null;
41
+ },
42
+ query(language: any, querySource: string) {
43
+ // biome-ignore lint: dynamic require needed for native module
44
+ var NativeParser = require("tree-sitter");
45
+ return new NativeParser.Query(language, querySource);
46
+ },
47
+ getChangedRanges(oldTree: any, newTree: any) {
48
+ if (typeof oldTree.getChangedRanges === "function") {
49
+ return oldTree.getChangedRanges(newTree);
50
+ }
51
+ return [];
52
+ },
53
+ };
54
+ } catch {
55
+ return null;
56
+ }
57
+ }
@@ -0,0 +1,39 @@
1
+ import type { ParserBackend } from "./native";
2
+
3
+ export async function tryLoadWasmBackend(): Promise<ParserBackend | null> {
4
+ try {
5
+ const mod = await import("web-tree-sitter");
6
+ const TreeSitter = mod.default as any;
7
+ await TreeSitter.init();
8
+
9
+ return {
10
+ type: "wasm",
11
+ createParser() {
12
+ return new TreeSitter();
13
+ },
14
+ async loadLanguage(wasmPath: string, _entrypoint?: string) {
15
+ return await TreeSitter.Language.load(wasmPath);
16
+ },
17
+ setTimeoutMicros(parser: any, micros: number) {
18
+ if (typeof parser.setTimeoutMicros === "function") {
19
+ parser.setTimeoutMicros(micros);
20
+ }
21
+ },
22
+ parse(parser: any, source: string, language: unknown, previousTree?: unknown) {
23
+ parser.setLanguage(language);
24
+ return parser.parse(source, previousTree as any) ?? null;
25
+ },
26
+ query(language: any, querySource: string) {
27
+ return language.query(querySource);
28
+ },
29
+ getChangedRanges(oldTree: any, newTree: any) {
30
+ if (typeof oldTree.getChangedRanges === "function") {
31
+ return oldTree.getChangedRanges(newTree);
32
+ }
33
+ return [];
34
+ },
35
+ };
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
@@ -0,0 +1,44 @@
1
+ import type { NodeVisitor, Point } from "./types";
2
+
3
+ export interface WalkResult {
4
+ nodesVisited: number;
5
+ }
6
+
7
+ export function walkTree(tree: any, visitor: NodeVisitor): WalkResult {
8
+ const cursor = tree.rootNode.walk();
9
+ let nodesVisited = 0;
10
+ let reachedRoot = false;
11
+
12
+ while (!reachedRoot) {
13
+ const nodeType: string = cursor.nodeType;
14
+ const nodeText: string = cursor.nodeText;
15
+ const startPosition: Point = cursor.startPosition;
16
+ const endPosition: Point = cursor.endPosition;
17
+
18
+ nodesVisited++;
19
+ const shouldDescend = visitor.enter?.(nodeType, nodeText, startPosition, endPosition);
20
+
21
+ if (shouldDescend !== false && cursor.gotoFirstChild()) {
22
+ continue;
23
+ }
24
+
25
+ visitor.leave?.(nodeType, nodeText, startPosition, endPosition);
26
+
27
+ if (cursor.gotoNextSibling()) {
28
+ continue;
29
+ }
30
+
31
+ while (true) {
32
+ if (!cursor.gotoParent()) {
33
+ reachedRoot = true;
34
+ break;
35
+ }
36
+ visitor.leave?.(cursor.nodeType, cursor.nodeText, cursor.startPosition, cursor.endPosition);
37
+ if (cursor.gotoNextSibling()) {
38
+ break;
39
+ }
40
+ }
41
+ }
42
+
43
+ return { nodesVisited };
44
+ }
@@ -0,0 +1,55 @@
1
+ import type { InputEdit, Point } from "./types";
2
+
3
+ export function computeEdits(oldSource: string, newSource: string): InputEdit[] {
4
+ if (oldSource === newSource) return [];
5
+
6
+ const oldLines = oldSource.split("\n");
7
+ const newLines = newSource.split("\n");
8
+
9
+ let topMatch = 0;
10
+ while (
11
+ topMatch < oldLines.length &&
12
+ topMatch < newLines.length &&
13
+ oldLines[topMatch] === newLines[topMatch]
14
+ ) {
15
+ topMatch++;
16
+ }
17
+
18
+ let oldBottom = oldLines.length - 1;
19
+ let newBottom = newLines.length - 1;
20
+ while (
21
+ oldBottom > topMatch &&
22
+ newBottom > topMatch &&
23
+ oldLines[oldBottom] === newLines[newBottom]
24
+ ) {
25
+ oldBottom--;
26
+ newBottom--;
27
+ }
28
+
29
+ const startIndex = byteOffsetForLine(oldLines, topMatch);
30
+ const oldEndIndex = byteOffsetForLine(oldLines, oldBottom + 1);
31
+ const newEndIndex = byteOffsetForLine(newLines, newBottom + 1);
32
+
33
+ const startPosition: Point = { row: topMatch, column: 0 };
34
+ const oldEndPosition: Point = { row: oldBottom + 1, column: 0 };
35
+ const newEndPosition: Point = { row: newBottom + 1, column: 0 };
36
+
37
+ return [
38
+ {
39
+ startIndex,
40
+ oldEndIndex,
41
+ newEndIndex,
42
+ startPosition,
43
+ oldEndPosition,
44
+ newEndPosition,
45
+ },
46
+ ];
47
+ }
48
+
49
+ function byteOffsetForLine(lines: string[], lineIndex: number): number {
50
+ let offset = 0;
51
+ for (let i = 0; i < lineIndex && i < lines.length; i++) {
52
+ offset += Buffer.byteLength(lines[i], "utf-8") + 1;
53
+ }
54
+ return offset;
55
+ }
@@ -0,0 +1,46 @@
1
+ import { readFileSync } from "node:fs";
2
+ import type { SiaQueryCapture, SiaQueryMatch } from "./types";
3
+
4
+ const querySourceCache = new Map<string, string>();
5
+
6
+ export function loadQuerySource(queryPath: string): string {
7
+ const cached = querySourceCache.get(queryPath);
8
+ if (cached) return cached;
9
+ const source = readFileSync(queryPath, "utf-8");
10
+ querySourceCache.set(queryPath, source);
11
+ return source;
12
+ }
13
+
14
+ export function mapMatchesToSiaMatches(
15
+ rawMatches: Array<{
16
+ pattern: number;
17
+ captures: Array<{
18
+ name: string;
19
+ node: {
20
+ text: string;
21
+ startPosition: { row: number; column: number };
22
+ endPosition: { row: number; column: number };
23
+ startIndex: number;
24
+ endIndex: number;
25
+ };
26
+ }>;
27
+ }>,
28
+ ): SiaQueryMatch[] {
29
+ return rawMatches.map((match) => ({
30
+ patternIndex: match.pattern,
31
+ captures: match.captures.map(
32
+ (cap): SiaQueryCapture => ({
33
+ name: cap.name,
34
+ text: cap.node.text,
35
+ startPosition: cap.node.startPosition,
36
+ endPosition: cap.node.endPosition,
37
+ startIndex: cap.node.startIndex,
38
+ endIndex: cap.node.endIndex,
39
+ }),
40
+ ),
41
+ }));
42
+ }
43
+
44
+ export function clearQueryCache(): void {
45
+ querySourceCache.clear();
46
+ }
@@ -0,0 +1,174 @@
1
+ import { join } from "node:path";
2
+ import { type LanguageConfig, resolveLanguageConfig } from "@/ast/languages";
3
+ import type { TreeSitterConfig } from "@/shared/config";
4
+ import type { ParserBackend } from "./backends/native";
5
+ import { tryLoadNativeBackend } from "./backends/native";
6
+ import { tryLoadWasmBackend } from "./backends/wasm";
7
+ import { walkTree } from "./call-walker";
8
+ import { loadQuerySource, mapMatchesToSiaMatches } from "./query-runner";
9
+ import { TreeCache } from "./tree-cache";
10
+ import type {
11
+ ITreeSitterService,
12
+ NodeVisitor,
13
+ Point,
14
+ SiaQueryMatch,
15
+ TreeSitterBackend,
16
+ TreeSitterRange,
17
+ } from "./types";
18
+
19
+ export class TreeSitterService implements ITreeSitterService {
20
+ private _backend: TreeSitterBackend = "unavailable";
21
+ private parserBackend: ParserBackend | null = null;
22
+ private parser: unknown = null;
23
+ private languages = new Map<string, unknown>();
24
+ private treeCache: TreeCache;
25
+ private initialized = false;
26
+ private initPromise: Promise<void> | null = null;
27
+
28
+ constructor(private readonly config: TreeSitterConfig) {
29
+ this.treeCache = new TreeCache(config.maxCachedTrees);
30
+ }
31
+
32
+ get backend(): TreeSitterBackend {
33
+ return this._backend;
34
+ }
35
+
36
+ get cache(): TreeCache {
37
+ return this.treeCache;
38
+ }
39
+
40
+ async initialize(): Promise<void> {
41
+ if (this.initialized) return;
42
+ if (this.initPromise) return this.initPromise;
43
+ this.initPromise = this._initialize();
44
+ await this.initPromise;
45
+ }
46
+
47
+ private async _initialize(): Promise<void> {
48
+ if (!this.config.enabled) {
49
+ this._backend = "unavailable";
50
+ this.initialized = true;
51
+ return;
52
+ }
53
+
54
+ if (this.config.preferNative) {
55
+ this.parserBackend = await tryLoadNativeBackend();
56
+ if (this.parserBackend) {
57
+ this._backend = "native";
58
+ this.parser = this.parserBackend.createParser();
59
+ this.parserBackend.setTimeoutMicros(this.parser, this.config.parseTimeoutMs * 1000);
60
+ this.initialized = true;
61
+ return;
62
+ }
63
+ }
64
+
65
+ this.parserBackend = await tryLoadWasmBackend();
66
+ if (this.parserBackend) {
67
+ this._backend = "wasm";
68
+ this.parser = this.parserBackend.createParser();
69
+ this.parserBackend.setTimeoutMicros(this.parser, this.config.parseTimeoutMs * 1000);
70
+ this.initialized = true;
71
+ return;
72
+ }
73
+
74
+ this._backend = "unavailable";
75
+ this.initialized = true;
76
+ }
77
+
78
+ private async ensureLanguage(langConfig: LanguageConfig): Promise<unknown | null> {
79
+ const resolved = resolveLanguageConfig(langConfig);
80
+ const key = `${resolved.nativePackage}:${resolved.parserEntrypoint ?? "default"}`;
81
+ const cached = this.languages.get(key);
82
+ if (cached) return cached;
83
+ if (!this.parserBackend) return null;
84
+
85
+ try {
86
+ let grammarRef: string;
87
+ if (this._backend === "wasm") {
88
+ grammarRef = join(this.config.wasmDir, resolved.wasmFile);
89
+ } else {
90
+ grammarRef = resolved.nativePackage;
91
+ }
92
+ const language = await this.parserBackend.loadLanguage(grammarRef, resolved.parserEntrypoint);
93
+ this.languages.set(key, language);
94
+ return language;
95
+ } catch {
96
+ return null;
97
+ }
98
+ }
99
+
100
+ async parse(source: string, langName: string, previousTree?: unknown): Promise<unknown | null> {
101
+ await this.initialize();
102
+ if (!this.parserBackend || !this.parser) return null;
103
+
104
+ const { LANGUAGE_REGISTRY } = await import("@/ast/languages");
105
+ const langConfig = LANGUAGE_REGISTRY[langName];
106
+ if (!langConfig) return null;
107
+
108
+ const language = await this.ensureLanguage(langConfig);
109
+ if (!language) return null;
110
+
111
+ try {
112
+ return this.parserBackend.parse(this.parser, source, language, previousTree);
113
+ } catch {
114
+ return null;
115
+ }
116
+ }
117
+
118
+ query(
119
+ tree: unknown,
120
+ querySchemePath: string,
121
+ startPosition?: Point,
122
+ endPosition?: Point,
123
+ ): SiaQueryMatch[] {
124
+ if (!this.parserBackend || !tree) return [];
125
+ try {
126
+ const querySource = loadQuerySource(querySchemePath);
127
+ const treeAny = tree as any;
128
+ const language = treeAny.getLanguage?.() ?? treeAny.rootNode?.language;
129
+ if (!language) return [];
130
+
131
+ const queryObj = this.parserBackend.query(language, querySource);
132
+ const queryAny = queryObj as any;
133
+
134
+ const options: any = {};
135
+ if (startPosition) options.startPosition = startPosition;
136
+ if (endPosition) options.endPosition = endPosition;
137
+
138
+ const rootNode = treeAny.rootNode ?? treeAny;
139
+ const matches = queryAny.matches?.(rootNode, options) ?? [];
140
+ return mapMatchesToSiaMatches(matches);
141
+ } catch {
142
+ return [];
143
+ }
144
+ }
145
+
146
+ walk(tree: unknown, visitor: NodeVisitor): void {
147
+ walkTree(tree, visitor);
148
+ }
149
+
150
+ getChangedRanges(oldTree: unknown, newTree: unknown): TreeSitterRange[] {
151
+ if (!this.parserBackend) return [];
152
+ try {
153
+ const ranges = this.parserBackend.getChangedRanges(oldTree, newTree);
154
+ return ranges.map((r) => ({
155
+ startPosition: r.startPosition,
156
+ endPosition: r.endPosition,
157
+ startIndex: r.startIndex,
158
+ endIndex: r.endIndex,
159
+ }));
160
+ } catch {
161
+ return [];
162
+ }
163
+ }
164
+
165
+ dispose(): void {
166
+ this.treeCache.clear();
167
+ this.languages.clear();
168
+ this.parser = null;
169
+ this.parserBackend = null;
170
+ this._backend = "unavailable";
171
+ this.initialized = false;
172
+ this.initPromise = null;
173
+ }
174
+ }
@@ -0,0 +1,39 @@
1
+ export interface TreeCacheEntry {
2
+ tree: unknown;
3
+ source: string;
4
+ }
5
+
6
+ export class TreeCache {
7
+ private cache = new Map<string, TreeCacheEntry>();
8
+
9
+ constructor(private readonly maxSize: number) {}
10
+
11
+ get size(): number {
12
+ return this.cache.size;
13
+ }
14
+
15
+ get(filePath: string): TreeCacheEntry | undefined {
16
+ const entry = this.cache.get(filePath);
17
+ if (!entry) return undefined;
18
+ this.cache.delete(filePath);
19
+ this.cache.set(filePath, entry);
20
+ return entry;
21
+ }
22
+
23
+ set(filePath: string, tree: unknown, source: string): void {
24
+ this.cache.delete(filePath);
25
+ if (this.cache.size >= this.maxSize) {
26
+ const oldest = this.cache.keys().next().value!;
27
+ this.cache.delete(oldest);
28
+ }
29
+ this.cache.set(filePath, { tree, source });
30
+ }
31
+
32
+ delete(filePath: string): boolean {
33
+ return this.cache.delete(filePath);
34
+ }
35
+
36
+ clear(): void {
37
+ this.cache.clear();
38
+ }
39
+ }
@@ -0,0 +1,79 @@
1
+ /** Which tree-sitter backend is active */
2
+ export type TreeSitterBackend = "native" | "wasm" | "unavailable";
3
+
4
+ /** Position in source code (0-indexed row/column) */
5
+ export interface Point {
6
+ row: number;
7
+ column: number;
8
+ }
9
+
10
+ /** A range in the source code */
11
+ export interface TreeSitterRange {
12
+ startPosition: Point;
13
+ endPosition: Point;
14
+ startIndex: number;
15
+ endIndex: number;
16
+ }
17
+
18
+ /** A single captured node from a .scm query */
19
+ export interface SiaQueryCapture {
20
+ name: string;
21
+ text: string;
22
+ startPosition: Point;
23
+ endPosition: Point;
24
+ startIndex: number;
25
+ endIndex: number;
26
+ }
27
+
28
+ /** A full match from a .scm query (may contain multiple captures) */
29
+ export interface SiaQueryMatch {
30
+ patternIndex: number;
31
+ captures: SiaQueryCapture[];
32
+ }
33
+
34
+ /** Tree-sitter InputEdit for incremental re-parsing */
35
+ export interface InputEdit {
36
+ startIndex: number;
37
+ oldEndIndex: number;
38
+ newEndIndex: number;
39
+ startPosition: Point;
40
+ oldEndPosition: Point;
41
+ newEndPosition: Point;
42
+ }
43
+
44
+ /** Visitor callbacks for programmatic tree traversal */
45
+ export interface NodeVisitor {
46
+ /** Called for each node. Return false to skip children. */
47
+ enter?(
48
+ nodeType: string,
49
+ text: string,
50
+ startPosition: Point,
51
+ endPosition: Point,
52
+ ): boolean | undefined;
53
+ /** Called after all children have been visited */
54
+ leave?(nodeType: string, text: string, startPosition: Point, endPosition: Point): void;
55
+ }
56
+
57
+ /**
58
+ * Core tree-sitter service interface.
59
+ * Encapsulates native/WASM duality behind a single API.
60
+ */
61
+ export interface ITreeSitterService {
62
+ /** Which backend was loaded: native, wasm, or unavailable */
63
+ readonly backend: TreeSitterBackend;
64
+
65
+ parse(source: string, langName: string, previousTree?: unknown): unknown | null;
66
+
67
+ query(
68
+ tree: unknown,
69
+ querySchemePath: string,
70
+ startPosition?: Point,
71
+ endPosition?: Point,
72
+ ): SiaQueryMatch[];
73
+
74
+ walk(tree: unknown, visitor: NodeVisitor): void;
75
+
76
+ getChangedRanges(oldTree: unknown, newTree: unknown): TreeSitterRange[];
77
+
78
+ dispose(): void;
79
+ }