spiracha 1.5.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 (365) hide show
  1. package/AGENTS.md +114 -205
  2. package/README.md +89 -269
  3. package/apps/ui/AGENTS.md +17 -7
  4. package/apps/ui/README.md +34 -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 +206 -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 +124 -0
  11. package/apps/ui/src/components/breadcrumbs.tsx +53 -0
  12. package/apps/ui/src/components/claude-code-sessions-table.tsx +114 -0
  13. package/apps/ui/src/components/claude-code-workspaces-table.tsx +55 -0
  14. package/apps/ui/src/components/cursor-threads-table.tsx +189 -0
  15. package/apps/ui/src/components/cursor-workspaces-table.tsx +140 -0
  16. package/apps/ui/src/components/data-table.tsx +241 -0
  17. package/apps/ui/src/components/delete-confirm-dialog.tsx +88 -0
  18. package/apps/ui/src/components/export-dialog.tsx +184 -0
  19. package/apps/ui/src/components/json-panel.tsx +17 -0
  20. package/apps/ui/src/components/kiro-sessions-table.tsx +112 -0
  21. package/apps/ui/src/components/kiro-workspaces-table.tsx +53 -0
  22. package/apps/ui/src/components/list-search-input.tsx +18 -0
  23. package/apps/ui/src/components/loading-panel.tsx +23 -0
  24. package/apps/ui/src/components/metadata-section.tsx +31 -0
  25. package/apps/ui/src/components/metric-card.tsx +19 -0
  26. package/apps/ui/src/components/opencode-sessions-table.tsx +128 -0
  27. package/apps/ui/src/components/opencode-workspaces-table.tsx +57 -0
  28. package/apps/ui/src/components/page-header.tsx +33 -0
  29. package/apps/ui/src/components/projects-loading-state.tsx +74 -0
  30. package/apps/ui/src/components/projects-table.tsx +108 -0
  31. package/apps/ui/src/components/qoder-sessions-table.tsx +112 -0
  32. package/apps/ui/src/components/qoder-workspaces-table.tsx +53 -0
  33. package/apps/ui/src/components/recent-threads-list.tsx +52 -0
  34. package/apps/ui/src/components/reload-error-panel.tsx +20 -0
  35. package/apps/ui/src/components/text-document-panel.tsx +19 -0
  36. package/apps/ui/src/components/theme-toggle.tsx +48 -0
  37. package/apps/ui/src/components/threads-table.tsx +202 -0
  38. package/apps/ui/src/components/transcript-view.tsx +552 -0
  39. package/apps/ui/src/components/ui/alert-dialog.tsx +160 -0
  40. package/apps/ui/src/components/ui/badge.tsx +45 -0
  41. package/apps/ui/src/components/ui/button.tsx +62 -0
  42. package/apps/ui/src/components/ui/checkbox.tsx +29 -0
  43. package/apps/ui/src/components/ui/dialog.tsx +137 -0
  44. package/apps/ui/src/components/ui/dropdown-menu.tsx +217 -0
  45. package/apps/ui/src/components/ui/input.tsx +21 -0
  46. package/apps/ui/src/components/ui/scroll-area.tsx +46 -0
  47. package/apps/ui/src/components/ui/select.tsx +163 -0
  48. package/apps/ui/src/components/ui/separator.tsx +28 -0
  49. package/apps/ui/src/components/ui/sheet.tsx +107 -0
  50. package/apps/ui/src/components/ui/skeleton.tsx +7 -0
  51. package/apps/ui/src/components/ui/table.tsx +76 -0
  52. package/apps/ui/src/components/ui/tabs.tsx +71 -0
  53. package/apps/ui/src/components/ui/tooltip.tsx +44 -0
  54. package/apps/ui/src/integrations/tanstack-query/devtools.tsx +6 -0
  55. package/apps/ui/src/integrations/tanstack-query/root-provider.tsx +10 -0
  56. package/apps/ui/src/lib/antigravity-conversation-state.ts +28 -0
  57. package/apps/ui/src/lib/antigravity-queries.ts +33 -0
  58. package/apps/ui/src/lib/antigravity-server.ts +128 -0
  59. package/apps/ui/src/lib/antigravity-transcript-events.ts +335 -0
  60. package/apps/ui/src/lib/claude-code-queries.ts +26 -0
  61. package/apps/ui/src/lib/claude-code-server.ts +75 -0
  62. package/apps/ui/src/lib/claude-code-transcript-events.ts +154 -0
  63. package/apps/ui/src/lib/codex-queries.ts +66 -0
  64. package/apps/ui/src/lib/codex-server.ts +209 -0
  65. package/apps/ui/src/lib/cursor-queries.ts +37 -0
  66. package/apps/ui/src/lib/cursor-server.ts +272 -0
  67. package/apps/ui/src/lib/cursor-transcript-events.ts +229 -0
  68. package/apps/ui/src/lib/download.ts +166 -0
  69. package/apps/ui/src/lib/formatters.ts +149 -0
  70. package/apps/ui/src/lib/kiro-queries.ts +22 -0
  71. package/apps/ui/src/lib/kiro-server.ts +73 -0
  72. package/apps/ui/src/lib/kiro-transcript-events.ts +113 -0
  73. package/apps/ui/src/lib/opencode-queries.ts +37 -0
  74. package/apps/ui/src/lib/opencode-server.ts +73 -0
  75. package/apps/ui/src/lib/opencode-transcript-events.ts +221 -0
  76. package/apps/ui/src/lib/package-metadata.ts +16 -0
  77. package/apps/ui/src/lib/path-utils.ts +13 -0
  78. package/apps/ui/src/lib/qoder-queries.ts +22 -0
  79. package/apps/ui/src/lib/qoder-server.ts +79 -0
  80. package/apps/ui/src/lib/qoder-transcript-events.ts +139 -0
  81. package/apps/ui/src/lib/route-search.ts +68 -0
  82. package/apps/ui/src/lib/settings-store.tsx +59 -0
  83. package/apps/ui/src/lib/source-session-export-server.ts +56 -0
  84. package/apps/ui/src/lib/text-filter.ts +22 -0
  85. package/apps/ui/src/lib/thread-id.ts +3 -0
  86. package/apps/ui/src/lib/thread-transcript-stats.ts +57 -0
  87. package/apps/ui/src/lib/utils.ts +7 -0
  88. package/apps/ui/src/routeTree.gen.ts +730 -0
  89. package/apps/ui/src/router.tsx +20 -0
  90. package/apps/ui/src/routes/$threadId.tsx +22 -0
  91. package/apps/ui/src/routes/__root.tsx +127 -0
  92. package/apps/ui/src/routes/analytics.tsx +143 -0
  93. package/apps/ui/src/routes/antigravity-conversations.$conversationId.tsx +438 -0
  94. package/apps/ui/src/routes/antigravity.$workspaceKey.tsx +127 -0
  95. package/apps/ui/src/routes/antigravity.index.tsx +51 -0
  96. package/apps/ui/src/routes/api.v1.conversation-query.ts +12 -0
  97. package/apps/ui/src/routes/api.v1.conversations.$source.$id.export.ts +12 -0
  98. package/apps/ui/src/routes/api.v1.conversations.$source.$id.ts +12 -0
  99. package/apps/ui/src/routes/api.v1.conversations.ts +12 -0
  100. package/apps/ui/src/routes/api.v1.resolve.ts +12 -0
  101. package/apps/ui/src/routes/api.v1.sources.ts +12 -0
  102. package/apps/ui/src/routes/claude-code-sessions.$sessionId.tsx +342 -0
  103. package/apps/ui/src/routes/claude-code.$workspaceKey.tsx +135 -0
  104. package/apps/ui/src/routes/claude-code.index.tsx +48 -0
  105. package/apps/ui/src/routes/codex.$project.tsx +390 -0
  106. package/apps/ui/src/routes/codex.index.tsx +116 -0
  107. package/apps/ui/src/routes/cursor-threads.$composerId.tsx +435 -0
  108. package/apps/ui/src/routes/cursor.$workspaceKey.tsx +416 -0
  109. package/apps/ui/src/routes/cursor.index.tsx +120 -0
  110. package/apps/ui/src/routes/index.tsx +124 -0
  111. package/apps/ui/src/routes/kiro-sessions.$sessionId.tsx +345 -0
  112. package/apps/ui/src/routes/kiro.$workspaceKey.tsx +136 -0
  113. package/apps/ui/src/routes/kiro.index.tsx +48 -0
  114. package/apps/ui/src/routes/opencode-sessions.$sessionId.tsx +334 -0
  115. package/apps/ui/src/routes/opencode.$workspaceKey.tsx +135 -0
  116. package/apps/ui/src/routes/opencode.index.tsx +48 -0
  117. package/apps/ui/src/routes/qoder-sessions.$sessionId.tsx +341 -0
  118. package/apps/ui/src/routes/qoder.$workspaceKey.tsx +139 -0
  119. package/apps/ui/src/routes/qoder.index.tsx +48 -0
  120. package/apps/ui/src/routes/settings.tsx +91 -0
  121. package/apps/ui/src/routes/threads.$threadId.tsx +619 -0
  122. package/apps/ui/src/styles.css +122 -0
  123. package/apps/ui/tsconfig.json +29 -0
  124. package/apps/ui/vite.config.ts +84 -0
  125. package/bin/spiracha.ts +32 -0
  126. package/package.json +46 -73
  127. package/src/client.ts +290 -0
  128. package/src/lib/antigravity-db.ts +213 -19
  129. package/src/lib/antigravity-exporter-types.ts +1 -0
  130. package/src/lib/codex-analytics.ts +1 -1
  131. package/src/lib/codex-browser-db.ts +410 -74
  132. package/src/lib/codex-browser-export.ts +6 -14
  133. package/src/lib/codex-browser-types.ts +1 -1
  134. package/src/lib/{codex-exporter-types.ts → codex-thread-types.ts} +2 -30
  135. package/src/lib/{codex-exporter-transcript.ts → codex-transcript-renderer.ts} +64 -28
  136. package/src/lib/conversation-api.ts +792 -0
  137. package/src/lib/conversation-data/adapter-helpers.ts +110 -0
  138. package/src/lib/conversation-data/antigravity-adapter.ts +148 -0
  139. package/src/lib/conversation-data/claude-code-adapter.ts +175 -0
  140. package/src/lib/conversation-data/codex-adapter.ts +245 -0
  141. package/src/lib/conversation-data/cursor-adapter.ts +171 -0
  142. package/src/lib/conversation-data/index.ts +311 -0
  143. package/src/lib/conversation-data/kiro-adapter.ts +140 -0
  144. package/src/lib/conversation-data/message-selector.ts +37 -0
  145. package/src/lib/conversation-data/opencode-adapter.ts +180 -0
  146. package/src/lib/conversation-data/path-match.ts +79 -0
  147. package/src/lib/conversation-data/qoder-adapter.ts +230 -0
  148. package/src/lib/conversation-data/types.ts +116 -0
  149. package/src/lib/cursor-db.ts +67 -21
  150. package/src/lib/cursor-exporter-types.ts +0 -19
  151. package/src/lib/qoder-acp-client.ts +268 -0
  152. package/src/lib/qoder-db.ts +1601 -0
  153. package/src/lib/qoder-exporter-types.ts +114 -0
  154. package/src/lib/qoder-transcript-phase.ts +41 -0
  155. package/src/lib/qoder-transcript.ts +112 -0
  156. package/apps/ui/dist/client/assets/_threadId-CAIeH5mq.js +0 -1
  157. package/apps/ui/dist/client/assets/analytics-DOy1b6Sh.js +0 -1
  158. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-DqySVO2K.js +0 -7
  159. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-KAcXtNxI.js +0 -1
  160. package/apps/ui/dist/client/assets/antigravity-keychain-panel-B77qJz6f.js +0 -1
  161. package/apps/ui/dist/client/assets/antigravity._workspaceKey-B3NM6gRH.js +0 -1
  162. package/apps/ui/dist/client/assets/antigravity._workspaceKey-ByitGWki.js +0 -1
  163. package/apps/ui/dist/client/assets/antigravity.index-DP9JC2P9.js +0 -1
  164. package/apps/ui/dist/client/assets/antigravity.index-DgW25FEV.js +0 -1
  165. package/apps/ui/dist/client/assets/badge-C3i4OKs8.js +0 -1
  166. package/apps/ui/dist/client/assets/checkbox-CdHitXWQ.js +0 -1
  167. package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-8pQ55ci2.js +0 -1
  168. package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-DVz5UmtU.js +0 -1
  169. package/apps/ui/dist/client/assets/claude-code._workspaceKey-BBKskSum.js +0 -1
  170. package/apps/ui/dist/client/assets/claude-code._workspaceKey-OkikMUFs.js +0 -1
  171. package/apps/ui/dist/client/assets/claude-code.index-Cwu76dbb.js +0 -1
  172. package/apps/ui/dist/client/assets/claude-code.index-D6eMd08t.js +0 -1
  173. package/apps/ui/dist/client/assets/createServerFn-B-KkwmHU.js +0 -3
  174. package/apps/ui/dist/client/assets/cursor-threads._composerId-CmBFclK8.js +0 -1
  175. package/apps/ui/dist/client/assets/cursor-threads._composerId-hBWlP1D-.js +0 -1
  176. package/apps/ui/dist/client/assets/cursor._workspaceKey-BFPkIRi-.js +0 -1
  177. package/apps/ui/dist/client/assets/cursor._workspaceKey-CaAZjGmm.js +0 -1
  178. package/apps/ui/dist/client/assets/cursor.index-8y4o20kb.js +0 -2
  179. package/apps/ui/dist/client/assets/cursor.index-CrnMwDCi.js +0 -1
  180. package/apps/ui/dist/client/assets/data-table-Br78_dk3.js +0 -4
  181. package/apps/ui/dist/client/assets/delete-confirm-dialog-Bxs07u-j.js +0 -7
  182. package/apps/ui/dist/client/assets/dist-B9pyYCVU.js +0 -1
  183. package/apps/ui/dist/client/assets/dist-BrJhN2A0.js +0 -5
  184. package/apps/ui/dist/client/assets/dist-Cmd3AIfD.js +0 -1
  185. package/apps/ui/dist/client/assets/dist-DvMS2965.js +0 -1
  186. package/apps/ui/dist/client/assets/download-Bf0QJKD3.js +0 -1
  187. package/apps/ui/dist/client/assets/dropdown-menu-D5cvPaZt.js +0 -1
  188. package/apps/ui/dist/client/assets/es2015-ad6040dw.js +0 -41
  189. package/apps/ui/dist/client/assets/export-dialog-Dr8d2MqD.js +0 -1
  190. package/apps/ui/dist/client/assets/formatters-BtqyrX_c.js +0 -1
  191. package/apps/ui/dist/client/assets/index-C-STgIH4.js +0 -166
  192. package/apps/ui/dist/client/assets/jsx-runtime-DGeXAQPT.js +0 -1
  193. package/apps/ui/dist/client/assets/kiro-sessions._sessionId-CKgfJ7GR.js +0 -1
  194. package/apps/ui/dist/client/assets/kiro-sessions._sessionId-zvIJHtQF.js +0 -1
  195. package/apps/ui/dist/client/assets/kiro._workspaceKey-DhVuJuZB.js +0 -1
  196. package/apps/ui/dist/client/assets/kiro._workspaceKey-QArsjkTY.js +0 -1
  197. package/apps/ui/dist/client/assets/kiro.index-C-fr4m7i.js +0 -1
  198. package/apps/ui/dist/client/assets/kiro.index-OYgAdtZd.js +0 -1
  199. package/apps/ui/dist/client/assets/metric-card-Dplm0ZiM.js +0 -1
  200. package/apps/ui/dist/client/assets/opencode-sessions._sessionId-DLjiTst-.js +0 -1
  201. package/apps/ui/dist/client/assets/opencode-sessions._sessionId-biBwrRbt.js +0 -8
  202. package/apps/ui/dist/client/assets/opencode._workspaceKey-C7OIzMOJ.js +0 -1
  203. package/apps/ui/dist/client/assets/opencode._workspaceKey-sBakX0oI.js +0 -1
  204. package/apps/ui/dist/client/assets/opencode.index-Bl_kNs9N.js +0 -1
  205. package/apps/ui/dist/client/assets/opencode.index-CN53bVmb.js +0 -1
  206. package/apps/ui/dist/client/assets/page-header-Cwa3p6Tl.js +0 -1
  207. package/apps/ui/dist/client/assets/preload-helper-B8fFrdxC.js +0 -1
  208. package/apps/ui/dist/client/assets/projects._project-D8WloxQN.js +0 -1
  209. package/apps/ui/dist/client/assets/projects._project-DSDwH4NF.js +0 -1
  210. package/apps/ui/dist/client/assets/projects.index-5xRtuJdX.js +0 -3
  211. package/apps/ui/dist/client/assets/projects.index-DEfhWqa8.js +0 -1
  212. package/apps/ui/dist/client/assets/react-dom-DL96Jor4.js +0 -1
  213. package/apps/ui/dist/client/assets/refresh-ccw-BgKjOiA6.js +0 -1
  214. package/apps/ui/dist/client/assets/reload-error-panel-AHqu0akK.js +0 -1
  215. package/apps/ui/dist/client/assets/routes-DnzF_9CX.js +0 -1
  216. package/apps/ui/dist/client/assets/scroll-text-fM0sMOB3.js +0 -1
  217. package/apps/ui/dist/client/assets/select-CYF6pF37.js +0 -1
  218. package/apps/ui/dist/client/assets/settings-Dx70jgP_.js +0 -1
  219. package/apps/ui/dist/client/assets/sqlite-error-B6uZjUe8.js +0 -1
  220. package/apps/ui/dist/client/assets/styles-B7Zi9EFA.css +0 -1
  221. package/apps/ui/dist/client/assets/tabs-CmuhkT-c.js +0 -7
  222. package/apps/ui/dist/client/assets/text-filter-DVAZySUS.js +0 -2
  223. package/apps/ui/dist/client/assets/thread-transcript-stats-BUNz6u7F.js +0 -1
  224. package/apps/ui/dist/client/assets/threads._threadId-BB9tTsV4.js +0 -1
  225. package/apps/ui/dist/client/assets/threads._threadId-BMRSFow3.js +0 -1
  226. package/apps/ui/dist/client/assets/useMutation-BSFult2i.js +0 -1
  227. package/apps/ui/dist/client/assets/useQuery-CjINKZf1.js +0 -1
  228. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CQ8Jjs3B.js +0 -387
  229. package/apps/ui/dist/server/assets/_threadId-B6SrBR9E.js +0 -6
  230. package/apps/ui/dist/server/assets/analytics-CYP_LT5Y.js +0 -16
  231. package/apps/ui/dist/server/assets/analytics-CtpOMVMO.js +0 -146
  232. package/apps/ui/dist/server/assets/antigravity-conversation-state-HgzS302O.js +0 -16
  233. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-BKOyL2T6.js +0 -613
  234. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-D426O-64.js +0 -11
  235. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-eS87Dx7g.js +0 -20
  236. package/apps/ui/dist/server/assets/antigravity-db-Bh8_U9uw.js +0 -580
  237. package/apps/ui/dist/server/assets/antigravity-keychain-DOiuHDwK.js +0 -126
  238. package/apps/ui/dist/server/assets/antigravity-keychain-panel-CC7FLmAK.js +0 -55
  239. package/apps/ui/dist/server/assets/antigravity-queries-CGrJO9Vr.js +0 -37
  240. package/apps/ui/dist/server/assets/antigravity-server-CHRjVFqN.js +0 -114
  241. package/apps/ui/dist/server/assets/antigravity._workspaceKey-3m_MzNFA.js +0 -11
  242. package/apps/ui/dist/server/assets/antigravity._workspaceKey-B0QeYUOh.js +0 -28
  243. package/apps/ui/dist/server/assets/antigravity._workspaceKey-C3kP-qyN.js +0 -210
  244. package/apps/ui/dist/server/assets/antigravity.index-CPCYkqCi.js +0 -104
  245. package/apps/ui/dist/server/assets/antigravity.index-DudTB3Tq.js +0 -11
  246. package/apps/ui/dist/server/assets/badge-EvdhKK_Z.js +0 -26
  247. package/apps/ui/dist/server/assets/button-CmTDnzOn.js +0 -46
  248. package/apps/ui/dist/server/assets/checkbox-C0hovF41.js +0 -19
  249. package/apps/ui/dist/server/assets/claude-code-db-Ik3VStKZ.js +0 -361
  250. package/apps/ui/dist/server/assets/claude-code-queries-Cgzi4K-e.js +0 -37
  251. package/apps/ui/dist/server/assets/claude-code-server-PfraClXS.js +0 -72
  252. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-C55oe6zj.js +0 -18
  253. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-D1RYYi3j.js +0 -473
  254. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-DSvPLEUL.js +0 -11
  255. package/apps/ui/dist/server/assets/claude-code-transcript-C-bxh3cS.js +0 -139
  256. package/apps/ui/dist/server/assets/claude-code-transcript-phase-DmUMc8VU.js +0 -10
  257. package/apps/ui/dist/server/assets/claude-code._workspaceKey-B5Xg_-tE.js +0 -28
  258. package/apps/ui/dist/server/assets/claude-code._workspaceKey-BPlzyXPa.js +0 -11
  259. package/apps/ui/dist/server/assets/claude-code._workspaceKey-DqDve2wl.js +0 -191
  260. package/apps/ui/dist/server/assets/claude-code.index-B7yYR7dD.js +0 -92
  261. package/apps/ui/dist/server/assets/claude-code.index-BUHThG1W.js +0 -11
  262. package/apps/ui/dist/server/assets/codex-queries-CtgeZ7VL.js +0 -99
  263. package/apps/ui/dist/server/assets/codex-server-CGXU4H8-.js +0 -2294
  264. package/apps/ui/dist/server/assets/concurrency-VXtYvlGh.js +0 -18
  265. package/apps/ui/dist/server/assets/createServerRpc-CF_DEwnm.js +0 -12
  266. package/apps/ui/dist/server/assets/createSsrRpc-C754NPki.js +0 -16
  267. package/apps/ui/dist/server/assets/cursor-db-CZnYy7aT.js +0 -830
  268. package/apps/ui/dist/server/assets/cursor-exporter-types-CI3goo-c.js +0 -34
  269. package/apps/ui/dist/server/assets/cursor-queries-NCIM0Nat.js +0 -67
  270. package/apps/ui/dist/server/assets/cursor-recovery-CXpO8KcD.js +0 -361
  271. package/apps/ui/dist/server/assets/cursor-server-DNu52A3K.js +0 -213
  272. package/apps/ui/dist/server/assets/cursor-threads._composerId-BB0Y_Mao.js +0 -11
  273. package/apps/ui/dist/server/assets/cursor-threads._composerId-Ckn6ItHI.js +0 -582
  274. package/apps/ui/dist/server/assets/cursor-threads._composerId-p9-ARAzc.js +0 -18
  275. package/apps/ui/dist/server/assets/cursor-transcript-B7tGnqtn.js +0 -125
  276. package/apps/ui/dist/server/assets/cursor._workspaceKey-CZuohIUL.js +0 -28
  277. package/apps/ui/dist/server/assets/cursor._workspaceKey-DPp5JSjy.js +0 -401
  278. package/apps/ui/dist/server/assets/cursor._workspaceKey-nmg3YIOQ.js +0 -11
  279. package/apps/ui/dist/server/assets/cursor.index-CcsX7DG0.js +0 -11
  280. package/apps/ui/dist/server/assets/cursor.index-DkWT-mxw.js +0 -189
  281. package/apps/ui/dist/server/assets/data-table-Cdct823O.js +0 -189
  282. package/apps/ui/dist/server/assets/delete-confirm-dialog-BcBNCxWB.js +0 -144
  283. package/apps/ui/dist/server/assets/download-DMmiy1xf.js +0 -92
  284. package/apps/ui/dist/server/assets/dropdown-menu-Dy_9t6TN.js +0 -36
  285. package/apps/ui/dist/server/assets/empty-plugin-adapters-B3lHh1La.js +0 -5
  286. package/apps/ui/dist/server/assets/export-dialog-D88ze9Gy.js +0 -240
  287. package/apps/ui/dist/server/assets/formatters-FJaGZgJk.js +0 -91
  288. package/apps/ui/dist/server/assets/kiro-db--fXrED_-.js +0 -552
  289. package/apps/ui/dist/server/assets/kiro-queries-CzNlM2ok.js +0 -37
  290. package/apps/ui/dist/server/assets/kiro-server-9WRxg2Au.js +0 -72
  291. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-CRY2c7YO.js +0 -11
  292. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-F1UlwxmR.js +0 -449
  293. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-bvTulT7C.js +0 -18
  294. package/apps/ui/dist/server/assets/kiro-transcript-DoekQBaH.js +0 -112
  295. package/apps/ui/dist/server/assets/kiro-transcript-phase-CJG40nQg.js +0 -27
  296. package/apps/ui/dist/server/assets/kiro._workspaceKey-BDe9sQwo.js +0 -11
  297. package/apps/ui/dist/server/assets/kiro._workspaceKey-CJsjgNwO.js +0 -28
  298. package/apps/ui/dist/server/assets/kiro._workspaceKey-D_-4Qb7y.js +0 -193
  299. package/apps/ui/dist/server/assets/kiro.index-C__-UROk.js +0 -11
  300. package/apps/ui/dist/server/assets/kiro.index-CmTbqeYj.js +0 -93
  301. package/apps/ui/dist/server/assets/loading-panel-BGFnWseS.js +0 -27
  302. package/apps/ui/dist/server/assets/metric-card-ByEeLu0r.js +0 -23
  303. package/apps/ui/dist/server/assets/model-label-B1NWGc65.js +0 -13
  304. package/apps/ui/dist/server/assets/opencode-db-BM7KjOzc.js +0 -397
  305. package/apps/ui/dist/server/assets/opencode-queries-BeNYXnQv.js +0 -50
  306. package/apps/ui/dist/server/assets/opencode-server-BpQ_kRze.js +0 -72
  307. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-CGQ-t0vD.js +0 -518
  308. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-D8Q7in_Z.js +0 -18
  309. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-DKOvi0lV.js +0 -11
  310. package/apps/ui/dist/server/assets/opencode-think-tags-CAoD-EcZ.js +0 -87
  311. package/apps/ui/dist/server/assets/opencode-transcript-BNTcGNym.js +0 -141
  312. package/apps/ui/dist/server/assets/opencode-transcript-phase-OqLkiQD0.js +0 -32
  313. package/apps/ui/dist/server/assets/opencode._workspaceKey-BdqcWHw1.js +0 -11
  314. package/apps/ui/dist/server/assets/opencode._workspaceKey-CfH96HTT.js +0 -28
  315. package/apps/ui/dist/server/assets/opencode._workspaceKey-DdbHPDrO.js +0 -207
  316. package/apps/ui/dist/server/assets/opencode.index-BbVzkJXP.js +0 -11
  317. package/apps/ui/dist/server/assets/opencode.index-Vh_Gq_1L.js +0 -93
  318. package/apps/ui/dist/server/assets/page-header-VNSaM3xd.js +0 -29
  319. package/apps/ui/dist/server/assets/path-transforms-DL2IwtYd.js +0 -31
  320. package/apps/ui/dist/server/assets/projects._project-4io5LO0E.js +0 -20
  321. package/apps/ui/dist/server/assets/projects._project-Bshqk7JA.js +0 -12
  322. package/apps/ui/dist/server/assets/projects._project-D6ZoGhJ8.js +0 -395
  323. package/apps/ui/dist/server/assets/projects.index-BLXOx5eL.js +0 -12
  324. package/apps/ui/dist/server/assets/projects.index-BkLiF2FF.js +0 -182
  325. package/apps/ui/dist/server/assets/projects.index-DesYXwfi.js +0 -14
  326. package/apps/ui/dist/server/assets/reload-error-panel-BJMxY3U1.js +0 -25
  327. package/apps/ui/dist/server/assets/route-search-ts4W9MJ9.js +0 -38
  328. package/apps/ui/dist/server/assets/router-Sac2DGk6.js +0 -518
  329. package/apps/ui/dist/server/assets/routes-Bsact1uB.js +0 -184
  330. package/apps/ui/dist/server/assets/routes-BzkJgq4W.js +0 -34
  331. package/apps/ui/dist/server/assets/select-GW76p-ld.js +0 -76
  332. package/apps/ui/dist/server/assets/settings-OayxIYQQ.js +0 -100
  333. package/apps/ui/dist/server/assets/settings-store-DpEJEQ7M.js +0 -52
  334. package/apps/ui/dist/server/assets/shared-DyhChtHf.js +0 -137
  335. package/apps/ui/dist/server/assets/source-session-export-server-DNutCawb.js +0 -38
  336. package/apps/ui/dist/server/assets/sqlite-error-LZDrnxdd.js +0 -13
  337. package/apps/ui/dist/server/assets/start-B_HFwkkk.js +0 -4
  338. package/apps/ui/dist/server/assets/tabs-DkaChNVg.js +0 -501
  339. package/apps/ui/dist/server/assets/text-filter-CGKxMCKt.js +0 -36
  340. package/apps/ui/dist/server/assets/thread-transcript-stats-Dh34mt2u.js +0 -45
  341. package/apps/ui/dist/server/assets/threads._threadId-BSSK4nkI.js +0 -26
  342. package/apps/ui/dist/server/assets/threads._threadId-BeXEc4Lo.js +0 -648
  343. package/apps/ui/dist/server/assets/threads._threadId-Ci0S4mKU.js +0 -18
  344. package/apps/ui/dist/server/assets/ui-export-files-BHLX9bhN.js +0 -83
  345. package/apps/ui/dist/server/assets/utils-C_uf36nf.js +0 -8
  346. package/apps/ui/dist/server/server.js +0 -5895
  347. package/bin/codex-chats-claude.js +0 -5
  348. package/bin/codex-chats.js +0 -5
  349. package/bin/spiracha.js +0 -5
  350. package/src/export-chats.ts +0 -120
  351. package/src/export-claude.ts +0 -36
  352. package/src/export-cursor.ts +0 -244
  353. package/src/lib/claude-exporter.ts +0 -864
  354. package/src/lib/codex-exporter-cli.ts +0 -277
  355. package/src/lib/codex-exporter-db.ts +0 -319
  356. package/src/lib/codex-exporter.ts +0 -115
  357. package/src/lib/cursor-exporter.ts +0 -266
  358. package/src/lib/interactive-cli.ts +0 -433
  359. package/src/lib/native-open.ts +0 -54
  360. package/src/mcp-server.ts +0 -137
  361. package/src/spiracha.ts +0 -116
  362. package/src/ui-cli.ts +0 -310
  363. /package/apps/ui/{dist/client → public}/icon.svg +0 -0
  364. /package/apps/ui/{dist/client → public}/manifest.json +0 -0
  365. /package/apps/ui/{dist/client → public}/robots.txt +0 -0
