hammoc 1.8.3 → 1.9.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/README.md +9 -6
- package/package.json +1 -1
- package/packages/client/dist/assets/MermaidViewer-B-LwclIl.js +7 -0
- package/packages/client/dist/assets/PdfViewer-C3Nymwn3.js +12 -0
- package/packages/client/dist/assets/PdfViewer-QCQEGvBO.css +1 -0
- package/packages/client/dist/assets/abnfDiagram-VRR7QNED-GfhY_hnV.js +1 -0
- package/packages/client/dist/assets/{agentExampleHighlight-B0EHAvjx.js → agentExampleHighlight-CyhVLy0_.js} +1 -1
- package/packages/client/dist/assets/arc-8nyjXGC3.js +1 -0
- package/packages/client/dist/assets/architectureDiagram-ZJ3FMSHR-B4onXLm4.js +36 -0
- package/packages/client/dist/assets/blockDiagram-677ZJIJ3-D0D6ncaN.js +132 -0
- package/packages/client/dist/assets/c4Diagram-LMCZKHZV-CE7Tip-_.js +10 -0
- package/packages/client/dist/assets/channel-CPjlbdOo.js +1 -0
- package/packages/client/dist/assets/chunk-2Q5K7J3B-4rW1da1Z.js +1 -0
- package/packages/client/dist/assets/chunk-32BRIVSS-JuzxS4QA.js +1 -0
- package/packages/client/dist/assets/chunk-5VM5RSS4-WRNf-xsi.js +15 -0
- package/packages/client/dist/assets/chunk-EX3LRPZG-BDWPlBKO.js +231 -0
- package/packages/client/dist/assets/chunk-JWPE2WC7-B8nCyQAc.js +1 -0
- package/packages/client/dist/assets/chunk-MOJQB5TN-7c-yriHe.js +88 -0
- package/packages/client/dist/assets/chunk-RYQCIY6F-LTDywRs7.js +1 -0
- package/packages/client/dist/assets/chunk-V7JOEXUC-DjVgQpjl.js +206 -0
- package/packages/client/dist/assets/chunk-VR4S4FIN-7jDdkUpx.js +1 -0
- package/packages/client/dist/assets/chunk-XXDRQBXY-ENKV2O8a.js +1 -0
- package/packages/client/dist/assets/classDiagram-OUVF2IWQ-C0PbC7Pi.js +1 -0
- package/packages/client/dist/assets/classDiagram-v2-EOCWNBFH-C0PbC7Pi.js +1 -0
- package/packages/client/dist/assets/{commandTokenHighlight-BFQeQmwm.js → commandTokenHighlight-DGP0RKx0.js} +1 -1
- package/packages/client/dist/assets/cose-bilkent-JH36ORCC-CQTNdQ-g.js +1 -0
- package/packages/client/dist/assets/cynefin-VYW2F7L2-BYlAJRcO.js +178 -0
- package/packages/client/dist/assets/cynefinDiagram-TSTJHNR4-7zyUTflT.js +62 -0
- package/packages/client/dist/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
- package/packages/client/dist/assets/dagre-VKFMJZFB-DyZir42W.js +4 -0
- package/packages/client/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/packages/client/dist/assets/diagram-FQU43EPY-CmNAU8Nw.js +3 -0
- package/packages/client/dist/assets/diagram-G47NLZAW-B0EIk03o.js +24 -0
- package/packages/client/dist/assets/diagram-NH7WQ7WH-Dulv0f1N.js +24 -0
- package/packages/client/dist/assets/diagram-OA4YK3LP-DEEcMLgi.js +30 -0
- package/packages/client/dist/assets/diagram-WEI45ONY-ZYebAZ93.js +41 -0
- package/packages/client/dist/assets/ebnfDiagram-CCIWWBDH-DCHpt3qn.js +1 -0
- package/packages/client/dist/assets/erDiagram-Q63AITRT-B6T87-48.js +85 -0
- package/packages/client/dist/assets/flowDiagram-23GEKE2U-DAcW6mKJ.js +156 -0
- package/packages/client/dist/assets/ganttDiagram-NO4QXBWP-Ct_eFFcM.js +292 -0
- package/packages/client/dist/assets/gitGraphDiagram-IHSO6WYX-BGi8Fdm2.js +106 -0
- package/packages/client/dist/assets/graph-C9eacEi8.js +1 -0
- package/packages/client/dist/assets/index-CtMiUbMJ.js +1671 -0
- package/packages/client/dist/assets/index-hTu6ZG2N.js +2 -0
- package/packages/client/dist/assets/index-oBa2uNlv.css +32 -0
- package/packages/client/dist/assets/infoDiagram-FWYZ7A6U-CqvwbXJn.js +2 -0
- package/packages/client/dist/assets/init-Gi6I4Gst.js +1 -0
- package/packages/client/dist/assets/ishikawaDiagram-FXEZZL3T-CHhr5ioQ.js +70 -0
- package/packages/client/dist/assets/journeyDiagram-5HDEW3XC-d20NzZAd.js +139 -0
- package/packages/client/dist/assets/kanban-definition-HUTT4EX6-CHx3wOer.js +89 -0
- package/packages/client/dist/assets/katex-C5jXJg4s.js +257 -0
- package/packages/client/dist/assets/layout-DEXfKzaS.js +1 -0
- package/packages/client/dist/assets/linear-Cnp1E9M4.js +1 -0
- package/packages/client/dist/assets/map-Czzmt4hB.js +1 -0
- package/packages/client/dist/assets/mermaid.core-jAhLhPYr.js +314 -0
- package/packages/client/dist/assets/mindmap-definition-LN4V7U3C-zi30RPoJ.js +96 -0
- package/packages/client/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/packages/client/dist/assets/pdf.worker.min-qwK7q_zL.mjs +28 -0
- package/packages/client/dist/assets/pegDiagram-2B236MQR-4gKLzTqu.js +1 -0
- package/packages/client/dist/assets/pieDiagram-ENE6RG2P-DRDhpjxP.js +39 -0
- package/packages/client/dist/assets/quadrantDiagram-ABIIQ3AL-FmTxRIlW.js +7 -0
- package/packages/client/dist/assets/railroadDiagram-RFXS5EU6-Bc-Q7iPs.js +1 -0
- package/packages/client/dist/assets/requirementDiagram-TGXJPOKE-D209tlqv.js +84 -0
- package/packages/client/dist/assets/sankeyDiagram-HTMAVEWB--I_lSbCV.js +40 -0
- package/packages/client/dist/assets/sequenceDiagram-DBY2YBRQ-Da5YJcDJ.js +162 -0
- package/packages/client/dist/assets/sizeCapture-X5ZJPWSS-DYuc-rzB.js +1 -0
- package/packages/client/dist/assets/{snippetTokenHighlight-DVju7SBc.js → snippetTokenHighlight-qXHxvlCE.js} +1 -1
- package/packages/client/dist/assets/stateDiagram-2N3HPSRC-DoOeZoRP.js +1 -0
- package/packages/client/dist/assets/stateDiagram-v2-6OUMAXLB-DLkUyWs6.js +1 -0
- package/packages/client/dist/assets/swimlanes-5IMT3BWC-BcR7uCTf.js +2 -0
- package/packages/client/dist/assets/swimlanesDiagram-G3AALYLV-C0FDo-hf.js +8 -0
- package/packages/client/dist/assets/timeline-definition-FHXFAJF6-CLzKR6_i.js +120 -0
- package/packages/client/dist/assets/vennDiagram-L72KCM5P-TajEacPR.js +34 -0
- package/packages/client/dist/assets/wardleyDiagram-EHGQE667-DKvVEb3V.js +78 -0
- package/packages/client/dist/assets/xychartDiagram-FW5EYKEG-CaJG8r0j.js +7 -0
- package/packages/client/dist/index.html +2 -2
- package/packages/client/dist/sw.js +2 -2
- package/packages/server/dist/controllers/accountController.d.ts.map +1 -1
- package/packages/server/dist/controllers/accountController.js +31 -11
- package/packages/server/dist/controllers/accountController.js.map +1 -1
- package/packages/server/dist/controllers/fileSystemController.d.ts +6 -0
- package/packages/server/dist/controllers/fileSystemController.d.ts.map +1 -1
- package/packages/server/dist/controllers/fileSystemController.js +34 -0
- package/packages/server/dist/controllers/fileSystemController.js.map +1 -1
- package/packages/server/dist/controllers/projectController.d.ts.map +1 -1
- package/packages/server/dist/controllers/projectController.js +4 -2
- package/packages/server/dist/controllers/projectController.js.map +1 -1
- package/packages/server/dist/controllers/sessionController.d.ts +5 -0
- package/packages/server/dist/controllers/sessionController.d.ts.map +1 -1
- package/packages/server/dist/controllers/sessionController.js +95 -3
- package/packages/server/dist/controllers/sessionController.js.map +1 -1
- package/packages/server/dist/handlers/hookBridge.d.ts +131 -0
- package/packages/server/dist/handlers/hookBridge.d.ts.map +1 -0
- package/packages/server/dist/handlers/hookBridge.js +178 -0
- package/packages/server/dist/handlers/hookBridge.js.map +1 -0
- package/packages/server/dist/handlers/streamCallbacks.d.ts.map +1 -1
- package/packages/server/dist/handlers/streamCallbacks.js +30 -4
- package/packages/server/dist/handlers/streamCallbacks.js.map +1 -1
- package/packages/server/dist/handlers/websocket.d.ts +44 -2
- package/packages/server/dist/handlers/websocket.d.ts.map +1 -1
- package/packages/server/dist/handlers/websocket.js +666 -64
- package/packages/server/dist/handlers/websocket.js.map +1 -1
- package/packages/server/dist/index.js +4 -1
- package/packages/server/dist/index.js.map +1 -1
- package/packages/server/dist/locales/en/server.json +9 -3
- package/packages/server/dist/locales/es/server.json +9 -3
- package/packages/server/dist/locales/ja/server.json +9 -3
- package/packages/server/dist/locales/ko/server.json +9 -3
- package/packages/server/dist/locales/pt/server.json +9 -3
- package/packages/server/dist/locales/zh-CN/server.json +9 -3
- package/packages/server/dist/routes/account.d.ts.map +1 -1
- package/packages/server/dist/routes/account.js +4 -2
- package/packages/server/dist/routes/account.js.map +1 -1
- package/packages/server/dist/routes/fileSystem.d.ts.map +1 -1
- package/packages/server/dist/routes/fileSystem.js +2 -0
- package/packages/server/dist/routes/fileSystem.js.map +1 -1
- package/packages/server/dist/routes/sessions.d.ts.map +1 -1
- package/packages/server/dist/routes/sessions.js +2 -0
- package/packages/server/dist/routes/sessions.js.map +1 -1
- package/packages/server/dist/services/accountInfoService.d.ts +36 -1
- package/packages/server/dist/services/accountInfoService.d.ts.map +1 -1
- package/packages/server/dist/services/accountInfoService.js +90 -4
- package/packages/server/dist/services/accountInfoService.js.map +1 -1
- package/packages/server/dist/services/accountStorageService.d.ts +55 -9
- package/packages/server/dist/services/accountStorageService.d.ts.map +1 -1
- package/packages/server/dist/services/accountStorageService.js +244 -12
- package/packages/server/dist/services/accountStorageService.js.map +1 -1
- package/packages/server/dist/services/chatEngine.d.ts +59 -3
- package/packages/server/dist/services/chatEngine.d.ts.map +1 -1
- package/packages/server/dist/services/chatService.d.ts +112 -3
- package/packages/server/dist/services/chatService.d.ts.map +1 -1
- package/packages/server/dist/services/chatService.js +353 -98
- package/packages/server/dist/services/chatService.js.map +1 -1
- package/packages/server/dist/services/claudeLoginService.d.ts +14 -3
- package/packages/server/dist/services/claudeLoginService.d.ts.map +1 -1
- package/packages/server/dist/services/claudeLoginService.js +18 -4
- package/packages/server/dist/services/claudeLoginService.js.map +1 -1
- package/packages/server/dist/services/cliChatEngine.d.ts.map +1 -1
- package/packages/server/dist/services/cliChatEngine.js +124 -22
- package/packages/server/dist/services/cliChatEngine.js.map +1 -1
- package/packages/server/dist/services/cliModalDetect.d.ts +14 -0
- package/packages/server/dist/services/cliModalDetect.d.ts.map +1 -1
- package/packages/server/dist/services/cliModalDetect.js +12 -3
- package/packages/server/dist/services/cliModalDetect.js.map +1 -1
- package/packages/server/dist/services/cliSessionPool.js +1 -1
- package/packages/server/dist/services/cliSessionPool.js.map +1 -1
- package/packages/server/dist/services/commandService.d.ts.map +1 -1
- package/packages/server/dist/services/commandService.js +19 -9
- package/packages/server/dist/services/commandService.js.map +1 -1
- package/packages/server/dist/services/engineResidencyRegistry.d.ts +112 -0
- package/packages/server/dist/services/engineResidencyRegistry.d.ts.map +1 -0
- package/packages/server/dist/services/engineResidencyRegistry.js +195 -0
- package/packages/server/dist/services/engineResidencyRegistry.js.map +1 -0
- package/packages/server/dist/services/harnessAgentService.d.ts.map +1 -1
- package/packages/server/dist/services/harnessAgentService.js +12 -2
- package/packages/server/dist/services/harnessAgentService.js.map +1 -1
- package/packages/server/dist/services/harnessLintService.d.ts.map +1 -1
- package/packages/server/dist/services/harnessLintService.js +25 -114
- package/packages/server/dist/services/harnessLintService.js.map +1 -1
- package/packages/server/dist/services/historyParser.d.ts.map +1 -1
- package/packages/server/dist/services/historyParser.js +23 -6
- package/packages/server/dist/services/historyParser.js.map +1 -1
- package/packages/server/dist/services/imageStorageService.d.ts.map +1 -1
- package/packages/server/dist/services/imageStorageService.js +7 -0
- package/packages/server/dist/services/imageStorageService.js.map +1 -1
- package/packages/server/dist/services/projectService.d.ts +4 -1
- package/packages/server/dist/services/projectService.d.ts.map +1 -1
- package/packages/server/dist/services/projectService.js +14 -1
- package/packages/server/dist/services/projectService.js.map +1 -1
- package/packages/server/dist/services/promptQueue.d.ts +34 -0
- package/packages/server/dist/services/promptQueue.d.ts.map +1 -0
- package/packages/server/dist/services/promptQueue.js +80 -0
- package/packages/server/dist/services/promptQueue.js.map +1 -0
- package/packages/server/dist/services/ptyService.d.ts.map +1 -1
- package/packages/server/dist/services/ptyService.js +4 -1
- package/packages/server/dist/services/ptyService.js.map +1 -1
- package/packages/server/dist/services/queueService.d.ts.map +1 -1
- package/packages/server/dist/services/queueService.js +62 -4
- package/packages/server/dist/services/queueService.js.map +1 -1
- package/packages/server/dist/services/rateLimitProbeService.d.ts +73 -3
- package/packages/server/dist/services/rateLimitProbeService.d.ts.map +1 -1
- package/packages/server/dist/services/rateLimitProbeService.js +397 -30
- package/packages/server/dist/services/rateLimitProbeService.js.map +1 -1
- package/packages/server/dist/services/sessionBufferManager.d.ts.map +1 -1
- package/packages/server/dist/services/sessionBufferManager.js +22 -4
- package/packages/server/dist/services/sessionBufferManager.js.map +1 -1
- package/packages/server/dist/services/sessionExportService.d.ts +34 -0
- package/packages/server/dist/services/sessionExportService.d.ts.map +1 -0
- package/packages/server/dist/services/sessionExportService.js +269 -0
- package/packages/server/dist/services/sessionExportService.js.map +1 -0
- package/packages/server/dist/services/sessionService.d.ts +6 -0
- package/packages/server/dist/services/sessionService.d.ts.map +1 -1
- package/packages/server/dist/services/sessionService.js +30 -9
- package/packages/server/dist/services/sessionService.js.map +1 -1
- package/packages/server/dist/services/streamHandler.d.ts +177 -1
- package/packages/server/dist/services/streamHandler.d.ts.map +1 -1
- package/packages/server/dist/services/streamHandler.js +425 -39
- package/packages/server/dist/services/streamHandler.js.map +1 -1
- package/packages/server/dist/services/workspaceContext.d.ts.map +1 -1
- package/packages/server/dist/services/workspaceContext.js +6 -0
- package/packages/server/dist/services/workspaceContext.js.map +1 -1
- package/packages/server/dist/snippets/fix-lint-command-not-on-path +13 -0
- package/packages/server/dist/snippets/fix-lint-duplicate-name +12 -0
- package/packages/server/dist/snippets/fix-lint-env-var-undefined +13 -0
- package/packages/server/dist/snippets/fix-lint-regex-invalid +14 -0
- package/packages/server/dist/snippets/fix-lint-tools-non-standard +14 -0
- package/packages/server/dist/snippets/fix-lint-url-invalid +13 -0
- package/packages/server/dist/snippets/fix-lint-yaml-parse-error +14 -0
- package/packages/server/dist/snippets/fix-malformed-skill +17 -0
- package/packages/server/dist/utils/backgroundHookSettings.d.ts +31 -0
- package/packages/server/dist/utils/backgroundHookSettings.d.ts.map +1 -0
- package/packages/server/dist/utils/backgroundHookSettings.js +41 -0
- package/packages/server/dist/utils/backgroundHookSettings.js.map +1 -0
- package/packages/server/dist/utils/backgroundTaskPoller.d.ts +69 -0
- package/packages/server/dist/utils/backgroundTaskPoller.d.ts.map +1 -0
- package/packages/server/dist/utils/backgroundTaskPoller.js +356 -0
- package/packages/server/dist/utils/backgroundTaskPoller.js.map +1 -0
- package/packages/server/dist/utils/backgroundTaskTracker.d.ts +51 -3
- package/packages/server/dist/utils/backgroundTaskTracker.d.ts.map +1 -1
- package/packages/server/dist/utils/backgroundTaskTracker.js +117 -9
- package/packages/server/dist/utils/backgroundTaskTracker.js.map +1 -1
- package/packages/server/dist/utils/backgroundToolGuard.d.ts +26 -0
- package/packages/server/dist/utils/backgroundToolGuard.d.ts.map +1 -0
- package/packages/server/dist/utils/backgroundToolGuard.js +40 -0
- package/packages/server/dist/utils/backgroundToolGuard.js.map +1 -0
- package/packages/server/dist/utils/boundedRing.d.ts +44 -0
- package/packages/server/dist/utils/boundedRing.d.ts.map +1 -0
- package/packages/server/dist/utils/boundedRing.js +77 -0
- package/packages/server/dist/utils/boundedRing.js.map +1 -0
- package/packages/server/dist/utils/effortUtils.d.ts +7 -6
- package/packages/server/dist/utils/effortUtils.d.ts.map +1 -1
- package/packages/server/dist/utils/effortUtils.js +10 -9
- package/packages/server/dist/utils/effortUtils.js.map +1 -1
- package/packages/server/dist/utils/messageTree.d.ts +25 -0
- package/packages/server/dist/utils/messageTree.d.ts.map +1 -1
- package/packages/server/dist/utils/messageTree.js +167 -3
- package/packages/server/dist/utils/messageTree.js.map +1 -1
- package/packages/server/dist/utils/pathUtils.d.ts.map +1 -1
- package/packages/server/dist/utils/pathUtils.js +1 -0
- package/packages/server/dist/utils/pathUtils.js.map +1 -1
- package/packages/server/dist/utils/residencyActivation.d.ts +61 -0
- package/packages/server/dist/utils/residencyActivation.d.ts.map +1 -0
- package/packages/server/dist/utils/residencyActivation.js +60 -0
- package/packages/server/dist/utils/residencyActivation.js.map +1 -0
- package/packages/server/dist/utils/residencyPolicy.d.ts +62 -0
- package/packages/server/dist/utils/residencyPolicy.d.ts.map +1 -0
- package/packages/server/dist/utils/residencyPolicy.js +82 -0
- package/packages/server/dist/utils/residencyPolicy.js.map +1 -0
- package/packages/server/dist/utils/runtimeParamStrategy.d.ts +51 -0
- package/packages/server/dist/utils/runtimeParamStrategy.d.ts.map +1 -0
- package/packages/server/dist/utils/runtimeParamStrategy.js +60 -0
- package/packages/server/dist/utils/runtimeParamStrategy.js.map +1 -0
- package/packages/server/dist/utils/stopStrategy.d.ts +62 -0
- package/packages/server/dist/utils/stopStrategy.d.ts.map +1 -0
- package/packages/server/dist/utils/stopStrategy.js +65 -0
- package/packages/server/dist/utils/stopStrategy.js.map +1 -0
- package/packages/server/resources/internals/INDEX.md +1 -1
- package/packages/server/resources/internals/image-storage.md +14 -2
- package/packages/server/resources/manual/02-chat.md +30 -13
- package/packages/server/resources/manual/03-sessions.md +22 -1
- package/packages/server/resources/manual/04-slash-commands-favorites.md +2 -1
- package/packages/server/resources/manual/05-projects.md +1 -0
- package/packages/server/resources/manual/06-file-explorer-editor.md +21 -2
- package/packages/server/resources/manual/07-git.md +1 -1
- package/packages/server/resources/manual/08-terminal.md +1 -1
- package/packages/server/resources/manual/12-harness-workbench.md +21 -16
- package/packages/server/resources/manual/13-settings.md +22 -6
- package/packages/server/resources/manual/14-keyboard-shortcuts.md +8 -1
- package/packages/shared/dist/constants/messageTree.d.ts +2 -0
- package/packages/shared/dist/constants/messageTree.d.ts.map +1 -1
- package/packages/shared/dist/constants/messageTree.js +6 -0
- package/packages/shared/dist/constants/messageTree.js.map +1 -1
- package/packages/shared/dist/index.d.ts +1 -1
- package/packages/shared/dist/index.d.ts.map +1 -1
- package/packages/shared/dist/index.js.map +1 -1
- package/packages/shared/dist/types/accounts.d.ts +13 -0
- package/packages/shared/dist/types/accounts.d.ts.map +1 -1
- package/packages/shared/dist/types/history.d.ts +14 -1
- package/packages/shared/dist/types/history.d.ts.map +1 -1
- package/packages/shared/dist/types/message.d.ts +26 -3
- package/packages/shared/dist/types/message.d.ts.map +1 -1
- package/packages/shared/dist/types/message.js +21 -1
- package/packages/shared/dist/types/message.js.map +1 -1
- package/packages/shared/dist/types/preferences.d.ts +5 -1
- package/packages/shared/dist/types/preferences.d.ts.map +1 -1
- package/packages/shared/dist/types/preferences.js +3 -0
- package/packages/shared/dist/types/preferences.js.map +1 -1
- package/packages/shared/dist/types/sdk.d.ts +68 -10
- package/packages/shared/dist/types/sdk.d.ts.map +1 -1
- package/packages/shared/dist/types/sdk.js +56 -16
- package/packages/shared/dist/types/sdk.js.map +1 -1
- package/packages/shared/dist/types/session.d.ts +6 -0
- package/packages/shared/dist/types/session.d.ts.map +1 -1
- package/packages/shared/dist/types/session.js +6 -0
- package/packages/shared/dist/types/session.js.map +1 -1
- package/packages/shared/dist/types/streaming.d.ts +32 -2
- package/packages/shared/dist/types/streaming.d.ts.map +1 -1
- package/packages/shared/dist/types/streaming.js.map +1 -1
- package/packages/shared/dist/types/websocket.d.ts +4 -0
- package/packages/shared/dist/types/websocket.d.ts.map +1 -1
- package/scripts/probe-persistent-hooks.mjs +795 -0
- package/packages/client/dist/assets/index-BX7y_Qt3.css +0 -32
- package/packages/client/dist/assets/index-Bav7AMMy.js +0 -2
- package/packages/client/dist/assets/index-DgRQoBIg.js +0 -1657
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
* Story 27.1: Holds history + streaming messages in memory,
|
|
4
4
|
* delivers all message data exclusively via WebSocket.
|
|
5
5
|
*/
|
|
6
|
-
import { ROOT_BRANCH_KEY } from '@hammoc/shared';
|
|
6
|
+
import { ROOT_BRANCH_KEY, COMPACT_MESSAGE_PREFIX, COMPACT_COMMAND_ECHO } from '@hammoc/shared';
|
|
7
7
|
import { parseJSONLFile, transformToHistoryMessages } from './historyParser.js';
|
|
8
8
|
import { sessionService } from './sessionService.js';
|
|
9
|
-
import { buildRawMessageTree, getActiveRawBranch, getDefaultRawBranchSelections, } from '../utils/messageTree.js';
|
|
9
|
+
import { buildRawMessageTree, getActiveRawBranch, getDefaultRawBranchSelections, repairPostCompactParenting, } from '../utils/messageTree.js';
|
|
10
10
|
import { createLogger } from '../utils/logger.js';
|
|
11
11
|
const log = createLogger('sessionBufferManager');
|
|
12
12
|
/**
|
|
@@ -30,6 +30,22 @@ function sortHistoryMessagesByTimestamp(messages) {
|
|
|
30
30
|
messages[i] = indexed[i].m;
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Pick the message that carries root-level (epoch) branch info.
|
|
35
|
+
* The client renders branch pagination only on compact_boundary dividers and
|
|
36
|
+
* visible user bubbles. The chronologically-first message of a compact epoch
|
|
37
|
+
* is one the chat view hides — the SDK stamps the summary echo 1-2ms BEFORE
|
|
38
|
+
* the boundary, and a manual /compact leaves its command echo even earlier —
|
|
39
|
+
* so attaching to messages[0] would pin the pagination onto an invisible
|
|
40
|
+
* message (arrows never render, even in branch viewer mode).
|
|
41
|
+
*/
|
|
42
|
+
function findRootBranchCarrier(messages) {
|
|
43
|
+
return messages.find((m) => m.type === 'system' && m.subtype === 'compact_boundary')
|
|
44
|
+
?? messages.find((m) => m.type === 'user'
|
|
45
|
+
&& !m.content.startsWith(COMPACT_MESSAGE_PREFIX)
|
|
46
|
+
&& m.content !== COMPACT_COMMAND_ECHO)
|
|
47
|
+
?? messages[0];
|
|
48
|
+
}
|
|
33
49
|
export class SessionBufferManager {
|
|
34
50
|
buffers = new Map();
|
|
35
51
|
create(sessionId, streaming = false) {
|
|
@@ -80,6 +96,7 @@ export class SessionBufferManager {
|
|
|
80
96
|
return [];
|
|
81
97
|
}
|
|
82
98
|
const tree = buildRawMessageTree(rawMessages);
|
|
99
|
+
repairPostCompactParenting(tree);
|
|
83
100
|
const defaults = getDefaultRawBranchSelections(tree.roots);
|
|
84
101
|
const selections = branchSelections
|
|
85
102
|
? { ...defaults, ...branchSelections }
|
|
@@ -100,8 +117,9 @@ export class SessionBufferManager {
|
|
|
100
117
|
for (const [msgId, info] of Object.entries(branchPoints)) {
|
|
101
118
|
const msg = idIndex.get(msgId)
|
|
102
119
|
// ROOT_BRANCH_KEY ('__root__') won't match any message ID —
|
|
103
|
-
// attach to the
|
|
104
|
-
|
|
120
|
+
// attach to a message the client actually renders as a pagination
|
|
121
|
+
// carrier so root-level branches are navigable.
|
|
122
|
+
?? (msgId === ROOT_BRANCH_KEY ? findRootBranchCarrier(historyMessages) : undefined);
|
|
105
123
|
if (msg) {
|
|
106
124
|
msg.branchInfo = info;
|
|
107
125
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionBufferManager.js","sourceRoot":"","sources":["../../src/services/sessionBufferManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"sessionBufferManager.js","sourceRoot":"","sources":["../../src/services/sessionBufferManager.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EAAE,cAAc,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChF,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,GAAG,GAAG,YAAY,CAAC,sBAAsB,CAAC,CAAC;AAEjD;;;;;GAKG;AACH,SAAS,8BAA8B,CAAC,QAA0B;IAChE,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;IAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpB,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,CAAC,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5B,OAAO,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IACH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,QAAQ,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAQD;;;;;;;;GAQG;AACH,SAAS,qBAAqB,CAAC,QAA0B;IACvD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,KAAK,kBAAkB,CAAC;WAC/E,QAAQ,CAAC,IAAI,CACd,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM;eACnB,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,sBAAsB,CAAC;eAC7C,CAAC,CAAC,OAAO,KAAK,oBAAoB,CACxC;WACE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,MAAM,OAAO,oBAAoB;IACvB,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEnD,MAAM,CAAC,SAAiB,EAAE,SAAS,GAAG,KAAK;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7C,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,SAAS,GAAG,SAAS,CAAC;YAC/B,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,MAAM,MAAM,GAAkB,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;QACrE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACpC,GAAG,CAAC,KAAK,CAAC,8BAA8B,SAAS,EAAE,CAAC,CAAC;QACrD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,GAAG,CAAC,SAAiB;QACnB,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IAED,WAAW,CAAC,SAAiB,EAAE,QAA0B;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,sCAAsC,SAAS,EAAE,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QACD,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC7B,CAAC;IAED,UAAU,CAAC,SAAiB,EAAE,OAAuB;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,qCAAqC,SAAS,EAAE,CAAC,CAAC;YAC3D,OAAO;QACT,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IAED,YAAY,CAAC,SAAiB,EAAE,SAAkB;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC3C,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,uCAAuC,SAAS,EAAE,CAAC,CAAC;YAC7D,OAAO;QACT,CAAC;QACD,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,SAAiB,EACjB,WAAmB,EACnB,gBAAyC;QAEzC,MAAM,QAAQ,GAAG,cAAc,CAAC,kBAAkB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAC,CAAC;QACnD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAClC,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,IAAI,GAAG,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAC9C,0BAA0B,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,QAAQ,GAAG,6BAA6B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,gBAAgB;YACjC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,gBAAgB,EAAE;YACtC,CAAC,CAAC,QAAQ,CAAC;QACb,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;QAC9F,MAAM,eAAe,GAAG,0BAA0B,CAAC,cAAc,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QAC3F,yEAAyE;QACzE,uEAAuE;QACvE,wEAAwE;QACxE,sDAAsD;QACtD,8BAA8B,CAAC,eAAe,CAAC,CAAC;QAChD,sFAAsF;QACtF,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,IAAI,GAAG,EAA0B,CAAC;YAClD,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,CAAC;gBAChC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;YACvB,CAAC;YACD,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;gBACzD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;oBAC5B,4DAA4D;oBAC5D,kEAAkE;oBAClE,gDAAgD;uBAC7C,CAAC,KAAK,KAAK,eAAe,CAAC,CAAC,CAAC,qBAAqB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;gBACtF,IAAI,GAAG,EAAE,CAAC;oBACR,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC;gBACxB,CAAC;YACH,CAAC;QACH,CAAC;QACD,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;QAC/C,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,4BAA4B,SAAS,KAAK,eAAe,CAAC,MAAM,WAAW,CAAC,CAAC;QACvF,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAa,EAAE,KAAa;QAChC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,gCAAgC,KAAK,EAAE,CAAC,CAAC;YAClD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3B,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAChC,GAAG,CAAC,KAAK,CAAC,oBAAoB,KAAK,MAAM,KAAK,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,OAAO,CAAC,SAAiB;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/C,IAAI,OAAO,EAAE,CAAC;YACZ,GAAG,CAAC,KAAK,CAAC,gCAAgC,SAAS,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAED,0BAA0B;IAC1B,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,oBAAoB,EAAE,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Export Service
|
|
3
|
+
*
|
|
4
|
+
* Converts a Claude Code session JSONL file into a self-contained Markdown
|
|
5
|
+
* document that preserves ALL conversation branches (edits, rewinds, forks).
|
|
6
|
+
*
|
|
7
|
+
* Unlike sessionService.getSessionMessages — which extracts only the *active*
|
|
8
|
+
* branch for on-screen display — this walks the ENTIRE message tree depth-first
|
|
9
|
+
* and inserts a "branch" divider at every fork, so every alternative path the
|
|
10
|
+
* user ever explored is included. The underlying tree-building primitives
|
|
11
|
+
* (buildRawMessageTree / groupRawChildrenIntoBranches / repairPostCompactParenting)
|
|
12
|
+
* are reused verbatim so the export structure matches what the chat view derives.
|
|
13
|
+
*/
|
|
14
|
+
import type { RawJSONLMessage } from '@hammoc/shared';
|
|
15
|
+
export interface SessionMarkdownMeta {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
projectSlug: string;
|
|
18
|
+
sessionName?: string | null;
|
|
19
|
+
exportedAt?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Pure transform: raw JSONL messages → Markdown string containing every branch.
|
|
23
|
+
* Separated from file IO so it can be unit-tested with in-memory fixtures.
|
|
24
|
+
*/
|
|
25
|
+
export declare function renderSessionMarkdown(raw: RawJSONLMessage[], meta: SessionMarkdownMeta): string;
|
|
26
|
+
/**
|
|
27
|
+
* Convert a session's JSONL into a Markdown string containing every branch.
|
|
28
|
+
* Returns null if the session file does not exist.
|
|
29
|
+
*/
|
|
30
|
+
export declare function exportSessionToMarkdown(projectSlug: string, sessionId: string, opts?: {
|
|
31
|
+
sessionName?: string | null;
|
|
32
|
+
exportedAt?: string;
|
|
33
|
+
}): Promise<string | null>;
|
|
34
|
+
//# sourceMappingURL=sessionExportService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionExportService.d.ts","sourceRoot":"","sources":["../../src/services/sessionExportService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EACV,eAAe,EAMhB,MAAM,gBAAgB,CAAC;AAgNxB,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,EAAE,EAAE,IAAI,EAAE,mBAAmB,GAAG,MAAM,CAuC/F;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9D,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAWxB"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Export Service
|
|
3
|
+
*
|
|
4
|
+
* Converts a Claude Code session JSONL file into a self-contained Markdown
|
|
5
|
+
* document that preserves ALL conversation branches (edits, rewinds, forks).
|
|
6
|
+
*
|
|
7
|
+
* Unlike sessionService.getSessionMessages — which extracts only the *active*
|
|
8
|
+
* branch for on-screen display — this walks the ENTIRE message tree depth-first
|
|
9
|
+
* and inserts a "branch" divider at every fork, so every alternative path the
|
|
10
|
+
* user ever explored is included. The underlying tree-building primitives
|
|
11
|
+
* (buildRawMessageTree / groupRawChildrenIntoBranches / repairPostCompactParenting)
|
|
12
|
+
* are reused verbatim so the export structure matches what the chat view derives.
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync } from 'fs';
|
|
15
|
+
import { sanitizeToolResultContent } from '@hammoc/shared';
|
|
16
|
+
import { buildRawMessageTree, groupRawChildrenIntoBranches, repairPostCompactParenting, isConversationRoot, } from '../utils/messageTree.js';
|
|
17
|
+
import { parseJSONLFile, cleanCommandTags, parseTaskNotification } from './historyParser.js';
|
|
18
|
+
import { sessionService } from './sessionService.js';
|
|
19
|
+
/**
|
|
20
|
+
* Build a map of tool_use block id → tool name across the whole file, so a
|
|
21
|
+
* tool_result (which only carries the id) can be labelled with its tool name.
|
|
22
|
+
*/
|
|
23
|
+
function buildToolNameMap(raw) {
|
|
24
|
+
const map = new Map();
|
|
25
|
+
for (const m of raw) {
|
|
26
|
+
if (m.type === 'assistant' && Array.isArray(m.message?.content)) {
|
|
27
|
+
for (const block of m.message.content) {
|
|
28
|
+
if (block.type === 'tool_use') {
|
|
29
|
+
map.set(block.id, block.name);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
else if (m.type === 'tool_use' && m.toolName) {
|
|
34
|
+
// Legacy inline tool_use format keyed by uuid
|
|
35
|
+
map.set(m.uuid, m.toolName);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return map;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Wrap content in a fenced code block whose fence is guaranteed longer than any
|
|
42
|
+
* backtick run inside the content, so embedded code fences can't break out.
|
|
43
|
+
*/
|
|
44
|
+
function fence(content, lang = '') {
|
|
45
|
+
const longestRun = (content.match(/`+/g) ?? []).reduce((max, s) => Math.max(max, s.length), 0);
|
|
46
|
+
const bar = '`'.repeat(Math.max(3, longestRun + 1));
|
|
47
|
+
return `${bar}${lang}\n${content}\n${bar}`;
|
|
48
|
+
}
|
|
49
|
+
/** Collapse a long value into a <details> block; short values stay inline. */
|
|
50
|
+
function collapsible(summary, body) {
|
|
51
|
+
return `<details><summary>${summary}</summary>\n\n${body}\n\n</details>`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Neutralize <details>/<summary> tags in a PROSE body destined for a collapsible
|
|
55
|
+
* wrapper. The body renders as markdown, where a raw closing tag passes through
|
|
56
|
+
* as HTML — it would close the wrapper early and spill the rest of the document
|
|
57
|
+
* out of it (an opening tag would nest). `<` renders back as a literal `<` in
|
|
58
|
+
* prose, so display fidelity is kept. Fenced bodies (tool results) don't need
|
|
59
|
+
* this — fence content is inert in markdown.
|
|
60
|
+
*/
|
|
61
|
+
function escapeDetailsTags(text) {
|
|
62
|
+
return text.replace(/<(\/?)(details|summary)\b/gi, '<$1$2');
|
|
63
|
+
}
|
|
64
|
+
function extractText(content) {
|
|
65
|
+
if (!content)
|
|
66
|
+
return '';
|
|
67
|
+
if (typeof content === 'string')
|
|
68
|
+
return content;
|
|
69
|
+
return content
|
|
70
|
+
.filter((b) => b.type === 'text')
|
|
71
|
+
.map((b) => b.text)
|
|
72
|
+
.join('\n');
|
|
73
|
+
}
|
|
74
|
+
function renderToolUse(block) {
|
|
75
|
+
const input = block.input && Object.keys(block.input).length > 0
|
|
76
|
+
? `\n\n${fence(JSON.stringify(block.input, null, 2), 'json')}`
|
|
77
|
+
: '';
|
|
78
|
+
return `### 🔧 ${block.name}${input}`;
|
|
79
|
+
}
|
|
80
|
+
function renderToolResult(block, toolNames) {
|
|
81
|
+
const name = toolNames.get(block.tool_use_id);
|
|
82
|
+
const isError = block.is_error ?? false;
|
|
83
|
+
const rawContent = typeof block.content === 'string'
|
|
84
|
+
? block.content
|
|
85
|
+
: Array.isArray(block.content)
|
|
86
|
+
? block.content.map((c) => (typeof c === 'string' ? c : JSON.stringify(c))).join('\n')
|
|
87
|
+
: '';
|
|
88
|
+
const cleaned = sanitizeToolResultContent(rawContent).trim();
|
|
89
|
+
if (!cleaned)
|
|
90
|
+
return '';
|
|
91
|
+
const summary = `↳ Result${name ? ` · ${name}` : ''}${isError ? ' ⚠️ error' : ''}`;
|
|
92
|
+
return collapsible(summary, fence(cleaned));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Render one raw message into zero or more Markdown blocks.
|
|
96
|
+
* Returns an empty string for messages that produce no visible output.
|
|
97
|
+
*/
|
|
98
|
+
function renderMessage(msg, toolNames) {
|
|
99
|
+
// Skip SDK-injected meta messages (expanded slash commands etc.)
|
|
100
|
+
if (msg.isMeta)
|
|
101
|
+
return '';
|
|
102
|
+
if (msg.type === 'system') {
|
|
103
|
+
if (msg.subtype === 'compact_boundary') {
|
|
104
|
+
return `\n---\n\n> 🗜️ **${msg.content || 'Conversation compacted'}**\n\n---`;
|
|
105
|
+
}
|
|
106
|
+
return '';
|
|
107
|
+
}
|
|
108
|
+
if (msg.type === 'assistant') {
|
|
109
|
+
const content = msg.message?.content;
|
|
110
|
+
const blocks = [];
|
|
111
|
+
if (Array.isArray(content)) {
|
|
112
|
+
for (const block of content) {
|
|
113
|
+
if (block.type === 'thinking') {
|
|
114
|
+
const thinking = block.thinking?.trim();
|
|
115
|
+
if (thinking)
|
|
116
|
+
blocks.push(collapsible('💭 Thinking', escapeDetailsTags(thinking)));
|
|
117
|
+
}
|
|
118
|
+
else if (block.type === 'text') {
|
|
119
|
+
const text = block.text?.trim();
|
|
120
|
+
if (text && text !== '(no content)')
|
|
121
|
+
blocks.push(text);
|
|
122
|
+
}
|
|
123
|
+
else if (block.type === 'tool_use') {
|
|
124
|
+
blocks.push(renderToolUse(block));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
const text = extractText(content).trim();
|
|
130
|
+
if (text && text !== '(no content)')
|
|
131
|
+
blocks.push(text);
|
|
132
|
+
}
|
|
133
|
+
if (blocks.length === 0)
|
|
134
|
+
return '';
|
|
135
|
+
return `## 🤖 Assistant\n\n${blocks.join('\n\n')}`;
|
|
136
|
+
}
|
|
137
|
+
if (msg.type === 'user') {
|
|
138
|
+
const content = msg.message?.content;
|
|
139
|
+
if (Array.isArray(content)) {
|
|
140
|
+
const toolResults = content.filter((b) => b.type === 'tool_result');
|
|
141
|
+
if (toolResults.length > 0) {
|
|
142
|
+
const rendered = toolResults.map((b) => renderToolResult(b, toolNames)).filter(Boolean);
|
|
143
|
+
return rendered.join('\n\n');
|
|
144
|
+
}
|
|
145
|
+
const imageCount = content.filter((b) => b.type === 'image').length;
|
|
146
|
+
const text = extractText(content);
|
|
147
|
+
const notif = parseTaskNotification(text);
|
|
148
|
+
if (notif) {
|
|
149
|
+
return `> 🔔 **Background task ${notif.status}** — ${notif.summary}`;
|
|
150
|
+
}
|
|
151
|
+
const cleaned = cleanCommandTags(text);
|
|
152
|
+
const imageNote = imageCount > 0 ? `🖼️ _[${imageCount} image(s) attached]_` : '';
|
|
153
|
+
const body = [imageNote, cleaned].filter(Boolean).join('\n\n');
|
|
154
|
+
if (!body.trim())
|
|
155
|
+
return '';
|
|
156
|
+
return `## 👤 User\n\n${body}`;
|
|
157
|
+
}
|
|
158
|
+
const text = extractText(content);
|
|
159
|
+
const notif = parseTaskNotification(text);
|
|
160
|
+
if (notif) {
|
|
161
|
+
return `> 🔔 **Background task ${notif.status}** — ${notif.summary}`;
|
|
162
|
+
}
|
|
163
|
+
const cleaned = cleanCommandTags(text);
|
|
164
|
+
if (!cleaned.trim())
|
|
165
|
+
return '';
|
|
166
|
+
return `## 👤 User\n\n${cleaned}`;
|
|
167
|
+
}
|
|
168
|
+
if (msg.type === 'tool_use') {
|
|
169
|
+
// Legacy inline tool_use
|
|
170
|
+
const input = msg.toolInput && Object.keys(msg.toolInput).length > 0
|
|
171
|
+
? `\n\n${fence(JSON.stringify(msg.toolInput, null, 2), 'json')}`
|
|
172
|
+
: '';
|
|
173
|
+
return `### 🔧 ${msg.toolName ?? 'tool'}${input}`;
|
|
174
|
+
}
|
|
175
|
+
if (msg.type === 'tool_result') {
|
|
176
|
+
// Legacy inline tool_result
|
|
177
|
+
const body = msg.error || msg.result || '';
|
|
178
|
+
if (!body.trim())
|
|
179
|
+
return '';
|
|
180
|
+
return collapsible(`↳ Result${msg.error ? ' ⚠️ error' : ''}`, fence(sanitizeToolResultContent(body)));
|
|
181
|
+
}
|
|
182
|
+
return '';
|
|
183
|
+
}
|
|
184
|
+
/** A horizontal branch divider, e.g. "━━━ Branch 2/3 · latest ━━━". */
|
|
185
|
+
function branchDivider(index, total, isLast) {
|
|
186
|
+
const bar = '━'.repeat(12);
|
|
187
|
+
const suffix = isLast ? ' · latest' : '';
|
|
188
|
+
return `\n#### ${bar} Branch ${index}/${total}${suffix} ${bar}\n`;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Depth-first walk that emits every message and, at each fork, a branch divider
|
|
192
|
+
* before each alternative path. Metadata-only branches are still walked so no
|
|
193
|
+
* content is silently dropped.
|
|
194
|
+
*/
|
|
195
|
+
function walk(node, out, toolNames) {
|
|
196
|
+
const rendered = renderMessage(node.message, toolNames);
|
|
197
|
+
if (rendered)
|
|
198
|
+
out.push(rendered);
|
|
199
|
+
const branches = groupRawChildrenIntoBranches(node.children);
|
|
200
|
+
if (branches.length <= 1) {
|
|
201
|
+
for (const child of branches[0] ?? []) {
|
|
202
|
+
walk(child, out, toolNames);
|
|
203
|
+
}
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
for (let i = 0; i < branches.length; i++) {
|
|
207
|
+
out.push(branchDivider(i + 1, branches.length, i === branches.length - 1));
|
|
208
|
+
for (const child of branches[i]) {
|
|
209
|
+
walk(child, out, toolNames);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Pure transform: raw JSONL messages → Markdown string containing every branch.
|
|
215
|
+
* Separated from file IO so it can be unit-tested with in-memory fixtures.
|
|
216
|
+
*/
|
|
217
|
+
export function renderSessionMarkdown(raw, meta) {
|
|
218
|
+
const tree = buildRawMessageTree(raw);
|
|
219
|
+
repairPostCompactParenting(tree);
|
|
220
|
+
const toolNames = buildToolNameMap(raw);
|
|
221
|
+
const messageCount = raw.filter((m) => m.type === 'user' || m.type === 'assistant').length;
|
|
222
|
+
const body = [];
|
|
223
|
+
const convRoots = tree.roots.filter(isConversationRoot);
|
|
224
|
+
if (convRoots.length > 1) {
|
|
225
|
+
// Multiple conversation roots (e.g. compact epochs or root-level edits):
|
|
226
|
+
// include them all, each under its own segment divider.
|
|
227
|
+
for (let i = 0; i < convRoots.length; i++) {
|
|
228
|
+
body.push(`\n### ▓▓ Conversation root ${i + 1}/${convRoots.length} ▓▓\n`);
|
|
229
|
+
walk(convRoots[i], body, toolNames);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
const start = convRoots.length > 0 ? convRoots : tree.roots;
|
|
234
|
+
for (const root of start) {
|
|
235
|
+
walk(root, body, toolNames);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const exportedAt = meta.exportedAt ?? new Date().toISOString();
|
|
239
|
+
const title = meta.sessionName || 'Claude Code Session';
|
|
240
|
+
const header = [
|
|
241
|
+
`# ${title}`,
|
|
242
|
+
'',
|
|
243
|
+
`- **Session**: \`${meta.sessionId}\``,
|
|
244
|
+
`- **Project**: \`${meta.projectSlug}\``,
|
|
245
|
+
`- **Exported**: ${exportedAt}`,
|
|
246
|
+
`- **Messages**: ${messageCount}`,
|
|
247
|
+
'',
|
|
248
|
+
'---',
|
|
249
|
+
'',
|
|
250
|
+
].join('\n');
|
|
251
|
+
return header + body.join('\n\n') + '\n';
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Convert a session's JSONL into a Markdown string containing every branch.
|
|
255
|
+
* Returns null if the session file does not exist.
|
|
256
|
+
*/
|
|
257
|
+
export async function exportSessionToMarkdown(projectSlug, sessionId, opts = {}) {
|
|
258
|
+
const filePath = sessionService.getSessionFilePath(projectSlug, sessionId);
|
|
259
|
+
if (!existsSync(filePath))
|
|
260
|
+
return null;
|
|
261
|
+
const raw = await parseJSONLFile(filePath);
|
|
262
|
+
return renderSessionMarkdown(raw, {
|
|
263
|
+
sessionId,
|
|
264
|
+
projectSlug,
|
|
265
|
+
sessionName: opts.sessionName,
|
|
266
|
+
exportedAt: opts.exportedAt,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=sessionExportService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionExportService.js","sourceRoot":"","sources":["../../src/services/sessionExportService.ts"],"names":[],"mappings":"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"}
|
|
@@ -125,6 +125,12 @@ export declare class SessionService {
|
|
|
125
125
|
*/
|
|
126
126
|
listSessionsBySlug(projectSlug: string, params?: SessionListParams & {
|
|
127
127
|
sessionNames?: Record<string, string>;
|
|
128
|
+
/**
|
|
129
|
+
* Turn start times (ms) of sessions with a running stream. A streaming session's
|
|
130
|
+
* last activity is "now" — the index cache only refreshes at turn end, so without
|
|
131
|
+
* this override a mid-turn list fetch would sort the session by its previous turn.
|
|
132
|
+
*/
|
|
133
|
+
activeStreamStartTimes?: Map<string, number>;
|
|
128
134
|
}): Promise<{
|
|
129
135
|
sessions: SessionListItem[];
|
|
130
136
|
total: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessionService.d.ts","sourceRoot":"","sources":["../../src/services/sessionService.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH,OAAO,KAAK,EACV,WAAW,EAGX,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,iBAAiB,EAClB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"sessionService.d.ts","sourceRoot":"","sources":["../../src/services/sessionService.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ import { existsSync, createReadStream, readFileSync, writeFileSync, unlinkSync,
|
|
|
12
12
|
import readline from 'readline';
|
|
13
13
|
import { createLogger } from '../utils/logger.js';
|
|
14
14
|
import { parseJSONLFile, parseJSONLSessionMeta, transformToHistoryMessages, cleanCommandTags, } from './historyParser.js';
|
|
15
|
-
import { buildRawMessageTree, getActiveRawBranch, getDefaultRawBranchSelections, } from '../utils/messageTree.js';
|
|
15
|
+
import { buildRawMessageTree, getActiveRawBranch, getDefaultRawBranchSelections, repairPostCompactParenting, } from '../utils/messageTree.js';
|
|
16
16
|
const log = createLogger('sessionService');
|
|
17
17
|
/**
|
|
18
18
|
* SessionService - Manages Claude Code session data
|
|
@@ -435,7 +435,13 @@ export class SessionService {
|
|
|
435
435
|
* - Supports search by query and content search (Story 23.1)
|
|
436
436
|
*/
|
|
437
437
|
async listSessionsBySlug(projectSlug, params = {}) {
|
|
438
|
-
const { includeEmpty = false, limit = 0, offset = 0, query, searchContent, sessionNames } = params;
|
|
438
|
+
const { includeEmpty = false, limit = 0, offset = 0, query, searchContent, sessionNames, activeStreamStartTimes } = params;
|
|
439
|
+
const nowIso = new Date().toISOString();
|
|
440
|
+
const nowMs = new Date(nowIso).getTime();
|
|
441
|
+
// Most recent activity first; ties (concurrent streams share "now") break by
|
|
442
|
+
// most recently started turn.
|
|
443
|
+
const byActivityDesc = (a, b) => (b.mtimeMs - a.mtimeMs) ||
|
|
444
|
+
((activeStreamStartTimes?.get(b.sessionId) ?? 0) - (activeStreamStartTimes?.get(a.sessionId) ?? 0));
|
|
439
445
|
const queryLower = query?.toLowerCase();
|
|
440
446
|
const projectDir = path.join(this.claudeProjectsDir, projectSlug);
|
|
441
447
|
const indexPath = path.join(projectDir, 'sessions-index.json');
|
|
@@ -468,6 +474,10 @@ export class SessionService {
|
|
|
468
474
|
const fileEntries = [];
|
|
469
475
|
for (const file of jsonlFiles) {
|
|
470
476
|
const sessionId = file.replace('.jsonl', '');
|
|
477
|
+
if (activeStreamStartTimes?.has(sessionId)) {
|
|
478
|
+
fileEntries.push({ file, sessionId, mtimeMs: nowMs });
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
471
481
|
const cached = indexMap.get(sessionId);
|
|
472
482
|
if (cached && cached.modified) {
|
|
473
483
|
fileEntries.push({ file, sessionId, mtimeMs: new Date(cached.modified).getTime() || 0 });
|
|
@@ -496,8 +506,8 @@ export class SessionService {
|
|
|
496
506
|
}
|
|
497
507
|
}
|
|
498
508
|
}
|
|
499
|
-
// Sort by modified time descending
|
|
500
|
-
fileEntries.sort(
|
|
509
|
+
// Sort by modified time descending (streaming sessions pinned to "now")
|
|
510
|
+
fileEntries.sort(byActivityDesc);
|
|
501
511
|
// When search is active, resolve cache misses for filtering
|
|
502
512
|
let candidates = fileEntries;
|
|
503
513
|
if (queryLower) {
|
|
@@ -545,7 +555,7 @@ export class SessionService {
|
|
|
545
555
|
const contentHits = contentMatched.filter((e) => e !== null);
|
|
546
556
|
candidates = [...metadataFiltered, ...contentHits];
|
|
547
557
|
// Re-sort after merging
|
|
548
|
-
candidates.sort(
|
|
558
|
+
candidates.sort(byActivityDesc);
|
|
549
559
|
}
|
|
550
560
|
else {
|
|
551
561
|
candidates = metadataFiltered;
|
|
@@ -560,7 +570,7 @@ export class SessionService {
|
|
|
560
570
|
firstPrompt: this.truncateFirstPrompt(cached.firstPrompt),
|
|
561
571
|
messageCount: cached.messageCount,
|
|
562
572
|
created: stat.birthtime.toISOString(),
|
|
563
|
-
modified: stat.mtime.toISOString(),
|
|
573
|
+
modified: activeStreamStartTimes?.has(sessionId) ? nowIso : stat.mtime.toISOString(),
|
|
564
574
|
};
|
|
565
575
|
}));
|
|
566
576
|
return { sessions, total: candidates.length };
|
|
@@ -616,7 +626,7 @@ export class SessionService {
|
|
|
616
626
|
firstPrompt: firstPrompt ? this.truncateFirstPrompt(firstPrompt) : '',
|
|
617
627
|
messageCount,
|
|
618
628
|
created: stat.birthtime.toISOString(),
|
|
619
|
-
modified: stat.mtime.toISOString(),
|
|
629
|
+
modified: activeStreamStartTimes?.has(sessionId) ? nowIso : stat.mtime.toISOString(),
|
|
620
630
|
});
|
|
621
631
|
}
|
|
622
632
|
else {
|
|
@@ -695,8 +705,18 @@ export class SessionService {
|
|
|
695
705
|
if (sessionMap.size === 0) {
|
|
696
706
|
return { sessions: [], total: 0 };
|
|
697
707
|
}
|
|
708
|
+
// Streaming sessions' last activity is "now" — override the stale on-disk timestamp
|
|
709
|
+
if (activeStreamStartTimes) {
|
|
710
|
+
for (const sid of activeStreamStartTimes.keys()) {
|
|
711
|
+
const active = sessionMap.get(sid);
|
|
712
|
+
if (active)
|
|
713
|
+
active.modified = nowIso;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
const byModifiedDesc = (a, b) => (this.parseDate(b.modified) - this.parseDate(a.modified)) ||
|
|
717
|
+
((activeStreamStartTimes?.get(b.sessionId) ?? 0) - (activeStreamStartTimes?.get(a.sessionId) ?? 0));
|
|
698
718
|
// Sort by modified descending (AC 3)
|
|
699
|
-
let sorted = [...sessionMap.values()].sort(
|
|
719
|
+
let sorted = [...sessionMap.values()].sort(byModifiedDesc);
|
|
700
720
|
// Apply search filter for full path
|
|
701
721
|
if (queryLower) {
|
|
702
722
|
const metadataMatched = new Set();
|
|
@@ -721,7 +741,7 @@ export class SessionService {
|
|
|
721
741
|
contentHits.push(s);
|
|
722
742
|
}
|
|
723
743
|
sorted = [...metadataFiltered, ...contentHits];
|
|
724
|
-
sorted.sort(
|
|
744
|
+
sorted.sort(byModifiedDesc);
|
|
725
745
|
}
|
|
726
746
|
else {
|
|
727
747
|
sorted = metadataFiltered;
|
|
@@ -924,6 +944,7 @@ export class SessionService {
|
|
|
924
944
|
const rawMessages = await parseJSONLFile(filePath);
|
|
925
945
|
// Build tree and extract active branch (Story 25.4)
|
|
926
946
|
const tree = buildRawMessageTree(rawMessages);
|
|
947
|
+
repairPostCompactParenting(tree);
|
|
927
948
|
const effectiveSelections = branchSelections && Object.keys(branchSelections).length > 0
|
|
928
949
|
? branchSelections
|
|
929
950
|
: getDefaultRawBranchSelections(tree.roots);
|