spiracha 1.3.3 → 1.5.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 (242) hide show
  1. package/AGENTS.md +55 -6
  2. package/README.md +46 -5
  3. package/apps/ui/AGENTS.md +31 -4
  4. package/apps/ui/README.md +59 -5
  5. package/apps/ui/dist/client/assets/analytics-DOy1b6Sh.js +1 -0
  6. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-DqySVO2K.js +7 -0
  7. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-KAcXtNxI.js +1 -0
  8. package/apps/ui/dist/client/assets/antigravity-keychain-panel-B77qJz6f.js +1 -0
  9. package/apps/ui/dist/client/assets/antigravity._workspaceKey-B3NM6gRH.js +1 -0
  10. package/apps/ui/dist/client/assets/antigravity._workspaceKey-ByitGWki.js +1 -0
  11. package/apps/ui/dist/client/assets/antigravity.index-DP9JC2P9.js +1 -0
  12. package/apps/ui/dist/client/assets/antigravity.index-DgW25FEV.js +1 -0
  13. package/apps/ui/dist/client/assets/badge-C3i4OKs8.js +1 -0
  14. package/apps/ui/dist/client/assets/checkbox-CdHitXWQ.js +1 -0
  15. package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-8pQ55ci2.js +1 -0
  16. package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-DVz5UmtU.js +1 -0
  17. package/apps/ui/dist/client/assets/claude-code._workspaceKey-BBKskSum.js +1 -0
  18. package/apps/ui/dist/client/assets/claude-code._workspaceKey-OkikMUFs.js +1 -0
  19. package/apps/ui/dist/client/assets/claude-code.index-Cwu76dbb.js +1 -0
  20. package/apps/ui/dist/client/assets/claude-code.index-D6eMd08t.js +1 -0
  21. package/apps/ui/dist/client/assets/createServerFn-B-KkwmHU.js +3 -0
  22. package/apps/ui/dist/client/assets/cursor-threads._composerId-CmBFclK8.js +1 -0
  23. package/apps/ui/dist/client/assets/cursor-threads._composerId-hBWlP1D-.js +1 -0
  24. package/apps/ui/dist/client/assets/cursor._workspaceKey-BFPkIRi-.js +1 -0
  25. package/apps/ui/dist/client/assets/cursor._workspaceKey-CaAZjGmm.js +1 -0
  26. package/apps/ui/dist/client/assets/cursor.index-8y4o20kb.js +2 -0
  27. package/apps/ui/dist/client/assets/cursor.index-CrnMwDCi.js +1 -0
  28. package/apps/ui/dist/client/assets/{data-table-DeQq8xdt.js → data-table-Br78_dk3.js} +2 -2
  29. package/apps/ui/dist/client/assets/delete-confirm-dialog-Bxs07u-j.js +7 -0
  30. package/apps/ui/dist/client/assets/dist-B9pyYCVU.js +1 -0
  31. package/apps/ui/dist/client/assets/dist-BrJhN2A0.js +5 -0
  32. package/apps/ui/dist/client/assets/dist-Cmd3AIfD.js +1 -0
  33. package/apps/ui/dist/client/assets/dist-DvMS2965.js +1 -0
  34. package/apps/ui/dist/client/assets/download-Bf0QJKD3.js +1 -0
  35. package/apps/ui/dist/client/assets/dropdown-menu-D5cvPaZt.js +1 -0
  36. package/apps/ui/dist/client/assets/es2015-ad6040dw.js +41 -0
  37. package/apps/ui/dist/client/assets/export-dialog-Dr8d2MqD.js +1 -0
  38. package/apps/ui/dist/client/assets/formatters-BtqyrX_c.js +1 -0
  39. package/apps/ui/dist/client/assets/index-C-STgIH4.js +166 -0
  40. package/apps/ui/dist/client/assets/jsx-runtime-DGeXAQPT.js +1 -0
  41. package/apps/ui/dist/client/assets/kiro-sessions._sessionId-CKgfJ7GR.js +1 -0
  42. package/apps/ui/dist/client/assets/kiro-sessions._sessionId-zvIJHtQF.js +1 -0
  43. package/apps/ui/dist/client/assets/kiro._workspaceKey-DhVuJuZB.js +1 -0
  44. package/apps/ui/dist/client/assets/kiro._workspaceKey-QArsjkTY.js +1 -0
  45. package/apps/ui/dist/client/assets/kiro.index-C-fr4m7i.js +1 -0
  46. package/apps/ui/dist/client/assets/kiro.index-OYgAdtZd.js +1 -0
  47. package/apps/ui/dist/client/assets/metric-card-Dplm0ZiM.js +1 -0
  48. package/apps/ui/dist/client/assets/opencode-sessions._sessionId-DLjiTst-.js +1 -0
  49. package/apps/ui/dist/client/assets/opencode-sessions._sessionId-biBwrRbt.js +8 -0
  50. package/apps/ui/dist/client/assets/opencode._workspaceKey-C7OIzMOJ.js +1 -0
  51. package/apps/ui/dist/client/assets/opencode._workspaceKey-sBakX0oI.js +1 -0
  52. package/apps/ui/dist/client/assets/opencode.index-Bl_kNs9N.js +1 -0
  53. package/apps/ui/dist/client/assets/opencode.index-CN53bVmb.js +1 -0
  54. package/apps/ui/dist/client/assets/page-header-Cwa3p6Tl.js +1 -0
  55. package/apps/ui/dist/client/assets/preload-helper-B8fFrdxC.js +1 -0
  56. package/apps/ui/dist/client/assets/projects._project-D8WloxQN.js +1 -0
  57. package/apps/ui/dist/client/assets/projects._project-DSDwH4NF.js +1 -0
  58. package/apps/ui/dist/client/assets/projects.index-5xRtuJdX.js +3 -0
  59. package/apps/ui/dist/client/assets/projects.index-DEfhWqa8.js +1 -0
  60. package/apps/ui/dist/client/assets/react-dom-DL96Jor4.js +1 -0
  61. package/apps/ui/dist/client/assets/refresh-ccw-BgKjOiA6.js +1 -0
  62. package/apps/ui/dist/client/assets/reload-error-panel-AHqu0akK.js +1 -0
  63. package/apps/ui/dist/client/assets/routes-DnzF_9CX.js +1 -0
  64. package/apps/ui/dist/client/assets/scroll-text-fM0sMOB3.js +1 -0
  65. package/apps/ui/dist/client/assets/select-CYF6pF37.js +1 -0
  66. package/apps/ui/dist/client/assets/settings-Dx70jgP_.js +1 -0
  67. package/apps/ui/dist/client/assets/sqlite-error-B6uZjUe8.js +1 -0
  68. package/apps/ui/dist/client/assets/styles-B7Zi9EFA.css +1 -0
  69. package/apps/ui/dist/client/assets/tabs-CmuhkT-c.js +7 -0
  70. package/apps/ui/dist/client/assets/text-filter-DVAZySUS.js +2 -0
  71. package/apps/ui/dist/client/assets/thread-transcript-stats-BUNz6u7F.js +1 -0
  72. package/apps/ui/dist/client/assets/threads._threadId-BB9tTsV4.js +1 -0
  73. package/apps/ui/dist/client/assets/threads._threadId-BMRSFow3.js +1 -0
  74. package/apps/ui/dist/client/assets/useMutation-BSFult2i.js +1 -0
  75. package/apps/ui/dist/client/assets/useQuery-CjINKZf1.js +1 -0
  76. package/apps/ui/dist/client/icon.svg +2 -1
  77. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CQ8Jjs3B.js +387 -0
  78. package/apps/ui/dist/server/assets/analytics-CYP_LT5Y.js +16 -0
  79. package/apps/ui/dist/server/assets/{analytics-Dc_QDZZC.js → analytics-CtpOMVMO.js} +13 -6
  80. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-BKOyL2T6.js +613 -0
  81. package/apps/ui/dist/server/assets/{antigravity-conversations._conversationId-C9z4AeN-.js → antigravity-conversations._conversationId-eS87Dx7g.js} +2 -2
  82. package/apps/ui/dist/server/assets/{antigravity-db-D9gW1D8G.js → antigravity-db-Bh8_U9uw.js} +11 -7
  83. package/apps/ui/dist/server/assets/{antigravity-keychain-panel-bpPoxhyp.js → antigravity-keychain-panel-CC7FLmAK.js} +1 -1
  84. package/apps/ui/dist/server/assets/{antigravity-queries-DVIKyOXi.js → antigravity-queries-CGrJO9Vr.js} +5 -5
  85. package/apps/ui/dist/server/assets/{antigravity-server-Cp1lc8fp.js → antigravity-server-CHRjVFqN.js} +11 -11
  86. package/apps/ui/dist/server/assets/{antigravity._workspaceKey-Dl8o1ptg.js → antigravity._workspaceKey-B0QeYUOh.js} +2 -2
  87. package/apps/ui/dist/server/assets/{antigravity._workspaceKey-BAoa4izU.js → antigravity._workspaceKey-C3kP-qyN.js} +4 -4
  88. package/apps/ui/dist/server/assets/{antigravity.index-BOlrJasZ.js → antigravity.index-CPCYkqCi.js} +2 -2
  89. package/apps/ui/dist/server/assets/claude-code-db-Ik3VStKZ.js +361 -0
  90. package/apps/ui/dist/server/assets/claude-code-queries-Cgzi4K-e.js +37 -0
  91. package/apps/ui/dist/server/assets/claude-code-server-PfraClXS.js +72 -0
  92. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-C55oe6zj.js +18 -0
  93. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-D1RYYi3j.js +473 -0
  94. package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-DSvPLEUL.js +11 -0
  95. package/apps/ui/dist/server/assets/claude-code-transcript-C-bxh3cS.js +139 -0
  96. package/apps/ui/dist/server/assets/claude-code-transcript-phase-DmUMc8VU.js +10 -0
  97. package/apps/ui/dist/server/assets/claude-code._workspaceKey-B5Xg_-tE.js +28 -0
  98. package/apps/ui/dist/server/assets/claude-code._workspaceKey-BPlzyXPa.js +11 -0
  99. package/apps/ui/dist/server/assets/claude-code._workspaceKey-DqDve2wl.js +191 -0
  100. package/apps/ui/dist/server/assets/claude-code.index-B7yYR7dD.js +92 -0
  101. package/apps/ui/dist/server/assets/claude-code.index-BUHThG1W.js +11 -0
  102. package/apps/ui/dist/server/assets/{codex-queries-ev_mRUzr.js → codex-queries-CtgeZ7VL.js} +15 -13
  103. package/apps/ui/dist/server/assets/{codex-server-DIYFLozB.js → codex-server-CGXU4H8-.js} +421 -146
  104. package/apps/ui/dist/server/assets/concurrency-VXtYvlGh.js +18 -0
  105. package/apps/ui/dist/server/assets/{createServerRpc-Cg-Zr1rq.js → createServerRpc-CF_DEwnm.js} +1 -1
  106. package/apps/ui/dist/server/assets/{createSsrRpc-DVnVQhGx.js → createSsrRpc-C754NPki.js} +1 -1
  107. package/apps/ui/dist/server/assets/{cursor-db-B7agkAvM.js → cursor-db-CZnYy7aT.js} +196 -9
  108. package/apps/ui/dist/server/assets/{cursor-queries-f7DjBKSD.js → cursor-queries-NCIM0Nat.js} +12 -10
  109. package/apps/ui/dist/server/assets/{cursor-recovery-9bJLs7vG.js → cursor-recovery-CXpO8KcD.js} +2 -2
  110. package/apps/ui/dist/server/assets/{cursor-server-nPzojHN3.js → cursor-server-DNu52A3K.js} +71 -42
  111. package/apps/ui/dist/server/assets/cursor-threads._composerId-Ckn6ItHI.js +582 -0
  112. package/apps/ui/dist/server/assets/{cursor-threads._composerId-B3qcsh9C.js → cursor-threads._composerId-p9-ARAzc.js} +2 -2
  113. package/apps/ui/dist/server/assets/{cursor-transcript-2iL3KFSK.js → cursor-transcript-B7tGnqtn.js} +1 -1
  114. package/apps/ui/dist/server/assets/{cursor._workspaceKey-BL_CQyHQ.js → cursor._workspaceKey-CZuohIUL.js} +2 -2
  115. package/apps/ui/dist/server/assets/{cursor._workspaceKey-BhQeepXB.js → cursor._workspaceKey-DPp5JSjy.js} +11 -9
  116. package/apps/ui/dist/server/assets/{cursor.index-CsrdckZD.js → cursor.index-DkWT-mxw.js} +2 -2
  117. package/apps/ui/dist/server/assets/{delete-confirm-dialog-PCD7S0_M.js → delete-confirm-dialog-BcBNCxWB.js} +5 -1
  118. package/apps/ui/dist/server/assets/{empty-plugin-adapters-D3qLMPfC.js → empty-plugin-adapters-B3lHh1La.js} +1 -1
  119. package/apps/ui/dist/server/assets/{export-dialog-DaPlOGFT.js → export-dialog-D88ze9Gy.js} +54 -12
  120. package/apps/ui/dist/server/assets/kiro-db--fXrED_-.js +552 -0
  121. package/apps/ui/dist/server/assets/kiro-queries-CzNlM2ok.js +37 -0
  122. package/apps/ui/dist/server/assets/kiro-server-9WRxg2Au.js +72 -0
  123. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-CRY2c7YO.js +11 -0
  124. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-F1UlwxmR.js +449 -0
  125. package/apps/ui/dist/server/assets/kiro-sessions._sessionId-bvTulT7C.js +18 -0
  126. package/apps/ui/dist/server/assets/kiro-transcript-DoekQBaH.js +112 -0
  127. package/apps/ui/dist/server/assets/kiro-transcript-phase-CJG40nQg.js +27 -0
  128. package/apps/ui/dist/server/assets/kiro._workspaceKey-BDe9sQwo.js +11 -0
  129. package/apps/ui/dist/server/assets/kiro._workspaceKey-CJsjgNwO.js +28 -0
  130. package/apps/ui/dist/server/assets/kiro._workspaceKey-D_-4Qb7y.js +193 -0
  131. package/apps/ui/dist/server/assets/kiro.index-C__-UROk.js +11 -0
  132. package/apps/ui/dist/server/assets/kiro.index-CmTbqeYj.js +93 -0
  133. package/apps/ui/dist/server/assets/opencode-db-BM7KjOzc.js +397 -0
  134. package/apps/ui/dist/server/assets/opencode-queries-BeNYXnQv.js +50 -0
  135. package/apps/ui/dist/server/assets/opencode-server-BpQ_kRze.js +72 -0
  136. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-CGQ-t0vD.js +518 -0
  137. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-D8Q7in_Z.js +18 -0
  138. package/apps/ui/dist/server/assets/opencode-sessions._sessionId-DKOvi0lV.js +11 -0
  139. package/apps/ui/dist/server/assets/opencode-think-tags-CAoD-EcZ.js +87 -0
  140. package/apps/ui/dist/server/assets/opencode-transcript-BNTcGNym.js +141 -0
  141. package/apps/ui/dist/server/assets/opencode-transcript-phase-OqLkiQD0.js +32 -0
  142. package/apps/ui/dist/server/assets/opencode._workspaceKey-BdqcWHw1.js +11 -0
  143. package/apps/ui/dist/server/assets/opencode._workspaceKey-CfH96HTT.js +28 -0
  144. package/apps/ui/dist/server/assets/opencode._workspaceKey-DdbHPDrO.js +207 -0
  145. package/apps/ui/dist/server/assets/opencode.index-BbVzkJXP.js +11 -0
  146. package/apps/ui/dist/server/assets/opencode.index-Vh_Gq_1L.js +93 -0
  147. package/apps/ui/dist/server/assets/{projects._project-CqqUFr4l.js → projects._project-4io5LO0E.js} +5 -3
  148. package/apps/ui/dist/server/assets/{projects._project-DahGqNYS.js → projects._project-D6ZoGhJ8.js} +42 -12
  149. package/apps/ui/dist/server/assets/{projects.index-CkTeFWNU.js → projects.index-BkLiF2FF.js} +21 -7
  150. package/apps/ui/dist/server/assets/projects.index-DesYXwfi.js +14 -0
  151. package/apps/ui/dist/server/assets/route-search-ts4W9MJ9.js +38 -0
  152. package/apps/ui/dist/server/assets/router-Sac2DGk6.js +518 -0
  153. package/apps/ui/dist/server/assets/{routes-Xix3ZeSo.js → routes-Bsact1uB.js} +2 -2
  154. package/apps/ui/dist/server/assets/{routes-0x1U0IHq.js → routes-BzkJgq4W.js} +2 -2
  155. package/apps/ui/dist/server/assets/{shared-CPRNYIql.js → shared-DyhChtHf.js} +4 -1
  156. package/apps/ui/dist/server/assets/source-session-export-server-DNutCawb.js +38 -0
  157. package/apps/ui/dist/server/assets/start-B_HFwkkk.js +4 -0
  158. package/apps/ui/dist/server/assets/tabs-DkaChNVg.js +501 -0
  159. package/apps/ui/dist/server/assets/thread-transcript-stats-Dh34mt2u.js +45 -0
  160. package/apps/ui/dist/server/assets/threads._threadId-BeXEc4Lo.js +648 -0
  161. package/apps/ui/dist/server/assets/{threads._threadId-BLCkGW--.js → threads._threadId-Ci0S4mKU.js} +2 -2
  162. package/apps/ui/dist/server/assets/ui-export-files-BHLX9bhN.js +83 -0
  163. package/apps/ui/dist/server/server.js +141 -83
  164. package/package.json +28 -11
  165. package/src/lib/antigravity-db.ts +20 -13
  166. package/src/lib/claude-code-db.ts +655 -0
  167. package/src/lib/claude-code-exporter-types.ts +110 -0
  168. package/src/lib/claude-code-transcript-phase.ts +25 -0
  169. package/src/lib/claude-code-transcript.ts +180 -0
  170. package/src/lib/codex-analytics.ts +118 -18
  171. package/src/lib/codex-browser-db.ts +491 -56
  172. package/src/lib/codex-browser-export.ts +27 -71
  173. package/src/lib/codex-thread-cache.ts +17 -1
  174. package/src/lib/concurrency.ts +25 -0
  175. package/src/lib/cursor-db.ts +318 -7
  176. package/src/lib/cursor-exporter.ts +2 -2
  177. package/src/lib/kiro-db.ts +949 -0
  178. package/src/lib/kiro-exporter-types.ts +100 -0
  179. package/src/lib/kiro-transcript-phase.ts +41 -0
  180. package/src/lib/kiro-transcript.ts +115 -0
  181. package/src/lib/opencode-db.ts +610 -0
  182. package/src/lib/opencode-exporter-types.ts +129 -0
  183. package/src/lib/opencode-think-tags.ts +126 -0
  184. package/src/lib/opencode-transcript-phase.ts +50 -0
  185. package/src/lib/opencode-transcript.ts +194 -0
  186. package/src/lib/shared.ts +25 -0
  187. package/src/lib/ui-cache.ts +14 -1
  188. package/src/lib/ui-export-archive.ts +61 -0
  189. package/apps/ui/dist/client/assets/analytics-C83LcWNb.js +0 -1
  190. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-DkY8EEpK.js +0 -1
  191. package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-OraHuz8j.js +0 -1
  192. package/apps/ui/dist/client/assets/antigravity-keychain-panel-DnDcq1ge.js +0 -1
  193. package/apps/ui/dist/client/assets/antigravity._workspaceKey-CQaZscA5.js +0 -1
  194. package/apps/ui/dist/client/assets/antigravity._workspaceKey-DTs99obU.js +0 -1
  195. package/apps/ui/dist/client/assets/antigravity.index-DbJa715k.js +0 -1
  196. package/apps/ui/dist/client/assets/antigravity.index-P-rs6w5X.js +0 -1
  197. package/apps/ui/dist/client/assets/badge-wgTVp-aq.js +0 -1
  198. package/apps/ui/dist/client/assets/checkbox-BUx0Gkuf.js +0 -1
  199. package/apps/ui/dist/client/assets/cursor-threads._composerId-D0DFXt8t.js +0 -1
  200. package/apps/ui/dist/client/assets/cursor-threads._composerId-tFa6Cf6A.js +0 -1
  201. package/apps/ui/dist/client/assets/cursor._workspaceKey-Df4PfA2k.js +0 -1
  202. package/apps/ui/dist/client/assets/cursor._workspaceKey-DwrzEtnV.js +0 -1
  203. package/apps/ui/dist/client/assets/cursor.index-CNBf4ZiR.js +0 -1
  204. package/apps/ui/dist/client/assets/cursor.index-DP9Hy8X6.js +0 -2
  205. package/apps/ui/dist/client/assets/delete-confirm-dialog-CPlNsLhM.js +0 -11
  206. package/apps/ui/dist/client/assets/dist-Ds3kS91l.js +0 -1
  207. package/apps/ui/dist/client/assets/download-DLuPnxpV.js +0 -1
  208. package/apps/ui/dist/client/assets/dropdown-menu-lFk6zjoL.js +0 -1
  209. package/apps/ui/dist/client/assets/es2015-D-H_iZF6.js +0 -41
  210. package/apps/ui/dist/client/assets/export-dialog-CyqyvwiP.js +0 -1
  211. package/apps/ui/dist/client/assets/formatters-DbCKP02D.js +0 -1
  212. package/apps/ui/dist/client/assets/index-C-ZPpKJ0.js +0 -22
  213. package/apps/ui/dist/client/assets/json-panel-BsngvucB.js +0 -1
  214. package/apps/ui/dist/client/assets/metadata-section-Dtl8dNag.js +0 -1
  215. package/apps/ui/dist/client/assets/metric-card-DNzR1Rne.js +0 -1
  216. package/apps/ui/dist/client/assets/page-header-dha_O7ZL.js +0 -1
  217. package/apps/ui/dist/client/assets/projects._project-B7HBhbXv.js +0 -1
  218. package/apps/ui/dist/client/assets/projects._project-DHVvuT7A.js +0 -1
  219. package/apps/ui/dist/client/assets/projects.index-BUUtx2AZ.js +0 -1
  220. package/apps/ui/dist/client/assets/projects.index-BojAe1Y4.js +0 -3
  221. package/apps/ui/dist/client/assets/refresh-ccw-B-ASKHtx.js +0 -1
  222. package/apps/ui/dist/client/assets/reload-error-panel-DD8M1BIY.js +0 -1
  223. package/apps/ui/dist/client/assets/routes-q7bzFp35.js +0 -1
  224. package/apps/ui/dist/client/assets/scroll-text-TvHyiJ_N.js +0 -1
  225. package/apps/ui/dist/client/assets/select-BFv1HMiT.js +0 -1
  226. package/apps/ui/dist/client/assets/settings-CvegTo4F.js +0 -1
  227. package/apps/ui/dist/client/assets/styles-Ch0r3kMZ.css +0 -1
  228. package/apps/ui/dist/client/assets/text-document-panel-D7Rws41o.js +0 -1
  229. package/apps/ui/dist/client/assets/text-filter-2q5pEoZh.js +0 -2
  230. package/apps/ui/dist/client/assets/threads._threadId-LpZVUlPq.js +0 -7
  231. package/apps/ui/dist/client/assets/threads._threadId-MSmNIBkq.js +0 -1
  232. package/apps/ui/dist/client/assets/useMutation-BOPJU9e0.js +0 -1
  233. package/apps/ui/dist/client/assets/useQuery-CbxZiVGF.js +0 -1
  234. package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-zvGzK-Yx.js +0 -229
  235. package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-JEhx-f2R.js +0 -212
  236. package/apps/ui/dist/server/assets/cursor-threads._composerId-BK3iW-3e.js +0 -218
  237. package/apps/ui/dist/server/assets/json-panel-RYsxWFae.js +0 -16
  238. package/apps/ui/dist/server/assets/metadata-section-D6Lbc7D6.js +0 -54
  239. package/apps/ui/dist/server/assets/router-K0m7dK4T.js +0 -394
  240. package/apps/ui/dist/server/assets/start-bX7bXjzw.js +0 -4
  241. package/apps/ui/dist/server/assets/text-document-panel-D8JbQWAn.js +0 -23
  242. package/apps/ui/dist/server/assets/threads._threadId-LjgsGUh-.js +0 -1052
