spiracha 1.4.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/AGENTS.md +116 -164
  2. package/README.md +92 -237
  3. package/apps/ui/AGENTS.md +36 -7
  4. package/apps/ui/README.md +79 -6
  5. package/apps/ui/components.json +21 -0
  6. package/apps/ui/package.json +65 -0
  7. package/apps/ui/{dist/client → public}/icon.svg +2 -1
  8. package/apps/ui/src/components/antigravity-conversations-table.tsx +206 -0
  9. package/apps/ui/src/components/antigravity-keychain-panel.tsx +76 -0
  10. package/apps/ui/src/components/antigravity-workspaces-table.tsx +63 -0
  11. package/apps/ui/src/components/app-shell.tsx +124 -0
  12. package/apps/ui/src/components/breadcrumbs.tsx +53 -0
  13. package/apps/ui/src/components/claude-code-sessions-table.tsx +114 -0
  14. package/apps/ui/src/components/claude-code-workspaces-table.tsx +55 -0
  15. package/apps/ui/src/components/cursor-threads-table.tsx +189 -0
  16. package/apps/ui/src/components/cursor-workspaces-table.tsx +140 -0
  17. package/apps/ui/src/components/data-table.tsx +241 -0
  18. package/apps/ui/src/components/delete-confirm-dialog.tsx +88 -0
  19. package/apps/ui/src/components/export-dialog.tsx +184 -0
  20. package/apps/ui/src/components/json-panel.tsx +17 -0
  21. package/apps/ui/src/components/kiro-sessions-table.tsx +112 -0
  22. package/apps/ui/src/components/kiro-workspaces-table.tsx +53 -0
  23. package/apps/ui/src/components/list-search-input.tsx +18 -0
  24. package/apps/ui/src/components/loading-panel.tsx +23 -0
  25. package/apps/ui/src/components/metadata-section.tsx +31 -0
  26. package/apps/ui/src/components/metric-card.tsx +19 -0
  27. package/apps/ui/src/components/opencode-sessions-table.tsx +128 -0
  28. package/apps/ui/src/components/opencode-workspaces-table.tsx +57 -0
  29. package/apps/ui/src/components/page-header.tsx +33 -0
  30. package/apps/ui/src/components/projects-loading-state.tsx +74 -0
  31. package/apps/ui/src/components/projects-table.tsx +108 -0
  32. package/apps/ui/src/components/qoder-sessions-table.tsx +112 -0
  33. package/apps/ui/src/components/qoder-workspaces-table.tsx +53 -0
  34. package/apps/ui/src/components/recent-threads-list.tsx +52 -0
  35. package/apps/ui/src/components/reload-error-panel.tsx +20 -0
  36. package/apps/ui/src/components/text-document-panel.tsx +19 -0
  37. package/apps/ui/src/components/theme-toggle.tsx +48 -0
  38. package/apps/ui/src/components/threads-table.tsx +202 -0
  39. package/apps/ui/src/components/transcript-view.tsx +552 -0
  40. package/apps/ui/src/components/ui/alert-dialog.tsx +160 -0
  41. package/apps/ui/src/components/ui/badge.tsx +45 -0
  42. package/apps/ui/src/components/ui/button.tsx +62 -0
  43. package/apps/ui/src/components/ui/checkbox.tsx +29 -0
  44. package/apps/ui/src/components/ui/dialog.tsx +137 -0
  45. package/apps/ui/src/components/ui/dropdown-menu.tsx +217 -0
  46. package/apps/ui/src/components/ui/input.tsx +21 -0
  47. package/apps/ui/src/components/ui/scroll-area.tsx +46 -0
  48. package/apps/ui/src/components/ui/select.tsx +163 -0
  49. package/apps/ui/src/components/ui/separator.tsx +28 -0
  50. package/apps/ui/src/components/ui/sheet.tsx +107 -0
  51. package/apps/ui/src/components/ui/skeleton.tsx +7 -0
  52. package/apps/ui/src/components/ui/table.tsx +76 -0
  53. package/apps/ui/src/components/ui/tabs.tsx +71 -0
  54. package/apps/ui/src/components/ui/tooltip.tsx +44 -0
  55. package/apps/ui/src/integrations/tanstack-query/devtools.tsx +6 -0
  56. package/apps/ui/src/integrations/tanstack-query/root-provider.tsx +10 -0
  57. package/apps/ui/src/lib/antigravity-conversation-state.ts +28 -0
  58. package/apps/ui/src/lib/antigravity-queries.ts +33 -0
  59. package/apps/ui/src/lib/antigravity-server.ts +128 -0
  60. package/apps/ui/src/lib/antigravity-transcript-events.ts +335 -0
  61. package/apps/ui/src/lib/claude-code-queries.ts +26 -0
  62. package/apps/ui/src/lib/claude-code-server.ts +75 -0
  63. package/apps/ui/src/lib/claude-code-transcript-events.ts +154 -0
  64. package/apps/ui/src/lib/codex-queries.ts +66 -0
  65. package/apps/ui/src/lib/codex-server.ts +209 -0
  66. package/apps/ui/src/lib/cursor-queries.ts +37 -0
  67. package/apps/ui/src/lib/cursor-server.ts +272 -0
  68. package/apps/ui/src/lib/cursor-transcript-events.ts +229 -0
  69. package/apps/ui/src/lib/download.ts +166 -0
  70. package/apps/ui/src/lib/formatters.ts +149 -0
  71. package/apps/ui/src/lib/kiro-queries.ts +22 -0
  72. package/apps/ui/src/lib/kiro-server.ts +73 -0
  73. package/apps/ui/src/lib/kiro-transcript-events.ts +113 -0
  74. package/apps/ui/src/lib/opencode-queries.ts +37 -0
  75. package/apps/ui/src/lib/opencode-server.ts +73 -0
  76. package/apps/ui/src/lib/opencode-transcript-events.ts +221 -0
  77. package/apps/ui/src/lib/package-metadata.ts +16 -0
  78. package/apps/ui/src/lib/path-utils.ts +13 -0
  79. package/apps/ui/src/lib/qoder-queries.ts +22 -0
  80. package/apps/ui/src/lib/qoder-server.ts +79 -0
  81. package/apps/ui/src/lib/qoder-transcript-events.ts +139 -0
  82. package/apps/ui/src/lib/route-search.ts +68 -0
  83. package/apps/ui/src/lib/settings-store.tsx +59 -0
  84. package/apps/ui/src/lib/source-session-export-server.ts +56 -0
  85. package/apps/ui/src/lib/text-filter.ts +22 -0
  86. package/apps/ui/src/lib/thread-id.ts +3 -0
  87. package/apps/ui/src/lib/thread-transcript-stats.ts +57 -0
  88. package/apps/ui/src/lib/utils.ts +7 -0
  89. package/apps/ui/src/routeTree.gen.ts +730 -0
  90. package/apps/ui/src/router.tsx +20 -0
  91. package/apps/ui/src/routes/$threadId.tsx +22 -0
  92. package/apps/ui/src/routes/__root.tsx +127 -0
  93. package/apps/ui/src/routes/analytics.tsx +143 -0
  94. package/apps/ui/src/routes/antigravity-conversations.$conversationId.tsx +438 -0
  95. package/apps/ui/src/routes/antigravity.$workspaceKey.tsx +127 -0
  96. package/apps/ui/src/routes/antigravity.index.tsx +51 -0
  97. package/apps/ui/src/routes/api.v1.conversation-query.ts +12 -0
  98. package/apps/ui/src/routes/api.v1.conversations.$source.$id.export.ts +12 -0
  99. package/apps/ui/src/routes/api.v1.conversations.$source.$id.ts +12 -0
  100. package/apps/ui/src/routes/api.v1.conversations.ts +12 -0
  101. package/apps/ui/src/routes/api.v1.resolve.ts +12 -0
  102. package/apps/ui/src/routes/api.v1.sources.ts +12 -0
  103. package/apps/ui/src/routes/claude-code-sessions.$sessionId.tsx +342 -0
  104. package/apps/ui/src/routes/claude-code.$workspaceKey.tsx +135 -0
  105. package/apps/ui/src/routes/claude-code.index.tsx +48 -0
  106. package/apps/ui/src/routes/codex.$project.tsx +390 -0
  107. package/apps/ui/src/routes/codex.index.tsx +116 -0
  108. package/apps/ui/src/routes/cursor-threads.$composerId.tsx +435 -0
  109. package/apps/ui/src/routes/cursor.$workspaceKey.tsx +416 -0
  110. package/apps/ui/src/routes/cursor.index.tsx +120 -0
  111. package/apps/ui/src/routes/index.tsx +124 -0
  112. package/apps/ui/src/routes/kiro-sessions.$sessionId.tsx +345 -0
  113. package/apps/ui/src/routes/kiro.$workspaceKey.tsx +136 -0
  114. package/apps/ui/src/routes/kiro.index.tsx +48 -0
  115. package/apps/ui/src/routes/opencode-sessions.$sessionId.tsx +334 -0
  116. package/apps/ui/src/routes/opencode.$workspaceKey.tsx +135 -0
  117. package/apps/ui/src/routes/opencode.index.tsx +48 -0
  118. package/apps/ui/src/routes/qoder-sessions.$sessionId.tsx +341 -0
  119. package/apps/ui/src/routes/qoder.$workspaceKey.tsx +139 -0
  120. package/apps/ui/src/routes/qoder.index.tsx +48 -0
  121. package/apps/ui/src/routes/settings.tsx +91 -0
  122. package/apps/ui/src/routes/threads.$threadId.tsx +619 -0
  123. package/apps/ui/src/styles.css +122 -0
  124. package/apps/ui/tsconfig.json +29 -0
  125. package/apps/ui/vite.config.ts +84 -0
  126. package/bin/spiracha.ts +32 -0
  127. package/package.json +50 -60
  128. package/src/client.ts +290 -0
  129. package/src/lib/antigravity-db.ts +213 -19
  130. package/src/lib/antigravity-exporter-types.ts +1 -0
  131. package/src/lib/claude-code-db.ts +655 -0
  132. package/src/lib/claude-code-exporter-types.ts +110 -0
  133. package/src/lib/claude-code-transcript-phase.ts +25 -0
  134. package/src/lib/claude-code-transcript.ts +180 -0
  135. package/src/lib/codex-analytics.ts +1 -1
  136. package/src/lib/codex-browser-db.ts +856 -61
  137. package/src/lib/codex-browser-export.ts +24 -16
  138. package/src/lib/codex-browser-types.ts +1 -1
  139. package/src/lib/codex-thread-cache.ts +17 -1
  140. package/src/lib/{codex-exporter-types.ts → codex-thread-types.ts} +2 -30
  141. package/src/lib/{codex-exporter-transcript.ts → codex-transcript-renderer.ts} +64 -28
  142. package/src/lib/concurrency.ts +25 -0
  143. package/src/lib/conversation-api.ts +792 -0
  144. package/src/lib/conversation-data/adapter-helpers.ts +110 -0
  145. package/src/lib/conversation-data/antigravity-adapter.ts +148 -0
  146. package/src/lib/conversation-data/claude-code-adapter.ts +175 -0
  147. package/src/lib/conversation-data/codex-adapter.ts +245 -0
  148. package/src/lib/conversation-data/cursor-adapter.ts +171 -0
  149. package/src/lib/conversation-data/index.ts +311 -0
  150. package/src/lib/conversation-data/kiro-adapter.ts +140 -0
  151. package/src/lib/conversation-data/message-selector.ts +37 -0
  152. package/src/lib/conversation-data/opencode-adapter.ts +180 -0
  153. package/src/lib/conversation-data/path-match.ts +79 -0
  154. package/src/lib/conversation-data/qoder-adapter.ts +230 -0
  155. package/src/lib/conversation-data/types.ts +116 -0
  156. package/src/lib/cursor-db.ts +67 -21
  157. package/src/lib/cursor-exporter-types.ts +0 -19
  158. package/src/lib/kiro-db.ts +949 -0
  159. package/src/lib/kiro-exporter-types.ts +100 -0
  160. package/src/lib/kiro-transcript-phase.ts +41 -0
  161. package/src/lib/kiro-transcript.ts +115 -0
  162. package/src/lib/opencode-db.ts +610 -0
  163. package/src/lib/opencode-exporter-types.ts +129 -0
  164. package/src/lib/opencode-think-tags.ts +126 -0
  165. package/src/lib/opencode-transcript-phase.ts +50 -0
  166. package/src/lib/opencode-transcript.ts +194 -0
  167. package/src/lib/qoder-acp-client.ts +268 -0
  168. package/src/lib/qoder-db.ts +1601 -0
  169. package/src/lib/qoder-exporter-types.ts +114 -0
  170. package/src/lib/qoder-transcript-phase.ts +41 -0
  171. package/src/lib/qoder-transcript.ts +112 -0
  172. package/src/lib/shared.ts +25 -0
  173. package/src/lib/ui-export-archive.ts +61 -0
  174. package/apps/ui/dist/client/assets/_threadId-CAIeH5mq.js +0 -1
  175. package/apps/ui/dist/client/assets/analytics-DK2jdvmI.js +0 -1
  176. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-DmD0sN8X.js +0 -7
  177. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-KAcXtNxI.js +0 -1
  178. package/apps/ui/dist/client/assets/antigravity-keychain-panel-BRHVjFAM.js +0 -1
  179. package/apps/ui/dist/client/assets/antigravity._workspaceKey-ByitGWki.js +0 -1
  180. package/apps/ui/dist/client/assets/antigravity._workspaceKey-CGV7amas.js +0 -1
  181. package/apps/ui/dist/client/assets/antigravity.index-DEEkjlZa.js +0 -1
  182. package/apps/ui/dist/client/assets/antigravity.index-DgW25FEV.js +0 -1
  183. package/apps/ui/dist/client/assets/badge-DfWvPfKF.js +0 -1
  184. package/apps/ui/dist/client/assets/checkbox-CdHitXWQ.js +0 -1
  185. package/apps/ui/dist/client/assets/createServerFn-CgRRVpBH.js +0 -3
  186. package/apps/ui/dist/client/assets/cursor-threads._composerId-CmBFclK8.js +0 -1
  187. package/apps/ui/dist/client/assets/cursor-threads._composerId-Ti2gTm63.js +0 -1
  188. package/apps/ui/dist/client/assets/cursor._workspaceKey-CaAZjGmm.js +0 -1
  189. package/apps/ui/dist/client/assets/cursor._workspaceKey-DzD_c6j9.js +0 -1
  190. package/apps/ui/dist/client/assets/cursor.index-CrnMwDCi.js +0 -1
  191. package/apps/ui/dist/client/assets/cursor.index-PkCFVcl4.js +0 -2
  192. package/apps/ui/dist/client/assets/data-table-Br78_dk3.js +0 -4
  193. package/apps/ui/dist/client/assets/delete-confirm-dialog-BHRmyLHr.js +0 -11
  194. package/apps/ui/dist/client/assets/dist-B9pyYCVU.js +0 -1
  195. package/apps/ui/dist/client/assets/dist-BhZOxAPP.js +0 -1
  196. package/apps/ui/dist/client/assets/dist-DvMS2965.js +0 -1
  197. package/apps/ui/dist/client/assets/download-Bf0QJKD3.js +0 -1
  198. package/apps/ui/dist/client/assets/dropdown-menu-Dy5cLzTy.js +0 -1
  199. package/apps/ui/dist/client/assets/es2015-BkCWttyM.js +0 -41
  200. package/apps/ui/dist/client/assets/export-dialog-C86SYHJn.js +0 -1
  201. package/apps/ui/dist/client/assets/formatters-BM9kB7ed.js +0 -1
  202. package/apps/ui/dist/client/assets/index-CPvAP-jk.js +0 -149
  203. package/apps/ui/dist/client/assets/jsx-runtime-DGeXAQPT.js +0 -1
  204. package/apps/ui/dist/client/assets/metric-card-Dplm0ZiM.js +0 -1
  205. package/apps/ui/dist/client/assets/page-header-Cwa3p6Tl.js +0 -1
  206. package/apps/ui/dist/client/assets/projects._project-Ckf6muWZ.js +0 -1
  207. package/apps/ui/dist/client/assets/projects._project-DSDwH4NF.js +0 -1
  208. package/apps/ui/dist/client/assets/projects.index-DEfhWqa8.js +0 -1
  209. package/apps/ui/dist/client/assets/projects.index-V5ibNZII.js +0 -3
  210. package/apps/ui/dist/client/assets/react-dom-DL96Jor4.js +0 -1
  211. package/apps/ui/dist/client/assets/refresh-ccw-BgKjOiA6.js +0 -1
  212. package/apps/ui/dist/client/assets/reload-error-panel-AHqu0akK.js +0 -1
  213. package/apps/ui/dist/client/assets/routes-Df2tgpyd.js +0 -1
  214. package/apps/ui/dist/client/assets/scroll-text-fM0sMOB3.js +0 -1
  215. package/apps/ui/dist/client/assets/select-Bf2GwfPR.js +0 -1
  216. package/apps/ui/dist/client/assets/settings-5VQIzME0.js +0 -1
  217. package/apps/ui/dist/client/assets/sqlite-error-B6uZjUe8.js +0 -1
  218. package/apps/ui/dist/client/assets/styles-BhRkXgwB.css +0 -1
  219. package/apps/ui/dist/client/assets/tabs-OO4VU5KR.js +0 -7
  220. package/apps/ui/dist/client/assets/text-filter-DVAZySUS.js +0 -2
  221. package/apps/ui/dist/client/assets/threads._threadId-BB9tTsV4.js +0 -1
  222. package/apps/ui/dist/client/assets/threads._threadId-BgDhFj2I.js +0 -1
  223. package/apps/ui/dist/client/assets/useMutation-CC_B7uy5.js +0 -1
  224. package/apps/ui/dist/client/assets/useQuery-C5By6WKU.js +0 -1
  225. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CRW2kqj0.js +0 -232
  226. package/apps/ui/dist/server/assets/_threadId-B6SrBR9E.js +0 -6
  227. package/apps/ui/dist/server/assets/analytics-CYP_LT5Y.js +0 -16
  228. package/apps/ui/dist/server/assets/analytics-CtpOMVMO.js +0 -146
  229. package/apps/ui/dist/server/assets/antigravity-conversation-state-HgzS302O.js +0 -16
  230. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-BtexWY-K.js +0 -613
  231. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-D426O-64.js +0 -11
  232. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-zMrR6v6R.js +0 -20
  233. package/apps/ui/dist/server/assets/antigravity-db-Bh8_U9uw.js +0 -580
  234. package/apps/ui/dist/server/assets/antigravity-keychain-DOiuHDwK.js +0 -126
  235. package/apps/ui/dist/server/assets/antigravity-keychain-panel-CC7FLmAK.js +0 -55
  236. package/apps/ui/dist/server/assets/antigravity-queries-CGrJO9Vr.js +0 -37
  237. package/apps/ui/dist/server/assets/antigravity-server-CHRjVFqN.js +0 -114
  238. package/apps/ui/dist/server/assets/antigravity._workspaceKey-3m_MzNFA.js +0 -11
  239. package/apps/ui/dist/server/assets/antigravity._workspaceKey-B0QeYUOh.js +0 -28
  240. package/apps/ui/dist/server/assets/antigravity._workspaceKey-C3kP-qyN.js +0 -210
  241. package/apps/ui/dist/server/assets/antigravity.index-CPCYkqCi.js +0 -104
  242. package/apps/ui/dist/server/assets/antigravity.index-DudTB3Tq.js +0 -11
  243. package/apps/ui/dist/server/assets/badge-EvdhKK_Z.js +0 -26
  244. package/apps/ui/dist/server/assets/button-CmTDnzOn.js +0 -46
  245. package/apps/ui/dist/server/assets/checkbox-C0hovF41.js +0 -19
  246. package/apps/ui/dist/server/assets/codex-queries-CtgeZ7VL.js +0 -99
  247. package/apps/ui/dist/server/assets/codex-server-CNXSJuc2.js +0 -2004
  248. package/apps/ui/dist/server/assets/concurrency-VXtYvlGh.js +0 -18
  249. package/apps/ui/dist/server/assets/createServerRpc-CF_DEwnm.js +0 -12
  250. package/apps/ui/dist/server/assets/createSsrRpc-C754NPki.js +0 -16
  251. package/apps/ui/dist/server/assets/cursor-db-cYZEU3WQ.js +0 -830
  252. package/apps/ui/dist/server/assets/cursor-exporter-types-CI3goo-c.js +0 -34
  253. package/apps/ui/dist/server/assets/cursor-queries-NCIM0Nat.js +0 -67
  254. package/apps/ui/dist/server/assets/cursor-recovery-nq-kR62j.js +0 -361
  255. package/apps/ui/dist/server/assets/cursor-server-C3q7hrp-.js +0 -213
  256. package/apps/ui/dist/server/assets/cursor-threads._composerId-BB0Y_Mao.js +0 -11
  257. package/apps/ui/dist/server/assets/cursor-threads._composerId-BPJFWfJj.js +0 -18
  258. package/apps/ui/dist/server/assets/cursor-threads._composerId-BkMMTQ3v.js +0 -582
  259. package/apps/ui/dist/server/assets/cursor-transcript-2iL3KFSK.js +0 -125
  260. package/apps/ui/dist/server/assets/cursor._workspaceKey-C5PdTaKB.js +0 -28
  261. package/apps/ui/dist/server/assets/cursor._workspaceKey-Ckj7apKI.js +0 -401
  262. package/apps/ui/dist/server/assets/cursor._workspaceKey-nmg3YIOQ.js +0 -11
  263. package/apps/ui/dist/server/assets/cursor.index-CcsX7DG0.js +0 -11
  264. package/apps/ui/dist/server/assets/cursor.index-DkWT-mxw.js +0 -189
  265. package/apps/ui/dist/server/assets/data-table-Cdct823O.js +0 -189
  266. package/apps/ui/dist/server/assets/delete-confirm-dialog-BcBNCxWB.js +0 -144
  267. package/apps/ui/dist/server/assets/download-DMmiy1xf.js +0 -92
  268. package/apps/ui/dist/server/assets/dropdown-menu-Dy_9t6TN.js +0 -36
  269. package/apps/ui/dist/server/assets/empty-plugin-adapters-B3lHh1La.js +0 -5
  270. package/apps/ui/dist/server/assets/export-dialog-BItjWgkZ.js +0 -240
  271. package/apps/ui/dist/server/assets/formatters-FJaGZgJk.js +0 -91
  272. package/apps/ui/dist/server/assets/loading-panel-BGFnWseS.js +0 -27
  273. package/apps/ui/dist/server/assets/metric-card-ByEeLu0r.js +0 -23
  274. package/apps/ui/dist/server/assets/model-label-B1NWGc65.js +0 -13
  275. package/apps/ui/dist/server/assets/page-header-VNSaM3xd.js +0 -29
  276. package/apps/ui/dist/server/assets/path-transforms-DL2IwtYd.js +0 -31
  277. package/apps/ui/dist/server/assets/projects._project-Bpbc3C-L.js +0 -20
  278. package/apps/ui/dist/server/assets/projects._project-Bshqk7JA.js +0 -12
  279. package/apps/ui/dist/server/assets/projects._project-CvZho6EQ.js +0 -395
  280. package/apps/ui/dist/server/assets/projects.index-BLXOx5eL.js +0 -12
  281. package/apps/ui/dist/server/assets/projects.index-BkLiF2FF.js +0 -182
  282. package/apps/ui/dist/server/assets/projects.index-DesYXwfi.js +0 -14
  283. package/apps/ui/dist/server/assets/reload-error-panel-BJMxY3U1.js +0 -25
  284. package/apps/ui/dist/server/assets/route-search-ts4W9MJ9.js +0 -38
  285. package/apps/ui/dist/server/assets/router-6m-ihwqA.js +0 -410
  286. package/apps/ui/dist/server/assets/routes-Bsact1uB.js +0 -184
  287. package/apps/ui/dist/server/assets/routes-BzkJgq4W.js +0 -34
  288. package/apps/ui/dist/server/assets/select-GW76p-ld.js +0 -76
  289. package/apps/ui/dist/server/assets/settings-OayxIYQQ.js +0 -100
  290. package/apps/ui/dist/server/assets/settings-store-DpEJEQ7M.js +0 -52
  291. package/apps/ui/dist/server/assets/shared-CPRNYIql.js +0 -134
  292. package/apps/ui/dist/server/assets/sqlite-error-LZDrnxdd.js +0 -13
  293. package/apps/ui/dist/server/assets/start-CI_0bSiY.js +0 -4
  294. package/apps/ui/dist/server/assets/tabs-CGA13IZM.js +0 -502
  295. package/apps/ui/dist/server/assets/text-filter-CGKxMCKt.js +0 -36
  296. package/apps/ui/dist/server/assets/threads._threadId-BSSK4nkI.js +0 -26
  297. package/apps/ui/dist/server/assets/threads._threadId-Bs0yuqO9.js +0 -18
  298. package/apps/ui/dist/server/assets/threads._threadId-D2GYkVn6.js +0 -639
  299. package/apps/ui/dist/server/assets/ui-export-files-BHLX9bhN.js +0 -83
  300. package/apps/ui/dist/server/assets/utils-C_uf36nf.js +0 -8
  301. package/apps/ui/dist/server/server.js +0 -5847
  302. package/bin/codex-chats-claude.js +0 -5
  303. package/bin/codex-chats.js +0 -5
  304. package/bin/spiracha.js +0 -5
  305. package/src/export-chats.ts +0 -120
  306. package/src/export-claude.ts +0 -36
  307. package/src/export-cursor.ts +0 -244
  308. package/src/lib/claude-exporter.ts +0 -864
  309. package/src/lib/codex-exporter-cli.ts +0 -277
  310. package/src/lib/codex-exporter-db.ts +0 -319
  311. package/src/lib/codex-exporter.ts +0 -115
  312. package/src/lib/cursor-exporter.ts +0 -266
  313. package/src/lib/interactive-cli.ts +0 -433
  314. package/src/lib/native-open.ts +0 -54
  315. package/src/mcp-server.ts +0 -137
  316. package/src/spiracha.ts +0 -116
  317. package/src/ui-cli.ts +0 -310
  318. /package/apps/ui/{dist/client → public}/manifest.json +0 -0
  319. /package/apps/ui/{dist/client → public}/robots.txt +0 -0
