spiracha 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/AGENTS.md +116 -164
  2. package/README.md +92 -237
  3. package/apps/ui/AGENTS.md +36 -7
  4. package/apps/ui/README.md +79 -6
  5. package/apps/ui/components.json +21 -0
  6. package/apps/ui/package.json +65 -0
  7. package/apps/ui/{dist/client → public}/icon.svg +2 -1
  8. package/apps/ui/src/components/antigravity-conversations-table.tsx +206 -0
  9. package/apps/ui/src/components/antigravity-keychain-panel.tsx +76 -0
  10. package/apps/ui/src/components/antigravity-workspaces-table.tsx +63 -0
  11. package/apps/ui/src/components/app-shell.tsx +124 -0
  12. package/apps/ui/src/components/breadcrumbs.tsx +53 -0
  13. package/apps/ui/src/components/claude-code-sessions-table.tsx +114 -0
  14. package/apps/ui/src/components/claude-code-workspaces-table.tsx +55 -0
  15. package/apps/ui/src/components/cursor-threads-table.tsx +189 -0
  16. package/apps/ui/src/components/cursor-workspaces-table.tsx +140 -0
  17. package/apps/ui/src/components/data-table.tsx +241 -0
  18. package/apps/ui/src/components/delete-confirm-dialog.tsx +88 -0
  19. package/apps/ui/src/components/export-dialog.tsx +184 -0
  20. package/apps/ui/src/components/json-panel.tsx +17 -0
  21. package/apps/ui/src/components/kiro-sessions-table.tsx +112 -0
  22. package/apps/ui/src/components/kiro-workspaces-table.tsx +53 -0
  23. package/apps/ui/src/components/list-search-input.tsx +18 -0
  24. package/apps/ui/src/components/loading-panel.tsx +23 -0
  25. package/apps/ui/src/components/metadata-section.tsx +31 -0
  26. package/apps/ui/src/components/metric-card.tsx +19 -0
  27. package/apps/ui/src/components/opencode-sessions-table.tsx +128 -0
  28. package/apps/ui/src/components/opencode-workspaces-table.tsx +57 -0
  29. package/apps/ui/src/components/page-header.tsx +33 -0
  30. package/apps/ui/src/components/projects-loading-state.tsx +74 -0
  31. package/apps/ui/src/components/projects-table.tsx +108 -0
  32. package/apps/ui/src/components/qoder-sessions-table.tsx +112 -0
  33. package/apps/ui/src/components/qoder-workspaces-table.tsx +53 -0
  34. package/apps/ui/src/components/recent-threads-list.tsx +52 -0
  35. package/apps/ui/src/components/reload-error-panel.tsx +20 -0
  36. package/apps/ui/src/components/text-document-panel.tsx +19 -0
  37. package/apps/ui/src/components/theme-toggle.tsx +48 -0
  38. package/apps/ui/src/components/threads-table.tsx +202 -0
  39. package/apps/ui/src/components/transcript-view.tsx +552 -0
  40. package/apps/ui/src/components/ui/alert-dialog.tsx +160 -0
  41. package/apps/ui/src/components/ui/badge.tsx +45 -0
  42. package/apps/ui/src/components/ui/button.tsx +62 -0
  43. package/apps/ui/src/components/ui/checkbox.tsx +29 -0
  44. package/apps/ui/src/components/ui/dialog.tsx +137 -0
  45. package/apps/ui/src/components/ui/dropdown-menu.tsx +217 -0
  46. package/apps/ui/src/components/ui/input.tsx +21 -0
  47. package/apps/ui/src/components/ui/scroll-area.tsx +46 -0
  48. package/apps/ui/src/components/ui/select.tsx +163 -0
  49. package/apps/ui/src/components/ui/separator.tsx +28 -0
  50. package/apps/ui/src/components/ui/sheet.tsx +107 -0
  51. package/apps/ui/src/components/ui/skeleton.tsx +7 -0
  52. package/apps/ui/src/components/ui/table.tsx +76 -0
  53. package/apps/ui/src/components/ui/tabs.tsx +71 -0
  54. package/apps/ui/src/components/ui/tooltip.tsx +44 -0
  55. package/apps/ui/src/integrations/tanstack-query/devtools.tsx +6 -0
  56. package/apps/ui/src/integrations/tanstack-query/root-provider.tsx +10 -0
  57. package/apps/ui/src/lib/antigravity-conversation-state.ts +28 -0
  58. package/apps/ui/src/lib/antigravity-queries.ts +33 -0
  59. package/apps/ui/src/lib/antigravity-server.ts +128 -0
  60. package/apps/ui/src/lib/antigravity-transcript-events.ts +335 -0
  61. package/apps/ui/src/lib/claude-code-queries.ts +26 -0
  62. package/apps/ui/src/lib/claude-code-server.ts +75 -0
  63. package/apps/ui/src/lib/claude-code-transcript-events.ts +154 -0
  64. package/apps/ui/src/lib/codex-queries.ts +66 -0
  65. package/apps/ui/src/lib/codex-server.ts +209 -0
  66. package/apps/ui/src/lib/cursor-queries.ts +37 -0
  67. package/apps/ui/src/lib/cursor-server.ts +272 -0
  68. package/apps/ui/src/lib/cursor-transcript-events.ts +229 -0
  69. package/apps/ui/src/lib/download.ts +166 -0
  70. package/apps/ui/src/lib/formatters.ts +149 -0
  71. package/apps/ui/src/lib/kiro-queries.ts +22 -0
  72. package/apps/ui/src/lib/kiro-server.ts +73 -0
  73. package/apps/ui/src/lib/kiro-transcript-events.ts +113 -0
  74. package/apps/ui/src/lib/opencode-queries.ts +37 -0
  75. package/apps/ui/src/lib/opencode-server.ts +73 -0
  76. package/apps/ui/src/lib/opencode-transcript-events.ts +221 -0
  77. package/apps/ui/src/lib/package-metadata.ts +16 -0
  78. package/apps/ui/src/lib/path-utils.ts +13 -0
  79. package/apps/ui/src/lib/qoder-queries.ts +22 -0
  80. package/apps/ui/src/lib/qoder-server.ts +79 -0
  81. package/apps/ui/src/lib/qoder-transcript-events.ts +139 -0
  82. package/apps/ui/src/lib/route-search.ts +68 -0
  83. package/apps/ui/src/lib/settings-store.tsx +59 -0
  84. package/apps/ui/src/lib/source-session-export-server.ts +56 -0
  85. package/apps/ui/src/lib/text-filter.ts +22 -0
  86. package/apps/ui/src/lib/thread-id.ts +3 -0
  87. package/apps/ui/src/lib/thread-transcript-stats.ts +57 -0
  88. package/apps/ui/src/lib/utils.ts +7 -0
  89. package/apps/ui/src/routeTree.gen.ts +730 -0
  90. package/apps/ui/src/router.tsx +20 -0
  91. package/apps/ui/src/routes/$threadId.tsx +22 -0
  92. package/apps/ui/src/routes/__root.tsx +127 -0
  93. package/apps/ui/src/routes/analytics.tsx +143 -0
  94. package/apps/ui/src/routes/antigravity-conversations.$conversationId.tsx +438 -0
  95. package/apps/ui/src/routes/antigravity.$workspaceKey.tsx +127 -0
  96. package/apps/ui/src/routes/antigravity.index.tsx +51 -0
  97. package/apps/ui/src/routes/api.v1.conversation-query.ts +12 -0
  98. package/apps/ui/src/routes/api.v1.conversations.$source.$id.export.ts +12 -0
  99. package/apps/ui/src/routes/api.v1.conversations.$source.$id.ts +12 -0
  100. package/apps/ui/src/routes/api.v1.conversations.ts +12 -0
  101. package/apps/ui/src/routes/api.v1.resolve.ts +12 -0
  102. package/apps/ui/src/routes/api.v1.sources.ts +12 -0
  103. package/apps/ui/src/routes/claude-code-sessions.$sessionId.tsx +342 -0
  104. package/apps/ui/src/routes/claude-code.$workspaceKey.tsx +135 -0
  105. package/apps/ui/src/routes/claude-code.index.tsx +48 -0
  106. package/apps/ui/src/routes/codex.$project.tsx +390 -0
  107. package/apps/ui/src/routes/codex.index.tsx +116 -0
  108. package/apps/ui/src/routes/cursor-threads.$composerId.tsx +435 -0
  109. package/apps/ui/src/routes/cursor.$workspaceKey.tsx +416 -0
  110. package/apps/ui/src/routes/cursor.index.tsx +120 -0
  111. package/apps/ui/src/routes/index.tsx +124 -0
  112. package/apps/ui/src/routes/kiro-sessions.$sessionId.tsx +345 -0
  113. package/apps/ui/src/routes/kiro.$workspaceKey.tsx +136 -0
  114. package/apps/ui/src/routes/kiro.index.tsx +48 -0
  115. package/apps/ui/src/routes/opencode-sessions.$sessionId.tsx +334 -0
  116. package/apps/ui/src/routes/opencode.$workspaceKey.tsx +135 -0
  117. package/apps/ui/src/routes/opencode.index.tsx +48 -0
  118. package/apps/ui/src/routes/qoder-sessions.$sessionId.tsx +341 -0
  119. package/apps/ui/src/routes/qoder.$workspaceKey.tsx +139 -0
  120. package/apps/ui/src/routes/qoder.index.tsx +48 -0
  121. package/apps/ui/src/routes/settings.tsx +91 -0
  122. package/apps/ui/src/routes/threads.$threadId.tsx +619 -0
  123. package/apps/ui/src/styles.css +122 -0
  124. package/apps/ui/tsconfig.json +29 -0
  125. package/apps/ui/vite.config.ts +84 -0
  126. package/bin/spiracha.ts +32 -0
  127. package/package.json +50 -60
  128. package/src/client.ts +290 -0
  129. package/src/lib/antigravity-db.ts +213 -19
  130. package/src/lib/antigravity-exporter-types.ts +1 -0
  131. package/src/lib/claude-code-db.ts +655 -0
  132. package/src/lib/claude-code-exporter-types.ts +110 -0
  133. package/src/lib/claude-code-transcript-phase.ts +25 -0
  134. package/src/lib/claude-code-transcript.ts +180 -0
  135. package/src/lib/codex-analytics.ts +1 -1
  136. package/src/lib/codex-browser-db.ts +856 -61
  137. package/src/lib/codex-browser-export.ts +24 -16
  138. package/src/lib/codex-browser-types.ts +1 -1
  139. package/src/lib/codex-thread-cache.ts +17 -1
  140. package/src/lib/{codex-exporter-types.ts → codex-thread-types.ts} +2 -30
  141. package/src/lib/{codex-exporter-transcript.ts → codex-transcript-renderer.ts} +64 -28
  142. package/src/lib/concurrency.ts +25 -0
  143. package/src/lib/conversation-api.ts +792 -0
  144. package/src/lib/conversation-data/adapter-helpers.ts +110 -0
  145. package/src/lib/conversation-data/antigravity-adapter.ts +148 -0
  146. package/src/lib/conversation-data/claude-code-adapter.ts +175 -0
  147. package/src/lib/conversation-data/codex-adapter.ts +245 -0
  148. package/src/lib/conversation-data/cursor-adapter.ts +171 -0
  149. package/src/lib/conversation-data/index.ts +311 -0
  150. package/src/lib/conversation-data/kiro-adapter.ts +140 -0
  151. package/src/lib/conversation-data/message-selector.ts +37 -0
  152. package/src/lib/conversation-data/opencode-adapter.ts +180 -0
  153. package/src/lib/conversation-data/path-match.ts +79 -0
  154. package/src/lib/conversation-data/qoder-adapter.ts +230 -0
  155. package/src/lib/conversation-data/types.ts +116 -0
  156. package/src/lib/cursor-db.ts +67 -21
  157. package/src/lib/cursor-exporter-types.ts +0 -19
  158. package/src/lib/kiro-db.ts +949 -0
  159. package/src/lib/kiro-exporter-types.ts +100 -0
  160. package/src/lib/kiro-transcript-phase.ts +41 -0
  161. package/src/lib/kiro-transcript.ts +115 -0
  162. package/src/lib/opencode-db.ts +610 -0
  163. package/src/lib/opencode-exporter-types.ts +129 -0
  164. package/src/lib/opencode-think-tags.ts +126 -0
  165. package/src/lib/opencode-transcript-phase.ts +50 -0
  166. package/src/lib/opencode-transcript.ts +194 -0
  167. package/src/lib/qoder-acp-client.ts +268 -0
  168. package/src/lib/qoder-db.ts +1601 -0
  169. package/src/lib/qoder-exporter-types.ts +114 -0
  170. package/src/lib/qoder-transcript-phase.ts +41 -0
  171. package/src/lib/qoder-transcript.ts +112 -0
  172. package/src/lib/shared.ts +25 -0
  173. package/src/lib/ui-export-archive.ts +61 -0
  174. package/apps/ui/dist/client/assets/_threadId-CAIeH5mq.js +0 -1
  175. package/apps/ui/dist/client/assets/analytics-DK2jdvmI.js +0 -1
  176. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-DmD0sN8X.js +0 -7
  177. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-KAcXtNxI.js +0 -1
  178. package/apps/ui/dist/client/assets/antigravity-keychain-panel-BRHVjFAM.js +0 -1
  179. package/apps/ui/dist/client/assets/antigravity._workspaceKey-ByitGWki.js +0 -1
  180. package/apps/ui/dist/client/assets/antigravity._workspaceKey-CGV7amas.js +0 -1
  181. package/apps/ui/dist/client/assets/antigravity.index-DEEkjlZa.js +0 -1
  182. package/apps/ui/dist/client/assets/antigravity.index-DgW25FEV.js +0 -1
  183. package/apps/ui/dist/client/assets/badge-DfWvPfKF.js +0 -1
  184. package/apps/ui/dist/client/assets/checkbox-CdHitXWQ.js +0 -1
  185. package/apps/ui/dist/client/assets/createServerFn-CgRRVpBH.js +0 -3
  186. package/apps/ui/dist/client/assets/cursor-threads._composerId-CmBFclK8.js +0 -1
  187. package/apps/ui/dist/client/assets/cursor-threads._composerId-Ti2gTm63.js +0 -1
  188. package/apps/ui/dist/client/assets/cursor._workspaceKey-CaAZjGmm.js +0 -1
  189. package/apps/ui/dist/client/assets/cursor._workspaceKey-DzD_c6j9.js +0 -1
  190. package/apps/ui/dist/client/assets/cursor.index-CrnMwDCi.js +0 -1
  191. package/apps/ui/dist/client/assets/cursor.index-PkCFVcl4.js +0 -2
  192. package/apps/ui/dist/client/assets/data-table-Br78_dk3.js +0 -4
  193. package/apps/ui/dist/client/assets/delete-confirm-dialog-BHRmyLHr.js +0 -11
  194. package/apps/ui/dist/client/assets/dist-B9pyYCVU.js +0 -1
  195. package/apps/ui/dist/client/assets/dist-BhZOxAPP.js +0 -1
  196. package/apps/ui/dist/client/assets/dist-DvMS2965.js +0 -1
  197. package/apps/ui/dist/client/assets/download-Bf0QJKD3.js +0 -1
  198. package/apps/ui/dist/client/assets/dropdown-menu-Dy5cLzTy.js +0 -1
  199. package/apps/ui/dist/client/assets/es2015-BkCWttyM.js +0 -41
  200. package/apps/ui/dist/client/assets/export-dialog-C86SYHJn.js +0 -1
  201. package/apps/ui/dist/client/assets/formatters-BM9kB7ed.js +0 -1
  202. package/apps/ui/dist/client/assets/index-CPvAP-jk.js +0 -149
  203. package/apps/ui/dist/client/assets/jsx-runtime-DGeXAQPT.js +0 -1
  204. package/apps/ui/dist/client/assets/metric-card-Dplm0ZiM.js +0 -1
  205. package/apps/ui/dist/client/assets/page-header-Cwa3p6Tl.js +0 -1
  206. package/apps/ui/dist/client/assets/projects._project-Ckf6muWZ.js +0 -1
  207. package/apps/ui/dist/client/assets/projects._project-DSDwH4NF.js +0 -1
  208. package/apps/ui/dist/client/assets/projects.index-DEfhWqa8.js +0 -1
  209. package/apps/ui/dist/client/assets/projects.index-V5ibNZII.js +0 -3
  210. package/apps/ui/dist/client/assets/react-dom-DL96Jor4.js +0 -1
  211. package/apps/ui/dist/client/assets/refresh-ccw-BgKjOiA6.js +0 -1
  212. package/apps/ui/dist/client/assets/reload-error-panel-AHqu0akK.js +0 -1
  213. package/apps/ui/dist/client/assets/routes-Df2tgpyd.js +0 -1
  214. package/apps/ui/dist/client/assets/scroll-text-fM0sMOB3.js +0 -1
  215. package/apps/ui/dist/client/assets/select-Bf2GwfPR.js +0 -1
  216. package/apps/ui/dist/client/assets/settings-5VQIzME0.js +0 -1
  217. package/apps/ui/dist/client/assets/sqlite-error-B6uZjUe8.js +0 -1
  218. package/apps/ui/dist/client/assets/styles-BhRkXgwB.css +0 -1
  219. package/apps/ui/dist/client/assets/tabs-OO4VU5KR.js +0 -7
  220. package/apps/ui/dist/client/assets/text-filter-DVAZySUS.js +0 -2
  221. package/apps/ui/dist/client/assets/threads._threadId-BB9tTsV4.js +0 -1
  222. package/apps/ui/dist/client/assets/threads._threadId-BgDhFj2I.js +0 -1
  223. package/apps/ui/dist/client/assets/useMutation-CC_B7uy5.js +0 -1
  224. package/apps/ui/dist/client/assets/useQuery-C5By6WKU.js +0 -1
  225. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CRW2kqj0.js +0 -232
  226. package/apps/ui/dist/server/assets/_threadId-B6SrBR9E.js +0 -6
  227. package/apps/ui/dist/server/assets/analytics-CYP_LT5Y.js +0 -16
  228. package/apps/ui/dist/server/assets/analytics-CtpOMVMO.js +0 -146
  229. package/apps/ui/dist/server/assets/antigravity-conversation-state-HgzS302O.js +0 -16
  230. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-BtexWY-K.js +0 -613
  231. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-D426O-64.js +0 -11
  232. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-zMrR6v6R.js +0 -20
  233. package/apps/ui/dist/server/assets/antigravity-db-Bh8_U9uw.js +0 -580
  234. package/apps/ui/dist/server/assets/antigravity-keychain-DOiuHDwK.js +0 -126
  235. package/apps/ui/dist/server/assets/antigravity-keychain-panel-CC7FLmAK.js +0 -55
  236. package/apps/ui/dist/server/assets/antigravity-queries-CGrJO9Vr.js +0 -37
  237. package/apps/ui/dist/server/assets/antigravity-server-CHRjVFqN.js +0 -114
  238. package/apps/ui/dist/server/assets/antigravity._workspaceKey-3m_MzNFA.js +0 -11
  239. package/apps/ui/dist/server/assets/antigravity._workspaceKey-B0QeYUOh.js +0 -28
  240. package/apps/ui/dist/server/assets/antigravity._workspaceKey-C3kP-qyN.js +0 -210
  241. package/apps/ui/dist/server/assets/antigravity.index-CPCYkqCi.js +0 -104
  242. package/apps/ui/dist/server/assets/antigravity.index-DudTB3Tq.js +0 -11
  243. package/apps/ui/dist/server/assets/badge-EvdhKK_Z.js +0 -26
  244. package/apps/ui/dist/server/assets/button-CmTDnzOn.js +0 -46
  245. package/apps/ui/dist/server/assets/checkbox-C0hovF41.js +0 -19
  246. package/apps/ui/dist/server/assets/codex-queries-CtgeZ7VL.js +0 -99
  247. package/apps/ui/dist/server/assets/codex-server-CNXSJuc2.js +0 -2004
  248. package/apps/ui/dist/server/assets/concurrency-VXtYvlGh.js +0 -18
  249. package/apps/ui/dist/server/assets/createServerRpc-CF_DEwnm.js +0 -12
  250. package/apps/ui/dist/server/assets/createSsrRpc-C754NPki.js +0 -16
  251. package/apps/ui/dist/server/assets/cursor-db-cYZEU3WQ.js +0 -830
  252. package/apps/ui/dist/server/assets/cursor-exporter-types-CI3goo-c.js +0 -34
  253. package/apps/ui/dist/server/assets/cursor-queries-NCIM0Nat.js +0 -67
  254. package/apps/ui/dist/server/assets/cursor-recovery-nq-kR62j.js +0 -361
  255. package/apps/ui/dist/server/assets/cursor-server-C3q7hrp-.js +0 -213
  256. package/apps/ui/dist/server/assets/cursor-threads._composerId-BB0Y_Mao.js +0 -11
  257. package/apps/ui/dist/server/assets/cursor-threads._composerId-BPJFWfJj.js +0 -18
  258. package/apps/ui/dist/server/assets/cursor-threads._composerId-BkMMTQ3v.js +0 -582
  259. package/apps/ui/dist/server/assets/cursor-transcript-2iL3KFSK.js +0 -125
  260. package/apps/ui/dist/server/assets/cursor._workspaceKey-C5PdTaKB.js +0 -28
  261. package/apps/ui/dist/server/assets/cursor._workspaceKey-Ckj7apKI.js +0 -401
  262. package/apps/ui/dist/server/assets/cursor._workspaceKey-nmg3YIOQ.js +0 -11
  263. package/apps/ui/dist/server/assets/cursor.index-CcsX7DG0.js +0 -11
  264. package/apps/ui/dist/server/assets/cursor.index-DkWT-mxw.js +0 -189
  265. package/apps/ui/dist/server/assets/data-table-Cdct823O.js +0 -189
  266. package/apps/ui/dist/server/assets/delete-confirm-dialog-BcBNCxWB.js +0 -144
  267. package/apps/ui/dist/server/assets/download-DMmiy1xf.js +0 -92
  268. package/apps/ui/dist/server/assets/dropdown-menu-Dy_9t6TN.js +0 -36
  269. package/apps/ui/dist/server/assets/empty-plugin-adapters-B3lHh1La.js +0 -5
  270. package/apps/ui/dist/server/assets/export-dialog-BItjWgkZ.js +0 -240
  271. package/apps/ui/dist/server/assets/formatters-FJaGZgJk.js +0 -91
  272. package/apps/ui/dist/server/assets/loading-panel-BGFnWseS.js +0 -27
  273. package/apps/ui/dist/server/assets/metric-card-ByEeLu0r.js +0 -23
  274. package/apps/ui/dist/server/assets/model-label-B1NWGc65.js +0 -13
  275. package/apps/ui/dist/server/assets/page-header-VNSaM3xd.js +0 -29
  276. package/apps/ui/dist/server/assets/path-transforms-DL2IwtYd.js +0 -31
  277. package/apps/ui/dist/server/assets/projects._project-Bpbc3C-L.js +0 -20
  278. package/apps/ui/dist/server/assets/projects._project-Bshqk7JA.js +0 -12
  279. package/apps/ui/dist/server/assets/projects._project-CvZho6EQ.js +0 -395
  280. package/apps/ui/dist/server/assets/projects.index-BLXOx5eL.js +0 -12
  281. package/apps/ui/dist/server/assets/projects.index-BkLiF2FF.js +0 -182
  282. package/apps/ui/dist/server/assets/projects.index-DesYXwfi.js +0 -14
  283. package/apps/ui/dist/server/assets/reload-error-panel-BJMxY3U1.js +0 -25
  284. package/apps/ui/dist/server/assets/route-search-ts4W9MJ9.js +0 -38
  285. package/apps/ui/dist/server/assets/router-6m-ihwqA.js +0 -410
  286. package/apps/ui/dist/server/assets/routes-Bsact1uB.js +0 -184
  287. package/apps/ui/dist/server/assets/routes-BzkJgq4W.js +0 -34
  288. package/apps/ui/dist/server/assets/select-GW76p-ld.js +0 -76
  289. package/apps/ui/dist/server/assets/settings-OayxIYQQ.js +0 -100
  290. package/apps/ui/dist/server/assets/settings-store-DpEJEQ7M.js +0 -52
  291. package/apps/ui/dist/server/assets/shared-CPRNYIql.js +0 -134
  292. package/apps/ui/dist/server/assets/sqlite-error-LZDrnxdd.js +0 -13
  293. package/apps/ui/dist/server/assets/start-CI_0bSiY.js +0 -4
  294. package/apps/ui/dist/server/assets/tabs-CGA13IZM.js +0 -502
  295. package/apps/ui/dist/server/assets/text-filter-CGKxMCKt.js +0 -36
  296. package/apps/ui/dist/server/assets/threads._threadId-BSSK4nkI.js +0 -26
  297. package/apps/ui/dist/server/assets/threads._threadId-Bs0yuqO9.js +0 -18
  298. package/apps/ui/dist/server/assets/threads._threadId-D2GYkVn6.js +0 -639
  299. package/apps/ui/dist/server/assets/ui-export-files-BHLX9bhN.js +0 -83
  300. package/apps/ui/dist/server/assets/utils-C_uf36nf.js +0 -8
  301. package/apps/ui/dist/server/server.js +0 -5847
  302. package/bin/codex-chats-claude.js +0 -5
  303. package/bin/codex-chats.js +0 -5
  304. package/bin/spiracha.js +0 -5
  305. package/src/export-chats.ts +0 -120
  306. package/src/export-claude.ts +0 -36
  307. package/src/export-cursor.ts +0 -244
  308. package/src/lib/claude-exporter.ts +0 -864
  309. package/src/lib/codex-exporter-cli.ts +0 -277
  310. package/src/lib/codex-exporter-db.ts +0 -319
  311. package/src/lib/codex-exporter.ts +0 -115
  312. package/src/lib/cursor-exporter.ts +0 -266
  313. package/src/lib/interactive-cli.ts +0 -433
  314. package/src/lib/native-open.ts +0 -54
  315. package/src/mcp-server.ts +0 -137
  316. package/src/spiracha.ts +0 -116
  317. package/src/ui-cli.ts +0 -310
  318. /package/apps/ui/{dist/client → public}/manifest.json +0 -0
  319. /package/apps/ui/{dist/client → public}/robots.txt +0 -0