@@ -1,16 +1,20 @@
1
1
  import { t as createServerFn } from "../server.js";
2
- import { t as createServerRpc } from "./createServerRpc-Cg-Zr1rq.js";
3
- import { a as cleanInlineTitle, c as formatInlineLiteral, d as readJsonlObjects, h as renderSection, i as cleanExtractedText, l as formatModelLabel, m as renderMetadataBlock, n as asObject, o as createExportWriteStream, p as renderDocumentTitle, r as asString, s as finalizeExportWriteStream, t as asNumber, u as getPortablePathBasename } from "./shared-CPRNYIql.js";
2
+ import { t as createServerRpc } from "./createServerRpc-CF_DEwnm.js";
3
+ import { a as sanitizeExportFileName, n as ensureUiExportDir, o as zipExportDirectory, r as getExportMimeType, s as zipExportFile, t as buildUiExportDownloadUrl } from "./ui-export-files-BHLX9bhN.js";
4
+ import { a as cleanExtractedText, c as finalizeExportWriteStream, d as getPortablePathBasename, f as readJsonlObjects$1, g as renderSection, h as renderMetadataBlock, i as asString, l as formatInlineLiteral, m as renderDocumentTitle, n as asNumber, o as cleanInlineTitle, r as asObject, s as createExportWriteStream, u as formatModelLabel } from "./shared-DyhChtHf.js";
5
+ import { t as mapWithConcurrency } from "./concurrency-VXtYvlGh.js";
4
6
  import { t as isRetryableSqliteError } from "./sqlite-error-LZDrnxdd.js";
