@getrift/rift 0.1.0-beta.21 → 0.1.0-beta.23

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 (320) hide show
  1. package/README.md +7 -3
  2. package/dist/src/capture/auto-capture.d.ts +105 -4
  3. package/dist/src/capture/auto-capture.d.ts.map +1 -1
  4. package/dist/src/capture/auto-capture.js +313 -34
  5. package/dist/src/capture/auto-capture.js.map +1 -1
  6. package/dist/src/capture/claude-cli-triage-provider.d.ts +28 -0
  7. package/dist/src/capture/claude-cli-triage-provider.d.ts.map +1 -0
  8. package/dist/src/capture/claude-cli-triage-provider.js +88 -0
  9. package/dist/src/capture/claude-cli-triage-provider.js.map +1 -0
  10. package/dist/src/capture/codex-cli-triage-provider.d.ts.map +1 -1
  11. package/dist/src/capture/codex-cli-triage-provider.js +1 -33
  12. package/dist/src/capture/codex-cli-triage-provider.js.map +1 -1
  13. package/dist/src/capture/cursor-capture.d.ts +89 -0
  14. package/dist/src/capture/cursor-capture.d.ts.map +1 -0
  15. package/dist/src/capture/cursor-capture.js +121 -0
  16. package/dist/src/capture/cursor-capture.js.map +1 -0
  17. package/dist/src/capture/observability.d.ts +30 -0
  18. package/dist/src/capture/observability.d.ts.map +1 -1
  19. package/dist/src/capture/observability.js +29 -0
  20. package/dist/src/capture/observability.js.map +1 -1
  21. package/dist/src/capture/recover-quarantine.d.ts +4 -4
  22. package/dist/src/capture/sources.d.ts +41 -3
  23. package/dist/src/capture/sources.d.ts.map +1 -1
  24. package/dist/src/capture/sources.js +43 -1
  25. package/dist/src/capture/sources.js.map +1 -1
  26. package/dist/src/capture/triage-classification.d.ts +69 -0
  27. package/dist/src/capture/triage-classification.d.ts.map +1 -0
  28. package/dist/src/capture/triage-classification.js +62 -0
  29. package/dist/src/capture/triage-classification.js.map +1 -0
  30. package/dist/src/capture/triage-provider-factory.d.ts +36 -0
  31. package/dist/src/capture/triage-provider-factory.d.ts.map +1 -0
  32. package/dist/src/capture/triage-provider-factory.js +55 -0
  33. package/dist/src/capture/triage-provider-factory.js.map +1 -0
  34. package/dist/src/capture/triage.d.ts +1 -1
  35. package/dist/src/capture/triage.d.ts.map +1 -1
  36. package/dist/src/capture/triage.js +8 -6
  37. package/dist/src/capture/triage.js.map +1 -1
  38. package/dist/src/cli/commands/capture.d.ts.map +1 -1
  39. package/dist/src/cli/commands/capture.js +79 -17
  40. package/dist/src/cli/commands/capture.js.map +1 -1
  41. package/dist/src/cli/commands/chunk-backfill.d.ts +13 -0
  42. package/dist/src/cli/commands/chunk-backfill.d.ts.map +1 -0
  43. package/dist/src/cli/commands/chunk-backfill.js +157 -0
  44. package/dist/src/cli/commands/chunk-backfill.js.map +1 -0
  45. package/dist/src/cli/commands/cursor-probe.d.ts +20 -0
  46. package/dist/src/cli/commands/cursor-probe.d.ts.map +1 -0
  47. package/dist/src/cli/commands/cursor-probe.js +162 -0
  48. package/dist/src/cli/commands/cursor-probe.js.map +1 -0
  49. package/dist/src/cli/commands/menubar.d.ts +3 -1
  50. package/dist/src/cli/commands/menubar.d.ts.map +1 -1
  51. package/dist/src/cli/commands/menubar.js +36 -12
  52. package/dist/src/cli/commands/menubar.js.map +1 -1
  53. package/dist/src/cli/commands/onboard.d.ts +22 -2
  54. package/dist/src/cli/commands/onboard.d.ts.map +1 -1
  55. package/dist/src/cli/commands/onboard.js +160 -32
  56. package/dist/src/cli/commands/onboard.js.map +1 -1
  57. package/dist/src/cli/commands/status.d.ts.map +1 -1
  58. package/dist/src/cli/commands/status.js +12 -0
  59. package/dist/src/cli/commands/status.js.map +1 -1
  60. package/dist/src/cli/commands/update.d.ts +34 -1
  61. package/dist/src/cli/commands/update.d.ts.map +1 -1
  62. package/dist/src/cli/commands/update.js +166 -1
  63. package/dist/src/cli/commands/update.js.map +1 -1
  64. package/dist/src/cli/index.d.ts.map +1 -1
  65. package/dist/src/cli/index.js +4 -0
  66. package/dist/src/cli/index.js.map +1 -1
  67. package/dist/src/cli/postinstall-menubar.d.ts +20 -13
  68. package/dist/src/cli/postinstall-menubar.d.ts.map +1 -1
  69. package/dist/src/cli/postinstall-menubar.js +56 -1
  70. package/dist/src/cli/postinstall-menubar.js.map +1 -1
  71. package/dist/src/cli/status/friend-header.d.ts +16 -3
  72. package/dist/src/cli/status/friend-header.d.ts.map +1 -1
  73. package/dist/src/cli/status/friend-header.js +186 -10
  74. package/dist/src/cli/status/friend-header.js.map +1 -1
  75. package/dist/src/cli/status/local-signals.d.ts +42 -4
  76. package/dist/src/cli/status/local-signals.d.ts.map +1 -1
  77. package/dist/src/cli/status/local-signals.js +52 -1
  78. package/dist/src/cli/status/local-signals.js.map +1 -1
  79. package/dist/src/config/schema.d.ts +220 -14
  80. package/dist/src/config/schema.d.ts.map +1 -1
  81. package/dist/src/config/schema.js +82 -7
  82. package/dist/src/config/schema.js.map +1 -1
  83. package/dist/src/diagnostics/claude-preflight.d.ts +35 -0
  84. package/dist/src/diagnostics/claude-preflight.d.ts.map +1 -0
  85. package/dist/src/diagnostics/claude-preflight.js +90 -0
  86. package/dist/src/diagnostics/claude-preflight.js.map +1 -0
  87. package/dist/src/diagnostics/codex-preflight.d.ts +1 -1
  88. package/dist/src/diagnostics/codex-preflight.d.ts.map +1 -1
  89. package/dist/src/diagnostics/codex-preflight.js +24 -0
  90. package/dist/src/diagnostics/codex-preflight.js.map +1 -1
  91. package/dist/src/diagnostics/doctor.d.ts +7 -4
  92. package/dist/src/diagnostics/doctor.d.ts.map +1 -1
  93. package/dist/src/diagnostics/doctor.js +70 -11
  94. package/dist/src/diagnostics/doctor.js.map +1 -1
  95. package/dist/src/diagnostics/memory-coverage.d.ts +54 -0
  96. package/dist/src/diagnostics/memory-coverage.d.ts.map +1 -0
  97. package/dist/src/diagnostics/memory-coverage.js +272 -0
  98. package/dist/src/diagnostics/memory-coverage.js.map +1 -0
  99. package/dist/src/diagnostics/notify.d.ts +20 -3
  100. package/dist/src/diagnostics/notify.d.ts.map +1 -1
  101. package/dist/src/diagnostics/notify.js +54 -14
  102. package/dist/src/diagnostics/notify.js.map +1 -1
  103. package/dist/src/ingestion/chunk-meta.d.ts +85 -0
  104. package/dist/src/ingestion/chunk-meta.d.ts.map +1 -0
  105. package/dist/src/ingestion/chunk-meta.js +167 -0
  106. package/dist/src/ingestion/chunk-meta.js.map +1 -0
  107. package/dist/src/ingestion/chunk-text.d.ts +39 -0
  108. package/dist/src/ingestion/chunk-text.d.ts.map +1 -0
  109. package/dist/src/ingestion/chunk-text.js +114 -0
  110. package/dist/src/ingestion/chunk-text.js.map +1 -0
  111. package/dist/src/ingestion/cursor/cursor-store.d.ts +177 -0
  112. package/dist/src/ingestion/cursor/cursor-store.d.ts.map +1 -0
  113. package/dist/src/ingestion/cursor/cursor-store.js +243 -0
  114. package/dist/src/ingestion/cursor/cursor-store.js.map +1 -0
  115. package/dist/src/ingestion/cursor/enrich-roots.d.ts +16 -0
  116. package/dist/src/ingestion/cursor/enrich-roots.d.ts.map +1 -0
  117. package/dist/src/ingestion/cursor/enrich-roots.js +22 -0
  118. package/dist/src/ingestion/cursor/enrich-roots.js.map +1 -0
  119. package/dist/src/ingestion/cursor/vscdb-reader.d.ts +32 -0
  120. package/dist/src/ingestion/cursor/vscdb-reader.d.ts.map +1 -0
  121. package/dist/src/ingestion/cursor/vscdb-reader.js +113 -0
  122. package/dist/src/ingestion/cursor/vscdb-reader.js.map +1 -0
  123. package/dist/src/ingestion/cursor/workspace-root.d.ts +96 -0
  124. package/dist/src/ingestion/cursor/workspace-root.d.ts.map +1 -0
  125. package/dist/src/ingestion/cursor/workspace-root.js +187 -0
  126. package/dist/src/ingestion/cursor/workspace-root.js.map +1 -0
  127. package/dist/src/ingestion/indexer.d.ts.map +1 -1
  128. package/dist/src/ingestion/indexer.js +41 -32
  129. package/dist/src/ingestion/indexer.js.map +1 -1
  130. package/dist/src/jobs/handlers/compact.d.ts.map +1 -1
  131. package/dist/src/jobs/handlers/compact.js +9 -4
  132. package/dist/src/jobs/handlers/compact.js.map +1 -1
  133. package/dist/src/jobs/handlers/ingest.d.ts.map +1 -1
  134. package/dist/src/jobs/handlers/ingest.js +60 -30
  135. package/dist/src/jobs/handlers/ingest.js.map +1 -1
  136. package/dist/src/jobs/handlers/reconcile.d.ts.map +1 -1
  137. package/dist/src/jobs/handlers/reconcile.js +128 -45
  138. package/dist/src/jobs/handlers/reconcile.js.map +1 -1
  139. package/dist/src/jobs/handlers/save.d.ts.map +1 -1
  140. package/dist/src/jobs/handlers/save.js +122 -72
  141. package/dist/src/jobs/handlers/save.js.map +1 -1
  142. package/dist/src/jobs/types.d.ts +1 -1
  143. package/dist/src/main.js +27 -16
  144. package/dist/src/main.js.map +1 -1
  145. package/dist/src/mcp/capture-diagnostics.d.ts +51 -0
  146. package/dist/src/mcp/capture-diagnostics.d.ts.map +1 -0
  147. package/dist/src/mcp/capture-diagnostics.js +127 -0
  148. package/dist/src/mcp/capture-diagnostics.js.map +1 -0
  149. package/dist/src/mcp/memory-diagnostics.d.ts +6 -0
  150. package/dist/src/mcp/memory-diagnostics.d.ts.map +1 -0
  151. package/dist/src/mcp/memory-diagnostics.js +51 -0
  152. package/dist/src/mcp/memory-diagnostics.js.map +1 -0
  153. package/dist/src/mcp/server.d.ts.map +1 -1
  154. package/dist/src/mcp/server.js +10 -3
  155. package/dist/src/mcp/server.js.map +1 -1
  156. package/dist/src/mcp/tools/context-pack.d.ts.map +1 -1
  157. package/dist/src/mcp/tools/context-pack.js +7 -1
  158. package/dist/src/mcp/tools/context-pack.js.map +1 -1
  159. package/dist/src/mcp/tools/conversations-search.d.ts +1 -1
  160. package/dist/src/mcp/tools/conversations-search.d.ts.map +1 -1
  161. package/dist/src/mcp/tools/conversations-search.js +7 -1
  162. package/dist/src/mcp/tools/conversations-search.js.map +1 -1
  163. package/dist/src/mcp/tools/evidence-feedback.d.ts +60 -0
  164. package/dist/src/mcp/tools/evidence-feedback.d.ts.map +1 -0
  165. package/dist/src/mcp/tools/evidence-feedback.js +62 -0
  166. package/dist/src/mcp/tools/evidence-feedback.js.map +1 -0
  167. package/dist/src/mcp/tools/log-outcome.d.ts +72 -0
  168. package/dist/src/mcp/tools/log-outcome.d.ts.map +1 -0
  169. package/dist/src/mcp/tools/log-outcome.js +59 -0
  170. package/dist/src/mcp/tools/log-outcome.js.map +1 -0
  171. package/dist/src/mcp/tools/open-evidence.d.ts +37 -0
  172. package/dist/src/mcp/tools/open-evidence.d.ts.map +1 -0
  173. package/dist/src/mcp/tools/open-evidence.js +72 -0
  174. package/dist/src/mcp/tools/open-evidence.js.map +1 -0
  175. package/dist/src/mcp/tools/save.d.ts +7 -2
  176. package/dist/src/mcp/tools/save.d.ts.map +1 -1
  177. package/dist/src/mcp/tools/save.js +7 -2
  178. package/dist/src/mcp/tools/save.js.map +1 -1
  179. package/dist/src/mcp/tools/search.d.ts.map +1 -1
  180. package/dist/src/mcp/tools/search.js +7 -1
  181. package/dist/src/mcp/tools/search.js.map +1 -1
  182. package/dist/src/mcp/tools/status.d.ts +15 -1
  183. package/dist/src/mcp/tools/status.d.ts.map +1 -1
  184. package/dist/src/mcp/tools/status.js +53 -2
  185. package/dist/src/mcp/tools/status.js.map +1 -1
  186. package/dist/src/observability/retrieval-feedback.d.ts +82 -0
  187. package/dist/src/observability/retrieval-feedback.d.ts.map +1 -0
  188. package/dist/src/observability/retrieval-feedback.js +231 -0
  189. package/dist/src/observability/retrieval-feedback.js.map +1 -0
  190. package/dist/src/observability/rift-context.d.ts.map +1 -1
  191. package/dist/src/observability/rift-context.js +3 -0
  192. package/dist/src/observability/rift-context.js.map +1 -1
  193. package/dist/src/observability/tool-usage-stats.d.ts +13 -0
  194. package/dist/src/observability/tool-usage-stats.d.ts.map +1 -1
  195. package/dist/src/observability/tool-usage-stats.js +15 -0
  196. package/dist/src/observability/tool-usage-stats.js.map +1 -1
  197. package/dist/src/observability/tool-usage.d.ts +56 -0
  198. package/dist/src/observability/tool-usage.d.ts.map +1 -1
  199. package/dist/src/observability/tool-usage.js +86 -0
  200. package/dist/src/observability/tool-usage.js.map +1 -1
  201. package/dist/src/providers/claude-cli-metadata-extraction.d.ts +47 -0
  202. package/dist/src/providers/claude-cli-metadata-extraction.d.ts.map +1 -0
  203. package/dist/src/providers/claude-cli-metadata-extraction.js +120 -0
  204. package/dist/src/providers/claude-cli-metadata-extraction.js.map +1 -0
  205. package/dist/src/providers/claude-cli-runner.d.ts +92 -0
  206. package/dist/src/providers/claude-cli-runner.d.ts.map +1 -0
  207. package/dist/src/providers/claude-cli-runner.js +598 -0
  208. package/dist/src/providers/claude-cli-runner.js.map +1 -0
  209. package/dist/src/providers/codex-cli-metadata-extraction.d.ts.map +1 -1
  210. package/dist/src/providers/codex-cli-metadata-extraction.js +1 -40
  211. package/dist/src/providers/codex-cli-metadata-extraction.js.map +1 -1
  212. package/dist/src/providers/codex-cli-runner.d.ts +7 -0
  213. package/dist/src/providers/codex-cli-runner.d.ts.map +1 -1
  214. package/dist/src/providers/codex-cli-runner.js +131 -5
  215. package/dist/src/providers/codex-cli-runner.js.map +1 -1
  216. package/dist/src/providers/conversation-generation.d.ts +10 -0
  217. package/dist/src/providers/conversation-generation.d.ts.map +1 -1
  218. package/dist/src/providers/conversation-generation.js +54 -13
  219. package/dist/src/providers/conversation-generation.js.map +1 -1
  220. package/dist/src/providers/openai-metadata-extraction.d.ts +48 -1
  221. package/dist/src/providers/openai-metadata-extraction.d.ts.map +1 -1
  222. package/dist/src/providers/openai-metadata-extraction.js +51 -2
  223. package/dist/src/providers/openai-metadata-extraction.js.map +1 -1
  224. package/dist/src/providers/types.d.ts +1 -1
  225. package/dist/src/providers/types.d.ts.map +1 -1
  226. package/dist/src/providers/types.js +4 -0
  227. package/dist/src/providers/types.js.map +1 -1
  228. package/dist/src/retrieval/canonical-files.d.ts +48 -0
  229. package/dist/src/retrieval/canonical-files.d.ts.map +1 -0
  230. package/dist/src/retrieval/canonical-files.js +210 -0
  231. package/dist/src/retrieval/canonical-files.js.map +1 -0
  232. package/dist/src/retrieval/compact.d.ts +95 -0
  233. package/dist/src/retrieval/compact.d.ts.map +1 -1
  234. package/dist/src/retrieval/compact.js +254 -8
  235. package/dist/src/retrieval/compact.js.map +1 -1
  236. package/dist/src/retrieval/context-pack.d.ts.map +1 -1
  237. package/dist/src/retrieval/context-pack.js +65 -15
  238. package/dist/src/retrieval/context-pack.js.map +1 -1
  239. package/dist/src/retrieval/conversation-dedup.d.ts +40 -0
  240. package/dist/src/retrieval/conversation-dedup.d.ts.map +1 -0
  241. package/dist/src/retrieval/conversation-dedup.js +141 -0
  242. package/dist/src/retrieval/conversation-dedup.js.map +1 -0
  243. package/dist/src/retrieval/evidence-key.d.ts +48 -0
  244. package/dist/src/retrieval/evidence-key.d.ts.map +1 -0
  245. package/dist/src/retrieval/evidence-key.js +131 -0
  246. package/dist/src/retrieval/evidence-key.js.map +1 -0
  247. package/dist/src/retrieval/feedback-ranking.d.ts +49 -0
  248. package/dist/src/retrieval/feedback-ranking.d.ts.map +1 -0
  249. package/dist/src/retrieval/feedback-ranking.js +138 -0
  250. package/dist/src/retrieval/feedback-ranking.js.map +1 -0
  251. package/dist/src/retrieval/git-state.d.ts +9 -0
  252. package/dist/src/retrieval/git-state.d.ts.map +1 -1
  253. package/dist/src/retrieval/git-state.js +18 -0
  254. package/dist/src/retrieval/git-state.js.map +1 -1
  255. package/dist/src/retrieval/group-by-parent.d.ts +38 -0
  256. package/dist/src/retrieval/group-by-parent.d.ts.map +1 -0
  257. package/dist/src/retrieval/group-by-parent.js +40 -0
  258. package/dist/src/retrieval/group-by-parent.js.map +1 -0
  259. package/dist/src/retrieval/lexical.d.ts.map +1 -1
  260. package/dist/src/retrieval/lexical.js +1 -3
  261. package/dist/src/retrieval/lexical.js.map +1 -1
  262. package/dist/src/retrieval/receipt.d.ts +57 -0
  263. package/dist/src/retrieval/receipt.d.ts.map +1 -0
  264. package/dist/src/retrieval/receipt.js +119 -0
  265. package/dist/src/retrieval/receipt.js.map +1 -0
  266. package/dist/src/retrieval/reranker.d.ts +49 -2
  267. package/dist/src/retrieval/reranker.d.ts.map +1 -1
  268. package/dist/src/retrieval/reranker.js +64 -4
  269. package/dist/src/retrieval/reranker.js.map +1 -1
  270. package/dist/src/retrieval/stitch-chunks.d.ts +73 -0
  271. package/dist/src/retrieval/stitch-chunks.d.ts.map +1 -0
  272. package/dist/src/retrieval/stitch-chunks.js +106 -0
  273. package/dist/src/retrieval/stitch-chunks.js.map +1 -0
  274. package/dist/src/server/app.d.ts +1 -1
  275. package/dist/src/server/app.d.ts.map +1 -1
  276. package/dist/src/server/app.js +20 -3
  277. package/dist/src/server/app.js.map +1 -1
  278. package/dist/src/server/routes/conversations-search.d.ts.map +1 -1
  279. package/dist/src/server/routes/conversations-search.js +22 -3
  280. package/dist/src/server/routes/conversations-search.js.map +1 -1
  281. package/dist/src/server/routes/friend-status.d.ts +64 -6
  282. package/dist/src/server/routes/friend-status.d.ts.map +1 -1
  283. package/dist/src/server/routes/friend-status.js +114 -18
  284. package/dist/src/server/routes/friend-status.js.map +1 -1
  285. package/dist/src/server/routes/mcp-usage.d.ts +9 -6
  286. package/dist/src/server/routes/mcp-usage.d.ts.map +1 -1
  287. package/dist/src/server/routes/mcp-usage.js.map +1 -1
  288. package/dist/src/server/routes/retrieval-feedback.d.ts +3 -0
  289. package/dist/src/server/routes/retrieval-feedback.d.ts.map +1 -0
  290. package/dist/src/server/routes/retrieval-feedback.js +290 -0
  291. package/dist/src/server/routes/retrieval-feedback.js.map +1 -0
  292. package/dist/src/server/routes/save.d.ts +3 -3
  293. package/dist/src/server/routes/save.d.ts.map +1 -1
  294. package/dist/src/server/routes/save.js +6 -2
  295. package/dist/src/server/routes/save.js.map +1 -1
  296. package/dist/src/server/routes/search.d.ts +1 -1
  297. package/dist/src/server/routes/search.d.ts.map +1 -1
  298. package/dist/src/server/routes/search.js +55 -8
  299. package/dist/src/server/routes/search.js.map +1 -1
  300. package/dist/src/server/serving-marker.d.ts +85 -0
  301. package/dist/src/server/serving-marker.d.ts.map +1 -0
  302. package/dist/src/server/serving-marker.js +226 -0
  303. package/dist/src/server/serving-marker.js.map +1 -0
  304. package/dist/src/storage/chunk-backfill.d.ts +39 -0
  305. package/dist/src/storage/chunk-backfill.d.ts.map +1 -0
  306. package/dist/src/storage/chunk-backfill.js +295 -0
  307. package/dist/src/storage/chunk-backfill.js.map +1 -0
  308. package/dist/src/storage/filter.d.ts +42 -0
  309. package/dist/src/storage/filter.d.ts.map +1 -0
  310. package/dist/src/storage/filter.js +70 -0
  311. package/dist/src/storage/filter.js.map +1 -0
  312. package/dist/src/storage/rebuild.d.ts.map +1 -1
  313. package/dist/src/storage/rebuild.js +44 -27
  314. package/dist/src/storage/rebuild.js.map +1 -1
  315. package/dist/src/storage/tables.d.ts +41 -0
  316. package/dist/src/storage/tables.d.ts.map +1 -1
  317. package/dist/src/storage/tables.js +64 -1
  318. package/dist/src/storage/tables.js.map +1 -1
  319. package/operator/swiftbar/render-menu.py +60 -18
  320. package/package.json +6 -4
