agentstudio 0.3.3 → 0.4.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/bin/agentstudio.js +44 -4
- package/bin/agentstudio.js.map +1 -1
- package/bin/serviceManager.d.ts.map +1 -1
- package/bin/serviceManager.js +312 -28
- package/bin/serviceManager.js.map +1 -1
- package/config/engineConfig.d.ts +96 -0
- package/config/engineConfig.d.ts.map +1 -0
- package/config/engineConfig.js +429 -0
- package/config/engineConfig.js.map +1 -0
- package/engines/claude/__tests__/supportedModels.test.d.ts +10 -0
- package/engines/claude/__tests__/supportedModels.test.d.ts.map +1 -0
- package/engines/claude/__tests__/supportedModels.test.js +89 -0
- package/engines/claude/__tests__/supportedModels.test.js.map +1 -0
- package/engines/claude/aguiAdapter.d.ts +101 -0
- package/engines/claude/aguiAdapter.d.ts.map +1 -0
- package/engines/claude/aguiAdapter.js +382 -0
- package/engines/claude/aguiAdapter.js.map +1 -0
- package/engines/claude/claudeEngine.d.ts +42 -0
- package/engines/claude/claudeEngine.d.ts.map +1 -0
- package/engines/claude/claudeEngine.js +325 -0
- package/engines/claude/claudeEngine.js.map +1 -0
- package/engines/claude/index.d.ts +8 -0
- package/engines/claude/index.d.ts.map +1 -0
- package/engines/claude/index.js +14 -0
- package/engines/claude/index.js.map +1 -0
- package/engines/cursor/__tests__/a2aAdapter.test.d.ts +6 -0
- package/engines/cursor/__tests__/a2aAdapter.test.d.ts.map +1 -0
- package/engines/cursor/__tests__/a2aAdapter.test.js +376 -0
- package/engines/cursor/__tests__/a2aAdapter.test.js.map +1 -0
- package/engines/cursor/a2aAdapter.d.ts +180 -0
- package/engines/cursor/a2aAdapter.d.ts.map +1 -0
- package/engines/cursor/a2aAdapter.js +405 -0
- package/engines/cursor/a2aAdapter.js.map +1 -0
- package/engines/cursor/aguiAdapter.d.ts +97 -0
- package/engines/cursor/aguiAdapter.d.ts.map +1 -0
- package/engines/cursor/aguiAdapter.js +507 -0
- package/engines/cursor/aguiAdapter.js.map +1 -0
- package/engines/cursor/cursorEngine.d.ts +68 -0
- package/engines/cursor/cursorEngine.d.ts.map +1 -0
- package/engines/cursor/cursorEngine.js +465 -0
- package/engines/cursor/cursorEngine.js.map +1 -0
- package/engines/cursor/index.d.ts +11 -0
- package/engines/cursor/index.d.ts.map +1 -0
- package/engines/cursor/index.js +21 -0
- package/engines/cursor/index.js.map +1 -0
- package/engines/engineManager.d.ts +80 -0
- package/engines/engineManager.d.ts.map +1 -0
- package/engines/engineManager.js +137 -0
- package/engines/engineManager.js.map +1 -0
- package/engines/index.d.ts +26 -0
- package/engines/index.d.ts.map +1 -0
- package/engines/index.js +81 -0
- package/engines/index.js.map +1 -0
- package/engines/types.d.ts +319 -0
- package/engines/types.d.ts.map +1 -0
- package/engines/types.js +69 -0
- package/engines/types.js.map +1 -0
- package/index.d.ts.map +1 -1
- package/index.js +178 -25
- package/index.js.map +1 -1
- package/middleware/auth.d.ts.map +1 -1
- package/middleware/auth.js +4 -0
- package/middleware/auth.js.map +1 -1
- package/package.json +7 -1
- package/public/assets/AgentsPage-D462iGRy.js +10 -0
- package/public/assets/{Button-BoiVlafj.js → Button-B_6lGF64.js} +1 -1
- package/public/assets/ChatPage-NjuRQPaL.js +478 -0
- package/public/assets/{CommandForm-Se4iemMp.js → CommandForm-DwGvE9A_.js} +1 -1
- package/public/assets/CommandsPage-DeUS8fhJ.js +1 -0
- package/public/assets/CursorConfigPage-Bl1Blrbr.js +1 -0
- package/public/assets/{DashboardPage-DbCVzPKz.js → DashboardPage-DH-2iuqf.js} +1 -1
- package/public/assets/EngineGate-DxTYx9wb.js +1 -0
- package/public/assets/{FileBrowser-DcoBWzKK.js → FileBrowser-CeGsJnUL.js} +5 -5
- package/public/assets/{FileExplorer-B41BB0LM.js → FileExplorer-x5R0Tcmk.js} +1 -1
- package/public/assets/GeneralSettingsPage-lhNEJQD_.js +1 -0
- package/public/assets/HooksPage-9fingjdz.js +1 -0
- package/public/assets/LandingPage-BAzi8PDo.js +1 -0
- package/public/assets/LoginPage-kQ_NWy8p.js +16 -0
- package/public/assets/McpAdminSettingsPage-DQHpWHRC.js +7 -0
- package/public/assets/McpPage-DLHfmhSJ.js +20 -0
- package/public/assets/{MemorySettingsPage-DYSuz-hU.js → MemorySettingsPage-CRIPja9X.js} +1 -1
- package/public/assets/ModelsPage-Bb5vSsuc.js +1 -0
- package/public/assets/PluginsPage-BhKM7gV7.js +12 -0
- package/public/assets/ProjectSelector-Cbct6pnn.js +1 -0
- package/public/assets/ProjectsPage-lQo7-7dt.js +21 -0
- package/public/assets/RulesPage-BRnB7__3.js +1 -0
- package/public/assets/ScheduledTasksPage-CZiABTSb.js +1 -0
- package/public/assets/SettingsLayout-BfG7ftoT.js +1 -0
- package/public/assets/SkillsPage-CL6MKxQ9.js +18 -0
- package/public/assets/{SubagentForm-C0R084ja.js → SubagentForm-BzzeWg0W.js} +2 -2
- package/public/assets/{SubagentsPage-BKFNmqxg.js → SubagentsPage-DhFP2kDE.js} +1 -1
- package/public/assets/SystemInfoPage-CFHUN3j8.js +1 -0
- package/public/assets/{TelemetrySettingsPage-Ck2btMol.js → TelemetrySettingsPage-BcZFVBXN.js} +1 -1
- package/public/assets/{ToastTestPage-B79DFhqI.js → ToastTestPage-BtGnZdyk.js} +1 -1
- package/public/assets/{ToolsList-Kfxwp80g.js → ToolsList-CTsQr53G.js} +1 -1
- package/public/assets/{UnifiedToolSelector-CkafUbz3.js → UnifiedToolSelector-BP6fuyzG.js} +1 -1
- package/public/assets/VersionSettingsPage-DjOjyL3X.js +5 -0
- package/public/assets/VoiceSettingsPage-d3l9AWBn.js +1 -0
- package/public/assets/WebSocketTunnelPage-CfHtJR9r.js +1 -0
- package/public/assets/_basePickBy-Bac3af5O.js +1 -0
- package/public/assets/{_baseUniq-COj5YnAO.js → _baseUniq-Dvh9sZ-T.js} +1 -1
- package/public/assets/{agents-3mB536QF.js → agents-KlPdWQ8K.js} +1 -1
- package/public/assets/arc-CRR5EPpK.js +1 -0
- package/public/assets/{architectureDiagram-VXUJARFQ-DD1BwT1T.js → architectureDiagram-VXUJARFQ-Ct1p8kmV.js} +1 -1
- package/public/assets/{blockDiagram-VD42YOAC-DFKUIZc6.js → blockDiagram-VD42YOAC-CX_8YiYn.js} +1 -1
- package/public/assets/{c4Diagram-YG6GDRKO-B0VVIIvh.js → c4Diagram-YG6GDRKO-BIBVWIY4.js} +1 -1
- package/public/assets/channel-CPs-2Y_m.js +1 -0
- package/public/assets/{chunk-4BX2VUAB-DM8J7YO9.js → chunk-4BX2VUAB-CQNNXsb5.js} +1 -1
- package/public/assets/{chunk-55IACEB6-BjhdmGlM.js → chunk-55IACEB6-N_ZrGhOu.js} +1 -1
- package/public/assets/{chunk-B4BG7PRW-1RJ6n2xv.js → chunk-B4BG7PRW-CI6DkhbM.js} +1 -1
- package/public/assets/{chunk-DI55MBZ5-1-EHSO67.js → chunk-DI55MBZ5-Dgj-Eo9U.js} +1 -1
- package/public/assets/{chunk-FMBD7UC4-DV3SMJK_.js → chunk-FMBD7UC4-o4B0HzSK.js} +1 -1
- package/public/assets/{chunk-QN33PNHL-IlsCTdDq.js → chunk-QN33PNHL-DXlfdPIk.js} +1 -1
- package/public/assets/{chunk-QZHKN3VN-DJXs-Fqo.js → chunk-QZHKN3VN-ZCBUGD7e.js} +1 -1
- package/public/assets/{chunk-TZMSLE5B-BxHO9wa1.js → chunk-TZMSLE5B-N3lZ106d.js} +1 -1
- package/public/assets/classDiagram-2ON5EDUG-DCwNRxvC.js +1 -0
- package/public/assets/classDiagram-v2-WZHVMYZB-DCwNRxvC.js +1 -0
- package/public/assets/clone-C3DcKvhB.js +1 -0
- package/public/assets/{cose-bilkent-S5V4N54A-BVJXoW_K.js → cose-bilkent-S5V4N54A-Crc39J9q.js} +1 -1
- package/public/assets/{dagre-6UL2VRFP-DHDnVshA.js → dagre-6UL2VRFP-nC3WLCf7.js} +1 -1
- package/public/assets/{diagram-PSM6KHXK-40qGxDeg.js → diagram-PSM6KHXK-B5DQIDQ3.js} +1 -1
- package/public/assets/diagram-QEK2KX5R-BccDOQuz.js +43 -0
- package/public/assets/{diagram-S2PKOQOG-D7AX72a5.js → diagram-S2PKOQOG-D-Cv16WE.js} +1 -1
- package/public/assets/{erDiagram-Q2GNP2WA-BHsgeBpL.js → erDiagram-Q2GNP2WA-Dr0ZgvnS.js} +1 -1
- package/public/assets/{flowDiagram-NV44I4VS-BYqChOSE.js → flowDiagram-NV44I4VS-DGbbfVi5.js} +1 -1
- package/public/assets/{ganttDiagram-LVOFAZNH-CZFFSLKX.js → ganttDiagram-LVOFAZNH-C-3Wnf96.js} +1 -1
- package/public/assets/{gitGraphDiagram-NY62KEGX-C5Bgrf0J.js → gitGraphDiagram-NY62KEGX--Q8whT5z.js} +1 -1
- package/public/assets/{graph-BP5lFRBg.js → graph-CO1DMS2E.js} +1 -1
- package/public/assets/{index-BEPv9Bqe.js → index-B5hSSnK3.js} +58 -58
- package/public/assets/index-gbHlIp96.css +1 -0
- package/public/assets/infoDiagram-F6ZHWCRC-DSR9cM2B.js +2 -0
- package/public/assets/{journeyDiagram-XKPGCS4Q--abC1RHz.js → journeyDiagram-XKPGCS4Q-Cc00zHNt.js} +1 -1
- package/public/assets/{kanban-definition-3W4ZIXB7-BJeChfWu.js → kanban-definition-3W4ZIXB7-BF_gHshF.js} +6 -6
- package/public/assets/{layout-DjAix4WK.js → layout-BxoLV88o.js} +1 -1
- package/public/assets/{linear-Cw0z8VNY.js → linear-Y8e2e012.js} +1 -1
- package/public/assets/{mindmap-definition-VGOIOE7T-U_T9xIUk.js → mindmap-definition-VGOIOE7T-CzpuQA4p.js} +1 -1
- package/public/assets/{pieDiagram-ADFJNKIX-B0mT9OgH.js → pieDiagram-ADFJNKIX-B22MhIcy.js} +2 -2
- package/public/assets/{quadrantDiagram-AYHSOK5B-BWdlgO0u.js → quadrantDiagram-AYHSOK5B-CTT9bIA8.js} +1 -1
- package/public/assets/{requirementDiagram-UZGBJVZJ-B-8LxsGB.js → requirementDiagram-UZGBJVZJ-B_vjXDH9.js} +1 -1
- package/public/assets/{sankeyDiagram-TZEHDZUN-OXuxkgGA.js → sankeyDiagram-TZEHDZUN-CKfZ4633.js} +1 -1
- package/public/assets/{sequenceDiagram-WL72ISMW-Bt5twlzi.js → sequenceDiagram-WL72ISMW-BmTPN6j6.js} +1 -1
- package/public/assets/{stateDiagram-FKZM4ZOC-Dmph7TeW.js → stateDiagram-FKZM4ZOC-y2fQE1C7.js} +1 -1
- package/public/assets/stateDiagram-v2-4FDKWEC3-C4CM6z52.js +1 -0
- package/public/assets/{table-DjMdAdjH.js → table-BJUz-ck5.js} +1 -1
- package/public/assets/{timeline-definition-IT6M3QCI-CcV8nyIH.js → timeline-definition-IT6M3QCI-DsXlR68n.js} +1 -1
- package/public/assets/{tools-BAI9XHGS.js → tools-BZTR2NP1.js} +1 -1
- package/public/assets/{treemap-KMMF4GRG-DBuwkj4f.js → treemap-KMMF4GRG-Cecs9uxX.js} +1 -1
- package/public/assets/{ui-components-DaGtjl0g.js → ui-components-DjgDPiqV.js} +153 -128
- package/public/assets/useAgents-8KXN6U61.js +2 -0
- package/public/assets/{useClaudeVersions-Cy71v4HE.js → useClaudeVersions-DicHLV6A.js} +1 -1
- package/public/assets/useCommands-DbSH48ba.js +1 -0
- package/public/assets/{useProjects-XgfgISgV.js → useProjects-Bbh6hJMM.js} +1 -1
- package/public/assets/{useSessions-CQgq4d84.js → useSessions-DOa4-xiB.js} +1 -1
- package/public/assets/{xychartDiagram-PRI3JC2R-Bo9K-U2S.js → xychartDiagram-PRI3JC2R-C2IWhyM7.js} +1 -1
- package/public/index.html +5 -5
- package/routes/a2a.d.ts +7 -0
- package/routes/a2a.d.ts.map +1 -1
- package/routes/a2a.js +193 -21
- package/routes/a2a.js.map +1 -1
- package/routes/agents.d.ts.map +1 -1
- package/routes/agents.js +45 -2
- package/routes/agents.js.map +1 -1
- package/routes/agui.d.ts +16 -0
- package/routes/agui.d.ts.map +1 -0
- package/routes/agui.js +520 -0
- package/routes/agui.js.map +1 -0
- package/routes/commands.d.ts.map +1 -1
- package/routes/commands.js +35 -3
- package/routes/commands.js.map +1 -1
- package/routes/cursorA2a.d.ts +18 -0
- package/routes/cursorA2a.d.ts.map +1 -0
- package/routes/cursorA2a.js +393 -0
- package/routes/cursorA2a.js.map +1 -0
- package/routes/engine.d.ts +12 -0
- package/routes/engine.d.ts.map +1 -0
- package/routes/engine.js +178 -0
- package/routes/engine.js.map +1 -0
- package/routes/gitVersions.d.ts +10 -0
- package/routes/gitVersions.d.ts.map +1 -0
- package/routes/gitVersions.js +147 -0
- package/routes/gitVersions.js.map +1 -0
- package/routes/hooks.d.ts +11 -0
- package/routes/hooks.d.ts.map +1 -0
- package/routes/hooks.js +303 -0
- package/routes/hooks.js.map +1 -0
- package/routes/mcp.d.ts.map +1 -1
- package/routes/mcp.js +28 -3
- package/routes/mcp.js.map +1 -1
- package/routes/plugins.d.ts.map +1 -1
- package/routes/plugins.js +317 -4
- package/routes/plugins.js.map +1 -1
- package/routes/rules.d.ts +9 -0
- package/routes/rules.d.ts.map +1 -0
- package/routes/rules.js +470 -0
- package/routes/rules.js.map +1 -0
- package/routes/sessions.d.ts.map +1 -1
- package/routes/sessions.js +68 -32
- package/routes/sessions.js.map +1 -1
- package/routes/speechToText.d.ts +8 -0
- package/routes/speechToText.d.ts.map +1 -0
- package/routes/speechToText.js +216 -0
- package/routes/speechToText.js.map +1 -0
- package/schemas/a2a.d.ts +2 -2
- package/services/__tests__/agentImporter.test.d.ts +5 -0
- package/services/__tests__/agentImporter.test.d.ts.map +1 -0
- package/services/__tests__/agentImporter.test.js +379 -0
- package/services/__tests__/agentImporter.test.js.map +1 -0
- package/services/__tests__/marketplaceUpdateService.test.d.ts +5 -0
- package/services/__tests__/marketplaceUpdateService.test.d.ts.map +1 -0
- package/services/__tests__/marketplaceUpdateService.test.js +227 -0
- package/services/__tests__/marketplaceUpdateService.test.js.map +1 -0
- package/services/__tests__/pluginInstaller.test.js +172 -0
- package/services/__tests__/pluginInstaller.test.js.map +1 -1
- package/services/__tests__/projectMetadataStorage.test.js +19 -4
- package/services/__tests__/projectMetadataStorage.test.js.map +1 -1
- package/services/a2a/__tests__/agentCardService.test.js +224 -0
- package/services/a2a/__tests__/agentCardService.test.js.map +1 -1
- package/services/a2a/__tests__/cursorA2aService.test.d.ts +6 -0
- package/services/a2a/__tests__/cursorA2aService.test.d.ts.map +1 -0
- package/services/a2a/__tests__/cursorA2aService.test.js +359 -0
- package/services/a2a/__tests__/cursorA2aService.test.js.map +1 -0
- package/services/a2a/agentCardService.d.ts +22 -0
- package/services/a2a/agentCardService.d.ts.map +1 -1
- package/services/a2a/agentCardService.js +246 -0
- package/services/a2a/agentCardService.js.map +1 -1
- package/services/a2a/cursorA2aService.d.ts +126 -0
- package/services/a2a/cursorA2aService.d.ts.map +1 -0
- package/services/a2a/cursorA2aService.js +336 -0
- package/services/a2a/cursorA2aService.js.map +1 -0
- package/services/agentImporter.d.ts +62 -0
- package/services/agentImporter.d.ts.map +1 -0
- package/services/agentImporter.js +335 -0
- package/services/agentImporter.js.map +1 -0
- package/services/cursorConfigService.d.ts +75 -0
- package/services/cursorConfigService.d.ts.map +1 -0
- package/services/cursorConfigService.js +538 -0
- package/services/cursorConfigService.js.map +1 -0
- package/services/gitVersionService.d.ts +52 -0
- package/services/gitVersionService.d.ts.map +1 -0
- package/services/gitVersionService.js +377 -0
- package/services/gitVersionService.js.map +1 -0
- package/services/marketplaceUpdateService.d.ts +66 -0
- package/services/marketplaceUpdateService.d.ts.map +1 -0
- package/services/marketplaceUpdateService.js +364 -0
- package/services/marketplaceUpdateService.js.map +1 -0
- package/services/mcpAdmin/__tests__/scheduledTaskTools.test.d.ts +5 -0
- package/services/mcpAdmin/__tests__/scheduledTaskTools.test.d.ts.map +1 -0
- package/services/mcpAdmin/__tests__/scheduledTaskTools.test.js +429 -0
- package/services/mcpAdmin/__tests__/scheduledTaskTools.test.js.map +1 -0
- package/services/mcpAdmin/tools/index.d.ts +1 -0
- package/services/mcpAdmin/tools/index.d.ts.map +1 -1
- package/services/mcpAdmin/tools/index.js +5 -1
- package/services/mcpAdmin/tools/index.js.map +1 -1
- package/services/mcpAdmin/tools/scheduledTaskTools.d.ts +64 -0
- package/services/mcpAdmin/tools/scheduledTaskTools.d.ts.map +1 -0
- package/services/mcpAdmin/tools/scheduledTaskTools.js +1002 -0
- package/services/mcpAdmin/tools/scheduledTaskTools.js.map +1 -0
- package/services/mcpAdmin/types.d.ts +1 -1
- package/services/mcpAdmin/types.d.ts.map +1 -1
- package/services/pluginInstaller.d.ts +55 -1
- package/services/pluginInstaller.d.ts.map +1 -1
- package/services/pluginInstaller.js +437 -13
- package/services/pluginInstaller.js.map +1 -1
- package/services/projectMetadataStorage.d.ts.map +1 -1
- package/services/projectMetadataStorage.js +4 -2
- package/services/projectMetadataStorage.js.map +1 -1
- package/services/sessionEventBus.d.ts +67 -0
- package/services/sessionEventBus.d.ts.map +1 -0
- package/services/sessionEventBus.js +106 -0
- package/services/sessionEventBus.js.map +1 -0
- package/services/sessionManager.d.ts.map +1 -1
- package/services/sessionManager.js +4 -2
- package/services/sessionManager.js.map +1 -1
- package/services/speechToText/__tests__/speechToText.test.d.ts +5 -0
- package/services/speechToText/__tests__/speechToText.test.d.ts.map +1 -0
- package/services/speechToText/__tests__/speechToText.test.js +208 -0
- package/services/speechToText/__tests__/speechToText.test.js.map +1 -0
- package/services/speechToText/index.d.ts +25 -0
- package/services/speechToText/index.d.ts.map +1 -0
- package/services/speechToText/index.js +228 -0
- package/services/speechToText/index.js.map +1 -0
- package/services/speechToText/providers/aliyun.d.ts +22 -0
- package/services/speechToText/providers/aliyun.d.ts.map +1 -0
- package/services/speechToText/providers/aliyun.js +185 -0
- package/services/speechToText/providers/aliyun.js.map +1 -0
- package/services/speechToText/providers/google.d.ts +24 -0
- package/services/speechToText/providers/google.d.ts.map +1 -0
- package/services/speechToText/providers/google.js +205 -0
- package/services/speechToText/providers/google.js.map +1 -0
- package/services/speechToText/providers/openaiCompatible.d.ts +22 -0
- package/services/speechToText/providers/openaiCompatible.d.ts.map +1 -0
- package/services/speechToText/providers/openaiCompatible.js +198 -0
- package/services/speechToText/providers/openaiCompatible.js.map +1 -0
- package/services/speechToText/providers/tencent.d.ts +23 -0
- package/services/speechToText/providers/tencent.d.ts.map +1 -0
- package/services/speechToText/providers/tencent.js +215 -0
- package/services/speechToText/providers/tencent.js.map +1 -0
- package/services/speechToText/types.d.ts +102 -0
- package/services/speechToText/types.d.ts.map +1 -0
- package/services/speechToText/types.js +43 -0
- package/services/speechToText/types.js.map +1 -0
- package/services/taskExecutor/__tests__/mcp-tools-integration.test.d.ts +8 -2
- package/services/taskExecutor/__tests__/mcp-tools-integration.test.d.ts.map +1 -1
- package/services/taskExecutor/__tests__/mcp-tools-integration.test.js +215 -72
- package/services/taskExecutor/__tests__/mcp-tools-integration.test.js.map +1 -1
- package/services/taskExecutor/taskWorker.js +9 -1
- package/services/taskExecutor/taskWorker.js.map +1 -1
- package/services/telemetry.js +1 -1
- package/types/a2a.d.ts +20 -0
- package/types/a2a.d.ts.map +1 -1
- package/types/engine.d.ts +314 -0
- package/types/engine.d.ts.map +1 -0
- package/types/engine.js +14 -0
- package/types/engine.js.map +1 -0
- package/types/hooks.d.ts +45 -0
- package/types/hooks.d.ts.map +1 -0
- package/types/hooks.js +9 -0
- package/types/hooks.js.map +1 -0
- package/types/plugins.d.ts +86 -2
- package/types/plugins.d.ts.map +1 -1
- package/types/plugins.js +1 -0
- package/types/plugins.js.map +1 -1
- package/types/rules.d.ts +51 -0
- package/types/rules.d.ts.map +1 -0
- package/types/rules.js +9 -0
- package/types/rules.js.map +1 -0
- package/utils/__tests__/cursorIdeAgentParser.test.d.ts +7 -0
- package/utils/__tests__/cursorIdeAgentParser.test.d.ts.map +1 -0
- package/utils/__tests__/cursorIdeAgentParser.test.js +289 -0
- package/utils/__tests__/cursorIdeAgentParser.test.js.map +1 -0
- package/utils/claudeUtils.d.ts +3 -1
- package/utils/claudeUtils.d.ts.map +1 -1
- package/utils/claudeUtils.js +26 -12
- package/utils/claudeUtils.js.map +1 -1
- package/utils/cursorCliHistoryParser.d.ts +58 -0
- package/utils/cursorCliHistoryParser.d.ts.map +1 -0
- package/utils/cursorCliHistoryParser.js +664 -0
- package/utils/cursorCliHistoryParser.js.map +1 -0
- package/utils/cursorIdeAgentParser.d.ts +49 -0
- package/utils/cursorIdeAgentParser.d.ts.map +1 -0
- package/utils/cursorIdeAgentParser.js +332 -0
- package/utils/cursorIdeAgentParser.js.map +1 -0
- package/public/assets/AgentsPage-gSnkPp2k.js +0 -10
- package/public/assets/ChatPage-BMrfVkpt.js +0 -471
- package/public/assets/CommandsPage-B6u4IO7L.js +0 -1
- package/public/assets/GeneralSettingsPage-BbEbWJUQ.js +0 -1
- package/public/assets/LandingPage-DFPm2d4Y.js +0 -1
- package/public/assets/LoginPage-D5kZJqhk.js +0 -16
- package/public/assets/McpAdminSettingsPage-D32iUEjH.js +0 -7
- package/public/assets/McpPage-QT4qs391.js +0 -20
- package/public/assets/PluginsPage-BotzuK9f.js +0 -1
- package/public/assets/ProjectSelector-DujNObqr.js +0 -1
- package/public/assets/ProjectsPage-CRWe6HPl.js +0 -21
- package/public/assets/ScheduledTasksPage-Beeurg-w.js +0 -1
- package/public/assets/SettingsLayout-BfkBUyI_.js +0 -1
- package/public/assets/SkillsPage-B59bAr6W.js +0 -18
- package/public/assets/SystemInfoPage-D89s7PjE.js +0 -1
- package/public/assets/VersionSettingsPage-CaB4PH6h.js +0 -5
- package/public/assets/WebSocketTunnelPage-Cbru_-hL.js +0 -1
- package/public/assets/_basePickBy-5fAM04Ra.js +0 -1
- package/public/assets/arc-C2gTU2ZR.js +0 -1
- package/public/assets/channel-DcVTcy-S.js +0 -1
- package/public/assets/classDiagram-2ON5EDUG-BXVT6Q7h.js +0 -1
- package/public/assets/classDiagram-v2-WZHVMYZB-BXVT6Q7h.js +0 -1
- package/public/assets/clone-Bp6orjIq.js +0 -1
- package/public/assets/diagram-QEK2KX5R-BfMGeeRo.js +0 -43
- package/public/assets/index-BgR-BTTw.css +0 -1
- package/public/assets/infoDiagram-F6ZHWCRC-C6OApgqf.js +0 -2
- package/public/assets/stateDiagram-v2-4FDKWEC3-DyE8O3Kx.js +0 -1
- package/public/assets/useAgents-D5EDAc_E.js +0 -2
- package/public/assets/useCommands-BgoCfyuu.js +0 -1
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cursor CLI Agent History Parser
|
|
4
|
+
*
|
|
5
|
+
* Parses Cursor CLI agent sessions from ~/.cursor/chats/<workspace-hash>/<session-uuid>/store.db
|
|
6
|
+
* CLI sessions are stored in SQLite databases with blobs containing JSON messages.
|
|
7
|
+
*
|
|
8
|
+
* Note: IDE Agent sessions are stored separately in ~/.cursor/projects/<path>/agent-transcripts/*.txt
|
|
9
|
+
* and are handled by cursorIdeAgentParser.ts (formerly cursorHistoryParser.ts)
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.readCursorCliSessions = readCursorCliSessions;
|
|
46
|
+
exports.readCursorCliSession = readCursorCliSession;
|
|
47
|
+
const fs = __importStar(require("fs"));
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const os = __importStar(require("os"));
|
|
50
|
+
const crypto = __importStar(require("crypto"));
|
|
51
|
+
const child_process_1 = require("child_process");
|
|
52
|
+
/**
|
|
53
|
+
* Extract image references from message content and load image data
|
|
54
|
+
* Looks for @.agentstudio-images/xxx.png patterns and reads the actual files
|
|
55
|
+
*
|
|
56
|
+
* @param content - Message content that may contain @path references
|
|
57
|
+
* @param projectPath - Project path where .agentstudio-images directory is located
|
|
58
|
+
* @returns Array of image data objects
|
|
59
|
+
*/
|
|
60
|
+
function extractAndLoadImages(content, projectPath) {
|
|
61
|
+
const images = [];
|
|
62
|
+
// Match @.agentstudio-images/imageN_timestamp.ext patterns
|
|
63
|
+
const imagePathRegex = /@(\.agentstudio-images\/image\d+_\d+\.(png|jpg|jpeg|gif|webp))/gi;
|
|
64
|
+
let match;
|
|
65
|
+
let index = 0;
|
|
66
|
+
while ((match = imagePathRegex.exec(content)) !== null) {
|
|
67
|
+
const relativePath = match[1];
|
|
68
|
+
const fullPath = path.join(projectPath, relativePath);
|
|
69
|
+
try {
|
|
70
|
+
if (fs.existsSync(fullPath)) {
|
|
71
|
+
const imageBuffer = fs.readFileSync(fullPath);
|
|
72
|
+
const base64Data = imageBuffer.toString('base64');
|
|
73
|
+
const ext = path.extname(fullPath).toLowerCase().slice(1);
|
|
74
|
+
// Map extension to media type
|
|
75
|
+
const mediaTypeMap = {
|
|
76
|
+
'png': 'image/png',
|
|
77
|
+
'jpg': 'image/jpeg',
|
|
78
|
+
'jpeg': 'image/jpeg',
|
|
79
|
+
'gif': 'image/gif',
|
|
80
|
+
'webp': 'image/webp'
|
|
81
|
+
};
|
|
82
|
+
const mediaType = mediaTypeMap[ext] || 'image/png';
|
|
83
|
+
images.push({
|
|
84
|
+
id: `img_${index}_${Date.now()}`,
|
|
85
|
+
data: base64Data,
|
|
86
|
+
mediaType,
|
|
87
|
+
filename: path.basename(fullPath)
|
|
88
|
+
});
|
|
89
|
+
index++;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.warn(`[CursorCLI] Failed to load image from ${fullPath}:`, error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return images;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Execute SQLite query using native sqlite3 CLI
|
|
100
|
+
* This properly handles WAL mode which sql.js doesn't support
|
|
101
|
+
*/
|
|
102
|
+
function executeSqliteQuery(dbPath, query) {
|
|
103
|
+
try {
|
|
104
|
+
// Use -json for structured output, fall back to raw if not available
|
|
105
|
+
const result = (0, child_process_1.execSync)(`sqlite3 -json "${dbPath}" "${query}"`, {
|
|
106
|
+
encoding: 'utf-8',
|
|
107
|
+
maxBuffer: 50 * 1024 * 1024, // 50MB buffer for large results
|
|
108
|
+
});
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
console.error('[CursorCLI] SQLite query failed:', error);
|
|
113
|
+
throw error;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Execute SQLite query and return raw blob data as hex
|
|
118
|
+
*/
|
|
119
|
+
function executeSqliteBlobQuery(dbPath, query) {
|
|
120
|
+
try {
|
|
121
|
+
// Use hex() to convert blob to hex string for safe transport
|
|
122
|
+
const result = (0, child_process_1.execSync)(`sqlite3 "${dbPath}" "${query}"`, {
|
|
123
|
+
encoding: 'utf-8',
|
|
124
|
+
maxBuffer: 50 * 1024 * 1024,
|
|
125
|
+
});
|
|
126
|
+
// Parse pipe-separated output: id|hex_data
|
|
127
|
+
const lines = result.trim().split('\n').filter(line => line.length > 0);
|
|
128
|
+
return lines.map(line => {
|
|
129
|
+
const pipeIndex = line.indexOf('|');
|
|
130
|
+
if (pipeIndex === -1)
|
|
131
|
+
return { id: line, data: '' };
|
|
132
|
+
return {
|
|
133
|
+
id: line.substring(0, pipeIndex),
|
|
134
|
+
data: line.substring(pipeIndex + 1),
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
console.error('[CursorCLI] SQLite blob query failed:', error);
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Generate workspace hash from project path (MD5)
|
|
145
|
+
*/
|
|
146
|
+
function getWorkspaceHash(projectPath) {
|
|
147
|
+
// Resolve symlinks first
|
|
148
|
+
let resolvedPath = projectPath;
|
|
149
|
+
try {
|
|
150
|
+
resolvedPath = fs.realpathSync(projectPath);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// If path doesn't exist, use original
|
|
154
|
+
}
|
|
155
|
+
return crypto.createHash('md5').update(resolvedPath).digest('hex');
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get the Cursor chats directory
|
|
159
|
+
*/
|
|
160
|
+
function getCursorChatsDir() {
|
|
161
|
+
return path.join(os.homedir(), '.cursor', 'chats');
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Extract text content from message content array or string
|
|
165
|
+
*/
|
|
166
|
+
function extractTextContent(content) {
|
|
167
|
+
if (typeof content === 'string') {
|
|
168
|
+
return content;
|
|
169
|
+
}
|
|
170
|
+
if (Array.isArray(content)) {
|
|
171
|
+
return content
|
|
172
|
+
.filter((c) => c.type === 'text' && 'text' in c && typeof c.text === 'string')
|
|
173
|
+
.map(c => c.text)
|
|
174
|
+
.join('\n');
|
|
175
|
+
}
|
|
176
|
+
return '';
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Clean up user query by removing XML tags and extracting the actual query
|
|
180
|
+
*/
|
|
181
|
+
function cleanUserQuery(text) {
|
|
182
|
+
// Extract content from <user_query> tags if present
|
|
183
|
+
const userQueryMatch = text.match(/<user_query>\s*([\s\S]*?)\s*<\/user_query>/);
|
|
184
|
+
if (userQueryMatch) {
|
|
185
|
+
return userQueryMatch[1].trim();
|
|
186
|
+
}
|
|
187
|
+
// If text starts with system info tags, skip it
|
|
188
|
+
if (text.startsWith('<user_info>') || text.startsWith('<rules>')) {
|
|
189
|
+
return '';
|
|
190
|
+
}
|
|
191
|
+
return text;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Parse text content and extract thinking blocks
|
|
195
|
+
* Returns { thinking: string | null, text: string }
|
|
196
|
+
*/
|
|
197
|
+
function parseThinkingContent(text) {
|
|
198
|
+
// Match <think>...</think> or <thinking>...</thinking> blocks
|
|
199
|
+
const thinkingMatch = text.match(/<think(?:ing)?>\s*([\s\S]*?)\s*<\/think(?:ing)?>/);
|
|
200
|
+
if (thinkingMatch) {
|
|
201
|
+
const thinking = thinkingMatch[1].trim();
|
|
202
|
+
// Remove thinking block from text
|
|
203
|
+
const remainingText = text
|
|
204
|
+
.replace(/<think(?:ing)?>\s*[\s\S]*?\s*<\/think(?:ing)?>/g, '')
|
|
205
|
+
.trim();
|
|
206
|
+
return { thinking, text: remainingText };
|
|
207
|
+
}
|
|
208
|
+
return { thinking: null, text };
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Extract a clean title from user message, skipping system info
|
|
212
|
+
*/
|
|
213
|
+
function extractSessionTitle(messages, sessionId, metaName) {
|
|
214
|
+
// Find the first user message with actual content
|
|
215
|
+
for (const msg of messages) {
|
|
216
|
+
if (msg.role === 'user' && msg.content) {
|
|
217
|
+
// Skip if it's system info
|
|
218
|
+
if (msg.content.startsWith('<user_info>') ||
|
|
219
|
+
msg.content.startsWith('<rules>') ||
|
|
220
|
+
msg.content.includes('<user_info>')) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
// Use the first 50 characters as title
|
|
224
|
+
let title = msg.content.substring(0, 50);
|
|
225
|
+
if (msg.content.length > 50) {
|
|
226
|
+
title += '...';
|
|
227
|
+
}
|
|
228
|
+
return title;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
// Fallback to meta name or session ID
|
|
232
|
+
return metaName || `Session ${sessionId.substring(0, 8)}`;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Parse blob data to extract JSON messages
|
|
236
|
+
*/
|
|
237
|
+
function parseBlobData(data) {
|
|
238
|
+
try {
|
|
239
|
+
// Convert buffer to string
|
|
240
|
+
const dataStr = data.toString('utf-8');
|
|
241
|
+
// Try parsing as JSON first
|
|
242
|
+
try {
|
|
243
|
+
const parsed = JSON.parse(dataStr);
|
|
244
|
+
if (parsed.role) {
|
|
245
|
+
return parsed;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
// Not valid JSON, continue
|
|
250
|
+
}
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Tool name mapping from Cursor SDK names to frontend expected names
|
|
259
|
+
* This ensures tool names match what CursorToolRenderer.tsx expects
|
|
260
|
+
*/
|
|
261
|
+
const CURSOR_TOOL_NAME_MAP = {
|
|
262
|
+
// Standard tools
|
|
263
|
+
'LS': 'lsToolCall',
|
|
264
|
+
'Ls': 'lsToolCall',
|
|
265
|
+
'Read': 'readToolCall',
|
|
266
|
+
'Write': 'writeToolCall',
|
|
267
|
+
'Edit': 'editToolCall',
|
|
268
|
+
'Delete': 'deleteToolCall',
|
|
269
|
+
'Glob': 'globToolCall',
|
|
270
|
+
'Grep': 'grepToolCall',
|
|
271
|
+
'Shell': 'shellToolCall',
|
|
272
|
+
'WebFetch': 'webFetchToolCall',
|
|
273
|
+
'SemSearch': 'semSearchToolCall',
|
|
274
|
+
'ListMcpResources': 'listMcpResourcesToolCall',
|
|
275
|
+
// Special mappings - Cursor SDK uses different names than frontend expects
|
|
276
|
+
'TodoWrite': 'updateTodosToolCall',
|
|
277
|
+
'StrReplace': 'strReplaceToolCall',
|
|
278
|
+
// MCP tool
|
|
279
|
+
'Mcp': 'mcpToolCall',
|
|
280
|
+
};
|
|
281
|
+
/**
|
|
282
|
+
* Convert tool name to Cursor format (e.g., "Glob" -> "globToolCall")
|
|
283
|
+
* Uses mapping table for known tools, falls back to camelCase conversion for unknown tools
|
|
284
|
+
*/
|
|
285
|
+
function toCursorToolName(toolName) {
|
|
286
|
+
// Check mapping table first
|
|
287
|
+
if (CURSOR_TOOL_NAME_MAP[toolName]) {
|
|
288
|
+
return CURSOR_TOOL_NAME_MAP[toolName];
|
|
289
|
+
}
|
|
290
|
+
// Fallback: convert to camelCase and add ToolCall suffix
|
|
291
|
+
// Handle all-uppercase names like "LS" -> "ls"
|
|
292
|
+
const baseName = toolName.length <= 2
|
|
293
|
+
? toolName.toLowerCase()
|
|
294
|
+
: toolName.charAt(0).toLowerCase() + toolName.slice(1);
|
|
295
|
+
return baseName + 'ToolCall';
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Convert snake_case keys to camelCase
|
|
299
|
+
*/
|
|
300
|
+
function snakeToCamel(str) {
|
|
301
|
+
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Convert all keys in an object from snake_case to camelCase
|
|
305
|
+
* Also handles arrays containing objects
|
|
306
|
+
*/
|
|
307
|
+
function convertKeysToCamelCase(obj) {
|
|
308
|
+
const result = {};
|
|
309
|
+
for (const key of Object.keys(obj)) {
|
|
310
|
+
const camelKey = snakeToCamel(key);
|
|
311
|
+
const value = obj[key];
|
|
312
|
+
if (Array.isArray(value)) {
|
|
313
|
+
// Handle arrays - convert objects within arrays
|
|
314
|
+
result[camelKey] = value.map(item => {
|
|
315
|
+
if (item && typeof item === 'object' && !Array.isArray(item)) {
|
|
316
|
+
return convertKeysToCamelCase(item);
|
|
317
|
+
}
|
|
318
|
+
return item;
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
else if (value && typeof value === 'object') {
|
|
322
|
+
// Recursively convert nested objects
|
|
323
|
+
result[camelKey] = convertKeysToCamelCase(value);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
result[camelKey] = value;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return result;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Extract tool calls from message content
|
|
333
|
+
* @param content - Array of message content items
|
|
334
|
+
* @param isUserMessage - Whether this is a user message (to clean <user_query> tags)
|
|
335
|
+
*/
|
|
336
|
+
function extractToolCalls(content, isUserMessage = false) {
|
|
337
|
+
const parts = [];
|
|
338
|
+
let order = 0;
|
|
339
|
+
for (const item of content) {
|
|
340
|
+
if (item.type === 'text' && 'text' in item && item.text) {
|
|
341
|
+
// Clean user query tags if this is a user message
|
|
342
|
+
let textContent = isUserMessage ? cleanUserQuery(item.text) : item.text;
|
|
343
|
+
// Skip empty text after cleaning
|
|
344
|
+
if (!textContent.trim())
|
|
345
|
+
continue;
|
|
346
|
+
// For assistant messages, check for thinking blocks
|
|
347
|
+
if (!isUserMessage) {
|
|
348
|
+
const { thinking, text } = parseThinkingContent(textContent);
|
|
349
|
+
// Add thinking part if present
|
|
350
|
+
if (thinking) {
|
|
351
|
+
parts.push({
|
|
352
|
+
id: `part_thinking_${order}`,
|
|
353
|
+
type: 'thinking',
|
|
354
|
+
content: thinking,
|
|
355
|
+
order: order++
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
// Update textContent to the remaining text
|
|
359
|
+
textContent = text;
|
|
360
|
+
// Skip if no remaining text
|
|
361
|
+
if (!textContent.trim())
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
364
|
+
parts.push({
|
|
365
|
+
id: `part_text_${order}`,
|
|
366
|
+
type: 'text',
|
|
367
|
+
content: textContent,
|
|
368
|
+
order: order++
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
else if (item.type === 'tool-call' && 'toolCallId' in item) {
|
|
372
|
+
parts.push({
|
|
373
|
+
id: item.toolCallId,
|
|
374
|
+
type: 'tool',
|
|
375
|
+
order: order++,
|
|
376
|
+
toolData: {
|
|
377
|
+
id: item.toolCallId,
|
|
378
|
+
toolName: toCursorToolName(item.toolName), // Convert to Cursor tool name format (e.g., "globToolCall")
|
|
379
|
+
toolInput: convertKeysToCamelCase(item.args || {}), // Convert snake_case to camelCase
|
|
380
|
+
}
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return parts;
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Parse a single CLI session from SQLite database
|
|
388
|
+
*
|
|
389
|
+
* @param sessionDir - Path to the session directory containing store.db
|
|
390
|
+
* @param sessionId - Session ID
|
|
391
|
+
* @param projectPath - Optional project path for loading image references
|
|
392
|
+
*/
|
|
393
|
+
async function parseCliSession(sessionDir, sessionId, projectPath) {
|
|
394
|
+
const dbPath = path.join(sessionDir, 'store.db');
|
|
395
|
+
if (!fs.existsSync(dbPath)) {
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
// Use native sqlite3 CLI to properly handle WAL mode
|
|
400
|
+
// sql.js doesn't support WAL and would miss recent changes
|
|
401
|
+
// Get meta information
|
|
402
|
+
// The value in meta table is stored as a hex-encoded JSON string
|
|
403
|
+
const metaValue = (0, child_process_1.execSync)(`sqlite3 "${dbPath}" "SELECT value FROM meta WHERE key = 0"`, {
|
|
404
|
+
encoding: 'utf-8',
|
|
405
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
406
|
+
}).trim();
|
|
407
|
+
if (!metaValue) {
|
|
408
|
+
return null;
|
|
409
|
+
}
|
|
410
|
+
// Decode hex-encoded meta value (stored as hex string in the database)
|
|
411
|
+
const metaJson = Buffer.from(metaValue, 'hex').toString('utf-8');
|
|
412
|
+
const meta = JSON.parse(metaJson);
|
|
413
|
+
// Get all blobs with hex-encoded data
|
|
414
|
+
const blobRows = executeSqliteBlobQuery(dbPath, 'SELECT id, hex(data) FROM blobs');
|
|
415
|
+
// Convert hex strings to Buffer
|
|
416
|
+
const blobs = blobRows.map(row => ({
|
|
417
|
+
id: row.id,
|
|
418
|
+
data: Buffer.from(row.data, 'hex'),
|
|
419
|
+
}));
|
|
420
|
+
// Parse messages from blobs - use Map to deduplicate by message id
|
|
421
|
+
const messageMap = new Map();
|
|
422
|
+
const toolResults = new Map();
|
|
423
|
+
let messageIndex = 0;
|
|
424
|
+
// Track seen content to deduplicate messages with same content
|
|
425
|
+
const seenContent = new Set();
|
|
426
|
+
// First pass: collect all messages and tool results
|
|
427
|
+
for (const blob of blobs) {
|
|
428
|
+
const parsed = parseBlobData(blob.data);
|
|
429
|
+
if (!parsed)
|
|
430
|
+
continue;
|
|
431
|
+
// Handle tool results
|
|
432
|
+
if (parsed.role === 'tool' && 'id' in parsed) {
|
|
433
|
+
const toolMsg = parsed;
|
|
434
|
+
if (Array.isArray(toolMsg.content)) {
|
|
435
|
+
for (const item of toolMsg.content) {
|
|
436
|
+
if (item.type === 'tool-result') {
|
|
437
|
+
toolResults.set(toolMsg.id, {
|
|
438
|
+
toolName: item.toolName,
|
|
439
|
+
result: item.result,
|
|
440
|
+
isError: item.isError
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
continue;
|
|
446
|
+
}
|
|
447
|
+
// Skip system messages
|
|
448
|
+
if (parsed.role === 'system')
|
|
449
|
+
continue;
|
|
450
|
+
// Handle user and assistant messages
|
|
451
|
+
if (parsed.role === 'user' || parsed.role === 'assistant') {
|
|
452
|
+
// Generate a unique message ID using blob.id (from database)
|
|
453
|
+
// This ensures each blob is processed independently
|
|
454
|
+
const msgId = `${parsed.role}_${blob.id}`;
|
|
455
|
+
// Skip if we already have this exact message (by message ID)
|
|
456
|
+
if (messageMap.has(msgId))
|
|
457
|
+
continue;
|
|
458
|
+
let textContent = '';
|
|
459
|
+
let messageParts = [];
|
|
460
|
+
const isUserMessage = parsed.role === 'user';
|
|
461
|
+
if (Array.isArray(parsed.content)) {
|
|
462
|
+
// Extract text content and tool calls from content array
|
|
463
|
+
// Pass isUserMessage to clean <user_query> tags
|
|
464
|
+
messageParts = extractToolCalls(parsed.content, isUserMessage);
|
|
465
|
+
textContent = messageParts
|
|
466
|
+
.filter(p => p.type === 'text' && p.content)
|
|
467
|
+
.map(p => p.content)
|
|
468
|
+
.join('\n');
|
|
469
|
+
}
|
|
470
|
+
else if (typeof parsed.content === 'string') {
|
|
471
|
+
// For string content, clean user query tags if needed
|
|
472
|
+
let rawContent = isUserMessage ? cleanUserQuery(parsed.content) : parsed.content;
|
|
473
|
+
if (rawContent) {
|
|
474
|
+
// For assistant messages, parse thinking blocks
|
|
475
|
+
if (!isUserMessage) {
|
|
476
|
+
const { thinking, text } = parseThinkingContent(rawContent);
|
|
477
|
+
if (thinking) {
|
|
478
|
+
messageParts.push({
|
|
479
|
+
id: `part_thinking_${messageIndex}`,
|
|
480
|
+
type: 'thinking',
|
|
481
|
+
content: thinking,
|
|
482
|
+
order: messageParts.length
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
textContent = text;
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
textContent = rawContent;
|
|
489
|
+
}
|
|
490
|
+
if (textContent) {
|
|
491
|
+
messageParts.push({
|
|
492
|
+
id: `part_${messageIndex}_0`,
|
|
493
|
+
type: 'text',
|
|
494
|
+
content: textContent,
|
|
495
|
+
order: messageParts.length
|
|
496
|
+
});
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
// textContent is already cleaned, use it directly
|
|
501
|
+
const cleanedContent = textContent;
|
|
502
|
+
// Skip if no meaningful content (no text, no thinking, no tool calls)
|
|
503
|
+
const hasToolCalls = messageParts.some(p => p.type === 'tool');
|
|
504
|
+
const hasThinking = messageParts.some(p => p.type === 'thinking');
|
|
505
|
+
if (!cleanedContent && !hasToolCalls && !hasThinking) {
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
// Skip system info in user messages
|
|
509
|
+
if (parsed.role === 'user' &&
|
|
510
|
+
(cleanedContent.startsWith('<user_info>') ||
|
|
511
|
+
cleanedContent.startsWith('<rules>') ||
|
|
512
|
+
cleanedContent.includes('<user_info>'))) {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
// Create content hash for deduplication (based on role + text content + tool calls)
|
|
516
|
+
const toolCallIds = messageParts
|
|
517
|
+
.filter(p => p.type === 'tool' && p.toolData)
|
|
518
|
+
.map(p => p.toolData.id)
|
|
519
|
+
.sort()
|
|
520
|
+
.join(',');
|
|
521
|
+
const contentHash = `${parsed.role}:${cleanedContent.substring(0, 200)}:${toolCallIds}`;
|
|
522
|
+
// Skip if we've already seen this exact content
|
|
523
|
+
if (seenContent.has(contentHash)) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
seenContent.add(contentHash);
|
|
527
|
+
// For user messages, try to extract and load image references
|
|
528
|
+
let images;
|
|
529
|
+
if (parsed.role === 'user' && projectPath && cleanedContent.includes('@.agentstudio-images/')) {
|
|
530
|
+
images = extractAndLoadImages(cleanedContent, projectPath);
|
|
531
|
+
if (images.length > 0) {
|
|
532
|
+
console.log(`📷 [CursorCLI] Loaded ${images.length} image(s) for user message`);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
messageMap.set(msgId, {
|
|
536
|
+
id: msgId,
|
|
537
|
+
role: parsed.role,
|
|
538
|
+
content: cleanedContent,
|
|
539
|
+
timestamp: meta.createdAt + (messageIndex * 1000),
|
|
540
|
+
messageParts: messageParts.length > 0 ? messageParts : [{
|
|
541
|
+
id: `part_${messageIndex}_0`,
|
|
542
|
+
type: 'text',
|
|
543
|
+
content: cleanedContent,
|
|
544
|
+
order: 0
|
|
545
|
+
}],
|
|
546
|
+
images // Include loaded images if any
|
|
547
|
+
});
|
|
548
|
+
messageIndex++;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
// Second pass: attach tool results to tool calls
|
|
552
|
+
for (const message of messageMap.values()) {
|
|
553
|
+
for (const part of message.messageParts) {
|
|
554
|
+
if (part.type === 'tool' && part.toolData) {
|
|
555
|
+
const result = toolResults.get(part.toolData.id);
|
|
556
|
+
if (result) {
|
|
557
|
+
part.toolData.toolResult = typeof result.result === 'string'
|
|
558
|
+
? result.result
|
|
559
|
+
: JSON.stringify(result.result);
|
|
560
|
+
// Also set toolUseResult as object with camelCase keys for frontend components
|
|
561
|
+
if (result.result && typeof result.result === 'object') {
|
|
562
|
+
part.toolData.toolUseResult = convertKeysToCamelCase(result.result);
|
|
563
|
+
}
|
|
564
|
+
else if (typeof result.result === 'string') {
|
|
565
|
+
// Try to parse string as JSON
|
|
566
|
+
try {
|
|
567
|
+
const parsed = JSON.parse(result.result);
|
|
568
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
569
|
+
part.toolData.toolUseResult = convertKeysToCamelCase(parsed);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
catch {
|
|
573
|
+
// Not JSON, leave toolUseResult undefined
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
part.toolData.isError = result.isError;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
// Convert map to array and sort by timestamp
|
|
582
|
+
const messages = Array.from(messageMap.values())
|
|
583
|
+
.sort((a, b) => a.timestamp - b.timestamp);
|
|
584
|
+
if (messages.length === 0) {
|
|
585
|
+
return null;
|
|
586
|
+
}
|
|
587
|
+
// Generate title from first meaningful user message (skip system info)
|
|
588
|
+
const title = extractSessionTitle(messages, sessionId, meta.name);
|
|
589
|
+
// Get directory stats for timestamps
|
|
590
|
+
const stats = fs.statSync(sessionDir);
|
|
591
|
+
return {
|
|
592
|
+
id: sessionId,
|
|
593
|
+
title,
|
|
594
|
+
createdAt: new Date(meta.createdAt).toISOString(),
|
|
595
|
+
lastUpdated: stats.mtime.toISOString(),
|
|
596
|
+
messages,
|
|
597
|
+
mode: meta.mode
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
catch (error) {
|
|
601
|
+
console.error(`Failed to parse CLI session ${sessionId}:`, error);
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Read all Cursor CLI sessions for a project
|
|
607
|
+
*/
|
|
608
|
+
async function readCursorCliSessions(projectPath) {
|
|
609
|
+
try {
|
|
610
|
+
const workspaceHash = getWorkspaceHash(projectPath);
|
|
611
|
+
const chatsDir = path.join(getCursorChatsDir(), workspaceHash);
|
|
612
|
+
console.log(`📂 [CURSOR CLI] Reading sessions from: ${chatsDir}`);
|
|
613
|
+
console.log(`📂 [CURSOR CLI] Workspace hash: ${workspaceHash} (from ${projectPath})`);
|
|
614
|
+
if (!fs.existsSync(chatsDir)) {
|
|
615
|
+
console.log(`❌ [CURSOR CLI] Chats directory not found: ${chatsDir}`);
|
|
616
|
+
return [];
|
|
617
|
+
}
|
|
618
|
+
const sessionDirs = fs.readdirSync(chatsDir)
|
|
619
|
+
.filter(name => {
|
|
620
|
+
const fullPath = path.join(chatsDir, name);
|
|
621
|
+
return fs.statSync(fullPath).isDirectory() && !name.startsWith('.');
|
|
622
|
+
});
|
|
623
|
+
console.log(`📋 [CURSOR CLI] Found ${sessionDirs.length} session directories`);
|
|
624
|
+
const sessions = [];
|
|
625
|
+
for (const sessionId of sessionDirs) {
|
|
626
|
+
const sessionDir = path.join(chatsDir, sessionId);
|
|
627
|
+
const session = await parseCliSession(sessionDir, sessionId);
|
|
628
|
+
if (session) {
|
|
629
|
+
sessions.push(session);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
// Sort by lastUpdated descending
|
|
633
|
+
sessions.sort((a, b) => new Date(b.lastUpdated).getTime() - new Date(a.lastUpdated).getTime());
|
|
634
|
+
console.log(`✅ [CURSOR CLI] Parsed ${sessions.length} sessions successfully`);
|
|
635
|
+
return sessions;
|
|
636
|
+
}
|
|
637
|
+
catch (error) {
|
|
638
|
+
console.error('Failed to read Cursor CLI sessions:', error);
|
|
639
|
+
return [];
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Read a single Cursor CLI session by ID
|
|
644
|
+
*/
|
|
645
|
+
async function readCursorCliSession(projectPath, sessionId) {
|
|
646
|
+
try {
|
|
647
|
+
const workspaceHash = getWorkspaceHash(projectPath);
|
|
648
|
+
// Strip 'cursor-' prefix if present (added by AgentStudio for internal tracking)
|
|
649
|
+
const actualSessionId = sessionId.startsWith('cursor-') ? sessionId.slice(7) : sessionId;
|
|
650
|
+
const sessionDir = path.join(getCursorChatsDir(), workspaceHash, actualSessionId);
|
|
651
|
+
if (!fs.existsSync(sessionDir)) {
|
|
652
|
+
console.log(`❌ [CURSOR CLI] Session directory not found: ${sessionDir}`);
|
|
653
|
+
return null;
|
|
654
|
+
}
|
|
655
|
+
// Pass projectPath for loading image references
|
|
656
|
+
// Use original sessionId (with prefix) to maintain consistency
|
|
657
|
+
return await parseCliSession(sessionDir, sessionId, projectPath);
|
|
658
|
+
}
|
|
659
|
+
catch (error) {
|
|
660
|
+
console.error(`Failed to read Cursor CLI session ${sessionId}:`, error);
|
|
661
|
+
return null;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
//# sourceMappingURL=cursorCliHistoryParser.js.map
|