5
7
  import { t as applyPathTransforms } from "./path-transforms-DL2IwtYd.js";
6
8
  import { finished } from "node:stream/promises";
7
9
  import { z } from "zod";
8
- import { Database } from "bun:sqlite";
10
+ import { createHash, randomUUID } from "node:crypto";
9
11
  import { copyFile, mkdir, mkdtemp, readdir, rename, rm, stat, utimes } from "node:fs/promises";
10
12
  import os from "node:os";
11
13
  import path from "node:path";
12
- import { createReadStream } from "node:fs";
13
- import { createHash, randomUUID } from "node:crypto";
14
+ import { Database, constants } from "bun:sqlite";
15
+ import { closeSync, createReadStream, openSync, readSync, readdirSync, statSync } from "node:fs";
16
+ import { StringDecoder } from "node:string_decoder";
17
+ import { pathToFileURL } from "node:url";
14
18
  //#region ../../src/lib/codex-exporter-types.ts
15
19
  var DEFAULT_CODEX_DIR = path.join(os.homedir(), ".codex");
16
20
  var DEFAULT_DB_PATH = path.join(DEFAULT_CODEX_DIR, "state_5.sqlite");
@@ -55,7 +59,7 @@ var parseCodexTranscriptFile = async (sessionFile, options = {}) => {
55
59
  const maxEvents = options.maxEvents ?? Number.POSITIVE_INFINITY;
56
60
  const maxTurnContexts = options.maxTurnContexts ?? Number.POSITIVE_INFINITY;
57
61
  let sequence = 0;
58
- for await (const parsed of readJsonlObjects(sessionFile)) {
62
+ for await (const parsed of readJsonlObjects$1(sessionFile)) {
59
63
  captureSessionMeta$1(parsed, sessionMeta);
60
64
  if (asString(parsed.type) === "turn_context") {
61
65
  if (turnContexts.length < maxTurnContexts) captureTurnContext(parsed, turnContexts);
@@ -373,6 +377,16 @@ var toCachePath = (key) => {
373
377
  var hashCacheKeyParts = (...parts) => {
374
378
  return createHash("sha1").update(parts.join("|")).digest("hex");
375
379
  };
380
+ var hashCacheKeyPartsIterable = (parts) => {
381
+ const hash = createHash("sha1");
382
+ for (const part of parts) {
383
+ hash.update(String(part.length));
384
+ hash.update(":");
385
+ hash.update(part);
386
+ hash.update(";");
387
+ }
388
+ return hash.digest("hex");
389
+ };
376
390
  var getFileFingerprint = async (filePath) => {
377
391
  const metadata = await stat(filePath);
378
392
  return `${filePath}:${metadata.size}:${metadata.mtimeMs}`;
@@ -390,7 +404,8 @@ var getCachedJson = async (key) => {
390
404
  return null;
391
405
  }
392
406
  if (parsed && typeof parsed === "object" && "version" in parsed && parsed.version === CACHE_ENVELOPE_VERSION && "value" in parsed) return parsed.value;
393
- return parsed;
407
+ await rm(filePath, { force: true });
408
+ return null;
394
409
  };
395
410
  var setCachedJson = async (key, value) => {
396
411
  await ensureCacheDir();
@@ -420,12 +435,24 @@ var invalidateCacheByPrefix = async (...prefixes) => {
420
435
  //#endregion
421
436
  //#region ../../src/lib/codex-thread-cache.ts
422
437
  var LARGE_THREAD_SIZE_BYTES = 100 * 1024 * 1024;
438
+ var isMissingFileError$2 = (error) => {
439
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
440
+ };
423
441
  var getCachedParsedCodexTranscript = async (sessionFile) => {
424
442
  const fingerprint = await getFileFingerprint(sessionFile);
425
443
  return withCachedJson(`thread-${hashCacheKeyParts(path.basename(sessionFile), fingerprint)}`, async () => parseCodexTranscriptFile(sessionFile));
426
444
  };
427
445
  var getThreadRolloutLoadState = async (sessionFile, largeTranscriptThresholdBytes = LARGE_THREAD_SIZE_BYTES) => {
428
- const metadata = await stat(sessionFile);
446
+ let metadata;
447
+ try {
448
+ metadata = await stat(sessionFile);
449
+ } catch (error) {
450
+ if (isMissingFileError$2(error)) return {
451
+ fileSizeBytes: null,
452
+ shouldDeferTranscriptLoad: false
453
+ };
454
+ throw error;
455
+ }
429
456
  return {
430
457
  fileSizeBytes: metadata.size,
431
458
  shouldDeferTranscriptLoad: metadata.size > largeTranscriptThresholdBytes
@@ -483,6 +510,13 @@ var runWithSqliteRetry = ({ action, delaysMs = DEFAULT_RETRY_DELAYS_MS, sleep =
483
510
  var SQLITE_DELETE_BATCH_SIZE = 400;
484
511
  var SESSION_FILE_DELETE_CONCURRENCY = 16;
485
512
  var THREAD_LIST_IO_CONCURRENCY = 8;
513
+ var CODEX_READONLY_DB_OPEN_FLAGS = constants.SQLITE_OPEN_READONLY | constants.SQLITE_OPEN_URI;
514
+ var JSONL_READ_CHUNK_BYTES = 64 * 1024;
515
+ var SESSION_META_READ_LIMIT_BYTES = 4 * 1024 * 1024;
516
+ var THREAD_ID_PATTERN = /([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/iu;
517
+ var isSqliteCantOpenError = (error) => {
518
+ return error.code === "SQLITE_CANTOPEN";
519
+ };
486
520
  var chunkValues = (values, chunkSize) => {
487
521
  const chunks = [];
488
522
  for (let index = 0; index < values.length; index += chunkSize) chunks.push(values.slice(index, index + chunkSize));
@@ -492,29 +526,16 @@ var isPromiseLike = (value) => {
492
526
  if (typeof value !== "object" && typeof value !== "function" || value === null) return false;
493
527
  return "then" in value && typeof value.then === "function";
494
528
  };
495
- var mapWithConcurrency = async (values, limit, mapper) => {
496
- const results = new Array(values.length);
497
- let nextIndex = 0;
498
- const worker = async () => {
499
- while (true) {
500
- const currentIndex = nextIndex;
501
- nextIndex += 1;
502
- if (currentIndex >= values.length) return;
503
- results[currentIndex] = await mapper(values[currentIndex], currentIndex);
504
- }
505
- };
506
- await Promise.all(Array.from({ length: Math.min(limit, values.length) }, () => worker()));
507
- return results;
508
- };
509
- var openReadonlyDb = (dbPath, busyTimeoutMs) => {
529
+ var openReadonlyDb = (dbPath) => {
510
530
  const db = new Database(dbPath, { readonly: true });
511
531
  try {
512
- db.exec(`PRAGMA busy_timeout = ${busyTimeoutMs}`);
532
+ db.query("SELECT name FROM sqlite_master LIMIT 1").get();
513
533
  return db;
514
534
  } catch (error) {
515
535
  db.close();
516
- throw error;
536
+ if (!isSqliteCantOpenError(error)) throw error;
517
537
  }
538
+ return new Database(`${pathToFileURL(dbPath).href}?immutable=1`, CODEX_READONLY_DB_OPEN_FLAGS);
518
539
  };
519
540
  var openWritableDb = (dbPath, busyTimeoutMs) => {
520
541
  const db = new Database(dbPath);
@@ -550,7 +571,7 @@ var parseJsonSafely$1 = (value) => {
550
571
  };
551
572
  var withReadonlyDb = (dbPath, callback) => {
552
573
  return runWithSqliteRetry({ action: () => {
553
- const db = openReadonlyDb(dbPath, 5e3);
574
+ const db = openReadonlyDb(dbPath);
554
575
  try {
555
576
  const result = callback(db);
556
577
  if (isPromiseLike(result)) throw new Error("Database callbacks must be synchronous");
@@ -581,9 +602,7 @@ var resolveCodexThreadDbPath = () => {
581
602
  path.join(os.homedir(), ".codex", "state_5.sqlite")
582
603
  ];
583
604
  for (const candidate of candidates) try {
584
- runWithSqliteRetry({ action: () => {
585
- return openReadonlyDb(candidate, 1500);
586
- } }).close();
605
+ if (!statSync(candidate).isFile()) continue;
587
606
  return candidate;
588
607
  } catch {}
589
608
  throw new Error(`Unable to open Codex thread database. Tried: ${candidates.join(", ")}`);
@@ -593,6 +612,256 @@ var readAllThreads = (dbPath) => {
593
612
  return db.query("SELECT * FROM threads ORDER BY COALESCE(updated_at_ms, updated_at * 1000) DESC, id DESC").all();
594
613
  });
595
614
  };
615
+ var resolveCodexDirFromDbPath$1 = (dbPath) => {
616
+ const dbDir = path.dirname(dbPath);
617
+ return path.basename(dbDir) === "sqlite" ? path.dirname(dbDir) : dbDir;
618
+ };
619
+ var parseJsonlObject = (line) => {
620
+ try {
621
+ return JSON.parse(line);
622
+ } catch {
623
+ return null;
624
+ }
625
+ };
626
+ var emitJsonlLine = (line, onRecord) => {
627
+ const trimmed = line.trim();
628
+ const parsed = trimmed ? parseJsonlObject(trimmed) : null;
629
+ if (parsed) onRecord(parsed);
630
+ };
631
+ var emitCompleteJsonlLines = (text, onRecord) => {
632
+ const lines = text.split(/\r?\n/u);
633
+ const pending = lines.pop() ?? "";
634
+ for (const line of lines) emitJsonlLine(line, onRecord);
635
+ return pending;
636
+ };
637
+ var readJsonlObjects = (filePath, onRecord) => {
638
+ let descriptor = null;
639
+ try {
640
+ if (!statSync(filePath).isFile()) return;
641
+ descriptor = openSync(filePath, "r");
642
+ const buffer = Buffer.alloc(JSONL_READ_CHUNK_BYTES);
643
+ const decoder = new StringDecoder("utf8");
644
+ let position = 0;
645
+ let pending = "";
646
+ while (true) {
647
+ const bytesRead = readSync(descriptor, buffer, 0, buffer.length, position);
648
+ if (bytesRead === 0) break;
649
+ position += bytesRead;
650
+ pending += decoder.write(buffer.subarray(0, bytesRead));
651
+ pending = emitCompleteJsonlLines(pending, onRecord);
652
+ }
653
+ emitJsonlLine(pending + decoder.end(), onRecord);
654
+ } catch {
655
+ return;
656
+ } finally {
657
+ if (descriptor !== null) closeSync(descriptor);
658
+ }
659
+ };
660
+ var collectJsonlObjects = (filePath) => {
661
+ const records = [];
662
+ readJsonlObjects(filePath, (record) => {
663
+ records.push(record);
664
+ });
665
+ return records;
666
+ };
667
+ var readSessionIndexEntries = (codexDir) => {
668
+ return collectJsonlObjects(path.join(codexDir, "session_index.jsonl")).filter((entry) => typeof entry.id === "string" && entry.id.length > 0);
669
+ };
670
+ var collectSessionFilesByThreadId = (sessionsDir) => {
671
+ const sessionFiles = /* @__PURE__ */ new Map();
672
+ const visit = (directory) => {
673
+ const entries = (() => {
674
+ try {
675
+ return readdirSync(directory, { withFileTypes: true });
676
+ } catch {
677
+ return null;
678
+ }
679
+ })();
680
+ if (!entries) return;
681
+ for (const entry of entries) {
682
+ const entryPath = path.join(directory, entry.name);
683
+ if (entry.isDirectory()) {
684
+ visit(entryPath);
685
+ continue;
686
+ }
687
+ if (!entry.isFile()) continue;
688
+ const threadId = THREAD_ID_PATTERN.exec(entry.name)?.[1];
689
+ if (threadId && !sessionFiles.has(threadId)) sessionFiles.set(threadId, entryPath);
690
+ }
691
+ };
692
+ visit(sessionsDir);
693
+ return sessionFiles;
694
+ };
695
+ var readSessionMetaLine = (sessionFile) => {
696
+ let descriptor = null;
697
+ try {
698
+ descriptor = openSync(sessionFile, "r");
699
+ const chunks = [];
700
+ let totalBytes = 0;
701
+ while (totalBytes < SESSION_META_READ_LIMIT_BYTES) {
702
+ const buffer = Buffer.alloc(Math.min(64 * 1024, SESSION_META_READ_LIMIT_BYTES - totalBytes));
703
+ const bytesRead = readSync(descriptor, buffer, 0, buffer.length, totalBytes);
704
+ if (bytesRead === 0) break;
705
+ chunks.push(buffer.subarray(0, bytesRead));
706
+ totalBytes += bytesRead;
707
+ if (buffer.subarray(0, bytesRead).includes(10)) break;
708
+ }
709
+ return Buffer.concat(chunks).toString("utf8").split(/\r?\n/u)[0]?.trim() || null;
710
+ } catch {
711
+ return null;
712
+ } finally {
713
+ if (descriptor !== null) closeSync(descriptor);
714
+ }
715
+ };
716
+ var readFallbackSessionMeta = (sessionFile) => {
717
+ const line = readSessionMetaLine(sessionFile);
718
+ if (!line) return null;
719
+ try {
720
+ const record = JSON.parse(line);
721
+ return record.type === "session_meta" && record.payload ? record.payload : null;
722
+ } catch {
723
+ return null;
724
+ }
725
+ };
726
+ var parseIsoMs = (value, fallback) => {
727
+ if (!value) return fallback;
728
+ const parsed = Date.parse(value);
729
+ return Number.isFinite(parsed) ? parsed : fallback;
730
+ };
731
+ var stringOrNull = (value) => typeof value === "string" && value.length > 0 ? value : null;
732
+ var numberOrNull = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
733
+ var objectOrNull = (value) => {
734
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
735
+ };
736
+ var isFallbackSubagent = (sessionMeta) => {
737
+ return Boolean(sessionMeta.thread_source === "subagent" || stringOrNull(sessionMeta.parent_thread_id) || stringOrNull(sessionMeta.forked_from_id));
738
+ };
739
+ var readFallbackRolloutStats = (sessionFile) => {
740
+ let model = null;
741
+ let tokensUsed = 0;
742
+ readJsonlObjects(sessionFile, (record) => {
743
+ const payload = objectOrNull(record.payload);
744
+ if (!payload) return;
745
+ if (record.type === "turn_context") {
746
+ model = stringOrNull(payload.model) ?? model;
747
+ return;
748
+ }
749
+ const payloadType = stringOrNull(payload.type);
750
+ if (payloadType === "message" || payloadType === "agent_message") {
751
+ model = stringOrNull(payload.model) ?? model;
752
+ return;
753
+ }
754
+ if (payloadType !== "token_count") return;
755
+ tokensUsed = numberOrNull(objectOrNull(objectOrNull(payload.info)?.total_token_usage)?.total_tokens) ?? tokensUsed;
756
+ });
757
+ return {
758
+ model,
759
+ tokensUsed
760
+ };
761
+ };
762
+ var buildFallbackThreadRow = (entry, sessionFile, sessionMeta, rolloutStats) => {
763
+ const cwd = stringOrNull(sessionMeta.cwd);
764
+ if (!cwd) return null;
765
+ let mtimeMs = Date.now();
766
+ try {
767
+ mtimeMs = statSync(sessionFile).mtimeMs;
768
+ } catch {}
769
+ const updatedAtMs = parseIsoMs(entry.updated_at, mtimeMs);
770
+ const createdAtMs = parseIsoMs(sessionMeta.timestamp, updatedAtMs);
771
+ const title = entry.thread_name?.trim() || path.basename(sessionFile, ".jsonl");
772
+ const source = stringOrNull(sessionMeta.source) ?? "session_file";
773
+ return {
774
+ agent_nickname: sessionMeta.agent_nickname ?? null,
775
+ agent_path: sessionMeta.agent_path ?? null,
776
+ agent_role: sessionMeta.agent_role ?? null,
777
+ approval_mode: "unknown",
778
+ archived: 0,
779
+ archived_at: null,
780
+ cli_version: sessionMeta.cli_version ?? "",
781
+ created_at: Math.floor(createdAtMs / 1e3),
782
+ created_at_ms: Math.floor(createdAtMs),
783
+ cwd,
784
+ first_user_message: title,
785
+ git_branch: null,
786
+ git_origin_url: null,
787
+ git_sha: null,
788
+ has_user_event: sessionMeta.thread_source === "user" ? 1 : 0,
789
+ id: entry.id,
790
+ memory_mode: "enabled",
791
+ model: rolloutStats.model,
792
+ model_provider: sessionMeta.model_provider ?? "unknown",
793
+ preview: title,
794
+ reasoning_effort: null,
795
+ rollout_path: sessionFile,
796
+ sandbox_policy: "{}",
797
+ source,
798
+ thread_source: sessionMeta.thread_source ?? null,
799
+ title,
800
+ tokens_used: rolloutStats.tokensUsed,
801
+ updated_at: Math.floor(updatedAtMs / 1e3),
802
+ updated_at_ms: Math.floor(updatedAtMs)
803
+ };
804
+ };
805
+ var readFallbackThreadRows = (dbPath, existingThreadIds, projectName = null, options = {}) => {
806
+ const codexDir = resolveCodexDirFromDbPath$1(dbPath);
807
+ const sessionFilesByThreadId = collectSessionFilesByThreadId(path.join(codexDir, "sessions"));
808
+ const fallbackThreads = [];
809
+ for (const entry of readSessionIndexEntries(codexDir)) {
810
+ if (existingThreadIds.has(entry.id)) continue;
811
+ const sessionFile = sessionFilesByThreadId.get(entry.id);
812
+ if (!sessionFile) continue;
813
+ const sessionMeta = readFallbackSessionMeta(sessionFile);
814
+ if (!sessionMeta) continue;
815
+ if (!options.includeSubagents && isFallbackSubagent(sessionMeta)) continue;
816
+ const fallbackThread = buildFallbackThreadRow(entry, sessionFile, sessionMeta, readFallbackRolloutStats(sessionFile));
817
+ if (!fallbackThread || projectName && getPortablePathBasename(fallbackThread.cwd) !== projectName) continue;
818
+ fallbackThreads.push(fallbackThread);
819
+ }
820
+ return fallbackThreads;
821
+ };
822
+ var mergeFallbackThreadRows = (dbPath, threads, projectName = null) => {
823
+ const threadIds = new Set(threads.map((thread) => thread.id));
824
+ return [...threads, ...readFallbackThreadRows(dbPath, threadIds, projectName)].sort((left, right) => {
825
+ const updatedDifference = toTimestampMs(right) - toTimestampMs(left);
826
+ if (updatedDifference !== 0) return updatedDifference;
827
+ return right.id.localeCompare(left.id);
828
+ });
829
+ };
830
+ var applyRolloutActivityTimestamps = (threads) => {
831
+ return threads.map((thread) => {
832
+ let rolloutUpdatedAtMs = toTimestampMs(thread);
833
+ try {
834
+ rolloutUpdatedAtMs = Math.max(rolloutUpdatedAtMs, statSync(thread.rollout_path).mtimeMs);
835
+ } catch {}
836
+ if (rolloutUpdatedAtMs <= toTimestampMs(thread)) return thread;
837
+ return {
838
+ ...thread,
839
+ updated_at: Math.floor(rolloutUpdatedAtMs / 1e3),
840
+ updated_at_ms: Math.floor(rolloutUpdatedAtMs)
841
+ };
842
+ }).sort((left, right) => {
843
+ const updatedDifference = toTimestampMs(right) - toTimestampMs(left);
844
+ if (updatedDifference !== 0) return updatedDifference;
845
+ return right.id.localeCompare(left.id);
846
+ });
847
+ };
848
+ var buildDashboardRecentThreads = (threads) => {
849
+ const bestThreadByProject = /* @__PURE__ */ new Map();
850
+ for (const thread of threads) {
851
+ const project = getPortablePathBasename(thread.cwd);
852
+ if (!project) continue;
853
+ const current = bestThreadByProject.get(project);
854
+ if (!current || toTimestampMs(thread) > toTimestampMs(current)) bestThreadByProject.set(project, thread);
855
+ }
856
+ return [...bestThreadByProject.values()].sort((left, right) => {
857
+ const updatedDifference = toTimestampMs(right) - toTimestampMs(left);
858
+ if (updatedDifference !== 0) return updatedDifference;
859
+ return right.id.localeCompare(left.id);
860
+ }).slice(0, 5).map((thread) => ({
861
+ project: getPortablePathBasename(thread.cwd),
862
+ thread: compactThreadListRow(thread)
863
+ }));
864
+ };
596
865
  var filterThreadsByProject = (threads, projectName) => {
597
866
  if (!projectName) return threads;
598
867
  return threads.filter((thread) => getPortablePathBasename(thread.cwd) === projectName);
@@ -697,7 +966,7 @@ var deleteThreadSessionFiles = async (sessionFiles) => {
697
966
  return uniqueSessionFiles;
698
967
  };
699
968
  var listCodexProjects = (dbPath) => {
700
- return mapProjectSummaries(buildProjectSummaryMap(readAllThreads(dbPath)));
969
+ return mapProjectSummaries(buildProjectSummaryMap(applyRolloutActivityTimestamps(mergeFallbackThreadRows(dbPath, readAllThreads(dbPath)))));
701
970
  };
702
971
  var compactThreadListRow = (thread) => {
703
972
  return {
@@ -707,8 +976,19 @@ var compactThreadListRow = (thread) => {
707
976
  };
708
977
  };
709
978
  var listProjectThreads = async (dbPath, projectName, options = {}) => {
710
- return (await mapWithConcurrency(filterThreadsByProject(readAllThreads(dbPath), projectName), THREAD_LIST_IO_CONCURRENCY, async (thread) => {
979
+ return (await mapWithConcurrency(applyRolloutActivityTimestamps(mergeFallbackThreadRows(dbPath, filterThreadsByProject(readAllThreads(dbPath), projectName), projectName)), THREAD_LIST_IO_CONCURRENCY, async (thread) => {
711
980
  const rollout = await getThreadRolloutLoadState(thread.rollout_path, options.largeTranscriptThresholdBytes);
981
+ if (rollout.fileSizeBytes === null) return {
982
+ project: projectName,
983
+ rolloutSizeBytes: null,
984
+ stats: {
985
+ deferred: false,
986
+ execCommandCount: 0,
987
+ toolCallCount: 0,
988
+ webSearchEventCount: 0
989
+ },
990
+ thread: compactThreadListRow(thread)
991
+ };
712
992
  if (rollout.shouldDeferTranscriptLoad) return {
713
993
  project: projectName,
714
994
  rolloutSizeBytes: rollout.fileSizeBytes,
@@ -737,10 +1017,11 @@ var listProjectThreads = async (dbPath, projectName, options = {}) => {
737
1017
  var getThreadBrowseData = (dbPath, threadId) => {
738
1018
  return withReadonlyDb(dbPath, (db) => {
739
1019
  const existingTableNames = getExistingTableNames(db);
740
- const thread = db.query("SELECT * FROM threads WHERE id = ? LIMIT 1").get(threadId);
1020
+ const dbThread = db.query("SELECT * FROM threads WHERE id = ? LIMIT 1").get(threadId);
1021
+ const thread = dbThread ?? readFallbackThreadRows(dbPath, /* @__PURE__ */ new Set(), null, { includeSubagents: true }).find((fallbackThread) => fallbackThread.id === threadId) ?? null;
741
1022
  if (!thread) throw new Error(`Thread not found: ${threadId}`);
742
1023
  return {
743
- dynamicTools: (existingTableNames.has("thread_dynamic_tools") ? db.query("SELECT thread_id, position, name, description, input_schema, defer_loading, namespace FROM thread_dynamic_tools WHERE thread_id = ? ORDER BY position ASC").all(threadId) : []).map((row) => parseDynamicToolRow(row)),
1024
+ dynamicTools: (dbThread && existingTableNames.has("thread_dynamic_tools") ? db.query("SELECT thread_id, position, name, description, input_schema, defer_loading, namespace FROM thread_dynamic_tools WHERE thread_id = ? ORDER BY position ASC").all(threadId) : []).map((row) => parseDynamicToolRow(row)),
744
1025
  project: getPortablePathBasename(thread.cwd),
745
1026
  relations: getRelationsForThread(db, threadId, existingTableNames),
746
1027
  thread
@@ -748,7 +1029,7 @@ var getThreadBrowseData = (dbPath, threadId) => {
748
1029
  });
749
1030
  };
750
1031
  var getCodexDashboardSummary = (dbPath) => {
751
- const threads = readAllThreads(dbPath);
1032
+ const threads = applyRolloutActivityTimestamps(mergeFallbackThreadRows(dbPath, readAllThreads(dbPath)));
752
1033
  const projects = mapProjectSummaries(buildProjectSummaryMap(threads));
753
1034
  const threadsWithRelations = withReadonlyDb(dbPath, (db) => {
754
1035
  if (!getExistingTableNames(db).has("thread_spawn_edges")) return 0;
@@ -758,10 +1039,7 @@ var getCodexDashboardSummary = (dbPath) => {
758
1039
  return {
759
1040
  activeThreads: threads.filter((thread) => !thread.archived).length,
760
1041
  archivedThreads: threads.filter((thread) => Boolean(thread.archived)).length,
761
- recentThreads: threads.slice(0, 5).filter((thread) => Boolean(getPortablePathBasename(thread.cwd))).map((thread) => ({
762
- project: getPortablePathBasename(thread.cwd),
763
- thread: compactThreadListRow(thread)
764
- })),
1042
+ recentThreads: buildDashboardRecentThreads(threads),
765
1043
  threadsWithRelations,
766
1044
  topProjectsByThreadCount: [...projects].sort((left, right) => {
767
1045
  if (left.threadCount !== right.threadCount) return right.threadCount - left.threadCount;
@@ -828,13 +1106,16 @@ var deleteCodexProject = async (dbPath, projectName, options = {}) => {
828
1106
  }
829
1107
  };
830
1108
  var listScopedThreads = (dbPath, projectName) => {
831
- return filterThreadsByProject(readAllThreads(dbPath), projectName);
1109
+ return mergeFallbackThreadRows(dbPath, filterThreadsByProject(readAllThreads(dbPath), projectName), projectName);
832
1110
  };
833
1111
  var invalidateCodexUiCaches = async () => {
834
1112
  await invalidateCacheByPrefix("analytics-", "thread-");
835
1113
  };
836
- //#endregion
837
- //#region ../../src/lib/codex-analytics.ts
1114
+ var resolveAnalyticsTranscriptConcurrency = (configuredValue = process.env.SPIRACHA_ANALYTICS_TRANSCRIPT_CONCURRENCY) => {
1115
+ const parsed = Number(configuredValue);
1116
+ if (!Number.isInteger(parsed) || parsed < 1) return 8;
1117
+ return parsed;
1118
+ };
838
1119
  var roundToTwoDecimals = (value) => {
839
1120
  return Number(value.toFixed(2));
840
1121
  };
@@ -870,20 +1151,68 @@ var buildModelsByTokens = (threads) => {
870
1151
  return left.model.localeCompare(right.model);
871
1152
  });
872
1153
  };
873
- var buildAnalyticsCacheKey = async (dbPath, threads, project) => {
874
- const dbFingerprint = await getFileFingerprint(dbPath);
875
- const rolloutFingerprints = await Promise.all(threads.map((thread) => getFileFingerprint(thread.rollout_path)));
876
- return `analytics-${hashCacheKeyParts(dbFingerprint, project ?? "all", ...rolloutFingerprints)}`;
1154
+ var timestampSignature = (thread) => {
1155
+ return String(thread.updated_at_ms ?? thread.updated_at * 1e3);
1156
+ };
1157
+ var threadMetadataCacheKeyParts = (thread) => [
1158
+ thread.id,
1159
+ thread.rollout_path,
1160
+ timestampSignature(thread),
1161
+ String(thread.created_at_ms ?? thread.created_at * 1e3),
1162
+ String(thread.tokens_used),
1163
+ String(thread.archived),
1164
+ String(thread.archived_at ?? ""),
1165
+ thread.cwd,
1166
+ thread.model ?? "",
1167
+ thread.model_provider,
1168
+ thread.cli_version,
1169
+ thread.title,
1170
+ thread.preview
1171
+ ];
1172
+ var buildCodexAnalyticsCacheKey = (dbPath, threads, project) => {
1173
+ return `analytics-${hashCacheKeyPartsIterable((function* () {
1174
+ yield "v2";
1175
+ yield dbPath;
1176
+ yield project ?? "all";
1177
+ yield String(threads.length);
1178
+ for (const thread of threads) yield* threadMetadataCacheKeyParts(thread);
1179
+ })())}`;
1180
+ };
1181
+ var buildThreadAnalyticsCacheKey = (thread) => {
1182
+ return `thread-analytics-${hashCacheKeyParts("v1", ...threadMetadataCacheKeyParts(thread))}`;
1183
+ };
1184
+ var parseThreadAnalyticsFile = async (sessionFile) => {
1185
+ const toolNames = [];
1186
+ let hasWebSearch = false;
1187
+ for await (const parsed of readJsonlObjects$1(sessionFile)) {
1188
+ if (parsed.type !== "response_item") continue;
1189
+ const payload = asObject(parsed.payload);
1190
+ if (!payload) continue;
1191
+ const payloadType = asString(payload.type);
1192
+ if (payloadType === "function_call") {
1193
+ toolNames.push(asString(payload.name) ?? "unknown");
1194
+ continue;
1195
+ }
1196
+ if (payloadType === "web_search_call" || payloadType === "web_search_end") hasWebSearch = true;
1197
+ }
1198
+ return {
1199
+ hasWebSearch,
1200
+ toolNames
1201
+ };
1202
+ };
1203
+ var getCachedThreadAnalytics = async (thread) => {
1204
+ return withCachedJson(buildThreadAnalyticsCacheKey(thread), () => parseThreadAnalyticsFile(thread.rollout_path));
877
1205
  };
878
- var computeCodexAnalytics = async (threads) => {
1206
+ var computeCodexAnalyticsFromThreads = async (threads, options = {}) => {
879
1207
  const totalTokens = threads.reduce((sum, thread) => sum + thread.tokens_used, 0);
880
1208
  const projectNames = new Set(threads.map((thread) => getPortablePathBasename(thread.cwd)).filter(Boolean));
881
1209
  const toolUsage = /* @__PURE__ */ new Map();
882
- const transcripts = await Promise.all(threads.map((thread) => getCachedParsedCodexTranscript(thread.rollout_path)));
883
1210
  let threadsWithWebSearch = 0;
884
- for (const transcript of transcripts) {
885
- if (transcript.stats.webSearchEventCount > 0) threadsWithWebSearch += 1;
886
- for (const event of transcript.events) if (event.kind === "tool_call") incrementCount(toolUsage, event.name);
1211
+ const loadThreadAnalytics = options.loadThreadAnalytics ?? getCachedThreadAnalytics;
1212
+ const threadAnalytics = await mapWithConcurrency(threads, options.transcriptConcurrency ?? resolveAnalyticsTranscriptConcurrency(), (thread) => loadThreadAnalytics(thread));
1213
+ for (const analytics of threadAnalytics) {
1214
+ if (analytics.hasWebSearch) threadsWithWebSearch += 1;
1215
+ for (const toolName of analytics.toolNames) incrementCount(toolUsage, toolName);
887
1216
  }
888
1217
  return {
889
1218
  modelsByTokens: buildModelsByTokens(threads),
@@ -904,7 +1233,7 @@ var computeCodexAnalytics = async (threads) => {
904
1233
  };
905
1234
  var getCodexAnalytics = async (input) => {
906
1235
  const threads = listScopedThreads(input.dbPath, input.project);
907
- return withCachedJson(await buildAnalyticsCacheKey(input.dbPath, threads, input.project), async () => computeCodexAnalytics(threads));
1236
+ return withCachedJson(buildCodexAnalyticsCacheKey(input.dbPath, threads, input.project), async () => computeCodexAnalyticsFromThreads(threads, { transcriptConcurrency: input.transcriptConcurrency }));
908
1237
  };
909
1238
  //#endregion
910
1239
  //#region ../../src/lib/codex-exporter-db.ts
@@ -956,7 +1285,7 @@ var writeSessionFileExport = async (target, options, outputPath, transform = (te
956
1285
  let wroteSection = false;
957
1286
  try {
958
1287
  transcriptStream = await createExportWriteStream(transcriptOutputPath);
959
- for await (const parsed of readJsonlObjects(target.sessionFile)) {
1288
+ for await (const parsed of readJsonlObjects$1(target.sessionFile)) {
960
1289
  captureSessionMeta(parsed, state.sessionMeta);
961
1290
  const block = renderCodexTranscriptRecord(parsed, options, state);
962
1291
  if (!block) continue;
@@ -993,7 +1322,7 @@ var collectCodexTranscript = async (sessionFile, options, assistantModel = null)
993
1322
  sections: [],
994
1323
  sessionMeta: {}
995
1324
  };
996
- for await (const parsed of readJsonlObjects(sessionFile)) processCodexTranscriptRecord(parsed, options, state);
1325
+ for await (const parsed of readJsonlObjects$1(sessionFile)) processCodexTranscriptRecord(parsed, options, state);
997
1326
  return state;
998
1327
  };
999
1328
  var getSectionSeparator = () => "\n";
@@ -1388,47 +1717,20 @@ var extractContentPart = (value) => {
1388
1717
  if (type === "input_image") return "[Image attached]";
1389
1718
  return text ?? "";
1390
1719
  };
1391
- var UI_EXPORT_URL_PREFIX = "/__exports/";
1392
- var DEFAULT_UI_EXPORT_DIR = path.join(os.tmpdir(), "spiracha-ui-exports");
1393
- var DEFAULT_EXPORT_MAX_AGE_MS = 1440 * 60 * 1e3;
1394
- var getUiExportDir = () => {
1395
- return process.env["SPIRACHA_UI_EXPORT_DIR"]?.trim() || DEFAULT_UI_EXPORT_DIR;
1396
- };
1397
- var ensureUiExportDir = async () => {
1398
- const exportDir = getUiExportDir();
1399
- await mkdir(exportDir, { recursive: true });
1400
- await purgeStaleUiExports(exportDir);
1401
- return exportDir;
1402
- };
1403
- var buildUiExportDownloadUrl = (filePath) => {
1404
- return `${UI_EXPORT_URL_PREFIX}${encodeURIComponent(path.basename(filePath))}`;
1405
- };
1406
- var purgeStaleUiExports = async (exportDir = getUiExportDir(), maxAgeMs = DEFAULT_EXPORT_MAX_AGE_MS) => {
1407
- const entries = await readdir(exportDir, { withFileTypes: true });
1408
- const cutoff = Date.now() - maxAgeMs;
1409
- await Promise.all(entries.filter((entry) => entry.isFile()).map(async (entry) => {
1410
- const filePath = path.join(exportDir, entry.name);
1411
- if ((await stat(filePath)).mtimeMs >= cutoff) return;
1412
- await rm(filePath, { force: true });
1413
- }));
1414
- };
1415
1720
  //#endregion
1416
1721
  //#region ../../src/lib/codex-browser-export.ts
1417
1722
  var LARGE_BROWSER_EXPORT_THRESHOLD_BYTES = 128 * 1024 * 1024;
1418
- var toSanitizedFileName = (value) => {
1419
- return value.replace(/[<>:"/\\|?*\u0000-\u001f]/gu, " ").replace(/\.\.+/gu, " ").replace(/\s+/gu, " ").trim();
1420
- };
1421
1723
  var formatReadableExportDate = (value) => {
1422
1724
  const date = new Date(value);
1423
1725
  return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, "0")}-${String(date.getUTCDate()).padStart(2, "0")}-${String(date.getUTCHours()).padStart(2, "0")}${String(date.getUTCMinutes()).padStart(2, "0")}`;
1424
1726
  };
1425
1727
  var buildExportBaseName = (thread) => {
1426
- return `${toSanitizedFileName(getPortablePathBasename(thread.cwd) || "thread") || "thread"}-${formatReadableExportDate(thread.updated_at_ms ?? thread.updated_at * 1e3)}-${thread.id.slice(0, 8)}`;
1728
+ return `${sanitizeExportFileName(getPortablePathBasename(thread.cwd) || "thread") || "thread"}-${formatReadableExportDate(thread.updated_at_ms ?? thread.updated_at * 1e3)}-${thread.id.slice(0, 8)}`;
1427
1729
  };
1428
1730
  var buildBatchExportBaseName = (threads) => {
1429
1731
  const firstThread = threads[0];
1430
1732
  if (!firstThread) throw new Error("No threads selected for export");
1431
- return `${toSanitizedFileName(getPortablePathBasename(firstThread.cwd) || "threads") || "threads"}-${formatReadableExportDate(Math.max(...threads.map((thread) => thread.updated_at_ms ?? thread.updated_at * 1e3)))}-threads-${threads.length}`;
1733
+ return `${sanitizeExportFileName(getPortablePathBasename(firstThread.cwd) || "threads") || "threads"}-${formatReadableExportDate(Math.max(...threads.map((thread) => thread.updated_at_ms ?? thread.updated_at * 1e3)))}-threads-${threads.length}`;
1432
1734
  };
1433
1735
  var buildUniqueArchivePath = (exportDir, exportBaseName) => {
1434
1736
  return path.join(exportDir, `${exportBaseName}-${randomUUID()}.zip`);
@@ -1457,9 +1759,6 @@ var toDownloadOptions = (input) => {
1457
1759
  threadIds: [input.threadId]
1458
1760
  };
1459
1761
  };
1460
- var getMimeType = (outputFormat) => {
1461
- return outputFormat === "md" ? "text/markdown; charset=utf-8" : "text/plain; charset=utf-8";
1462
- };
1463
1762
  var resolvePublicExportDir = async (publicExportDir) => {
1464
1763
  if (publicExportDir) {
1465
1764
  await ensureDirectory(publicExportDir);
@@ -1480,17 +1779,27 @@ var getRolloutSnapshot = async (rolloutPath) => {
1480
1779
  sizeBytes: metadata.size
1481
1780
  };
1482
1781
  };
1782
+ var isMissingFileError$1 = (error) => {
1783
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
1784
+ };
1785
+ var getExistingRolloutSnapshot = async (threadId, rolloutPath) => {
1786
+ try {
1787
+ return await getRolloutSnapshot(rolloutPath);
1788
+ } catch (error) {
1789
+ if (isMissingFileError$1(error)) throw new Error(`Thread ${threadId} rollout file is missing: ${rolloutPath}`, { cause: error });
1790
+ throw error;
1791
+ }
1792
+ };
1483
1793
  var logExportEvent = (level, event, details) => {
1484
1794
  console[level](`[spiracha:export] ${event}`, details);
1485
1795
  };
1486
- var logRolloutChangeIfDetected = (threadId, rolloutPath, beforeSnapshot, afterSnapshot) => {
1796
+ var logRolloutChangeIfDetected = (threadId, beforeSnapshot, afterSnapshot) => {
1487
1797
  if (beforeSnapshot.mtimeMs === afterSnapshot.mtimeMs && beforeSnapshot.sizeBytes === afterSnapshot.sizeBytes) return;
1488
1798
  logExportEvent("warn", "rollout_changed_during_export", {
1489
1799
  afterMtimeMs: afterSnapshot.mtimeMs,
1490
1800
  afterSizeBytes: afterSnapshot.sizeBytes,
1491
1801
  beforeMtimeMs: beforeSnapshot.mtimeMs,
1492
1802
  beforeSizeBytes: beforeSnapshot.sizeBytes,
1493
- rolloutPath,
1494
1803
  threadId
1495
1804
  });
1496
1805
  };
@@ -1507,63 +1816,25 @@ var cleanupExportWorkspace = async (workspacePath) => {
1507
1816
  });
1508
1817
  }
1509
1818
  };
1510
- var zipExportFile = async (sourcePath, zipPath) => {
1511
- const proc = Bun.spawn([
1512
- "zip",
1513
- "-9",
1514
- "-j",
1515
- zipPath,
1516
- sourcePath
1517
- ], {
1518
- stderr: "pipe",
1519
- stdout: "pipe"
1520
- });
1521
- const [stdoutText, stderrText, exitCode] = await Promise.all([
1522
- new Response(proc.stdout).text(),
1523
- new Response(proc.stderr).text(),
1524
- proc.exited
1525
- ]);
1526
- if (exitCode !== 0) throw new Error(`zip failed (${exitCode}): ${(stderrText || stdoutText).trim()}`);
1527
- };
1528
- var zipExportDirectory = async (sourceDirectory, zipPath) => {
1529
- const proc = Bun.spawn([
1530
- "zip",
1531
- "-9",
1532
- "-r",
1533
- zipPath,
1534
- "."
1535
- ], {
1536
- cwd: sourceDirectory,
1537
- stderr: "pipe",
1538
- stdout: "pipe"
1539
- });
1540
- const [stdoutText, stderrText, exitCode] = await Promise.all([
1541
- new Response(proc.stdout).text(),
1542
- new Response(proc.stderr).text(),
1543
- proc.exited
1544
- ]);
1545
- if (exitCode !== 0) throw new Error(`zip failed (${exitCode}): ${(stderrText || stdoutText).trim()}`);
1546
- };
1547
1819
  var renderCodexThreadDownload = async (input) => {
1548
1820
  const startedAt = Date.now();
1549
1821
  const browseData = getThreadBrowseData(input.dbPath, input.threadId);
1550
1822
  const extension = input.outputFormat === "md" ? "md" : "txt";
1551
1823
  const fileBaseName = buildExportBaseName(browseData.thread);
1552
1824
  const fileName = `${fileBaseName}.${extension}`;
1553
- const mimeType = getMimeType(input.outputFormat);
1825
+ const mimeType = getExportMimeType(input.outputFormat);
1554
1826
  const transform = (text) => input.pathDisplaySettings ? applyPathTransforms(text, {
1555
1827
  ...input.pathDisplaySettings,
1556
1828
  projectPath: browseData.thread.cwd
1557
1829
  }) : text;
1558
- const rolloutSnapshotBefore = await getRolloutSnapshot(browseData.thread.rollout_path);
1830
+ const rolloutSnapshotBefore = await getExistingRolloutSnapshot(input.threadId, browseData.thread.rollout_path);
1559
1831
  logExportEvent("info", "single_start", {
1560
1832
  fileName,
1561
- rolloutPath: browseData.thread.rollout_path,
1562
1833
  sizeBytes: rolloutSnapshotBefore.sizeBytes,
1563
1834
  threadId: input.threadId
1564
1835
  });
1565
1836
  try {
1566
- if (rolloutSnapshotBefore.sizeBytes > (input.largeExportThresholdBytes ?? LARGE_BROWSER_EXPORT_THRESHOLD_BYTES)) {
1837
+ if (input.zipArchive || rolloutSnapshotBefore.sizeBytes > (input.largeExportThresholdBytes ?? LARGE_BROWSER_EXPORT_THRESHOLD_BYTES)) {
1567
1838
  const exportBaseName = fileBaseName;
1568
1839
  const exportDir = await resolvePublicExportDir(input.publicExportDir);
1569
1840
  const workspaceDir = await createExportWorkspace(exportDir, exportBaseName);
@@ -1582,7 +1853,7 @@ var renderCodexThreadDownload = async (input) => {
1582
1853
  await cleanupExportWorkspace(workspaceDir);
1583
1854
  }
1584
1855
  const rolloutSnapshotAfter = await getRolloutSnapshot(browseData.thread.rollout_path);
1585
- logRolloutChangeIfDetected(input.threadId, browseData.thread.rollout_path, rolloutSnapshotBefore, rolloutSnapshotAfter);
1856
+ logRolloutChangeIfDetected(input.threadId, rolloutSnapshotBefore, rolloutSnapshotAfter);
1586
1857
  const zipStat = await Bun.file(zipPath).stat();
1587
1858
  logExportEvent("info", "single_zip_ready", {
1588
1859
  downloadUrl: buildUiExportDownloadUrl(zipPath),
@@ -1608,7 +1879,7 @@ var renderCodexThreadDownload = async (input) => {
1608
1879
  }, toDownloadOptions(input));
1609
1880
  if (!content) throw new Error(`Thread ${input.threadId} produced no exportable content`);
1610
1881
  const rolloutSnapshotAfter = await getRolloutSnapshot(browseData.thread.rollout_path);
1611
- logRolloutChangeIfDetected(input.threadId, browseData.thread.rollout_path, rolloutSnapshotBefore, rolloutSnapshotAfter);
1882
+ logRolloutChangeIfDetected(input.threadId, rolloutSnapshotBefore, rolloutSnapshotAfter);
1612
1883
  logExportEvent("info", "single_inline_ready", {
1613
1884
  durationMs: Date.now() - startedAt,
1614
1885
  fileName,
@@ -1649,7 +1920,7 @@ var renderCodexThreadsDownload = async (input) => {
1649
1920
  });
1650
1921
  try {
1651
1922
  for (const entry of browseEntries) {
1652
- const rolloutSnapshotBefore = await getRolloutSnapshot(entry.thread.rollout_path);
1923
+ const rolloutSnapshotBefore = await getExistingRolloutSnapshot(entry.thread.id, entry.thread.rollout_path);
1653
1924
  const singleBaseName = buildExportBaseName(entry.thread);
1654
1925
  const uniqueBaseName = buildUniqueBatchEntryBaseName(singleBaseName, entry.thread.id, usedBatchEntryBaseNames);
1655
1926
  const relativeFileName = `${uniqueBaseName}.${input.outputFormat === "md" ? "md" : "txt"}`;
@@ -1677,7 +1948,7 @@ var renderCodexThreadsDownload = async (input) => {
1677
1948
  threadIds: [entry.thread.id]
1678
1949
  }, savedPath, transform)) throw new Error(`Thread ${entry.thread.id} produced no exportable content`);
1679
1950
  const rolloutSnapshotAfter = await getRolloutSnapshot(entry.thread.rollout_path);
1680
- logRolloutChangeIfDetected(entry.thread.id, entry.thread.rollout_path, rolloutSnapshotBefore, rolloutSnapshotAfter);
1951
+ logRolloutChangeIfDetected(entry.thread.id, rolloutSnapshotBefore, rolloutSnapshotAfter);
1681
1952
  }
1682
1953
  await zipExportDirectory(bundleDirectory, zipPath);
1683
1954
  } catch (error) {
@@ -1863,7 +2134,8 @@ var exportSchema = z.object({
1863
2134
  includeTools: z.boolean(),
1864
2135
  outputFormat: z.enum(["md", "txt"]),
1865
2136
  redactUsername: z.boolean(),
1866
- threadId: z.string().min(1)
2137
+ threadId: z.string().min(1),
2138
+ zipArchive: z.boolean().default(false)
1867
2139
  });
1868
2140
  var exportThreadsSchema = z.object({
1869
2141
  convertToProjectRoot: z.boolean(),
@@ -1872,7 +2144,8 @@ var exportThreadsSchema = z.object({
1872
2144
  includeTools: z.boolean(),
1873
2145
  outputFormat: z.enum(["md", "txt"]),
1874
2146
  redactUsername: z.boolean(),
1875
- threadIds: z.array(z.string().min(1)).min(1)
2147
+ threadIds: z.array(z.string().min(1)).min(1),
2148
+ zipArchive: z.boolean().default(true)
1876
2149
  });
1877
2150
  var getDbPath = () => process.env.SPIRACHA_CODEX_DB?.trim() || resolveCodexThreadDbPath();
1878
2151
  var isMissingFileError = (error) => {
@@ -1899,7 +2172,7 @@ var listProjectThreadsFn_createServerFn_handler = createServerRpc({
1899
2172
  name: "listProjectThreadsFn",
1900
2173
  filename: "src/lib/codex-server.ts"
1901
2174
  }, (opts) => listProjectThreadsFn.__executeServer(opts));
1902
- var listProjectThreadsFn = createServerFn({ method: "GET" }).inputValidator(projectSchema).handler(listProjectThreadsFn_createServerFn_handler, async ({ data }) => {
2175
+ var listProjectThreadsFn = createServerFn({ method: "GET" }).validator(projectSchema).handler(listProjectThreadsFn_createServerFn_handler, async ({ data }) => {
1903
2176
  return listProjectThreads(getDbPath(), data.project);
1904
2177
  });
1905
2178
  var getThreadSnapshotFn_createServerFn_handler = createServerRpc({
@@ -1907,7 +2180,7 @@ var getThreadSnapshotFn_createServerFn_handler = createServerRpc({
1907
2180
  name: "getThreadSnapshotFn",
1908
2181
  filename: "src/lib/codex-server.ts"
1909
2182
  }, (opts) => getThreadSnapshotFn.__executeServer(opts));
1910
- var getThreadSnapshotFn = createServerFn({ method: "GET" }).inputValidator(threadSchema).handler(getThreadSnapshotFn_createServerFn_handler, async ({ data }) => {
2183
+ var getThreadSnapshotFn = createServerFn({ method: "GET" }).validator(threadSchema).handler(getThreadSnapshotFn_createServerFn_handler, async ({ data }) => {
1911
2184
  const browseData = getThreadBrowseData(getDbPath(), data.threadId);
1912
2185
  const rollout = await getThreadRolloutLoadState(browseData.thread.rollout_path);
1913
2186
  let transcript = null;
@@ -1931,7 +2204,7 @@ var getThreadTranscriptFn_createServerFn_handler = createServerRpc({
1931
2204
  name: "getThreadTranscriptFn",
1932
2205
  filename: "src/lib/codex-server.ts"
1933
2206
  }, (opts) => getThreadTranscriptFn.__executeServer(opts));
1934
- var getThreadTranscriptFn = createServerFn({ method: "GET" }).inputValidator(threadSchema).handler(getThreadTranscriptFn_createServerFn_handler, async ({ data }) => {
2207
+ var getThreadTranscriptFn = createServerFn({ method: "GET" }).validator(threadSchema).handler(getThreadTranscriptFn_createServerFn_handler, async ({ data }) => {
1935
2208
  return getCachedThreadTranscriptPreview(getThreadBrowseData(getDbPath(), data.threadId).thread.rollout_path);
1936
2209
  });
1937
2210
  var getAnalyticsFn_createServerFn_handler = createServerRpc({
@@ -1939,7 +2212,7 @@ var getAnalyticsFn_createServerFn_handler = createServerRpc({
1939
2212
  name: "getAnalyticsFn",
1940
2213
  filename: "src/lib/codex-server.ts"
1941
2214
  }, (opts) => getAnalyticsFn.__executeServer(opts));
1942
- var getAnalyticsFn = createServerFn({ method: "GET" }).inputValidator(analyticsSchema).handler(getAnalyticsFn_createServerFn_handler, async ({ data }) => {
2215
+ var getAnalyticsFn = createServerFn({ method: "GET" }).validator(analyticsSchema).handler(getAnalyticsFn_createServerFn_handler, async ({ data }) => {
1943
2216
  return getCodexAnalytics({
1944
2217
  dbPath: getDbPath(),
1945
2218
  project: data.project
@@ -1950,7 +2223,7 @@ var exportThreadFn_createServerFn_handler = createServerRpc({
1950
2223
  name: "exportThreadFn",
1951
2224
  filename: "src/lib/codex-server.ts"
1952
2225
  }, (opts) => exportThreadFn.__executeServer(opts));
1953
- var exportThreadFn = createServerFn({ method: "POST" }).inputValidator(exportSchema).handler(exportThreadFn_createServerFn_handler, async ({ data }) => {
2226
+ var exportThreadFn = createServerFn({ method: "POST" }).validator(exportSchema).handler(exportThreadFn_createServerFn_handler, async ({ data }) => {
1954
2227
  return renderCodexThreadDownload({
1955
2228
  dbPath: getDbPath(),
1956
2229
  includeCommentary: data.includeCommentary,
@@ -1961,7 +2234,8 @@ var exportThreadFn = createServerFn({ method: "POST" }).inputValidator(exportSch
1961
2234
  convertToProjectRoot: data.convertToProjectRoot,
1962
2235
  redactUsername: data.redactUsername
1963
2236
  },
1964
- threadId: data.threadId
2237
+ threadId: data.threadId,
2238
+ zipArchive: data.zipArchive
1965
2239
  });
1966
2240
  });
1967
2241
  var exportThreadsFn_createServerFn_handler = createServerRpc({
@@ -1969,7 +2243,7 @@ var exportThreadsFn_createServerFn_handler = createServerRpc({
1969
2243
  name: "exportThreadsFn",
1970
2244
  filename: "src/lib/codex-server.ts"
1971
2245
  }, (opts) => exportThreadsFn.__executeServer(opts));
1972
- var exportThreadsFn = createServerFn({ method: "POST" }).inputValidator(exportThreadsSchema).handler(exportThreadsFn_createServerFn_handler, async ({ data }) => {
2246
+ var exportThreadsFn = createServerFn({ method: "POST" }).validator(exportThreadsSchema).handler(exportThreadsFn_createServerFn_handler, async ({ data }) => {
1973
2247
  return renderCodexThreadsDownload({
1974
2248
  dbPath: getDbPath(),
1975
2249
  includeCommentary: data.includeCommentary,
@@ -1980,7 +2254,8 @@ var exportThreadsFn = createServerFn({ method: "POST" }).inputValidator(exportTh
1980
2254
  convertToProjectRoot: data.convertToProjectRoot,
1981
2255
  redactUsername: data.redactUsername
1982
2256
  },
1983
- threadIds: data.threadIds
2257
+ threadIds: data.threadIds,
2258
+ zipArchive: data.zipArchive
1984
2259
  });
1985
2260
  });
1986
2261
  var deleteThreadFn_createServerFn_handler = createServerRpc({
@@ -1988,7 +2263,7 @@ var deleteThreadFn_createServerFn_handler = createServerRpc({
1988
2263
  name: "deleteThreadFn",
1989
2264
  filename: "src/lib/codex-server.ts"
1990
2265
  }, (opts) => deleteThreadFn.__executeServer(opts));
1991
- var deleteThreadFn = createServerFn({ method: "POST" }).inputValidator(deleteThreadSchema).handler(deleteThreadFn_createServerFn_handler, async ({ data }) => {
2266
+ var deleteThreadFn = createServerFn({ method: "POST" }).validator(deleteThreadSchema).handler(deleteThreadFn_createServerFn_handler, async ({ data }) => {
1992
2267
  return deleteCodexThread(getDbPath(), data.threadId, { deleteSessionFiles: data.deleteSessionFiles });
1993
2268
  });
1994
2269
  var deleteThreadsFn_createServerFn_handler = createServerRpc({
@@ -1996,7 +2271,7 @@ var deleteThreadsFn_createServerFn_handler = createServerRpc({
1996
2271
  name: "deleteThreadsFn",
1997
2272
  filename: "src/lib/codex-server.ts"
1998
2273
  }, (opts) => deleteThreadsFn.__executeServer(opts));
1999
- var deleteThreadsFn = createServerFn({ method: "POST" }).inputValidator(deleteThreadsSchema).handler(deleteThreadsFn_createServerFn_handler, async ({ data }) => {
2274
+ var deleteThreadsFn = createServerFn({ method: "POST" }).validator(deleteThreadsSchema).handler(deleteThreadsFn_createServerFn_handler, async ({ data }) => {
2000
2275
  return deleteCodexThreads(getDbPath(), data.threadIds, { deleteSessionFiles: data.deleteSessionFiles });
2001
2276
  });
2002
2277
  var deleteProjectFn_createServerFn_handler = createServerRpc({
@@ -2004,7 +2279,7 @@ var deleteProjectFn_createServerFn_handler = createServerRpc({
2004
2279
  name: "deleteProjectFn",
2005
2280
  filename: "src/lib/codex-server.ts"
2006
2281
  }, (opts) => deleteProjectFn.__executeServer(opts));
2007
- var deleteProjectFn = createServerFn({ method: "POST" }).inputValidator(deleteProjectSchema).handler(deleteProjectFn_createServerFn_handler, async ({ data }) => {
2282
+ var deleteProjectFn = createServerFn({ method: "POST" }).validator(deleteProjectSchema).handler(deleteProjectFn_createServerFn_handler, async ({ data }) => {
2008
2283
  return deleteCodexProject(getDbPath(), data.project, { deleteSessionFiles: data.deleteSessionFiles });
2009
2284
  });
2010
2285
  var recoverProjectThreadsFn_createServerFn_handler = createServerRpc({
@@ -2012,7 +2287,7 @@ var recoverProjectThreadsFn_createServerFn_handler = createServerRpc({
2012
2287
  name: "recoverProjectThreadsFn",
2013
2288
  filename: "src/lib/codex-server.ts"
2014
2289
  }, (opts) => recoverProjectThreadsFn.__executeServer(opts));
2015
- var recoverProjectThreadsFn = createServerFn({ method: "POST" }).inputValidator(projectSchema).handler(recoverProjectThreadsFn_createServerFn_handler, async ({ data }) => {
2290
+ var recoverProjectThreadsFn = createServerFn({ method: "POST" }).validator(projectSchema).handler(recoverProjectThreadsFn_createServerFn_handler, async ({ data }) => {
2016
2291
  return recoverCodexProjectThreads(getDbPath(), data.project);
2017
2292
  });
2018
2293
  //#endregion