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,345 @@
1
+ import type { ThreadEvent, ThreadTranscriptStats } from '@spiracha/lib/codex-browser-types';
2
+ import type { KiroSessionTranscript } from '@spiracha/lib/kiro-exporter-types';
3
+ import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
4
+ import { createFileRoute, Link } from '@tanstack/react-router';
5
+ import { Download } from 'lucide-react';
6
+ import { useMemo, useState } from 'react';
7
+ import { Breadcrumbs } from '#/components/breadcrumbs';
8
+ import { ExportDialog } from '#/components/export-dialog';
9
+ import { JsonPanel } from '#/components/json-panel';
10
+ import { LoadingPanel } from '#/components/loading-panel';
11
+ import { MetadataSection } from '#/components/metadata-section';
12
+ import { MetricCard } from '#/components/metric-card';
13
+ import { PageHeader } from '#/components/page-header';
14
+ import { ReloadErrorPanel } from '#/components/reload-error-panel';
15
+ import { TranscriptView } from '#/components/transcript-view';
16
+ import { Button } from '#/components/ui/button';
17
+ import { Checkbox } from '#/components/ui/checkbox';
18
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '#/components/ui/tabs';
19
+ import { downloadTextFile, downloadUrlFile } from '#/lib/download';
20
+ import { formatDateTime, formatList, formatNumber } from '#/lib/formatters';
21
+ import { kiroSessionDetailQueryOptions } from '#/lib/kiro-queries';
22
+ import { exportKiroSessionFn } from '#/lib/kiro-server';
23
+ import { getKiroThreadTranscriptStats, kiroTranscriptToThreadEvents } from '#/lib/kiro-transcript-events';
24
+
25
+ type ExportDialogOptions = {
26
+ includeCommentary: boolean;
27
+ includeMetadata: boolean;
28
+ includeTools: boolean;
29
+ outputFormat: 'md' | 'txt';
30
+ zipArchive: boolean;
31
+ };
32
+
33
+ type TranscriptControlsProps = {
34
+ rawJsonDisabled?: boolean;
35
+ showCommentary: boolean;
36
+ showExtraEvents: boolean;
37
+ showRawJson: boolean;
38
+ showToolCalls: boolean;
39
+ showUserMessages: boolean;
40
+ onShowCommentaryChange: (checked: boolean) => void;
41
+ onShowExtraEventsChange: (checked: boolean) => void;
42
+ onShowRawJsonChange: (checked: boolean) => void;
43
+ onShowToolCallsChange: (checked: boolean) => void;
44
+ onShowUserMessagesChange: (checked: boolean) => void;
45
+ };
46
+
47
+ const KiroSessionDetailErrorComponent = ({ error }: { error: Error }) => {
48
+ return <ReloadErrorPanel description={error.message} title="Failed to load Kiro session" />;
49
+ };
50
+
51
+ const getKiroModelLabel = (detail: KiroSessionTranscript): string => {
52
+ return detail.session.selectedModel ?? detail.session.defaultModelTitle ?? 'unknown';
53
+ };
54
+
55
+ const buildSessionMetadata = (detail: KiroSessionTranscript) => [
56
+ { label: 'Session ID', value: <span data-mono="true">{detail.session.sessionId}</span> },
57
+ {
58
+ label: 'Workspace',
59
+ value: (
60
+ <Link
61
+ className="text-[var(--accent)]"
62
+ params={{ workspaceKey: detail.session.workspaceKey }}
63
+ to="/kiro/$workspaceKey"
64
+ >
65
+ {detail.session.workspaceLabel}
66
+ </Link>
67
+ ),
68
+ },
69
+ { label: 'Worktree', value: detail.session.worktree },
70
+ { label: 'Workspace path', value: detail.session.workspacePath ?? 'unknown' },
71
+ { label: 'Workspace directory', value: detail.session.workspaceDirectory ?? 'unknown' },
72
+ { label: 'Selected model', value: detail.session.selectedModel ?? 'unknown' },
73
+ { label: 'Default model', value: detail.session.defaultModelTitle ?? 'unknown' },
74
+ { label: 'Profile', value: detail.session.selectedProfileId ?? 'unknown' },
75
+ { label: 'Autonomy mode', value: detail.session.autonomyMode ?? 'unknown' },
76
+ { label: 'Session type', value: detail.session.sessionType ?? 'unknown' },
77
+ { label: 'Created', value: <span suppressHydrationWarning>{formatDateTime(detail.session.createdAtMs)}</span> },
78
+ {
79
+ label: 'Last active',
80
+ value: <span suppressHydrationWarning>{formatDateTime(detail.session.lastActiveAtMs)}</span>,
81
+ },
82
+ { label: 'Source file', value: detail.session.filePath },
83
+ ];
84
+
85
+ const buildTranscriptStatsItems = (
86
+ detail: KiroSessionTranscript,
87
+ events: ThreadEvent[],
88
+ stats: ThreadTranscriptStats,
89
+ ) => [
90
+ { label: 'Event kinds', value: formatList([...new Set(events.map((event) => event.kind))]) },
91
+ { label: 'Messages', value: formatNumber(stats.messageCount) },
92
+ { label: 'User messages', value: formatNumber(stats.userMessageCount) },
93
+ { label: 'Assistant messages', value: formatNumber(stats.assistantMessageCount) },
94
+ { label: 'Final answers', value: formatNumber(stats.finalAnswerCount) },
95
+ { label: 'Images', value: formatNumber(detail.session.imageCount) },
96
+ { label: 'Prompt logs', value: formatNumber(detail.session.promptLogCount) },
97
+ { label: 'Renderable parts', value: formatNumber(detail.renderablePartCount) },
98
+ ];
99
+
100
+ const KiroTranscriptControls = ({
101
+ rawJsonDisabled = false,
102
+ showCommentary,
103
+ showExtraEvents,
104
+ showRawJson,
105
+ showToolCalls,
106
+ showUserMessages,
107
+ onShowCommentaryChange,
108
+ onShowExtraEventsChange,
109
+ onShowRawJsonChange,
110
+ onShowToolCallsChange,
111
+ onShowUserMessagesChange,
112
+ }: TranscriptControlsProps) => {
113
+ return (
114
+ <div className="flex flex-wrap gap-4 rounded-xl border border-[var(--border)] bg-[var(--panel)] px-4 py-3 shadow-[var(--panel-shadow)]">
115
+ <div className="flex items-center gap-2 text-sm">
116
+ <Checkbox
117
+ checked={showToolCalls}
118
+ id="kiro-transcript-show-tool-calls"
119
+ onCheckedChange={(checked) => onShowToolCallsChange(checked === true)}
120
+ />
121
+ <label htmlFor="kiro-transcript-show-tool-calls">Show tool calls</label>
122
+ </div>
123
+ <div className="flex items-center gap-2 text-sm">
124
+ <Checkbox
125
+ checked={showCommentary}
126
+ id="kiro-transcript-show-commentary"
127
+ onCheckedChange={(checked) => onShowCommentaryChange(checked === true)}
128
+ />
129
+ <label htmlFor="kiro-transcript-show-commentary">Show commentary</label>
130
+ </div>
131
+ <div className="flex items-center gap-2 text-sm">
132
+ <Checkbox
133
+ checked={showExtraEvents}
134
+ id="kiro-transcript-show-extra-events"
135
+ onCheckedChange={(checked) => onShowExtraEventsChange(checked === true)}
136
+ />
137
+ <label htmlFor="kiro-transcript-show-extra-events">Show extra events</label>
138
+ </div>
139
+ <div className="flex items-center gap-2 text-sm">
140
+ <Checkbox
141
+ checked={showRawJson}
142
+ disabled={rawJsonDisabled}
143
+ id="kiro-transcript-show-raw-json"
144
+ onCheckedChange={(checked) => onShowRawJsonChange(checked === true)}
145
+ />
146
+ <label htmlFor="kiro-transcript-show-raw-json">Raw JSON</label>
147
+ </div>
148
+ <div className="flex items-center gap-2 text-sm">
149
+ <Checkbox
150
+ checked={showUserMessages}
151
+ id="kiro-transcript-show-user-messages"
152
+ onCheckedChange={(checked) => onShowUserMessagesChange(checked === true)}
153
+ />
154
+ <label htmlFor="kiro-transcript-show-user-messages">User</label>
155
+ </div>
156
+ </div>
157
+ );
158
+ };
159
+
160
+ const KiroRawPanels = ({ detail, events }: { detail: KiroSessionTranscript; events: ThreadEvent[] }) => {
161
+ return (
162
+ <div className="space-y-4">
163
+ <JsonPanel title="Session summary" value={detail.session} />
164
+ <JsonPanel title="Kiro entries" value={detail.entries} />
165
+ <JsonPanel title="Raw Kiro session" value={detail.rawSession} />
166
+ <JsonPanel title="Transcript events" value={events} />
167
+ </div>
168
+ );
169
+ };
170
+
171
+ const KiroSessionDetailPage = () => {
172
+ const detail = useSuspenseQuery(kiroSessionDetailQueryOptions(Route.useParams().sessionId)).data;
173
+ const [pendingExport, setPendingExport] = useState(false);
174
+ const [showToolCalls, setShowToolCalls] = useState(false);
175
+ const [showCommentary, setShowCommentary] = useState(false);
176
+ const [showExtraEvents, setShowExtraEvents] = useState(false);
177
+ const [showRawJson, setShowRawJson] = useState(false);
178
+ const [showUserMessages, setShowUserMessages] = useState(true);
179
+ const transcriptEvents = useMemo(() => kiroTranscriptToThreadEvents(detail), [detail]);
180
+ const transcriptStats = useMemo(() => getKiroThreadTranscriptStats(transcriptEvents), [transcriptEvents]);
181
+ const modelLabel = getKiroModelLabel(detail);
182
+
183
+ const exportSessionMutation = useMutation({
184
+ mutationFn: async (options: ExportDialogOptions) => {
185
+ const download = await exportKiroSessionFn({
186
+ data: {
187
+ includeCommentary: options.includeCommentary,
188
+ includeMetadata: options.includeMetadata,
189
+ includeTools: options.includeTools,
190
+ outputFormat: options.outputFormat,
191
+ sessionId: detail.session.sessionId,
192
+ zipArchive: options.zipArchive,
193
+ },
194
+ });
195
+ if (download.mode === 'download') {
196
+ downloadTextFile(download.fileName, download.content, download.mimeType);
197
+ return;
198
+ }
199
+
200
+ await downloadUrlFile(download.fileName, download.downloadUrl);
201
+ },
202
+ onSuccess: () => {
203
+ setPendingExport(false);
204
+ },
205
+ });
206
+
207
+ return (
208
+ <div className="space-y-6">
209
+ <PageHeader
210
+ actions={
211
+ <Button
212
+ className="rounded-full"
213
+ type="button"
214
+ variant="outline"
215
+ onClick={() => setPendingExport(true)}
216
+ >
217
+ <Download className="mr-2 size-4" />
218
+ Export
219
+ </Button>
220
+ }
221
+ breadcrumb={
222
+ <Breadcrumbs
223
+ items={[
224
+ { label: 'Kiro', to: '/kiro' },
225
+ {
226
+ label: detail.session.workspaceLabel,
227
+ params: { workspaceKey: detail.session.workspaceKey },
228
+ to: '/kiro/$workspaceKey',
229
+ },
230
+ { label: detail.session.title },
231
+ ]}
232
+ />
233
+ }
234
+ eyebrow="Kiro session"
235
+ subtitle="Session detail for the selected Kiro workspace conversation."
236
+ title={detail.session.title}
237
+ />
238
+
239
+ <div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4">
240
+ <MetricCard label="Messages" value={formatNumber(detail.session.messageCount)} />
241
+ <MetricCard label="Images" value={formatNumber(detail.session.imageCount)} />
242
+ <MetricCard label="Prompt logs" value={formatNumber(detail.session.promptLogCount)} />
243
+ <MetricCard label="Model" value={modelLabel} />
244
+ </div>
245
+
246
+ <Tabs className="space-y-4" defaultValue="transcript">
247
+ <TabsList className="grid w-fit min-w-[24rem] grid-cols-3 rounded-full border border-[var(--border)] bg-[var(--panel)] p-1">
248
+ <TabsTrigger className="rounded-full px-5 text-sm" value="transcript">
249
+ Transcript
250
+ </TabsTrigger>
251
+ <TabsTrigger className="rounded-full px-5 text-sm" value="metadata">
252
+ Metadata
253
+ </TabsTrigger>
254
+ <TabsTrigger className="rounded-full px-5 text-sm" value="raw">
255
+ Raw
256
+ </TabsTrigger>
257
+ </TabsList>
258
+
259
+ <TabsContent className="space-y-3" value="transcript">
260
+ <KiroTranscriptControls
261
+ rawJsonDisabled={transcriptEvents.length === 0}
262
+ showCommentary={showCommentary}
263
+ showExtraEvents={showExtraEvents}
264
+ showRawJson={showRawJson}
265
+ showToolCalls={showToolCalls}
266
+ showUserMessages={showUserMessages}
267
+ onShowCommentaryChange={setShowCommentary}
268
+ onShowExtraEventsChange={setShowExtraEvents}
269
+ onShowRawJsonChange={setShowRawJson}
270
+ onShowToolCallsChange={setShowToolCalls}
271
+ onShowUserMessagesChange={setShowUserMessages}
272
+ />
273
+ {transcriptEvents.length > 0 ? (
274
+ <TranscriptView
275
+ assistantModel={modelLabel}
276
+ events={transcriptEvents}
277
+ projectPath={detail.session.worktree}
278
+ showCommentary={showCommentary}
279
+ showExtraEvents={showExtraEvents}
280
+ showRawJson={showRawJson}
281
+ showToolCalls={showToolCalls}
282
+ showUserMessages={showUserMessages}
283
+ />
284
+ ) : (
285
+ <section className="rounded-[1.6rem] border border-[var(--border)] bg-[var(--panel)] p-5 shadow-[var(--panel-shadow)]">
286
+ <h3 className="font-semibold text-[var(--muted-foreground)] text-sm uppercase tracking-[0.18em]">
287
+ Transcript
288
+ </h3>
289
+ <p className="mt-4 text-[var(--muted-foreground)] text-sm">
290
+ No renderable Kiro transcript content was found for this session.
291
+ </p>
292
+ </section>
293
+ )}
294
+ </TabsContent>
295
+
296
+ <TabsContent value="metadata">
297
+ <div className="grid gap-4 xl:grid-cols-[0.95fr_1.05fr]">
298
+ <MetadataSection items={buildSessionMetadata(detail)} title="Session metadata" />
299
+ <MetadataSection
300
+ items={buildTranscriptStatsItems(detail, transcriptEvents, transcriptStats)}
301
+ title="Transcript stats"
302
+ />
303
+ </div>
304
+ </TabsContent>
305
+
306
+ <TabsContent value="raw">
307
+ <KiroRawPanels detail={detail} events={transcriptEvents} />
308
+ </TabsContent>
309
+ </Tabs>
310
+
311
+ <ExportDialog
312
+ errorMessage={
313
+ exportSessionMutation.isError
314
+ ? exportSessionMutation.error instanceof Error
315
+ ? exportSessionMutation.error.message
316
+ : 'Export failed'
317
+ : null
318
+ }
319
+ open={pendingExport}
320
+ pending={exportSessionMutation.isPending}
321
+ title={`Export ${detail.session.title}`}
322
+ onExport={(options) => exportSessionMutation.mutate(options)}
323
+ onOpenChange={(open) => {
324
+ setPendingExport(open);
325
+ if (!open) {
326
+ exportSessionMutation.reset();
327
+ }
328
+ }}
329
+ />
330
+ </div>
331
+ );
332
+ };
333
+
334
+ export const Route = createFileRoute('/kiro-sessions/$sessionId')({
335
+ component: KiroSessionDetailPage,
336
+ errorComponent: KiroSessionDetailErrorComponent,
337
+ loader: ({ context, params }) =>
338
+ context.queryClient.ensureQueryData(kiroSessionDetailQueryOptions(params.sessionId)),
339
+ pendingComponent: () => (
340
+ <LoadingPanel
341
+ description="Loading the Kiro transcript, messages, attachments, and session metadata."
342
+ title="Loading session"
343
+ />
344
+ ),
345
+ });
@@ -0,0 +1,136 @@
1
+ import type { KiroSessionSummary, KiroWorkspaceGroup } from '@spiracha/lib/kiro-exporter-types';
2
+ import { useMutation, useSuspenseQuery } from '@tanstack/react-query';
3
+ import { createFileRoute } from '@tanstack/react-router';
4
+ import { useDeferredValue, useState } from 'react';
5
+ import { ExportDialog } from '#/components/export-dialog';
6
+ import { KiroSessionsTable } from '#/components/kiro-sessions-table';
7
+ import { ListSearchInput } from '#/components/list-search-input';
8
+ import { LoadingPanel } from '#/components/loading-panel';
9
+ import { PageHeader } from '#/components/page-header';
10
+ import { ReloadErrorPanel } from '#/components/reload-error-panel';
11
+ import { downloadTextFile, downloadUrlFile } from '#/lib/download';
12
+ import { kiroSessionsQueryOptions, kiroWorkspacesQueryOptions } from '#/lib/kiro-queries';
13
+ import { exportKiroSessionFn } from '#/lib/kiro-server';
14
+ import { matchesTextQuery } from '#/lib/text-filter';
15
+
16
+ type ExportDialogOptions = {
17
+ includeCommentary: boolean;
18
+ includeMetadata: boolean;
19
+ includeTools: boolean;
20
+ outputFormat: 'md' | 'txt';
21
+ zipArchive: boolean;
22
+ };
23
+
24
+ const findWorkspaceOrThrow = (workspaces: KiroWorkspaceGroup[], workspaceKey: string) => {
25
+ const workspace = workspaces.find((candidate) => candidate.key === workspaceKey);
26
+ if (!workspace) {
27
+ throw new Error(`Kiro workspace not found: ${workspaceKey}`);
28
+ }
29
+
30
+ return workspace;
31
+ };
32
+
33
+ const KiroWorkspaceErrorComponent = ({ error }: { error: Error }) => {
34
+ return <ReloadErrorPanel description={error.message} title="Failed to load Kiro workspace" />;
35
+ };
36
+
37
+ const KiroWorkspacePage = () => {
38
+ const params = Route.useParams();
39
+ const workspaces = useSuspenseQuery(kiroWorkspacesQueryOptions()).data;
40
+ const workspace = findWorkspaceOrThrow(workspaces, params.workspaceKey);
41
+ const sessions = useSuspenseQuery(kiroSessionsQueryOptions(workspace.key)).data;
42
+ const [searchInput, setSearchInput] = useState('');
43
+ const [pendingExport, setPendingExport] = useState<KiroSessionSummary | null>(null);
44
+ const deferredSearch = useDeferredValue(searchInput);
45
+
46
+ const exportMutation = useMutation({
47
+ mutationFn: async (options: ExportDialogOptions) => {
48
+ if (!pendingExport) {
49
+ throw new Error('No Kiro session selected for export');
50
+ }
51
+
52
+ const download = await exportKiroSessionFn({
53
+ data: {
54
+ includeCommentary: options.includeCommentary,
55
+ includeMetadata: options.includeMetadata,
56
+ includeTools: options.includeTools,
57
+ outputFormat: options.outputFormat,
58
+ sessionId: pendingExport.sessionId,
59
+ zipArchive: options.zipArchive,
60
+ },
61
+ });
62
+ if (download.mode === 'download') {
63
+ downloadTextFile(download.fileName, download.content, download.mimeType);
64
+ return;
65
+ }
66
+
67
+ await downloadUrlFile(download.fileName, download.downloadUrl);
68
+ },
69
+ onSuccess: () => {
70
+ setPendingExport(null);
71
+ },
72
+ });
73
+
74
+ const visibleSessions = sessions.filter((session) =>
75
+ matchesTextQuery(deferredSearch, [
76
+ session.title,
77
+ session.sessionId,
78
+ session.selectedModel,
79
+ session.defaultModelTitle,
80
+ session.selectedProfileId,
81
+ session.sessionType,
82
+ session.filePath,
83
+ ]),
84
+ );
85
+
86
+ return (
87
+ <div className="space-y-6">
88
+ <PageHeader
89
+ actions={
90
+ <ListSearchInput
91
+ placeholder="Search session title, id, model, or type"
92
+ value={searchInput}
93
+ onValueChange={setSearchInput}
94
+ />
95
+ }
96
+ eyebrow="Kiro workspace"
97
+ subtitle="Inspect local Kiro sessions, user prompts, assistant responses, images, and prompt logs."
98
+ title={workspace.label}
99
+ />
100
+
101
+ <KiroSessionsTable sessions={visibleSessions} onExportSession={setPendingExport} />
102
+
103
+ <ExportDialog
104
+ open={pendingExport !== null}
105
+ pending={exportMutation.isPending}
106
+ title={pendingExport ? `Export ${pendingExport.title}` : 'Export session'}
107
+ onExport={(options) => exportMutation.mutate(options)}
108
+ onOpenChange={(open) => {
109
+ if (!open) {
110
+ setPendingExport(null);
111
+ exportMutation.reset();
112
+ }
113
+ }}
114
+ />
115
+
116
+ {exportMutation.isError ? (
117
+ <p className="text-[var(--destructive)] text-sm">
118
+ {exportMutation.error instanceof Error ? exportMutation.error.message : 'Session export failed'}
119
+ </p>
120
+ ) : null}
121
+ </div>
122
+ );
123
+ };
124
+
125
+ export const Route = createFileRoute('/kiro/$workspaceKey')({
126
+ component: KiroWorkspacePage,
127
+ errorComponent: KiroWorkspaceErrorComponent,
128
+ loader: async ({ context, params }) => {
129
+ const workspaces = await context.queryClient.ensureQueryData(kiroWorkspacesQueryOptions());
130
+ findWorkspaceOrThrow(workspaces, params.workspaceKey);
131
+ await context.queryClient.ensureQueryData(kiroSessionsQueryOptions(params.workspaceKey));
132
+ },
133
+ pendingComponent: () => (
134
+ <LoadingPanel description="Loading Kiro sessions and transcript metadata." title="Loading workspace" />
135
+ ),
136
+ });
@@ -0,0 +1,48 @@
1
+ import { useSuspenseQuery } from '@tanstack/react-query';
2
+ import { createFileRoute } from '@tanstack/react-router';
3
+ import { useDeferredValue, useState } from 'react';
4
+ import { KiroWorkspacesTable } from '#/components/kiro-workspaces-table';
5
+ import { ListSearchInput } from '#/components/list-search-input';
6
+ import { PageHeader } from '#/components/page-header';
7
+ import { ReloadErrorPanel } from '#/components/reload-error-panel';
8
+ import { kiroWorkspacesQueryOptions } from '#/lib/kiro-queries';
9
+ import { matchesTextQuery } from '#/lib/text-filter';
10
+
11
+ const KiroErrorComponent = ({ error }: { error: Error }) => {
12
+ return <ReloadErrorPanel description={error.message} title="Failed to load Kiro workspaces" />;
13
+ };
14
+
15
+ const KiroPage = () => {
16
+ const workspaces = useSuspenseQuery(kiroWorkspacesQueryOptions()).data;
17
+ const [searchInput, setSearchInput] = useState('');
18
+ const deferredSearch = useDeferredValue(searchInput);
19
+
20
+ const visibleWorkspaces = workspaces.filter((workspace) =>
21
+ matchesTextQuery(deferredSearch, [workspace.label, workspace.worktree, workspace.key, workspace.directoryName]),
22
+ );
23
+
24
+ return (
25
+ <div className="space-y-6">
26
+ <PageHeader
27
+ actions={
28
+ <ListSearchInput
29
+ placeholder="Search workspace name or path"
30
+ value={searchInput}
31
+ onValueChange={setSearchInput}
32
+ />
33
+ }
34
+ eyebrow="Inventory"
35
+ subtitle="Workspace groups are derived from local Kiro workspace session files."
36
+ title="Kiro"
37
+ />
38
+
39
+ <KiroWorkspacesTable workspaces={visibleWorkspaces} />
40
+ </div>
41
+ );
42
+ };
43
+
44
+ export const Route = createFileRoute('/kiro/')({
45
+ component: KiroPage,
46
+ errorComponent: KiroErrorComponent,
47
+ loader: ({ context }) => context.queryClient.ensureQueryData(kiroWorkspacesQueryOptions()),
48
+ });