@@ -2,8 +2,8 @@ import { randomUUID } from 'node:crypto';
2
2
  import { mkdir, mkdtemp, rm, stat } from 'node:fs/promises';
3
3
  import path from 'node:path';
4
4
  import { getThreadBrowseData } from './codex-browser-db';
5
- import { convertSessionFile, writeSessionFileExport } from './codex-exporter-transcript';
6
- import type { CodexCliOptions } from './codex-exporter-types';
5
+ import type { CodexTranscriptRenderOptions } from './codex-thread-types';
6
+ import { renderCodexSessionFile, writeCodexSessionFileExport } from './codex-transcript-renderer';
7
7
  import { applyPathTransforms, type PathDisplaySettings } from './path-transforms';
8
8
  import { type ExportFormat, getPortablePathBasename } from './shared';
9
9
  import { getExportMimeType, sanitizeExportFileName, zipExportDirectory, zipExportFile } from './ui-export-archive';
@@ -89,19 +89,12 @@ type RolloutSnapshot = {
89
89
  sizeBytes: number;
90
90
  };
91
91
 
92
- const toDownloadOptions = (input: RenderCodexThreadDownloadInput): CodexCliOptions => {
92
+ const toDownloadOptions = (input: RenderCodexThreadDownloadInput): CodexTranscriptRenderOptions => {
93
93
  return {
94
- cwdFilter: null,
95
- dbPath: input.dbPath,
96
- flat: false,
97
94
  includeCommentary: input.includeCommentary,
98
95
  includeMetadata: input.includeMetadata,
99
96
  includeTools: input.includeTools,
100
- inputDir: '',
101
- outputDir: '',
102
97
  outputFormat: input.outputFormat,
103
- projectFilter: null,
104
- threadIds: [input.threadId],
105
98
  };
106
99
  };
107
100
 
@@ -130,6 +123,22 @@ const getRolloutSnapshot = async (rolloutPath: string): Promise<RolloutSnapshot>
130
123
  };
