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
@@ -2,11 +2,17 @@ import { randomUUID } from 'node:crypto';
2
2
  import { mkdir, mkdtemp, rm, stat } from 'node:fs/promises';
3
3
  import path from 'node:path';
4
4
  import { getThreadBrowseData } from './codex-browser-db';
5
- import { convertSessionFile, writeSessionFileExport } from './codex-exporter-transcript';
6
- import type { CodexCliOptions } from './codex-exporter-types';
5
+ import type { CodexTranscriptRenderOptions } from './codex-thread-types';
6
+ import { renderCodexSessionFile, writeCodexSessionFileExport } from './codex-transcript-renderer';
7
7
  import { applyPathTransforms, type PathDisplaySettings } from './path-transforms';
8
- import { type ExportFormat, getPortablePathBasename } from './shared';
9
- import { getExportMimeType, sanitizeExportFileName, zipExportDirectory, zipExportFile } from './ui-export-archive';
8
+ import type { ExportFormat } from './shared';
9
+ import {
10
+ buildBatchExportBaseName,
11
+ buildConversationExportBaseName,
12
+ getExportMimeType,
13
+ zipExportDirectory,
14
+ zipExportFile,
15
+ } from './ui-export-archive';
10
16
  import { buildUiExportDownloadUrl, ensureUiExportDir } from './ui-export-files';
11
17
 