@@ -0,0 +1,128 @@
1
+ import { createServerFn } from '@tanstack/react-start';
2
+ import { z } from 'zod';
3
+ import { canExportAntigravityConversation, isAntigravityConversationLocked } from './antigravity-conversation-state';
4
+
5
+ const workspaceSchema = z.object({
6
+ workspaceKey: z.string().min(1),
7
+ });
8
+
9
+ const conversationSchema = z.object({
10
+ conversationId: z.string().min(1),
11
+ });
12
+
13
+ const exportSchema = z.object({
14
+ conversationId: z.string().min(1),
15
+ });
16
+
17
+ export const listAntigravityWorkspacesFn = createServerFn({ method: 'GET' }).handler(async () => {
18
+ const { listAntigravityWorkspaceGroups } = await import('@spiracha/lib/antigravity-db');
19
+ return listAntigravityWorkspaceGroups();
20
+ });
21
+
22
+ export const getAntigravityDecryptionStateFn = createServerFn({ method: 'GET' }).handler(async () => {
23
+ const { getAntigravityDecryptionState } = await import('@spiracha/lib/antigravity-keychain');
24
+ return getAntigravityDecryptionState();
25
+ });
26
+
27
+ export const unlockAntigravityDecryptionFn = createServerFn({ method: 'POST' }).handler(async () => {
28
+ const { unlockAntigravityDecryption } = await import('@spiracha/lib/antigravity-keychain');
29
+ return unlockAntigravityDecryption();
30
+ });
31
+
32
+ export const listAntigravityConversationsFn = createServerFn({ method: 'GET' })
33
+ .validator(workspaceSchema)
34
+ .handler(async ({ data }) => {
35
+ const { listAntigravityConversationsForGroup } = await import('@spiracha/lib/antigravity-db');
36
+ return listAntigravityConversationsForGroup(data.workspaceKey);
37
+ });
38
+
39
+ const findAntigravityConversationById = async (conversationId: string) => {
40
+ const { listAntigravityConversations } = await import('@spiracha/lib/antigravity-db');
41
+ const conversation = (await listAntigravityConversations()).find(
42
+ (candidate) => candidate.conversationId === conversationId,
43
+ );
44
+ if (!conversation) {
45
+ throw new Error(`Antigravity conversation not found: ${conversationId}`);
46
+ }
47
+
48
+ return conversation;
49
+ };
50
+
51
+ export const loadAntigravityConversationDetail = async (conversationId: string) => {
52
+ const { renderAntigravityArtifactsMarkdown, renderAntigravityConversationMarkdown } = await import(
53
+ '@spiracha/lib/antigravity-db'
54
+ );
55
+ const { getCachedAntigravityKeychainSecret } = await import('@spiracha/lib/antigravity-keychain');
56
+ const conversation = await findAntigravityConversationById(conversationId);
57
+ const keychainSecret = getCachedAntigravityKeychainSecret();
58
+ const hasKeychainSecret = Boolean(keychainSecret);
59
+ const transcriptLocked = isAntigravityConversationLocked(conversation, hasKeychainSecret);
60
+ const conversationMarkdown = transcriptLocked
61
+ ? null
62
+ : await renderAntigravityConversationMarkdown(conversation, { keychainSecret });
63
+ const artifactsMarkdown =
64
+ conversation.artifactCount > 0 ? await renderAntigravityArtifactsMarkdown(conversation) : null;
65
+
66
+ return {
67
+ artifactsMarkdown,
68
+ conversation,
69
+ // Suppress the duplicate panel when artifactsMarkdown and conversationMarkdown are identical.
70
+ conversationMarkdown: conversationMarkdown === artifactsMarkdown ? null : conversationMarkdown,
71
+ transcriptLocked,
72
+ };
73
+ };
74
+
75
+ export const loadAntigravityConversationExport = async (conversationId: string) => {
76
+ const { renderAntigravityConversationMarkdown } = await import('@spiracha/lib/antigravity-db');
77
+ const { getCachedAntigravityKeychainSecret } = await import('@spiracha/lib/antigravity-keychain');
78
+ const conversation = await findAntigravityConversationById(conversationId);
79
+ const keychainSecret = getCachedAntigravityKeychainSecret();
80
+ const hasKeychainSecret = Boolean(keychainSecret);
81
+
82
+ if (!canExportAntigravityConversation(conversation, hasKeychainSecret)) {
83
+ if (isAntigravityConversationLocked(conversation, hasKeychainSecret)) {
84
+ throw new Error('Unlock Antigravity Keychain access before exporting transcript logs.');
85
+ }
86
+
87
+ throw new Error(`No exportable Antigravity transcript found for conversation: ${conversationId}`);
88
+ }
89
+
90
+ const content = await renderAntigravityConversationMarkdown(conversation, { keychainSecret });
91
+ if (!content) {
92
+ throw new Error(`No exportable Antigravity transcript found for conversation: ${conversationId}`);
93
+ }
94
+
95
+ return {
96
+ content,
97
+ filename: `${conversationId}.md`,
98
+ };
99
+ };
100
+
101
+ export const getAntigravityConversationDetailFn = createServerFn({ method: 'GET' })
102
+ .validator(conversationSchema)
103
+ .handler(async ({ data }) => {
104
+ return loadAntigravityConversationDetail(data.conversationId);
105
+ });
106
+
107
+ export const exportAntigravityArtifactsFn = createServerFn({ method: 'POST' })
108
+ .validator(exportSchema)
109
+ .handler(async ({ data }) => {
110
+ const { renderAntigravityArtifactsMarkdown } = await import('@spiracha/lib/antigravity-db');
111
+ const conversation = await findAntigravityConversationById(data.conversationId);
112
+
113
+ const content = await renderAntigravityArtifactsMarkdown(conversation);
114
+ if (!content) {
115
+ throw new Error(`No Markdown artifacts found for conversation: ${data.conversationId}`);
116
+ }
117
+
118
+ return {
119
+ content,
120
+ filename: `${data.conversationId}-artifacts.md`,
121
+ };
122
+ });
123
+
124
+ export const exportAntigravityConversationFn = createServerFn({ method: 'POST' })
125
+ .validator(exportSchema)
126
+ .handler(async ({ data }) => {
127
+ return loadAntigravityConversationExport(data.conversationId);
128
+ });
@@ -0,0 +1,335 @@
1
+ import type { ThreadEvent, ThreadTranscriptStats } from '@spiracha/lib/codex-browser-types';
2
+ import type { JsonValue } from '@spiracha/lib/shared';
3
+
4
+ type MarkdownSection = {
5
+ body: string;
6
+ heading: string;
7
+ sequence: number;
8
+ };
9
+
10
+ type ParsedAssistantSection = {
11
+ content: string;
12
+ thinking: string;
13
+ toolCalls: ParsedToolCall[];
14
+ };
15
+
16
+ type ParsedToolCall = {
17
+ argumentsText: string | null;
18
+ name: string;
19
+ };
20
+
21
+ const HEADING_PATTERN = /^##\s+(.+)$/u;
22
+ const TIMESTAMP_PATTERN = /^_Timestamp:\s*(.+?)_$/u;
23
+ const TOOL_HEADING_PATTERN = /^tool:\s*(.+)$/iu;
24
+
25
+ const splitMarkdownSections = (markdown: string | null): MarkdownSection[] => {
26
+ if (!markdown?.trim()) {
27
+ return [];
28
+ }
29
+
30
+ const sections: MarkdownSection[] = [];
31
+ const lines = markdown.split(/\r?\n/u);
32
+ let currentHeading: string | null = null;
33
+ let currentLines: string[] = [];
34
+
35
+ const flush = () => {
36
+ if (!currentHeading) {
37
+ return;
38
+ }
39
+
40
+ sections.push({
41
+ body: currentLines.join('\n').trim(),
42
+ heading: currentHeading,
43
+ sequence: sections.length * 10,
44
+ });
45
+ };
46
+
47
+ for (const line of lines) {
48
+ const heading = HEADING_PATTERN.exec(line);
49
+ if (heading) {
50
+ flush();
51
+ currentHeading = heading[1]!.trim();
52
+ currentLines = [];
53
+ continue;
54
+ }
55
+
56
+ if (currentHeading) {
57
+ currentLines.push(line);
58
+ }
59
+ }
60
+
61
+ flush();
62
+ return sections;
63
+ };
64
+
65
+ const extractTimestamp = (body: string): { body: string; timestamp: string | null } => {
66
+ const lines = body.split(/\r?\n/u);
67
+ const timestamp = TIMESTAMP_PATTERN.exec(lines[0]?.trim() ?? '')?.[1]?.trim() ?? null;
68
+ return {
69
+ body: timestamp ? lines.slice(1).join('\n').trim() : body.trim(),
70
+ timestamp,
71
+ };
72
+ };
73
+
74
+ const sectionBodyBeforeSubheading = (body: string): string => {
75
+ return body.split(/^###\s+/mu)[0]?.trim() ?? '';
76
+ };
77
+
78
+ const extractSubheadingBlock = (body: string, title: string): string => {
79
+ const lines = body.split(/\r?\n/u);
80
+ const startIndex = lines.findIndex((line) => line.trim().toLowerCase() === `### ${title.toLowerCase()}`);
81
+ if (startIndex === -1) {
82
+ return '';
83
+ }
84
+
85
+ const nextSubheadingIndex = lines.findIndex((line, index) => index > startIndex && line.startsWith('### '));
86
+ return lines
87
+ .slice(startIndex + 1, nextSubheadingIndex === -1 ? undefined : nextSubheadingIndex)
88
+ .join('\n')
89
+ .trim();
90
+ };
91
+
92
+ const parseToolCalls = (body: string): ParsedToolCall[] => {
93
+ const toolCallsBlock = extractSubheadingBlock(body, 'Tool Calls');
94
+ if (!toolCallsBlock) {
95
+ return [];
96
+ }
97
+
98
+ const calls: ParsedToolCall[] = [];
99
+ const callPattern = /-\s+`([^`]+)`(?:\s*\n+```json\s*\n([\s\S]*?)\n```)?/gu;
100
+ for (const match of toolCallsBlock.matchAll(callPattern)) {
101
+ calls.push({
102
+ argumentsText: match[2]?.trim() ?? null,
103
+ name: match[1]?.trim() || 'unknown',
104
+ });
105
+ }
106
+
107
+ return calls;
108
+ };
109
+
110
+ const parseAssistantSection = (body: string): ParsedAssistantSection => {
111
+ const content = sectionBodyBeforeSubheading(body);
112
+ const thinkingBlock = extractSubheadingBlock(body, 'Thinking');
113
+ const [thinking, ...remainingThinkingBlock] = thinkingBlock.split(/\n{2,}/u).map((entry) => entry.trim());
114
+
115
+ return {
116
+ content: content || remainingThinkingBlock.join('\n\n').trim(),
117
+ thinking: thinking ?? '',
118
+ toolCalls: parseToolCalls(body),
119
+ };
120
+ };
121
+
122
+ const buildRaw = (section: MarkdownSection, extra: Record<string, JsonValue> = {}): Record<string, JsonValue> => ({
123
+ heading: section.heading,
124
+ source: 'antigravity_markdown',
125
+ ...extra,
126
+ });
127
+
128
+ const buildMessageEvent = (
129
+ section: MarkdownSection,
130
+ role: string,
131
+ text: string,
132
+ timestamp: string | null,
133
+ phase: string | null,
134
+ sequenceOffset = 0,
135
+ ): ThreadEvent => ({
136
+ isHiddenByDefault: role !== 'assistant' && role !== 'user',
137
+ kind: 'message',
138
+ memoryCitation: null,
139
+ model: null,
140
+ phase,
141
+ raw: buildRaw(section, { role }),
142
+ role,
143
+ sequence: section.sequence + sequenceOffset,
144
+ text,
145
+ timestamp,
146
+ variant: role === 'user' ? 'user_message' : role === 'assistant' ? 'agent_message' : 'message',
147
+ });
148
+
149
+ const buildToolCallEvent = (
150
+ section: MarkdownSection,
151
+ toolCall: ParsedToolCall,
152
+ timestamp: string | null,
153
+ sequenceOffset: number,
154
+ ): ThreadEvent => ({
155
+ argumentsParseFailed: false,
156
+ argumentsText: toolCall.argumentsText,
157
+ callId: null,
158
+ command: [toolCall.name, toolCall.argumentsText].filter(Boolean).join('\n'),
159
+ kind: 'tool_call',
160
+ name: toolCall.name,
161
+ raw: buildRaw(section, {
162
+ argumentsText: toolCall.argumentsText,
163
+ name: toolCall.name,
164
+ }),
165
+ sequence: section.sequence + sequenceOffset,
166
+ timestamp,
167
+ workdir: null,
168
+ });
169
+
170
+ const buildToolOutputEvent = (
171
+ section: MarkdownSection,
172
+ toolName: string,
173
+ outputText: string,
174
+ timestamp: string | null,
175
+ ): ThreadEvent => ({
176
+ callId: null,
177
+ exitCode: null,
178
+ kind: 'tool_output',
179
+ outputText,
180
+ raw: buildRaw(section, {
181
+ name: toolName,
182
+ }),
183
+ sequence: section.sequence,
184
+ summary: outputText,
185
+ timestamp,
186
+ wallTime: null,
187
+ });
188
+
189
+ const getFinalAssistantSectionSequences = (sections: MarkdownSection[]): Set<number> => {
190
+ const finalAssistantSectionSequences = new Set<number>();
191
+ let currentAssistantContentSequence: number | null = null;
192
+
193
+ const flushAssistantRun = () => {
194
+ if (currentAssistantContentSequence !== null) {
195
+ finalAssistantSectionSequences.add(currentAssistantContentSequence);
196
+ }
197
+ currentAssistantContentSequence = null;
198
+ };
199
+
200
+ for (const section of sections) {
201
+ const heading = section.heading.toLowerCase();
202
+ if (heading === 'user') {
203
+ flushAssistantRun();
204
+ continue;
205
+ }
206
+
207
+ if (heading !== 'assistant') {
208
+ continue;
209
+ }
210
+
211
+ const { body } = extractTimestamp(section.body);
212
+ const parsed = parseAssistantSection(body);
213
+ if (parsed.toolCalls.length > 0) {
214
+ currentAssistantContentSequence = null;
215
+ } else if (parsed.content) {
216
+ currentAssistantContentSequence = section.sequence;
217
+ }
218
+ }
219
+
220
+ flushAssistantRun();
221
+ return finalAssistantSectionSequences;
222
+ };
223
+
224
+ const textSectionToEvents = (
225
+ section: MarkdownSection,
226
+ role: string,
227
+ body: string,
228
+ timestamp: string | null,
229
+ ): ThreadEvent[] => {
230
+ return body ? [buildMessageEvent(section, role, body, timestamp, null)] : [];
231
+ };
232
+
233
+ const toolOutputSectionToEvents = (
234
+ section: MarkdownSection,
235
+ toolName: string,
236
+ body: string,
237
+ timestamp: string | null,
238
+ ): ThreadEvent[] => {
239
+ return body ? [buildToolOutputEvent(section, toolName, body, timestamp)] : [];
240
+ };
241
+
242
+ const assistantSectionToEvents = (
243
+ section: MarkdownSection,
244
+ body: string,
245
+ timestamp: string | null,
246
+ finalAssistantSectionSequences: Set<number>,
247
+ ): ThreadEvent[] => {
248
+ const parsed = parseAssistantSection(body);
249
+ const events: ThreadEvent[] = [];
250
+ if (parsed.thinking) {
251
+ events.push(buildMessageEvent(section, 'assistant', parsed.thinking, timestamp, 'commentary'));
252
+ }
253
+ if (parsed.content) {
254
+ const phase = finalAssistantSectionSequences.has(section.sequence) ? 'final_answer' : 'commentary';
255
+ events.push(buildMessageEvent(section, 'assistant', parsed.content, timestamp, phase, 1));
256
+ }
257
+ parsed.toolCalls.forEach((toolCall, index) => {
258
+ events.push(buildToolCallEvent(section, toolCall, timestamp, 2 + index));
259
+ });
260
+ return events;
261
+ };
262
+
263
+ const sectionToEvents = (section: MarkdownSection, finalAssistantSectionSequences: Set<number>): ThreadEvent[] => {
264
+ const { body, timestamp } = extractTimestamp(section.body);
265
+ const heading = section.heading.toLowerCase();
266
+ const toolHeading = TOOL_HEADING_PATTERN.exec(section.heading);
267
+
268
+ if (heading === 'user') {
269
+ return textSectionToEvents(section, 'user', body, timestamp);
270
+ }
271
+
272
+ if (toolHeading) {
273
+ return toolOutputSectionToEvents(section, toolHeading[1]?.trim() || 'unknown', body, timestamp);
274
+ }
275
+
276
+ if (heading === 'assistant') {
277
+ return assistantSectionToEvents(section, body, timestamp, finalAssistantSectionSequences);
278
+ }
279
+
280
+ if (heading === 'system') {
281
+ return textSectionToEvents(section, 'system', body, timestamp);
282
+ }
283
+
284
+ return textSectionToEvents(section, 'event', body, timestamp);
285
+ };
286
+
287
+ export const antigravityMarkdownToThreadEvents = (markdown: string | null): ThreadEvent[] => {
288
+ const sections = splitMarkdownSections(markdown);
289
+ const finalAssistantSectionSequences = getFinalAssistantSectionSequences(sections);
290
+ return sections.flatMap((section) => sectionToEvents(section, finalAssistantSectionSequences));
291
+ };
292
+
293
+ const updateMessageStats = (stats: ThreadTranscriptStats, event: Extract<ThreadEvent, { kind: 'message' }>) => {
294
+ stats.messageCount += 1;
295
+ if (event.role === 'assistant') {
296
+ stats.assistantMessageCount += 1;
297
+ }
298
+ if (event.role === 'user') {
299
+ stats.userMessageCount += 1;
300
+ }
301
+ if (event.phase === 'commentary') {
302
+ stats.commentaryCount += 1;
303
+ }
304
+ if (event.phase === 'final_answer') {
305
+ stats.finalAnswerCount += 1;
306
+ }
307
+ };
308
+
309
+ export const getAntigravityThreadTranscriptStats = (events: ThreadEvent[]): ThreadTranscriptStats => {
310
+ const stats: ThreadTranscriptStats = {
311
+ assistantMessageCount: 0,
312
+ commentaryCount: 0,
313
+ execCommandCount: 0,
314
+ finalAnswerCount: 0,
315
+ messageCount: 0,
316
+ toolCallCount: 0,
317
+ toolOutputCount: 0,
318
+ userMessageCount: 0,
319
+ webSearchEventCount: 0,
320
+ };
321
+
322
+ for (const event of events) {
323
+ if (event.kind === 'message') {
324
+ updateMessageStats(stats, event);
325
+ }
326
+ if (event.kind === 'tool_call') {
327
+ stats.toolCallCount += 1;
328
+ }
329
+ if (event.kind === 'tool_output') {
330
+ stats.toolOutputCount += 1;
331
+ }
332
+ }
333
+
334
+ return stats;
335
+ };
@@ -0,0 +1,26 @@
1
+ import { queryOptions } from '@tanstack/react-query';
2
+ import {
3
+ getClaudeCodeSessionDetailFn,
4
+ listClaudeCodeSessionsFn,
5
+ listClaudeCodeWorkspacesFn,
6
+ } from './claude-code-server';
7
+
8
+ export const claudeCodeWorkspacesQueryOptions = () =>
9
+ queryOptions({
10
+ queryFn: () => listClaudeCodeWorkspacesFn(),
11
+ queryKey: ['claude-code-workspaces'],
12
+ });
13
+
14
+ export const claudeCodeSessionsQueryOptions = (workspaceKey: string | null) =>
15
+ queryOptions({
16
+ enabled: workspaceKey !== null,
17
+ queryFn: () => listClaudeCodeSessionsFn({ data: { workspaceKey: workspaceKey ?? '' } }),
18
+ queryKey: ['claude-code-sessions', workspaceKey ?? 'none'],
19
+ });
20
+
21
+ export const claudeCodeSessionDetailQueryOptions = (sessionId: string | null) =>
22
+ queryOptions({
23
+ enabled: sessionId !== null,
24
+ queryFn: () => getClaudeCodeSessionDetailFn({ data: { sessionId: sessionId ?? '' } }),
25
+ queryKey: ['claude-code-session', sessionId ?? 'none'],
26
+ });
@@ -0,0 +1,75 @@
1
+ import { createServerFn } from '@tanstack/react-start';
2
+ import { z } from 'zod';
3
+ import { renderSourceSessionDownload } from './source-session-export-server';
4
+
5
+ const workspaceSchema = z.object({
6
+ workspaceKey: z.string().min(1),
7
+ });
8
+
9
+ const sessionSchema = z.object({
10
+ sessionId: z.string().min(1),
11
+ });
12
+
13
+ const exportSessionSchema = z.object({
14
+ includeCommentary: z.boolean().default(true),
15
+ includeMetadata: z.boolean().default(true),
16
+ includeTools: z.boolean().default(true),
17
+ outputFormat: z.enum(['md', 'txt']).default('md'),
18
+ sessionId: z.string().min(1),
19
+ zipArchive: z.boolean().default(false),
20
+ });
21
+
22
+ export const listClaudeCodeWorkspacesFn = createServerFn({ method: 'GET' }).handler(async () => {
23
+ const { listClaudeCodeWorkspaceGroups } = await import('@spiracha/lib/claude-code-db');
24
+ return listClaudeCodeWorkspaceGroups();
25
+ });
26
+
27
+ export const listClaudeCodeSessionsFn = createServerFn({ method: 'GET' })
28
+ .validator(workspaceSchema)
29
+ .handler(async ({ data }) => {
30
+ const { listClaudeCodeSessionsForGroup } = await import('@spiracha/lib/claude-code-db');
31
+ return listClaudeCodeSessionsForGroup(data.workspaceKey);
32
+ });
33
+
34
+ const loadClaudeCodeSessionTranscript = async (sessionId: string) => {
35
+ const { readClaudeCodeSessionTranscript, resolveClaudeCodeProjectsDir } = await import(
36
+ '@spiracha/lib/claude-code-db'
37
+ );
38
+ const transcript = await readClaudeCodeSessionTranscript(resolveClaudeCodeProjectsDir(), sessionId);
39
+ if (!transcript) {
40
+ throw new Error(`Claude Code session not found: ${sessionId}`);
41
+ }
42
+
43
+ return transcript;
44
+ };
45
+
46
+ export const getClaudeCodeSessionDetailFn = createServerFn({ method: 'GET' })
47
+ .validator(sessionSchema)
48
+ .handler(async ({ data }) => {
49
+ return loadClaudeCodeSessionTranscript(data.sessionId);
50
+ });
51
+
52
+ export const exportClaudeCodeSessionFn = createServerFn({ method: 'POST' })
53
+ .validator(exportSessionSchema)
54
+ .handler(async ({ data }) => {
55
+ const { renderClaudeCodeTranscript } = await import('@spiracha/lib/claude-code-transcript');
56
+ const transcript = await loadClaudeCodeSessionTranscript(data.sessionId);
57
+ const content = renderClaudeCodeTranscript(transcript, {
58
+ includeCommentary: data.includeCommentary,
59
+ includeMetadata: data.includeMetadata,
60
+ includeTools: data.includeTools,
61
+ outputFormat: data.outputFormat,
62
+ });
63
+
64
+ if (!content) {
65
+ throw new Error(`Claude Code session has no exportable content: ${data.sessionId}`);
66
+ }
67
+
68
+ return renderSourceSessionDownload({
69
+ content,
70
+ fallbackBaseName: 'claude-code-session',
71
+ fileBaseName: transcript.session.title || transcript.session.sessionId,
72
+ outputFormat: data.outputFormat,
73
+ zipArchive: data.zipArchive,
74
+ });
75
+ });