@@ -1,277 +0,0 @@
1
- import path from 'node:path';
2
- import { type CodexCliOptions, DEFAULT_DB_PATH, DEFAULT_INPUT_DIR, DEFAULT_OUTPUT_DIR } from './codex-exporter-types';
3
- import { CliUsageError, type ExportFormat, expandHome, getPortablePathBasename } from './shared';
4
-
5
- export const parseCodexCliArgs = (argv: string[]): CodexCliOptions => {
6
- let dbPath = DEFAULT_DB_PATH;
7
- let inputDir = DEFAULT_INPUT_DIR;
8
- let outputDir: string | null = null;
9
- let cwdFilter: string | null = null;
10
- let projectFilter: string | null = null;
11
- let threadIds: string[] = [];
12
- let outputProvided = false;
13
- let includeMetadata = true;
14
- let includeCommentary = true;
15
- let includeTools = false;
16
- let outputFormat: ExportFormat = 'md';
17
- let flat = false;
18
-
19
- for (let index = 0; index < argv.length; index += 1) {
20
- const nextIndex = applyCodexCliArg(argv, index, {
21
- cwdFilter,
22
- dbPath,
23
- flat,
24
- includeCommentary,
25
- includeMetadata,
26
- includeTools,
27
- inputDir,
28
- outputDir,
29
- outputFormat,
30
- outputProvided,
31
- projectFilter,
32
- threadIds,
33
- });
34
-
35
- ({
36
- cwdFilter,
37
- dbPath,
38
- flat,
39
- includeCommentary,
40
- includeMetadata,
41
- includeTools,
42
- inputDir,
43
- outputDir,
44
- outputFormat,
45
- outputProvided,
46
- projectFilter,
47
- threadIds,
48
- } = nextIndex.state);
49
- index = nextIndex.index;
50
- }
51
-
52
- if (!outputProvided) {
53
- outputDir = resolveDefaultOutputDir(cwdFilter);
54
- }
55
-
56
- return {
57
- cwdFilter,
58
- dbPath,
59
- flat,
60
- includeCommentary,
61
- includeMetadata,
62
- includeTools,
63
- inputDir,
64
- outputDir: outputDir ?? DEFAULT_OUTPUT_DIR,
65
- outputFormat,
66
- projectFilter,
67
- threadIds: [...new Set(threadIds)],
68
- };
69
- };
70
-
71
- type CodexCliState = {
72
- cwdFilter: string | null;
73
- dbPath: string;
74
- flat: boolean;
75
- includeCommentary: boolean;
76
- includeMetadata: boolean;
77
- includeTools: boolean;
78
- inputDir: string;
79
- outputDir: string | null;
80
- outputFormat: ExportFormat;
81
- outputProvided: boolean;
82
- projectFilter: string | null;
83
- threadIds: string[];
84
- };
85
-
86
- type CodexCliNext = {
87
- index: number;
88
- state: CodexCliState;
89
- };
90
-
91
- const applyCodexCliArg = (argv: string[], index: number, state: CodexCliState): CodexCliNext => {
92
- const arg = argv[index];
93
-
94
- if (arg === '--db') {
95
- return {
96
- index: index + 1,
97
- state: {
98
- ...state,
99
- dbPath: expandHome(requireValue(argv[index + 1], '--db')),
100
- },
101
- };
102
- }
103
-
104
- if (arg === '--input' || arg === '-i') {
105
- return {
106
- index: index + 1,
107
- state: {
108
- ...state,
109
- inputDir: expandHome(requireValue(argv[index + 1], arg)),
110
- },
111
- };
112
- }
113
-
114
- if (arg === '--output' || arg === '-o') {
115
- return {
116
- index: index + 1,
117
- state: {
118
- ...state,
119
- outputDir: expandHome(requireValue(argv[index + 1], arg)),
120
- outputProvided: true,
121
- },
122
- };
123
- }
124
-
125
- if (arg === '--cwd') {
126
- return {
127
- index: index + 1,
128
- state: {
129
- ...state,
130
- cwdFilter: expandHome(requireValue(argv[index + 1], '--cwd')),
131
- },
132
- };
133
- }
134
-
135
- if (arg === '--project') {
136
- return {
137
- index: index + 1,
138
- state: {
139
- ...state,
140
- projectFilter: requireValue(argv[index + 1], '--project').trim(),
141
- },
142
- };
143
- }
144
-
145
- if (arg === '--no-metadata') {
146
- return {
147
- index,
148
- state: {
149
- ...state,
150
- includeMetadata: false,
151
- },
152
- };
153
- }
154
-
155
- if (arg === '--tools') {
156
- return {
157
- index,
158
- state: {
159
- ...state,
160
- includeTools: true,
161
- },
162
- };
163
- }
164
-
165
- if (arg === '--flat') {
166
- return {
167
- index,
168
- state: {
169
- ...state,
170
- flat: true,
171
- },
172
- };
173
- }
174
-
175
- if (arg.startsWith('--output-format=')) {
176
- return {
177
- index,
178
- state: {
179
- ...state,
180
- outputFormat: parseExportFormat(arg.slice('--output-format='.length)),
181
- },
182
- };
183
- }
184
-
185
- if (arg === '--output-format') {
186
- return {
187
- index: index + 1,
188
- state: {
189
- ...state,
190
- outputFormat: parseExportFormat(requireValue(argv[index + 1], '--output-format')),
191
- },
192
- };
193
- }
194
-
195
- if (!arg.startsWith('-')) {
196
- const threadId = parseThreadSelectionArg(arg);
197
- if (!threadId) {
198
- throw new CliUsageError(
199
- `Unsupported positional argument: ${arg}\nExpected a Codex thread deeplink like codex://threads/<thread-id>`,
200
- );
201
- }
202
-
203
- return {
204
- index,
205
- state: {
206
- ...state,
207
- threadIds: [...state.threadIds, threadId],
208
- },
209
- };
210
- }
211
-
212
- throw new CliUsageError(`Unknown argument: ${arg}`);
213
- };
214
-
215
- export const getCodexHelpText = (): string => {
216
- return [
217
- 'Export Codex session JSONL files to Markdown or TXT.',
218
- 'Run with no arguments to enter interactive mode.',
219
- '',
220
- 'Usage:',
221
- ' codex-chats',
222
- ' codex-chats --interactive',
223
- ' codex-chats [--db FILE] [--input DIR] [--output DIR] [--cwd DIR] [--project NAME] [--no-metadata] [--tools] [--flat] [--output-format md|txt] [codex://threads/<thread-id> ...]',
224
- '',
225
- 'Options:',
226
- ` --db Thread database path (default: ${DEFAULT_DB_PATH})`,
227
- ` --input, -i Source sessions directory (default: ${DEFAULT_INPUT_DIR})`,
228
- ' --output, -o Export directory (default: ./<cwd-basename> when --cwd is set, otherwise ./exports)',
229
- ' --cwd Only export chats whose cwd matches this exact path',
230
- ' --project Only export chats whose cwd basename matches this project name',
231
- ' codex://threads/<id>',
232
- ' Only export the exact threads referenced by these Codex deeplinks',
233
- ' --no-metadata Omit the chat metadata section from the export header',
234
- ' --tools Include tool-call logs such as exec_command invocations',
235
- ' --flat Write all exports into one folder instead of nested subfolders',
236
- ' --output-format Output file format: md or txt (default: md)',
237
- ' --interactive Start the interactive prompt flow',
238
- ' --help, -h Show this help text',
239
- ].join('\n');
240
- };
241
-
242
- export const parseThreadSelectionArg = (value: string): string | null => {
243
- const trimmed = value.trim();
244
- if (!trimmed) {
245
- return null;
246
- }
247
-
248
- const match = /^codex:\/\/threads\/([^/?#]+)$/u.exec(trimmed);
249
- return match?.[1] ?? null;
250
- };
251
-
252
- export const resolveDefaultOutputDir = (cwdFilter: string | null): string => {
253
- if (cwdFilter) {
254
- const basename = getPortablePathBasename(cwdFilter);
255
- if (basename) {
256
- return path.join(process.cwd(), basename);
257
- }
258
- }
259
-
260
- return DEFAULT_OUTPUT_DIR;
261
- };
262
-
263
- const requireValue = (value: string | undefined, flag: string): string => {
264
- if (!value || (value.startsWith('-') && value !== '-')) {
265
- throw new CliUsageError(`Missing value for ${flag}`);
266
- }
267
-
268
- return value;
269
- };
270
-
271
- const parseExportFormat = (value: string): ExportFormat => {
272
- if (value === 'md' || value === 'txt') {
273
- return value;
274
- }
275
-
276
- throw new CliUsageError(`Unsupported output format: ${value}`);
277
- };
@@ -1,319 +0,0 @@
1
- import { readdir } from 'node:fs/promises';
2
- import path from 'node:path';
3
- import { withReadonlyDb } from './codex-browser-db';
4
- import {
5
- type CodexCliOptions,
6
- DEFAULT_CODEX_DIR,
7
- type ExportTarget,
8
- type SpawnEdgeRow,
9
- type ThreadData,
10
- type ThreadRelations,
11
- type ThreadRow,
12
- } from './codex-exporter-types';
13
- import { getPortablePathBasename } from './shared';
14
-
15
- export const loadThreadData = (dbPath: string, options: CodexCliOptions): ThreadData => {
16
- const threadsById = new Map<string, ThreadRow>();
17
- const parentByChildId = new Map<string, SpawnEdgeRow>();
18
- const childEdgesByParentId = new Map<string, SpawnEdgeRow[]>();
19
-
20
- try {
21
- withReadonlyDb(dbPath, (db) => {
22
- const threadQuery = buildThreadQuery(options);
23
- const threadRows = db.query(threadQuery.sql).all(...threadQuery.params) as ThreadRow[];
24
-
25
- for (const row of threadRows) {
26
- threadsById.set(row.id, row);
27
- }
28
-
29
- const edgeQuery = buildSpawnEdgeQuery([...threadsById.keys()], options);
30
- const edgeRows = db.query(edgeQuery.sql).all(...edgeQuery.params) as SpawnEdgeRow[];
31
-
32
- for (const row of edgeRows) {
33
- parentByChildId.set(row.child_thread_id, row);
34
-
35
- const existing = childEdgesByParentId.get(row.parent_thread_id) ?? [];
36
- existing.push(row);
37
- childEdgesByParentId.set(row.parent_thread_id, existing);
38
- }
39
- });
40
- } catch (error) {
41
- const message = error instanceof Error ? error.message : String(error);
42
- throw new Error(`Failed to read thread database at ${dbPath}: ${message}`);
43
- }
44
-
45
- return {
46
- childEdgesByParentId,
47
- parentByChildId,
48
- threadsById,
49
- };
50
- };
51
-
52
- export const buildThreadQuery = (options: CodexCliOptions) => {
53
- const clauses: string[] = [];
54
- const params: string[] = [];
55
-
56
- if (options.threadIds.length > 0) {
57
- clauses.push(`id IN (${options.threadIds.map(() => '?').join(', ')})`);
58
- params.push(...options.threadIds);
59
- }
60
-
61
- if (options.cwdFilter) {
62
- clauses.push('cwd = ?');
63
- params.push(options.cwdFilter);
64
- }
65
-
66
- if (options.projectFilter) {
67
- clauses.push("(cwd = ? OR cwd LIKE ? ESCAPE '\\' OR cwd LIKE ? ESCAPE '\\')");
68
- const projectPattern = escapeSqlLike(options.projectFilter);
69
- params.push(options.projectFilter, `%/${projectPattern}`, `%\\${projectPattern}`);
70
- }
71
-
72
- return {
73
- params,
74
- sql: clauses.length > 0 ? `SELECT * FROM threads WHERE ${clauses.join(' AND ')}` : 'SELECT * FROM threads',
75
- };
76
- };
77
-
78
- export const buildSpawnEdgeQuery = (threadIds: string[], options: CodexCliOptions) => {
79
- const hasScopedFilters =
80
- options.threadIds.length > 0 || options.cwdFilter !== null || options.projectFilter !== null;
81
-
82
- if (!hasScopedFilters || threadIds.length === 0) {
83
- return {
84
- params: [] as string[],
85
- sql: 'SELECT * FROM thread_spawn_edges',
86
- };
87
- }
88
-
89
- const placeholders = threadIds.map(() => '?').join(', ');
90
- return {
91
- params: [...threadIds, ...threadIds],
92
- sql: `SELECT * FROM thread_spawn_edges WHERE parent_thread_id IN (${placeholders}) OR child_thread_id IN (${placeholders})`,
93
- };
94
- };
95
-
96
- export const findJsonlFiles = async (rootDir: string): Promise<string[]> => {
97
- const entries = await readdir(rootDir, { withFileTypes: true });
98
- const files: string[] = [];
99
-
100
- for (const entry of entries) {
101
- const fullPath = path.join(rootDir, entry.name);
102
-
103
- if (entry.isDirectory()) {
104
- files.push(...(await findJsonlFiles(fullPath)));
105
- continue;
106
- }
107
-
108
- if (entry.isFile() && fullPath.endsWith('.jsonl')) {
109
- files.push(fullPath);
110
- }
111
- }
112
-
113
- files.sort();
114
- return files;
115
- };
116
-
117
- export const shouldScanFallbackSessionFiles = (options: CodexCliOptions) => {
118
- return !options.cwdFilter && !options.projectFilter && options.threadIds.length === 0;
119
- };
120
-
121
- export const buildExportTargets = (
122
- threadData: ThreadData,
123
- sessionFiles: string[],
124
- options: CodexCliOptions,
125
- ): ExportTarget[] => {
126
- const targets: ExportTarget[] = [];
127
- const seenSessionFiles = new Set<string>();
128
- const threadOrder = new Map(options.threadIds.map((threadId, index) => [threadId, index] as const));
129
-
130
- for (const thread of threadData.threadsById.values()) {
131
- if (!matchesFilters(thread.cwd, options)) {
132
- continue;
133
- }
134
-
135
- const sessionFile = path.resolve(thread.rollout_path);
136
- seenSessionFiles.add(sessionFile);
137
-
138
- targets.push({
139
- fallbackReason: null,
140
- outputRelativePath: toOutputRelativePath(sessionFile, options, thread.cwd),
141
- relations: getRelations(thread.id, threadData),
142
- sessionFile,
143
- thread,
144
- });
145
- }
146
-
147
- for (const sessionFile of sessionFiles) {
148
- const normalized = path.resolve(sessionFile);
149
- if (seenSessionFiles.has(normalized)) {
150
- continue;
151
- }
152
-
153
- targets.push({
154
- fallbackReason: 'missing_thread_row',
155
- outputRelativePath: toOutputRelativePath(normalized, options),
156
- relations: {
157
- childEdges: [],
158
- parentThreadId: null,
159
- },
160
- sessionFile: normalized,
161
- thread: null,
162
- });
163
- }
164
-
165
- if (options.threadIds.length > 0) {
166
- targets.sort((left, right) => {
167
- const leftOrder = left.thread
168
- ? (threadOrder.get(left.thread.id) ?? Number.MAX_SAFE_INTEGER)
169
- : Number.MAX_SAFE_INTEGER;
170
- const rightOrder = right.thread
171
- ? (threadOrder.get(right.thread.id) ?? Number.MAX_SAFE_INTEGER)
172
- : Number.MAX_SAFE_INTEGER;
173
-
174
- if (leftOrder !== rightOrder) {
175
- return leftOrder - rightOrder;
176
- }
177
-
178
- return left.outputRelativePath.localeCompare(right.outputRelativePath);
179
- });
180
- } else {
181
- targets.sort((left, right) => left.outputRelativePath.localeCompare(right.outputRelativePath));
182
- }
183
-
184
- return options.flat ? ensureUniqueFlatOutputPaths(targets) : targets;
185
- };
186
-
187
- export const matchesFilters = (
188
- value: string | null | undefined,
189
- options: Pick<CodexCliOptions, 'cwdFilter' | 'projectFilter'>,
190
- ): boolean => {
191
- return matchesCwdFilter(value, options.cwdFilter) && matchesProjectFilter(value, options.projectFilter);
192
- };
193
-
194
- export const toOutputRelativePath = (
195
- sessionFile: string,
196
- options: CodexCliOptions,
197
- projectCwd?: string | null,
198
- ): string => {
199
- const normalized = path.resolve(sessionFile);
200
- const inputRoot = path.resolve(options.inputDir);
201
- const codexRoot = path.resolve(DEFAULT_CODEX_DIR);
202
- const extension = options.outputFormat === 'txt' ? '.txt' : '.md';
203
- const flatName = toFlatFileName(normalized, extension, projectCwd);
204
-
205
- if (options.flat) {
206
- return flatName;
207
- }
208
-
209
- // Prefer preserving the input sessions tree when the rollout lives under the configured input root.
210
- if (normalized.startsWith(`${inputRoot}${path.sep}`)) {
211
- return path.relative(inputRoot, normalized).replace(/\.jsonl$/i, extension);
212
- }
213
-
214
- // Fall back to a stable Codex-relative path when the file is under ~/.codex.
215
- if (normalized.startsWith(`${codexRoot}${path.sep}`)) {
216
- return path.relative(codexRoot, normalized).replace(/\.jsonl$/i, extension);
217
- }
218
-
219
- // Otherwise collapse to the basename so ad hoc session files cannot escape the output directory.
220
- return path.basename(normalized).replace(/\.jsonl$/i, extension);
221
- };
222
-
223
- export const toCodexRelativePath = (targetPath: string): string => {
224
- const codexRoot = path.resolve(DEFAULT_CODEX_DIR);
225
- const normalized = path.resolve(targetPath);
226
-
227
- if (normalized.startsWith(`${codexRoot}${path.sep}`)) {
228
- return path.relative(codexRoot, normalized);
229
- }
230
-
231
- return normalized;
232
- };
233
-
234
- const escapeSqlLike = (value: string) => {
235
- return value.replace(/([\\%_])/g, '\\$1');
236
- };
237
-
238
- const getRelations = (threadId: string, threadData: ThreadData): ThreadRelations => {
239
- const parentEdge = threadData.parentByChildId.get(threadId) ?? null;
240
- const childEdges = [...(threadData.childEdgesByParentId.get(threadId) ?? [])].sort((left, right) =>
241
- left.child_thread_id.localeCompare(right.child_thread_id),
242
- );
243
-
244
- return {
245
- childEdges,
246
- parentThreadId: parentEdge?.parent_thread_id ?? null,
247
- };
248
- };
249
-
250
- const matchesCwdFilter = (value: string | null | undefined, cwdFilter: string | null): boolean => {
251
- if (!cwdFilter) {
252
- return true;
253
- }
254
-
255
- return value === cwdFilter;
256
- };
257
-
258
- const matchesProjectFilter = (value: string | null | undefined, projectFilter: string | null): boolean => {
259
- if (!projectFilter) {
260
- return true;
261
- }
262
-
263
- if (!value) {
264
- return false;
265
- }
266
-
267
- return getPortablePathBasename(value) === projectFilter;
268
- };
269
-
270
- const toFlatFileName = (sessionFile: string, extension: string, projectCwd?: string | null): string => {
271
- const normalized = path.resolve(sessionFile);
272
- const codexRoot = path.resolve(DEFAULT_CODEX_DIR);
273
- const relative = normalized.startsWith(`${codexRoot}${path.sep}`)
274
- ? path.relative(codexRoot, normalized)
275
- : path.basename(normalized);
276
-
277
- const flattened = relative.replace(/[\\/]/g, '__').replace(/\.jsonl$/i, extension);
278
-
279
- if (!projectCwd) {
280
- return flattened;
281
- }
282
-
283
- const portableProjectName = getPortablePathBasename(projectCwd);
284
- if (!portableProjectName) {
285
- return flattened;
286
- }
287
-
288
- return `${portableProjectName}${extension}`;
289
- };
290
-
291
- const ensureUniqueFlatOutputPaths = (targets: ExportTarget[]): ExportTarget[] => {
292
- const counts = new Map<string, number>();
293
- for (const target of targets) {
294
- counts.set(target.outputRelativePath, (counts.get(target.outputRelativePath) ?? 0) + 1);
295
- }
296
-
297
- return targets.map((target) => {
298
- if ((counts.get(target.outputRelativePath) ?? 0) < 2) {
299
- return target;
300
- }
301
-
302
- const suffix = getFlatCollisionSuffix(target);
303
- const extension = path.extname(target.outputRelativePath);
304
- const basename = extension ? target.outputRelativePath.slice(0, -extension.length) : target.outputRelativePath;
305
-
306
- return {
307
- ...target,
308
- outputRelativePath: `${basename}__${suffix}${extension}`,
309
- };
310
- });
311
- };
312
-
313
- const getFlatCollisionSuffix = (target: ExportTarget): string => {
314
- if (target.thread?.id) {
315
- return target.thread.id.slice(0, 8);
316
- }
317
-
318
- return path.basename(target.sessionFile, '.jsonl').slice(-8);
319
- };
@@ -1,115 +0,0 @@
1
- import path from 'node:path';
2
- import {
3
- buildExportTargets,
4
- findJsonlFiles,
5
- loadThreadData,
6
- shouldScanFallbackSessionFiles,
7
- } from './codex-exporter-db';
8
- import { convertSessionFile } from './codex-exporter-transcript';
9
- import type { CodexCliOptions, CodexExportedFile, CodexExportRunResult } from './codex-exporter-types';
10
- import { writeExportFile } from './shared';
11
-
12
- export {
13
- getCodexHelpText,
14
- parseCodexCliArgs,
15
- parseThreadSelectionArg,
16
- resolveDefaultOutputDir,
17
- } from './codex-exporter-cli';
18
- export {
19
- buildExportTargets,
20
- buildSpawnEdgeQuery,
21
- buildThreadQuery,
22
- findJsonlFiles,
23
- loadThreadData,
24
- matchesFilters,
25
- shouldScanFallbackSessionFiles,
26
- toCodexRelativePath,
27
- toOutputRelativePath,
28
- } from './codex-exporter-db';
29
- export {
30
- convertSessionFile,
31
- formatToolOutputSummary,
32
- parseExecCommandArguments,
33
- } from './codex-exporter-transcript';
34
- export {
35
- type CodexCliOptions,
36
- type CodexExportedFile,
37
- type CodexExportRunResult,
38
- DEFAULT_CODEX_DIR,
39
- DEFAULT_DB_PATH,
40
- DEFAULT_INPUT_DIR,
41
- DEFAULT_OUTPUT_DIR,
42
- type ExportTarget,
43
- type MessageRecord,
44
- type SessionMeta,
45
- type SpawnEdgeRow,
46
- type ThreadData,
47
- type ThreadRelations,
48
- type ThreadRow,
49
- type ToolRecord,
50
- } from './codex-exporter-types';
51
-
52
- export const runCodexExport = async (options: CodexCliOptions): Promise<CodexExportRunResult> => {
53
- const threadData = loadThreadData(options.dbPath, options);
54
- const sessionFiles = shouldScanFallbackSessionFiles(options) ? await findJsonlFiles(options.inputDir) : [];
55
-
56
- if (threadData.threadsById.size === 0 && sessionFiles.length === 0) {
57
- throw new Error(`No threads found in ${options.dbPath} and no .jsonl files found in ${options.inputDir}`);
58
- }
59
-
60
- const exportTargets = buildExportTargets(threadData, sessionFiles, options);
61
- const files = await writeCodexExportTargets(exportTargets, options);
62
- const missingThreadIds = options.threadIds.filter((threadId) => !threadData.threadsById.has(threadId));
63
-
64
- if (shouldThrowNoMatchError(options, files.length)) {
65
- throw new Error(buildNoMatchErrorMessage(options));
66
- }
67
-
68
- return {
69
- exportedCount: files.length,
70
- files,
71
- missingThreadIds,
72
- outputDir: options.outputDir,
73
- };
74
- };
75
-
76
- const writeCodexExportTargets = async (
77
- exportTargets: ReturnType<typeof buildExportTargets>,
78
- options: CodexCliOptions,
79
- ): Promise<CodexExportedFile[]> => {
80
- const files: CodexExportedFile[] = [];
81
-
82
- for (const target of exportTargets) {
83
- const content = await convertSessionFile(target, options);
84
- if (!content) {
85
- continue;
86
- }
87
-
88
- const outputPath = path.join(options.outputDir, target.outputRelativePath);
89
- await writeExportFile(outputPath, content);
90
- files.push({
91
- outputPath,
92
- sourcePath: target.sessionFile,
93
- threadId: target.thread?.id ?? null,
94
- });
95
- }
96
-
97
- return files;
98
- };
99
-
100
- const shouldThrowNoMatchError = (options: CodexCliOptions, exportedCount: number): boolean => {
101
- return (
102
- exportedCount === 0 &&
103
- (options.threadIds.length > 0 || options.cwdFilter !== null || options.projectFilter !== null)
104
- );
105
- };
106
-
107
- const buildNoMatchErrorMessage = (options: CodexCliOptions): string => {
108
- const filters = [
109
- options.cwdFilter ? `cwd=${options.cwdFilter}` : null,
110
- options.projectFilter ? `project=${options.projectFilter}` : null,
111
- options.threadIds.length > 0 ? `threadIds=${options.threadIds.join(',')}` : null,
112
- ].filter(Boolean);
113
-
114
- return `No chats matched the requested filters (${filters.join('; ')})`;
115
- };