131
124
  };
132
125
 
126
+ const isMissingFileError = (error: unknown) => {
127
+ return error instanceof Error && 'code' in error && error.code === 'ENOENT';
128
+ };
129
+
130
+ const getExistingRolloutSnapshot = async (threadId: string, rolloutPath: string): Promise<RolloutSnapshot> => {
131
+ try {
132
+ return await getRolloutSnapshot(rolloutPath);
133
+ } catch (error) {
134
+ if (isMissingFileError(error)) {
135
+ throw new Error(`Thread ${threadId} rollout file is missing: ${rolloutPath}`, { cause: error });
136
+ }
137
+
138
+ throw error;
139
+ }
140
+ };
141
+
133
142
  const logExportEvent = (level: 'error' | 'info' | 'warn', event: string, details: Record<string, unknown>) => {
134
143
  console[level](`[spiracha:export] ${event}`, details);
135
144
  };
@@ -179,7 +188,7 @@ export const renderCodexThreadDownload = async (
179
188
  projectPath: browseData.thread.cwd,
180
189
  })
181
190
  : text;
182
- const rolloutSnapshotBefore = await getRolloutSnapshot(browseData.thread.rollout_path);
191
+ const rolloutSnapshotBefore = await getExistingRolloutSnapshot(input.threadId, browseData.thread.rollout_path);
183
192
 