@@ -0,0 +1,243 @@
1
+ import { resolveProjectRoot, } from "./workspace-root.js";
2
+ const ITEM_KEY_COMPOSER_HEADERS = "composer.composerHeaders";
3
+ const KV_PREFIX_COMPOSER_DATA = "composerData:";
4
+ const KV_PREFIX_BUBBLE = "bubbleId:";
5
+ const BUBBLE_TYPE_USER = 1;
6
+ const BUBBLE_TYPE_ASSISTANT = 2;
7
+ function safeJsonParse(value) {
8
+ try {
9
+ return JSON.parse(value);
10
+ }
11
+ catch {
12
+ return null;
13
+ }
14
+ }
15
+ function indexByKey(rows) {
16
+ const map = new Map();
17
+ for (const row of rows)
18
+ map.set(row.key, row.value);
19
+ return map;
20
+ }
21
+ function epochMsToIso(ms) {
22
+ if (typeof ms !== "number" || !Number.isFinite(ms) || ms <= 0)
23
+ return null;
24
+ return new Date(ms).toISOString();
25
+ }
26
+ /**
27
+ * Map a Cursor model label to a coarse backend. Cursor records its OWN labels
28
+ * (e.g. "composer-2.5"), not raw provider ids, and very often "default" (the
29
+ * account-level pick), which is NOT resolvable from local artifacts. This is a
30
+ * best-effort heuristic — see "Unknowns" in the discovery doc.
31
+ */
32
+ export function classifyBackend(modelName) {
33
+ if (!modelName)
34
+ return "unknown";
35
+ const m = modelName.toLowerCase();
36
+ if (m === "default" || m === "auto")
37
+ return "default";
38
+ if (m.startsWith("composer") || m.startsWith("cursor"))
39
+ return "cursor_native";
40
+ if (m.includes("claude") || m.includes("sonnet") || m.includes("opus") || m.includes("haiku")) {
41
+ return "anthropic";
42
+ }
43
+ if (m.startsWith("gpt") || /^o\d/.test(m) || m.includes("openai") || m.includes("chatgpt")) {
44
+ return "openai";
45
+ }
46
+ if (m.includes("gemini"))
47
+ return "google";
48
+ return "unknown";
49
+ }
50
+ /**
51
+ * Stable, deterministic session key for idempotent capture. composerId is a
52
+ * UUID minted once per session by Cursor and never reused, so it is the natural
53
+ * idempotency anchor. Prefixed by source so it can't collide with CLI keys.
54
+ *
55
+ * Change detection across re-captures is a SEPARATE concern: pair this key with
56
+ * a content fingerprint (see {@link cursorConversationFingerprintInput}) and the
57
+ * session's lastUpdatedAt, exactly as the CLI lanes do. Designing this now
58
+ * satisfies the "stable key before any scheduled capture" requirement.
59
+ */
60
+ export function cursorSessionKey(composerId) {
61
+ return `cursor_composer:${composerId}`;
62
+ }
63
+ /**
64
+ * Discover native Cursor composer/chat sessions from raw vscdb rows.
65
+ *
66
+ * Pure and side-effect free. Uses ONLY the session index + per-session metadata
67
+ * rows — never bubble bodies — so discovery reveals no private message text.
68
+ * Sessions are returned newest-updated first.
69
+ */
70
+ export function discoverCursorComposerSessions(raw) {
71
+ const items = indexByKey(raw.itemTable);
72
+ const headersRaw = items.get(ITEM_KEY_COMPOSER_HEADERS);
73
+ const index = headersRaw
74
+ ? safeJsonParse(headersRaw)
75
+ : null;
76
+ // Body rows, indexed by composerId, give us authoritative model + turn count.
77
+ const bodyById = new Map();
78
+ for (const row of raw.cursorDiskKV) {
79
+ if (!row.key.startsWith(KV_PREFIX_COMPOSER_DATA))
80
+ continue;
81
+ const body = safeJsonParse(row.value);
82
+ if (!body)
83
+ continue;
84
+ const id = body.composerId ?? row.key.slice(KV_PREFIX_COMPOSER_DATA.length);
85
+ if (id)
86
+ bodyById.set(id, body);
87
+ }
88
+ // Prefer the header index as the session roster (it is the UI source of
89
+ // truth); fall back to body rows if the index is missing/corrupt.
90
+ const headers = index?.allComposers ?? [];
91
+ const seen = new Set();
92
+ const candidates = [];
93
+ const pushCandidate = (composerId, header, body) => {
94
+ if (!composerId || seen.has(composerId))
95
+ return;
96
+ seen.add(composerId);
97
+ const modelName = body?.modelConfig?.modelName ?? null;
98
+ const created = header?.createdAt ?? body?.createdAt;
99
+ const updated = header?.lastUpdatedAt ?? body?.lastUpdatedAt;
100
+ // Pure (inline-uri-only) resolution — discovery never touches the fs. The
101
+ // probe upgrades any legacy `unresolved` row via the workspace.json join.
102
+ const resolution = resolveProjectRoot(header?.workspaceIdentifier);
103
+ candidates.push({
104
+ composerId,
105
+ name: header?.name ?? body?.name ?? null,
106
+ mode: header?.unifiedMode ?? body?.unifiedMode ?? null,
107
+ modelName,
108
+ backend: classifyBackend(modelName),
109
+ workspaceId: header?.workspaceIdentifier?.id ?? null,
110
+ projectRoot: resolution.status === "resolved" ? resolution.root : null,
111
+ projectRootSource: resolution.status === "resolved" ? resolution.source : null,
112
+ projectRootStatus: resolution.status,
113
+ createdAt: epochMsToIso(created),
114
+ updatedAt: epochMsToIso(updated),
115
+ turnCount: body?.fullConversationHeadersOnly?.length ?? 0,
116
+ isDraft: header?.isDraft === true,
117
+ hasBody: body !== undefined,
118
+ });
119
+ };
120
+ for (const header of headers) {
121
+ if (!header?.composerId)
122
+ continue;
123
+ pushCandidate(header.composerId, header, bodyById.get(header.composerId));
124
+ }
125
+ // Bodies present but absent from the index (orphans) still get surfaced.
126
+ for (const [composerId, body] of bodyById) {
127
+ pushCandidate(composerId, undefined, body);
128
+ }
129
+ return candidates.sort((a, b) => {
130
+ const at = a.updatedAt ?? a.createdAt ?? "";
131
+ const bt = b.updatedAt ?? b.createdAt ?? "";
132
+ return bt.localeCompare(at);
133
+ });
134
+ }
135
+ /** Build the proposed provenance row for a candidate (design artifact only). */
136
+ export function proposeCursorProvenance(candidate) {
137
+ return {
138
+ source: "cursor_composer",
139
+ source_app: "cursor",
140
+ source_session_id: candidate.composerId,
141
+ idempotency_key: cursorSessionKey(candidate.composerId),
142
+ workspace_id: candidate.workspaceId,
143
+ project_root: candidate.projectRoot,
144
+ project_root_source: candidate.projectRootSource,
145
+ model_name: candidate.modelName,
146
+ backend: candidate.backend,
147
+ mode: candidate.mode,
148
+ created_at: candidate.createdAt,
149
+ updated_at: candidate.updatedAt,
150
+ };
151
+ }
152
+ /**
153
+ * Collect a session's bubbles in conversation order. Order comes from the
154
+ * session body's `fullConversationHeadersOnly` when present; otherwise we fall
155
+ * back to whatever bubble rows exist for this composer, in key order. Returns
156
+ * EVERY referenced bubble (including empty/tool-only ones) so callers — notably
157
+ * the fingerprint — can see structural changes that carry no prose.
158
+ */
159
+ export function collectOrderedBubbles(raw, composerId) {
160
+ const kv = indexByKey(raw.cursorDiskKV);
161
+ const bodyRaw = kv.get(`${KV_PREFIX_COMPOSER_DATA}${composerId}`);
162
+ const body = bodyRaw ? safeJsonParse(bodyRaw) : null;
163
+ let order;
164
+ if (body?.fullConversationHeadersOnly?.length) {
165
+ order = body.fullConversationHeadersOnly
166
+ .map((h) => h.bubbleId)
167
+ .filter((id) => typeof id === "string");
168
+ }
169
+ else {
170
+ const prefix = `${KV_PREFIX_BUBBLE}${composerId}:`;
171
+ order = raw.cursorDiskKV
172
+ .filter((r) => r.key.startsWith(prefix))
173
+ .map((r) => r.key.slice(prefix.length))
174
+ .sort();
175
+ }
176
+ const bubbles = [];
177
+ for (const bubbleId of order) {
178
+ const bubbleRaw = kv.get(`${KV_PREFIX_BUBBLE}${composerId}:${bubbleId}`);
179
+ if (!bubbleRaw)
180
+ continue;
181
+ const bubble = safeJsonParse(bubbleRaw);
182
+ if (!bubble)
183
+ continue;
184
+ bubbles.push({
185
+ bubbleId,
186
+ type: typeof bubble.type === "number" ? bubble.type : 0,
187
+ text: bubble.text ?? "",
188
+ });
189
+ }
190
+ return bubbles;
191
+ }
192
+ /**
193
+ * Deterministic fingerprint input for a session, over the ordered
194
+ * `(bubbleId, type, text)` of every turn. This is the change-detection contract
195
+ * the capture slice will hash (NOT hashed here — the hashing util stays in one
196
+ * place): re-running on an unchanged session yields an identical string, while
197
+ * an edited/added/removed turn — including a tool-only turn that carries no
198
+ * prose — changes it. Requires bubble bodies to be present in `raw`.
199
+ */
200
+ export function cursorConversationFingerprintInput(raw, composerId) {
201
+ return collectOrderedBubbles(raw, composerId)
202
+ .map((b) => `${b.bubbleId}\t${b.type}\t${b.text}`)
203
+ .join("\n");
204
+ }
205
+ /**
206
+ * Full parse of a single native Cursor session into the shared
207
+ * {@link ParsedConversation} contract. Requires the session's bubble bodies to
208
+ * be present in `raw.cursorDiskKV` (the reader only fetches these on explicit,
209
+ * privacy-acknowledged opt-in). Returns null when no user/assistant turns with
210
+ * text exist.
211
+ *
212
+ * Provided for the FUTURE capture slice and for round-trip tests; the discovery
213
+ * probe does not call it by default.
214
+ */
215
+ export function parseCursorComposerSession(raw, composerId) {
216
+ const kv = indexByKey(raw.cursorDiskKV);
217
+ const bodyRaw = kv.get(`${KV_PREFIX_COMPOSER_DATA}${composerId}`);
218
+ const body = bodyRaw ? safeJsonParse(bodyRaw) : null;
219
+ const turns = [];
220
+ for (const bubble of collectOrderedBubbles(raw, composerId)) {
221
+ const text = bubble.text.trim();
222
+ if (!text)
223
+ continue; // tool-only / empty assistant bubbles carry no prose
224
+ if (bubble.type === BUBBLE_TYPE_USER) {
225
+ turns.push({ role: "user", text });
226
+ }
227
+ else if (bubble.type === BUBBLE_TYPE_ASSISTANT) {
228
+ turns.push({ role: "assistant", text });
229
+ }
230
+ }
231
+ if (turns.length === 0)
232
+ return null;
233
+ const content = turns
234
+ .map((t) => `${t.role === "user" ? "User" : "Assistant"}: ${t.text}`)
235
+ .join("\n\n");
236
+ const name = body?.name?.trim();
237
+ const firstUser = turns.find((t) => t.role === "user");
238
+ const rawTitle = name || firstUser?.text.slice(0, 120) || "Cursor session";
239
+ const title = rawTitle.includes("\n") ? rawTitle.split("\n")[0] : rawTitle;
240
+ const createdAt = epochMsToIso(body?.createdAt) ?? new Date(0).toISOString();
241
+ return { id: composerId, title, createdAt, content };
242
+ }
243
+ //# sourceMappingURL=cursor-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor-store.js","sourceRoot":"","sources":["../../../../src/ingestion/cursor/cursor-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Shared project-root enrichment for native Cursor sessions.
3
+ *
4
+ * Pure discovery (`discoverCursorComposerSessions`) resolves a project root only
5
+ * from the inline header `uri` (current Cursor builds) and never touches the
6
+ * filesystem. Legacy builds omit that inline uri, leaving the candidate
7
+ * `unresolved`. This helper upgrades those by joining the workspace id to the
8
+ * on-disk `workspace.json` — READ-ONLY, and only for `unresolved` candidates, so
9
+ * inline-resolved rows are left untouched.
10
+ *
11
+ * Used by both `rift cursor-probe` (inspection) and the auto-capture bridge so
12
+ * the two agree on exactly which sessions are project-attributable.
13
+ */
14
+ import type { CursorSessionCandidate } from "./cursor-store.js";
15
+ export declare function enrichCursorProjectRoots(candidates: CursorSessionCandidate[], cursorDir: string): CursorSessionCandidate[];
16
+ //# sourceMappingURL=enrich-roots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrich-roots.d.ts","sourceRoot":"","sources":["../../../../src/ingestion/cursor/enrich-roots.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAGhE,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,sBAAsB,EAAE,EACpC,SAAS,EAAE,MAAM,GAChB,sBAAsB,EAAE,CAiB1B"}
@@ -0,0 +1,22 @@
1
+ import { resolveProjectRootByWorkspaceId } from "./workspace-root.js";
2
+ export function enrichCursorProjectRoots(candidates, cursorDir) {
3
+ return candidates.map((c) => {
4
+ if (c.projectRootStatus !== "unresolved" || !c.workspaceId)
5
+ return c;
6
+ const r = resolveProjectRootByWorkspaceId(cursorDir, c.workspaceId);
7
+ if (r.status === "resolved") {
8
+ return {
9
+ ...c,
10
+ projectRoot: r.root,
11
+ projectRootSource: r.source,
12
+ projectRootStatus: r.status,
13
+ };
14
+ }
15
+ // A non-`resolved`, non-`unresolved` on-disk outcome (empty_window /
16
+ // multi_root / remote) is still more informative than bare `unresolved`.
17
+ if (r.status !== "unresolved")
18
+ return { ...c, projectRootStatus: r.status };
19
+ return c;
20
+ });
21
+ }
22
+ //# sourceMappingURL=enrich-roots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enrich-roots.js","sourceRoot":"","sources":["../../../../src/ingestion/cursor/enrich-roots.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,+BAA+B,EAAE,MAAM,qBAAqB,CAAC;AAEtE,MAAM,UAAU,wBAAwB,CACtC,UAAoC,EACpC,SAAiB;IAEjB,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC1B,IAAI,CAAC,CAAC,iBAAiB,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,WAAW;YAAE,OAAO,CAAC,CAAC;QACrE,MAAM,CAAC,GAAG,+BAA+B,CAAC,SAAS,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC;QACpE,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YAC5B,OAAO;gBACL,GAAG,CAAC;gBACJ,WAAW,EAAE,CAAC,CAAC,IAAI;gBACnB,iBAAiB,EAAE,CAAC,CAAC,MAAM;gBAC3B,iBAAiB,EAAE,CAAC,CAAC,MAAM;aAC5B,CAAC;QACJ,CAAC;QACD,qEAAqE;QACrE,yEAAyE;QACzE,IAAI,CAAC,CAAC,MAAM,KAAK,YAAY;YAAE,OAAO,EAAE,GAAG,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;QAC5E,OAAO,CAAC,CAAC;IACX,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { CursorRawRows } from "./cursor-store.js";
2
+ /** Default macOS location of Cursor's per-user application support dir. */
3
+ export declare function defaultCursorDir(): string;
4
+ /** Global KV store path under a Cursor application-support dir. */
5
+ export declare function globalStatePath(cursorDir: string): string;
6
+ export interface CursorReadResult {
7
+ /** Absolute path of the db that was read. */
8
+ dbPath: string;
9
+ /** Raw rows for the pure discovery layer. */
10
+ rows: CursorRawRows;
11
+ }
12
+ export declare class CursorReaderError extends Error {
13
+ readonly code: "sqlite_missing" | "db_missing" | "query_failed";
14
+ constructor(message: string, code: "sqlite_missing" | "db_missing" | "query_failed");
15
+ }
16
+ export interface ReadOptions {
17
+ /** Cursor application-support dir; defaults to the standard macOS path. */
18
+ cursorDir?: string;
19
+ /**
20
+ * When true, ALSO fetch bubble bodies (`bubbleId:*`) — the actual message
21
+ * text. Off by default: discovery never needs private content. Only enable
22
+ * when the caller has acknowledged it will read prose (e.g. parse round-trip).
23
+ */
24
+ includeBubbles?: boolean;
25
+ }
26
+ /**
27
+ * Read the global Cursor state.vscdb read-only and return raw rows for the pure
28
+ * discovery layer. Throws {@link CursorReaderError} with a stable `code` for the
29
+ * three expected failure modes so callers can render friendly guidance.
30
+ */
31
+ export declare function readCursorGlobalState(options?: ReadOptions): CursorReadResult;
32
+ //# sourceMappingURL=vscdb-reader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vscdb-reader.d.ts","sourceRoot":"","sources":["../../../../src/ingestion/cursor/vscdb-reader.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEpE,2EAA2E;AAC3E,wBAAgB,gBAAgB,IAAI,MAAM,CAOzC;AAED,mEAAmE;AACnE,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,MAAM,EAAE,MAAM,CAAC;IACf,6CAA6C;IAC7C,IAAI,EAAE,aAAa,CAAC;CACrB;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAGxC,QAAQ,CAAC,IAAI,EACT,gBAAgB,GAChB,YAAY,GACZ,cAAc;gBAJlB,OAAO,EAAE,MAAM,EACN,IAAI,EACT,gBAAgB,GAChB,YAAY,GACZ,cAAc;CAKrB;AAmDD,MAAM,WAAW,WAAW;IAC1B,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,WAAgB,GAAG,gBAAgB,CA+CjF"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Read-only reader for Cursor's `state.vscdb` SQLite stores.
3
+ *
4
+ * DISCOVERY SLICE ONLY — this is the single I/O boundary for Cursor capture.
5
+ * It is deliberately read-only by THREE independent guarantees:
6
+ * 1. SQLite is opened with the `immutable=1` URI flag, which forbids any
7
+ * write and never creates/touches the -wal/-shm sidecar files.
8
+ * 2. Only SELECT statements are ever issued.
9
+ * 3. We shell out to the system `sqlite3` binary rather than linking a
10
+ * writable driver. (Cursor itself holds the db open under WAL; immutable
11
+ * lets us read a consistent snapshot without contending for the lock.)
12
+ *
13
+ * Why shell out instead of a native dep: Rift's Node engine floor still
14
+ * includes Node 20 (no `node:sqlite`), and we don't want to pull a native
15
+ * addon (better-sqlite3) into the tree for a read-only probe. macOS always
16
+ * ships `/usr/bin/sqlite3`, and Cursor is macOS-first. The future capture slice
17
+ * can revisit this (node:sqlite once the floor rises). See the discovery doc.
18
+ *
19
+ * PRIVACY: by default we fetch only the session index + per-session metadata
20
+ * (`composer.composerHeaders`, `composerData:*`). We never SELECT `cursorAuth/*`
21
+ * (access/refresh tokens) or `secret://*` (MCP OAuth secrets), and we do not
22
+ * fetch bubble bodies (`bubbleId:*`, the actual message text) unless the caller
23
+ * explicitly opts in.
24
+ */
25
+ import { execFileSync } from "node:child_process";
26
+ import fs from "node:fs";
27
+ import os from "node:os";
28
+ import path from "node:path";
29
+ /** Default macOS location of Cursor's per-user application support dir. */
30
+ export function defaultCursorDir() {
31
+ return path.join(os.homedir(), "Library", "Application Support", "Cursor");
32
+ }
33
+ /** Global KV store path under a Cursor application-support dir. */
34
+ export function globalStatePath(cursorDir) {
35
+ return path.join(cursorDir, "User", "globalStorage", "state.vscdb");
36
+ }
37
+ export class CursorReaderError extends Error {
38
+ code;
39
+ constructor(message, code) {
40
+ super(message);
41
+ this.code = code;
42
+ this.name = "CursorReaderError";
43
+ }
44
+ }
45
+ function sqlite3Available() {
46
+ try {
47
+ execFileSync("sqlite3", ["--version"], { stdio: ["ignore", "ignore", "ignore"] });
48
+ return true;
49
+ }
50
+ catch {
51
+ return false;
52
+ }
53
+ }
54
+ /**
55
+ * Run a single SELECT against an immutable (read-only) view of the db and
56
+ * return rows as objects. Uses `.mode json` so values come back as strings.
57
+ */
58
+ function selectJson(dbPath, sql) {
59
+ const uri = `file:${dbPath}?immutable=1`;
60
+ let stdout;
61
+ try {
62
+ stdout = execFileSync("sqlite3", ["-cmd", ".mode json", uri, sql], {
63
+ encoding: "utf-8",
64
+ maxBuffer: 256 * 1024 * 1024, // composer blobs can be large
65
+ });
66
+ }
67
+ catch (err) {
68
+ throw new CursorReaderError(`sqlite3 query failed: ${err instanceof Error ? err.message : String(err)}`, "query_failed");
69
+ }
70
+ const trimmed = stdout.trim();
71
+ if (!trimmed)
72
+ return [];
73
+ try {
74
+ return JSON.parse(trimmed);
75
+ }
76
+ catch (err) {
77
+ throw new CursorReaderError(`failed to parse sqlite3 JSON output: ${err instanceof Error ? err.message : String(err)}`, "query_failed");
78
+ }
79
+ }
80
+ function toKvRows(records) {
81
+ const rows = [];
82
+ for (const rec of records) {
83
+ if (typeof rec.key === "string" && typeof rec.value === "string") {
84
+ rows.push({ key: rec.key, value: rec.value });
85
+ }
86
+ }
87
+ return rows;
88
+ }
89
+ /**
90
+ * Read the global Cursor state.vscdb read-only and return raw rows for the pure
91
+ * discovery layer. Throws {@link CursorReaderError} with a stable `code` for the
92
+ * three expected failure modes so callers can render friendly guidance.
93
+ */
94
+ export function readCursorGlobalState(options = {}) {
95
+ const cursorDir = options.cursorDir ?? defaultCursorDir();
96
+ const dbPath = globalStatePath(cursorDir);
97
+ if (!fs.existsSync(dbPath)) {
98
+ throw new CursorReaderError(`Cursor state.vscdb not found at ${dbPath}`, "db_missing");
99
+ }
100
+ if (!sqlite3Available()) {
101
+ throw new CursorReaderError("The `sqlite3` binary is required to read Cursor's store but was not found on PATH.", "sqlite_missing");
102
+ }
103
+ // Session index (ItemTable). Single, small row.
104
+ const itemTable = toKvRows(selectJson(dbPath, "SELECT key, value FROM ItemTable WHERE key = 'composer.composerHeaders'"));
105
+ // Per-session metadata (cursorDiskKV). Small; never tokens/secrets.
106
+ const composerData = toKvRows(selectJson(dbPath, "SELECT key, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'"));
107
+ const cursorDiskKV = [...composerData];
108
+ if (options.includeBubbles) {
109
+ cursorDiskKV.push(...toKvRows(selectJson(dbPath, "SELECT key, value FROM cursorDiskKV WHERE key LIKE 'bubbleId:%'")));
110
+ }
111
+ return { dbPath, rows: { itemTable, cursorDiskKV } };
112
+ }
113
+ //# sourceMappingURL=vscdb-reader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vscdb-reader.js","sourceRoot":"","sources":["../../../../src/ingestion/cursor/vscdb-reader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ /** Sentinel `workspaceIdentifier.id` Cursor uses when no folder is open. */
2
+ export declare const EMPTY_WINDOW_ID = "empty-window";
3
+ /** The `uri` object Cursor embeds in a folder-bound composer header. */
4
+ export interface CursorWorkspaceUri {
5
+ scheme?: string;
6
+ fsPath?: string;
7
+ path?: string;
8
+ external?: string;
9
+ }
10
+ /** A composer header's `workspaceIdentifier` (id + optional inline uri). */
11
+ export interface CursorWorkspaceIdentifier {
12
+ id?: string;
13
+ uri?: CursorWorkspaceUri | null;
14
+ }
15
+ /**
16
+ * Outcome of resolving a workspace identifier to a project root. Every
17
+ * non-`resolved` status is a deliberate, named outcome — the capture slice must
18
+ * branch on these rather than ever fabricate a root.
19
+ */
20
+ export type ProjectRootResolution = {
21
+ status: "resolved";
22
+ /** Absolute filesystem path of the project root. */
23
+ root: string;
24
+ /** Which link produced the root. */
25
+ source: "header_uri" | "workspace_json";
26
+ workspaceId: string | null;
27
+ }
28
+ /** No folder open (`empty-window`). Expected; not attributable. */
29
+ | {
30
+ status: "empty_window";
31
+ workspaceId: "empty-window";
32
+ }
33
+ /** Multi-root `.code-workspace`; root ambiguous. */
34
+ | {
35
+ status: "multi_root";
36
+ workspaceId: string;
37
+ configPath: string | null;
38
+ }
39
+ /** Non-`file` scheme (remote/ssh/wsl/devcontainer); not a local path. */
40
+ | {
41
+ status: "remote";
42
+ workspaceId: string | null;
43
+ scheme: string;
44
+ }
45
+ /** Id present but no inline uri and no readable `workspace.json`. */
46
+ | {
47
+ status: "unresolved";
48
+ workspaceId: string | null;
49
+ };
50
+ /**
51
+ * Parse a `workspace.json` file's text. Returns the folder root (single-folder
52
+ * window), a multi-root marker (`.code-workspace`), or unknown. Pure.
53
+ */
54
+ export declare function parseWorkspaceJson(text: string): {
55
+ kind: "folder";
56
+ scheme: string | null;
57
+ root: string | null;
58
+ } | {
59
+ kind: "multi_root";
60
+ configPath: string | null;
61
+ } | {
62
+ kind: "unknown";
63
+ };
64
+ /** Injected dependencies for the pure resolver. */
65
+ export interface ResolveOptions {
66
+ /**
67
+ * Returns the raw text of `workspaceStorage/<id>/workspace.json`, or null if
68
+ * absent. Injected so the resolver stays pure and fully fixture-testable.
69
+ * Used only as a fallback when the header carries no inline uri.
70
+ */
71
+ readWorkspaceJson?: (workspaceId: string) => string | null;
72
+ }
73
+ /**
74
+ * Resolve a composer header's `workspaceIdentifier` to a project root. Pure:
75
+ * the only I/O is the injected {@link ResolveOptions.readWorkspaceJson}. Tries
76
+ * the inline header uri first (current builds), then the on-disk
77
+ * `workspace.json` join (legacy builds / uri stripped). Never guesses — every
78
+ * non-resolvable case maps to an explicit status.
79
+ */
80
+ export declare function resolveProjectRoot(identifier: CursorWorkspaceIdentifier | null | undefined, options?: ResolveOptions): ProjectRootResolution;
81
+ /** Path to a workspace's `workspace.json` under a Cursor app-support dir. */
82
+ export declare function workspaceJsonPath(cursorDir: string, workspaceId: string): string;
83
+ /** Read `workspace.json` text read-only; null if it does not exist / unreadable. */
84
+ export declare function readWorkspaceJsonFromDisk(cursorDir: string, workspaceId: string): string | null;
85
+ /**
86
+ * Filesystem-backed resolution: resolve a header's identifier against a real
87
+ * Cursor app-support dir, reading `workspace.json` read-only when needed.
88
+ */
89
+ export declare function resolveCursorProjectRoot(identifier: CursorWorkspaceIdentifier | null | undefined, cursorDir: string): ProjectRootResolution;
90
+ /**
91
+ * Resolve a project root from a workspace id alone (no inline uri available).
92
+ * Used by the probe to upgrade `unresolved` discovery candidates on legacy
93
+ * builds via the on-disk `workspace.json` join.
94
+ */
95
+ export declare function resolveProjectRootByWorkspaceId(cursorDir: string, workspaceId: string): ProjectRootResolution;
96
+ //# sourceMappingURL=workspace-root.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-root.d.ts","sourceRoot":"","sources":["../../../../src/ingestion/cursor/workspace-root.ts"],"names":[],"mappings":"AAsDA,4EAA4E;AAC5E,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAE9C,wEAAwE;AACxE,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,4EAA4E;AAC5E,MAAM,WAAW,yBAAyB;IACxC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACjC;AAED;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAC7B;IACE,MAAM,EAAE,UAAU,CAAC;IACnB,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,MAAM,EAAE,YAAY,GAAG,gBAAgB,CAAC;IACxC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AACH,mEAAmE;GACjE;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,WAAW,EAAE,cAAc,CAAA;CAAE;AACzD,oDAAoD;GAClD;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;AAC1E,yEAAyE;GACvE;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAClE,qEAAqE;GACnE;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAoCzD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GAEV;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAkBtB;AAED,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAC5D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,yBAAyB,GAAG,IAAI,GAAG,SAAS,EACxD,OAAO,GAAE,cAAmB,GAC3B,qBAAqB,CAqCvB;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEhF;AAED,oFAAoF;AACpF,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAMf;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,UAAU,EAAE,yBAAyB,GAAG,IAAI,GAAG,SAAS,EACxD,SAAS,EAAE,MAAM,GAChB,qBAAqB,CAIvB;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,qBAAqB,CAEvB"}