spiracha 1.5.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.
- package/AGENTS.md +114 -205
- package/README.md +89 -269
- package/apps/ui/AGENTS.md +17 -7
- package/apps/ui/README.md +34 -8
- package/apps/ui/components.json +21 -0
- package/apps/ui/package.json +65 -0
- package/apps/ui/src/components/antigravity-conversations-table.tsx +206 -0
- package/apps/ui/src/components/antigravity-keychain-panel.tsx +76 -0
- package/apps/ui/src/components/antigravity-workspaces-table.tsx +63 -0
- package/apps/ui/src/components/app-shell.tsx +124 -0
- package/apps/ui/src/components/breadcrumbs.tsx +53 -0
- package/apps/ui/src/components/claude-code-sessions-table.tsx +114 -0
- package/apps/ui/src/components/claude-code-workspaces-table.tsx +55 -0
- package/apps/ui/src/components/cursor-threads-table.tsx +189 -0
- package/apps/ui/src/components/cursor-workspaces-table.tsx +140 -0
- package/apps/ui/src/components/data-table.tsx +241 -0
- package/apps/ui/src/components/delete-confirm-dialog.tsx +88 -0
- package/apps/ui/src/components/export-dialog.tsx +184 -0
- package/apps/ui/src/components/json-panel.tsx +17 -0
- package/apps/ui/src/components/kiro-sessions-table.tsx +112 -0
- package/apps/ui/src/components/kiro-workspaces-table.tsx +53 -0
- package/apps/ui/src/components/list-search-input.tsx +18 -0
- package/apps/ui/src/components/loading-panel.tsx +23 -0
- package/apps/ui/src/components/metadata-section.tsx +31 -0
- package/apps/ui/src/components/metric-card.tsx +19 -0
- package/apps/ui/src/components/opencode-sessions-table.tsx +128 -0
- package/apps/ui/src/components/opencode-workspaces-table.tsx +57 -0
- package/apps/ui/src/components/page-header.tsx +33 -0
- package/apps/ui/src/components/projects-loading-state.tsx +74 -0
- package/apps/ui/src/components/projects-table.tsx +108 -0
- package/apps/ui/src/components/qoder-sessions-table.tsx +112 -0
- package/apps/ui/src/components/qoder-workspaces-table.tsx +53 -0
- package/apps/ui/src/components/recent-threads-list.tsx +52 -0
- package/apps/ui/src/components/reload-error-panel.tsx +20 -0
- package/apps/ui/src/components/text-document-panel.tsx +19 -0
- package/apps/ui/src/components/theme-toggle.tsx +48 -0
- package/apps/ui/src/components/threads-table.tsx +202 -0
- package/apps/ui/src/components/transcript-view.tsx +552 -0
- package/apps/ui/src/components/ui/alert-dialog.tsx +160 -0
- package/apps/ui/src/components/ui/badge.tsx +45 -0
- package/apps/ui/src/components/ui/button.tsx +62 -0
- package/apps/ui/src/components/ui/checkbox.tsx +29 -0
- package/apps/ui/src/components/ui/dialog.tsx +137 -0
- package/apps/ui/src/components/ui/dropdown-menu.tsx +217 -0
- package/apps/ui/src/components/ui/input.tsx +21 -0
- package/apps/ui/src/components/ui/scroll-area.tsx +46 -0
- package/apps/ui/src/components/ui/select.tsx +163 -0
- package/apps/ui/src/components/ui/separator.tsx +28 -0
- package/apps/ui/src/components/ui/sheet.tsx +107 -0
- package/apps/ui/src/components/ui/skeleton.tsx +7 -0
- package/apps/ui/src/components/ui/table.tsx +76 -0
- package/apps/ui/src/components/ui/tabs.tsx +71 -0
- package/apps/ui/src/components/ui/tooltip.tsx +44 -0
- package/apps/ui/src/integrations/tanstack-query/devtools.tsx +6 -0
- package/apps/ui/src/integrations/tanstack-query/root-provider.tsx +10 -0
- package/apps/ui/src/lib/antigravity-conversation-state.ts +28 -0
- package/apps/ui/src/lib/antigravity-queries.ts +33 -0
- package/apps/ui/src/lib/antigravity-server.ts +128 -0
- package/apps/ui/src/lib/antigravity-transcript-events.ts +335 -0
- package/apps/ui/src/lib/claude-code-queries.ts +26 -0
- package/apps/ui/src/lib/claude-code-server.ts +75 -0
- package/apps/ui/src/lib/claude-code-transcript-events.ts +154 -0
- package/apps/ui/src/lib/codex-queries.ts +66 -0
- package/apps/ui/src/lib/codex-server.ts +209 -0
- package/apps/ui/src/lib/cursor-queries.ts +37 -0
- package/apps/ui/src/lib/cursor-server.ts +272 -0
- package/apps/ui/src/lib/cursor-transcript-events.ts +229 -0
- package/apps/ui/src/lib/download.ts +166 -0
- package/apps/ui/src/lib/formatters.ts +149 -0
- package/apps/ui/src/lib/kiro-queries.ts +22 -0
- package/apps/ui/src/lib/kiro-server.ts +73 -0
- package/apps/ui/src/lib/kiro-transcript-events.ts +113 -0
- package/apps/ui/src/lib/opencode-queries.ts +37 -0
- package/apps/ui/src/lib/opencode-server.ts +73 -0
- package/apps/ui/src/lib/opencode-transcript-events.ts +221 -0
- package/apps/ui/src/lib/package-metadata.ts +16 -0
- package/apps/ui/src/lib/path-utils.ts +13 -0
- package/apps/ui/src/lib/qoder-queries.ts +22 -0
- package/apps/ui/src/lib/qoder-server.ts +79 -0
- package/apps/ui/src/lib/qoder-transcript-events.ts +139 -0
- package/apps/ui/src/lib/route-search.ts +68 -0
- package/apps/ui/src/lib/settings-store.tsx +59 -0
- package/apps/ui/src/lib/source-session-export-server.ts +56 -0
- package/apps/ui/src/lib/text-filter.ts +22 -0
- package/apps/ui/src/lib/thread-id.ts +3 -0
- package/apps/ui/src/lib/thread-transcript-stats.ts +57 -0
- package/apps/ui/src/lib/utils.ts +7 -0
- package/apps/ui/src/routeTree.gen.ts +730 -0
- package/apps/ui/src/router.tsx +20 -0
- package/apps/ui/src/routes/$threadId.tsx +22 -0
- package/apps/ui/src/routes/__root.tsx +127 -0
- package/apps/ui/src/routes/analytics.tsx +143 -0
- package/apps/ui/src/routes/antigravity-conversations.$conversationId.tsx +438 -0
- package/apps/ui/src/routes/antigravity.$workspaceKey.tsx +127 -0
- package/apps/ui/src/routes/antigravity.index.tsx +51 -0
- package/apps/ui/src/routes/api.v1.conversation-query.ts +12 -0
- package/apps/ui/src/routes/api.v1.conversations.$source.$id.export.ts +12 -0
- package/apps/ui/src/routes/api.v1.conversations.$source.$id.ts +12 -0
- package/apps/ui/src/routes/api.v1.conversations.ts +12 -0
- package/apps/ui/src/routes/api.v1.resolve.ts +12 -0
- package/apps/ui/src/routes/api.v1.sources.ts +12 -0
- package/apps/ui/src/routes/claude-code-sessions.$sessionId.tsx +342 -0
- package/apps/ui/src/routes/claude-code.$workspaceKey.tsx +135 -0
- package/apps/ui/src/routes/claude-code.index.tsx +48 -0
- package/apps/ui/src/routes/codex.$project.tsx +390 -0
- package/apps/ui/src/routes/codex.index.tsx +116 -0
- package/apps/ui/src/routes/cursor-threads.$composerId.tsx +435 -0
- package/apps/ui/src/routes/cursor.$workspaceKey.tsx +416 -0
- package/apps/ui/src/routes/cursor.index.tsx +120 -0
- package/apps/ui/src/routes/index.tsx +124 -0
- package/apps/ui/src/routes/kiro-sessions.$sessionId.tsx +345 -0
- package/apps/ui/src/routes/kiro.$workspaceKey.tsx +136 -0
- package/apps/ui/src/routes/kiro.index.tsx +48 -0
- package/apps/ui/src/routes/opencode-sessions.$sessionId.tsx +334 -0
- package/apps/ui/src/routes/opencode.$workspaceKey.tsx +135 -0
- package/apps/ui/src/routes/opencode.index.tsx +48 -0
- package/apps/ui/src/routes/qoder-sessions.$sessionId.tsx +341 -0
- package/apps/ui/src/routes/qoder.$workspaceKey.tsx +139 -0
- package/apps/ui/src/routes/qoder.index.tsx +48 -0
- package/apps/ui/src/routes/settings.tsx +91 -0
- package/apps/ui/src/routes/threads.$threadId.tsx +619 -0
- package/apps/ui/src/styles.css +122 -0
- package/apps/ui/tsconfig.json +29 -0
- package/apps/ui/vite.config.ts +84 -0
- package/bin/spiracha.ts +32 -0
- package/package.json +46 -73
- package/src/client.ts +290 -0
- package/src/lib/antigravity-db.ts +213 -19
- package/src/lib/antigravity-exporter-types.ts +1 -0
- package/src/lib/codex-analytics.ts +1 -1
- package/src/lib/codex-browser-db.ts +410 -74
- package/src/lib/codex-browser-export.ts +6 -14
- package/src/lib/codex-browser-types.ts +1 -1
- package/src/lib/{codex-exporter-types.ts → codex-thread-types.ts} +2 -30
- package/src/lib/{codex-exporter-transcript.ts → codex-transcript-renderer.ts} +64 -28
- package/src/lib/conversation-api.ts +792 -0
- package/src/lib/conversation-data/adapter-helpers.ts +110 -0
- package/src/lib/conversation-data/antigravity-adapter.ts +148 -0
- package/src/lib/conversation-data/claude-code-adapter.ts +175 -0
- package/src/lib/conversation-data/codex-adapter.ts +245 -0
- package/src/lib/conversation-data/cursor-adapter.ts +171 -0
- package/src/lib/conversation-data/index.ts +311 -0
- package/src/lib/conversation-data/kiro-adapter.ts +140 -0
- package/src/lib/conversation-data/message-selector.ts +37 -0
- package/src/lib/conversation-data/opencode-adapter.ts +180 -0
- package/src/lib/conversation-data/path-match.ts +79 -0
- package/src/lib/conversation-data/qoder-adapter.ts +230 -0
- package/src/lib/conversation-data/types.ts +116 -0
- package/src/lib/cursor-db.ts +67 -21
- package/src/lib/cursor-exporter-types.ts +0 -19
- package/src/lib/qoder-acp-client.ts +268 -0
- package/src/lib/qoder-db.ts +1601 -0
- package/src/lib/qoder-exporter-types.ts +114 -0
- package/src/lib/qoder-transcript-phase.ts +41 -0
- package/src/lib/qoder-transcript.ts +112 -0
- package/apps/ui/dist/client/assets/_threadId-CAIeH5mq.js +0 -1
- package/apps/ui/dist/client/assets/analytics-DOy1b6Sh.js +0 -1
- package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-DqySVO2K.js +0 -7
- package/apps/ui/dist/client/assets/antigravity-conversations._conversationId-KAcXtNxI.js +0 -1
- package/apps/ui/dist/client/assets/antigravity-keychain-panel-B77qJz6f.js +0 -1
- package/apps/ui/dist/client/assets/antigravity._workspaceKey-B3NM6gRH.js +0 -1
- package/apps/ui/dist/client/assets/antigravity._workspaceKey-ByitGWki.js +0 -1
- package/apps/ui/dist/client/assets/antigravity.index-DP9JC2P9.js +0 -1
- package/apps/ui/dist/client/assets/antigravity.index-DgW25FEV.js +0 -1
- package/apps/ui/dist/client/assets/badge-C3i4OKs8.js +0 -1
- package/apps/ui/dist/client/assets/checkbox-CdHitXWQ.js +0 -1
- package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-8pQ55ci2.js +0 -1
- package/apps/ui/dist/client/assets/claude-code-sessions._sessionId-DVz5UmtU.js +0 -1
- package/apps/ui/dist/client/assets/claude-code._workspaceKey-BBKskSum.js +0 -1
- package/apps/ui/dist/client/assets/claude-code._workspaceKey-OkikMUFs.js +0 -1
- package/apps/ui/dist/client/assets/claude-code.index-Cwu76dbb.js +0 -1
- package/apps/ui/dist/client/assets/claude-code.index-D6eMd08t.js +0 -1
- package/apps/ui/dist/client/assets/createServerFn-B-KkwmHU.js +0 -3
- package/apps/ui/dist/client/assets/cursor-threads._composerId-CmBFclK8.js +0 -1
- package/apps/ui/dist/client/assets/cursor-threads._composerId-hBWlP1D-.js +0 -1
- package/apps/ui/dist/client/assets/cursor._workspaceKey-BFPkIRi-.js +0 -1
- package/apps/ui/dist/client/assets/cursor._workspaceKey-CaAZjGmm.js +0 -1
- package/apps/ui/dist/client/assets/cursor.index-8y4o20kb.js +0 -2
- package/apps/ui/dist/client/assets/cursor.index-CrnMwDCi.js +0 -1
- package/apps/ui/dist/client/assets/data-table-Br78_dk3.js +0 -4
- package/apps/ui/dist/client/assets/delete-confirm-dialog-Bxs07u-j.js +0 -7
- package/apps/ui/dist/client/assets/dist-B9pyYCVU.js +0 -1
- package/apps/ui/dist/client/assets/dist-BrJhN2A0.js +0 -5
- package/apps/ui/dist/client/assets/dist-Cmd3AIfD.js +0 -1
- package/apps/ui/dist/client/assets/dist-DvMS2965.js +0 -1
- package/apps/ui/dist/client/assets/download-Bf0QJKD3.js +0 -1
- package/apps/ui/dist/client/assets/dropdown-menu-D5cvPaZt.js +0 -1
- package/apps/ui/dist/client/assets/es2015-ad6040dw.js +0 -41
- package/apps/ui/dist/client/assets/export-dialog-Dr8d2MqD.js +0 -1
- package/apps/ui/dist/client/assets/formatters-BtqyrX_c.js +0 -1
- package/apps/ui/dist/client/assets/index-C-STgIH4.js +0 -166
- package/apps/ui/dist/client/assets/jsx-runtime-DGeXAQPT.js +0 -1
- package/apps/ui/dist/client/assets/kiro-sessions._sessionId-CKgfJ7GR.js +0 -1
- package/apps/ui/dist/client/assets/kiro-sessions._sessionId-zvIJHtQF.js +0 -1
- package/apps/ui/dist/client/assets/kiro._workspaceKey-DhVuJuZB.js +0 -1
- package/apps/ui/dist/client/assets/kiro._workspaceKey-QArsjkTY.js +0 -1
- package/apps/ui/dist/client/assets/kiro.index-C-fr4m7i.js +0 -1
- package/apps/ui/dist/client/assets/kiro.index-OYgAdtZd.js +0 -1
- package/apps/ui/dist/client/assets/metric-card-Dplm0ZiM.js +0 -1
- package/apps/ui/dist/client/assets/opencode-sessions._sessionId-DLjiTst-.js +0 -1
- package/apps/ui/dist/client/assets/opencode-sessions._sessionId-biBwrRbt.js +0 -8
- package/apps/ui/dist/client/assets/opencode._workspaceKey-C7OIzMOJ.js +0 -1
- package/apps/ui/dist/client/assets/opencode._workspaceKey-sBakX0oI.js +0 -1
- package/apps/ui/dist/client/assets/opencode.index-Bl_kNs9N.js +0 -1
- package/apps/ui/dist/client/assets/opencode.index-CN53bVmb.js +0 -1
- package/apps/ui/dist/client/assets/page-header-Cwa3p6Tl.js +0 -1
- package/apps/ui/dist/client/assets/preload-helper-B8fFrdxC.js +0 -1
- package/apps/ui/dist/client/assets/projects._project-D8WloxQN.js +0 -1
- package/apps/ui/dist/client/assets/projects._project-DSDwH4NF.js +0 -1
- package/apps/ui/dist/client/assets/projects.index-5xRtuJdX.js +0 -3
- package/apps/ui/dist/client/assets/projects.index-DEfhWqa8.js +0 -1
- package/apps/ui/dist/client/assets/react-dom-DL96Jor4.js +0 -1
- package/apps/ui/dist/client/assets/refresh-ccw-BgKjOiA6.js +0 -1
- package/apps/ui/dist/client/assets/reload-error-panel-AHqu0akK.js +0 -1
- package/apps/ui/dist/client/assets/routes-DnzF_9CX.js +0 -1
- package/apps/ui/dist/client/assets/scroll-text-fM0sMOB3.js +0 -1
- package/apps/ui/dist/client/assets/select-CYF6pF37.js +0 -1
- package/apps/ui/dist/client/assets/settings-Dx70jgP_.js +0 -1
- package/apps/ui/dist/client/assets/sqlite-error-B6uZjUe8.js +0 -1
- package/apps/ui/dist/client/assets/styles-B7Zi9EFA.css +0 -1
- package/apps/ui/dist/client/assets/tabs-CmuhkT-c.js +0 -7
- package/apps/ui/dist/client/assets/text-filter-DVAZySUS.js +0 -2
- package/apps/ui/dist/client/assets/thread-transcript-stats-BUNz6u7F.js +0 -1
- package/apps/ui/dist/client/assets/threads._threadId-BB9tTsV4.js +0 -1
- package/apps/ui/dist/client/assets/threads._threadId-BMRSFow3.js +0 -1
- package/apps/ui/dist/client/assets/useMutation-BSFult2i.js +0 -1
- package/apps/ui/dist/client/assets/useQuery-CjINKZf1.js +0 -1
- package/apps/ui/dist/server/assets/_tanstack-start-manifest_v-CQ8Jjs3B.js +0 -387
- package/apps/ui/dist/server/assets/_threadId-B6SrBR9E.js +0 -6
- package/apps/ui/dist/server/assets/analytics-CYP_LT5Y.js +0 -16
- package/apps/ui/dist/server/assets/analytics-CtpOMVMO.js +0 -146
- package/apps/ui/dist/server/assets/antigravity-conversation-state-HgzS302O.js +0 -16
- package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-BKOyL2T6.js +0 -613
- package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-D426O-64.js +0 -11
- package/apps/ui/dist/server/assets/antigravity-conversations._conversationId-eS87Dx7g.js +0 -20
- package/apps/ui/dist/server/assets/antigravity-db-Bh8_U9uw.js +0 -580
- package/apps/ui/dist/server/assets/antigravity-keychain-DOiuHDwK.js +0 -126
- package/apps/ui/dist/server/assets/antigravity-keychain-panel-CC7FLmAK.js +0 -55
- package/apps/ui/dist/server/assets/antigravity-queries-CGrJO9Vr.js +0 -37
- package/apps/ui/dist/server/assets/antigravity-server-CHRjVFqN.js +0 -114
- package/apps/ui/dist/server/assets/antigravity._workspaceKey-3m_MzNFA.js +0 -11
- package/apps/ui/dist/server/assets/antigravity._workspaceKey-B0QeYUOh.js +0 -28
- package/apps/ui/dist/server/assets/antigravity._workspaceKey-C3kP-qyN.js +0 -210
- package/apps/ui/dist/server/assets/antigravity.index-CPCYkqCi.js +0 -104
- package/apps/ui/dist/server/assets/antigravity.index-DudTB3Tq.js +0 -11
- package/apps/ui/dist/server/assets/badge-EvdhKK_Z.js +0 -26
- package/apps/ui/dist/server/assets/button-CmTDnzOn.js +0 -46
- package/apps/ui/dist/server/assets/checkbox-C0hovF41.js +0 -19
- package/apps/ui/dist/server/assets/claude-code-db-Ik3VStKZ.js +0 -361
- package/apps/ui/dist/server/assets/claude-code-queries-Cgzi4K-e.js +0 -37
- package/apps/ui/dist/server/assets/claude-code-server-PfraClXS.js +0 -72
- package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-C55oe6zj.js +0 -18
- package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-D1RYYi3j.js +0 -473
- package/apps/ui/dist/server/assets/claude-code-sessions._sessionId-DSvPLEUL.js +0 -11
- package/apps/ui/dist/server/assets/claude-code-transcript-C-bxh3cS.js +0 -139
- package/apps/ui/dist/server/assets/claude-code-transcript-phase-DmUMc8VU.js +0 -10
- package/apps/ui/dist/server/assets/claude-code._workspaceKey-B5Xg_-tE.js +0 -28
- package/apps/ui/dist/server/assets/claude-code._workspaceKey-BPlzyXPa.js +0 -11
- package/apps/ui/dist/server/assets/claude-code._workspaceKey-DqDve2wl.js +0 -191
- package/apps/ui/dist/server/assets/claude-code.index-B7yYR7dD.js +0 -92
- package/apps/ui/dist/server/assets/claude-code.index-BUHThG1W.js +0 -11
- package/apps/ui/dist/server/assets/codex-queries-CtgeZ7VL.js +0 -99
- package/apps/ui/dist/server/assets/codex-server-CGXU4H8-.js +0 -2294
- package/apps/ui/dist/server/assets/concurrency-VXtYvlGh.js +0 -18
- package/apps/ui/dist/server/assets/createServerRpc-CF_DEwnm.js +0 -12
- package/apps/ui/dist/server/assets/createSsrRpc-C754NPki.js +0 -16
- package/apps/ui/dist/server/assets/cursor-db-CZnYy7aT.js +0 -830
- package/apps/ui/dist/server/assets/cursor-exporter-types-CI3goo-c.js +0 -34
- package/apps/ui/dist/server/assets/cursor-queries-NCIM0Nat.js +0 -67
- package/apps/ui/dist/server/assets/cursor-recovery-CXpO8KcD.js +0 -361
- package/apps/ui/dist/server/assets/cursor-server-DNu52A3K.js +0 -213
- package/apps/ui/dist/server/assets/cursor-threads._composerId-BB0Y_Mao.js +0 -11
- package/apps/ui/dist/server/assets/cursor-threads._composerId-Ckn6ItHI.js +0 -582
- package/apps/ui/dist/server/assets/cursor-threads._composerId-p9-ARAzc.js +0 -18
- package/apps/ui/dist/server/assets/cursor-transcript-B7tGnqtn.js +0 -125
- package/apps/ui/dist/server/assets/cursor._workspaceKey-CZuohIUL.js +0 -28
- package/apps/ui/dist/server/assets/cursor._workspaceKey-DPp5JSjy.js +0 -401
- package/apps/ui/dist/server/assets/cursor._workspaceKey-nmg3YIOQ.js +0 -11
- package/apps/ui/dist/server/assets/cursor.index-CcsX7DG0.js +0 -11
- package/apps/ui/dist/server/assets/cursor.index-DkWT-mxw.js +0 -189
- package/apps/ui/dist/server/assets/data-table-Cdct823O.js +0 -189
- package/apps/ui/dist/server/assets/delete-confirm-dialog-BcBNCxWB.js +0 -144
- package/apps/ui/dist/server/assets/download-DMmiy1xf.js +0 -92
- package/apps/ui/dist/server/assets/dropdown-menu-Dy_9t6TN.js +0 -36
- package/apps/ui/dist/server/assets/empty-plugin-adapters-B3lHh1La.js +0 -5
- package/apps/ui/dist/server/assets/export-dialog-D88ze9Gy.js +0 -240
- package/apps/ui/dist/server/assets/formatters-FJaGZgJk.js +0 -91
- package/apps/ui/dist/server/assets/kiro-db--fXrED_-.js +0 -552
- package/apps/ui/dist/server/assets/kiro-queries-CzNlM2ok.js +0 -37
- package/apps/ui/dist/server/assets/kiro-server-9WRxg2Au.js +0 -72
- package/apps/ui/dist/server/assets/kiro-sessions._sessionId-CRY2c7YO.js +0 -11
- package/apps/ui/dist/server/assets/kiro-sessions._sessionId-F1UlwxmR.js +0 -449
- package/apps/ui/dist/server/assets/kiro-sessions._sessionId-bvTulT7C.js +0 -18
- package/apps/ui/dist/server/assets/kiro-transcript-DoekQBaH.js +0 -112
- package/apps/ui/dist/server/assets/kiro-transcript-phase-CJG40nQg.js +0 -27
- package/apps/ui/dist/server/assets/kiro._workspaceKey-BDe9sQwo.js +0 -11
- package/apps/ui/dist/server/assets/kiro._workspaceKey-CJsjgNwO.js +0 -28
- package/apps/ui/dist/server/assets/kiro._workspaceKey-D_-4Qb7y.js +0 -193
- package/apps/ui/dist/server/assets/kiro.index-C__-UROk.js +0 -11
- package/apps/ui/dist/server/assets/kiro.index-CmTbqeYj.js +0 -93
- package/apps/ui/dist/server/assets/loading-panel-BGFnWseS.js +0 -27
- package/apps/ui/dist/server/assets/metric-card-ByEeLu0r.js +0 -23
- package/apps/ui/dist/server/assets/model-label-B1NWGc65.js +0 -13
- package/apps/ui/dist/server/assets/opencode-db-BM7KjOzc.js +0 -397
- package/apps/ui/dist/server/assets/opencode-queries-BeNYXnQv.js +0 -50
- package/apps/ui/dist/server/assets/opencode-server-BpQ_kRze.js +0 -72
- package/apps/ui/dist/server/assets/opencode-sessions._sessionId-CGQ-t0vD.js +0 -518
- package/apps/ui/dist/server/assets/opencode-sessions._sessionId-D8Q7in_Z.js +0 -18
- package/apps/ui/dist/server/assets/opencode-sessions._sessionId-DKOvi0lV.js +0 -11
- package/apps/ui/dist/server/assets/opencode-think-tags-CAoD-EcZ.js +0 -87
- package/apps/ui/dist/server/assets/opencode-transcript-BNTcGNym.js +0 -141
- package/apps/ui/dist/server/assets/opencode-transcript-phase-OqLkiQD0.js +0 -32
- package/apps/ui/dist/server/assets/opencode._workspaceKey-BdqcWHw1.js +0 -11
- package/apps/ui/dist/server/assets/opencode._workspaceKey-CfH96HTT.js +0 -28
- package/apps/ui/dist/server/assets/opencode._workspaceKey-DdbHPDrO.js +0 -207
- package/apps/ui/dist/server/assets/opencode.index-BbVzkJXP.js +0 -11
- package/apps/ui/dist/server/assets/opencode.index-Vh_Gq_1L.js +0 -93
- package/apps/ui/dist/server/assets/page-header-VNSaM3xd.js +0 -29
- package/apps/ui/dist/server/assets/path-transforms-DL2IwtYd.js +0 -31
- package/apps/ui/dist/server/assets/projects._project-4io5LO0E.js +0 -20
- package/apps/ui/dist/server/assets/projects._project-Bshqk7JA.js +0 -12
- package/apps/ui/dist/server/assets/projects._project-D6ZoGhJ8.js +0 -395
- package/apps/ui/dist/server/assets/projects.index-BLXOx5eL.js +0 -12
- package/apps/ui/dist/server/assets/projects.index-BkLiF2FF.js +0 -182
- package/apps/ui/dist/server/assets/projects.index-DesYXwfi.js +0 -14
- package/apps/ui/dist/server/assets/reload-error-panel-BJMxY3U1.js +0 -25
- package/apps/ui/dist/server/assets/route-search-ts4W9MJ9.js +0 -38
- package/apps/ui/dist/server/assets/router-Sac2DGk6.js +0 -518
- package/apps/ui/dist/server/assets/routes-Bsact1uB.js +0 -184
- package/apps/ui/dist/server/assets/routes-BzkJgq4W.js +0 -34
- package/apps/ui/dist/server/assets/select-GW76p-ld.js +0 -76
- package/apps/ui/dist/server/assets/settings-OayxIYQQ.js +0 -100
- package/apps/ui/dist/server/assets/settings-store-DpEJEQ7M.js +0 -52
- package/apps/ui/dist/server/assets/shared-DyhChtHf.js +0 -137
- package/apps/ui/dist/server/assets/source-session-export-server-DNutCawb.js +0 -38
- package/apps/ui/dist/server/assets/sqlite-error-LZDrnxdd.js +0 -13
- package/apps/ui/dist/server/assets/start-B_HFwkkk.js +0 -4
- package/apps/ui/dist/server/assets/tabs-DkaChNVg.js +0 -501
- package/apps/ui/dist/server/assets/text-filter-CGKxMCKt.js +0 -36
- package/apps/ui/dist/server/assets/thread-transcript-stats-Dh34mt2u.js +0 -45
- package/apps/ui/dist/server/assets/threads._threadId-BSSK4nkI.js +0 -26
- package/apps/ui/dist/server/assets/threads._threadId-BeXEc4Lo.js +0 -648
- package/apps/ui/dist/server/assets/threads._threadId-Ci0S4mKU.js +0 -18
- package/apps/ui/dist/server/assets/ui-export-files-BHLX9bhN.js +0 -83
- package/apps/ui/dist/server/assets/utils-C_uf36nf.js +0 -8
- package/apps/ui/dist/server/server.js +0 -5895
- package/bin/codex-chats-claude.js +0 -5
- package/bin/codex-chats.js +0 -5
- package/bin/spiracha.js +0 -5
- package/src/export-chats.ts +0 -120
- package/src/export-claude.ts +0 -36
- package/src/export-cursor.ts +0 -244
- package/src/lib/claude-exporter.ts +0 -864
- package/src/lib/codex-exporter-cli.ts +0 -277
- package/src/lib/codex-exporter-db.ts +0 -319
- package/src/lib/codex-exporter.ts +0 -115
- package/src/lib/cursor-exporter.ts +0 -266
- package/src/lib/interactive-cli.ts +0 -433
- package/src/lib/native-open.ts +0 -54
- package/src/mcp-server.ts +0 -137
- package/src/spiracha.ts +0 -116
- package/src/ui-cli.ts +0 -310
- /package/apps/ui/{dist/client → public}/icon.svg +0 -0
- /package/apps/ui/{dist/client → public}/manifest.json +0 -0
- /package/apps/ui/{dist/client → public}/robots.txt +0 -0
package/src/lib/cursor-db.ts
CHANGED
|
@@ -360,8 +360,11 @@ export const groupCursorBuckets = (buckets: CursorWorkspaceBucket[]): CursorWork
|
|
|
360
360
|
return groups.sort((a, b) => b.lastActiveMs - a.lastActiveMs);
|
|
361
361
|
};
|
|
362
362
|
|
|
363
|
-
export const listCursorWorkspaceGroups = async (
|
|
364
|
-
|
|
363
|
+
export const listCursorWorkspaceGroups = async (
|
|
364
|
+
userDir = resolveCursorUserDir(),
|
|
365
|
+
options: CursorDiscoveryOptions = {},
|
|
366
|
+
): Promise<CursorWorkspaceGroup[]> => {
|
|
367
|
+
return (await discoverCursorWorkspaces(userDir, options)).groups;
|
|
365
368
|
};
|
|
366
369
|
|
|
367
370
|
export const cursorBucketMatchesQuery = (bucket: CursorWorkspaceBucket, query: string): boolean => {
|
|
@@ -462,6 +465,7 @@ export const findCursorTranscriptDirs = async (
|
|
|
462
465
|
|
|
463
466
|
export type ListCursorThreadsOptions = {
|
|
464
467
|
includeTranscriptDirs?: boolean;
|
|
468
|
+
updatedAfterMs?: number;
|
|
465
469
|
};
|
|
466
470
|
|
|
467
471
|
export const listCursorThreadsForGroup = async (
|
|
@@ -469,7 +473,7 @@ export const listCursorThreadsForGroup = async (
|
|
|
469
473
|
userDir = resolveCursorUserDir(),
|
|
470
474
|
options: ListCursorThreadsOptions = {},
|
|
471
475
|
): Promise<CursorThreadSummary[]> => {
|
|
472
|
-
const discovery = await discoverCursorWorkspaces(userDir);
|
|
476
|
+
const discovery = await discoverCursorWorkspaces(userDir, options);
|
|
473
477
|
const threads = discovery.threadsByKey.get(group.key) ?? [];
|
|
474
478
|
|
|
475
479
|
if (options.includeTranscriptDirs === false) {
|
|
@@ -505,6 +509,10 @@ type CursorDiscovery = {
|
|
|
505
509
|
threadsByKey: Map<string, CursorThreadSummary[]>;
|
|
506
510
|
};
|
|
507
511
|
|
|
512
|
+
type CursorDiscoveryOptions = {
|
|
513
|
+
updatedAfterMs?: number;
|
|
514
|
+
};
|
|
515
|
+
|
|
508
516
|
// Discovery does a full scan of the (potentially multi-GB) global DB, so cache it briefly. Writes
|
|
509
517
|
// (recover/prune/delete) call invalidateCursorDiscoveryCache() so the UI never shows stale results.
|
|
510
518
|
const DISCOVERY_TTL_MS = 60_000;
|
|
@@ -662,7 +670,20 @@ const inferFolderFromBubbles = (db: Database, composerId: string): string | null
|
|
|
662
670
|
return inferFolderFromPaths(paths);
|
|
663
671
|
};
|
|
664
672
|
|
|
665
|
-
const readAllHeads = (db: Database): Map<string, GlobalHead> => {
|
|
673
|
+
const readAllHeads = (db: Database, options: CursorDiscoveryOptions = {}): Map<string, GlobalHead> => {
|
|
674
|
+
if (options.updatedAfterMs !== undefined) {
|
|
675
|
+
const rows = db
|
|
676
|
+
.query(
|
|
677
|
+
`SELECT substr(key, 14) AS id, value
|
|
678
|
+
FROM cursorDiskKV
|
|
679
|
+
WHERE key LIKE 'composerData:%'
|
|
680
|
+
AND COALESCE(json_extract(value, '$.lastUpdatedAt'), 0) >= ?`,
|
|
681
|
+
)
|
|
682
|
+
.all(options.updatedAfterMs) as Array<{ id: string; value: string }>;
|
|
683
|
+
|
|
684
|
+
return new Map(rows.map((row) => [row.id, parseGlobalHead(row.value)]));
|
|
685
|
+
}
|
|
686
|
+
|
|
666
687
|
const rows = db
|
|
667
688
|
.query(`SELECT substr(key, 14) AS id, value FROM cursorDiskKV WHERE key LIKE 'composerData:%'`)
|
|
668
689
|
.all() as Array<{ id: string; value: string }>;
|
|
@@ -693,17 +714,28 @@ const parseGlobalHead = (value: string): GlobalHead => {
|
|
|
693
714
|
};
|
|
694
715
|
};
|
|
695
716
|
|
|
696
|
-
const readBubbleStats = (db: Database): Map<string, BubbleStat> => {
|
|
717
|
+
const readBubbleStats = (db: Database, composerIds?: Iterable<string>): Map<string, BubbleStat> => {
|
|
718
|
+
const ids = composerIds ? [...composerIds] : null;
|
|
719
|
+
if (ids?.length === 0) {
|
|
720
|
+
return new Map();
|
|
721
|
+
}
|
|
722
|
+
|
|
697
723
|
// Keys are `bubbleId:<composerId>:<bubbleId>`; composer ids contain no colon, so slice up to the
|
|
698
724
|
// next ':' rather than assuming a fixed UUID length (keeps tests and any id format working).
|
|
699
|
-
const
|
|
700
|
-
|
|
701
|
-
`SELECT substr(key, 10, instr(substr(key, 10), ':') - 1) AS id,
|
|
725
|
+
const query =
|
|
726
|
+
ids === null
|
|
727
|
+
? `SELECT substr(key, 10, instr(substr(key, 10), ':') - 1) AS id,
|
|
728
|
+
COUNT(*) AS count,
|
|
729
|
+
COALESCE(SUM(length(value)), 0) AS bytes
|
|
730
|
+
FROM cursorDiskKV WHERE key GLOB 'bubbleId:*:*' GROUP BY id`
|
|
731
|
+
: `SELECT substr(key, 10, instr(substr(key, 10), ':') - 1) AS id,
|
|
702
732
|
COUNT(*) AS count,
|
|
703
733
|
COALESCE(SUM(length(value)), 0) AS bytes
|
|
704
|
-
FROM cursorDiskKV
|
|
705
|
-
|
|
706
|
-
|
|
734
|
+
FROM cursorDiskKV
|
|
735
|
+
WHERE key GLOB 'bubbleId:*:*'
|
|
736
|
+
AND substr(key, 10, instr(substr(key, 10), ':') - 1) IN (${ids.map(() => '?').join(',')})
|
|
737
|
+
GROUP BY id`;
|
|
738
|
+
const rows = db.query(query).all(...(ids ?? [])) as Array<{ id: string; count: number; bytes: number }>;
|
|
707
739
|
|
|
708
740
|
return new Map(rows.map((row) => [row.id, { bytes: row.bytes, count: row.count }]));
|
|
709
741
|
};
|
|
@@ -936,14 +968,13 @@ const buildDiscoveryGroups = (
|
|
|
936
968
|
return groups.sort((a, b) => b.lastActiveMs - a.lastActiveMs);
|
|
937
969
|
};
|
|
938
970
|
|
|
939
|
-
const buildDiscovery = async (userDir: string): Promise<CursorDiscovery> => {
|
|
971
|
+
const buildDiscovery = async (userDir: string, options: CursorDiscoveryOptions = {}): Promise<CursorDiscovery> => {
|
|
940
972
|
const buckets = await loadCursorBuckets(userDir);
|
|
941
973
|
const bucketGroups = groupCursorBuckets(buckets);
|
|
942
|
-
const fileHistoryActivity = await readCursorFileHistoryProjectActivity(userDir);
|
|
943
974
|
const globalDbPath = getCursorGlobalDbPath(userDir);
|
|
944
975
|
|
|
945
976
|
if (!(await pathExists(globalDbPath))) {
|
|
946
|
-
return assembleDiscovery([], bucketGroups,
|
|
977
|
+
return assembleDiscovery([], bucketGroups, new Map());
|
|
947
978
|
}
|
|
948
979
|
|
|
949
980
|
const bucketIdToGroupKey = new Map<string, string>();
|
|
@@ -955,14 +986,20 @@ const buildDiscovery = async (userDir: string): Promise<CursorDiscovery> => {
|
|
|
955
986
|
}
|
|
956
987
|
}
|
|
957
988
|
|
|
958
|
-
const headerInfo = readHeaderInfo(globalDbPath);
|
|
959
|
-
const bucketComposerIds = collectBucketComposerIds(buckets);
|
|
960
|
-
|
|
961
989
|
const db = openCursorReadonlyDb(globalDbPath);
|
|
962
990
|
try {
|
|
963
|
-
const heads = readAllHeads(db);
|
|
964
|
-
|
|
965
|
-
|
|
991
|
+
const heads = readAllHeads(db, options);
|
|
992
|
+
if (options.updatedAfterMs !== undefined && heads.size === 0) {
|
|
993
|
+
return assembleDiscovery([], bucketGroups, new Map());
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
const headerInfo = readHeaderInfo(globalDbPath);
|
|
997
|
+
const bucketComposerIds = options.updatedAfterMs === undefined ? collectBucketComposerIds(buckets) : new Map();
|
|
998
|
+
const stats = readBubbleStats(db, options.updatedAfterMs === undefined ? undefined : heads.keys());
|
|
999
|
+
const universe =
|
|
1000
|
+
options.updatedAfterMs === undefined
|
|
1001
|
+
? new Set<string>([...heads.keys(), ...headerInfo.keys(), ...bucketComposerIds.keys()])
|
|
1002
|
+
: new Set<string>(heads.keys());
|
|
966
1003
|
const resolved: ResolvedThread[] = [];
|
|
967
1004
|
|
|
968
1005
|
for (const composerId of universe) {
|
|
@@ -980,13 +1017,22 @@ const buildDiscovery = async (userDir: string): Promise<CursorDiscovery> => {
|
|
|
980
1017
|
);
|
|
981
1018
|
}
|
|
982
1019
|
|
|
1020
|
+
const fileHistoryActivity =
|
|
1021
|
+
options.updatedAfterMs === undefined ? await readCursorFileHistoryProjectActivity(userDir) : new Map();
|
|
983
1022
|
return assembleDiscovery(resolved, bucketGroups, fileHistoryActivity);
|
|
984
1023
|
} finally {
|
|
985
1024
|
db.close();
|
|
986
1025
|
}
|
|
987
1026
|
};
|
|
988
1027
|
|
|
989
|
-
const discoverCursorWorkspaces = async (
|
|
1028
|
+
const discoverCursorWorkspaces = async (
|
|
1029
|
+
userDir: string,
|
|
1030
|
+
options: CursorDiscoveryOptions = {},
|
|
1031
|
+
): Promise<CursorDiscovery> => {
|
|
1032
|
+
if (options.updatedAfterMs !== undefined) {
|
|
1033
|
+
return await buildDiscovery(userDir, options);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
990
1036
|
const now = Date.now();
|
|
991
1037
|
if (discoveryCache && discoveryCache.userDir === userDir && now - discoveryCache.at < DISCOVERY_TTL_MS) {
|
|
992
1038
|
return discoveryCache.value;
|
|
@@ -152,25 +152,6 @@ export type CursorExportOptions = {
|
|
|
152
152
|
outputFormat: ExportFormat;
|
|
153
153
|
};
|
|
154
154
|
|
|
155
|
-
export type CursorCliOptions = CursorExportOptions & {
|
|
156
|
-
userDir: string;
|
|
157
|
-
workspaceQuery: string | null;
|
|
158
|
-
threadIds: string[];
|
|
159
|
-
outputDir: string | null;
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
export type CursorExportedFile = {
|
|
163
|
-
composerId: string;
|
|
164
|
-
outputPath: string;
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
export type CursorExportRunResult = {
|
|
168
|
-
outputDir: string;
|
|
169
|
-
exportedCount: number;
|
|
170
|
-
files: CursorExportedFile[];
|
|
171
|
-
missingThreadIds: string[];
|
|
172
|
-
};
|
|
173
|
-
|
|
174
155
|
export type CursorRecoverResult = {
|
|
175
156
|
workspaceKey: string;
|
|
176
157
|
activeBucketId: string;
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import net from 'node:net';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { resolveQoderUserDir } from './qoder-exporter-types';
|
|
4
|
+
import { asObject, asString, type JsonValue } from './shared';
|
|
5
|
+
|
|
6
|
+
const DEFAULT_TIMEOUT_MS = 2_500;
|
|
7
|
+
const DEFAULT_DRAIN_MS = 300;
|
|
8
|
+
const INITIALIZE_REQUEST_ID = 1;
|
|
9
|
+
const LOAD_REQUEST_ID = 2;
|
|
10
|
+
|
|
11
|
+
type JsonRpcMessage = {
|
|
12
|
+
id?: number;
|
|
13
|
+
jsonrpc?: '2.0';
|
|
14
|
+
method?: string;
|
|
15
|
+
params?: Record<string, JsonValue>;
|
|
16
|
+
result?: JsonValue;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type QoderAcpSessionUpdate = {
|
|
20
|
+
requestId: string | null;
|
|
21
|
+
sessionId: string;
|
|
22
|
+
update: Record<string, JsonValue>;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type QoderAcpSessionLoadResult = {
|
|
26
|
+
events: QoderAcpSessionUpdate[];
|
|
27
|
+
socketPath: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type QoderAcpSessionLoadOptions = {
|
|
31
|
+
cwd: string;
|
|
32
|
+
drainMs?: number;
|
|
33
|
+
requestLimit?: number;
|
|
34
|
+
sessionId: string;
|
|
35
|
+
socketPath?: string;
|
|
36
|
+
taskId?: string | null;
|
|
37
|
+
timeoutMs?: number;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const resolveQoderAcpSocketPath = (): string => {
|
|
41
|
+
const configured = process.env.SPIRACHA_QODER_SOCKET_PATH?.trim() || process.env.SPIRACHA_QODER_SOCKET?.trim();
|
|
42
|
+
return configured ? configured : path.join(path.dirname(resolveQoderUserDir()), 'SharedClientCache', 'qoder.sock');
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const encodeJsonRpcMessage = (message: JsonRpcMessage): string => {
|
|
46
|
+
const body = JSON.stringify(message);
|
|
47
|
+
return `Content-Length: ${Buffer.byteLength(body)}\r\n\r\n${body}`;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const appendSocketChunk = (
|
|
51
|
+
buffer: Buffer<ArrayBufferLike>,
|
|
52
|
+
chunk: Buffer<ArrayBufferLike> | string,
|
|
53
|
+
): Buffer<ArrayBufferLike> => {
|
|
54
|
+
return Buffer.concat([buffer, typeof chunk === 'string' ? Buffer.from(chunk) : chunk]);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const parseJsonRpcMessages = (
|
|
58
|
+
buffer: Buffer<ArrayBufferLike>,
|
|
59
|
+
): {
|
|
60
|
+
messages: JsonRpcMessage[];
|
|
61
|
+
rest: Buffer<ArrayBufferLike>;
|
|
62
|
+
} => {
|
|
63
|
+
const messages: JsonRpcMessage[] = [];
|
|
64
|
+
let rest = buffer;
|
|
65
|
+
|
|
66
|
+
while (true) {
|
|
67
|
+
const headerEnd = rest.indexOf('\r\n\r\n');
|
|
68
|
+
if (headerEnd < 0) {
|
|
69
|
+
return { messages, rest };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const header = rest.subarray(0, headerEnd).toString('utf8');
|
|
73
|
+
const lengthMatch = /Content-Length:\s*(\d+)/iu.exec(header);
|
|
74
|
+
if (!lengthMatch) {
|
|
75
|
+
return { messages, rest: Buffer.alloc(0) };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const contentLength = Number(lengthMatch[1]);
|
|
79
|
+
const bodyStart = headerEnd + 4;
|
|
80
|
+
const bodyEnd = bodyStart + contentLength;
|
|
81
|
+
if (rest.length < bodyEnd) {
|
|
82
|
+
return { messages, rest };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
messages.push(JSON.parse(rest.subarray(bodyStart, bodyEnd).toString('utf8')) as JsonRpcMessage);
|
|
87
|
+
} catch {}
|
|
88
|
+
|
|
89
|
+
rest = rest.subarray(bodyEnd);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const getRequestId = (params: Record<string, JsonValue> | null): string | null => {
|
|
94
|
+
const meta = asObject(params?._meta ?? null);
|
|
95
|
+
return asString(meta?.['ai-coding/request-id'] ?? null);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const getSessionUpdate = (message: JsonRpcMessage): QoderAcpSessionUpdate | null => {
|
|
99
|
+
if (message.method !== 'session/update') {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const params = asObject(message.params ?? null);
|
|
104
|
+
const sessionId = asString(params?.sessionId ?? null);
|
|
105
|
+
const update = asObject(params?.update ?? null);
|
|
106
|
+
if (!sessionId || !update) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return {
|
|
111
|
+
requestId: getRequestId(params),
|
|
112
|
+
sessionId,
|
|
113
|
+
update,
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export const loadQoderAcpSession = async (
|
|
118
|
+
options: QoderAcpSessionLoadOptions,
|
|
119
|
+
): Promise<QoderAcpSessionLoadResult | null> => {
|
|
120
|
+
const socketPath = options.socketPath ?? resolveQoderAcpSocketPath();
|
|
121
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
122
|
+
const drainMs = options.drainMs ?? DEFAULT_DRAIN_MS;
|
|
123
|
+
const requestLimit = options.requestLimit ?? 50;
|
|
124
|
+
|
|
125
|
+
return await new Promise<QoderAcpSessionLoadResult | null>((resolve) => {
|
|
126
|
+
const socket = net.createConnection(socketPath);
|
|
127
|
+
const events: QoderAcpSessionUpdate[] = [];
|
|
128
|
+
let buffer: Buffer<ArrayBufferLike> = Buffer.alloc(0);
|
|
129
|
+
let resolved = false;
|
|
130
|
+
let loadCompleted = false;
|
|
131
|
+
let drainTimer: ReturnType<typeof setTimeout> | null = null;
|
|
132
|
+
let timeout: ReturnType<typeof setTimeout> | null = null;
|
|
133
|
+
|
|
134
|
+
const cleanup = () => {
|
|
135
|
+
if (drainTimer) {
|
|
136
|
+
clearTimeout(drainTimer);
|
|
137
|
+
}
|
|
138
|
+
if (timeout) {
|
|
139
|
+
clearTimeout(timeout);
|
|
140
|
+
}
|
|
141
|
+
socket.destroy();
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const finish = (result: QoderAcpSessionLoadResult | null) => {
|
|
145
|
+
if (resolved) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
resolved = true;
|
|
150
|
+
cleanup();
|
|
151
|
+
resolve(result);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
timeout = setTimeout(() => {
|
|
155
|
+
finish(events.length > 0 ? { events, socketPath } : null);
|
|
156
|
+
}, timeoutMs);
|
|
157
|
+
|
|
158
|
+
const write = (message: JsonRpcMessage) => {
|
|
159
|
+
socket.write(encodeJsonRpcMessage(message));
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const sendLoadRequest = () => {
|
|
163
|
+
write({
|
|
164
|
+
id: LOAD_REQUEST_ID,
|
|
165
|
+
jsonrpc: '2.0',
|
|
166
|
+
method: 'session/load',
|
|
167
|
+
params: {
|
|
168
|
+
_meta: {
|
|
169
|
+
'ai-coding/load-request-limit': requestLimit,
|
|
170
|
+
...(options.taskId ? { 'ai-coding/quest-task-id': options.taskId } : {}),
|
|
171
|
+
},
|
|
172
|
+
cwd: options.cwd,
|
|
173
|
+
mcpServers: [],
|
|
174
|
+
sessionId: options.sessionId,
|
|
175
|
+
timestamp: Date.now(),
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const scheduleDrain = () => {
|
|
181
|
+
if (drainTimer) {
|
|
182
|
+
clearTimeout(drainTimer);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
drainTimer = setTimeout(() => {
|
|
186
|
+
finish(events.length > 0 ? { events, socketPath } : null);
|
|
187
|
+
}, drainMs);
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const recordMatchingUpdate = (message: JsonRpcMessage) => {
|
|
191
|
+
const update = getSessionUpdate(message);
|
|
192
|
+
if (update?.sessionId !== options.sessionId) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (events.length < requestLimit) {
|
|
197
|
+
events.push(update);
|
|
198
|
+
}
|
|
199
|
+
if (loadCompleted && events.length >= requestLimit) {
|
|
200
|
+
finish({ events, socketPath });
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
if (loadCompleted) {
|
|
204
|
+
scheduleDrain();
|
|
205
|
+
}
|
|
206
|
+
return true;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const markLoadCompleted = (message: JsonRpcMessage) => {
|
|
210
|
+
if (message.id !== LOAD_REQUEST_ID || loadCompleted) {
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
loadCompleted = true;
|
|
215
|
+
if (events.length >= requestLimit) {
|
|
216
|
+
finish({ events, socketPath });
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
scheduleDrain();
|
|
220
|
+
return true;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const handleMessage = (message: JsonRpcMessage) => {
|
|
224
|
+
if (message.id === INITIALIZE_REQUEST_ID) {
|
|
225
|
+
sendLoadRequest();
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (recordMatchingUpdate(message)) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
markLoadCompleted(message);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
socket.on('connect', () => {
|
|
237
|
+
write({
|
|
238
|
+
id: INITIALIZE_REQUEST_ID,
|
|
239
|
+
jsonrpc: '2.0',
|
|
240
|
+
method: 'initialize',
|
|
241
|
+
params: {
|
|
242
|
+
clientCapabilities: {},
|
|
243
|
+
ideWindowType: 'quest',
|
|
244
|
+
protocolVersion: 1,
|
|
245
|
+
timestamp: Date.now(),
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
socket.on('data', (chunk) => {
|
|
251
|
+
try {
|
|
252
|
+
const parsed = parseJsonRpcMessages(appendSocketChunk(buffer, chunk));
|
|
253
|
+
buffer = parsed.rest;
|
|
254
|
+
parsed.messages.forEach(handleMessage);
|
|
255
|
+
} catch {
|
|
256
|
+
finish(events.length > 0 ? { events, socketPath } : null);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
socket.on('error', () => {
|
|
261
|
+
finish(null);
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
socket.on('close', () => {
|
|
265
|
+
finish(events.length > 0 ? { events, socketPath } : null);
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
};
|