spiracha 1.5.0 → 2.1.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 (401) hide show
  1. package/AGENTS.md +114 -205
  2. package/README.md +94 -269
  3. package/apps/ui/AGENTS.md +17 -7
  4. package/apps/ui/README.md +52 -8
  5. package/apps/ui/components.json +21 -0
  6. package/apps/ui/package.json +65 -0
  7. package/apps/ui/src/components/antigravity-conversations-table.tsx +245 -0
  8. package/apps/ui/src/components/antigravity-keychain-panel.tsx +76 -0
  9. package/apps/ui/src/components/antigravity-workspaces-table.tsx +63 -0
  10. package/apps/ui/src/components/app-shell.tsx +125 -0
  11. package/apps/ui/src/components/breadcrumbs.tsx +71 -0
  12. package/apps/ui/src/components/claude-code-sessions-table.tsx +150 -0
  13. package/apps/ui/src/components/claude-code-workspaces-table.tsx +57 -0
  14. package/apps/ui/src/components/cursor-threads-table.tsx +152 -0
  15. package/apps/ui/src/components/cursor-workspaces-table.tsx +140 -0
  16. package/apps/ui/src/components/data-table.tsx +243 -0
  17. package/apps/ui/src/components/delete-confirm-dialog.tsx +88 -0
  18. package/apps/ui/src/components/export-dialog.tsx +174 -0
  19. package/apps/ui/src/components/grok-sessions-table.tsx +146 -0
  20. package/apps/ui/src/components/grok-workspaces-table.tsx +53 -0
  21. package/apps/ui/src/components/json-panel.tsx +17 -0
  22. package/apps/ui/src/components/kiro-sessions-table.tsx +148 -0
  23. package/apps/ui/src/components/kiro-workspaces-table.tsx +53 -0
  24. package/apps/ui/src/components/list-search-input.tsx +18 -0
  25. package/apps/ui/src/components/loading-panel.tsx +23 -0
  26. package/apps/ui/src/components/metadata-section.tsx +31 -0
  27. package/apps/ui/src/components/metric-card.tsx +19 -0
  28. package/apps/ui/src/components/opencode-sessions-table.tsx +164 -0
  29. package/apps/ui/src/components/opencode-workspaces-table.tsx +57 -0
  30. package/apps/ui/src/components/page-header.tsx +39 -0
  31. package/apps/ui/src/components/projects-loading-state.tsx +74 -0
  32. package/apps/ui/src/components/projects-table.tsx +108 -0
  33. package/apps/ui/src/components/qoder-sessions-table.tsx +133 -0
  34. package/apps/ui/src/components/qoder-workspaces-table.tsx +57 -0
  35. package/apps/ui/src/components/recent-threads-list.tsx +52 -0
  36. package/apps/ui/src/components/reload-error-panel.tsx +20 -0
  37. package/apps/ui/src/components/selection-actions-toolbar.tsx +80 -0
  38. package/apps/ui/src/components/text-document-panel.tsx +19 -0
  39. package/apps/ui/src/components/theme-toggle.tsx +48 -0
  40. package/apps/ui/src/components/threads-table.tsx +165 -0
  41. package/apps/ui/src/components/transcript-view.tsx +648 -0
  42. package/apps/ui/src/components/ui/alert-dialog.tsx +160 -0
  43. package/apps/ui/src/components/ui/badge.tsx +45 -0
  44. package/apps/ui/src/components/ui/button.tsx +62 -0
  45. package/apps/ui/src/components/ui/checkbox.tsx +29 -0
  46. package/apps/ui/src/components/ui/dialog.tsx +137 -0
  47. package/apps/ui/src/components/ui/dropdown-menu.tsx +217 -0
  48. package/apps/ui/src/components/ui/input.tsx +21 -0
  49. package/apps/ui/src/components/ui/scroll-area.tsx +46 -0
  50. package/apps/ui/src/components/ui/select.tsx +163 -0
  51. package/apps/ui/src/components/ui/separator.tsx +28 -0
  52. package/apps/ui/src/components/ui/sheet.tsx +107 -0
  53. package/apps/ui/src/components/ui/skeleton.tsx +7 -0
  54. package/apps/ui/src/components/ui/table.tsx +76 -0
  55. package/apps/ui/src/components/ui/tabs.tsx +71 -0
  56. package/apps/ui/src/components/ui/tooltip.tsx +44 -0
  57. package/apps/ui/src/integrations/tanstack-query/devtools.tsx +6 -0
  58. package/apps/ui/src/integrations/tanstack-query/root-provider.tsx +10 -0
  59. package/apps/ui/src/lib/antigravity-conversation-state.ts +41 -0
  60. package/apps/ui/src/lib/antigravity-queries.ts +33 -0
  61. package/apps/ui/src/lib/antigravity-server.ts +273 -0
  62. package/apps/ui/src/lib/antigravity-transcript-events.ts +343 -0
  63. package/apps/ui/src/lib/claude-code-queries.ts +34 -0
  64. package/apps/ui/src/lib/claude-code-server.ts +243 -0
  65. package/apps/ui/src/lib/claude-code-transcript-events.ts +161 -0
  66. package/apps/ui/src/lib/codex-queries.ts +82 -0
  67. package/apps/ui/src/lib/codex-server.ts +291 -0
  68. package/apps/ui/src/lib/cursor-queries.ts +37 -0
  69. package/apps/ui/src/lib/cursor-server.ts +315 -0
  70. package/apps/ui/src/lib/cursor-transcript-events.ts +229 -0
  71. package/apps/ui/src/lib/download.ts +166 -0
  72. package/apps/ui/src/lib/formatters.ts +147 -0
  73. package/apps/ui/src/lib/grok-queries.ts +22 -0
  74. package/apps/ui/src/lib/grok-server.ts +169 -0
  75. package/apps/ui/src/lib/grok-transcript-events.ts +149 -0
  76. package/apps/ui/src/lib/kiro-queries.ts +22 -0
  77. package/apps/ui/src/lib/kiro-server.ts +151 -0
  78. package/apps/ui/src/lib/kiro-transcript-events.ts +113 -0
  79. package/apps/ui/src/lib/opencode-queries.ts +37 -0
  80. package/apps/ui/src/lib/opencode-server.ts +151 -0
  81. package/apps/ui/src/lib/opencode-transcript-events.ts +221 -0
  82. package/apps/ui/src/lib/package-metadata.ts +16 -0
  83. package/apps/ui/src/lib/path-utils.ts +13 -0
  84. package/apps/ui/src/lib/qoder-queries.ts +22 -0
  85. package/apps/ui/src/lib/qoder-server.ts +135 -0
  86. package/apps/ui/src/lib/qoder-transcript-events.ts +139 -0
  87. package/apps/ui/src/lib/route-search.ts +182 -0
  88. package/apps/ui/src/lib/settings-store.tsx +59 -0
  89. package/apps/ui/src/lib/source-session-export-server.ts +139 -0
  90. package/apps/ui/src/lib/text-filter.ts +22 -0
  91. package/apps/ui/src/lib/thread-id.ts +3 -0
  92. package/apps/ui/src/lib/thread-transcript-load.ts +15 -0
  93. package/apps/ui/src/lib/thread-transcript-stats.ts +57 -0
  94. package/apps/ui/src/lib/utils.ts +7 -0
  95. package/apps/ui/src/lib/workspace-delete-navigation.ts +12 -0
  96. package/apps/ui/src/routeTree.gen.ts +837 -0
  97. package/apps/ui/src/router.tsx +20 -0
  98. package/apps/ui/src/routes/$threadId.tsx +22 -0
  99. package/apps/ui/src/routes/__root.tsx +127 -0
  100. package/apps/ui/src/routes/analytics.tsx +143 -0
  101. package/apps/ui/src/routes/antigravity-conversations.$conversationId.tsx +504 -0
  102. package/apps/ui/src/routes/antigravity.$workspaceKey.tsx +365 -0
  103. package/apps/ui/src/routes/antigravity.index.tsx +51 -0
  104. package/apps/ui/src/routes/api.v1.conversation-query.ts +12 -0
  105. package/apps/ui/src/routes/api.v1.conversations.$source.$id.export.ts +12 -0
  106. package/apps/ui/src/routes/api.v1.conversations.$source.$id.ts +16 -0
  107. package/apps/ui/src/routes/api.v1.conversations.delete.ts +12 -0
  108. package/apps/ui/src/routes/api.v1.conversations.export.ts +12 -0
  109. package/apps/ui/src/routes/api.v1.conversations.ts +12 -0
  110. package/apps/ui/src/routes/api.v1.resolve.ts +12 -0
  111. package/apps/ui/src/routes/api.v1.sources.ts +12 -0
  112. package/apps/ui/src/routes/claude-code-sessions.$sessionId.tsx +468 -0
  113. package/apps/ui/src/routes/claude-code.$workspaceKey.tsx +274 -0
  114. package/apps/ui/src/routes/claude-code.index.tsx +48 -0
  115. package/apps/ui/src/routes/codex.$project.tsx +390 -0
  116. package/apps/ui/src/routes/codex.index.tsx +116 -0
  117. package/apps/ui/src/routes/cursor-threads.$composerId.tsx +435 -0
  118. package/apps/ui/src/routes/cursor.$workspaceKey.tsx +426 -0
  119. package/apps/ui/src/routes/cursor.index.tsx +120 -0
  120. package/apps/ui/src/routes/grok-sessions.$sessionId.tsx +388 -0
  121. package/apps/ui/src/routes/grok.$workspaceKey.tsx +301 -0
  122. package/apps/ui/src/routes/grok.index.tsx +48 -0
  123. package/apps/ui/src/routes/index.tsx +124 -0
  124. package/apps/ui/src/routes/kiro-sessions.$sessionId.tsx +396 -0
  125. package/apps/ui/src/routes/kiro.$workspaceKey.tsx +303 -0
  126. package/apps/ui/src/routes/kiro.index.tsx +48 -0
  127. package/apps/ui/src/routes/opencode-sessions.$sessionId.tsx +420 -0
  128. package/apps/ui/src/routes/opencode.$workspaceKey.tsx +327 -0
  129. package/apps/ui/src/routes/opencode.index.tsx +61 -0
  130. package/apps/ui/src/routes/qoder-sessions.$sessionId.tsx +344 -0
  131. package/apps/ui/src/routes/qoder.$workspaceKey.tsx +186 -0
  132. package/apps/ui/src/routes/qoder.index.tsx +48 -0
  133. package/apps/ui/src/routes/settings.tsx +91 -0
  134. package/apps/ui/src/routes/threads.$threadId.tsx +1103 -0
  135. package/apps/ui/src/styles.css +122 -0
  136. package/apps/ui/tsconfig.json +29 -0
  137. package/apps/ui/vite.config.ts +84 -0
  138. package/bin/spiracha.ts +32 -0
  139. package/package.json +54 -80
  140. package/src/client.ts +423 -0
  141. package/src/lib/antigravity-db.ts +414 -44
  142. package/src/lib/antigravity-exporter-types.ts +4 -0
  143. package/src/lib/antigravity-projects.ts +201 -0
  144. package/src/lib/claude-code-db.ts +498 -32
  145. package/src/lib/claude-code-exporter-types.ts +5 -0
  146. package/src/lib/claude-code-transcript-phase.ts +60 -1
  147. package/src/lib/claude-code-transcript.ts +8 -5
  148. package/src/lib/codex-analytics.ts +1 -1
  149. package/src/lib/codex-browser-db.ts +410 -74
  150. package/src/lib/codex-browser-export.ts +29 -41
  151. package/src/lib/codex-browser-types.ts +1 -1
  152. package/src/lib/codex-thread-cache.ts +41 -13
  153. package/src/lib/codex-thread-parser.ts +86 -35
  154. package/src/lib/{codex-exporter-types.ts → codex-thread-types.ts} +2 -30
  155. package/src/lib/codex-transcript-filter.ts +31 -0
  156. package/src/lib/{codex-exporter-transcript.ts → codex-transcript-renderer.ts} +104 -48
  157. package/src/lib/concurrency.ts +41 -0
  158. package/src/lib/conversation-api.ts +1172 -0
  159. package/src/lib/conversation-data/adapter-helpers.ts +110 -0
  160. package/src/lib/conversation-data/antigravity-adapter.ts +167 -0
  161. package/src/lib/conversation-data/claude-code-adapter.ts +206 -0
  162. package/src/lib/conversation-data/codex-adapter.ts +269 -0
  163. package/src/lib/conversation-data/cursor-adapter.ts +205 -0
  164. package/src/lib/conversation-data/grok-adapter.ts +210 -0
  165. package/src/lib/conversation-data/index.ts +386 -0
  166. package/src/lib/conversation-data/kiro-adapter.ts +174 -0
  167. package/src/lib/conversation-data/message-selector.ts +37 -0
  168. package/src/lib/conversation-data/opencode-adapter.ts +202 -0
  169. package/src/lib/conversation-data/path-match.ts +79 -0
  170. package/src/lib/conversation-data/qoder-adapter.ts +255 -0
  171. package/src/lib/conversation-data/types.ts +159 -0
  172. package/src/lib/conversation-zip-export.ts +57 -0
  173. package/src/lib/cursor-db.ts +100 -25
  174. package/src/lib/cursor-exporter-types.ts +0 -19
  175. package/src/lib/grok-db.ts +1026 -0
  176. package/src/lib/grok-exporter-types.ts +110 -0
  177. package/src/lib/grok-transcript-phase.ts +52 -0
  178. package/src/lib/grok-transcript.ts +154 -0
  179. package/src/lib/kiro-db.ts +52 -1
  180. package/src/lib/model-label.ts +11 -3
  181. package/src/lib/opencode-db.ts +598 -55
  182. package/src/lib/opencode-transcript.ts +8 -5
  183. package/src/lib/qoder-acp-client.ts +268 -0
  184. package/src/lib/qoder-db.ts +1601 -0
  185. package/src/lib/qoder-exporter-types.ts +114 -0
  186. package/src/lib/qoder-transcript-phase.ts +41 -0
  187. package/src/lib/qoder-transcript.ts +112 -0
  188. package/src/lib/shared.ts +12 -0
  189. package/src/lib/transcript-load-limiter.ts +82 -0
  190. package/src/lib/ui-cache.ts +43 -17
  191. package/src/lib/ui-export-archive.ts +60 -0
  192. package/apps/ui/dist/client/assets/_threadId-CAIeH5mq.js +0 -1
  193. package/apps/ui/dist/client/assets/analytics-DOy1b6Sh.js +0 -1
  194. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-DqySVO2K.js +0 -7
  195. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-KAcXtNxI.js +0 -1
  196. package/apps/ui/dist/client/assets/antigravity-keychain-panel-B77qJz6f.js +0 -1
  197. package/apps/ui/dist/client/assets/antigravity._workspaceKey-B3NM6gRH.js +0 -1
  198. package/apps/ui/dist/client/assets/antigravity._workspaceKey-ByitGWki.js +0 -1
  199. package/apps/ui/dist/client/assets/antigravity.index-DP9JC2P9.js +0 -1
  200. package/apps/ui/dist/client/assets/antigravity.index-DgW25FEV.js +0 -1
  201. package/apps/ui/dist/client/assets/badge-C3i4OKs8.js +0 -1
  202. package/apps/ui/dist/client/assets/checkbox-CdHitXWQ.js +0 -1
  203. package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-8pQ55ci2.js +0 -1
  204. package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-DVz5UmtU.js +0 -1
  205. package/apps/ui/dist/client/assets/claude-code._workspaceKey-BBKskSum.js +0 -1
  206. package/apps/ui/dist/client/assets/claude-code._workspaceKey-OkikMUFs.js +0 -1
  207. package/apps/ui/dist/client/assets/claude-code.index-Cwu76dbb.js +0 -1
  208. package/apps/ui/dist/client/assets/claude-code.index-D6eMd08t.js +0 -1
  209. package/apps/ui/dist/client/assets/createServerFn-B-KkwmHU.js +0 -3
  210. package/apps/ui/dist/client/assets/cursor-threads._composerId-CmBFclK8.js +0 -1
  211. package/apps/ui/dist/client/assets/cursor-threads._composerId-hBWlP1D-.js +0 -1
  212. package/apps/ui/dist/client/assets/cursor._workspaceKey-BFPkIRi-.js +0 -1
  213. package/apps/ui/dist/client/assets/cursor._workspaceKey-CaAZjGmm.js +0 -1
  214. package/apps/ui/dist/client/assets/cursor.index-8y4o20kb.js +0 -2
  215. package/apps/ui/dist/client/assets/cursor.index-CrnMwDCi.js +0 -1
  216. package/apps/ui/dist/client/assets/data-table-Br78_dk3.js +0 -4
  217. package/apps/ui/dist/client/assets/delete-confirm-dialog-Bxs07u-j.js +0 -7
  218. package/apps/ui/dist/client/assets/dist-B9pyYCVU.js +0 -1
  219. package/apps/ui/dist/client/assets/dist-BrJhN2A0.js +0 -5
  220. package/apps/ui/dist/client/assets/dist-Cmd3AIfD.js +0 -1
  221. package/apps/ui/dist/client/assets/dist-DvMS2965.js +0 -1
  222. package/apps/ui/dist/client/assets/download-Bf0QJKD3.js +0 -1
  223. package/apps/ui/dist/client/assets/dropdown-menu-D5cvPaZt.js +0 -1
  224. package/apps/ui/dist/client/assets/es2015-ad6040dw.js +0 -41
  225. package/apps/ui/dist/client/assets/export-dialog-Dr8d2MqD.js +0 -1
  226. package/apps/ui/dist/client/assets/formatters-BtqyrX_c.js +0 -1
  227. package/apps/ui/dist/client/assets/index-C-STgIH4.js +0 -166
  228. package/apps/ui/dist/client/assets/jsx-runtime-DGeXAQPT.js +0 -1
  229. package/apps/ui/dist/client/assets/kiro-sessions._sessionId-CKgfJ7GR.js +0 -1
  230. package/apps/ui/dist/client/assets/kiro-sessions._sessionId-zvIJHtQF.js +0 -1
  231. package/apps/ui/dist/client/assets/kiro._workspaceKey-DhVuJuZB.js +0 -1
  232. package/apps/ui/dist/client/assets/kiro._workspaceKey-QArsjkTY.js +0 -1
  233. package/apps/ui/dist/client/assets/kiro.index-C-fr4m7i.js +0 -1
  234. package/apps/ui/dist/client/assets/kiro.index-OYgAdtZd.js +0 -1
  235. package/apps/ui/dist/client/assets/metric-card-Dplm0ZiM.js +0 -1
  236. package/apps/ui/dist/client/assets/opencode-sessions._sessionId-DLjiTst-.js +0 -1
  237. package/apps/ui/dist/client/assets/opencode-sessions._sessionId-biBwrRbt.js +0 -8
  238. package/apps/ui/dist/client/assets/opencode._workspaceKey-C7OIzMOJ.js +0 -1
  239. package/apps/ui/dist/client/assets/opencode._workspaceKey-sBakX0oI.js +0 -1
  240. package/apps/ui/dist/client/assets/opencode.index-Bl_kNs9N.js +0 -1
  241. package/apps/ui/dist/client/assets/opencode.index-CN53bVmb.js +0 -1
  242. package/apps/ui/dist/client/assets/page-header-Cwa3p6Tl.js +0 -1
  243. package/apps/ui/dist/client/assets/preload-helper-B8fFrdxC.js +0 -1
  244. package/apps/ui/dist/client/assets/projects._project-D8WloxQN.js +0 -1
  245. package/apps/ui/dist/client/assets/projects._project-DSDwH4NF.js +0 -1
  246. package/apps/ui/dist/client/assets/projects.index-5xRtuJdX.js +0 -3
  247. package/apps/ui/dist/client/assets/projects.index-DEfhWqa8.js +0 -1
  248. package/apps/ui/dist/client/assets/react-dom-DL96Jor4.js +0 -1
  249. package/apps/ui/dist/client/assets/refresh-ccw-BgKjOiA6.js +0 -1
  250. package/apps/ui/dist/client/assets/reload-error-panel-AHqu0akK.js +0 -1
  251. package/apps/ui/dist/client/assets/routes-DnzF_9CX.js +0 -1
  252. package/apps/ui/dist/client/assets/scroll-text-fM0sMOB3.js +0 -1
  253. package/apps/ui/dist/client/assets/select-CYF6pF37.js +0 -1
  254. package/apps/ui/dist/client/assets/settings-Dx70jgP_.js +0 -1
  255. package/apps/ui/dist/client/assets/sqlite-error-B6uZjUe8.js +0 -1
  256. package/apps/ui/dist/client/assets/styles-B7Zi9EFA.css +0 -1
  257. package/apps/ui/dist/client/assets/tabs-CmuhkT-c.js +0 -7
  258. package/apps/ui/dist/client/assets/text-filter-DVAZySUS.js +0 -2
  259. package/apps/ui/dist/client/assets/thread-transcript-stats-BUNz6u7F.js +0 -1
  260. package/apps/ui/dist/client/assets/threads._threadId-BB9tTsV4.js +0 -1
  261. package/apps/ui/dist/client/assets/threads._threadId-BMRSFow3.js +0 -1
  262. package/apps/ui/dist/client/assets/useMutation-BSFult2i.js +0 -1
  263. package/apps/ui/dist/client/assets/useQuery-CjINKZf1.js +0 -1
  264. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CQ8Jjs3B.js +0 -387
  265. package/apps/ui/dist/server/assets/_threadId-B6SrBR9E.js +0 -6
  266. package/apps/ui/dist/server/assets/analytics-CYP_LT5Y.js +0 -16
  267. package/apps/ui/dist/server/assets/analytics-CtpOMVMO.js +0 -146
  268. package/apps/ui/dist/server/assets/antigravity-conversation-state-HgzS302O.js +0 -16
  269. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-BKOyL2T6.js +0 -613
  270. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-D426O-64.js +0 -11
  271. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-eS87Dx7g.js +0 -20
  272. package/apps/ui/dist/server/assets/antigravity-db-Bh8_U9uw.js +0 -580
  273. package/apps/ui/dist/server/assets/antigravity-keychain-DOiuHDwK.js +0 -126
  274. package/apps/ui/dist/server/assets/antigravity-keychain-panel-CC7FLmAK.js +0 -55
  275. package/apps/ui/dist/server/assets/antigravity-queries-CGrJO9Vr.js +0 -37
  276. package/apps/ui/dist/server/assets/antigravity-server-CHRjVFqN.js +0 -114
  277. package/apps/ui/dist/server/assets/antigravity._workspaceKey-3m_MzNFA.js +0 -11
  278. package/apps/ui/dist/server/assets/antigravity._workspaceKey-B0QeYUOh.js +0 -28
  279. package/apps/ui/dist/server/assets/antigravity._workspaceKey-C3kP-qyN.js +0 -210
  280. package/apps/ui/dist/server/assets/antigravity.index-CPCYkqCi.js +0 -104
  281. package/apps/ui/dist/server/assets/antigravity.index-DudTB3Tq.js +0 -11
  282. package/apps/ui/dist/server/assets/badge-EvdhKK_Z.js +0 -26
  283. package/apps/ui/dist/server/assets/button-CmTDnzOn.js +0 -46
  284. package/apps/ui/dist/server/assets/checkbox-C0hovF41.js +0 -19
  285. package/apps/ui/dist/server/assets/claude-code-db-Ik3VStKZ.js +0 -361
  286. package/apps/ui/dist/server/assets/claude-code-queries-Cgzi4K-e.js +0 -37
  287. package/apps/ui/dist/server/assets/claude-code-server-PfraClXS.js +0 -72
  288. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-C55oe6zj.js +0 -18
  289. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-D1RYYi3j.js +0 -473
  290. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-DSvPLEUL.js +0 -11
  291. package/apps/ui/dist/server/assets/claude-code-transcript-C-bxh3cS.js +0 -139
  292. package/apps/ui/dist/server/assets/claude-code-transcript-phase-DmUMc8VU.js +0 -10
  293. package/apps/ui/dist/server/assets/claude-code._workspaceKey-B5Xg_-tE.js +0 -28
  294. package/apps/ui/dist/server/assets/claude-code._workspaceKey-BPlzyXPa.js +0 -11
  295. package/apps/ui/dist/server/assets/claude-code._workspaceKey-DqDve2wl.js +0 -191
  296. package/apps/ui/dist/server/assets/claude-code.index-B7yYR7dD.js +0 -92
  297. package/apps/ui/dist/server/assets/claude-code.index-BUHThG1W.js +0 -11
  298. package/apps/ui/dist/server/assets/codex-queries-CtgeZ7VL.js +0 -99
  299. package/apps/ui/dist/server/assets/codex-server-CGXU4H8-.js +0 -2294
  300. package/apps/ui/dist/server/assets/concurrency-VXtYvlGh.js +0 -18
  301. package/apps/ui/dist/server/assets/createServerRpc-CF_DEwnm.js +0 -12
  302. package/apps/ui/dist/server/assets/createSsrRpc-C754NPki.js +0 -16
  303. package/apps/ui/dist/server/assets/cursor-db-CZnYy7aT.js +0 -830
  304. package/apps/ui/dist/server/assets/cursor-exporter-types-CI3goo-c.js +0 -34
  305. package/apps/ui/dist/server/assets/cursor-queries-NCIM0Nat.js +0 -67
  306. package/apps/ui/dist/server/assets/cursor-recovery-CXpO8KcD.js +0 -361
  307. package/apps/ui/dist/server/assets/cursor-server-DNu52A3K.js +0 -213
  308. package/apps/ui/dist/server/assets/cursor-threads._composerId-BB0Y_Mao.js +0 -11
  309. package/apps/ui/dist/server/assets/cursor-threads._composerId-Ckn6ItHI.js +0 -582
  310. package/apps/ui/dist/server/assets/cursor-threads._composerId-p9-ARAzc.js +0 -18
  311. package/apps/ui/dist/server/assets/cursor-transcript-B7tGnqtn.js +0 -125
  312. package/apps/ui/dist/server/assets/cursor._workspaceKey-CZuohIUL.js +0 -28
  313. package/apps/ui/dist/server/assets/cursor._workspaceKey-DPp5JSjy.js +0 -401
  314. package/apps/ui/dist/server/assets/cursor._workspaceKey-nmg3YIOQ.js +0 -11
  315. package/apps/ui/dist/server/assets/cursor.index-CcsX7DG0.js +0 -11
  316. package/apps/ui/dist/server/assets/cursor.index-DkWT-mxw.js +0 -189
  317. package/apps/ui/dist/server/assets/data-table-Cdct823O.js +0 -189
  318. package/apps/ui/dist/server/assets/delete-confirm-dialog-BcBNCxWB.js +0 -144
  319. package/apps/ui/dist/server/assets/download-DMmiy1xf.js +0 -92
  320. package/apps/ui/dist/server/assets/dropdown-menu-Dy_9t6TN.js +0 -36
  321. package/apps/ui/dist/server/assets/empty-plugin-adapters-B3lHh1La.js +0 -5
  322. package/apps/ui/dist/server/assets/export-dialog-D88ze9Gy.js +0 -240
  323. package/apps/ui/dist/server/assets/formatters-FJaGZgJk.js +0 -91
  324. package/apps/ui/dist/server/assets/kiro-db--fXrED_-.js +0 -552
  325. package/apps/ui/dist/server/assets/kiro-queries-CzNlM2ok.js +0 -37
  326. package/apps/ui/dist/server/assets/kiro-server-9WRxg2Au.js +0 -72
  327. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-CRY2c7YO.js +0 -11
  328. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-F1UlwxmR.js +0 -449
  329. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-bvTulT7C.js +0 -18
  330. package/apps/ui/dist/server/assets/kiro-transcript-DoekQBaH.js +0 -112
  331. package/apps/ui/dist/server/assets/kiro-transcript-phase-CJG40nQg.js +0 -27
  332. package/apps/ui/dist/server/assets/kiro._workspaceKey-BDe9sQwo.js +0 -11
  333. package/apps/ui/dist/server/assets/kiro._workspaceKey-CJsjgNwO.js +0 -28
  334. package/apps/ui/dist/server/assets/kiro._workspaceKey-D_-4Qb7y.js +0 -193
  335. package/apps/ui/dist/server/assets/kiro.index-C__-UROk.js +0 -11
  336. package/apps/ui/dist/server/assets/kiro.index-CmTbqeYj.js +0 -93
  337. package/apps/ui/dist/server/assets/loading-panel-BGFnWseS.js +0 -27
  338. package/apps/ui/dist/server/assets/metric-card-ByEeLu0r.js +0 -23
  339. package/apps/ui/dist/server/assets/model-label-B1NWGc65.js +0 -13
  340. package/apps/ui/dist/server/assets/opencode-db-BM7KjOzc.js +0 -397
  341. package/apps/ui/dist/server/assets/opencode-queries-BeNYXnQv.js +0 -50
  342. package/apps/ui/dist/server/assets/opencode-server-BpQ_kRze.js +0 -72
  343. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-CGQ-t0vD.js +0 -518
  344. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-D8Q7in_Z.js +0 -18
  345. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-DKOvi0lV.js +0 -11
  346. package/apps/ui/dist/server/assets/opencode-think-tags-CAoD-EcZ.js +0 -87
  347. package/apps/ui/dist/server/assets/opencode-transcript-BNTcGNym.js +0 -141
  348. package/apps/ui/dist/server/assets/opencode-transcript-phase-OqLkiQD0.js +0 -32
  349. package/apps/ui/dist/server/assets/opencode._workspaceKey-BdqcWHw1.js +0 -11
  350. package/apps/ui/dist/server/assets/opencode._workspaceKey-CfH96HTT.js +0 -28
  351. package/apps/ui/dist/server/assets/opencode._workspaceKey-DdbHPDrO.js +0 -207
  352. package/apps/ui/dist/server/assets/opencode.index-BbVzkJXP.js +0 -11
  353. package/apps/ui/dist/server/assets/opencode.index-Vh_Gq_1L.js +0 -93
  354. package/apps/ui/dist/server/assets/page-header-VNSaM3xd.js +0 -29
  355. package/apps/ui/dist/server/assets/path-transforms-DL2IwtYd.js +0 -31
  356. package/apps/ui/dist/server/assets/projects._project-4io5LO0E.js +0 -20
  357. package/apps/ui/dist/server/assets/projects._project-Bshqk7JA.js +0 -12
  358. package/apps/ui/dist/server/assets/projects._project-D6ZoGhJ8.js +0 -395
  359. package/apps/ui/dist/server/assets/projects.index-BLXOx5eL.js +0 -12
  360. package/apps/ui/dist/server/assets/projects.index-BkLiF2FF.js +0 -182
  361. package/apps/ui/dist/server/assets/projects.index-DesYXwfi.js +0 -14
  362. package/apps/ui/dist/server/assets/reload-error-panel-BJMxY3U1.js +0 -25
  363. package/apps/ui/dist/server/assets/route-search-ts4W9MJ9.js +0 -38
  364. package/apps/ui/dist/server/assets/router-Sac2DGk6.js +0 -518
  365. package/apps/ui/dist/server/assets/routes-Bsact1uB.js +0 -184
  366. package/apps/ui/dist/server/assets/routes-BzkJgq4W.js +0 -34
  367. package/apps/ui/dist/server/assets/select-GW76p-ld.js +0 -76
  368. package/apps/ui/dist/server/assets/settings-OayxIYQQ.js +0 -100
  369. package/apps/ui/dist/server/assets/settings-store-DpEJEQ7M.js +0 -52
  370. package/apps/ui/dist/server/assets/shared-DyhChtHf.js +0 -137
  371. package/apps/ui/dist/server/assets/source-session-export-server-DNutCawb.js +0 -38
  372. package/apps/ui/dist/server/assets/sqlite-error-LZDrnxdd.js +0 -13
  373. package/apps/ui/dist/server/assets/start-B_HFwkkk.js +0 -4
  374. package/apps/ui/dist/server/assets/tabs-DkaChNVg.js +0 -501
  375. package/apps/ui/dist/server/assets/text-filter-CGKxMCKt.js +0 -36
  376. package/apps/ui/dist/server/assets/thread-transcript-stats-Dh34mt2u.js +0 -45
  377. package/apps/ui/dist/server/assets/threads._threadId-BSSK4nkI.js +0 -26
  378. package/apps/ui/dist/server/assets/threads._threadId-BeXEc4Lo.js +0 -648
  379. package/apps/ui/dist/server/assets/threads._threadId-Ci0S4mKU.js +0 -18
  380. package/apps/ui/dist/server/assets/ui-export-files-BHLX9bhN.js +0 -83
  381. package/apps/ui/dist/server/assets/utils-C_uf36nf.js +0 -8
  382. package/apps/ui/dist/server/server.js +0 -5895
  383. package/bin/codex-chats-claude.js +0 -5
  384. package/bin/codex-chats.js +0 -5
  385. package/bin/spiracha.js +0 -5
  386. package/src/export-chats.ts +0 -120
  387. package/src/export-claude.ts +0 -36
  388. package/src/export-cursor.ts +0 -244
  389. package/src/lib/claude-exporter.ts +0 -864
  390. package/src/lib/codex-exporter-cli.ts +0 -277
  391. package/src/lib/codex-exporter-db.ts +0 -319
  392. package/src/lib/codex-exporter.ts +0 -115
  393. package/src/lib/cursor-exporter.ts +0 -266
  394. package/src/lib/interactive-cli.ts +0 -433
  395. package/src/lib/native-open.ts +0 -54
  396. package/src/mcp-server.ts +0 -137
  397. package/src/spiracha.ts +0 -116
  398. package/src/ui-cli.ts +0 -310
  399. /package/apps/ui/{dist/client → public}/icon.svg +0 -0
  400. /package/apps/ui/{dist/client → public}/manifest.json +0 -0
  401. /package/apps/ui/{dist/client → public}/robots.txt +0 -0
