@getrift/rift 0.0.0 → 0.1.0-beta.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 (628) hide show
  1. package/README.dev.md +110 -0
  2. package/README.md +130 -0
  3. package/dist/src/auth/keychain.d.ts +25 -0
  4. package/dist/src/auth/keychain.d.ts.map +1 -0
  5. package/dist/src/auth/keychain.js +113 -0
  6. package/dist/src/auth/keychain.js.map +1 -0
  7. package/dist/src/auth/middleware.d.ts +20 -0
  8. package/dist/src/auth/middleware.d.ts.map +1 -0
  9. package/dist/src/auth/middleware.js +49 -0
  10. package/dist/src/auth/middleware.js.map +1 -0
  11. package/dist/src/auth/rate-limit.d.ts +16 -0
  12. package/dist/src/auth/rate-limit.d.ts.map +1 -0
  13. package/dist/src/auth/rate-limit.js +38 -0
  14. package/dist/src/auth/rate-limit.js.map +1 -0
  15. package/dist/src/auth/rotation.d.ts +67 -0
  16. package/dist/src/auth/rotation.d.ts.map +1 -0
  17. package/dist/src/auth/rotation.js +190 -0
  18. package/dist/src/auth/rotation.js.map +1 -0
  19. package/dist/src/backfill/project-context-batch-constructor.d.ts +127 -0
  20. package/dist/src/backfill/project-context-batch-constructor.d.ts.map +1 -0
  21. package/dist/src/backfill/project-context-batch-constructor.js +210 -0
  22. package/dist/src/backfill/project-context-batch-constructor.js.map +1 -0
  23. package/dist/src/capture/auto-capture.d.ts +162 -0
  24. package/dist/src/capture/auto-capture.d.ts.map +1 -0
  25. package/dist/src/capture/auto-capture.js +601 -0
  26. package/dist/src/capture/auto-capture.js.map +1 -0
  27. package/dist/src/capture/batch-budget.d.ts +90 -0
  28. package/dist/src/capture/batch-budget.d.ts.map +1 -0
  29. package/dist/src/capture/batch-budget.js +148 -0
  30. package/dist/src/capture/batch-budget.js.map +1 -0
  31. package/dist/src/capture/codex-cli-triage-provider.d.ts +17 -0
  32. package/dist/src/capture/codex-cli-triage-provider.d.ts.map +1 -0
  33. package/dist/src/capture/codex-cli-triage-provider.js +109 -0
  34. package/dist/src/capture/codex-cli-triage-provider.js.map +1 -0
  35. package/dist/src/capture/observability.d.ts +42 -0
  36. package/dist/src/capture/observability.d.ts.map +1 -0
  37. package/dist/src/capture/observability.js +87 -0
  38. package/dist/src/capture/observability.js.map +1 -0
  39. package/dist/src/capture/openai-triage-provider.d.ts +92 -0
  40. package/dist/src/capture/openai-triage-provider.d.ts.map +1 -0
  41. package/dist/src/capture/openai-triage-provider.js +267 -0
  42. package/dist/src/capture/openai-triage-provider.js.map +1 -0
  43. package/dist/src/capture/review-queue-index.d.ts +51 -0
  44. package/dist/src/capture/review-queue-index.d.ts.map +1 -0
  45. package/dist/src/capture/review-queue-index.js +204 -0
  46. package/dist/src/capture/review-queue-index.js.map +1 -0
  47. package/dist/src/capture/review-queue.d.ts +43 -0
  48. package/dist/src/capture/review-queue.d.ts.map +1 -0
  49. package/dist/src/capture/review-queue.js +116 -0
  50. package/dist/src/capture/review-queue.js.map +1 -0
  51. package/dist/src/capture/sources.d.ts +7 -0
  52. package/dist/src/capture/sources.d.ts.map +1 -0
  53. package/dist/src/capture/sources.js +3 -0
  54. package/dist/src/capture/sources.js.map +1 -0
  55. package/dist/src/capture/triage-lane.d.ts +39 -0
  56. package/dist/src/capture/triage-lane.d.ts.map +1 -0
  57. package/dist/src/capture/triage-lane.js +217 -0
  58. package/dist/src/capture/triage-lane.js.map +1 -0
  59. package/dist/src/capture/triage-provider.d.ts +75 -0
  60. package/dist/src/capture/triage-provider.d.ts.map +1 -0
  61. package/dist/src/capture/triage-provider.js +120 -0
  62. package/dist/src/capture/triage-provider.js.map +1 -0
  63. package/dist/src/capture/triage.d.ts +30 -0
  64. package/dist/src/capture/triage.d.ts.map +1 -0
  65. package/dist/src/capture/triage.js +48 -0
  66. package/dist/src/capture/triage.js.map +1 -0
  67. package/dist/src/cli/commands/backfill.d.ts +3 -0
  68. package/dist/src/cli/commands/backfill.d.ts.map +1 -0
  69. package/dist/src/cli/commands/backfill.js +1376 -0
  70. package/dist/src/cli/commands/backfill.js.map +1 -0
  71. package/dist/src/cli/commands/bulk-ingest.d.ts +3 -0
  72. package/dist/src/cli/commands/bulk-ingest.d.ts.map +1 -0
  73. package/dist/src/cli/commands/bulk-ingest.js +126 -0
  74. package/dist/src/cli/commands/bulk-ingest.js.map +1 -0
  75. package/dist/src/cli/commands/capture.d.ts +12 -0
  76. package/dist/src/cli/commands/capture.d.ts.map +1 -0
  77. package/dist/src/cli/commands/capture.js +123 -0
  78. package/dist/src/cli/commands/capture.js.map +1 -0
  79. package/dist/src/cli/commands/compact.d.ts +3 -0
  80. package/dist/src/cli/commands/compact.d.ts.map +1 -0
  81. package/dist/src/cli/commands/compact.js +70 -0
  82. package/dist/src/cli/commands/compact.js.map +1 -0
  83. package/dist/src/cli/commands/feedback.d.ts +22 -0
  84. package/dist/src/cli/commands/feedback.d.ts.map +1 -0
  85. package/dist/src/cli/commands/feedback.js +125 -0
  86. package/dist/src/cli/commands/feedback.js.map +1 -0
  87. package/dist/src/cli/commands/import.d.ts +19 -0
  88. package/dist/src/cli/commands/import.d.ts.map +1 -0
  89. package/dist/src/cli/commands/import.js +258 -0
  90. package/dist/src/cli/commands/import.js.map +1 -0
  91. package/dist/src/cli/commands/ingest.d.ts +3 -0
  92. package/dist/src/cli/commands/ingest.d.ts.map +1 -0
  93. package/dist/src/cli/commands/ingest.js +80 -0
  94. package/dist/src/cli/commands/ingest.js.map +1 -0
  95. package/dist/src/cli/commands/mcp-install.d.ts +25 -0
  96. package/dist/src/cli/commands/mcp-install.d.ts.map +1 -0
  97. package/dist/src/cli/commands/mcp-install.js +134 -0
  98. package/dist/src/cli/commands/mcp-install.js.map +1 -0
  99. package/dist/src/cli/commands/onboard.d.ts +98 -0
  100. package/dist/src/cli/commands/onboard.d.ts.map +1 -0
  101. package/dist/src/cli/commands/onboard.js +742 -0
  102. package/dist/src/cli/commands/onboard.js.map +1 -0
  103. package/dist/src/cli/commands/rebuild.d.ts +12 -0
  104. package/dist/src/cli/commands/rebuild.d.ts.map +1 -0
  105. package/dist/src/cli/commands/rebuild.js +164 -0
  106. package/dist/src/cli/commands/rebuild.js.map +1 -0
  107. package/dist/src/cli/commands/reconcile.d.ts +3 -0
  108. package/dist/src/cli/commands/reconcile.d.ts.map +1 -0
  109. package/dist/src/cli/commands/reconcile.js +56 -0
  110. package/dist/src/cli/commands/reconcile.js.map +1 -0
  111. package/dist/src/cli/commands/reindex.d.ts +3 -0
  112. package/dist/src/cli/commands/reindex.d.ts.map +1 -0
  113. package/dist/src/cli/commands/reindex.js +66 -0
  114. package/dist/src/cli/commands/reindex.js.map +1 -0
  115. package/dist/src/cli/commands/review.d.ts +13 -0
  116. package/dist/src/cli/commands/review.d.ts.map +1 -0
  117. package/dist/src/cli/commands/review.js +383 -0
  118. package/dist/src/cli/commands/review.js.map +1 -0
  119. package/dist/src/cli/commands/save.d.ts +3 -0
  120. package/dist/src/cli/commands/save.d.ts.map +1 -0
  121. package/dist/src/cli/commands/save.js +111 -0
  122. package/dist/src/cli/commands/save.js.map +1 -0
  123. package/dist/src/cli/commands/search.d.ts +35 -0
  124. package/dist/src/cli/commands/search.d.ts.map +1 -0
  125. package/dist/src/cli/commands/search.js +88 -0
  126. package/dist/src/cli/commands/search.js.map +1 -0
  127. package/dist/src/cli/commands/stats.d.ts +3 -0
  128. package/dist/src/cli/commands/stats.d.ts.map +1 -0
  129. package/dist/src/cli/commands/stats.js +42 -0
  130. package/dist/src/cli/commands/stats.js.map +1 -0
  131. package/dist/src/cli/commands/status.d.ts +15 -0
  132. package/dist/src/cli/commands/status.d.ts.map +1 -0
  133. package/dist/src/cli/commands/status.js +89 -0
  134. package/dist/src/cli/commands/status.js.map +1 -0
  135. package/dist/src/cli/commands/token-issue.d.ts +3 -0
  136. package/dist/src/cli/commands/token-issue.d.ts.map +1 -0
  137. package/dist/src/cli/commands/token-issue.js +25 -0
  138. package/dist/src/cli/commands/token-issue.js.map +1 -0
  139. package/dist/src/cli/commands/triage.d.ts +3 -0
  140. package/dist/src/cli/commands/triage.d.ts.map +1 -0
  141. package/dist/src/cli/commands/triage.js +125 -0
  142. package/dist/src/cli/commands/triage.js.map +1 -0
  143. package/dist/src/cli/commands/uninstall.d.ts +3 -0
  144. package/dist/src/cli/commands/uninstall.d.ts.map +1 -0
  145. package/dist/src/cli/commands/uninstall.js +238 -0
  146. package/dist/src/cli/commands/uninstall.js.map +1 -0
  147. package/dist/src/cli/feedback/feedback-config.d.ts +21 -0
  148. package/dist/src/cli/feedback/feedback-config.d.ts.map +1 -0
  149. package/dist/src/cli/feedback/feedback-config.js +43 -0
  150. package/dist/src/cli/feedback/feedback-config.js.map +1 -0
  151. package/dist/src/cli/feedback/feedback-history.d.ts +4 -0
  152. package/dist/src/cli/feedback/feedback-history.d.ts.map +1 -0
  153. package/dist/src/cli/feedback/feedback-history.js +115 -0
  154. package/dist/src/cli/feedback/feedback-history.js.map +1 -0
  155. package/dist/src/cli/feedback/feedback-payload.d.ts +53 -0
  156. package/dist/src/cli/feedback/feedback-payload.d.ts.map +1 -0
  157. package/dist/src/cli/feedback/feedback-payload.js +10 -0
  158. package/dist/src/cli/feedback/feedback-payload.js.map +1 -0
  159. package/dist/src/cli/feedback/feedback-relay.d.ts +15 -0
  160. package/dist/src/cli/feedback/feedback-relay.d.ts.map +1 -0
  161. package/dist/src/cli/feedback/feedback-relay.js +47 -0
  162. package/dist/src/cli/feedback/feedback-relay.js.map +1 -0
  163. package/dist/src/cli/feedback/feedback-status.d.ts +11 -0
  164. package/dist/src/cli/feedback/feedback-status.d.ts.map +1 -0
  165. package/dist/src/cli/feedback/feedback-status.js +122 -0
  166. package/dist/src/cli/feedback/feedback-status.js.map +1 -0
  167. package/dist/src/cli/http-client.d.ts +36 -0
  168. package/dist/src/cli/http-client.d.ts.map +1 -0
  169. package/dist/src/cli/http-client.js +153 -0
  170. package/dist/src/cli/http-client.js.map +1 -0
  171. package/dist/src/cli/index.d.ts +4 -0
  172. package/dist/src/cli/index.d.ts.map +1 -0
  173. package/dist/src/cli/index.js +66 -0
  174. package/dist/src/cli/index.js.map +1 -0
  175. package/dist/src/cli/job-poller.d.ts +13 -0
  176. package/dist/src/cli/job-poller.d.ts.map +1 -0
  177. package/dist/src/cli/job-poller.js +29 -0
  178. package/dist/src/cli/job-poller.js.map +1 -0
  179. package/dist/src/cli/mcp-config-writers/codex-toml.d.ts +10 -0
  180. package/dist/src/cli/mcp-config-writers/codex-toml.d.ts.map +1 -0
  181. package/dist/src/cli/mcp-config-writers/codex-toml.js +410 -0
  182. package/dist/src/cli/mcp-config-writers/codex-toml.js.map +1 -0
  183. package/dist/src/cli/mcp-config-writers/errors.d.ts +17 -0
  184. package/dist/src/cli/mcp-config-writers/errors.d.ts.map +1 -0
  185. package/dist/src/cli/mcp-config-writers/errors.js +13 -0
  186. package/dist/src/cli/mcp-config-writers/errors.js.map +1 -0
  187. package/dist/src/cli/mcp-config-writers/index.d.ts +18 -0
  188. package/dist/src/cli/mcp-config-writers/index.d.ts.map +1 -0
  189. package/dist/src/cli/mcp-config-writers/index.js +49 -0
  190. package/dist/src/cli/mcp-config-writers/index.js.map +1 -0
  191. package/dist/src/cli/mcp-config-writers/json-config.d.ts +12 -0
  192. package/dist/src/cli/mcp-config-writers/json-config.d.ts.map +1 -0
  193. package/dist/src/cli/mcp-config-writers/json-config.js +177 -0
  194. package/dist/src/cli/mcp-config-writers/json-config.js.map +1 -0
  195. package/dist/src/cli/mcp-config-writers/redact.d.ts +28 -0
  196. package/dist/src/cli/mcp-config-writers/redact.d.ts.map +1 -0
  197. package/dist/src/cli/mcp-config-writers/redact.js +48 -0
  198. package/dist/src/cli/mcp-config-writers/redact.js.map +1 -0
  199. package/dist/src/cli/mcp-config-writers/types.d.ts +32 -0
  200. package/dist/src/cli/mcp-config-writers/types.d.ts.map +1 -0
  201. package/dist/src/cli/mcp-config-writers/types.js +5 -0
  202. package/dist/src/cli/mcp-config-writers/types.js.map +1 -0
  203. package/dist/src/cli/output.d.ts +8 -0
  204. package/dist/src/cli/output.d.ts.map +1 -0
  205. package/dist/src/cli/output.js +34 -0
  206. package/dist/src/cli/output.js.map +1 -0
  207. package/dist/src/cli/status/friend-header.d.ts +33 -0
  208. package/dist/src/cli/status/friend-header.d.ts.map +1 -0
  209. package/dist/src/cli/status/friend-header.js +108 -0
  210. package/dist/src/cli/status/friend-header.js.map +1 -0
  211. package/dist/src/cli/status/local-signals.d.ts +14 -0
  212. package/dist/src/cli/status/local-signals.d.ts.map +1 -0
  213. package/dist/src/cli/status/local-signals.js +73 -0
  214. package/dist/src/cli/status/local-signals.js.map +1 -0
  215. package/dist/src/cli/token.d.ts +37 -0
  216. package/dist/src/cli/token.d.ts.map +1 -0
  217. package/dist/src/cli/token.js +105 -0
  218. package/dist/src/cli/token.js.map +1 -0
  219. package/dist/src/cli/uninstall/mcp-uninstall.d.ts +33 -0
  220. package/dist/src/cli/uninstall/mcp-uninstall.d.ts.map +1 -0
  221. package/dist/src/cli/uninstall/mcp-uninstall.js +181 -0
  222. package/dist/src/cli/uninstall/mcp-uninstall.js.map +1 -0
  223. package/dist/src/config/loader.d.ts +9 -0
  224. package/dist/src/config/loader.d.ts.map +1 -0
  225. package/dist/src/config/loader.js +73 -0
  226. package/dist/src/config/loader.js.map +1 -0
  227. package/dist/src/config/schema.d.ts +635 -0
  228. package/dist/src/config/schema.d.ts.map +1 -0
  229. package/dist/src/config/schema.js +208 -0
  230. package/dist/src/config/schema.js.map +1 -0
  231. package/dist/src/ingestion/bulk-ingest.d.ts +11 -0
  232. package/dist/src/ingestion/bulk-ingest.d.ts.map +1 -0
  233. package/dist/src/ingestion/bulk-ingest.js +11 -0
  234. package/dist/src/ingestion/bulk-ingest.js.map +1 -0
  235. package/dist/src/ingestion/extractor.d.ts +16 -0
  236. package/dist/src/ingestion/extractor.d.ts.map +1 -0
  237. package/dist/src/ingestion/extractor.js +85 -0
  238. package/dist/src/ingestion/extractor.js.map +1 -0
  239. package/dist/src/ingestion/extractors/docx.d.ts +3 -0
  240. package/dist/src/ingestion/extractors/docx.d.ts.map +1 -0
  241. package/dist/src/ingestion/extractors/docx.js +20 -0
  242. package/dist/src/ingestion/extractors/docx.js.map +1 -0
  243. package/dist/src/ingestion/extractors/pdf.d.ts +3 -0
  244. package/dist/src/ingestion/extractors/pdf.d.ts.map +1 -0
  245. package/dist/src/ingestion/extractors/pdf.js +32 -0
  246. package/dist/src/ingestion/extractors/pdf.js.map +1 -0
  247. package/dist/src/ingestion/historical-campaign.d.ts +340 -0
  248. package/dist/src/ingestion/historical-campaign.d.ts.map +1 -0
  249. package/dist/src/ingestion/historical-campaign.js +1010 -0
  250. package/dist/src/ingestion/historical-campaign.js.map +1 -0
  251. package/dist/src/ingestion/ignored-paths.d.ts +20 -0
  252. package/dist/src/ingestion/ignored-paths.d.ts.map +1 -0
  253. package/dist/src/ingestion/ignored-paths.js +45 -0
  254. package/dist/src/ingestion/ignored-paths.js.map +1 -0
  255. package/dist/src/ingestion/inbox-watcher.d.ts +12 -0
  256. package/dist/src/ingestion/inbox-watcher.d.ts.map +1 -0
  257. package/dist/src/ingestion/inbox-watcher.js +99 -0
  258. package/dist/src/ingestion/inbox-watcher.js.map +1 -0
  259. package/dist/src/ingestion/indexer.d.ts +32 -0
  260. package/dist/src/ingestion/indexer.d.ts.map +1 -0
  261. package/dist/src/ingestion/indexer.js +68 -0
  262. package/dist/src/ingestion/indexer.js.map +1 -0
  263. package/dist/src/ingestion/metadata-extraction.d.ts +53 -0
  264. package/dist/src/ingestion/metadata-extraction.d.ts.map +1 -0
  265. package/dist/src/ingestion/metadata-extraction.js +132 -0
  266. package/dist/src/ingestion/metadata-extraction.js.map +1 -0
  267. package/dist/src/ingestion/parsers/chatgpt-web.d.ts +29 -0
  268. package/dist/src/ingestion/parsers/chatgpt-web.d.ts.map +1 -0
  269. package/dist/src/ingestion/parsers/chatgpt-web.js +100 -0
  270. package/dist/src/ingestion/parsers/chatgpt-web.js.map +1 -0
  271. package/dist/src/ingestion/parsers/claude-code-jsonl.d.ts +16 -0
  272. package/dist/src/ingestion/parsers/claude-code-jsonl.d.ts.map +1 -0
  273. package/dist/src/ingestion/parsers/claude-code-jsonl.js +123 -0
  274. package/dist/src/ingestion/parsers/claude-code-jsonl.js.map +1 -0
  275. package/dist/src/ingestion/parsers/claude-web.d.ts +24 -0
  276. package/dist/src/ingestion/parsers/claude-web.d.ts.map +1 -0
  277. package/dist/src/ingestion/parsers/claude-web.js +78 -0
  278. package/dist/src/ingestion/parsers/claude-web.js.map +1 -0
  279. package/dist/src/ingestion/parsers/codex-jsonl.d.ts +18 -0
  280. package/dist/src/ingestion/parsers/codex-jsonl.d.ts.map +1 -0
  281. package/dist/src/ingestion/parsers/codex-jsonl.js +125 -0
  282. package/dist/src/ingestion/parsers/codex-jsonl.js.map +1 -0
  283. package/dist/src/ingestion/parsers/gemini-web.d.ts +16 -0
  284. package/dist/src/ingestion/parsers/gemini-web.d.ts.map +1 -0
  285. package/dist/src/ingestion/parsers/gemini-web.js +170 -0
  286. package/dist/src/ingestion/parsers/gemini-web.js.map +1 -0
  287. package/dist/src/ingestion/parsers/grok-web.d.ts +40 -0
  288. package/dist/src/ingestion/parsers/grok-web.d.ts.map +1 -0
  289. package/dist/src/ingestion/parsers/grok-web.js +67 -0
  290. package/dist/src/ingestion/parsers/grok-web.js.map +1 -0
  291. package/dist/src/ingestion/parsers/types.d.ts +34 -0
  292. package/dist/src/ingestion/parsers/types.d.ts.map +1 -0
  293. package/dist/src/ingestion/parsers/types.js +26 -0
  294. package/dist/src/ingestion/parsers/types.js.map +1 -0
  295. package/dist/src/ingestion/scanner.d.ts +48 -0
  296. package/dist/src/ingestion/scanner.d.ts.map +1 -0
  297. package/dist/src/ingestion/scanner.js +131 -0
  298. package/dist/src/ingestion/scanner.js.map +1 -0
  299. package/dist/src/ingestion/staging.d.ts +109 -0
  300. package/dist/src/ingestion/staging.d.ts.map +1 -0
  301. package/dist/src/ingestion/staging.js +411 -0
  302. package/dist/src/ingestion/staging.js.map +1 -0
  303. package/dist/src/ingestion/watcher.d.ts +65 -0
  304. package/dist/src/ingestion/watcher.d.ts.map +1 -0
  305. package/dist/src/ingestion/watcher.js +182 -0
  306. package/dist/src/ingestion/watcher.js.map +1 -0
  307. package/dist/src/jobs/codex-override-handler.d.ts +3 -0
  308. package/dist/src/jobs/codex-override-handler.d.ts.map +1 -0
  309. package/dist/src/jobs/codex-override-handler.js +16 -0
  310. package/dist/src/jobs/codex-override-handler.js.map +1 -0
  311. package/dist/src/jobs/handlers/compact.d.ts +30 -0
  312. package/dist/src/jobs/handlers/compact.d.ts.map +1 -0
  313. package/dist/src/jobs/handlers/compact.js +329 -0
  314. package/dist/src/jobs/handlers/compact.js.map +1 -0
  315. package/dist/src/jobs/handlers/ingest.d.ts +13 -0
  316. package/dist/src/jobs/handlers/ingest.d.ts.map +1 -0
  317. package/dist/src/jobs/handlers/ingest.js +255 -0
  318. package/dist/src/jobs/handlers/ingest.js.map +1 -0
  319. package/dist/src/jobs/handlers/reconcile.d.ts +29 -0
  320. package/dist/src/jobs/handlers/reconcile.d.ts.map +1 -0
  321. package/dist/src/jobs/handlers/reconcile.js +476 -0
  322. package/dist/src/jobs/handlers/reconcile.js.map +1 -0
  323. package/dist/src/jobs/handlers/reindex.d.ts +38 -0
  324. package/dist/src/jobs/handlers/reindex.d.ts.map +1 -0
  325. package/dist/src/jobs/handlers/reindex.js +52 -0
  326. package/dist/src/jobs/handlers/reindex.js.map +1 -0
  327. package/dist/src/jobs/handlers/save.d.ts +10 -0
  328. package/dist/src/jobs/handlers/save.d.ts.map +1 -0
  329. package/dist/src/jobs/handlers/save.js +206 -0
  330. package/dist/src/jobs/handlers/save.js.map +1 -0
  331. package/dist/src/jobs/handlers/triage.d.ts +47 -0
  332. package/dist/src/jobs/handlers/triage.d.ts.map +1 -0
  333. package/dist/src/jobs/handlers/triage.js +95 -0
  334. package/dist/src/jobs/handlers/triage.js.map +1 -0
  335. package/dist/src/jobs/queue.d.ts +107 -0
  336. package/dist/src/jobs/queue.d.ts.map +1 -0
  337. package/dist/src/jobs/queue.js +319 -0
  338. package/dist/src/jobs/queue.js.map +1 -0
  339. package/dist/src/jobs/types.d.ts +39 -0
  340. package/dist/src/jobs/types.d.ts.map +1 -0
  341. package/dist/src/jobs/types.js +29 -0
  342. package/dist/src/jobs/types.js.map +1 -0
  343. package/dist/src/jobs/worker-entry.d.ts +10 -0
  344. package/dist/src/jobs/worker-entry.d.ts.map +1 -0
  345. package/dist/src/jobs/worker-entry.js +210 -0
  346. package/dist/src/jobs/worker-entry.js.map +1 -0
  347. package/dist/src/jobs/worker-process.d.ts +50 -0
  348. package/dist/src/jobs/worker-process.d.ts.map +1 -0
  349. package/dist/src/jobs/worker-process.js +186 -0
  350. package/dist/src/jobs/worker-process.js.map +1 -0
  351. package/dist/src/jobs/worker.d.ts +11 -0
  352. package/dist/src/jobs/worker.d.ts.map +1 -0
  353. package/dist/src/jobs/worker.js +14 -0
  354. package/dist/src/jobs/worker.js.map +1 -0
  355. package/dist/src/main.d.ts +2 -0
  356. package/dist/src/main.d.ts.map +1 -0
  357. package/dist/src/main.js +425 -0
  358. package/dist/src/main.js.map +1 -0
  359. package/dist/src/mcp/errors.d.ts +8 -0
  360. package/dist/src/mcp/errors.d.ts.map +1 -0
  361. package/dist/src/mcp/errors.js +50 -0
  362. package/dist/src/mcp/errors.js.map +1 -0
  363. package/dist/src/mcp/server.d.ts +10 -0
  364. package/dist/src/mcp/server.d.ts.map +1 -0
  365. package/dist/src/mcp/server.js +94 -0
  366. package/dist/src/mcp/server.js.map +1 -0
  367. package/dist/src/mcp/tools/context-pack.d.ts +35 -0
  368. package/dist/src/mcp/tools/context-pack.d.ts.map +1 -0
  369. package/dist/src/mcp/tools/context-pack.js +97 -0
  370. package/dist/src/mcp/tools/context-pack.js.map +1 -0
  371. package/dist/src/mcp/tools/conversations-search.d.ts +38 -0
  372. package/dist/src/mcp/tools/conversations-search.d.ts.map +1 -0
  373. package/dist/src/mcp/tools/conversations-search.js +73 -0
  374. package/dist/src/mcp/tools/conversations-search.js.map +1 -0
  375. package/dist/src/mcp/tools/save.d.ts +32 -0
  376. package/dist/src/mcp/tools/save.d.ts.map +1 -0
  377. package/dist/src/mcp/tools/save.js +60 -0
  378. package/dist/src/mcp/tools/save.js.map +1 -0
  379. package/dist/src/mcp/tools/search.d.ts +33 -0
  380. package/dist/src/mcp/tools/search.d.ts.map +1 -0
  381. package/dist/src/mcp/tools/search.js +58 -0
  382. package/dist/src/mcp/tools/search.js.map +1 -0
  383. package/dist/src/mcp/tools/status.d.ts +17 -0
  384. package/dist/src/mcp/tools/status.d.ts.map +1 -0
  385. package/dist/src/mcp/tools/status.js +12 -0
  386. package/dist/src/mcp/tools/status.js.map +1 -0
  387. package/dist/src/observability/coverage.d.ts +100 -0
  388. package/dist/src/observability/coverage.d.ts.map +1 -0
  389. package/dist/src/observability/coverage.js +180 -0
  390. package/dist/src/observability/coverage.js.map +1 -0
  391. package/dist/src/observability/rift-context.d.ts +47 -0
  392. package/dist/src/observability/rift-context.d.ts.map +1 -0
  393. package/dist/src/observability/rift-context.js +118 -0
  394. package/dist/src/observability/rift-context.js.map +1 -0
  395. package/dist/src/observability/staleness.d.ts +43 -0
  396. package/dist/src/observability/staleness.d.ts.map +1 -0
  397. package/dist/src/observability/staleness.js +74 -0
  398. package/dist/src/observability/staleness.js.map +1 -0
  399. package/dist/src/observability/tool-usage-stats.d.ts +23 -0
  400. package/dist/src/observability/tool-usage-stats.d.ts.map +1 -0
  401. package/dist/src/observability/tool-usage-stats.js +83 -0
  402. package/dist/src/observability/tool-usage-stats.js.map +1 -0
  403. package/dist/src/observability/tool-usage.d.ts +68 -0
  404. package/dist/src/observability/tool-usage.d.ts.map +1 -0
  405. package/dist/src/observability/tool-usage.js +207 -0
  406. package/dist/src/observability/tool-usage.js.map +1 -0
  407. package/dist/src/onboarding/daemon-control.d.ts +33 -0
  408. package/dist/src/onboarding/daemon-control.d.ts.map +1 -0
  409. package/dist/src/onboarding/daemon-control.js +92 -0
  410. package/dist/src/onboarding/daemon-control.js.map +1 -0
  411. package/dist/src/onboarding/env-file.d.ts +18 -0
  412. package/dist/src/onboarding/env-file.d.ts.map +1 -0
  413. package/dist/src/onboarding/env-file.js +89 -0
  414. package/dist/src/onboarding/env-file.js.map +1 -0
  415. package/dist/src/onboarding/voyage-validate.d.ts +16 -0
  416. package/dist/src/onboarding/voyage-validate.d.ts.map +1 -0
  417. package/dist/src/onboarding/voyage-validate.js +85 -0
  418. package/dist/src/onboarding/voyage-validate.js.map +1 -0
  419. package/dist/src/providers/anthropic-digest.d.ts +23 -0
  420. package/dist/src/providers/anthropic-digest.d.ts.map +1 -0
  421. package/dist/src/providers/anthropic-digest.js +91 -0
  422. package/dist/src/providers/anthropic-digest.js.map +1 -0
  423. package/dist/src/providers/codex-cli-digest.d.ts +12 -0
  424. package/dist/src/providers/codex-cli-digest.d.ts.map +1 -0
  425. package/dist/src/providers/codex-cli-digest.js +70 -0
  426. package/dist/src/providers/codex-cli-digest.js.map +1 -0
  427. package/dist/src/providers/codex-cli-metadata-extraction.d.ts +14 -0
  428. package/dist/src/providers/codex-cli-metadata-extraction.d.ts.map +1 -0
  429. package/dist/src/providers/codex-cli-metadata-extraction.js +101 -0
  430. package/dist/src/providers/codex-cli-metadata-extraction.js.map +1 -0
  431. package/dist/src/providers/codex-cli-runner.d.ts +14 -0
  432. package/dist/src/providers/codex-cli-runner.d.ts.map +1 -0
  433. package/dist/src/providers/codex-cli-runner.js +272 -0
  434. package/dist/src/providers/codex-cli-runner.js.map +1 -0
  435. package/dist/src/providers/conversation-generation.d.ts +10 -0
  436. package/dist/src/providers/conversation-generation.d.ts.map +1 -0
  437. package/dist/src/providers/conversation-generation.js +54 -0
  438. package/dist/src/providers/conversation-generation.js.map +1 -0
  439. package/dist/src/providers/ollama-embed.d.ts +22 -0
  440. package/dist/src/providers/ollama-embed.d.ts.map +1 -0
  441. package/dist/src/providers/ollama-embed.js +133 -0
  442. package/dist/src/providers/ollama-embed.js.map +1 -0
  443. package/dist/src/providers/ollama.d.ts +42 -0
  444. package/dist/src/providers/ollama.d.ts.map +1 -0
  445. package/dist/src/providers/ollama.js +169 -0
  446. package/dist/src/providers/ollama.js.map +1 -0
  447. package/dist/src/providers/openai-metadata-extraction.d.ts +73 -0
  448. package/dist/src/providers/openai-metadata-extraction.d.ts.map +1 -0
  449. package/dist/src/providers/openai-metadata-extraction.js +161 -0
  450. package/dist/src/providers/openai-metadata-extraction.js.map +1 -0
  451. package/dist/src/providers/operator-overrides.d.ts +24 -0
  452. package/dist/src/providers/operator-overrides.d.ts.map +1 -0
  453. package/dist/src/providers/operator-overrides.js +84 -0
  454. package/dist/src/providers/operator-overrides.js.map +1 -0
  455. package/dist/src/providers/stub.d.ts +17 -0
  456. package/dist/src/providers/stub.d.ts.map +1 -0
  457. package/dist/src/providers/stub.js +72 -0
  458. package/dist/src/providers/stub.js.map +1 -0
  459. package/dist/src/providers/types.d.ts +82 -0
  460. package/dist/src/providers/types.d.ts.map +1 -0
  461. package/dist/src/providers/types.js +52 -0
  462. package/dist/src/providers/types.js.map +1 -0
  463. package/dist/src/providers/voyage.d.ts +23 -0
  464. package/dist/src/providers/voyage.d.ts.map +1 -0
  465. package/dist/src/providers/voyage.js +135 -0
  466. package/dist/src/providers/voyage.js.map +1 -0
  467. package/dist/src/retrieval/compact.d.ts +89 -0
  468. package/dist/src/retrieval/compact.d.ts.map +1 -0
  469. package/dist/src/retrieval/compact.js +348 -0
  470. package/dist/src/retrieval/compact.js.map +1 -0
  471. package/dist/src/retrieval/context-pack.d.ts +123 -0
  472. package/dist/src/retrieval/context-pack.d.ts.map +1 -0
  473. package/dist/src/retrieval/context-pack.js +553 -0
  474. package/dist/src/retrieval/context-pack.js.map +1 -0
  475. package/dist/src/retrieval/cwd.d.ts +25 -0
  476. package/dist/src/retrieval/cwd.d.ts.map +1 -0
  477. package/dist/src/retrieval/cwd.js +48 -0
  478. package/dist/src/retrieval/cwd.js.map +1 -0
  479. package/dist/src/retrieval/degraded.d.ts +20 -0
  480. package/dist/src/retrieval/degraded.d.ts.map +1 -0
  481. package/dist/src/retrieval/degraded.js +43 -0
  482. package/dist/src/retrieval/degraded.js.map +1 -0
  483. package/dist/src/retrieval/hybrid.d.ts +38 -0
  484. package/dist/src/retrieval/hybrid.d.ts.map +1 -0
  485. package/dist/src/retrieval/hybrid.js +82 -0
  486. package/dist/src/retrieval/hybrid.js.map +1 -0
  487. package/dist/src/retrieval/lexical.d.ts +28 -0
  488. package/dist/src/retrieval/lexical.d.ts.map +1 -0
  489. package/dist/src/retrieval/lexical.js +301 -0
  490. package/dist/src/retrieval/lexical.js.map +1 -0
  491. package/dist/src/retrieval/post-filter.d.ts +32 -0
  492. package/dist/src/retrieval/post-filter.d.ts.map +1 -0
  493. package/dist/src/retrieval/post-filter.js +57 -0
  494. package/dist/src/retrieval/post-filter.js.map +1 -0
  495. package/dist/src/retrieval/reranker.d.ts +72 -0
  496. package/dist/src/retrieval/reranker.d.ts.map +1 -0
  497. package/dist/src/retrieval/reranker.js +129 -0
  498. package/dist/src/retrieval/reranker.js.map +1 -0
  499. package/dist/src/retrieval/vector.d.ts +47 -0
  500. package/dist/src/retrieval/vector.d.ts.map +1 -0
  501. package/dist/src/retrieval/vector.js +112 -0
  502. package/dist/src/retrieval/vector.js.map +1 -0
  503. package/dist/src/runtime/legacy-migration.d.ts +27 -0
  504. package/dist/src/runtime/legacy-migration.d.ts.map +1 -0
  505. package/dist/src/runtime/legacy-migration.js +140 -0
  506. package/dist/src/runtime/legacy-migration.js.map +1 -0
  507. package/dist/src/runtime/legacy-name-guard.d.ts +35 -0
  508. package/dist/src/runtime/legacy-name-guard.d.ts.map +1 -0
  509. package/dist/src/runtime/legacy-name-guard.js +58 -0
  510. package/dist/src/runtime/legacy-name-guard.js.map +1 -0
  511. package/dist/src/runtime/rift-env.d.ts +14 -0
  512. package/dist/src/runtime/rift-env.d.ts.map +1 -0
  513. package/dist/src/runtime/rift-env.js +79 -0
  514. package/dist/src/runtime/rift-env.js.map +1 -0
  515. package/dist/src/runtime/watcher-startup.d.ts +2 -0
  516. package/dist/src/runtime/watcher-startup.d.ts.map +1 -0
  517. package/dist/src/runtime/watcher-startup.js +4 -0
  518. package/dist/src/runtime/watcher-startup.js.map +1 -0
  519. package/dist/src/security/archive.d.ts +23 -0
  520. package/dist/src/security/archive.d.ts.map +1 -0
  521. package/dist/src/security/archive.js +163 -0
  522. package/dist/src/security/archive.js.map +1 -0
  523. package/dist/src/security/paths.d.ts +21 -0
  524. package/dist/src/security/paths.d.ts.map +1 -0
  525. package/dist/src/security/paths.js +67 -0
  526. package/dist/src/security/paths.js.map +1 -0
  527. package/dist/src/server/app.d.ts +29 -0
  528. package/dist/src/server/app.d.ts.map +1 -0
  529. package/dist/src/server/app.js +226 -0
  530. package/dist/src/server/app.js.map +1 -0
  531. package/dist/src/server/build-info.d.ts +8 -0
  532. package/dist/src/server/build-info.d.ts.map +1 -0
  533. package/dist/src/server/build-info.js +61 -0
  534. package/dist/src/server/build-info.js.map +1 -0
  535. package/dist/src/server/lifecycle.d.ts +30 -0
  536. package/dist/src/server/lifecycle.d.ts.map +1 -0
  537. package/dist/src/server/lifecycle.js +59 -0
  538. package/dist/src/server/lifecycle.js.map +1 -0
  539. package/dist/src/server/middleware/multipart.d.ts +51 -0
  540. package/dist/src/server/middleware/multipart.d.ts.map +1 -0
  541. package/dist/src/server/middleware/multipart.js +86 -0
  542. package/dist/src/server/middleware/multipart.js.map +1 -0
  543. package/dist/src/server/routes/compact.d.ts +37 -0
  544. package/dist/src/server/routes/compact.d.ts.map +1 -0
  545. package/dist/src/server/routes/compact.js +77 -0
  546. package/dist/src/server/routes/compact.js.map +1 -0
  547. package/dist/src/server/routes/context.d.ts +5 -0
  548. package/dist/src/server/routes/context.d.ts.map +1 -0
  549. package/dist/src/server/routes/context.js +50 -0
  550. package/dist/src/server/routes/context.js.map +1 -0
  551. package/dist/src/server/routes/conversations-search.d.ts +4 -0
  552. package/dist/src/server/routes/conversations-search.d.ts.map +1 -0
  553. package/dist/src/server/routes/conversations-search.js +243 -0
  554. package/dist/src/server/routes/conversations-search.js.map +1 -0
  555. package/dist/src/server/routes/friend-status.d.ts +72 -0
  556. package/dist/src/server/routes/friend-status.d.ts.map +1 -0
  557. package/dist/src/server/routes/friend-status.js +71 -0
  558. package/dist/src/server/routes/friend-status.js.map +1 -0
  559. package/dist/src/server/routes/ingest.d.ts +15 -0
  560. package/dist/src/server/routes/ingest.d.ts.map +1 -0
  561. package/dist/src/server/routes/ingest.js +139 -0
  562. package/dist/src/server/routes/ingest.js.map +1 -0
  563. package/dist/src/server/routes/jobs.d.ts +10 -0
  564. package/dist/src/server/routes/jobs.d.ts.map +1 -0
  565. package/dist/src/server/routes/jobs.js +29 -0
  566. package/dist/src/server/routes/jobs.js.map +1 -0
  567. package/dist/src/server/routes/mcp-usage.d.ts +13 -0
  568. package/dist/src/server/routes/mcp-usage.d.ts.map +1 -0
  569. package/dist/src/server/routes/mcp-usage.js +17 -0
  570. package/dist/src/server/routes/mcp-usage.js.map +1 -0
  571. package/dist/src/server/routes/reconcile.d.ts +4 -0
  572. package/dist/src/server/routes/reconcile.d.ts.map +1 -0
  573. package/dist/src/server/routes/reconcile.js +43 -0
  574. package/dist/src/server/routes/reconcile.js.map +1 -0
  575. package/dist/src/server/routes/reindex.d.ts +4 -0
  576. package/dist/src/server/routes/reindex.d.ts.map +1 -0
  577. package/dist/src/server/routes/reindex.js +74 -0
  578. package/dist/src/server/routes/reindex.js.map +1 -0
  579. package/dist/src/server/routes/save.d.ts +40 -0
  580. package/dist/src/server/routes/save.d.ts.map +1 -0
  581. package/dist/src/server/routes/save.js +112 -0
  582. package/dist/src/server/routes/save.js.map +1 -0
  583. package/dist/src/server/routes/search.d.ts +5 -0
  584. package/dist/src/server/routes/search.d.ts.map +1 -0
  585. package/dist/src/server/routes/search.js +400 -0
  586. package/dist/src/server/routes/search.js.map +1 -0
  587. package/dist/src/server/routes/stats.d.ts +10 -0
  588. package/dist/src/server/routes/stats.d.ts.map +1 -0
  589. package/dist/src/server/routes/stats.js +15 -0
  590. package/dist/src/server/routes/stats.js.map +1 -0
  591. package/dist/src/server/routes/status.d.ts +20 -0
  592. package/dist/src/server/routes/status.d.ts.map +1 -0
  593. package/dist/src/server/routes/status.js +31 -0
  594. package/dist/src/server/routes/status.js.map +1 -0
  595. package/dist/src/server/routes/triage.d.ts +4 -0
  596. package/dist/src/server/routes/triage.d.ts.map +1 -0
  597. package/dist/src/server/routes/triage.js +94 -0
  598. package/dist/src/server/routes/triage.js.map +1 -0
  599. package/dist/src/server/save-quality.d.ts +21 -0
  600. package/dist/src/server/save-quality.d.ts.map +1 -0
  601. package/dist/src/server/save-quality.js +51 -0
  602. package/dist/src/server/save-quality.js.map +1 -0
  603. package/dist/src/storage/atomic.d.ts +8 -0
  604. package/dist/src/storage/atomic.d.ts.map +1 -0
  605. package/dist/src/storage/atomic.js +22 -0
  606. package/dist/src/storage/atomic.js.map +1 -0
  607. package/dist/src/storage/db.d.ts +15 -0
  608. package/dist/src/storage/db.d.ts.map +1 -0
  609. package/dist/src/storage/db.js +43 -0
  610. package/dist/src/storage/db.js.map +1 -0
  611. package/dist/src/storage/integrity.d.ts +11 -0
  612. package/dist/src/storage/integrity.d.ts.map +1 -0
  613. package/dist/src/storage/integrity.js +66 -0
  614. package/dist/src/storage/integrity.js.map +1 -0
  615. package/dist/src/storage/rebuild.d.ts +37 -0
  616. package/dist/src/storage/rebuild.d.ts.map +1 -0
  617. package/dist/src/storage/rebuild.js +353 -0
  618. package/dist/src/storage/rebuild.js.map +1 -0
  619. package/dist/src/storage/shadow-swap.d.ts +20 -0
  620. package/dist/src/storage/shadow-swap.d.ts.map +1 -0
  621. package/dist/src/storage/shadow-swap.js +163 -0
  622. package/dist/src/storage/shadow-swap.js.map +1 -0
  623. package/dist/src/storage/tables.d.ts +77 -0
  624. package/dist/src/storage/tables.d.ts.map +1 -0
  625. package/dist/src/storage/tables.js +196 -0
  626. package/dist/src/storage/tables.js.map +1 -0
  627. package/package.json +45 -14
  628. package/index.js +0 -3
