factory-factory 0.4.4 → 0.4.5
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/dist/client/assets/{abnfDiagram-VRR7QNED-CtUj9J56.js → abnfDiagram-VRR7QNED-DygwVN25.js} +1 -1
- package/dist/client/assets/{arc-2QeawLbF.js → arc-CcnMw5av.js} +1 -1
- package/dist/client/assets/{architectureDiagram-ZJ3FMSHR-Cz-V9xRh.js → architectureDiagram-ZJ3FMSHR-BZgeaNrI.js} +1 -1
- package/dist/client/assets/{blockDiagram-677ZJIJ3-BN6MDejN.js → blockDiagram-677ZJIJ3-DQ77xvqH.js} +1 -1
- package/dist/client/assets/{c4Diagram-LMCZKHZV-ZxcmUt9u.js → c4Diagram-LMCZKHZV-B-9QZJ1e.js} +1 -1
- package/dist/client/assets/channel-zAL33ya-.js +1 -0
- package/dist/client/assets/{chunk-2Q5K7J3B-CyvdNBvs.js → chunk-2Q5K7J3B-DhfBY-Wd.js} +1 -1
- package/dist/client/assets/{chunk-32BRIVSS-BXA35oY0.js → chunk-32BRIVSS-CV9UmSkI.js} +1 -1
- package/dist/client/assets/{chunk-5VM5RSS4-6lY9D3Us.js → chunk-5VM5RSS4-BUNj3iDY.js} +1 -1
- package/dist/client/assets/{chunk-EX3LRPZG-BRYEhwoK.js → chunk-EX3LRPZG-Dj63JdET.js} +1 -1
- package/dist/client/assets/{chunk-JWPE2WC7-DBeDDTf3.js → chunk-JWPE2WC7-i6Ud3VAu.js} +1 -1
- package/dist/client/assets/{chunk-MOJQB5TN-MIX8YUEz.js → chunk-MOJQB5TN-PY5GLOxr.js} +1 -1
- package/dist/client/assets/{chunk-RYQCIY6F-CT_f1sbt.js → chunk-RYQCIY6F-pIEuQy1L.js} +1 -1
- package/dist/client/assets/{chunk-V7JOEXUC-DpMacC1A.js → chunk-V7JOEXUC--zp7Z0xS.js} +1 -1
- package/dist/client/assets/{chunk-VR4S4FIN-Bd6MGh78.js → chunk-VR4S4FIN-JstmsazP.js} +1 -1
- package/dist/client/assets/{chunk-XXDRQBXY-BYg-oILv.js → chunk-XXDRQBXY-C66lsFmy.js} +1 -1
- package/dist/client/assets/classDiagram-OUVF2IWQ-Dksz7rAA.js +1 -0
- package/dist/client/assets/classDiagram-v2-EOCWNBFH-Dksz7rAA.js +1 -0
- package/dist/client/assets/{cose-bilkent-JH36ORCC-BGhjYi6z.js → cose-bilkent-JH36ORCC-D3jSuAHn.js} +1 -1
- package/dist/client/assets/{cynefin-VYW2F7L2-BouObN4T.js → cynefin-VYW2F7L2-Dx3xfGS7.js} +1 -1
- package/dist/client/assets/{cynefinDiagram-TSTJHNR4-DrbscNyk.js → cynefinDiagram-TSTJHNR4-BcGYZcSJ.js} +1 -1
- package/dist/client/assets/{dagre-VKFMJZFB-CpHBhtab.js → dagre-VKFMJZFB-CLZSDf9x.js} +1 -1
- package/dist/client/assets/{diagram-FQU43EPY-C_pXymmj.js → diagram-FQU43EPY-Nosv2FJf.js} +1 -1
- package/dist/client/assets/{diagram-G47NLZAW-DNPz9Qrh.js → diagram-G47NLZAW-CPjqONaO.js} +1 -1
- package/dist/client/assets/{diagram-NH7WQ7WH-DWHcerSm.js → diagram-NH7WQ7WH-BmRiUIAJ.js} +1 -1
- package/dist/client/assets/{diagram-OA4YK3LP-C6Jnb8nm.js → diagram-OA4YK3LP-C7WEtC2B.js} +1 -1
- package/dist/client/assets/{diagram-WEI45ONY-DF667tXW.js → diagram-WEI45ONY-up5rQ6My.js} +1 -1
- package/dist/client/assets/{ebnfDiagram-CCIWWBDH-_Wt4C-Lm.js → ebnfDiagram-CCIWWBDH-D2Ye87k4.js} +1 -1
- package/dist/client/assets/{erDiagram-Q63AITRT-D9F9IIZ7.js → erDiagram-Q63AITRT-CgZF8eG-.js} +1 -1
- package/dist/client/assets/{flowDiagram-23GEKE2U-BzTUtnLY.js → flowDiagram-23GEKE2U-bxoO3Eep.js} +1 -1
- package/dist/client/assets/{ganttDiagram-NO4QXBWP-lmFnKYE5.js → ganttDiagram-NO4QXBWP-BAtqPw6P.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-IHSO6WYX-DiIQa_m6.js → gitGraphDiagram-IHSO6WYX-DYQqeJ8w.js} +1 -1
- package/dist/client/assets/{index-CpvT2M5m.js → index-BZQlu-dZ.js} +155 -150
- package/dist/client/assets/{infoDiagram-FWYZ7A6U-BXtmiN5g.js → infoDiagram-FWYZ7A6U-CZQCerFQ.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-FXEZZL3T-Ce8fzasD.js → ishikawaDiagram-FXEZZL3T-Bc7wE25N.js} +1 -1
- package/dist/client/assets/{journeyDiagram-5HDEW3XC-CAhJE-OU.js → journeyDiagram-5HDEW3XC-D5qqjKJz.js} +1 -1
- package/dist/client/assets/{kanban-definition-HUTT4EX6-B8br5xew.js → kanban-definition-HUTT4EX6-42kkaHBo.js} +1 -1
- package/dist/client/assets/{linear-BPVVEns_.js → linear-Dg3NQEM3.js} +1 -1
- package/dist/client/assets/{mindmap-definition-LN4V7U3C-lX6h9H-N.js → mindmap-definition-LN4V7U3C-CRANKUcD.js} +1 -1
- package/dist/client/assets/{mobile-baseline-C45NSkzw.js → mobile-baseline-D6bQ8WTB.js} +1 -1
- package/dist/client/assets/{pegDiagram-2B236MQR-CiFWwnk4.js → pegDiagram-2B236MQR-qJQPOd8H.js} +1 -1
- package/dist/client/assets/{pieDiagram-ENE6RG2P-CvkwWtzQ.js → pieDiagram-ENE6RG2P-B5wB7Ccf.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-ABIIQ3AL-B40anMyK.js → quadrantDiagram-ABIIQ3AL-CCZfXF8m.js} +1 -1
- package/dist/client/assets/{railroadDiagram-RFXS5EU6-WVYsdkDC.js → railroadDiagram-RFXS5EU6-BuIrSJUW.js} +1 -1
- package/dist/client/assets/{requirementDiagram-TGXJPOKE-DBTIsXpA.js → requirementDiagram-TGXJPOKE-DfIr0zZ3.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-HTMAVEWB-Dx8y47pZ.js → sankeyDiagram-HTMAVEWB-CJoUXRWq.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-DBY2YBRQ-C6ZZMZJm.js → sequenceDiagram-DBY2YBRQ-Cq1lOU1b.js} +1 -1
- package/dist/client/assets/{sizeCapture-X5ZJPWSS-DLy8loNR.js → sizeCapture-X5ZJPWSS-XHOsOkor.js} +1 -1
- package/dist/client/assets/{stateDiagram-2N3HPSRC-RoTcqZkX.js → stateDiagram-2N3HPSRC-BLVzzete.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-6OUMAXLB-DA02HYvU.js +1 -0
- package/dist/client/assets/{swimlanes-5IMT3BWC-CFmoSHiT.js → swimlanes-5IMT3BWC-C20mYIPR.js} +2 -2
- package/dist/client/assets/swimlanesDiagram-G3AALYLV-CbfcpXpQ.js +8 -0
- package/dist/client/assets/{terminal-instance-Br0jXsXE.js → terminal-instance-Dw2gcPib.js} +1 -1
- package/dist/client/assets/{timeline-definition-FHXFAJF6-Bh5XA09y.js → timeline-definition-FHXFAJF6-DlceJAxJ.js} +1 -1
- package/dist/client/assets/{vennDiagram-L72KCM5P-BC754zGO.js → vennDiagram-L72KCM5P-CFl-Eo1Y.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-EHGQE667-xJdUzWCg.js → wardleyDiagram-EHGQE667-eBpeLOoN.js} +1 -1
- package/dist/client/assets/{xychartDiagram-FW5EYKEG-wxQH1S7i.js → xychartDiagram-FW5EYKEG-B8RBkKiX.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/prisma/generated/browser.d.ts +1 -0
- package/dist/prisma/generated/browser.d.ts.map +1 -1
- package/dist/prisma/generated/client.d.ts +1 -0
- package/dist/prisma/generated/client.d.ts.map +1 -1
- package/dist/prisma/generated/commonInputTypes.d.ts +60 -0
- package/dist/prisma/generated/commonInputTypes.d.ts.map +1 -1
- package/dist/prisma/generated/enums.d.ts +15 -0
- package/dist/prisma/generated/enums.d.ts.map +1 -1
- package/dist/prisma/generated/enums.js +13 -0
- package/dist/prisma/generated/enums.js.map +1 -1
- package/dist/prisma/generated/internal/class.d.ts +3 -0
- package/dist/prisma/generated/internal/class.d.ts.map +1 -1
- package/dist/prisma/generated/internal/class.js +4 -4
- package/dist/prisma/generated/internal/class.js.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespace.d.ts +90 -1
- package/dist/prisma/generated/internal/prismaNamespace.d.ts.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespace.js +11 -0
- package/dist/prisma/generated/internal/prismaNamespace.js.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts +12 -0
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.d.ts.map +1 -1
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.js +11 -0
- package/dist/prisma/generated/internal/prismaNamespaceBrowser.js.map +1 -1
- package/dist/prisma/generated/models/SessionLifecycleEvent.d.ts +657 -0
- package/dist/prisma/generated/models/SessionLifecycleEvent.d.ts.map +1 -0
- package/dist/prisma/generated/models/SessionLifecycleEvent.js +2 -0
- package/dist/prisma/generated/models/SessionLifecycleEvent.js.map +1 -0
- package/dist/prisma/generated/models/Workspace.d.ts +264 -0
- package/dist/prisma/generated/models/Workspace.d.ts.map +1 -1
- package/dist/prisma/generated/models.d.ts +1 -0
- package/dist/prisma/generated/models.d.ts.map +1 -1
- package/dist/src/backend/app-context.d.ts.map +1 -1
- package/dist/src/backend/app-context.js +2 -1
- package/dist/src/backend/app-context.js.map +1 -1
- package/dist/src/backend/interceptors/branch-naming.interceptor.d.ts.map +1 -1
- package/dist/src/backend/interceptors/branch-naming.interceptor.js +0 -4
- package/dist/src/backend/interceptors/branch-naming.interceptor.js.map +1 -1
- package/dist/src/backend/interceptors/branch-naming.interceptor.test.js +26 -0
- package/dist/src/backend/interceptors/branch-naming.interceptor.test.js.map +1 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts +2 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.js +6 -6
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js +18 -8
- package/dist/src/backend/orchestration/domain-bridges.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.js +3 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.test.js +3 -1
- package/dist/src/backend/orchestration/event-collector.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/reconciliation.service.d.ts +11 -8
- package/dist/src/backend/orchestration/reconciliation.service.d.ts.map +1 -1
- package/dist/src/backend/orchestration/reconciliation.service.js +41 -33
- package/dist/src/backend/orchestration/reconciliation.service.js.map +1 -1
- package/dist/src/backend/orchestration/reconciliation.service.test.js +9 -42
- package/dist/src/backend/orchestration/reconciliation.service.test.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts +4 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.js +4 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js +15 -2
- package/dist/src/backend/orchestration/workspace-archive.orchestrator.test.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-init-issue-prompts.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-init-issue-prompts.js +3 -1
- package/dist/src/backend/orchestration/workspace-init-issue-prompts.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-init-issue-prompts.test.d.ts +2 -0
- package/dist/src/backend/orchestration/workspace-init-issue-prompts.test.d.ts.map +1 -0
- package/dist/src/backend/orchestration/workspace-init-issue-prompts.test.js +75 -0
- package/dist/src/backend/orchestration/workspace-init-issue-prompts.test.js.map +1 -0
- package/dist/src/backend/orchestration/workspace-init.orchestrator.d.ts +7 -4
- package/dist/src/backend/orchestration/workspace-init.orchestrator.d.ts.map +1 -1
- package/dist/src/backend/orchestration/workspace-init.orchestrator.js +36 -1
- package/dist/src/backend/orchestration/workspace-init.orchestrator.js.map +1 -1
- package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js +117 -8
- package/dist/src/backend/orchestration/workspace-init.orchestrator.test.js.map +1 -1
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.d.ts.map +1 -1
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.js +27 -6
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.js.map +1 -1
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.test.js +7 -0
- package/dist/src/backend/services/periodic-task/resources/periodic-task.accessor.test.js.map +1 -1
- package/dist/src/backend/services/port.service.d.ts.map +1 -1
- package/dist/src/backend/services/port.service.js +4 -0
- package/dist/src/backend/services/port.service.js.map +1 -1
- package/dist/src/backend/services/port.service.test.js +8 -0
- package/dist/src/backend/services/port.service.test.js.map +1 -1
- package/dist/src/backend/services/registry.d.ts +2 -2
- package/dist/src/backend/services/registry.d.ts.map +1 -1
- package/dist/src/backend/services/registry.js +2 -1
- package/dist/src/backend/services/registry.js.map +1 -1
- package/dist/src/backend/services/session/resources/session-lifecycle-event.accessor.d.ts +23 -0
- package/dist/src/backend/services/session/resources/session-lifecycle-event.accessor.d.ts.map +1 -0
- package/dist/src/backend/services/session/resources/session-lifecycle-event.accessor.js +23 -0
- package/dist/src/backend/services/session/resources/session-lifecycle-event.accessor.js.map +1 -0
- package/dist/src/backend/services/session/resources/session-lifecycle-event.accessor.test.d.ts +2 -0
- package/dist/src/backend/services/session/resources/session-lifecycle-event.accessor.test.d.ts.map +1 -0
- package/dist/src/backend/services/session/resources/session-lifecycle-event.accessor.test.js +62 -0
- package/dist/src/backend/services/session/resources/session-lifecycle-event.accessor.test.js.map +1 -0
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.d.ts +2 -1
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.js +14 -7
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.js.map +1 -1
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.test.js +33 -0
- package/dist/src/backend/services/session/service/acp/acp-runtime-manager.test.js.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/attachment-processing.test.js +21 -0
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/attachment-processing.test.js.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.js +3 -279
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.js.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.test.js +154 -7
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/load-session.handler.test.js.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/stop.handler.js +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/stop.handler.js.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/stop.handler.test.js +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/handlers/stop.handler.test.js.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/image-format-validation.js +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers/image-format-validation.js.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.js +4 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.js.map +1 -1
- package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.test.js +49 -0
- package/dist/src/backend/services/session/service/chat/chat-message-handlers.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/index.d.ts +1 -1
- package/dist/src/backend/services/session/service/index.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/index.js +1 -1
- package/dist/src/backend/services/session/service/index.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.d.ts +5 -1
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.js +23 -4
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.text-streaming.test.js +28 -0
- package/dist/src/backend/services/session/service/lifecycle/acp-event-processor.text-streaming.test.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session-lifecycle-event.service.d.ts +26 -0
- package/dist/src/backend/services/session/service/lifecycle/session-lifecycle-event.service.d.ts.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session-lifecycle-event.service.js +84 -0
- package/dist/src/backend/services/session/service/lifecycle/session-lifecycle-event.service.js.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session-lifecycle-event.service.test.d.ts +2 -0
- package/dist/src/backend/services/session/service/lifecycle/session-lifecycle-event.service.test.d.ts.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session-lifecycle-event.service.test.js +283 -0
- package/dist/src/backend/services/session/service/lifecycle/session-lifecycle-event.service.test.js.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session-provider-history-hydrator.d.ts +10 -0
- package/dist/src/backend/services/session/service/lifecycle/session-provider-history-hydrator.d.ts.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session-provider-history-hydrator.js +299 -0
- package/dist/src/backend/services/session/service/lifecycle/session-provider-history-hydrator.js.map +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session-services.d.ts +2 -0
- package/dist/src/backend/services/session/service/lifecycle/session-services.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session-services.js +11 -0
- package/dist/src/backend/services/session/service/lifecycle/session-services.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.d.ts +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.js +17 -0
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.test.js +42 -0
- package/dist/src/backend/services/session/service/lifecycle/session.config.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.error-message.d.ts +2 -0
- package/dist/src/backend/services/session/service/lifecycle/session.error-message.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.error-message.js +21 -0
- package/dist/src/backend/services/session/service/lifecycle/session.error-message.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.error-message.test.js +26 -1
- package/dist/src/backend/services/session/service/lifecycle/session.error-message.test.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.d.ts +31 -2
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.js +279 -109
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.test.js +465 -8
- package/dist/src/backend/services/session/service/lifecycle/session.lifecycle.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.prompt.service.test.js +206 -5
- package/dist/src/backend/services/session/service/lifecycle/session.prompt.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.service.d.ts +15 -2
- package/dist/src/backend/services/session/service/lifecycle/session.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.service.js +87 -14
- package/dist/src/backend/services/session/service/lifecycle/session.service.js.map +1 -1
- package/dist/src/backend/services/session/service/lifecycle/session.service.test.js +1 -0
- package/dist/src/backend/services/session/service/lifecycle/session.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/session-domain.service.d.ts +1 -0
- package/dist/src/backend/services/session/service/session-domain.service.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/session-domain.service.js +9 -0
- package/dist/src/backend/services/session/service/session-domain.service.js.map +1 -1
- package/dist/src/backend/services/session/service/session-domain.service.test.js +58 -0
- package/dist/src/backend/services/session/service/session-domain.service.test.js.map +1 -1
- package/dist/src/backend/services/session/service/store/session-lifecycle-transcript.d.ts +6 -0
- package/dist/src/backend/services/session/service/store/session-lifecycle-transcript.d.ts.map +1 -0
- package/dist/src/backend/services/session/service/store/session-lifecycle-transcript.js +114 -0
- package/dist/src/backend/services/session/service/store/session-lifecycle-transcript.js.map +1 -0
- package/dist/src/backend/services/session/service/store/session-lifecycle-transcript.test.d.ts +2 -0
- package/dist/src/backend/services/session/service/store/session-lifecycle-transcript.test.d.ts.map +1 -0
- package/dist/src/backend/services/session/service/store/session-lifecycle-transcript.test.js +129 -0
- package/dist/src/backend/services/session/service/store/session-lifecycle-transcript.test.js.map +1 -0
- package/dist/src/backend/services/session/service/store/session-transcript.d.ts.map +1 -1
- package/dist/src/backend/services/session/service/store/session-transcript.js +7 -4
- package/dist/src/backend/services/session/service/store/session-transcript.js.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.js +1 -0
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.js.map +1 -1
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.test.js +12 -0
- package/dist/src/backend/services/workspace/service/lifecycle/creation.service.test.js.map +1 -1
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.d.ts +1 -0
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.d.ts.map +1 -1
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.js +14 -0
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.js.map +1 -1
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.test.js +54 -0
- package/dist/src/backend/services/workspace/service/worktree/worktree-lifecycle.service.test.js.map +1 -1
- package/dist/src/backend/trpc/project.router.test.js +19 -0
- package/dist/src/backend/trpc/project.router.test.js.map +1 -1
- package/dist/src/backend/trpc/project.trpc.js +1 -1
- package/dist/src/backend/trpc/project.trpc.js.map +1 -1
- package/dist/src/backend/trpc/session.router.test.js +11 -0
- package/dist/src/backend/trpc/session.router.test.js.map +1 -1
- package/dist/src/backend/trpc/session.trpc.d.ts.map +1 -1
- package/dist/src/backend/trpc/session.trpc.js +4 -0
- package/dist/src/backend/trpc/session.trpc.js.map +1 -1
- package/dist/src/cli/runtime-utils.d.ts.map +1 -1
- package/dist/src/cli/runtime-utils.js +4 -0
- package/dist/src/cli/runtime-utils.js.map +1 -1
- package/dist/src/cli/runtime-utils.test.js +7 -0
- package/dist/src/cli/runtime-utils.test.js.map +1 -1
- package/dist/src/shared/acp-protocol/protocol/messages.d.ts +18 -2
- package/dist/src/shared/acp-protocol/protocol/messages.d.ts.map +1 -1
- package/dist/src/shared/acp-protocol/protocol/messages.js +1 -0
- package/dist/src/shared/acp-protocol/protocol/messages.js.map +1 -1
- package/dist/src/shared/acp-protocol/protocol/renderer-window.d.ts.map +1 -1
- package/dist/src/shared/acp-protocol/protocol/renderer-window.js +3 -0
- package/dist/src/shared/acp-protocol/protocol/renderer-window.js.map +1 -1
- package/dist/src/shared/core/enums.d.ts +15 -0
- package/dist/src/shared/core/enums.d.ts.map +1 -1
- package/dist/src/shared/core/enums.js +13 -0
- package/dist/src/shared/core/enums.js.map +1 -1
- package/dist/src/shared/core/index.d.ts +1 -1
- package/dist/src/shared/core/index.d.ts.map +1 -1
- package/dist/src/shared/core/index.js +1 -1
- package/dist/src/shared/core/index.js.map +1 -1
- package/dist/src/shared/issue-start-prompt.d.ts.map +1 -1
- package/dist/src/shared/issue-start-prompt.js +8 -3
- package/dist/src/shared/issue-start-prompt.js.map +1 -1
- package/dist/src/test-utils/application-graph.d.ts.map +1 -1
- package/dist/src/test-utils/application-graph.js +3 -1
- package/dist/src/test-utils/application-graph.js.map +1 -1
- package/dist/tsconfig.backend.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/prisma/migrations/20260730140000_add_session_lifecycle_events/migration.sql +20 -0
- package/prisma/schema.prisma +32 -0
- package/dist/client/assets/channel-DVMObwOq.js +0 -1
- package/dist/client/assets/classDiagram-OUVF2IWQ-wHGXcbfd.js +0 -1
- package/dist/client/assets/classDiagram-v2-EOCWNBFH-wHGXcbfd.js +0 -1
- package/dist/client/assets/stateDiagram-v2-6OUMAXLB-CGxDgHho.js +0 -1
- package/dist/client/assets/swimlanesDiagram-G3AALYLV-1u_1g3u4.js +0 -8
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
1
2
|
import { configService } from '../../../../../backend/services/config.service.js';
|
|
2
3
|
import { createLogger } from '../../../../../backend/services/logger.service.js';
|
|
3
4
|
import { getChildWorkspaceMcpServerConfig } from '../../../../../backend/services/session/service/acp/child-workspace-mcp-server.js';
|
|
@@ -5,7 +6,7 @@ import { acpTraceLogger } from '../../../../../backend/services/session/service/
|
|
|
5
6
|
import { sessionEventBus } from '../../../../../backend/services/session/service/session-event-bus.js';
|
|
6
7
|
import { userSettingsService } from '../../../../../backend/services/settings/index.js';
|
|
7
8
|
import { workspaceDataService, workspaceNotificationService } from '../../../../../backend/services/workspace/index.js';
|
|
8
|
-
import { SessionStatus } from '../../../../../shared/core/index.js';
|
|
9
|
+
import { SessionLifecycleEventKind, SessionLifecycleEventReason, SessionStatus, } from '../../../../../shared/core/index.js';
|
|
9
10
|
import { createInitialSessionRuntimeState, } from '../../../../../shared/session-runtime.js';
|
|
10
11
|
import { buildWorkspaceNotificationMessageText, WORKSPACE_NOTIFICATION_MESSAGE_ID_PREFIX, workspaceNotificationMessageId, } from '../../../../../shared/workspace-notifications.js';
|
|
11
12
|
import { closedSessionPersistenceService } from './closed-session-persistence.service.js';
|
|
@@ -16,6 +17,13 @@ const logger = createLogger('session');
|
|
|
16
17
|
function getPersistedStatusForExitCode(exitCode) {
|
|
17
18
|
return exitCode === 0 ? SessionStatus.COMPLETED : SessionStatus.FAILED;
|
|
18
19
|
}
|
|
20
|
+
const SESSION_STOP_MESSAGES = {
|
|
21
|
+
USER_STOP: 'Session stopped by you.',
|
|
22
|
+
SESSION_CLOSED: 'Session closed by you.',
|
|
23
|
+
WORKSPACE_ARCHIVED: 'Session stopped because the workspace was archived.',
|
|
24
|
+
SYSTEM_STOP: 'Session stopped by the system.',
|
|
25
|
+
};
|
|
26
|
+
const SHUTDOWN_LIFECYCLE_RECORD_TIMEOUT_MS = 1000;
|
|
19
27
|
export class SessionLifecycleService {
|
|
20
28
|
repository;
|
|
21
29
|
promptBuilder;
|
|
@@ -26,11 +34,16 @@ export class SessionLifecycleService {
|
|
|
26
34
|
acpEventProcessor;
|
|
27
35
|
promptTurnCompletionService;
|
|
28
36
|
retryService;
|
|
37
|
+
lifecycleEventService;
|
|
38
|
+
hydrateProviderHistory;
|
|
29
39
|
sendSessionMessage;
|
|
30
40
|
onBeforeStopSession;
|
|
31
41
|
onSessionExit;
|
|
32
42
|
stoppingSessions = new Set();
|
|
43
|
+
shutdownSessions = new Set();
|
|
44
|
+
stopGenerationCounter = 0;
|
|
33
45
|
stopGenerations = new Map();
|
|
46
|
+
startupGenerationReferences = new Map();
|
|
34
47
|
clientCreationOperations = new Map();
|
|
35
48
|
workspaceBridge = null;
|
|
36
49
|
messageQueueBridge = null;
|
|
@@ -45,6 +58,9 @@ export class SessionLifecycleService {
|
|
|
45
58
|
this.acpEventProcessor = options.acpEventProcessor;
|
|
46
59
|
this.promptTurnCompletionService = options.promptTurnCompletionService;
|
|
47
60
|
this.retryService = options.retryService;
|
|
61
|
+
this.lifecycleEventService = options.lifecycleEventService;
|
|
62
|
+
this.hydrateProviderHistory =
|
|
63
|
+
options.hydrateProviderHistory ?? (async () => undefined);
|
|
48
64
|
this.sendSessionMessage = options.sendSessionMessage;
|
|
49
65
|
this.onBeforeStopSession = options.onBeforeStopSession;
|
|
50
66
|
this.onSessionExit = options.onSessionExit;
|
|
@@ -55,32 +71,34 @@ export class SessionLifecycleService {
|
|
|
55
71
|
this.autoIterationExitBridge = bridges.autoIterationExit ?? null;
|
|
56
72
|
}
|
|
57
73
|
async startSession(sessionId, options) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
await this.runStartupOperation(sessionId, async (stopGeneration) => {
|
|
75
|
+
const session = await this.repository.getSessionById(sessionId);
|
|
76
|
+
if (!session) {
|
|
77
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
78
|
+
}
|
|
79
|
+
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
80
|
+
const existingClient = this.runtimeManager.getClient(sessionId);
|
|
81
|
+
if (existingClient) {
|
|
82
|
+
throw new Error('Session is already running');
|
|
83
|
+
}
|
|
84
|
+
const startupModePreset = options?.startupModePreset;
|
|
85
|
+
const { handle, resolvedPreset, dispatchableNotificationCount } = await this.getOrCreateAcpSessionClient(sessionId, {}, session, stopGeneration);
|
|
86
|
+
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
87
|
+
await this.applyStartupModePreset(sessionId, handle, startupModePreset, session.workflow);
|
|
88
|
+
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
89
|
+
await this.applyConfiguredPermissionPreset(sessionId, session, handle, resolvedPreset);
|
|
90
|
+
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
91
|
+
await this.dispatchQueuedNotificationsIfNeeded(sessionId, dispatchableNotificationCount);
|
|
92
|
+
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
93
|
+
const initialPrompt = options?.initialPrompt ?? 'Continue with the task.';
|
|
94
|
+
const shouldSendInitialPrompt = dispatchableNotificationCount === 0 ||
|
|
95
|
+
(typeof options?.initialPrompt === 'string' && !options.initialPromptIsDefault);
|
|
96
|
+
if (shouldSendInitialPrompt && initialPrompt) {
|
|
97
|
+
await this.sendSessionMessage(sessionId, initialPrompt);
|
|
98
|
+
}
|
|
99
|
+
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
100
|
+
logger.info('Session started', { sessionId, provider: session.provider });
|
|
101
|
+
});
|
|
84
102
|
}
|
|
85
103
|
async restartSession(sessionId, options) {
|
|
86
104
|
const isRunning = this.runtimeManager.isSessionRunning(sessionId);
|
|
@@ -110,25 +128,38 @@ export class SessionLifecycleService {
|
|
|
110
128
|
logger.debug('Session stop already in progress', { sessionId });
|
|
111
129
|
return;
|
|
112
130
|
}
|
|
113
|
-
this.
|
|
131
|
+
this.advanceStopGeneration(sessionId);
|
|
114
132
|
this.stoppingSessions.add(sessionId);
|
|
133
|
+
const stopInvocationId = randomUUID();
|
|
115
134
|
try {
|
|
116
|
-
await this.stopSessionWithBarrier(sessionId, options);
|
|
135
|
+
await this.stopSessionWithBarrier(sessionId, stopInvocationId, options);
|
|
117
136
|
}
|
|
118
137
|
finally {
|
|
119
138
|
this.stoppingSessions.delete(sessionId);
|
|
139
|
+
this.stopGenerations.delete(sessionId);
|
|
120
140
|
}
|
|
121
141
|
}
|
|
122
|
-
async stopSessionWithBarrier(sessionId, options) {
|
|
142
|
+
async stopSessionWithBarrier(sessionId, stopInvocationId, options) {
|
|
123
143
|
this.promptTurnCompletionService.clearSession(sessionId);
|
|
124
144
|
this.onBeforeStopSession?.(sessionId);
|
|
125
145
|
this.sessionDomainService.clearQueuedWork(sessionId, { emitSnapshot: true });
|
|
126
146
|
const session = await this.loadSessionForStop(sessionId);
|
|
127
147
|
const workspaceId = session?.workspaceId ?? this.acpEventProcessor.getWorkspaceId(sessionId);
|
|
148
|
+
const reason = options?.reason ?? 'SYSTEM_STOP';
|
|
128
149
|
if (this.runtimeManager.isStopInProgress(sessionId)) {
|
|
129
150
|
logger.debug('Session stop already in progress', { sessionId });
|
|
130
151
|
return;
|
|
131
152
|
}
|
|
153
|
+
if (workspaceId && options?.recordLifecycleEvent !== false) {
|
|
154
|
+
await this.lifecycleEventService.record({
|
|
155
|
+
workspaceId,
|
|
156
|
+
sessionId,
|
|
157
|
+
kind: SessionLifecycleEventKind.SESSION_STOPPED,
|
|
158
|
+
reason,
|
|
159
|
+
message: SESSION_STOP_MESSAGES[reason],
|
|
160
|
+
dedupeKey: `session-stop:${stopInvocationId}`,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
132
163
|
const current = this.getRuntimeSnapshot(sessionId);
|
|
133
164
|
this.sessionDomainService.setRuntimeSnapshot(sessionId, {
|
|
134
165
|
...current,
|
|
@@ -190,14 +221,14 @@ export class SessionLifecycleService {
|
|
|
190
221
|
await this.runtimeManager.stopClient(sessionId);
|
|
191
222
|
}
|
|
192
223
|
}
|
|
193
|
-
async stopWorkspaceSessions(workspaceId) {
|
|
224
|
+
async stopWorkspaceSessions(workspaceId, options) {
|
|
194
225
|
const sessions = await this.repository.getSessionsByWorkspaceId(workspaceId);
|
|
195
226
|
const stopErrors = [];
|
|
196
227
|
for (const session of sessions) {
|
|
197
228
|
if (session.status === SessionStatus.RUNNING ||
|
|
198
229
|
this.runtimeManager.isSessionRunning(session.id)) {
|
|
199
230
|
try {
|
|
200
|
-
await this.stopSession(session.id);
|
|
231
|
+
await this.stopSession(session.id, { reason: options?.reason ?? 'SYSTEM_STOP' });
|
|
201
232
|
}
|
|
202
233
|
catch (error) {
|
|
203
234
|
logger.error('Failed to stop workspace session', {
|
|
@@ -215,36 +246,38 @@ export class SessionLifecycleService {
|
|
|
215
246
|
logger.info('Stopped all workspace sessions', { workspaceId, count: sessions.length });
|
|
216
247
|
}
|
|
217
248
|
async getOrCreateSessionClient(sessionId, options) {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
224
|
-
const hadClient = !!this.runtimeManager.getClient(sessionId);
|
|
225
|
-
const { handle, resolvedPreset, dispatchableNotificationCount } = await this.getOrCreateAcpSessionClient(sessionId, options ?? {}, session, stopGeneration);
|
|
226
|
-
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
227
|
-
if (!hadClient) {
|
|
228
|
-
await this.applyConfiguredPermissionPreset(sessionId, session, handle, resolvedPreset);
|
|
249
|
+
return await this.runStartupOperation(sessionId, async (stopGeneration) => {
|
|
250
|
+
const session = await this.repository.getSessionById(sessionId);
|
|
251
|
+
if (!session) {
|
|
252
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
253
|
+
}
|
|
229
254
|
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
230
|
-
|
|
255
|
+
const hadClient = !!this.runtimeManager.getClient(sessionId);
|
|
256
|
+
const { handle, resolvedPreset, dispatchableNotificationCount } = await this.getOrCreateAcpSessionClient(sessionId, options ?? {}, session, stopGeneration);
|
|
231
257
|
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
232
|
-
|
|
233
|
-
|
|
258
|
+
if (!hadClient) {
|
|
259
|
+
await this.applyConfiguredPermissionPreset(sessionId, session, handle, resolvedPreset);
|
|
260
|
+
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
261
|
+
await this.dispatchQueuedNotificationsIfNeeded(sessionId, dispatchableNotificationCount);
|
|
262
|
+
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
263
|
+
}
|
|
264
|
+
return handle;
|
|
265
|
+
});
|
|
234
266
|
}
|
|
235
267
|
async getOrCreateSessionClientFromRecord(session, options) {
|
|
236
|
-
|
|
237
|
-
this.assertStartupAllowed(session.id, stopGeneration);
|
|
238
|
-
const hadClient = !!this.runtimeManager.getClient(session.id);
|
|
239
|
-
const { handle, resolvedPreset, dispatchableNotificationCount } = await this.getOrCreateAcpSessionClient(session.id, options ?? {}, session, stopGeneration);
|
|
240
|
-
this.assertStartupAllowed(session.id, stopGeneration);
|
|
241
|
-
if (!hadClient) {
|
|
242
|
-
await this.applyConfiguredPermissionPreset(session.id, session, handle, resolvedPreset);
|
|
268
|
+
return await this.runStartupOperation(session.id, async (stopGeneration) => {
|
|
243
269
|
this.assertStartupAllowed(session.id, stopGeneration);
|
|
244
|
-
|
|
270
|
+
const hadClient = !!this.runtimeManager.getClient(session.id);
|
|
271
|
+
const { handle, resolvedPreset, dispatchableNotificationCount } = await this.getOrCreateAcpSessionClient(session.id, options ?? {}, session, stopGeneration);
|
|
245
272
|
this.assertStartupAllowed(session.id, stopGeneration);
|
|
246
|
-
|
|
247
|
-
|
|
273
|
+
if (!hadClient) {
|
|
274
|
+
await this.applyConfiguredPermissionPreset(session.id, session, handle, resolvedPreset);
|
|
275
|
+
this.assertStartupAllowed(session.id, stopGeneration);
|
|
276
|
+
await this.dispatchQueuedNotificationsIfNeeded(session.id, dispatchableNotificationCount);
|
|
277
|
+
this.assertStartupAllowed(session.id, stopGeneration);
|
|
278
|
+
}
|
|
279
|
+
return handle;
|
|
280
|
+
});
|
|
248
281
|
}
|
|
249
282
|
getSessionClient(sessionId) {
|
|
250
283
|
return this.runtimeManager.getClient(sessionId);
|
|
@@ -285,10 +318,49 @@ export class SessionLifecycleService {
|
|
|
285
318
|
return this.stoppingSessions.has(sessionId) || this.runtimeManager.isStopInProgress(sessionId);
|
|
286
319
|
}
|
|
287
320
|
getStopGeneration(sessionId) {
|
|
288
|
-
return this.stopGenerations.get(sessionId) ??
|
|
321
|
+
return this.stopGenerations.get(sessionId) ?? this.advanceStopGeneration(sessionId);
|
|
322
|
+
}
|
|
323
|
+
async runStartupOperation(sessionId, operation) {
|
|
324
|
+
const stopGeneration = this.getStopGeneration(sessionId);
|
|
325
|
+
this.startupGenerationReferences.set(stopGeneration, (this.startupGenerationReferences.get(stopGeneration) ?? 0) + 1);
|
|
326
|
+
let succeeded = false;
|
|
327
|
+
try {
|
|
328
|
+
const result = await operation(stopGeneration);
|
|
329
|
+
succeeded = true;
|
|
330
|
+
return result;
|
|
331
|
+
}
|
|
332
|
+
finally {
|
|
333
|
+
this.releaseStartupGeneration(sessionId, stopGeneration, succeeded);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
releaseStartupGeneration(sessionId, stopGeneration, succeeded) {
|
|
337
|
+
const referenceCount = this.startupGenerationReferences.get(stopGeneration);
|
|
338
|
+
if (referenceCount === undefined) {
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
if (referenceCount > 1) {
|
|
342
|
+
this.startupGenerationReferences.set(stopGeneration, referenceCount - 1);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
this.startupGenerationReferences.delete(stopGeneration);
|
|
346
|
+
if (!(succeeded ||
|
|
347
|
+
this.isSessionStopping(sessionId) ||
|
|
348
|
+
this.runtimeManager.getClient(sessionId)) &&
|
|
349
|
+
this.isStopGenerationCurrent(sessionId, stopGeneration)) {
|
|
350
|
+
this.stopGenerations.delete(sessionId);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
isStopGenerationCurrent(sessionId, stopGeneration) {
|
|
354
|
+
return this.stopGenerations.get(sessionId) === stopGeneration;
|
|
355
|
+
}
|
|
356
|
+
advanceStopGeneration(sessionId) {
|
|
357
|
+
this.stopGenerationCounter += 1;
|
|
358
|
+
this.stopGenerations.set(sessionId, this.stopGenerationCounter);
|
|
359
|
+
return this.stopGenerationCounter;
|
|
289
360
|
}
|
|
290
361
|
assertStartupAllowed(sessionId, stopGeneration) {
|
|
291
|
-
if (this.isSessionStopping(sessionId) ||
|
|
362
|
+
if (this.isSessionStopping(sessionId) ||
|
|
363
|
+
!this.isStopGenerationCurrent(sessionId, stopGeneration)) {
|
|
292
364
|
throw new Error('Session is currently being stopped');
|
|
293
365
|
}
|
|
294
366
|
}
|
|
@@ -307,6 +379,11 @@ export class SessionLifecycleService {
|
|
|
307
379
|
}
|
|
308
380
|
async stopAllClients(timeoutMs = 5000) {
|
|
309
381
|
this.promptTurnCompletionService.clearAll();
|
|
382
|
+
const shutdownSessionIds = this.runtimeManager.beginShutdown();
|
|
383
|
+
for (const sessionId of shutdownSessionIds) {
|
|
384
|
+
this.shutdownSessions.add(sessionId);
|
|
385
|
+
}
|
|
386
|
+
await this.recordShutdownLifecycleEvents(shutdownSessionIds);
|
|
310
387
|
try {
|
|
311
388
|
await this.runtimeManager.stopAllClients(timeoutMs);
|
|
312
389
|
}
|
|
@@ -317,8 +394,52 @@ export class SessionLifecycleService {
|
|
|
317
394
|
throw error;
|
|
318
395
|
}
|
|
319
396
|
}
|
|
397
|
+
async recordShutdownLifecycleEvent(sessionId) {
|
|
398
|
+
const session = await this.loadSessionForStop(sessionId);
|
|
399
|
+
const workspaceId = session?.workspaceId ?? this.acpEventProcessor.getWorkspaceId(sessionId);
|
|
400
|
+
if (!workspaceId) {
|
|
401
|
+
logger.warn('Skipped shutdown lifecycle event without workspace owner', { sessionId });
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
await this.lifecycleEventService.record({
|
|
405
|
+
workspaceId,
|
|
406
|
+
sessionId,
|
|
407
|
+
kind: SessionLifecycleEventKind.SESSION_STOPPED,
|
|
408
|
+
reason: SessionLifecycleEventReason.SYSTEM_STOP,
|
|
409
|
+
message: SESSION_STOP_MESSAGES.SYSTEM_STOP,
|
|
410
|
+
dedupeKey: `session-stop:${randomUUID()}`,
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
async recordShutdownLifecycleEvents(sessionIds) {
|
|
414
|
+
const resultsPromise = Promise.allSettled(sessionIds.map((sessionId) => this.recordShutdownLifecycleEvent(sessionId)));
|
|
415
|
+
let timeout;
|
|
416
|
+
const results = await Promise.race([
|
|
417
|
+
resultsPromise,
|
|
418
|
+
new Promise((resolve) => {
|
|
419
|
+
timeout = setTimeout(() => resolve(null), SHUTDOWN_LIFECYCLE_RECORD_TIMEOUT_MS);
|
|
420
|
+
}),
|
|
421
|
+
]);
|
|
422
|
+
if (timeout) {
|
|
423
|
+
clearTimeout(timeout);
|
|
424
|
+
}
|
|
425
|
+
if (results === null) {
|
|
426
|
+
logger.warn('Timed out recording shutdown lifecycle events; continuing shutdown', {
|
|
427
|
+
timeoutMs: SHUTDOWN_LIFECYCLE_RECORD_TIMEOUT_MS,
|
|
428
|
+
});
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
for (const [index, result] of results.entries()) {
|
|
432
|
+
if (result.status === 'rejected') {
|
|
433
|
+
logger.warn('Failed recording shutdown lifecycle event; continuing shutdown', {
|
|
434
|
+
sessionId: sessionIds[index],
|
|
435
|
+
error: result.reason instanceof Error ? result.reason.message : String(result.reason),
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
320
440
|
setupAcpEventHandler(sessionId) {
|
|
321
441
|
const runtimeEventHandler = this.acpEventProcessor.createRuntimeEventHandler(sessionId);
|
|
442
|
+
const runtimeIncarnationId = randomUUID();
|
|
322
443
|
return {
|
|
323
444
|
...runtimeEventHandler,
|
|
324
445
|
onSessionId: async (sid, providerSessionId) => {
|
|
@@ -342,51 +463,12 @@ export class SessionLifecycleService {
|
|
|
342
463
|
}
|
|
343
464
|
},
|
|
344
465
|
onExit: async (sid, exitCode) => {
|
|
345
|
-
this.
|
|
346
|
-
this.
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
this.
|
|
350
|
-
|
|
351
|
-
try {
|
|
352
|
-
this.sessionDomainService.markProcessExit(sid, exitCode);
|
|
353
|
-
const persistedStatus = getPersistedStatusForExitCode(exitCode);
|
|
354
|
-
const session = await this.repository.updateSession(sid, {
|
|
355
|
-
status: persistedStatus,
|
|
356
|
-
});
|
|
357
|
-
logger.debug('Updated ACP session status on exit', {
|
|
358
|
-
sessionId: sid,
|
|
359
|
-
exitCode,
|
|
360
|
-
status: persistedStatus,
|
|
361
|
-
});
|
|
362
|
-
await this.recordRatchetSessionEndOnExit(session.workspaceId, sid, exitCode);
|
|
363
|
-
void this.maybeDiscoverPROnSessionEnd(session.workspaceId);
|
|
364
|
-
if (session.workflow === 'ratchet') {
|
|
365
|
-
await this.persistRatchetTranscript(sid, session);
|
|
366
|
-
await this.repository.deleteSession(sid);
|
|
367
|
-
this.sessionDomainService.clearSession(sid);
|
|
368
|
-
logger.debug('Deleted transient ratchet ACP session', { sessionId: sid });
|
|
369
|
-
}
|
|
370
|
-
if (session.workflow === 'auto-iteration' && this.autoIterationExitBridge) {
|
|
371
|
-
if (!this.runtimeManager.isStopInProgress(sid)) {
|
|
372
|
-
this.autoIterationExitBridge.onAutoIterationSessionExit(session.workspaceId, sid);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
catch (error) {
|
|
377
|
-
logger.warn('Failed to update ACP session status on exit', {
|
|
378
|
-
sessionId: sid,
|
|
379
|
-
error: error instanceof Error ? error.message : String(error),
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
finally {
|
|
383
|
-
try {
|
|
384
|
-
this.clearSessionStoreIfInactive(sid, 'runtime_exit');
|
|
385
|
-
}
|
|
386
|
-
finally {
|
|
387
|
-
acpTraceLogger.closeSession(sid);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
466
|
+
this.stopGenerations.delete(sid);
|
|
467
|
+
const wasDeliberateStop = this.stoppingSessions.has(sid) ||
|
|
468
|
+
this.shutdownSessions.has(sid) ||
|
|
469
|
+
this.runtimeManager.isStopInProgress(sid);
|
|
470
|
+
this.prepareAcpRuntimeExit(sid, exitCode);
|
|
471
|
+
await this.handleAcpRuntimeExit(sid, exitCode, wasDeliberateStop, runtimeIncarnationId);
|
|
390
472
|
},
|
|
391
473
|
onError: (sid, error) => {
|
|
392
474
|
acpTraceLogger.log(sid, 'runtime_error', {
|
|
@@ -405,6 +487,85 @@ export class SessionLifecycleService {
|
|
|
405
487
|
},
|
|
406
488
|
};
|
|
407
489
|
}
|
|
490
|
+
prepareAcpRuntimeExit(sessionId, exitCode) {
|
|
491
|
+
this.promptTurnCompletionService.clearSession(sessionId);
|
|
492
|
+
this.onSessionExit?.(sessionId);
|
|
493
|
+
this.finalizeOrphanedToolCalls(sessionId, 'runtime_exit');
|
|
494
|
+
this.acpEventProcessor.clearSessionState(sessionId);
|
|
495
|
+
this.sessionPermissionService.cancelPendingRequests(sessionId);
|
|
496
|
+
acpTraceLogger.log(sessionId, 'runtime_exit', { exitCode });
|
|
497
|
+
}
|
|
498
|
+
async handleAcpRuntimeExit(sessionId, exitCode, wasDeliberateStop, runtimeIncarnationId) {
|
|
499
|
+
try {
|
|
500
|
+
this.sessionDomainService.markProcessExit(sessionId, exitCode);
|
|
501
|
+
const session = await this.repository.getSessionById(sessionId);
|
|
502
|
+
if (!session) {
|
|
503
|
+
logger.warn('Failed to find ACP session on exit', { sessionId });
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
const persistedStatus = getPersistedStatusForExitCode(exitCode);
|
|
507
|
+
try {
|
|
508
|
+
await this.repository.updateSession(sessionId, { status: persistedStatus });
|
|
509
|
+
logger.debug('Updated ACP session status on exit', {
|
|
510
|
+
sessionId,
|
|
511
|
+
exitCode,
|
|
512
|
+
status: persistedStatus,
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
catch (error) {
|
|
516
|
+
logger.warn('Failed to update ACP session status on exit', {
|
|
517
|
+
sessionId,
|
|
518
|
+
error: error instanceof Error ? error.message : String(error),
|
|
519
|
+
});
|
|
520
|
+
}
|
|
521
|
+
await this.recordUnexpectedExitIfNeeded(session, sessionId, exitCode, wasDeliberateStop, runtimeIncarnationId);
|
|
522
|
+
await this.recordRatchetSessionEndOnExit(session.workspaceId, sessionId, exitCode);
|
|
523
|
+
void this.maybeDiscoverPROnSessionEnd(session.workspaceId);
|
|
524
|
+
await this.cleanupExitedWorkflow(session, sessionId, wasDeliberateStop);
|
|
525
|
+
}
|
|
526
|
+
catch (error) {
|
|
527
|
+
logger.warn('Failed to process ACP session exit', {
|
|
528
|
+
sessionId,
|
|
529
|
+
error: error instanceof Error ? error.message : String(error),
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
finally {
|
|
533
|
+
try {
|
|
534
|
+
this.clearSessionStoreIfInactive(sessionId, 'runtime_exit');
|
|
535
|
+
}
|
|
536
|
+
finally {
|
|
537
|
+
acpTraceLogger.closeSession(sessionId);
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
async recordUnexpectedExitIfNeeded(session, sessionId, exitCode, wasDeliberateStop, runtimeIncarnationId) {
|
|
542
|
+
if (wasDeliberateStop) {
|
|
543
|
+
return;
|
|
544
|
+
}
|
|
545
|
+
await this.lifecycleEventService.record({
|
|
546
|
+
workspaceId: session.workspaceId,
|
|
547
|
+
sessionId,
|
|
548
|
+
kind: SessionLifecycleEventKind.SESSION_STOPPED,
|
|
549
|
+
reason: SessionLifecycleEventReason.UNEXPECTED_EXIT,
|
|
550
|
+
message: exitCode === null
|
|
551
|
+
? 'Session stopped: agent process exited unexpectedly.'
|
|
552
|
+
: `Session stopped: agent process exited unexpectedly (code ${exitCode}).`,
|
|
553
|
+
dedupeKey: `process-exit:${runtimeIncarnationId}:${exitCode ?? 'signal'}`,
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
async cleanupExitedWorkflow(session, sessionId, wasDeliberateStop) {
|
|
557
|
+
if (session.workflow === 'ratchet') {
|
|
558
|
+
await this.persistRatchetTranscript(sessionId);
|
|
559
|
+
await this.repository.deleteSession(sessionId);
|
|
560
|
+
this.sessionDomainService.clearSession(sessionId);
|
|
561
|
+
logger.debug('Deleted transient ratchet ACP session', { sessionId });
|
|
562
|
+
}
|
|
563
|
+
if (session.workflow === 'auto-iteration' &&
|
|
564
|
+
this.autoIterationExitBridge &&
|
|
565
|
+
!wasDeliberateStop) {
|
|
566
|
+
this.autoIterationExitBridge.onAutoIterationSessionExit(session.workspaceId, sessionId);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
408
569
|
async createAcpClient(sessionId, options, session, permissionPreset, stopGeneration = this.getStopGeneration(sessionId)) {
|
|
409
570
|
const sessionContext = await this.loadSessionContext(sessionId, session);
|
|
410
571
|
if (!sessionContext) {
|
|
@@ -581,7 +742,7 @@ export class SessionLifecycleService {
|
|
|
581
742
|
return;
|
|
582
743
|
}
|
|
583
744
|
try {
|
|
584
|
-
await this.persistRatchetTranscript(sessionId
|
|
745
|
+
await this.persistRatchetTranscript(sessionId);
|
|
585
746
|
await this.repository.deleteSession(sessionId);
|
|
586
747
|
this.sessionDomainService.clearSession(sessionId);
|
|
587
748
|
logger.debug('Deleted transient ratchet session after stop', { sessionId });
|
|
@@ -617,20 +778,26 @@ export class SessionLifecycleService {
|
|
|
617
778
|
this.sessionDomainService.clearSession(sessionId, { preserveRejections: true });
|
|
618
779
|
logger.debug('Cleared inactive in-memory session state', { sessionId, reason });
|
|
619
780
|
}
|
|
620
|
-
async
|
|
621
|
-
|
|
622
|
-
|
|
781
|
+
async persistClosedSession(sessionId) {
|
|
782
|
+
const session = await this.repository.getSessionById(sessionId);
|
|
783
|
+
if (!session) {
|
|
784
|
+
logger.warn('Cannot persist closed session: session not found', { sessionId });
|
|
623
785
|
return;
|
|
624
786
|
}
|
|
625
|
-
const transcript = this.sessionDomainService.getTranscriptSnapshot(sessionId);
|
|
626
787
|
const workspace = await workspaceDataService.findById(session.workspaceId);
|
|
627
788
|
if (!workspace?.worktreePath) {
|
|
628
|
-
logger.warn('Cannot persist
|
|
789
|
+
logger.warn('Cannot persist closed session: no worktree path', {
|
|
629
790
|
sessionId,
|
|
630
791
|
workspaceId: session.workspaceId,
|
|
631
792
|
});
|
|
632
793
|
return;
|
|
633
794
|
}
|
|
795
|
+
await this.hydrateProviderHistory(sessionId, {
|
|
796
|
+
...session,
|
|
797
|
+
workspace: { worktreePath: workspace.worktreePath },
|
|
798
|
+
});
|
|
799
|
+
await this.lifecycleEventService.hydrate(sessionId);
|
|
800
|
+
const transcript = this.sessionDomainService.getTranscriptSnapshot(sessionId);
|
|
634
801
|
await closedSessionPersistenceService.persistClosedSession({
|
|
635
802
|
sessionId,
|
|
636
803
|
workspaceId: session.workspaceId,
|
|
@@ -643,6 +810,9 @@ export class SessionLifecycleService {
|
|
|
643
810
|
messages: transcript,
|
|
644
811
|
});
|
|
645
812
|
}
|
|
813
|
+
async persistRatchetTranscript(sessionId) {
|
|
814
|
+
await this.persistClosedSession(sessionId);
|
|
815
|
+
}
|
|
646
816
|
async getOrCreateAcpSessionClient(sessionId, options, session, stopGeneration) {
|
|
647
817
|
this.assertStartupAllowed(sessionId, stopGeneration);
|
|
648
818
|
const existingAcp = this.runtimeManager.getClient(sessionId);
|