@@ -1,54 +0,0 @@
1
- type NativeOpenTarget = {
2
- kind: 'path' | 'url';
3
- value: string;
4
- };
5
-
6
- const resolveNativeOpenCommand = () => {
7
- if (process.platform === 'darwin') {
8
- return {
9
- argv: (target: NativeOpenTarget) => ['open', target.value],
10
- label: 'open',
11
- };
12
- }
13
-
14
- if (process.platform === 'win32') {
15
- return {
16
- argv: (target: NativeOpenTarget) => ['cmd', '/c', 'start', '', target.value],
17
- label: 'start',
18
- };
19
- }
20
-
21
- return {
22
- argv: (target: NativeOpenTarget) => ['xdg-open', target.value],
23
- label: 'xdg-open',
24
- };
25
- };
26
-
27
- const openNatively = async (target: NativeOpenTarget) => {
28
- const command = resolveNativeOpenCommand();
29
- const proc = Bun.spawn(command.argv(target), {
30
- stderr: 'pipe',
31
- stdout: 'ignore',
32
- });
33
- const exitCode = await proc.exited;
34
- if (exitCode !== 0) {
35
- const errorText = await new Response(proc.stderr).text();
36
- throw new Error(
37
- `Failed to open ${target.value} with ${command.label}: ${errorText.trim() || `exit code ${exitCode}`}`,
38
- );
39
- }
40
- };
41
-
42
- export const openPathNatively = async (targetPath: string) => {
43
- await openNatively({
44
- kind: 'path',
45
- value: targetPath,
46
- });
47
- };
48
-
49
- export const openUrlNatively = async (url: string) => {
50
- await openNatively({
51
- kind: 'url',
52
- value: url,
53
- });
54
- };
package/src/mcp-server.ts DELETED
@@ -1,137 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
5
- import type { AnySchema } from '@modelcontextprotocol/sdk/server/zod-compat.js';
6
- import { z } from 'zod';
7
- import { runClaudeExport } from './lib/claude-exporter';
8
- import {
9
- DEFAULT_DB_PATH,
10
- DEFAULT_INPUT_DIR,
11
- parseThreadSelectionArg,
12
- resolveDefaultOutputDir,
13
- runCodexExport,
14
- } from './lib/codex-exporter';
15
- import { expandHome } from './lib/shared';
16
-
17
- const server = new McpServer({
18
- name: 'codex-chats-export',
19
- version: '0.1.0',
20
- });
21
-
22
- const exportCodexChatsInputSchema = {
23
- cwd: z.string().optional().describe('Optional exact cwd filter'),
24
- dbPath: z.string().optional().describe('Optional override for the Codex SQLite database'),
25
- deeplinks: z.array(z.string()).optional().describe('Optional Codex deeplinks like codex://threads/<thread-id>'),
26
- flat: z.boolean().optional().describe('Write output into a single flat folder'),
27
- includeMetadata: z.boolean().optional().describe('Include the chat metadata section at the top of each export'),
28
- includeTools: z.boolean().optional().describe('Include exec_command tool logs'),
29
- inputDir: z.string().optional().describe('Optional override for the Codex sessions directory'),
30
- outputDir: z.string().optional().describe('Optional output directory'),
31
- outputFormat: z.enum(['md', 'txt']).optional().describe('Output format'),
32
- project: z.string().optional().describe('Optional project name matched against path basename'),
33
- } as unknown as Record<string, AnySchema>;
34
-
35
- const exportClaudeTranscriptInputSchema = {
36
- includeTools: z.boolean().optional().describe('Include Bash tool calls and outputs'),
37
- inputPath: z.string().describe('Path to a Claude transcript .jsonl file or export directory'),
38
- outputFormat: z.enum(['md', 'txt']).optional().describe('Output format'),
39
- outputPath: z.string().optional().describe('Optional output file path or directory'),
40
- } as unknown as Record<string, AnySchema>;
41
-
42
- server.registerTool(
43
- 'export_codex_chats',
44
- {
45
- description: 'Export Codex chats by deeplink, project name, or cwd to markdown or plain text.',
46
- inputSchema: exportCodexChatsInputSchema,
47
- },
48
- async (args: any) => {
49
- const threadIds = parseThreadSelections(args.deeplinks ?? []);
50
- const cwdFilter = args.cwd ? expandHome(args.cwd) : null;
51
-
52
- if (threadIds.length === 0 && !args.project && !cwdFilter) {
53
- throw new Error(
54
- 'Provide at least one deeplink, project, or cwd filter to avoid exporting the entire Codex history by accident.',
55
- );
56
- }
57
-
58
- const result = await runCodexExport({
59
- cwdFilter,
60
- dbPath: expandHome(args.dbPath ?? DEFAULT_DB_PATH),
61
- flat: args.flat ?? false,
62
- includeCommentary: true,
63
- includeMetadata: args.includeMetadata ?? true,
64
- includeTools: args.includeTools ?? false,
65
- inputDir: expandHome(args.inputDir ?? DEFAULT_INPUT_DIR),
66
- outputDir: args.outputDir ? expandHome(args.outputDir) : resolveDefaultOutputDir(cwdFilter),
67
- outputFormat: args.outputFormat ?? 'md',
68
- projectFilter: args.project ?? null,
69
- threadIds,
70
- });
71
-
72
- return {
73
- content: [
74
- {
75
- text: JSON.stringify(
76
- {
77
- exportedCount: result.exportedCount,
78
- files: result.files,
79
- missingThreadIds: result.missingThreadIds,
80
- outputDir: result.outputDir,
81
- },
82
- null,
83
- 2,
84
- ),
85
- type: 'text',
86
- },
87
- ],
88
- };
89
- },
90
- );
91
-
92
- server.registerTool(
93
- 'export_claude_transcript',
94
- {
95
- description: 'Export a Claude Code transcript JSONL or export directory to markdown or plain text.',
96
- inputSchema: exportClaudeTranscriptInputSchema,
97
- },
98
- async (args: any) => {
99
- const result = await runClaudeExport({
100
- includeTools: args.includeTools ?? false,
101
- inputPath: expandHome(args.inputPath),
102
- outputFormat: args.outputFormat ?? 'md',
103
- outputPath: args.outputPath ? expandHome(args.outputPath) : null,
104
- });
105
-
106
- return {
107
- content: [
108
- {
109
- text: JSON.stringify(result, null, 2),
110
- type: 'text',
111
- },
112
- ],
113
- };
114
- },
115
- );
116
-
117
- const main = async () => {
118
- const transport = new StdioServerTransport();
119
- await server.connect(transport);
120
- };
121
-
122
- const parseThreadSelections = (deeplinks: string[]): string[] => {
123
- return deeplinks.map((deeplink) => {
124
- const threadId = parseThreadSelectionArg(deeplink);
125
- if (!threadId) {
126
- throw new Error(`Invalid Codex deeplink: ${deeplink}. Expected codex://threads/<thread-id>`);
127
- }
128
-
129
- return threadId;
130
- });
131
- };
132
-
133
- main().catch((error) => {
134
- const message = error instanceof Error ? error.message : String(error);
135
- console.error(message);
136
- process.exit(1);
137
- });
package/src/spiracha.ts DELETED
@@ -1,116 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- type SpirachaCommandKind = 'codex' | 'claude' | 'cursor' | 'help' | 'ui' | 'version';
4
-
5
- type SpirachaInvocation = {
6
- kind: SpirachaCommandKind;
7
- argv: string[];
8
- };
9
-
10
- export const resolveSpirachaInvocation = (argv: string[]): SpirachaInvocation => {
11
- const [firstArg, ...rest] = argv;
12
-
13
- if (firstArg === 'claude') {
14
- return { argv: rest, kind: 'claude' };
15
- }
16
-
17
- if (firstArg === 'codex') {
18
- return { argv: rest, kind: 'codex' };
19
- }
20
-
21
- if (firstArg === 'cursor') {
22
- return { argv: rest, kind: 'cursor' };
23
- }
24
-
25
- if (firstArg === 'ui') {
26
- return { argv: rest, kind: 'ui' };
27
- }
28
-
29
- if (firstArg === '--help' || firstArg === '-h' || firstArg === 'help') {
30
- return { argv: [], kind: 'help' };
31
- }
32
-
33
- if (firstArg === '--version' || firstArg === '-v' || firstArg === 'version') {
34
- return { argv: [], kind: 'version' };
35
- }
36
-
37
- return { argv, kind: 'codex' };
38
- };
39
-
40
- export const readSpirachaPackageVersion = async (): Promise<string> => {
41
- const manifest = (await Bun.file(new URL('../package.json', import.meta.url)).json()) as { version?: unknown };
42
- if (typeof manifest.version !== 'string' || !manifest.version) {
43
- throw new Error('Unable to read Spiracha version from package.json.');
44
- }
45
-
46
- return manifest.version;
47
- };
48
-
49
- export const getSpirachaHelpText = (): string => {
50
- return [
51
- 'spiracha - export local assistant transcripts and browse local history',
52
- '',
53
- 'Usage:',
54
- ' spiracha',
55
- ' spiracha codex [Codex options]',
56
- ' spiracha claude [Claude options]',
57
- ' spiracha cursor [Cursor options]',
58
- ' spiracha ui [UI options]',
59
- '',
60
- 'Commands:',
61
- ' codex Export Codex chats (default when no subcommand is provided)',
62
- ' claude Export a Claude transcript file or export directory',
63
- ' cursor Export, recover, and prune local Cursor Agent/Composer threads',
64
- ' ui Launch the local browser UI for Codex, Cursor, and Antigravity history',
65
- '',
66
- 'Aliases:',
67
- ' codex-chats',
68
- ' codex-chats-claude',
69
- '',
70
- 'For command-specific help:',
71
- ' spiracha codex --help',
72
- ' spiracha claude --help',
73
- ' spiracha cursor --help',
74
- ' spiracha ui --help',
75
- ' spiracha --version',
76
- ].join('\n');
77
- };
78
-
79
- export const runSpirachaCli = async (argv = process.argv.slice(2)): Promise<void> => {
80
- const invocation = resolveSpirachaInvocation(argv);
81
-
82
- if (invocation.kind === 'help') {
83
- console.log(getSpirachaHelpText());
84
- return;
85
- }
86
-
87
- if (invocation.kind === 'version') {
88
- console.log(await readSpirachaPackageVersion());
89
- return;
90
- }
91
-
92
- if (invocation.kind === 'claude') {
93
- const { runExportClaudeCli } = await import('./export-claude');
94
- await runExportClaudeCli(invocation.argv);
95
- return;
96
- }
97
-
98
- if (invocation.kind === 'cursor') {
99
- const { runExportCursorCli } = await import('./export-cursor');
100
- await runExportCursorCli(invocation.argv);
101
- return;
102
- }
103
-
104
- if (invocation.kind === 'ui') {
105
- const { runUiCli } = await import('./ui-cli');
106
- await runUiCli(invocation.argv);
107
- return;
108
- }
109
-
110
- const { runExportChatsCli } = await import('./export-chats');
111
- await runExportChatsCli(invocation.argv);
112
- };
113
-
114
- if (import.meta.main) {
115
- await runSpirachaCli();
116
- }
package/src/ui-cli.ts DELETED
@@ -1,310 +0,0 @@
1
- #!/usr/bin/env bun
2
-
3
- import { access, constants } from 'node:fs/promises';
4
- import path from 'node:path';
5
- import { openUrlNatively } from './lib/native-open';
6
- import { CliUsageError } from './lib/shared';
7
- import {
8
- buildUiExportContentDisposition,
9
- ensureUiExportDir,
10
- resolveUiExportFilePathFromRequestPath,
11
- } from './lib/ui-export-files';
12
-
13
- type UiCliOptions = {
14
- dbPath: string | null;
15
- host: string;
16
- openBrowser: boolean;
17
- port: number;
18
- };
19
-
20
- const DEFAULT_UI_HOST = '127.0.0.1';
21
- const DEFAULT_UI_PORT = 3000;
22
- const MAX_PORT_ATTEMPTS = 10;
23
-
24
- const resolveUiDistPaths = () => {
25
- const distRoot = path.resolve(import.meta.dir, '..', 'apps', 'ui', 'dist');
26
- return {
27
- clientDir: path.join(distRoot, 'client'),
28
- serverEntryPath: path.join(distRoot, 'server', 'server.js'),
29
- };
30
- };
31
-
32
- const ensureUiBuildExists = async () => {
33
- const { clientDir, serverEntryPath } = resolveUiDistPaths();
34
- const serverEntry = Bun.file(serverEntryPath);
35
- const clientAssetExists = await Bun.file(path.join(clientDir, 'icon.svg')).exists();
36
- const serverEntryExists = await serverEntry.exists();
37
-
38
- if (!clientAssetExists || !serverEntryExists) {
39
- throw new Error('UI build artifacts are missing. Run `bun run build` before launching `spiracha ui`.');
40
- }
41
-
42
- await ensureUiExportDir();
43
- };
44
-
45
- const parsePort = (value: string) => {
46
- const parsed = Number.parseInt(value, 10);
47
- if (!Number.isInteger(parsed) || parsed <= 0 || parsed > 65535) {
48
- throw new CliUsageError(`Invalid port: ${value}`);
49
- }
50
-
51
- return parsed;
52
- };
53
-
54
- const requireUiArgValue = (value: string | undefined, flag: string) => {
55
- if (!value) {
56
- throw new CliUsageError(`Missing value for ${flag}`);
57
- }
58
-
59
- return value;
60
- };
61
-
62
- const applyUiCliArg = (
63
- argv: string[],
64
- index: number,
65
- state: UiCliOptions,
66
- ): {
67
- index: number;
68
- state: UiCliOptions;
69
- } => {
70
- const arg = argv[index];
71
-
72
- if (arg === '--no-open') {
73
- return {
74
- index,
75
- state: {
76
- ...state,
77
- openBrowser: false,
78
- },
79
- };
80
- }
81
-
82
- if (arg === '--port') {
83
- return {
84
- index: index + 1,
85
- state: {
86
- ...state,
87
- port: parsePort(requireUiArgValue(argv[index + 1], '--port')),
88
- },
89
- };
90
- }
91
-
92
- if (arg === '--host') {
93
- return {
94
- index: index + 1,
95
- state: {
96
- ...state,
97
- host: requireUiArgValue(argv[index + 1], '--host'),
98
- },
99
- };
100
- }
101
-
102
- if (arg === '--db') {
103
- return {
104
- index: index + 1,
105
- state: {
106
- ...state,
107
- dbPath: requireUiArgValue(argv[index + 1], '--db'),
108
- },
109
- };
110
- }
111
-
112
- throw new CliUsageError(`Unknown UI argument: ${arg}`);
113
- };
114
-
115
- export const parseUiCliArgs = (argv: string[]): UiCliOptions => {
116
- let state: UiCliOptions = {
117
- dbPath: null,
118
- host: DEFAULT_UI_HOST,
119
- openBrowser: true,
120
- port: DEFAULT_UI_PORT,
121
- };
122
-
123
- for (let index = 0; index < argv.length; index += 1) {
124
- const next = applyUiCliArg(argv, index, state);
125
- state = next.state;
126
- index = next.index;
127
- }
128
-
129
- return state;
130
- };
131
-
132
- export const getUiHelpText = (): string => {
133
- return [
134
- 'Launch the Spiracha browser UI for Codex, Cursor, and Antigravity history.',
135
- '',
136
- 'Usage:',
137
- ' spiracha ui [--port 3000] [--host 127.0.0.1] [--db FILE] [--no-open]',
138
- '',
139
- 'Options:',
140
- ` --port HTTP port to bind (default: ${DEFAULT_UI_PORT})`,
141
- ` --host Hostname to bind (default: ${DEFAULT_UI_HOST})`,
142
- ' --db Override the Codex SQLite database path for the UI',
143
- ' --no-open Do not open the browser automatically',
144
- ' --help,-h Show this help text',
145
- '',
146
- 'Stop the UI with Ctrl+C.',
147
- ].join('\n');
148
- };
149
-
150
- const toPublicFilePath = (clientDir: string, pathname: string) => {
151
- const normalizedPath = pathname === '/' ? '' : pathname.replace(/^\/+/u, '');
152
- const resolved = path.resolve(clientDir, normalizedPath);
153
- const relative = path.relative(clientDir, resolved);
154
-
155
- if (relative.startsWith('..') || path.isAbsolute(relative)) {
156
- return null;
157
- }
158
-
159
- return resolved;
160
- };
161
-
162
- export const getUiStaticResponse = async (clientDir: string, pathname: string): Promise<Response | null> => {
163
- if (pathname === '/') {
164
- return null;
165
- }
166
-
167
- const exportFilePath = resolveUiExportFilePathFromRequestPath(pathname);
168
- if (exportFilePath) {
169
- try {
170
- await access(exportFilePath, constants.R_OK);
171
- } catch {
172
- return new Response('Not Found', { status: 404 });
173
- }
174
-
175
- return new Response(Bun.file(exportFilePath), {
176
- headers: {
177
- 'cache-control': 'no-store',
178
- 'content-disposition': buildUiExportContentDisposition(exportFilePath),
179
- },
180
- });
181
- }
182
-
183
- const targetPath = toPublicFilePath(clientDir, pathname);
184
- if (!targetPath) {
185
- return new Response('Forbidden', { status: 403 });
186
- }
187
-
188
- const file = Bun.file(targetPath);
189
- if (!(await file.exists())) {
190
- return null;
191
- }
192
-
193
- return new Response(file);
194
- };
195
-
196
- const openBrowserIfRequested = async (url: string, openBrowser: boolean) => {
197
- if (!openBrowser) {
198
- return;
199
- }
200
-
201
- try {
202
- await openUrlNatively(url);
203
- } catch (error) {
204
- const message = error instanceof Error ? error.message : String(error);
205
- console.warn(`Could not open the browser automatically: ${message}`);
206
- }
207
- };
208
-
209
- const startUiServer = async (options: UiCliOptions) => {
210
- await ensureUiBuildExists();
211
- const { clientDir, serverEntryPath } = resolveUiDistPaths();
212
- const serverModule = (await import(serverEntryPath)) as {
213
- default: {
214
- fetch: (request: Request) => Promise<Response> | Response;
215
- };
216
- };
217
-
218
- if (options.dbPath) {
219
- process.env.SPIRACHA_CODEX_DB = options.dbPath;
220
- }
221
-
222
- for (let attempt = 0; attempt < MAX_PORT_ATTEMPTS; attempt += 1) {
223
- const port = options.port + attempt;
224
-
225
- try {
226
- const server = Bun.serve({
227
- fetch: async (request) => {
228
- const url = new URL(request.url);
229
- const staticResponse = await getUiStaticResponse(clientDir, url.pathname);
230
- if (staticResponse) {
231
- return staticResponse;
232
- }
233
-
234
- return serverModule.default.fetch(request);
235
- },
236
- hostname: options.host,
237
- idleTimeout: 30,
238
- port,
239
- });
240
-
241
- return {
242
- port,
243
- server,
244
- };
245
- } catch (error) {
246
- if (
247
- attempt < MAX_PORT_ATTEMPTS - 1 &&
248
- error instanceof Error &&
249
- /address already in use|EADDRINUSE/i.test(error.message)
250
- ) {
251
- continue;
252
- }
253
-
254
- throw error;
255
- }
256
- }
257
-
258
- throw new Error(`Unable to bind the UI server after ${MAX_PORT_ATTEMPTS} port attempts.`);
259
- };
260
-
261
- export const runUiCli = async (argv = process.argv.slice(2)) => {
262
- try {
263
- if (argv.includes('--help') || argv.includes('-h')) {
264
- console.log(getUiHelpText());
265
- return;
266
- }
267
- const options = parseUiCliArgs(argv);
268
- const { port, server } = await startUiServer(options);
269
- const url = `http://${options.host}:${port}`;
270
-
271
- console.log(`Spiracha UI running at ${url}`);
272
- console.log('Press Ctrl+C to stop.');
273
-
274
- await openBrowserIfRequested(url, options.openBrowser);
275
-
276
- let shuttingDown = false;
277
- const shutdown = () => {
278
- if (shuttingDown) {
279
- return;
280
- }
281
- shuttingDown = true;
282
- server.stop(true);
283
- console.log('Spiracha UI stopped.');
284
- process.exit(0);
285
- };
286
-
287
- process.once('SIGINT', shutdown);
288
- process.once('SIGTERM', shutdown);
289
-
290
- await new Promise<void>(() => {});
291
- } catch (error) {
292
- if (error instanceof CliUsageError) {
293
- console.error(error.message);
294
- console.error('');
295
- console.error(getUiHelpText());
296
- process.exit(1);
297
- }
298
-
299
- if (error instanceof Error) {
300
- console.error(error.message);
301
- process.exit(1);
302
- }
303
-
304
- throw error;
305
- }
306
- };
307
-
308
- if (import.meta.main) {
309
- await runUiCli();
310
- }
File without changes
File without changes
File without changes