@@ -0,0 +1,742 @@
1
+ /**
2
+ * `rift onboard` — first-run wizard.
3
+ *
4
+ * Walks a friend from "fresh install + Voyage key in hand" to "first
5
+ * useful recall against their freshly-imported data". Step ordering
6
+ * matches Slice 4 in the friend-beta plan; each step is idempotent and
7
+ * `--yes` accepts every prompt's default.
8
+ *
9
+ * Flags worth pointing out:
10
+ * --voyage-key <key> non-interactive key entry
11
+ * --voyage-label <label> operator-supplied display label (no inference)
12
+ * --enable-feedback-relay <url>
13
+ * opt into the Clem-side relay non-interactively
14
+ * --import-export <path> import an export inline; `--no-import-export`
15
+ * skips the prompt entirely
16
+ * --reconfigure-voyage Slice 6 recovery flow — skip everything
17
+ * except validate + write key + kickstart + smoke
18
+ * --yes accept all defaults (used by install scripts)
19
+ * --skip-capture suppress the post-onboarding capture pass
20
+ * (useful in tests / CI dry-runs)
21
+ */
22
+ import crypto from "node:crypto";
23
+ import fs from "node:fs";
24
+ import os from "node:os";
25
+ import path from "node:path";
26
+ import readline from "node:readline";
27
+ import { Command } from "commander";
28
+ import { CliError, createHttpClient, readToken, resolveBaseUrl, } from "../http-client.js";
29
+ import { issueToken } from "../token.js";
30
+ import { loadConfig } from "../../config/loader.js";
31
+ import { defaultRiftEnvPath, loadRiftEnv, } from "../../runtime/rift-env.js";
32
+ import { runLegacyMigration } from "../../runtime/legacy-migration.js";
33
+ import { sanitizeProjectLabel } from "../../runtime/legacy-name-guard.js";
34
+ import { validateVoyageKey } from "../../onboarding/voyage-validate.js";
35
+ import { writeEnvFile } from "../../onboarding/env-file.js";
36
+ import { kickstartDaemon, waitForHealth, } from "../../onboarding/daemon-control.js";
37
+ import { runAutoCapture, resolveCodexCaptureDeps, } from "../../capture/auto-capture.js";
38
+ import { CodexCliTriageProvider } from "../../capture/codex-cli-triage-provider.js";
39
+ import { discoverClaudeCodeSessions } from "../../ingestion/parsers/claude-code-jsonl.js";
40
+ import { discoverCodexSessions } from "../../ingestion/parsers/codex-jsonl.js";
41
+ import { pollJob } from "../job-poller.js";
42
+ import { isJobFailure } from "../output.js";
43
+ const SUPPORTED_INGEST_EXTENSIONS = new Set([".json", ".zip"]);
44
+ const DEFAULT_DATA_DIR = path.join(os.homedir(), "Library", "Application Support", "Rift", "data");
45
+ // Inline import is intentionally narrow until Slice 3 lands the real
46
+ // `rift import` flow with structural sniffing per source. ChatGPT exports
47
+ // are the most common friend handoff and we route them straight through.
48
+ const ONBOARD_INLINE_IMPORT_SOURCE = "chatgpt_web";
49
+ export function makeOnboardCommand() {
50
+ return new Command("onboard")
51
+ .description("First-run wizard: validate Voyage key, capture, import, recall test")
52
+ .option("--voyage-key <key>", "Voyage API key (skips paste prompt)")
53
+ .option("--voyage-label <label>", "Operator-supplied display label for the Voyage project")
54
+ .option("--enable-feedback-relay <url>", "Opt into the Rift feedback relay non-interactively (URL required)")
55
+ .option("--no-feedback-relay", "Decline the feedback relay (local-only)")
56
+ .option("--import-export <path>", "Import an export inline (.json or .zip)")
57
+ .option("--no-import-export", "Skip the import-now prompt")
58
+ .option("--reconfigure-voyage", "Recovery flow: replace the Voyage key only", false)
59
+ .option("--yes", "Accept all defaults (non-interactive)", false)
60
+ .option("--skip-capture", "Skip the post-setup capture pass (test-only)", false)
61
+ .action(async (opts, cmd) => {
62
+ const globalOpts = cmd.optsWithGlobals();
63
+ try {
64
+ await runOnboard(opts, globalOpts);
65
+ }
66
+ catch (err) {
67
+ const msg = err instanceof CliError
68
+ ? err.message
69
+ : err instanceof Error
70
+ ? err.message
71
+ : String(err);
72
+ process.stderr.write(`onboard failed: ${msg}\n`);
73
+ process.exitCode = 1;
74
+ }
75
+ });
76
+ }
77
+ async function runOnboard(opts, globalOpts) {
78
+ const rl = readline.createInterface({
79
+ input: process.stdin,
80
+ output: process.stdout,
81
+ terminal: !!process.stdin.isTTY,
82
+ });
83
+ try {
84
+ if (opts.reconfigureVoyage) {
85
+ await reconfigureVoyageFlow(opts, globalOpts, rl);
86
+ return;
87
+ }
88
+ say("");
89
+ say("Rift — first-run setup");
90
+ say("─────────────────────");
91
+ // Step 1 — legacy migration (idempotent).
92
+ const dataDir = await ensureConfigAndDataDir(globalOpts.config, opts, rl);
93
+ say("");
94
+ say("Running legacy migration check…");
95
+ const migration = await runLegacyMigration({ dataDir });
96
+ if (migration.migratedCount > 0) {
97
+ say(`Migrated ${migration.migratedCount} legacy artifact(s).`);
98
+ }
99
+ else {
100
+ say("No legacy artifacts found.");
101
+ }
102
+ // Step 2 — Voyage key + validate + persist + kickstart + smoke.
103
+ say("");
104
+ say("Voyage API key");
105
+ const last4 = await collectAndPersistVoyageKey(opts, globalOpts, rl);
106
+ // Step 2b — sanitize + persist optional --voyage-label to config.json
107
+ // (backup first). Invalid labels are dropped without echoing the raw
108
+ // value, so a key-shaped, path-shaped, or legacy-name-shaped label
109
+ // can never leak through stdout or config.json.
110
+ const safeLabel = applyVoyageLabel(opts.voyageLabel, globalOpts.config, say);
111
+ // Step 3 — Codex CLI preflight.
112
+ say("");
113
+ say("Codex CLI preflight…");
114
+ const codexOk = await codexPreflight();
115
+ if (!codexOk) {
116
+ say("Codex CLI is not authenticated. Run: codex login");
117
+ say("(Auto-capture needs Codex CLI auth. Re-run rift onboard once codex login succeeds.)");
118
+ throw new CliError("Codex CLI preflight failed.", "validation");
119
+ }
120
+ say("Codex CLI ready.");
121
+ // Step 4 — discover sessions.
122
+ say("");
123
+ const claudeSessions = safeDiscover(() => discoverClaudeCodeSessions(path.join(os.homedir(), ".claude")));
124
+ const codexSessions = safeDiscover(() => discoverCodexSessions());
125
+ say(`Found ${claudeSessions} Claude Code session(s) and ${codexSessions} Codex CLI session(s).`);
126
+ // Step 5 — privacy + feedback opt-in.
127
+ say("");
128
+ say("Privacy");
129
+ sayPrivacyContract();
130
+ const feedback = await collectFeedbackPreference(opts, rl, dataDir);
131
+ if (feedback.enabled) {
132
+ say(`Feedback relay enabled (installation_id: ${feedback.installation_id}).`);
133
+ }
134
+ else {
135
+ say("Feedback relay off — feedback stays in local JSONL only.");
136
+ }
137
+ // Step 6 + 7 — watermark current sessions + run one capture pass.
138
+ let captureSaved = 0;
139
+ if (!opts.skipCapture) {
140
+ say("");
141
+ say("Running first capture pass (watermark + scan)…");
142
+ const captureResult = await runFirstCapturePass(globalOpts.config, dataDir);
143
+ captureSaved = captureResult.saved;
144
+ }
145
+ else {
146
+ say("Skipping capture pass (--skip-capture).");
147
+ }
148
+ // Step 8 — optional export import.
149
+ say("");
150
+ let importSucceeded = false;
151
+ if (!opts.noImportExport) {
152
+ const importPath = await collectImportPath(opts, rl);
153
+ if (importPath) {
154
+ const outcome = await runImport(importPath, globalOpts.config);
155
+ if (outcome.kind === "imported" || outcome.kind === "duplicate") {
156
+ importSucceeded = true;
157
+ }
158
+ }
159
+ else {
160
+ say("Skipping import. Run rift import <path> --source <name> later.");
161
+ }
162
+ }
163
+ else {
164
+ say("Skipping import (--no-import-export).");
165
+ }
166
+ // Step 9 — first-recall verification.
167
+ // Onboarding declares "complete" only when (a) capture or import landed
168
+ // user data this run, AND (b) a recall query against the daemon returns
169
+ // at least one hit. Without (a), there is nothing to recall — calling
170
+ // it "complete" because /search returned 0 rows would be misleading.
171
+ say("");
172
+ const ingestedAny = captureSaved > 0 || importSucceeded;
173
+ say(`First-recall sanity check (capture saved ${captureSaved} · import ${importSucceeded ? "ok" : "none"})…`);
174
+ const recall = ingestedAny
175
+ ? await firstRecallCheck(globalOpts.config)
176
+ : { ok: false, reason: "no user data was captured or imported during onboarding" };
177
+ // Step 10 — next-action card.
178
+ say("");
179
+ say("─────────────────────");
180
+ for (const line of decideOnboardOutcome({ ingestedAny, recall }))
181
+ say(line);
182
+ say(`Voyage: key valid (last 4 …${last4})${safeLabel ? ` · label ${safeLabel}` : ""}`);
183
+ say("");
184
+ }
185
+ finally {
186
+ rl.close();
187
+ }
188
+ }
189
+ // ----- Step 1: config.json + data dir -----
190
+ async function ensureConfigAndDataDir(configPath, opts, rl) {
191
+ const absoluteConfig = path.resolve(configPath);
192
+ if (fs.existsSync(absoluteConfig)) {
193
+ const config = loadConfig(absoluteConfig);
194
+ say(`Using existing config: ${absoluteConfig}`);
195
+ say(`Data dir: ${config.data_paths.data_dir}`);
196
+ return config.data_paths.data_dir;
197
+ }
198
+ const defaultDataDir = DEFAULT_DATA_DIR;
199
+ const dataDir = opts.yes
200
+ ? defaultDataDir
201
+ : (await ask(rl, `Data dir [${defaultDataDir}]: `, defaultDataDir)).trim() ||
202
+ defaultDataDir;
203
+ fs.mkdirSync(dataDir, { recursive: true });
204
+ const inboxDir = path.join(dataDir, "inbox");
205
+ fs.mkdirSync(inboxDir, { recursive: true });
206
+ const config = {
207
+ sources: [
208
+ {
209
+ path: inboxDir,
210
+ extraction: "cloud",
211
+ mode: "watch",
212
+ scope: "project",
213
+ },
214
+ ],
215
+ embedding: { provider: "voyage", model: "voyage-3-lite" },
216
+ data_paths: { data_dir: dataDir, jobs_dir: path.join(dataDir, "..", "jobs") },
217
+ rate_limit: { window_ms: 60_000, max_requests: 100 },
218
+ capture: { enabled: true, interval_seconds: 3600 },
219
+ };
220
+ fs.mkdirSync(path.dirname(absoluteConfig), { recursive: true });
221
+ fs.writeFileSync(absoluteConfig, JSON.stringify(config, null, 2) + "\n", {
222
+ encoding: "utf8",
223
+ mode: 0o644,
224
+ });
225
+ say(`Wrote default config: ${absoluteConfig}`);
226
+ say(`Data dir: ${dataDir}`);
227
+ // Trigger ensureDirectories.
228
+ loadConfig(absoluteConfig);
229
+ return dataDir;
230
+ }
231
+ // ----- Step 2a: persist --voyage-label to config.json -----
232
+ /**
233
+ * Sanitize a raw `--voyage-label`, persist it when valid, and return the
234
+ * string the caller should use for display. Invalid labels are dropped
235
+ * with a generic notice that never echoes the raw value — so a
236
+ * key-shaped, path-shaped, or legacy-name-shaped label cannot leak
237
+ * through stdout or `config.json`. Returns `null` when the input was
238
+ * absent or rejected.
239
+ *
240
+ * Exported for orchestrator-level tests; `runOnboard` is the only
241
+ * production caller.
242
+ */
243
+ export function applyVoyageLabel(rawLabel, configPath, emit) {
244
+ if (rawLabel === undefined)
245
+ return null;
246
+ const sanitized = sanitizeProjectLabel(rawLabel);
247
+ if (!sanitized) {
248
+ // Generic message: never echo the raw value. Anything we say here
249
+ // also has to land in the friend's terminal, so it must not name
250
+ // the rejected token.
251
+ emit("Ignoring --voyage-label: must be 1–32 chars of letters, digits, '-' or '_' " +
252
+ "(no paths, secrets, or legacy product names).");
253
+ return null;
254
+ }
255
+ persistVoyageLabel(configPath, sanitized);
256
+ emit(`Stored Voyage label: ${sanitized}`);
257
+ return sanitized;
258
+ }
259
+ /**
260
+ * Merge `voyage.project_label` into the config file. The file is
261
+ * backed up to `<file>.bak.<iso>` first so an interrupted write or a
262
+ * future operator typo can be undone. Display only — never sent to the
263
+ * relay, never inferred from the key bytes.
264
+ *
265
+ * Defensively re-runs `sanitizeProjectLabel` even though the standard
266
+ * `applyVoyageLabel` caller has already validated: a future programmer
267
+ * who reaches for this export directly still cannot land an unsafe
268
+ * string in the file.
269
+ */
270
+ export function persistVoyageLabel(configPath, label) {
271
+ const sanitized = sanitizeProjectLabel(label);
272
+ if (!sanitized) {
273
+ throw new CliError("Refusing to persist Voyage label: not a valid label " +
274
+ "(1–32 chars of letters, digits, '-' or '_'; no paths, secrets, or legacy names).", "validation");
275
+ }
276
+ const absolute = path.resolve(configPath);
277
+ if (!fs.existsSync(absolute)) {
278
+ // ensureConfigAndDataDir always writes config.json before this runs;
279
+ // a missing file here means the caller bypassed step 1.
280
+ throw new CliError(`Cannot persist Voyage label: config not found at ${absolute}`, "validation");
281
+ }
282
+ const raw = fs.readFileSync(absolute, "utf8");
283
+ const stamp = new Date().toISOString().replace(/[:.]/g, "-");
284
+ fs.writeFileSync(`${absolute}.bak.${stamp}`, raw, { encoding: "utf8", mode: 0o600 });
285
+ const parsed = JSON.parse(raw);
286
+ const voyage = parsed["voyage"] ?? {};
287
+ voyage["project_label"] = sanitized;
288
+ parsed["voyage"] = voyage;
289
+ const tmp = `${absolute}.tmp.${process.pid}`;
290
+ fs.writeFileSync(tmp, JSON.stringify(parsed, null, 2) + "\n", {
291
+ encoding: "utf8",
292
+ mode: 0o644,
293
+ });
294
+ fs.renameSync(tmp, absolute);
295
+ }
296
+ // ----- Step 2: Voyage key flow -----
297
+ async function collectAndPersistVoyageKey(opts, globalOpts, rl) {
298
+ const key = await collectVoyageKey(opts, rl);
299
+ say("Validating with Voyage API…");
300
+ const validation = await validateVoyageKey({ apiKey: key });
301
+ if (!validation.ok) {
302
+ throw new CliError(`Voyage validation failed: ${validation.reason}`, "validation");
303
+ }
304
+ say(`Voyage key valid (last 4 …${validation.last4}).`);
305
+ const envPath = defaultRiftEnvPath();
306
+ const writeResult = writeEnvFile({ filePath: envPath, key: "VOYAGE_API_KEY", value: key });
307
+ say(writeResult.backedUp
308
+ ? "Wrote ~/.rift.env (existing file backed up)."
309
+ : "Wrote ~/.rift.env (mode 0600).");
310
+ // Refresh process.env so any subsequent in-process Voyage call sees it.
311
+ loadRiftEnv({ filePath: envPath });
312
+ const refresh = await daemonRefreshFlow(globalOpts);
313
+ // `not_configured` / `agent_not_loaded` are recoverable — the daemon
314
+ // simply isn't running yet (typical on fresh-Mac install before
315
+ // install.sh bootstraps the plist). Onboarding continues without the
316
+ // post-kickstart smoke; install.sh will pick it up.
317
+ if (!refresh.ok && refresh.kind !== "not_configured" && refresh.kind !== "agent_not_loaded") {
318
+ throw new CliError(`Voyage smoke failed after daemon kickstart: ${refresh.reason}`, "server_error");
319
+ }
320
+ return validation.last4;
321
+ }
322
+ async function collectVoyageKey(opts, rl) {
323
+ if (opts.voyageKey)
324
+ return opts.voyageKey.trim();
325
+ if (process.env["VOYAGE_API_KEY"])
326
+ return process.env["VOYAGE_API_KEY"].trim();
327
+ if (opts.yes) {
328
+ throw new CliError("--yes given but no Voyage key found (use --voyage-key or set VOYAGE_API_KEY).", "validation");
329
+ }
330
+ const answer = (await ask(rl, "Paste your Voyage API key: ")).trim();
331
+ if (answer.length === 0) {
332
+ throw new CliError("Voyage key is required.", "validation");
333
+ }
334
+ return answer;
335
+ }
336
+ /**
337
+ * Kickstart, wait for /health, confirm the respawned daemon process has
338
+ * VOYAGE_API_KEY loaded. The smoke is fully non-indexing — `/health`
339
+ * exposes `voyage_key_present` so we never write a row to LanceDB just to
340
+ * prove the daemon read its env file. That keeps first-recall results
341
+ * free of an "onboarding probe" hit that would otherwise satisfy the
342
+ * completion check without any real user data being present.
343
+ */
344
+ async function daemonRefreshFlow(globalOpts) {
345
+ const baseUrl = safeResolveBaseUrl(globalOpts.config);
346
+ if (!baseUrl) {
347
+ say("Daemon not configured yet — skipping kickstart. Bootstrap via install.sh, then re-run rift onboard.");
348
+ return { ok: false, reason: "daemon not configured", kind: "not_configured" };
349
+ }
350
+ const kick = await kickstartDaemon();
351
+ if (kick.status === "agent_not_loaded") {
352
+ say(kick.hint);
353
+ return { ok: false, reason: kick.hint ?? "agent not loaded", kind: "agent_not_loaded" };
354
+ }
355
+ if (kick.status === "failed") {
356
+ return {
357
+ ok: false,
358
+ reason: kick.hint ?? "kickstart failed",
359
+ kind: "kickstart_failed",
360
+ };
361
+ }
362
+ say("Daemon kickstarted.");
363
+ const health = await waitForHealth({ baseUrl });
364
+ if (!health.ok) {
365
+ return { ok: false, reason: health.reason, kind: "health_failed" };
366
+ }
367
+ say(`Daemon healthy (uptime ${health.uptimeSeconds}s).`);
368
+ if (!health.voyageKeyPresent) {
369
+ return {
370
+ ok: false,
371
+ reason: "Daemon /health reports voyage_key_present=false after kickstart.",
372
+ kind: "smoke_failed",
373
+ };
374
+ }
375
+ say("Cloud embedding live (daemon loaded VOYAGE_API_KEY).");
376
+ return { ok: true, kickstarted: true };
377
+ }
378
+ // ----- Token helpers -----
379
+ async function ensureToken(configPath) {
380
+ const existing = await readToken();
381
+ if (existing)
382
+ return existing;
383
+ try {
384
+ const { token } = await issueToken(path.resolve(configPath));
385
+ // Mirror to ~/.rift/token so subsequent CLI calls don't depend on Keychain.
386
+ const tokenPath = path.join(os.homedir(), ".rift", "token");
387
+ fs.mkdirSync(path.dirname(tokenPath), { recursive: true });
388
+ fs.writeFileSync(tokenPath, token + "\n", { encoding: "utf8", mode: 0o600 });
389
+ fs.chmodSync(tokenPath, 0o600);
390
+ return token;
391
+ }
392
+ catch {
393
+ return null;
394
+ }
395
+ }
396
+ // ----- Step 3: Codex preflight -----
397
+ async function codexPreflight() {
398
+ try {
399
+ await new CodexCliTriageProvider({ timeoutMs: 120_000 }).triage({
400
+ content: "User: Rift onboarding preflight.\n\nAssistant: Ready.",
401
+ source: "codex_cli",
402
+ });
403
+ return true;
404
+ }
405
+ catch {
406
+ return false;
407
+ }
408
+ }
409
+ async function collectFeedbackPreference(opts, rl, dataDir) {
410
+ let enabled = false;
411
+ let url;
412
+ if (opts.enableFeedbackRelay) {
413
+ enabled = true;
414
+ url = opts.enableFeedbackRelay;
415
+ }
416
+ else if (opts.noFeedbackRelay || opts.yes) {
417
+ enabled = false;
418
+ }
419
+ else {
420
+ const answer = (await ask(rl, "Opt into the Rift feedback relay? [y/N]: ", "n"))
421
+ .trim()
422
+ .toLowerCase();
423
+ enabled = answer === "y" || answer === "yes";
424
+ if (enabled) {
425
+ url = (await ask(rl, "Relay URL: ")).trim();
426
+ if (!url) {
427
+ say("No URL supplied — keeping relay off.");
428
+ enabled = false;
429
+ url = undefined;
430
+ }
431
+ }
432
+ }
433
+ const cfg = enabled && url
434
+ ? { enabled: true, url, installation_id: crypto.randomUUID() }
435
+ : { enabled: false };
436
+ fs.mkdirSync(dataDir, { recursive: true });
437
+ const sidecar = path.join(dataDir, "feedback-config.json");
438
+ fs.writeFileSync(sidecar, JSON.stringify(cfg, null, 2) + "\n", {
439
+ encoding: "utf8",
440
+ mode: 0o600,
441
+ });
442
+ fs.chmodSync(sidecar, 0o600);
443
+ return cfg;
444
+ }
445
+ // ----- Step 6 + 7: capture pass -----
446
+ export async function runFirstCapturePass(configPath, dataDir) {
447
+ const baseUrl = safeResolveBaseUrl(configPath);
448
+ if (!baseUrl) {
449
+ say("Daemon not reachable — skipping capture pass.");
450
+ return { saved: 0, reviewed: 0 };
451
+ }
452
+ const token = await ensureToken(configPath);
453
+ if (!token) {
454
+ say("No auth token — skipping capture pass.");
455
+ return { saved: 0, reviewed: 0 };
456
+ }
457
+ const client = createHttpClient({ baseUrl, token });
458
+ let codexCaptureDeps = {};
459
+ try {
460
+ const { loadConfig } = await import("../../config/loader.js");
461
+ codexCaptureDeps = resolveCodexCaptureDeps(loadConfig(configPath));
462
+ }
463
+ catch {
464
+ codexCaptureDeps = {};
465
+ }
466
+ try {
467
+ const report = await runAutoCapture({
468
+ dataDir,
469
+ ...codexCaptureDeps,
470
+ saveFn: async (saveOpts) => {
471
+ const { data } = await client.post("/save", {
472
+ source: saveOpts.source,
473
+ summary: saveOpts.summary,
474
+ content: saveOpts.content,
475
+ topics: saveOpts.topics,
476
+ domain: saveOpts.domain,
477
+ idempotency_key: saveOpts.idempotency_key,
478
+ ...(saveOpts.replace_idempotency_key
479
+ ? { replace_idempotency_key: saveOpts.replace_idempotency_key }
480
+ : {}),
481
+ });
482
+ const resp = data;
483
+ if (resp.duplicate)
484
+ return;
485
+ const result = await pollJob({ get: client.get.bind(client), jobId: resp.job_id });
486
+ if (isJobFailure(result.job, result.timedOut)) {
487
+ throw new Error(`Save job failed: ${result.job.error ?? "unknown"}`);
488
+ }
489
+ },
490
+ });
491
+ say(`Capture: discovered ${report.total_discovered}, new ${report.new_conversations}, saved ${report.saved}, review ${report.review}, errors ${report.errors}.`);
492
+ return { saved: report.saved, reviewed: report.review };
493
+ }
494
+ catch (err) {
495
+ say(`Capture pass error (non-fatal): ${err instanceof Error ? err.message : String(err)}`);
496
+ return { saved: 0, reviewed: 0 };
497
+ }
498
+ }
499
+ // ----- Step 8: import -----
500
+ async function collectImportPath(opts, rl) {
501
+ if (opts.importExport)
502
+ return opts.importExport;
503
+ if (opts.yes)
504
+ return null;
505
+ const answer = (await ask(rl, "Drop a path to a ChatGPT/Claude/Grok/Gemini export to import now (or `skip`): ", "skip")).trim();
506
+ if (!answer || answer.toLowerCase() === "skip")
507
+ return null;
508
+ return answer;
509
+ }
510
+ /**
511
+ * Inline import is intentionally narrow: ChatGPT exports only.
512
+ * Friends importing Claude / Grok / Gemini exports during onboarding
513
+ * are pointed at the standalone `rift import <path> --source <name>`
514
+ * command (Slice 3), which adds structural sniffing per source.
515
+ */
516
+ async function runImport(filePath, configPath) {
517
+ const absolute = path.resolve(filePath);
518
+ if (!fs.existsSync(absolute)) {
519
+ say(`Import file not found: ${absolute}`);
520
+ return { kind: "skipped", reason: "file not found" };
521
+ }
522
+ const ext = path.extname(absolute).toLowerCase();
523
+ if (!SUPPORTED_INGEST_EXTENSIONS.has(ext)) {
524
+ say(`Unsupported file extension "${ext}". Allowed: .json, .zip.`);
525
+ return { kind: "skipped", reason: "unsupported extension" };
526
+ }
527
+ const baseUrl = safeResolveBaseUrl(configPath);
528
+ const token = await ensureToken(configPath);
529
+ if (!baseUrl || !token) {
530
+ say("Daemon not reachable — cannot import.");
531
+ return { kind: "skipped", reason: "daemon not reachable" };
532
+ }
533
+ const client = createHttpClient({ baseUrl, token });
534
+ const buf = fs.readFileSync(absolute);
535
+ const form = new FormData();
536
+ form.append("source", ONBOARD_INLINE_IMPORT_SOURCE);
537
+ form.append("file", new Blob([buf]), path.basename(absolute));
538
+ say(`Importing ${path.basename(absolute)} as ${ONBOARD_INLINE_IMPORT_SOURCE}…`);
539
+ say("(For Claude/Grok/Gemini exports, run: rift import <path> --source <name>)");
540
+ const { data } = await client.postMultipart("/ingest", form);
541
+ const resp = data;
542
+ if (resp.duplicate) {
543
+ say(`Import already submitted (job ${resp.job_id}).`);
544
+ return { kind: "duplicate", jobId: resp.job_id };
545
+ }
546
+ const result = await pollJob({ get: client.get.bind(client), jobId: resp.job_id });
547
+ if (isJobFailure(result.job, result.timedOut)) {
548
+ const reason = result.job.error ?? "unknown";
549
+ say(`Import failed: ${reason}`);
550
+ return { kind: "failed", reason };
551
+ }
552
+ say(`Import complete (job ${resp.job_id}).`);
553
+ return { kind: "imported", jobId: resp.job_id };
554
+ }
555
+ /**
556
+ * Pure outcome decision for the next-action card. Onboarding is only
557
+ * "complete" when this run actually ingested user data AND a recall
558
+ * query against the freshly-ingested data returned at least one hit.
559
+ * Smoke is non-indexing (see daemonRefreshFlow), so any hit is real
560
+ * user data, not a leftover probe.
561
+ */
562
+ export function decideOnboardOutcome(input) {
563
+ const { ingestedAny, recall } = input;
564
+ if (ingestedAny && recall.ok && recall.hits > 0) {
565
+ return [
566
+ `Setup complete — recall returned ${recall.hits} result(s) from your data.`,
567
+ "Next: rift mcp install --client=claude-desktop",
568
+ ];
569
+ }
570
+ if (!ingestedAny) {
571
+ return [
572
+ "Setup incomplete — no user data was captured or imported during onboarding.",
573
+ "Next: drop an export at the prompt above and re-run rift onboard,",
574
+ " or run: rift import <path> --source <name>",
575
+ ];
576
+ }
577
+ if (recall.ok) {
578
+ return [
579
+ "Setup partially complete — capture+import succeeded but search returned 0 hits.",
580
+ "Next: rift feedback --kind=broke --with-status \"first-recall returned 0\"",
581
+ ];
582
+ }
583
+ return [
584
+ `Setup partially complete — recall check failed: ${recall.reason}`,
585
+ "Next: rift status (then: rift feedback --kind=broke --with-status)",
586
+ ];
587
+ }
588
+ // ----- Step 9: first-recall verification -----
589
+ async function firstRecallCheck(configPath) {
590
+ const baseUrl = safeResolveBaseUrl(configPath);
591
+ const token = await ensureToken(configPath);
592
+ if (!baseUrl || !token) {
593
+ return { ok: false, reason: "daemon not reachable" };
594
+ }
595
+ const client = createHttpClient({ baseUrl, token });
596
+ // Generic, content-bearing query — likely to land on captured CLI
597
+ // sessions or imported chat exports without targeting any onboarding
598
+ // marker. The smoke is non-indexing (see daemonRefreshFlow), so any
599
+ // hit returned here is real user data, not a leftover probe.
600
+ try {
601
+ const { data } = await client.post("/search", {
602
+ query: "recent conversation",
603
+ scope: "all",
604
+ top_k: 10,
605
+ });
606
+ const body = data;
607
+ const hits = (body.results?.length ?? body.hits?.length ?? 0);
608
+ return { ok: true, hits };
609
+ }
610
+ catch (err) {
611
+ return { ok: false, reason: err instanceof Error ? err.message : String(err) };
612
+ }
613
+ }
614
+ // ----- Slice 6: --reconfigure-voyage -----
615
+ /**
616
+ * Reconfigure the Voyage key. ALL of (kickstart succeeds, /health 200,
617
+ * smoke `voyage_key_present=true`) must pass; any failure rolls back the
618
+ * env file AND restores the previous in-process VOYAGE_API_KEY so a
619
+ * caller is never left with a half-replaced credential. `agent_not_loaded`
620
+ * counts as a failure here (unlike initial onboard) because reconfigure
621
+ * is, by definition, called against a daemon that should already be
622
+ * running — if the launchd label is gone, we don't trust the new key.
623
+ */
624
+ async function reconfigureVoyageFlow(opts, globalOpts, rl) {
625
+ say("Reconfiguring Voyage key…");
626
+ const key = await collectVoyageKey(opts, rl);
627
+ await performVoyageReconfigure({
628
+ key,
629
+ envPath: defaultRiftEnvPath(),
630
+ refresh: () => daemonRefreshFlow(globalOpts),
631
+ });
632
+ }
633
+ /**
634
+ * Core reconfigure logic, extracted so tests can drive every failure
635
+ * branch (validate fail, kickstart agent_not_loaded, /health fail,
636
+ * voyage_key_present=false) without spinning up a real daemon.
637
+ *
638
+ * Contract: ALL of {validate ok, daemonRefresh ok} must succeed; any
639
+ * failure rolls back the env file AND restores the previous in-process
640
+ * VOYAGE_API_KEY. agent_not_loaded counts as a failure here — the call
641
+ * site only invokes this when the daemon should already be running.
642
+ */
643
+ export async function performVoyageReconfigure(deps) {
644
+ const validate = deps.validate ?? validateVoyageKey;
645
+ const write = deps.write ?? writeEnvFile;
646
+ const loadEnv = deps.loadEnv ?? loadRiftEnv;
647
+ const emit = deps.emit ?? say;
648
+ const validation = await validate({ apiKey: deps.key });
649
+ if (!validation.ok) {
650
+ throw new CliError(`Voyage validation failed: ${validation.reason}`, "validation");
651
+ }
652
+ emit(`Voyage key valid (last 4 …${validation.last4}).`);
653
+ const previousInProcessKey = process.env["VOYAGE_API_KEY"];
654
+ const writeResult = write({
655
+ filePath: deps.envPath,
656
+ key: "VOYAGE_API_KEY",
657
+ value: deps.key,
658
+ });
659
+ loadEnv({ filePath: deps.envPath });
660
+ const refresh = await deps.refresh();
661
+ if (refresh.ok) {
662
+ emit(`Voyage reconfigured (last 4 …${validation.last4}).`);
663
+ return;
664
+ }
665
+ rollbackVoyageEnv(deps.envPath, writeResult, previousInProcessKey);
666
+ throw new CliError(`Reconfigure failed — restored previous Voyage key (reason: ${refresh.reason}).`, "server_error");
667
+ }
668
+ /**
669
+ * Restore a Voyage env file + in-process VOYAGE_API_KEY after a failed
670
+ * write. Exported for testing — `reconfigureVoyageFlow` is the only
671
+ * production caller. When `writeResult.backedUp` is true, the prior
672
+ * env-file contents are copied back at mode 0600; when false (no prior
673
+ * file existed), the file we just wrote is removed so we don't leave
674
+ * a key paired with a now-rejected daemon respawn.
675
+ */
676
+ export function rollbackVoyageEnv(envPath, writeResult, previousInProcessKey) {
677
+ // 1. Env file.
678
+ if (writeResult.backedUp && writeResult.backupPath) {
679
+ try {
680
+ fs.copyFileSync(writeResult.backupPath, envPath);
681
+ fs.chmodSync(envPath, 0o600);
682
+ }
683
+ catch {
684
+ say("Reconfigure rollback: env-file restore failed — ping Clem for recovery.");
685
+ }
686
+ }
687
+ else {
688
+ // No prior env file — best effort: drop the line we just wrote so we
689
+ // don't leave a key paired with a now-rejected daemon respawn.
690
+ try {
691
+ fs.rmSync(envPath, { force: true });
692
+ }
693
+ catch {
694
+ // Best-effort.
695
+ }
696
+ }
697
+ // 2. In-process VOYAGE_API_KEY — restore prior value or delete.
698
+ if (typeof previousInProcessKey === "string" && previousInProcessKey.length > 0) {
699
+ process.env["VOYAGE_API_KEY"] = previousInProcessKey;
700
+ }
701
+ else {
702
+ delete process.env["VOYAGE_API_KEY"];
703
+ }
704
+ }
705
+ // ----- Helpers -----
706
+ function ask(rl, question, fallback) {
707
+ return new Promise((resolve) => {
708
+ rl.question(question, (answer) => {
709
+ resolve(answer || fallback || "");
710
+ });
711
+ });
712
+ }
713
+ function say(line) {
714
+ process.stdout.write(line + "\n");
715
+ }
716
+ function sayPrivacyContract() {
717
+ say([
718
+ " • Conversation content stays local (LanceDB + raw transcripts).",
719
+ " • Content snippets leave the machine for embedding only (Voyage AI).",
720
+ " • The Voyage key sits in ~/.rift.env (mode 0600). Never logged, never sent to Clem.",
721
+ " • Feedback is stored locally as JSONL. Relay is opt-in: explicit notes only,",
722
+ " plus daemon health booleans — no paths, no content, no key bytes.",
723
+ " • Full contract: docs/feedback/PRIVACY.md",
724
+ ].join("\n"));
725
+ }
726
+ function safeDiscover(fn) {
727
+ try {
728
+ return fn().length;
729
+ }
730
+ catch {
731
+ return 0;
732
+ }
733
+ }
734
+ function safeResolveBaseUrl(configPath) {
735
+ try {
736
+ return resolveBaseUrl(configPath);
737
+ }
738
+ catch {
739
+ return null;
740
+ }
741
+ }
742
+ //# sourceMappingURL=onboard.js.map