agent-tower 0.7.3 → 0.7.4-beta.1
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/git/worktree.manager.d.ts +2 -0
- package/dist/git/worktree.manager.d.ts.map +1 -1
- package/dist/git/worktree.manager.js +29 -8
- package/dist/git/worktree.manager.js.map +1 -1
- package/dist/git/worktree.manager.test.js +38 -0
- package/dist/git/worktree.manager.test.js.map +1 -1
- package/dist/mcp/http-client.d.ts +3 -1
- package/dist/mcp/http-client.d.ts.map +1 -1
- package/dist/mcp/http-client.js +6 -0
- package/dist/mcp/http-client.js.map +1 -1
- package/dist/mcp/tools/__tests__/tasks.test.js +33 -1
- package/dist/mcp/tools/__tests__/tasks.test.js.map +1 -1
- package/dist/mcp/tools/tasks.d.ts.map +1 -1
- package/dist/mcp/tools/tasks.js +30 -2
- package/dist/mcp/tools/tasks.js.map +1 -1
- package/dist/mcp/types.d.ts +24 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js +12 -1
- package/dist/mcp/types.js.map +1 -1
- package/dist/prompts/task-handoff.d.ts +6 -0
- package/dist/prompts/task-handoff.d.ts.map +1 -0
- package/dist/prompts/task-handoff.js +18 -0
- package/dist/prompts/task-handoff.js.map +1 -0
- package/dist/prompts/task-handoff.test.d.ts +2 -0
- package/dist/prompts/task-handoff.test.d.ts.map +1 -0
- package/dist/prompts/task-handoff.test.js +27 -0
- package/dist/prompts/task-handoff.test.js.map +1 -0
- package/dist/prompts/workspace-background-service-policy.d.ts +6 -0
- package/dist/prompts/workspace-background-service-policy.d.ts.map +1 -1
- package/dist/prompts/workspace-background-service-policy.js +2 -1
- package/dist/prompts/workspace-background-service-policy.js.map +1 -1
- package/dist/routes/__tests__/sessions-runtime.test.js +2 -0
- package/dist/routes/__tests__/sessions-runtime.test.js.map +1 -1
- package/dist/routes/__tests__/task-handoff.test.d.ts +2 -0
- package/dist/routes/__tests__/task-handoff.test.d.ts.map +1 -0
- package/dist/routes/__tests__/task-handoff.test.js +185 -0
- package/dist/routes/__tests__/task-handoff.test.js.map +1 -0
- package/dist/routes/__tests__/tasks.test.js +64 -0
- package/dist/routes/__tests__/tasks.test.js.map +1 -1
- package/dist/routes/__tests__/workspace-history.test.d.ts +2 -0
- package/dist/routes/__tests__/workspace-history.test.d.ts.map +1 -0
- package/dist/routes/__tests__/workspace-history.test.js +174 -0
- package/dist/routes/__tests__/workspace-history.test.js.map +1 -0
- package/dist/routes/sessions.d.ts.map +1 -1
- package/dist/routes/sessions.js +10 -0
- package/dist/routes/sessions.js.map +1 -1
- package/dist/routes/tasks.d.ts.map +1 -1
- package/dist/routes/tasks.js +67 -2
- package/dist/routes/tasks.js.map +1 -1
- package/dist/runtime/__tests__/cli-driver-lifecycle.test.js +84 -0
- package/dist/runtime/__tests__/cli-driver-lifecycle.test.js.map +1 -1
- package/dist/runtime/cli-driver.js +11 -8
- package/dist/runtime/cli-driver.js.map +1 -1
- package/dist/services/__tests__/session-manager.lifecycle.test.js +171 -1
- package/dist/services/__tests__/session-manager.lifecycle.test.js.map +1 -1
- package/dist/services/__tests__/task.service.test.js +152 -76
- package/dist/services/__tests__/task.service.test.js.map +1 -1
- package/dist/services/__tests__/workspace-background-service.service.test.js +74 -26
- package/dist/services/__tests__/workspace-background-service.service.test.js.map +1 -1
- package/dist/services/__tests__/workspace.service.test.js +100 -5
- package/dist/services/__tests__/workspace.service.test.js.map +1 -1
- package/dist/services/message-delivery.service.d.ts +3 -0
- package/dist/services/message-delivery.service.d.ts.map +1 -1
- package/dist/services/project.service.d.ts +2 -0
- package/dist/services/project.service.d.ts.map +1 -1
- package/dist/services/session-manager.d.ts +12 -1
- package/dist/services/session-manager.d.ts.map +1 -1
- package/dist/services/session-manager.js +21 -3
- package/dist/services/session-manager.js.map +1 -1
- package/dist/services/session-resource-cleanup.d.ts +5 -0
- package/dist/services/session-resource-cleanup.d.ts.map +1 -1
- package/dist/services/session-resource-cleanup.js +7 -0
- package/dist/services/session-resource-cleanup.js.map +1 -1
- package/dist/services/task-cleanup.service.d.ts +4 -0
- package/dist/services/task-cleanup.service.d.ts.map +1 -1
- package/dist/services/task-cleanup.service.js +6 -2
- package/dist/services/task-cleanup.service.js.map +1 -1
- package/dist/services/task-handoff.service.d.ts +18 -0
- package/dist/services/task-handoff.service.d.ts.map +1 -0
- package/dist/services/task-handoff.service.js +87 -0
- package/dist/services/task-handoff.service.js.map +1 -0
- package/dist/services/task.service.d.ts +46 -10
- package/dist/services/task.service.d.ts.map +1 -1
- package/dist/services/task.service.js +258 -170
- package/dist/services/task.service.js.map +1 -1
- package/dist/services/team-run.service.d.ts +2 -0
- package/dist/services/team-run.service.d.ts.map +1 -1
- package/dist/services/team-task-input.service.d.ts +2 -0
- package/dist/services/team-task-input.service.d.ts.map +1 -1
- package/dist/services/workspace-background-service.service.d.ts +1 -3
- package/dist/services/workspace-background-service.service.d.ts.map +1 -1
- package/dist/services/workspace-background-service.service.js +17 -65
- package/dist/services/workspace-background-service.service.js.map +1 -1
- package/dist/services/workspace.service.d.ts +20 -7
- package/dist/services/workspace.service.d.ts.map +1 -1
- package/dist/services/workspace.service.js +197 -82
- package/dist/services/workspace.service.js.map +1 -1
- package/dist/web/assets/AgentDemoPage-DiHEh1iv.js +1 -0
- package/dist/web/assets/{AgentEnvironmentSettingsPage-CvvkMKT1.js → AgentEnvironmentSettingsPage-B_Xk7Bef.js} +1 -1
- package/dist/web/assets/AttachmentPreview-BngGSahV.js +2 -0
- package/dist/web/assets/{BranchSelect-Cv92vEjG.js → BranchSelect-BgVKUnxj.js} +1 -1
- package/dist/web/assets/BrandLogo-CBahjTd7.js +1 -0
- package/dist/web/assets/ConversationPage-kgJIlyS5.js +1 -0
- package/dist/web/assets/CreateTaskInput-Cllw4abW.js +1 -0
- package/dist/web/assets/{DemoPage-CpYNBQhA.js → DemoPage-CkS__9CE.js} +3 -3
- package/dist/web/assets/{DesignSystemPage-DLeH6DnV.js → DesignSystemPage-BklN99GA.js} +3 -3
- package/dist/web/assets/{ExecutionPermissionSelector-IoWR9YLb.js → ExecutionPermissionSelector-Bsi1aa7q.js} +1 -1
- package/dist/web/assets/{GeneralSettingsPage-BAYgxCqx.js → GeneralSettingsPage-BC9TUWiu.js} +1 -1
- package/dist/web/assets/{LoadingPreviewPage-CumrzyxW.js → LoadingPreviewPage-Dx8Si6-g.js} +1 -1
- package/dist/web/assets/{McpSettingsPage-CFNwxT9Y.js → McpSettingsPage-fqXRGtFu.js} +1 -1
- package/dist/web/assets/{MemberAvatar-BVXD0jTy.js → MemberAvatar-CZ3F53Ep.js} +1 -1
- package/dist/web/assets/MobileTaskDetail-B68iYPOI.js +3 -0
- package/dist/web/assets/{NotificationSettingsPage-B0s5YbG3.js → NotificationSettingsPage-D9KGIFVA.js} +1 -1
- package/dist/web/assets/{ProfileSettingsPage-BuhoF-mL.js → ProfileSettingsPage-D_Hw5lpd.js} +2 -2
- package/dist/web/assets/ProjectKanbanPage-CUX0Kh-t.js +12 -0
- package/dist/web/assets/{ProjectSettingsPage-DDMg6axy.js → ProjectSettingsPage-CJANCPJX.js} +2 -2
- package/dist/web/assets/{ProviderSettingsPage-DRt9m4mF.js → ProviderSettingsPage-B6Ro5PQa.js} +2 -2
- package/dist/web/assets/{SettingsMasterDetail-D7vStQjR.js → SettingsMasterDetail-Q-049Dvh.js} +1 -1
- package/dist/web/assets/TaskDetail-DBtWf0YV.js +1 -0
- package/dist/web/assets/TaskHandoffPanel-BpGiZ5eT.js +70 -0
- package/dist/web/assets/TeamSettingsPage-DbKgqEO_.js +1 -0
- package/dist/web/assets/{TranslationSettingsPage-D2oks6OM.js → TranslationSettingsPage-Ba-iypOV.js} +1 -1
- package/dist/web/assets/{arc-vYWCZsE_.js → arc-SOqs3Svk.js} +1 -1
- package/dist/web/assets/{architectureDiagram-3BPJPVTR-Cu1VIpcJ.js → architectureDiagram-3BPJPVTR-BH25ukq_.js} +1 -1
- package/dist/web/assets/{at-sign-BhSPafOS.js → at-sign-CEsum1vJ.js} +1 -1
- package/dist/web/assets/{blockDiagram-GPEHLZMM-C4x_nj5S.js → blockDiagram-GPEHLZMM-CKA17iNP.js} +1 -1
- package/dist/web/assets/{c4Diagram-AAUBKEIU-jHOo5lal.js → c4Diagram-AAUBKEIU-DnZ_8oOf.js} +1 -1
- package/dist/web/assets/channel-xU45IQlP.js +1 -0
- package/dist/web/assets/check-DUA2DjGH.js +1 -0
- package/dist/web/assets/{chevron-down-BoS08pMa.js → chevron-down-Bmwy-nvS.js} +1 -1
- package/dist/web/assets/{chevron-up-BWtKfdKT.js → chevron-up-CClL6-SF.js} +1 -1
- package/dist/web/assets/{chip-Ck4dqxR3.js → chip-BSMT2uT1.js} +1 -1
- package/dist/web/assets/{chunk-2J33WTMH-BZcpjmfm.js → chunk-2J33WTMH-BrtUyBDF.js} +1 -1
- package/dist/web/assets/{chunk-4BX2VUAB-DZGB3q-I.js → chunk-4BX2VUAB-DZDNetDC.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-CcNrOmyy.js → chunk-55IACEB6-xVa3bJqv.js} +1 -1
- package/dist/web/assets/{chunk-727SXJPM-dWrxio8O.js → chunk-727SXJPM-B7n9vxY4.js} +1 -1
- package/dist/web/assets/{chunk-AQP2D5EJ-K4gkVzqE.js → chunk-AQP2D5EJ-DQd4G76y.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-CnHyY4qD.js → chunk-FMBD7UC4-CXyP08kl.js} +1 -1
- package/dist/web/assets/{chunk-ND2GUHAM-CHUmcyDv.js → chunk-ND2GUHAM-BtnIS-HK.js} +1 -1
- package/dist/web/assets/{chunk-QZHKN3VN-Bzzjd-Qt.js → chunk-QZHKN3VN-D4D-V_ex.js} +1 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-pvRulc6s.js +1 -0
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-pvRulc6s.js +1 -0
- package/dist/web/assets/{code-block-OCS4YCEC-B2hHBO_G.js → code-block-OCS4YCEC-DfERo9L1.js} +1 -1
- package/dist/web/assets/confirm-dialog-8ItnHBi0.js +1 -0
- package/dist/web/assets/{content-D0qmHfHK.js → content-DrW8KnXu.js} +2 -2
- package/dist/web/assets/{copy-C4WnOY6Y.js → copy-prrQrInw.js} +1 -1
- package/dist/web/assets/{cose-bilkent-S5V4N54A-Dcn8tOhb.js → cose-bilkent-S5V4N54A-CXdH8Idq.js} +1 -1
- package/dist/web/assets/cssMode-CJ6_f10q.js +1 -0
- package/dist/web/assets/{dagre-BM42HDAG-DWBV4UfP.js → dagre-BM42HDAG-XZydDwXe.js} +1 -1
- package/dist/web/assets/{diagram-2AECGRRQ-CnNTJQ3q.js → diagram-2AECGRRQ-CofEe0Fr.js} +1 -1
- package/dist/web/assets/{diagram-5GNKFQAL-DlXJFzDF.js → diagram-5GNKFQAL-BbTtW5WH.js} +1 -1
- package/dist/web/assets/{diagram-KO2AKTUF-DZ22YV4n.js → diagram-KO2AKTUF-BJHZXpUM.js} +1 -1
- package/dist/web/assets/{diagram-LMA3HP47-B4pQJjG9.js → diagram-LMA3HP47-DN7A27YU.js} +1 -1
- package/dist/web/assets/{diagram-OG6HWLK6-DJBLjtgL.js → diagram-OG6HWLK6-4IdYadiw.js} +1 -1
- package/dist/web/assets/{dialog-1o8KQWoQ.js → dialog-BUsI4h2U.js} +2 -2
- package/dist/web/assets/{erDiagram-TEJ5UH35-CDsfoJUT.js → erDiagram-TEJ5UH35-BFijhCWv.js} +1 -1
- package/dist/web/assets/{file-6qwbIga1.js → file-C6QMUr5_.js} +1 -1
- package/dist/web/assets/{flowDiagram-I6XJVG4X-CuGOAYmY.js → flowDiagram-I6XJVG4X-D9MxC-El.js} +1 -1
- package/dist/web/assets/{folder-picker-Cj1VZOZU.js → folder-picker-CBdw-4v3.js} +1 -1
- package/dist/web/assets/{freemarker2-BG8VyI2V.js → freemarker2-CJVobC22.js} +2 -2
- package/dist/web/assets/{ganttDiagram-6RSMTGT7-BjrSOqAM.js → ganttDiagram-6RSMTGT7-BijCAyPQ.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-PVQCEYII-4VVr4F8_.js → gitGraphDiagram-PVQCEYII-AvI5QqxQ.js} +1 -1
- package/dist/web/assets/{globe-CxeM27yy.js → globe-BOfcTsvL.js} +1 -1
- package/dist/web/assets/handlebars-DTqWmI25.js +1 -0
- package/dist/web/assets/html-Bx7L8DX_.js +1 -0
- package/dist/web/assets/htmlMode-D_S0NjZc.js +1 -0
- package/dist/web/assets/{index-hHrknzh7.js → index-BClyhWqz.js} +1 -1
- package/dist/web/assets/index-BDON669P.css +1 -0
- package/dist/web/assets/{index-DVdiOmqt.js → index-BFcDmhr0.js} +1 -1
- package/dist/web/assets/index-BRu1Yhrx.js +122 -0
- package/dist/web/assets/{index-Db28hRe8.js → index-Bg8TlDo_.js} +1 -1
- package/dist/web/assets/{index-Da2mWAtm.js → index-COigMgrJ.js} +1 -1
- package/dist/web/assets/{index-cu8sedJH.js → index-Cdmj8aPv.js} +1 -1
- package/dist/web/assets/index-CtOu4p9B.js +1 -0
- package/dist/web/assets/{index-CrKx8Yaz.js → index-DUmVscrR.js} +4 -4
- package/dist/web/assets/{index-C1lMEjmZ.js → index-JXcQeorP.js} +1 -1
- package/dist/web/assets/{infoDiagram-5YYISTIA-Cy9ntb6t.js → infoDiagram-5YYISTIA-76JLqjJ0.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-D6UiVzRz.js → ishikawaDiagram-YF4QCWOH-CXHFTVly.js} +1 -1
- package/dist/web/assets/javascript-80FDzX3y.js +1 -0
- package/dist/web/assets/{journeyDiagram-JHISSGLW-owdKzZoh.js → journeyDiagram-JHISSGLW-6SDJs9C5.js} +1 -1
- package/dist/web/assets/jsonMode-BGg9MhFR.js +7 -0
- package/dist/web/assets/{kanban-definition-UN3LZRKU-v5TBnyp0.js → kanban-definition-UN3LZRKU-C0Y3zy1P.js} +1 -1
- package/dist/web/assets/{kbd-Cl4AzzJp.js → kbd-D4KIW7lm.js} +1 -1
- package/dist/web/assets/{key-round-CnYjSrCz.js → key-round-C4vhwqUu.js} +1 -1
- package/dist/web/assets/{layers-XImbMX-P.js → layers-BBHgMnhN.js} +1 -1
- package/dist/web/assets/{linear-DNlKYt8R.js → linear-CjeIgBwO.js} +1 -1
- package/dist/web/assets/{link-DQk-Vapq.js → link-C-Jq7dnc.js} +1 -1
- package/dist/web/assets/liquid-guocpCJB.js +1 -0
- package/dist/web/assets/{lspLanguageFeatures-DD_y1bZa.js → lspLanguageFeatures-CPXERxVW.js} +1 -1
- package/dist/web/assets/mdx-DA4ymd3l.js +1 -0
- package/dist/web/assets/{menu-DXF6iUsq.js → menu-BgtmXAzT.js} +1 -1
- package/dist/web/assets/{mermaid-NOHMQCX5-CG_LpwAI.js → mermaid-NOHMQCX5-XQbfQDGS.js} +49 -49
- package/dist/web/assets/{message-square-BviHdb67.js → message-square-DIFv9yrO.js} +1 -1
- package/dist/web/assets/{mindmap-definition-RKZ34NQL-Bn_rnnGT.js → mindmap-definition-RKZ34NQL-6ucD61UV.js} +1 -1
- package/dist/web/assets/modal-Dx4N46s5.js +1 -0
- package/dist/web/assets/{monaco-yuGji-2E.js → monaco-Mn1xgio_.js} +3 -3
- package/dist/web/assets/nav-row-DwEkbw3N.js +1 -0
- package/dist/web/assets/{paperclip-D9ka2IAB.js → paperclip-CdQvl5ee.js} +1 -1
- package/dist/web/assets/{pencil-isP1rXC-.js → pencil-ChX7G9j9.js} +1 -1
- package/dist/web/assets/{people-CbmH8m4i.js → people-D_VwidfV.js} +1 -1
- package/dist/web/assets/{pieDiagram-4H26LBE5-DIE_f9W_.js → pieDiagram-4H26LBE5-KVvAyrIn.js} +1 -1
- package/dist/web/assets/{popover-D8VtO5qF.js → popover-CGEFZKuu.js} +1 -1
- package/dist/web/assets/python-BzNNRn8W.js +1 -0
- package/dist/web/assets/{quadrantDiagram-W4KKPZXB-CavFxJCk.js → quadrantDiagram-W4KKPZXB-ClVzvpE7.js} +1 -1
- package/dist/web/assets/razor-DF2ZxqCE.js +1 -0
- package/dist/web/assets/{requirementDiagram-4Y6WPE33-Dm1FwUUh.js → requirementDiagram-4Y6WPE33-uXN6Uoln.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-5OEKKPKP-qeqcO27M.js → sankeyDiagram-5OEKKPKP-Bi3Tc0wR.js} +1 -1
- package/dist/web/assets/{search-DOMr5jPS.js → search--FRFbCre.js} +1 -1
- package/dist/web/assets/{select-Cw5BaOLQ.js → select-D0sHgfcU.js} +1 -1
- package/dist/web/assets/{select-CzZNbe1Z.js → select-c5IIpQj0.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-3UESZ5HK-Dqtb3BYG.js → sequenceDiagram-3UESZ5HK-CLdrO2PY.js} +1 -1
- package/dist/web/assets/{server-u-PC-CcX.js → server-Dr_6KJFM.js} +1 -1
- package/dist/web/assets/{stateDiagram-AJRCARHV-C_MqF9Fy.js → stateDiagram-AJRCARHV-BGInldGc.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-D44x8SXb.js +1 -0
- package/dist/web/assets/{textarea-xt2hLb-d.js → textarea-W-xQPto3.js} +1 -1
- package/dist/web/assets/{timeline-definition-PNZ67QCA-Bzov6t31.js → timeline-definition-PNZ67QCA-BUp6Qykc.js} +1 -1
- package/dist/web/assets/{toggles-B6E1UBYN.js → toggles-Bgp7vdwg.js} +1 -1
- package/dist/web/assets/tooltip-DZcaSN1F.js +1 -0
- package/dist/web/assets/{track-BeqaPopG.js → track-Cj1Ogapu.js} +1 -1
- package/dist/web/assets/{trash-2-5jI3_KHh.js → trash-2-DmFXzIhh.js} +1 -1
- package/dist/web/assets/tsMode-CSHMQttX.js +11 -0
- package/dist/web/assets/typescript-CyQKmnN-.js +1 -0
- package/dist/web/assets/{upload-DUteazR7.js → upload-C-4QDrwN.js} +1 -1
- package/dist/web/assets/use-profiles-D5mIgeQU.js +1 -0
- package/dist/web/assets/{use-providers-CQwBj9hp.js → use-providers-BViTes-6.js} +1 -1
- package/dist/web/assets/{use-translation-settings-DBzFqP-d.js → use-translation-settings-Dgw0oKP1.js} +1 -1
- package/dist/web/assets/{useNormalizedLogs-DsdwmfS7.js → useNormalizedLogs-BX7pMg0-.js} +1 -1
- package/dist/web/assets/useTokenUsage-T03faPfn.js +1 -0
- package/dist/web/assets/{vennDiagram-CIIHVFJN-BqxICvT_.js → vennDiagram-CIIHVFJN-iQYnP9Ux.js} +1 -1
- package/dist/web/assets/{wardley-L42UT6IY-BTdLPFcA.js → wardley-L42UT6IY-J7vXwA5J.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-YWT4CUSO-icnFsFn4.js → wardleyDiagram-YWT4CUSO-CdtM5GJv.js} +1 -1
- package/dist/web/assets/xml-C79KdvcD.js +1 -0
- package/dist/web/assets/{xychartDiagram-2RQKCTM6-BN2_ducK.js → xychartDiagram-2RQKCTM6-B3gcBChQ.js} +1 -1
- package/dist/web/assets/yaml-C1WLpuVe.js +1 -0
- package/dist/web/index.html +2 -2
- package/node_modules/@agent-tower/shared/dist/index.d.ts +2 -0
- package/node_modules/@agent-tower/shared/dist/index.d.ts.map +1 -1
- package/node_modules/@agent-tower/shared/dist/index.js +2 -0
- package/node_modules/@agent-tower/shared/dist/index.js.map +1 -1
- package/node_modules/@agent-tower/shared/dist/task-handoff.d.ts +12 -0
- package/node_modules/@agent-tower/shared/dist/task-handoff.d.ts.map +1 -0
- package/node_modules/@agent-tower/shared/dist/task-handoff.js +2 -0
- package/node_modules/@agent-tower/shared/dist/task-handoff.js.map +1 -0
- package/node_modules/@agent-tower/shared/dist/task-hierarchy.d.ts +17 -0
- package/node_modules/@agent-tower/shared/dist/task-hierarchy.d.ts.map +1 -0
- package/node_modules/@agent-tower/shared/dist/task-hierarchy.js +12 -0
- package/node_modules/@agent-tower/shared/dist/task-hierarchy.js.map +1 -0
- package/node_modules/@agent-tower/shared/dist/types.d.ts +22 -1
- package/node_modules/@agent-tower/shared/dist/types.d.ts.map +1 -1
- package/node_modules/@agent-tower/shared/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/prisma/migrations/20261023010000_add_subtasks/migration.sql +2 -0
- package/prisma/migrations/20261026000000_add_task_handoff/migration.sql +1 -0
- package/prisma/migrations/20261027000000_preserve_workspace_history/migration.sql +2 -0
- package/prisma/schema.prisma +7 -0
- package/dist/web/assets/AgentDemoPage-Dwux6TyV.js +0 -1
- package/dist/web/assets/AttachmentPreview-CFJ6MZ1f.js +0 -2
- package/dist/web/assets/BrandLogo-H4nCbVzs.js +0 -1
- package/dist/web/assets/ConversationPage-CZzGME21.js +0 -1
- package/dist/web/assets/CreateTaskInput-BM2tx4hJ.js +0 -1
- package/dist/web/assets/EditableTaskTitle-BEsiULnD.js +0 -70
- package/dist/web/assets/MobileTaskDetail-IOQ1WnS8.js +0 -3
- package/dist/web/assets/ProjectKanbanPage-DMtv15rq.js +0 -12
- package/dist/web/assets/TaskDetail-DzKbs5Jt.js +0 -1
- package/dist/web/assets/TeamSettingsPage-fjlaqaLo.js +0 -1
- package/dist/web/assets/channel-D1cEj22-.js +0 -1
- package/dist/web/assets/check-D_VFGpIy.js +0 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-DIrDMefa.js +0 -1
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-DIrDMefa.js +0 -1
- package/dist/web/assets/confirm-dialog-CL_1pF4K.js +0 -1
- package/dist/web/assets/cssMode-CXBMyfYY.js +0 -1
- package/dist/web/assets/handlebars-Ci38FPsA.js +0 -1
- package/dist/web/assets/html-5hdYEgVF.js +0 -1
- package/dist/web/assets/htmlMode-BzU9qsw0.js +0 -1
- package/dist/web/assets/icon-button-BmrJtYFC.js +0 -1
- package/dist/web/assets/index-BR3Wg2fS.js +0 -122
- package/dist/web/assets/index-DSy5JLC1.js +0 -1
- package/dist/web/assets/index-DZLg4-xM.css +0 -1
- package/dist/web/assets/javascript-Ib060GQ8.js +0 -1
- package/dist/web/assets/jsonMode-CLmu6gzc.js +0 -7
- package/dist/web/assets/liquid-Bc7OSAPR.js +0 -1
- package/dist/web/assets/mdx-CxJNHHTn.js +0 -1
- package/dist/web/assets/modal-D496f1fE.js +0 -1
- package/dist/web/assets/python-C0E43gUo.js +0 -1
- package/dist/web/assets/razor-xarhYR9V.js +0 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-BxmbGAhh.js +0 -1
- package/dist/web/assets/tooltip-C8--8CNX.js +0 -1
- package/dist/web/assets/tsMode-uT3sMVHt.js +0 -11
- package/dist/web/assets/typescript-Dkdj2ks0.js +0 -1
- package/dist/web/assets/use-profiles-T3saKiBg.js +0 -1
- package/dist/web/assets/useTokenUsage-Drh3v3kx.js +0 -1
- package/dist/web/assets/xml-BO8gYu0L.js +0 -1
- package/dist/web/assets/yaml-DlovbQzw.js +0 -1
- /package/dist/web/assets/{EditableTaskTitle-DcpNTP1B.css → TaskHandoffPanel-DcpNTP1B.css} +0 -0
|
@@ -131,9 +131,11 @@ export declare class WorkspaceService {
|
|
|
131
131
|
updatedAt: Date;
|
|
132
132
|
title: string;
|
|
133
133
|
deletedAt: Date | null;
|
|
134
|
+
handoff: string | null;
|
|
134
135
|
baseBranch: string | null;
|
|
135
136
|
position: number;
|
|
136
137
|
projectId: string;
|
|
138
|
+
parentTaskId: string | null;
|
|
137
139
|
};
|
|
138
140
|
sessions: {
|
|
139
141
|
agentType: string;
|
|
@@ -166,6 +168,7 @@ export declare class WorkspaceService {
|
|
|
166
168
|
commitMessage: string | null;
|
|
167
169
|
previewTarget: string | null;
|
|
168
170
|
hibernatedAt: Date | null;
|
|
171
|
+
cleanedAt: Date | null;
|
|
169
172
|
}) | null>;
|
|
170
173
|
/**
|
|
171
174
|
* 获取 Task 下所有 Workspace
|
|
@@ -202,6 +205,7 @@ export declare class WorkspaceService {
|
|
|
202
205
|
commitMessage: string | null;
|
|
203
206
|
previewTarget: string | null;
|
|
204
207
|
hibernatedAt: Date | null;
|
|
208
|
+
cleanedAt: Date | null;
|
|
205
209
|
})[]>;
|
|
206
210
|
getSetupProgress(taskId: string): Promise<WorkspaceSetupProgressPayload[]>;
|
|
207
211
|
listVerdicts(workspaceId: string): Promise<WorkspaceVerdict[]>;
|
|
@@ -261,9 +265,11 @@ export declare class WorkspaceService {
|
|
|
261
265
|
updatedAt: Date;
|
|
262
266
|
title: string;
|
|
263
267
|
deletedAt: Date | null;
|
|
268
|
+
handoff: string | null;
|
|
264
269
|
baseBranch: string | null;
|
|
265
270
|
position: number;
|
|
266
271
|
projectId: string;
|
|
272
|
+
parentTaskId: string | null;
|
|
267
273
|
};
|
|
268
274
|
sessions: {
|
|
269
275
|
agentType: string;
|
|
@@ -296,6 +302,7 @@ export declare class WorkspaceService {
|
|
|
296
302
|
commitMessage: string | null;
|
|
297
303
|
previewTarget: string | null;
|
|
298
304
|
hibernatedAt: Date | null;
|
|
305
|
+
cleanedAt: Date | null;
|
|
299
306
|
}>;
|
|
300
307
|
getOrCreateDedicatedWorkspace(teamRunId: string, memberId: string): Promise<{
|
|
301
308
|
task: {
|
|
@@ -327,9 +334,11 @@ export declare class WorkspaceService {
|
|
|
327
334
|
updatedAt: Date;
|
|
328
335
|
title: string;
|
|
329
336
|
deletedAt: Date | null;
|
|
337
|
+
handoff: string | null;
|
|
330
338
|
baseBranch: string | null;
|
|
331
339
|
position: number;
|
|
332
340
|
projectId: string;
|
|
341
|
+
parentTaskId: string | null;
|
|
333
342
|
};
|
|
334
343
|
sessions: {
|
|
335
344
|
agentType: string;
|
|
@@ -362,6 +371,7 @@ export declare class WorkspaceService {
|
|
|
362
371
|
commitMessage: string | null;
|
|
363
372
|
previewTarget: string | null;
|
|
364
373
|
hibernatedAt: Date | null;
|
|
374
|
+
cleanedAt: Date | null;
|
|
365
375
|
}>;
|
|
366
376
|
private findOrCreateMainWorkspace;
|
|
367
377
|
private findOrCreateDedicatedWorkspace;
|
|
@@ -373,12 +383,8 @@ export declare class WorkspaceService {
|
|
|
373
383
|
private ensureActiveWorkspaceWorktree;
|
|
374
384
|
private restoreInactiveWorkspace;
|
|
375
385
|
/**
|
|
376
|
-
*
|
|
377
|
-
*
|
|
378
|
-
* - 删除前检查是否有 RUNNING 状态的 Session,有则拒绝删除
|
|
379
|
-
* - 删除时先停止所有关联 Session 的进程
|
|
380
|
-
* - 删除时调用 WorktreeManager.remove 清理 worktree
|
|
381
|
-
* - worktree 清理失败时仍然删除数据库记录(记录警告日志)
|
|
386
|
+
* 回收 Workspace 的运行资源,保留任务下的会话历史。
|
|
387
|
+
* 只有任务/项目硬删除才级联删除 Workspace 和 Session。
|
|
382
388
|
*/
|
|
383
389
|
delete(id: string): Promise<boolean>;
|
|
384
390
|
private deleteWithLifecycle;
|
|
@@ -446,9 +452,11 @@ export declare class WorkspaceService {
|
|
|
446
452
|
updatedAt: Date;
|
|
447
453
|
title: string;
|
|
448
454
|
deletedAt: Date | null;
|
|
455
|
+
handoff: string | null;
|
|
449
456
|
baseBranch: string | null;
|
|
450
457
|
position: number;
|
|
451
458
|
projectId: string;
|
|
459
|
+
parentTaskId: string | null;
|
|
452
460
|
};
|
|
453
461
|
sessions: {
|
|
454
462
|
agentType: string;
|
|
@@ -497,6 +505,7 @@ export declare class WorkspaceService {
|
|
|
497
505
|
commitMessage: string | null;
|
|
498
506
|
previewTarget: string | null;
|
|
499
507
|
hibernatedAt: Date | null;
|
|
508
|
+
cleanedAt: Date | null;
|
|
500
509
|
}>;
|
|
501
510
|
private archiveWithLifecycle;
|
|
502
511
|
/**
|
|
@@ -538,9 +547,11 @@ export declare class WorkspaceService {
|
|
|
538
547
|
updatedAt: Date;
|
|
539
548
|
title: string;
|
|
540
549
|
deletedAt: Date | null;
|
|
550
|
+
handoff: string | null;
|
|
541
551
|
baseBranch: string | null;
|
|
542
552
|
position: number;
|
|
543
553
|
projectId: string;
|
|
554
|
+
parentTaskId: string | null;
|
|
544
555
|
};
|
|
545
556
|
sessions: {
|
|
546
557
|
agentType: string;
|
|
@@ -573,6 +584,7 @@ export declare class WorkspaceService {
|
|
|
573
584
|
commitMessage: string | null;
|
|
574
585
|
previewTarget: string | null;
|
|
575
586
|
hibernatedAt: Date | null;
|
|
587
|
+
cleanedAt: Date | null;
|
|
576
588
|
}>;
|
|
577
589
|
private cleanupCreatedWorktree;
|
|
578
590
|
private cleanupRestoredWorktree;
|
|
@@ -591,11 +603,12 @@ export declare class WorkspaceService {
|
|
|
591
603
|
*/
|
|
592
604
|
private autoCommitIfDirty;
|
|
593
605
|
/**
|
|
594
|
-
*
|
|
606
|
+
* 回收已完成任务的 ABANDONED/MERGED Workspace 资源,保留会话历史。
|
|
595
607
|
*
|
|
596
608
|
* @returns 被清理的 Workspace 数量
|
|
597
609
|
*/
|
|
598
610
|
cleanup(): Promise<number>;
|
|
611
|
+
private cleanupWorkspaceBranch;
|
|
599
612
|
private assertWorktreeWorkspace;
|
|
600
613
|
/**
|
|
601
614
|
* 复制项目配置的文件到 worktree
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace.service.d.ts","sourceRoot":"","sources":["../../src/services/workspace.service.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"workspace.service.d.ts","sourceRoot":"","sources":["../../src/services/workspace.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1013,6 +1013,7 @@ export class WorkspaceService {
|
|
|
1013
1013
|
ownerMemberId: options.ownerMemberId,
|
|
1014
1014
|
workspaceKind: WorkspaceKind.WORKTREE,
|
|
1015
1015
|
status: { in: [WorkspaceStatus.MERGED, WorkspaceStatus.HIBERNATED] },
|
|
1016
|
+
cleanedAt: null,
|
|
1016
1017
|
},
|
|
1017
1018
|
orderBy: { updatedAt: 'desc' },
|
|
1018
1019
|
});
|
|
@@ -1344,7 +1345,26 @@ export class WorkspaceService {
|
|
|
1344
1345
|
if (workspace.status === WorkspaceStatus.HIBERNATED) {
|
|
1345
1346
|
return this.restoreInactiveWorkspace(workspace);
|
|
1346
1347
|
}
|
|
1347
|
-
if (workspace.status === WorkspaceStatus.MERGED
|
|
1348
|
+
if (workspace.status === WorkspaceStatus.MERGED
|
|
1349
|
+
|| (workspace.status === WorkspaceStatus.ABANDONED && workspace.cleanedAt)) {
|
|
1350
|
+
if (workspace.cleanedAt) {
|
|
1351
|
+
return defaultWorkspaceLifecycleBarrier.withWorkspaces([workspace.id, mainWorkspace.id], async () => {
|
|
1352
|
+
const current = await prisma.workspace.findUnique({
|
|
1353
|
+
where: { id: workspace.id }, include: { task: { include: { project: true } } },
|
|
1354
|
+
});
|
|
1355
|
+
if (!current)
|
|
1356
|
+
throw new NotFoundError('Workspace', workspace.id);
|
|
1357
|
+
ensureTaskNotDeleted(current.task);
|
|
1358
|
+
const activeMain = await prisma.workspace.findFirst({
|
|
1359
|
+
where: { id: mainWorkspace.id, status: WorkspaceStatus.ACTIVE, cleanedAt: null, task: { deletedAt: null } },
|
|
1360
|
+
});
|
|
1361
|
+
if (!activeMain)
|
|
1362
|
+
throw new ServiceError('TeamRun main workspace is no longer active', 'WORKSPACE_NOT_ACTIVE', 409);
|
|
1363
|
+
if (!current.cleanedAt)
|
|
1364
|
+
return this.activateDedicatedWorkspace(current, mainWorkspace);
|
|
1365
|
+
return this.resetMergedDedicatedWorkspace(current, mainWorkspace);
|
|
1366
|
+
});
|
|
1367
|
+
}
|
|
1348
1368
|
return this.resetMergedDedicatedWorkspace(workspace, mainWorkspace);
|
|
1349
1369
|
}
|
|
1350
1370
|
throw new ServiceError(`Cannot reuse dedicated workspace in ${workspace.status} status`, 'DEDICATED_WORKSPACE_UNAVAILABLE', 409);
|
|
@@ -1353,41 +1373,61 @@ export class WorkspaceService {
|
|
|
1353
1373
|
this.assertWorktreeWorkspace(workspace);
|
|
1354
1374
|
this.assertWorktreeWorkspace(mainWorkspace);
|
|
1355
1375
|
const worktreeManager = new WorktreeManager(workspace.task.project.repoPath);
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1376
|
+
// The retained record still occupies the member's unique workspace slot.
|
|
1377
|
+
// Rebuild its resources with a fresh branch; the previous name is no longer owned.
|
|
1378
|
+
const branchName = workspace.cleanedAt ? `${workspace.branchName}-${randomUUID().slice(0, 8)}` : workspace.branchName;
|
|
1379
|
+
const worktreePath = workspace.cleanedAt
|
|
1380
|
+
? await worktreeManager.create(branchName, mainWorkspace.branchName)
|
|
1381
|
+
: await worktreeManager.ensureWorktreeExists(branchName);
|
|
1382
|
+
let resourcesBound = false;
|
|
1383
|
+
try {
|
|
1384
|
+
if (!(await worktreeManager.isWorktreeClean(worktreePath))) {
|
|
1385
|
+
throw new ServiceError(`Cannot start new work from merged workspace ${workspace.id} because it has uncommitted changes`, 'MERGED_WORKSPACE_DIRTY', 409);
|
|
1386
|
+
}
|
|
1387
|
+
const mainHead = (await execGit(mainWorkspace.worktreePath, ['rev-parse', 'HEAD'])).trim();
|
|
1388
|
+
await execGit(worktreePath, ['reset', '--hard', mainHead]);
|
|
1389
|
+
const actualHead = (await execGit(worktreePath, ['rev-parse', 'HEAD'])).trim();
|
|
1390
|
+
if (!mainHead || actualHead !== mainHead || !(await worktreeManager.isWorktreeClean(worktreePath))) {
|
|
1391
|
+
throw new ServiceError(`Merged workspace ${workspace.id} could not be aligned to the TeamRun main workspace`, 'MERGED_WORKSPACE_RESET_FAILED', 500);
|
|
1392
|
+
}
|
|
1393
|
+
const updateResult = await prisma.workspace.updateMany({
|
|
1394
|
+
where: {
|
|
1395
|
+
id: workspace.id,
|
|
1396
|
+
status: workspace.status,
|
|
1397
|
+
cleanedAt: workspace.cleanedAt,
|
|
1398
|
+
task: { deletedAt: null },
|
|
1399
|
+
},
|
|
1400
|
+
data: {
|
|
1401
|
+
status: WorkspaceStatus.ACTIVE,
|
|
1402
|
+
branchName,
|
|
1403
|
+
baseBranch: mainWorkspace.branchName,
|
|
1404
|
+
worktreePath,
|
|
1405
|
+
workingDir: worktreePath,
|
|
1406
|
+
hibernatedAt: null,
|
|
1407
|
+
commitMessage: null,
|
|
1408
|
+
cleanedAt: null,
|
|
1409
|
+
},
|
|
1410
|
+
});
|
|
1411
|
+
if (updateResult.count !== 1) {
|
|
1412
|
+
throw new ServiceError(`Merged workspace ${workspace.id} changed state while starting new work`, 'MERGED_WORKSPACE_STATE_CHANGED', 409);
|
|
1413
|
+
}
|
|
1414
|
+
resourcesBound = true;
|
|
1415
|
+
this.runCopyFiles(workspace.task.project.repoPath, worktreePath, workspace.task.project.copyFiles);
|
|
1416
|
+
this.fireSetupScript(workspace.id, workspace.taskId, worktreePath, workspace.task.project.setupScript);
|
|
1417
|
+
const activated = await prisma.workspace.findUniqueOrThrow({
|
|
1418
|
+
where: { id: workspace.id },
|
|
1419
|
+
include: { sessions: visibleSessionsFilter, task: { include: { project: true } } },
|
|
1420
|
+
});
|
|
1421
|
+
return activated;
|
|
1365
1422
|
}
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
}
|
|
1372
|
-
|
|
1373
|
-
status: WorkspaceStatus.ACTIVE,
|
|
1374
|
-
baseBranch: mainWorkspace.branchName,
|
|
1375
|
-
worktreePath,
|
|
1376
|
-
workingDir: worktreePath,
|
|
1377
|
-
hibernatedAt: null,
|
|
1378
|
-
commitMessage: null,
|
|
1379
|
-
},
|
|
1380
|
-
});
|
|
1381
|
-
if (updateResult.count !== 1) {
|
|
1382
|
-
throw new ServiceError(`Merged workspace ${workspace.id} changed state while starting new work`, 'MERGED_WORKSPACE_STATE_CHANGED', 409);
|
|
1423
|
+
catch (error) {
|
|
1424
|
+
if (workspace.cleanedAt && !resourcesBound) {
|
|
1425
|
+
await this.cleanupCreatedWorktree(worktreeManager, worktreePath, branchName, [
|
|
1426
|
+
workspace.task.project.mainBranch, mainWorkspace.branchName,
|
|
1427
|
+
]);
|
|
1428
|
+
}
|
|
1429
|
+
throw error;
|
|
1383
1430
|
}
|
|
1384
|
-
this.runCopyFiles(workspace.task.project.repoPath, worktreePath, workspace.task.project.copyFiles);
|
|
1385
|
-
this.fireSetupScript(workspace.id, workspace.taskId, worktreePath, workspace.task.project.setupScript);
|
|
1386
|
-
const activated = await prisma.workspace.findUniqueOrThrow({
|
|
1387
|
-
where: { id: workspace.id },
|
|
1388
|
-
include: { sessions: visibleSessionsFilter, task: { include: { project: true } } },
|
|
1389
|
-
});
|
|
1390
|
-
return activated;
|
|
1391
1431
|
}
|
|
1392
1432
|
async waitForWorkspaceReady(workspace) {
|
|
1393
1433
|
if (workspace.branchName) {
|
|
@@ -1457,12 +1497,8 @@ export class WorkspaceService {
|
|
|
1457
1497
|
}
|
|
1458
1498
|
// ── Delete ───────────────────────────────────────────────────────────────────
|
|
1459
1499
|
/**
|
|
1460
|
-
*
|
|
1461
|
-
*
|
|
1462
|
-
* - 删除前检查是否有 RUNNING 状态的 Session,有则拒绝删除
|
|
1463
|
-
* - 删除时先停止所有关联 Session 的进程
|
|
1464
|
-
* - 删除时调用 WorktreeManager.remove 清理 worktree
|
|
1465
|
-
* - worktree 清理失败时仍然删除数据库记录(记录警告日志)
|
|
1500
|
+
* 回收 Workspace 的运行资源,保留任务下的会话历史。
|
|
1501
|
+
* 只有任务/项目硬删除才级联删除 Workspace 和 Session。
|
|
1466
1502
|
*/
|
|
1467
1503
|
async delete(id) {
|
|
1468
1504
|
return withSessionResourceCleanup({ workspaceId: id }, () => (defaultWorkspaceLifecycleBarrier.withWorkspace(id, () => this.deleteWithLifecycle(id))));
|
|
@@ -1479,25 +1515,44 @@ export class WorkspaceService {
|
|
|
1479
1515
|
throw new NotFoundError('Workspace', id);
|
|
1480
1516
|
}
|
|
1481
1517
|
ensureProjectIsMutable(workspace.task.project, 'delete workspaces');
|
|
1518
|
+
ensureTaskNotDeleted(workspace.task);
|
|
1519
|
+
if (workspace.cleanedAt)
|
|
1520
|
+
return true;
|
|
1482
1521
|
// A completed ACP turn may still own a reusable adapter process.
|
|
1483
1522
|
for (const session of workspace.sessions) {
|
|
1484
1523
|
await stopSessionForResourceCleanup(this.sessionService, session.id);
|
|
1485
1524
|
}
|
|
1486
1525
|
await this.backgroundService.stopAllForWorkspace(id);
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
catch (err) {
|
|
1494
|
-
// worktree 清理失败时记录警告但不阻断删除
|
|
1495
|
-
console.warn(`[WorkspaceService] Failed to remove worktree for workspace ${id}: ${err instanceof Error ? err.message : err}`);
|
|
1526
|
+
const worktreeManager = isWorktreeWorkspace(workspace)
|
|
1527
|
+
? new WorktreeManager(workspace.task.project.repoPath) : null;
|
|
1528
|
+
if (worktreeManager && workspace.worktreePath) {
|
|
1529
|
+
const result = await worktreeManager.remove(workspace.worktreePath);
|
|
1530
|
+
if (result.status === 'unregistered') {
|
|
1531
|
+
throw new ServiceError('Workspace directory could not be safely removed', 'WORKSPACE_CLEANUP_PENDING', 409);
|
|
1496
1532
|
}
|
|
1497
1533
|
}
|
|
1498
|
-
// 删除数据库记录(级联删除 sessions/services)
|
|
1499
1534
|
await this.backgroundService.releaseLogsForWorkspace?.(id);
|
|
1500
|
-
await prisma.workspace.
|
|
1535
|
+
await prisma.workspace.update({
|
|
1536
|
+
where: { id },
|
|
1537
|
+
data: {
|
|
1538
|
+
status: workspace.status === WorkspaceStatus.MERGED ? WorkspaceStatus.MERGED : WorkspaceStatus.ABANDONED,
|
|
1539
|
+
worktreePath: '',
|
|
1540
|
+
workingDir: '',
|
|
1541
|
+
previewTarget: null,
|
|
1542
|
+
hibernatedAt: null,
|
|
1543
|
+
},
|
|
1544
|
+
});
|
|
1545
|
+
try {
|
|
1546
|
+
// Preserve branch ownership for retry if another task still needs it.
|
|
1547
|
+
if (!worktreeManager || await this.cleanupWorkspaceBranch(workspace, worktreeManager)) {
|
|
1548
|
+
await prisma.workspace.update({ where: { id }, data: { cleanedAt: new Date() } });
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
finally {
|
|
1552
|
+
this.eventBus.emit('task:updated', {
|
|
1553
|
+
taskId: workspace.taskId, projectId: workspace.task.projectId, status: workspace.task.status,
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1501
1556
|
return true;
|
|
1502
1557
|
}
|
|
1503
1558
|
// ── Diff ─────────────────────────────────────────────────────────────────────
|
|
@@ -1597,7 +1652,18 @@ export class WorkspaceService {
|
|
|
1597
1652
|
await worktreeManager.abortOperation(workspace.worktreePath);
|
|
1598
1653
|
}
|
|
1599
1654
|
async merge(id, commitMessageOrOptions) {
|
|
1600
|
-
|
|
1655
|
+
const source = await prisma.workspace.findUnique({ where: { id }, include: { task: true } });
|
|
1656
|
+
if (!source || source.task.deletedAt)
|
|
1657
|
+
throw new NotFoundError('Workspace', id);
|
|
1658
|
+
const target = source.parentWorkspaceId || !source.baseBranch ? null : await prisma.workspace.findFirst({
|
|
1659
|
+
where: {
|
|
1660
|
+
id: { not: id }, branchName: source.baseBranch, status: WorkspaceStatus.ACTIVE,
|
|
1661
|
+
parentWorkspaceId: null, workspaceKind: WorkspaceKind.WORKTREE,
|
|
1662
|
+
task: { projectId: source.task.projectId, deletedAt: null },
|
|
1663
|
+
},
|
|
1664
|
+
include: { task: { include: { project: true } } },
|
|
1665
|
+
});
|
|
1666
|
+
return defaultWorkspaceLifecycleBarrier.withWorkspaces([id, ...(target ? [target.id] : [])], async () => {
|
|
1601
1667
|
const options = typeof commitMessageOrOptions === 'string'
|
|
1602
1668
|
? { commitMessage: commitMessageOrOptions }
|
|
1603
1669
|
: (commitMessageOrOptions ?? {});
|
|
@@ -1605,18 +1671,32 @@ export class WorkspaceService {
|
|
|
1605
1671
|
where: { id },
|
|
1606
1672
|
include: { task: { include: { project: true, teamRun: true } } },
|
|
1607
1673
|
});
|
|
1608
|
-
if (!workspace) {
|
|
1674
|
+
if (!workspace || workspace.task.deletedAt) {
|
|
1609
1675
|
throw new NotFoundError('Workspace', id);
|
|
1610
1676
|
}
|
|
1677
|
+
if (workspace.baseBranch !== source.baseBranch) {
|
|
1678
|
+
throw new ServiceError('Merge target changed. Refresh before merging.', 'MERGE_TARGET_CHANGED', 409);
|
|
1679
|
+
}
|
|
1680
|
+
const currentTarget = target ? await prisma.workspace.findUnique({
|
|
1681
|
+
where: { id: target.id }, include: { task: { include: { project: true } } },
|
|
1682
|
+
}) : null;
|
|
1683
|
+
if (target && (!currentTarget || currentTarget.task.deletedAt || currentTarget.status !== WorkspaceStatus.ACTIVE
|
|
1684
|
+
|| currentTarget.branchName !== workspace.baseBranch)) {
|
|
1685
|
+
throw new ServiceError('Merge target changed. Refresh before merging.', 'MERGE_TARGET_CHANGED', 409);
|
|
1686
|
+
}
|
|
1687
|
+
if (currentTarget) {
|
|
1688
|
+
await this.assertNoActiveWriteSessions(currentTarget.id);
|
|
1689
|
+
await this.assertNoActiveBackgroundServices(currentTarget.id);
|
|
1690
|
+
}
|
|
1611
1691
|
ensureProjectIsMutable(workspace.task.project, 'merge workspaces');
|
|
1612
1692
|
this.assertWorktreeWorkspace(workspace);
|
|
1613
1693
|
if (!options.stopActiveServices) {
|
|
1614
1694
|
await this.assertNoActiveBackgroundServices(workspace.id);
|
|
1615
1695
|
}
|
|
1616
|
-
return this.withMergeTargetLock(this.getMergeLockTarget(workspace), options.lockOwnerId, () => this.mergeWithLock(workspace, options));
|
|
1696
|
+
return this.withMergeTargetLock(currentTarget ? this.getParentWorkspaceMergeLockTarget(currentTarget.id) : this.getMergeLockTarget(workspace), options.lockOwnerId, () => this.mergeWithLock(workspace, options, currentTarget));
|
|
1617
1697
|
});
|
|
1618
1698
|
}
|
|
1619
|
-
async mergeWithLock(workspace, options) {
|
|
1699
|
+
async mergeWithLock(workspace, options, targetWorkspace = null) {
|
|
1620
1700
|
if (this.isTeamRunDedicatedChildWorkspace(workspace) && workspace.status === WorkspaceStatus.MERGED) {
|
|
1621
1701
|
if (!workspace.worktreePath) {
|
|
1622
1702
|
return '';
|
|
@@ -1645,7 +1725,7 @@ export class WorkspaceService {
|
|
|
1645
1725
|
if (parentWorkspace) {
|
|
1646
1726
|
return this.mergeChildIntoParent(workspace, parentWorkspace, options.commitMessage);
|
|
1647
1727
|
}
|
|
1648
|
-
return this.mergeRootWorkspaceToMain(workspace, options.commitMessage);
|
|
1728
|
+
return this.mergeRootWorkspaceToMain(workspace, options.commitMessage, targetWorkspace);
|
|
1649
1729
|
}
|
|
1650
1730
|
isTeamRunDedicatedChildWorkspace(workspace) {
|
|
1651
1731
|
return Boolean(workspace.task.teamRun
|
|
@@ -1774,17 +1854,22 @@ export class WorkspaceService {
|
|
|
1774
1854
|
});
|
|
1775
1855
|
return sha;
|
|
1776
1856
|
}
|
|
1777
|
-
async mergeRootWorkspaceToMain(workspace, commitMessage) {
|
|
1857
|
+
async mergeRootWorkspaceToMain(workspace, commitMessage, targetWorkspace = null) {
|
|
1778
1858
|
this.assertWorktreeWorkspace(workspace);
|
|
1779
1859
|
const worktreeManager = new WorktreeManager(workspace.task.project.repoPath);
|
|
1780
1860
|
let sha;
|
|
1781
1861
|
const targetBranch = this.getBaseBranch(workspace);
|
|
1782
1862
|
try {
|
|
1783
|
-
({ sha } = await worktreeManager.merge(workspace.worktreePath, targetBranch, { commitMessage: commitMessage || workspace.commitMessage || undefined
|
|
1863
|
+
({ sha } = await worktreeManager.merge(workspace.worktreePath, targetBranch, { commitMessage: commitMessage || workspace.commitMessage || undefined,
|
|
1864
|
+
...(targetWorkspace ? { targetWorktreePath: targetWorkspace.worktreePath }
|
|
1865
|
+
: workspace.task.parentTaskId ? { restoreOriginalBranch: true } : {}),
|
|
1866
|
+
}));
|
|
1784
1867
|
}
|
|
1785
1868
|
catch (error) {
|
|
1786
1869
|
if (error instanceof MergeConflictError) {
|
|
1787
1870
|
error.sourceWorkspaceId = workspace.id;
|
|
1871
|
+
if (targetWorkspace)
|
|
1872
|
+
error.targetWorkspaceId = targetWorkspace.id;
|
|
1788
1873
|
error.sourceWorktreePath ??= workspace.worktreePath;
|
|
1789
1874
|
error.sourceBranch ??= workspace.branchName;
|
|
1790
1875
|
error.targetBranch ??= targetBranch;
|
|
@@ -2124,7 +2209,7 @@ export class WorkspaceService {
|
|
|
2124
2209
|
}
|
|
2125
2210
|
// ── Cleanup ──────────────────────────────────────────────────────────────────
|
|
2126
2211
|
/**
|
|
2127
|
-
*
|
|
2212
|
+
* 回收已完成任务的 ABANDONED/MERGED Workspace 资源,保留会话历史。
|
|
2128
2213
|
*
|
|
2129
2214
|
* @returns 被清理的 Workspace 数量
|
|
2130
2215
|
*/
|
|
@@ -2132,56 +2217,86 @@ export class WorkspaceService {
|
|
|
2132
2217
|
const workspaces = await prisma.workspace.findMany({
|
|
2133
2218
|
where: {
|
|
2134
2219
|
status: { in: [WorkspaceStatus.ABANDONED, WorkspaceStatus.MERGED] },
|
|
2135
|
-
|
|
2220
|
+
cleanedAt: null,
|
|
2221
|
+
task: { status: TaskStatus.DONE, deletedAt: null },
|
|
2136
2222
|
},
|
|
2137
|
-
|
|
2223
|
+
select: { id: true },
|
|
2138
2224
|
});
|
|
2139
2225
|
let cleaned = 0;
|
|
2140
|
-
for (const
|
|
2226
|
+
for (const candidate of workspaces) {
|
|
2141
2227
|
try {
|
|
2142
|
-
await withSessionResourceCleanup({ workspaceId:
|
|
2228
|
+
await withSessionResourceCleanup({ workspaceId: candidate.id }, () => (defaultWorkspaceLifecycleBarrier.withWorkspace(candidate.id, async () => {
|
|
2229
|
+
// Recheck after acquiring the lifecycle lock: another cleanup or
|
|
2230
|
+
// reactivation may have already consumed this candidate.
|
|
2231
|
+
const workspace = await prisma.workspace.findFirst({
|
|
2232
|
+
where: {
|
|
2233
|
+
id: candidate.id, cleanedAt: null,
|
|
2234
|
+
status: { in: [WorkspaceStatus.ABANDONED, WorkspaceStatus.MERGED] },
|
|
2235
|
+
task: { status: TaskStatus.DONE, deletedAt: null },
|
|
2236
|
+
},
|
|
2237
|
+
include: { task: { include: { project: true } } },
|
|
2238
|
+
});
|
|
2239
|
+
if (!workspace)
|
|
2240
|
+
return;
|
|
2143
2241
|
const sessions = await prisma.session.findMany({ where: { workspaceId: workspace.id }, select: { id: true } });
|
|
2144
2242
|
for (const session of sessions) {
|
|
2145
2243
|
await stopSessionForResourceCleanup(this.sessionService, session.id);
|
|
2146
2244
|
}
|
|
2147
2245
|
await this.backgroundService.stopAllForWorkspace(workspace.id);
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
await prisma.workspace.delete({ where: { id: workspace.id } });
|
|
2151
|
-
cleaned++;
|
|
2152
|
-
return;
|
|
2153
|
-
}
|
|
2154
|
-
const worktreeManager = new WorktreeManager(workspace.task.project.repoPath);
|
|
2246
|
+
const worktreeManager = isWorktreeWorkspace(workspace)
|
|
2247
|
+
? new WorktreeManager(workspace.task.project.repoPath) : null;
|
|
2155
2248
|
// 清理残留 worktree(如果还存在)
|
|
2156
|
-
if (workspace.worktreePath) {
|
|
2249
|
+
if (worktreeManager && workspace.worktreePath) {
|
|
2157
2250
|
const removeResult = await worktreeManager.remove(workspace.worktreePath);
|
|
2158
2251
|
if (removeResult.status === 'unregistered') {
|
|
2159
2252
|
console.warn(`[WorkspaceService] cleanup: workspace ${workspace.id} path is unregistered or unsafe to remove: ${removeResult.path}`);
|
|
2160
2253
|
return;
|
|
2161
2254
|
}
|
|
2162
2255
|
}
|
|
2163
|
-
//
|
|
2164
|
-
|
|
2165
|
-
|
|
2256
|
+
// Clear live paths even when branch reclamation needs a later retry.
|
|
2257
|
+
// MAIN_DIRECTORY releases its binding without removing project files.
|
|
2258
|
+
await this.backgroundService.releaseLogsForWorkspace?.(workspace.id);
|
|
2259
|
+
await prisma.workspace.update({
|
|
2260
|
+
where: { id: workspace.id },
|
|
2261
|
+
data: { worktreePath: '', workingDir: '', previewTarget: null },
|
|
2166
2262
|
});
|
|
2167
|
-
|
|
2168
|
-
|
|
2263
|
+
const cleanupComplete = !worktreeManager || await this.cleanupWorkspaceBranch(workspace, worktreeManager);
|
|
2264
|
+
if (cleanupComplete) {
|
|
2265
|
+
await prisma.workspace.update({ where: { id: workspace.id }, data: { cleanedAt: new Date() } });
|
|
2169
2266
|
}
|
|
2170
|
-
|
|
2171
|
-
|
|
2267
|
+
if (cleanupComplete || getWorkspaceWorkingDir(workspace)) {
|
|
2268
|
+
cleaned++;
|
|
2269
|
+
this.eventBus.emit('task:updated', {
|
|
2270
|
+
taskId: workspace.taskId, projectId: workspace.task.projectId, status: workspace.task.status,
|
|
2271
|
+
});
|
|
2172
2272
|
}
|
|
2173
|
-
await this.backgroundService.releaseLogsForWorkspace?.(workspace.id);
|
|
2174
|
-
await prisma.workspace.delete({ where: { id: workspace.id } });
|
|
2175
|
-
cleaned++;
|
|
2176
2273
|
})));
|
|
2177
2274
|
}
|
|
2178
2275
|
catch (err) {
|
|
2179
2276
|
// Keep process evidence and directory resources for a later retry.
|
|
2180
|
-
console.warn(`[WorkspaceService] cleanup: failed for workspace ${
|
|
2277
|
+
console.warn(`[WorkspaceService] cleanup: failed for workspace ${candidate.id}: ${err instanceof Error ? err.message : err}`);
|
|
2181
2278
|
}
|
|
2182
2279
|
}
|
|
2183
2280
|
return cleaned;
|
|
2184
2281
|
}
|
|
2282
|
+
async cleanupWorkspaceBranch(workspace, worktreeManager) {
|
|
2283
|
+
const referencedByTask = await prisma.task.findFirst({
|
|
2284
|
+
where: { projectId: workspace.task.projectId, id: { not: workspace.taskId }, deletedAt: null, OR: [
|
|
2285
|
+
{ baseBranch: workspace.branchName },
|
|
2286
|
+
{ workspaces: { some: { baseBranch: workspace.branchName, cleanedAt: null } } },
|
|
2287
|
+
] }, select: { id: true },
|
|
2288
|
+
});
|
|
2289
|
+
if (referencedByTask)
|
|
2290
|
+
return false;
|
|
2291
|
+
const result = await worktreeManager.deleteBranchIfSafe(workspace.branchName, {
|
|
2292
|
+
protectedBranches: [workspace.task.project.mainBranch, workspace.baseBranch],
|
|
2293
|
+
});
|
|
2294
|
+
if (result.status === 'failed' || result.status === 'checked_out') {
|
|
2295
|
+
console.warn(`[WorkspaceService] cleanup: branch ${result.branchName} retained for workspace ${workspace.id}: ${result.reason}`);
|
|
2296
|
+
return false;
|
|
2297
|
+
}
|
|
2298
|
+
return true;
|
|
2299
|
+
}
|
|
2185
2300
|
// ── Startup Prune ────────────────────────────────────────────────────────────
|
|
2186
2301
|
assertWorktreeWorkspace(workspace) {
|
|
2187
2302
|
if (isWorktreeWorkspace(workspace))
|