184
193
  logExportEvent('info', 'single_start', {
185
194
  fileName,
@@ -198,7 +207,7 @@ export const renderCodexThreadDownload = async (
198
207
  const savedPath = path.join(workspaceDir, `${exportBaseName}.${extension}`);
199
208
  const zipPath = buildUniqueArchivePath(exportDir, exportBaseName);
200
209
  try {
201
- const saved = await writeSessionFileExport(
210
+ const saved = await writeCodexSessionFileExport(
202
211
  {
203
212
  fallbackReason: null,
204
213
  outputRelativePath: fileName,
@@ -241,7 +250,7 @@ export const renderCodexThreadDownload = async (
241
250
  };
242
251
  }
243
252
 
244
- const content = await convertSessionFile(
253
+ const content = await renderCodexSessionFile(
245
254
  {
246
255
  fallbackReason: null,
247
256
  outputRelativePath: fileName,
@@ -307,7 +316,7 @@ export const renderCodexThreadsDownload = async (
307
316
 
308
317
  try {
309
318
  for (const entry of browseEntries) {
310
- const rolloutSnapshotBefore = await getRolloutSnapshot(entry.thread.rollout_path);
319
+ const rolloutSnapshotBefore = await getExistingRolloutSnapshot(entry.thread.id, entry.thread.rollout_path);
311
320
  const singleBaseName = buildExportBaseName(entry.thread);
312
321
  const uniqueBaseName = buildUniqueBatchEntryBaseName(
313
322
  singleBaseName,
@@ -333,7 +342,7 @@ export const renderCodexThreadsDownload = async (
333
342
  });
334
343
  }
335
344
 
336
- const saved = await writeSessionFileExport(
345
+ const saved = await writeCodexSessionFileExport(
337
346
  {
338
347
  fallbackReason: null,
339
348
  outputRelativePath: relativeFileName,
@@ -346,7 +355,6 @@ export const renderCodexThreadsDownload = async (
346
355
  ...input,
347
356
  threadId: entry.thread.id,
348
357
  }),
349
- threadIds: [entry.thread.id],
350
358
  },
351
359
  savedPath,
352
360
  transform,
@@ -1,4 +1,4 @@
1
- import type { SessionMeta, ThreadRelations, ThreadRow } from './codex-exporter-types';
1
+ import type { SessionMeta, ThreadRelations, ThreadRow } from './codex-thread-types';
2
2
  import type { JsonValue } from './shared';
3
3
 
4
4
  export type DynamicToolDefinition = {
@@ -7,6 +7,10 @@ import { getFileFingerprint, hashCacheKeyParts, withCachedJson } from './ui-cach
7
7
  export const LARGE_THREAD_SIZE_BYTES = 100 * 1024 * 1024;
8
8
  export const LARGE_THREAD_PREVIEW_EVENT_LIMIT = 200;
9
9
 
10
+ const isMissingFileError = (error: unknown) => {
11
+ return error instanceof Error && 'code' in error && error.code === 'ENOENT';
12
+ };
13
+
10
14
  export const getCachedParsedCodexTranscript = async (sessionFile: string): Promise<ParsedCodexTranscript> => {
11
15
  const fingerprint = await getFileFingerprint(sessionFile);
12
16
  const key = `thread-${hashCacheKeyParts(path.basename(sessionFile), fingerprint)}`;
@@ -23,7 +27,19 @@ export const getThreadRolloutLoadState = async (
23
27
  sessionFile: string,
24
28
  largeTranscriptThresholdBytes = LARGE_THREAD_SIZE_BYTES,
25
29
  ) => {
26
- const metadata = await stat(sessionFile);
30
+ let metadata: Awaited<ReturnType<typeof stat>>;
31
+ try {
32
+ metadata = await stat(sessionFile);
33
+ } catch (error) {
34
+ if (isMissingFileError(error)) {
35
+ return {
36
+ fileSizeBytes: null,
37
+ shouldDeferTranscriptLoad: false,
38
+ };
39
+ }
40
+
41
+ throw error;
42
+ }
27
43
 
28
44
  return {
29
45
  fileSizeBytes: metadata.size,
@@ -2,31 +2,11 @@ import os from 'node:os';
2
2
  import path from 'node:path';
3
3
  import type { ExportFormat, JsonValue } from './shared';
4
4
 
5
- export type CodexCliOptions = {
6
- dbPath: string;
7
- inputDir: string;
8
- outputDir: string;
9
- cwdFilter: string | null;
10
- projectFilter: string | null;
11
- threadIds: string[];
5
+ export type CodexTranscriptRenderOptions = {
12
6
  includeMetadata: boolean;
13
7
  includeCommentary: boolean;
14
8
  includeTools: boolean;
15
9
  outputFormat: ExportFormat;
16
- flat: boolean;
17
- };
18
-
19
- export type CodexExportedFile = {
20
- sourcePath: string;
21
- outputPath: string;
22
- threadId: string | null;
23
- };
24
-
25
- export type CodexExportRunResult = {
26
- outputDir: string;
27
- exportedCount: number;
28
- files: CodexExportedFile[];
29
- missingThreadIds: string[];
30
10
  };
31
11
 
32
12
  export type SessionMeta = {
@@ -98,7 +78,7 @@ export type ThreadRelations = {
98
78
  childEdges: SpawnEdgeRow[];
99
79
  };
100
80
 
101
- export type ExportTarget = {
81
+ export type CodexTranscriptExportTarget = {
102
82
  sessionFile: string;
103
83
  outputRelativePath: string;
104
84
  thread: ThreadRow | null;
@@ -106,13 +86,5 @@ export type ExportTarget = {
106
86
  fallbackReason: string | null;
107
87
  };
108
88
 
109
- export type ThreadData = {
110
- threadsById: Map<string, ThreadRow>;
111
- parentByChildId: Map<string, SpawnEdgeRow>;
112
- childEdgesByParentId: Map<string, SpawnEdgeRow[]>;
113
- };
114
-
115
89
  export const DEFAULT_CODEX_DIR = path.join(os.homedir(), '.codex');
116
90
  export const DEFAULT_DB_PATH = path.join(DEFAULT_CODEX_DIR, 'state_5.sqlite');
117
- export const DEFAULT_INPUT_DIR = path.join(DEFAULT_CODEX_DIR, 'sessions');
118
- export const DEFAULT_OUTPUT_DIR = path.join(process.cwd(), 'exports');
@@ -2,8 +2,14 @@ import { createReadStream } from 'node:fs';
2
2
  import { rm } from 'node:fs/promises';
3
3
  import path from 'node:path';
4
4
  import { finished } from 'node:stream/promises';
5
- import { matchesFilters, toCodexRelativePath } from './codex-exporter-db';
6
- import type { CodexCliOptions, ExportTarget, MessageRecord, SessionMeta, ToolRecord } from './codex-exporter-types';
5
+ import {
6
+ type CodexTranscriptExportTarget,
7
+ type CodexTranscriptRenderOptions,
8
+ DEFAULT_CODEX_DIR,
9
+ type MessageRecord,
10
+ type SessionMeta,
11
+ type ToolRecord,
12
+ } from './codex-thread-types';
7
13
  import {
8
14
  asObject,
9
15
  asString,
@@ -22,7 +28,10 @@ import {
22
28
  renderSection,
23
29
  } from './shared';
24
30
 
25
- export const convertSessionFile = async (target: ExportTarget, options: CodexCliOptions): Promise<string | null> => {
31
+ export const renderCodexSessionFile = async (
32
+ target: CodexTranscriptExportTarget,
33
+ options: CodexTranscriptRenderOptions,
34
+ ): Promise<string | null> => {
26
35
  let transcriptState: CodexTranscriptState;
27
36
 
28
37
  try {
@@ -32,10 +41,6 @@ export const convertSessionFile = async (target: ExportTarget, options: CodexCli
32
41
  throw new Error(`Failed to read Codex transcript ${target.sessionFile}: ${message}`);
33
42
  }
34
43
 
35
- if (!matchesFilters(target.thread?.cwd ?? transcriptState.sessionMeta.cwd ?? null, options)) {
36
- return null;
37
- }
38
-
39
44
  if (transcriptState.sections.length === 0) {
40
45
  return null;
41
46
  }
@@ -57,9 +62,9 @@ export const convertSessionFile = async (target: ExportTarget, options: CodexCli
57
62
 
58
63
  type TranscriptTextTransform = (text: string) => string;
59
64
 
60
- export const writeSessionFileExport = async (
61
- target: ExportTarget,
62
- options: CodexCliOptions,
65
+ export const writeCodexSessionFileExport = async (
66
+ target: CodexTranscriptExportTarget,
67
+ options: CodexTranscriptRenderOptions,
63
68
  outputPath: string,
64
69
  transform: TranscriptTextTransform = (text) => text,
65
70
  ): Promise<boolean> => {
@@ -87,7 +92,7 @@ export const writeSessionFileExport = async (
87
92
  await finalizeExportWriteStream(transcriptStream);
88
93
  transcriptStream = null;
89
94
 
90
- if (!matchesFilters(target.thread?.cwd ?? state.sessionMeta.cwd ?? null, options) || !wroteSection) {
95
+ if (!wroteSection) {
91
96
  return false;
92
97
  }
93
98
 
@@ -127,7 +132,7 @@ type CodexTranscriptState = {
127
132
 
128
133
  const collectCodexTranscript = async (
129
134
  sessionFile: string,
130
- options: CodexCliOptions,
135
+ options: CodexTranscriptRenderOptions,
131
136
  assistantModel: string | null = null,
132
137
  ): Promise<CodexTranscriptState> => {
133
138
  const state: CodexTranscriptState = {
@@ -147,7 +152,7 @@ const getSectionSeparator = () => '\n';
147
152
 
148
153
  const processCodexTranscriptRecord = (
149
154
  parsed: Record<string, JsonValue>,
150
- options: CodexCliOptions,
155
+ options: CodexTranscriptRenderOptions,
151
156
  state: CodexTranscriptState,
152
157
  ) => {
153
158
  captureSessionMeta(parsed, state.sessionMeta);
@@ -159,7 +164,7 @@ const processCodexTranscriptRecord = (
159
164
 
160
165
  const renderCodexTranscriptRecord = (
161
166
  parsed: Record<string, JsonValue>,
162
- options: CodexCliOptions,
167
+ options: CodexTranscriptRenderOptions,
163
168
  state: CodexTranscriptState,
164
169
  ) => {
165
170
  const message = extractMessageRecord(parsed);
@@ -179,16 +184,24 @@ const renderCodexTranscriptRecord = (
179
184
  return renderToolBlock(tool, options.outputFormat);
180
185
  };
181
186
 
182
- const processCodexMessageRecord = (message: MessageRecord, options: CodexCliOptions, state: CodexTranscriptState) => {
187
+ const processCodexMessageRecord = (
188
+ message: MessageRecord,
189
+ options: CodexTranscriptRenderOptions,
190
+ state: CodexTranscriptState,
191
+ ) => {
183
192
  return renderMessageBlock(message, options.outputFormat, state.assistantModel, options.includeCommentary);
184
193
  };
185
194
 
186
- const buildStreamExportPrefix = (target: ExportTarget, sessionMeta: SessionMeta, options: CodexCliOptions) => {
195
+ const buildStreamExportPrefix = (
196
+ target: CodexTranscriptExportTarget,
197
+ sessionMeta: SessionMeta,
198
+ options: CodexTranscriptRenderOptions,
199
+ ) => {
200
+ const title = getTitle(target, sessionMeta);
187
201
  if (!options.includeMetadata) {
188
- return '';
202
+ return `${renderDocumentTitle(title, options.outputFormat)}\n`;
189
203
  }
190
204
 
191
- const title = getTitle(target, sessionMeta);
192
205
  const parts = [
193
206
  renderDocumentTitle(title, options.outputFormat),
194
207
  '',
@@ -253,7 +266,7 @@ export const parseExecCommandArguments = (argumentsText?: string) => {
253
266
  }
254
267
  };
255
268
 
256
- const getTitle = (target: ExportTarget, sessionMeta: SessionMeta): string => {
269
+ const getTitle = (target: CodexTranscriptExportTarget, sessionMeta: SessionMeta): string => {
257
270
  if (target.thread?.title) {
258
271
  return cleanInlineTitle(target.thread.title);
259
272
  }
@@ -261,10 +274,21 @@ const getTitle = (target: ExportTarget, sessionMeta: SessionMeta): string => {
261
274
  return sessionMeta.id ?? path.basename(target.sessionFile, '.jsonl');
262
275
  };
263
276
 
277
+ const toCodexRelativePath = (targetPath: string): string => {
278
+ const codexRoot = path.resolve(DEFAULT_CODEX_DIR);
279
+ const normalized = path.resolve(targetPath);
280
+
281
+ if (normalized.startsWith(`${codexRoot}${path.sep}`)) {
282
+ return path.relative(codexRoot, normalized);
283
+ }
284
+
285
+ return normalized;
286
+ };
287
+
264
288
  const buildMetadataEntries = (
265
- target: ExportTarget,
289
+ target: CodexTranscriptExportTarget,
266
290
  sessionMeta: SessionMeta,
267
- options: CodexCliOptions,
291
+ options: CodexTranscriptRenderOptions,
268
292
  ): MetadataEntry[] => {
269
293
  return [
270
294
  ...buildCodexExportIdentityMetadata(target, sessionMeta),
@@ -275,7 +299,10 @@ const buildMetadataEntries = (
275
299
  ];
276
300
  };
277
301
 
278
- const buildCodexExportIdentityMetadata = (target: ExportTarget, sessionMeta: SessionMeta): MetadataEntry[] => {
302
+ const buildCodexExportIdentityMetadata = (
303
+ target: CodexTranscriptExportTarget,
304
+ sessionMeta: SessionMeta,
305
+ ): MetadataEntry[] => {
279
306
  const thread = target.thread;
280
307
 
281
308
  return [
@@ -289,7 +316,10 @@ const buildCodexExportIdentityMetadata = (target: ExportTarget, sessionMeta: Ses
289
316
  ];
290
317
  };
291
318
 
292
- const buildCodexExportPathMetadata = (target: ExportTarget, options: CodexCliOptions): MetadataEntry[] => {
319
+ const buildCodexExportPathMetadata = (
320
+ target: CodexTranscriptExportTarget,
321
+ options: CodexTranscriptRenderOptions,
322
+ ): MetadataEntry[] => {
293
323
  const relativeOutputPath = target.outputRelativePath;
294
324
 
295
325
  return [
@@ -306,7 +336,7 @@ const buildCodexExportPathMetadata = (target: ExportTarget, options: CodexCliOpt
306
336
  ];
307
337
  };
308
338
 
309
- const buildCodexRelationMetadata = (target: ExportTarget): MetadataEntry[] => {
339
+ const buildCodexRelationMetadata = (target: CodexTranscriptExportTarget): MetadataEntry[] => {
310
340
  const childThreadIds = target.relations.childEdges.map((edge) => edge.child_thread_id);
311
341
  const childEdges = target.relations.childEdges.map((edge) => ({
312
342
  child_thread_id: edge.child_thread_id,
@@ -320,14 +350,17 @@ const buildCodexRelationMetadata = (target: ExportTarget): MetadataEntry[] => {
320
350
  ];
321
351
  };
322
352
 
323
- const buildCodexThreadMetadata = (target: ExportTarget, sessionMeta: SessionMeta): MetadataEntry[] => {
353
+ const buildCodexThreadMetadata = (target: CodexTranscriptExportTarget, sessionMeta: SessionMeta): MetadataEntry[] => {
324
354
  return [
325
355
  ...buildCodexThreadTimingMetadata(target, sessionMeta),
326
356
  ...buildCodexThreadIdentityMetadata(target, sessionMeta),
327
357
  ];
328
358
  };
329
359
 
330
- const buildCodexThreadTimingMetadata = (target: ExportTarget, sessionMeta: SessionMeta): MetadataEntry[] => {
360
+ const buildCodexThreadTimingMetadata = (
361
+ target: CodexTranscriptExportTarget,
362
+ sessionMeta: SessionMeta,
363
+ ): MetadataEntry[] => {
331
364
  const thread = target.thread;
332
365
 
333
366
  return [
@@ -341,7 +374,10 @@ const buildCodexThreadTimingMetadata = (target: ExportTarget, sessionMeta: Sessi
341
374
  ];
342
375
  };
343
376
 
344
- const buildCodexThreadIdentityMetadata = (target: ExportTarget, sessionMeta: SessionMeta): MetadataEntry[] => {
377
+ const buildCodexThreadIdentityMetadata = (
378
+ target: CodexTranscriptExportTarget,
379
+ sessionMeta: SessionMeta,
380
+ ): MetadataEntry[] => {
345
381
  const thread = target.thread;
346
382
 
347
383
  return [
@@ -367,7 +403,7 @@ const buildCodexThreadIdentityMetadata = (target: ExportTarget, sessionMeta: Ses
367
403
  ];
368
404
  };
369
405
 
370
- const buildCodexAgentMetadata = (target: ExportTarget): MetadataEntry[] => {
406
+ const buildCodexAgentMetadata = (target: CodexTranscriptExportTarget): MetadataEntry[] => {
371
407
  const thread = target.thread;
372
408
 
373
409
  return [
@@ -0,0 +1,25 @@
1
+ export const mapWithConcurrency = async <T, TResult>(
2
+ values: T[],
3
+ limit: number,
4
+ mapper: (value: T, index: number) => Promise<TResult>,
5
+ ) => {
6
+ if (values.length === 0) {
7
+ return [];
8
+ }
9
+
10
+ const requestedLimit = Number.isFinite(limit) ? Math.floor(limit) : 1;
11
+ const workerLimit = Math.max(1, requestedLimit);
12
+ const results = new Array<TResult>(values.length);
13
+ let nextIndex = 0;
14
+
15
+ const worker = async () => {
16
+ while (nextIndex < values.length) {
17
+ const currentIndex = nextIndex;
18
+ nextIndex += 1;
19
+ results[currentIndex] = await mapper(values[currentIndex]!, currentIndex);
20
+ }
21
+ };
22
+
23
+ await Promise.all(Array.from({ length: Math.min(workerLimit, values.length) }, () => worker()));
24
+ return results;
25
+ };