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,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
- };