12
18
  type RenderCodexThreadDownloadInput = {
@@ -42,31 +48,15 @@ export type CodexThreadDownload =
42
48
 
43
49
  const LARGE_BROWSER_EXPORT_THRESHOLD_BYTES = 128 * 1024 * 1024;
44
50
 
45
- const formatReadableExportDate = (value: number) => {
46
- const date = new Date(value);
47
- const year = date.getUTCFullYear();
48
- const month = String(date.getUTCMonth() + 1).padStart(2, '0');
49
- const day = String(date.getUTCDate()).padStart(2, '0');
50
- const hours = String(date.getUTCHours()).padStart(2, '0');
51
- const minutes = String(date.getUTCMinutes()).padStart(2, '0');
52
- return `${year}-${month}-${day}-${hours}${minutes}`;
53
- };
54
-
55
51
  const buildExportBaseName = (thread: ReturnType<typeof getThreadBrowseData>['thread']) => {
56
- const projectName = sanitizeExportFileName(getPortablePathBasename(thread.cwd) || 'thread') || 'thread';
57
- const timestamp = thread.updated_at_ms ?? thread.updated_at * 1000;
58
- return `${projectName}-${formatReadableExportDate(timestamp)}-${thread.id.slice(0, 8)}`;
59
- };
60
-
61
- const buildBatchExportBaseName = (threads: Array<ReturnType<typeof getThreadBrowseData>['thread']>) => {
62
- const firstThread = threads[0];
63
- if (!firstThread) {
64
- throw new Error('No threads selected for export');
65
- }
66
-
67
- const projectName = sanitizeExportFileName(getPortablePathBasename(firstThread.cwd) || 'threads') || 'threads';
68
- const latestTimestamp = Math.max(...threads.map((thread) => thread.updated_at_ms ?? thread.updated_at * 1000));
69
- return `${projectName}-${formatReadableExportDate(latestTimestamp)}-threads-${threads.length}`;
52
+ return buildConversationExportBaseName(
53
+ {
54
+ cwd: thread.cwd,
55
+ id: thread.id,
56
+ updatedAtMs: thread.updated_at_ms ?? thread.updated_at * 1000,
57
+ },
58
+ 'thread',
59
+ );
70
60
  };
71
61
 
72
62
  const buildUniqueArchivePath = (exportDir: string, exportBaseName: string) => {
@@ -89,19 +79,12 @@ type RolloutSnapshot = {
89
79
  sizeBytes: number;
90
80
  };
91
81
 
92
- const toDownloadOptions = (input: RenderCodexThreadDownloadInput): CodexCliOptions => {
82
+ const toDownloadOptions = (input: RenderCodexThreadDownloadInput): CodexTranscriptRenderOptions => {
93
83
  return {
94
- cwdFilter: null,
95
- dbPath: input.dbPath,
96
- flat: false,
97
84
  includeCommentary: input.includeCommentary,
98
85
  includeMetadata: input.includeMetadata,
99
86
  includeTools: input.includeTools,
100
- inputDir: '',
101
- outputDir: '',
102
87
  outputFormat: input.outputFormat,
103
- projectFilter: null,
104
- threadIds: [input.threadId],
105
88
  };
106
89
  };
107
90
 
@@ -214,7 +197,7 @@ export const renderCodexThreadDownload = async (
214
197
  const savedPath = path.join(workspaceDir, `${exportBaseName}.${extension}`);
215
198
  const zipPath = buildUniqueArchivePath(exportDir, exportBaseName);
216
199
  try {
217
- const saved = await writeSessionFileExport(
200
+ const saved = await writeCodexSessionFileExport(
218
201
  {
219
202
  fallbackReason: null,
220
203
  outputRelativePath: fileName,
@@ -257,7 +240,7 @@ export const renderCodexThreadDownload = async (
257
240
  };
258
241
  }
259
242
 
260
- const content = await convertSessionFile(
243
+ const content = await renderCodexSessionFile(
261
244
  {
262
245
  fallbackReason: null,
263
246
  outputRelativePath: fileName,
@@ -309,7 +292,13 @@ export const renderCodexThreadsDownload = async (
309
292
  const browseEntries = threadIds.map((threadId) => getThreadBrowseData(input.dbPath, threadId));
310
293
  const threads = browseEntries.map((entry) => entry.thread);
311
294
  const exportDir = await resolvePublicExportDir(input.publicExportDir);
312
- const exportBaseName = buildBatchExportBaseName(threads);
295
+ const exportBaseName = buildBatchExportBaseName(
296
+ threads.map((thread) => ({
297
+ cwd: thread.cwd,
298
+ updatedAtMs: thread.updated_at_ms ?? thread.updated_at * 1000,
299
+ })),
300
+ 'threads',
301
+ );
313
302
  const bundleDirectory = await createExportWorkspace(exportDir, exportBaseName);
314
303
  const zipPath = buildUniqueArchivePath(exportDir, exportBaseName);
315
304
  const usedBatchEntryBaseNames = new Set<string>();
@@ -349,7 +338,7 @@ export const renderCodexThreadsDownload = async (
349
338
  });
350
339
  }
351
340
 
352
- const saved = await writeSessionFileExport(
341
+ const saved = await writeCodexSessionFileExport(
353
342
  {
354
343
  fallbackReason: null,
355
344
  outputRelativePath: relativeFileName,
@@ -362,7 +351,6 @@ export const renderCodexThreadsDownload = async (
362
351
  ...input,
363
352
  threadId: entry.thread.id,
364
353
  }),
365
- threadIds: [entry.thread.id],
366
354
  },
367
355
  savedPath,
368
356
  transform,
@@ -1,4 +1,4 @@
1
- import type { SessionMeta, ThreadRelations, ThreadRow } from './codex-exporter-types';
1
+ import type { SessionMeta, ThreadRelations, ThreadRow } from './codex-thread-types';
2
2
  import type { JsonValue } from './shared';
3
3
 
4
4
  export type DynamicToolDefinition = {
@@ -2,10 +2,15 @@ import { stat } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import type { ParsedCodexTranscript } from './codex-browser-types';
4
4
  import { parseCodexTranscriptFile } from './codex-thread-parser';
5
+ import type { CodexTranscriptEventFilters } from './codex-transcript-filter';
6
+ import { shouldShowCodexTranscriptEvent } from './codex-transcript-filter';
7
+ import { runWithTranscriptLoadLimit } from './transcript-load-limiter';
5
8
  import { getFileFingerprint, hashCacheKeyParts, withCachedJson } from './ui-cache';
6
9
 
7
- export const LARGE_THREAD_SIZE_BYTES = 100 * 1024 * 1024;
10
+ // Keep initial thread payloads below sizes that make TanStack Start SSR responses unreliable.
11
+ export const LARGE_THREAD_SIZE_BYTES = 8 * 1024 * 1024;
8
12
  export const LARGE_THREAD_PREVIEW_EVENT_LIMIT = 200;
13
+ const CODEX_TRANSCRIPT_CACHE_VERSION = 'v2';
9
14
 
10
15
  const isMissingFileError = (error: unknown) => {
11
16
  return error instanceof Error && 'code' in error && error.code === 'ENOENT';
@@ -13,12 +18,18 @@ const isMissingFileError = (error: unknown) => {
13
18
 
14
19
  export const getCachedParsedCodexTranscript = async (sessionFile: string): Promise<ParsedCodexTranscript> => {
15
20
  const fingerprint = await getFileFingerprint(sessionFile);
16
- const key = `thread-${hashCacheKeyParts(path.basename(sessionFile), fingerprint)}`;
21
+ const key = `thread-${hashCacheKeyParts(CODEX_TRANSCRIPT_CACHE_VERSION, path.basename(sessionFile), fingerprint)}`;
17
22
 
18
- return withCachedJson(key, async () => parseCodexTranscriptFile(sessionFile));
23
+ return withCachedJson(key, async () =>
24
+ runWithTranscriptLoadLimit(() => parseCodexTranscriptFile(sessionFile), {
25
+ path: sessionFile,
26
+ source: 'codex-full',
27
+ }),
28
+ );
19
29
  };
20
30
 
21
31
  type CachedThreadTranscriptPreviewOptions = {
32
+ filters?: CodexTranscriptEventFilters;
22
33
  largeTranscriptThresholdBytes?: number;
23
34
  previewEventLimit?: number;
24
35
  };
@@ -53,22 +64,39 @@ export const getCachedThreadTranscriptPreview = async (
53
64
  ): Promise<ParsedCodexTranscript> => {
54
65
  const threshold = options.largeTranscriptThresholdBytes ?? LARGE_THREAD_SIZE_BYTES;
55
66
  const previewEventLimit = options.previewEventLimit ?? LARGE_THREAD_PREVIEW_EVENT_LIMIT;
67
+ const filters = options.filters;
56
68
  const fingerprint = await getFileFingerprint(sessionFile);
57
69
  const { fileSizeBytes, shouldDeferTranscriptLoad } = await getThreadRolloutLoadState(sessionFile, threshold);
58
- const key = `thread-preview-${hashCacheKeyParts(path.basename(sessionFile), fingerprint, String(threshold), String(previewEventLimit))}`;
70
+ const filterKey = filters ? JSON.stringify(filters) : 'all';
71
+ const key = `thread-preview-${hashCacheKeyParts(CODEX_TRANSCRIPT_CACHE_VERSION, path.basename(sessionFile), fingerprint, String(threshold), String(previewEventLimit), filterKey)}`;
59
72
 
60
73
  return withCachedJson(key, async () => {
61
74
  if (!shouldDeferTranscriptLoad) {
62
- return parseCodexTranscriptFile(sessionFile, {
63
- sourceFileSizeBytes: fileSizeBytes,
64
- });
75
+ return runWithTranscriptLoadLimit(
76
+ () =>
77
+ parseCodexTranscriptFile(sessionFile, {
78
+ sourceFileSizeBytes: fileSizeBytes,
79
+ }),
80
+ {
81
+ path: sessionFile,
82
+ source: 'codex-preview-full',
83
+ },
84
+ );
65
85
  }
66
86
 
67
- return parseCodexTranscriptFile(sessionFile, {
68
- includeRaw: false,
69
- maxEvents: previewEventLimit,
70
- maxTurnContexts: 0,
71
- sourceFileSizeBytes: fileSizeBytes,
72
- });
87
+ return runWithTranscriptLoadLimit(
88
+ () =>
89
+ parseCodexTranscriptFile(sessionFile, {
90
+ eventFilter: filters ? (event) => shouldShowCodexTranscriptEvent(event, filters) : undefined,
91
+ includeRaw: false,
92
+ maxTurnContexts: 0,
93
+ sourceFileSizeBytes: fileSizeBytes,
94
+ tailEventLimit: previewEventLimit,
95
+ }),
96
+ {
97
+ path: sessionFile,
98
+ source: 'codex-preview',
99
+ },
100
+ );
73
101
  });
74
102
  };
@@ -14,13 +14,27 @@ import type {
14
14
  TurnContextRecord,
15
15
  WebSearchEvent,
16
16
  } from './codex-browser-types';
17
- import { asNumber, asObject, asString, type JsonValue, readJsonlObjects } from './shared';
17
+ import { asNumber, asObject, asString, type JsonValue, readJsonlObjects, stripCodexAppDirectiveLines } from './shared';
18
18
 
19
19
  type ParseCodexTranscriptOptions = {
20
+ eventFilter?: (event: ThreadEvent) => boolean;
20
21
  includeRaw?: boolean;
21
22
  maxEvents?: number;
22
23
  maxTurnContexts?: number;
23
24
  sourceFileSizeBytes?: number | null;
25
+ tailEventLimit?: number;
26
+ };
27
+
28
+ type ParseCodexTranscriptState = {
29
+ events: ThreadEvent[];
30
+ eventFilter: (event: ThreadEvent) => boolean;
31
+ includeRaw: boolean;
32
+ maxEvents: number;
33
+ maxTurnContexts: number;
34
+ sequence: number;
35
+ shouldStop: boolean;
36
+ tailEventLimit: number;
37
+ turnContexts: TurnContextRecord[];
24
38
  };
25
39
 
26
40
  const createEmptyStats = (): ThreadTranscriptStats => {
@@ -64,45 +78,74 @@ export const parseCodexTranscriptFile = async (
64
78
  const includeRaw = options.includeRaw ?? true;
65
79
  const maxEvents = options.maxEvents ?? Number.POSITIVE_INFINITY;
66
80
  const maxTurnContexts = options.maxTurnContexts ?? Number.POSITIVE_INFINITY;
67
- let sequence = 0;
81
+ const tailEventLimit = options.tailEventLimit ?? Number.POSITIVE_INFINITY;
82
+ const eventFilter = options.eventFilter ?? (() => true);
83
+ const state: ParseCodexTranscriptState = {
84
+ eventFilter,
85
+ events,
86
+ includeRaw,
87
+ maxEvents,
88
+ maxTurnContexts,
89
+ sequence: 0,
90
+ shouldStop: false,
91
+ tailEventLimit,
92
+ turnContexts,
93
+ };
68
94
 
69
95
  for await (const parsed of readJsonlObjects(sessionFile)) {
70
96
  captureSessionMeta(parsed, sessionMeta);
71
- const topLevelType = asString(parsed.type);
72
-
73
- if (topLevelType === 'turn_context') {
74
- if (turnContexts.length < maxTurnContexts) {
75
- captureTurnContext(parsed, turnContexts);
76
- }
77
- continue;
78
- }
79
-
80
- const event = toThreadEvent(parsed, sequence, includeRaw);
81
- if (!event) {
82
- continue;
97
+ captureTranscriptRecord(parsed, state);
98
+ if (state.shouldStop) {
99
+ break;
83
100
  }
101
+ }
84
102
 
85
- events.push(event);
103
+ for (const event of events) {
86
104
  updateTranscriptStats(stats, event);
87
- sequence += 1;
88
-
89
- if (events.length >= maxEvents) {
90
- break;
91
- }
92
105
  }
93
106
 
94
107
  return {
95
108
  events,
96
- isPartial: Number.isFinite(maxEvents) || Number.isFinite(maxTurnContexts),
109
+ isPartial:
110
+ Number.isFinite(maxEvents) ||
111
+ Number.isFinite(maxTurnContexts) ||
112
+ Number.isFinite(tailEventLimit) ||
113
+ options.eventFilter !== undefined,
97
114
  rawIncluded: includeRaw,
98
115
  sessionMeta,
99
116
  sourceFileSizeBytes: options.sourceFileSizeBytes ?? null,
100
117
  stats,
101
- statsArePartial: Number.isFinite(maxEvents),
118
+ statsArePartial:
119
+ Number.isFinite(maxEvents) || Number.isFinite(tailEventLimit) || options.eventFilter !== undefined,
102
120
  turnContexts,
103
121
  };
104
122
  };
105
123
 
124
+ const captureTranscriptRecord = (parsed: Record<string, JsonValue>, state: ParseCodexTranscriptState) => {
125
+ if (asString(parsed.type) === 'turn_context') {
126
+ if (state.turnContexts.length < state.maxTurnContexts) {
127
+ captureTurnContext(parsed, state.turnContexts);
128
+ }
129
+ return;
130
+ }
131
+
132
+ const event = toThreadEvent(parsed, state.sequence, state.includeRaw);
133
+ if (!event) {
134
+ return;
135
+ }
136
+
137
+ state.sequence += 1;
138
+ if (!state.eventFilter(event)) {
139
+ return;
140
+ }
141
+
142
+ state.events.push(event);
143
+ if (state.events.length > state.tailEventLimit) {
144
+ state.events.shift();
145
+ }
146
+ state.shouldStop = state.events.length >= state.maxEvents;
147
+ };
148
+
106
149
  const captureSessionMeta = (parsed: Record<string, JsonValue>, sessionMeta: SessionMetaExtended) => {
107
150
  if (parsed.type !== 'session_meta') {
108
151
  return;
@@ -261,12 +304,13 @@ const createMessageEvent = (
261
304
  ): MessageEvent | null => {
262
305
  const role = asString(payload.role);
263
306
  const content = payload.content;
307
+ const text = extractText(content);
264
308
  if (!role || content === undefined) {
265
309
  return null;
266
310
  }
267
311
 
268
312
  return {
269
- isHiddenByDefault: shouldHideTranscriptText(role, extractText(content)),
313
+ isHiddenByDefault: shouldHideTranscriptText(role, text),
270
314
  kind: 'message',
271
315
  memoryCitation: null,
272
316
  model: asString(payload.model),
@@ -274,7 +318,7 @@ const createMessageEvent = (
274
318
  raw,
275
319
  role,
276
320
  sequence,
277
- text: extractText(content),
321
+ text,
278
322
  timestamp,
279
323
  variant: 'message',
280
324
  };
@@ -286,8 +330,9 @@ const createUserMessageEvent = (
286
330
  sequence: number,
287
331
  timestamp: string | null,
288
332
  ): MessageEvent => {
333
+ const text = stripMemoryCitationBlocks(asString(payload.message) ?? '');
289
334
  return {
290
- isHiddenByDefault: shouldHideTranscriptText('user', asString(payload.message)?.trim() ?? ''),
335
+ isHiddenByDefault: shouldHideTranscriptText('user', text),
291
336
  kind: 'message',
292
337
  memoryCitation: null,
293
338
  model: null,
@@ -295,7 +340,7 @@ const createUserMessageEvent = (
295
340
  raw,
296
341
  role: 'user',
297
342
  sequence,
298
- text: asString(payload.message)?.trim() ?? '',
343
+ text,
299
344
  timestamp,
300
345
  variant: 'user_message',
301
346
  };
@@ -307,8 +352,9 @@ const createAgentMessageEvent = (
307
352
  sequence: number,
308
353
  timestamp: string | null,
309
354
  ): MessageEvent => {
355
+ const text = stripMemoryCitationBlocks(asString(payload.message) ?? '');
310
356
  return {
311
- isHiddenByDefault: false,
357
+ isHiddenByDefault: shouldHideTranscriptText('assistant', text),
312
358
  kind: 'message',
313
359
  memoryCitation: payload.memory_citation ?? null,
314
360
  model: asString(payload.model),
@@ -316,7 +362,7 @@ const createAgentMessageEvent = (
316
362
  raw,
317
363
  role: 'assistant',
318
364
  sequence,
319
- text: asString(payload.message)?.trim() ?? '',
365
+ text,
320
366
  timestamp,
321
367
  variant: 'agent_message',
322
368
  };
@@ -548,24 +594,29 @@ const parseExecCommandArguments = (argumentsText: string | null) => {
548
594
 
549
595
  const extractText = (content: JsonValue): string => {
550
596
  if (typeof content === 'string') {
551
- return content.trim();
597
+ return stripMemoryCitationBlocks(content);
552
598
  }
553
599
 
554
600
  if (Array.isArray(content)) {
555
- return content
556
- .map((entry) => extractTextPart(entry))
557
- .filter(Boolean)
558
- .join('\n\n')
559
- .trim();
601
+ return stripMemoryCitationBlocks(
602
+ content
603
+ .map((entry) => extractTextPart(entry))
604
+ .filter(Boolean)
605
+ .join('\n\n'),
606
+ );
560
607
  }
561
608
 
562
609
  if (content && typeof content === 'object') {
563
- return asString((content as Record<string, JsonValue>).text)?.trim() ?? '';
610
+ return stripMemoryCitationBlocks(asString((content as Record<string, JsonValue>).text) ?? '');
564
611
  }
565
612
 
566
613
  return '';
567
614
  };
568
615
 
616
+ const stripMemoryCitationBlocks = (text: string): string => {
617
+ return stripCodexAppDirectiveLines(text.replace(/<oai-mem-citation>[\s\S]*?<\/oai-mem-citation>/gu, ''));
618
+ };
619
+
569
620
  const extractTextPart = (entry: JsonValue): string => {
570
621
  const objectValue = asObject(entry);
571
622
  if (!objectValue) {
@@ -2,31 +2,11 @@ import os from 'node:os';
2
2
  import path from 'node:path';
3
3
  import type { ExportFormat, JsonValue } from './shared';
4
4
 
5
- export type CodexCliOptions = {
6
- dbPath: string;
7
- inputDir: string;
8
- outputDir: string;
9
- cwdFilter: string | null;
10
- projectFilter: string | null;
11
- threadIds: string[];
5
+ export type CodexTranscriptRenderOptions = {
12
6
  includeMetadata: boolean;
13
7
  includeCommentary: boolean;
14
8
  includeTools: boolean;
15
9
  outputFormat: ExportFormat;
16
- flat: boolean;
17
- };
18
-
19
- export type CodexExportedFile = {
20
- sourcePath: string;
21
- outputPath: string;
22
- threadId: string | null;
23
- };
24
-
25
- export type CodexExportRunResult = {
26
- outputDir: string;
27
- exportedCount: number;
28
- files: CodexExportedFile[];
29
- missingThreadIds: string[];
30
10
  };
31
11
 
32
12
  export type SessionMeta = {
@@ -98,7 +78,7 @@ export type ThreadRelations = {
98
78
  childEdges: SpawnEdgeRow[];
99
79
  };
100
80
 
101
- export type ExportTarget = {
81
+ export type CodexTranscriptExportTarget = {
102
82
  sessionFile: string;
103
83
  outputRelativePath: string;
104
84
  thread: ThreadRow | null;
@@ -106,13 +86,5 @@ export type ExportTarget = {
106
86
  fallbackReason: string | null;
107
87
  };
108
88
 
109
- export type ThreadData = {
110
- threadsById: Map<string, ThreadRow>;
111
- parentByChildId: Map<string, SpawnEdgeRow>;
112
- childEdgesByParentId: Map<string, SpawnEdgeRow[]>;
113
- };
114
-
115
89
  export const DEFAULT_CODEX_DIR = path.join(os.homedir(), '.codex');
116
90
  export const DEFAULT_DB_PATH = path.join(DEFAULT_CODEX_DIR, 'state_5.sqlite');
117
- export const DEFAULT_INPUT_DIR = path.join(DEFAULT_CODEX_DIR, 'sessions');
118
- export const DEFAULT_OUTPUT_DIR = path.join(process.cwd(), 'exports');
@@ -0,0 +1,31 @@
1
+ import type { ThreadEvent } from './codex-browser-types';
2
+
3
+ const isCommentaryMessage = (event: ThreadEvent) =>
4
+ event.kind === 'message' && event.role === 'assistant' && event.phase === 'commentary';
5
+
6
+ export type CodexTranscriptEventFilters = {
7
+ showCommentary: boolean;
8
+ showExtraEvents: boolean;
9
+ showToolCalls: boolean;
10
+ showUserMessages: boolean;
11
+ };
12
+
13
+ export const shouldShowCodexTranscriptEvent = (event: ThreadEvent, filters: CodexTranscriptEventFilters) => {
14
+ if (isCommentaryMessage(event) && !filters.showCommentary) {
15
+ return false;
16
+ }
17
+
18
+ if (event.kind === 'message') {
19
+ if (event.role === 'user' && !filters.showUserMessages) {
20
+ return false;
21
+ }
22
+
23
+ return !event.isHiddenByDefault || filters.showExtraEvents;
24
+ }
25
+
26
+ if (event.kind === 'tool_call' || event.kind === 'tool_output') {
27
+ return filters.showToolCalls;
28
+ }
29
+
30
+ return filters.showExtraEvents;
31
+ };