agent-tower 0.7.4-beta.2 → 0.7.5-beta.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/app.d.ts.map +1 -1
- package/dist/app.js +6 -1
- package/dist/app.js.map +1 -1
- package/dist/core/container.d.ts +2 -0
- package/dist/core/container.d.ts.map +1 -1
- package/dist/core/container.js +25 -0
- package/dist/core/container.js.map +1 -1
- package/dist/executors/__tests__/base.executor.test.js +19 -0
- package/dist/executors/__tests__/base.executor.test.js.map +1 -1
- package/dist/executors/__tests__/claude-code-mcp.test.d.ts +2 -0
- package/dist/executors/__tests__/claude-code-mcp.test.d.ts.map +1 -0
- package/dist/executors/__tests__/claude-code-mcp.test.js +211 -0
- package/dist/executors/__tests__/claude-code-mcp.test.js.map +1 -0
- package/dist/executors/base.executor.d.ts.map +1 -1
- package/dist/executors/base.executor.js +13 -0
- package/dist/executors/base.executor.js.map +1 -1
- package/dist/executors/claude-code.executor.d.ts +1 -0
- package/dist/executors/claude-code.executor.d.ts.map +1 -1
- package/dist/executors/claude-code.executor.js +52 -3
- package/dist/executors/claude-code.executor.js.map +1 -1
- package/dist/git/worktree.manager.d.ts.map +1 -1
- package/dist/git/worktree.manager.js +5 -2
- package/dist/git/worktree.manager.js.map +1 -1
- package/dist/mcp/http-client.d.ts +8 -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__/workspace-services.test.js +34 -1
- package/dist/mcp/tools/__tests__/workspace-services.test.js.map +1 -1
- package/dist/mcp/tools/tasks.js +1 -1
- package/dist/mcp/tools/tasks.js.map +1 -1
- package/dist/mcp/tools/workspace-services.d.ts.map +1 -1
- package/dist/mcp/tools/workspace-services.js +39 -2
- package/dist/mcp/tools/workspace-services.js.map +1 -1
- package/dist/mcp/types.d.ts +20 -0
- package/dist/mcp/types.d.ts.map +1 -1
- package/dist/mcp/types.js +12 -0
- package/dist/mcp/types.js.map +1 -1
- package/dist/middleware/__tests__/preview-fallback.test.d.ts +2 -0
- package/dist/middleware/__tests__/preview-fallback.test.d.ts.map +1 -0
- package/dist/middleware/__tests__/preview-fallback.test.js +93 -0
- package/dist/middleware/__tests__/preview-fallback.test.js.map +1 -0
- package/dist/middleware/preview-fallback.d.ts +5 -0
- package/dist/middleware/preview-fallback.d.ts.map +1 -0
- package/dist/middleware/preview-fallback.js +91 -0
- package/dist/middleware/preview-fallback.js.map +1 -0
- package/dist/output/__tests__/claude-code-parser-continuation.test.d.ts +2 -0
- package/dist/output/__tests__/claude-code-parser-continuation.test.d.ts.map +1 -0
- package/dist/output/__tests__/claude-code-parser-continuation.test.js +89 -0
- package/dist/output/__tests__/claude-code-parser-continuation.test.js.map +1 -0
- package/dist/output/__tests__/claude-code-parser-lifecycle.test.js +4 -1
- package/dist/output/__tests__/claude-code-parser-lifecycle.test.js.map +1 -1
- package/dist/output/claude-code-parser.d.ts +36 -1
- package/dist/output/claude-code-parser.d.ts.map +1 -1
- package/dist/output/claude-code-parser.js +149 -18
- package/dist/output/claude-code-parser.js.map +1 -1
- package/dist/output/types.d.ts +2 -0
- package/dist/output/types.d.ts.map +1 -1
- package/dist/output/types.js.map +1 -1
- package/dist/prompts/workspace-background-service-policy.d.ts +6 -2
- package/dist/prompts/workspace-background-service-policy.d.ts.map +1 -1
- package/dist/prompts/workspace-background-service-policy.js +12 -3
- package/dist/prompts/workspace-background-service-policy.js.map +1 -1
- package/dist/prompts/workspace-background-service-policy.test.js +11 -0
- package/dist/prompts/workspace-background-service-policy.test.js.map +1 -1
- package/dist/routes/__tests__/previews.integration.test.js +117 -6
- package/dist/routes/__tests__/previews.integration.test.js.map +1 -1
- package/dist/routes/__tests__/previews.test.js +223 -194
- package/dist/routes/__tests__/previews.test.js.map +1 -1
- package/dist/routes/__tests__/task-handoff.test.js +25 -16
- package/dist/routes/__tests__/task-handoff.test.js.map +1 -1
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +3 -0
- package/dist/routes/index.js.map +1 -1
- package/dist/routes/previews.d.ts +11 -9
- package/dist/routes/previews.d.ts.map +1 -1
- package/dist/routes/previews.js +137 -516
- package/dist/routes/previews.js.map +1 -1
- package/dist/routes/session-wakeups.d.ts +7 -0
- package/dist/routes/session-wakeups.d.ts.map +1 -0
- package/dist/routes/session-wakeups.js +86 -0
- package/dist/routes/session-wakeups.js.map +1 -0
- package/dist/routes/tasks.d.ts.map +1 -1
- package/dist/routes/tasks.js +3 -1
- package/dist/routes/tasks.js.map +1 -1
- package/dist/runtime/__tests__/claude-cli-driver.test.js +96 -2
- package/dist/runtime/__tests__/claude-cli-driver.test.js.map +1 -1
- package/dist/runtime/__tests__/claude-run-lifecycle.test.d.ts +2 -0
- package/dist/runtime/__tests__/claude-run-lifecycle.test.d.ts.map +1 -0
- package/dist/runtime/__tests__/claude-run-lifecycle.test.js +88 -0
- package/dist/runtime/__tests__/claude-run-lifecycle.test.js.map +1 -0
- package/dist/runtime/__tests__/cli-driver-lifecycle.test.js +14 -7
- package/dist/runtime/__tests__/cli-driver-lifecycle.test.js.map +1 -1
- package/dist/runtime/claude-run-lifecycle.d.ts +77 -0
- package/dist/runtime/claude-run-lifecycle.d.ts.map +1 -0
- package/dist/runtime/claude-run-lifecycle.js +147 -0
- package/dist/runtime/claude-run-lifecycle.js.map +1 -0
- package/dist/runtime/cli-driver.d.ts.map +1 -1
- package/dist/runtime/cli-driver.js +89 -3
- package/dist/runtime/cli-driver.js.map +1 -1
- package/dist/runtime/contracts.d.ts +6 -1
- package/dist/runtime/contracts.d.ts.map +1 -1
- package/dist/runtime/process-scope/__tests__/process-scope.test.d.ts +2 -0
- package/dist/runtime/process-scope/__tests__/process-scope.test.d.ts.map +1 -0
- package/dist/runtime/process-scope/__tests__/process-scope.test.js +156 -0
- package/dist/runtime/process-scope/__tests__/process-scope.test.js.map +1 -0
- package/dist/runtime/process-scope/process-scope.d.ts +46 -0
- package/dist/runtime/process-scope/process-scope.d.ts.map +1 -0
- package/dist/runtime/process-scope/process-scope.js +68 -0
- package/dist/runtime/process-scope/process-scope.js.map +1 -0
- package/dist/runtime/process-scope/scope-helper.d.ts +28 -0
- package/dist/runtime/process-scope/scope-helper.d.ts.map +1 -0
- package/dist/runtime/process-scope/scope-helper.js +78 -0
- package/dist/runtime/process-scope/scope-helper.js.map +1 -0
- package/dist/runtime/runtime-coordinator.d.ts.map +1 -1
- package/dist/runtime/runtime-coordinator.js +6 -0
- package/dist/runtime/runtime-coordinator.js.map +1 -1
- package/dist/services/__tests__/preview-runtime-manager.test.js +13 -112
- package/dist/services/__tests__/preview-runtime-manager.test.js.map +1 -1
- package/dist/services/__tests__/preview.service.test.js +13 -14
- package/dist/services/__tests__/preview.service.test.js.map +1 -1
- package/dist/services/__tests__/session-manager.lifecycle.test.js +147 -1
- package/dist/services/__tests__/session-manager.lifecycle.test.js.map +1 -1
- package/dist/services/__tests__/session-wakeup.service.test.d.ts +2 -0
- package/dist/services/__tests__/session-wakeup.service.test.d.ts.map +1 -0
- package/dist/services/__tests__/session-wakeup.service.test.js +173 -0
- package/dist/services/__tests__/session-wakeup.service.test.js.map +1 -0
- package/dist/services/__tests__/terminal-manager.test.js +129 -51
- package/dist/services/__tests__/terminal-manager.test.js.map +1 -1
- package/dist/services/message-delivery.service.d.ts +3 -2
- package/dist/services/message-delivery.service.d.ts.map +1 -1
- package/dist/services/message-delivery.service.js +11 -7
- package/dist/services/message-delivery.service.js.map +1 -1
- package/dist/services/preview-bridge.d.ts +50 -0
- package/dist/services/preview-bridge.d.ts.map +1 -0
- package/dist/services/preview-bridge.js +537 -0
- package/dist/services/preview-bridge.js.map +1 -0
- package/dist/services/preview-cookies.d.ts +28 -0
- package/dist/services/preview-cookies.d.ts.map +1 -0
- package/dist/services/preview-cookies.js +133 -0
- package/dist/services/preview-cookies.js.map +1 -0
- package/dist/services/preview-proxy.d.ts +71 -0
- package/dist/services/preview-proxy.d.ts.map +1 -0
- package/dist/services/preview-proxy.js +462 -0
- package/dist/services/preview-proxy.js.map +1 -0
- package/dist/services/preview-runtime-manager.d.ts +11 -25
- package/dist/services/preview-runtime-manager.d.ts.map +1 -1
- package/dist/services/preview-runtime-manager.js +46 -363
- package/dist/services/preview-runtime-manager.js.map +1 -1
- package/dist/services/preview.service.d.ts.map +1 -1
- package/dist/services/preview.service.js +11 -9
- package/dist/services/preview.service.js.map +1 -1
- package/dist/services/project.service.d.ts +13 -13
- package/dist/services/session-manager.d.ts +2 -0
- package/dist/services/session-manager.d.ts.map +1 -1
- package/dist/services/session-manager.js +4 -2
- package/dist/services/session-manager.js.map +1 -1
- package/dist/services/session-wakeup.service.d.ts +105 -0
- package/dist/services/session-wakeup.service.d.ts.map +1 -0
- package/dist/services/session-wakeup.service.js +319 -0
- package/dist/services/session-wakeup.service.js.map +1 -0
- package/dist/services/task-handoff.service.d.ts +3 -2
- package/dist/services/task-handoff.service.d.ts.map +1 -1
- package/dist/services/task-handoff.service.js +7 -6
- package/dist/services/task-handoff.service.js.map +1 -1
- package/dist/services/team-room-delivery.d.ts +4 -4
- package/dist/services/terminal-manager.d.ts +16 -0
- package/dist/services/terminal-manager.d.ts.map +1 -1
- package/dist/services/terminal-manager.js +64 -7
- package/dist/services/terminal-manager.js.map +1 -1
- package/dist/services/workspace-background-service.service.d.ts +15 -1
- package/dist/services/workspace-background-service.service.d.ts.map +1 -1
- package/dist/services/workspace-background-service.service.js +41 -2
- package/dist/services/workspace-background-service.service.js.map +1 -1
- package/dist/utils/database-schema.d.ts.map +1 -1
- package/dist/utils/database-schema.js +9 -4
- package/dist/utils/database-schema.js.map +1 -1
- package/dist/utils/database-schema.test.js +21 -0
- package/dist/utils/database-schema.test.js.map +1 -1
- package/dist/utils/owned-child-process.d.ts +32 -3
- package/dist/utils/owned-child-process.d.ts.map +1 -1
- package/dist/utils/owned-child-process.js +138 -1
- package/dist/utils/owned-child-process.js.map +1 -1
- package/dist/web/assets/{AgentDemoPage-CrkoVCOZ.js → AgentDemoPage-D6clLNZx.js} +1 -1
- package/dist/web/assets/{AgentEnvironmentSettingsPage-BRihy3_Q.js → AgentEnvironmentSettingsPage-O1hlpsgp.js} +1 -1
- package/dist/web/assets/AttachmentPreview-hD3g_T_y.js +2 -0
- package/dist/web/assets/{BranchSelect-Bo5uhKCt.js → BranchSelect-BkuXnEG2.js} +1 -1
- package/dist/web/assets/{BrandLogo-DEL42B23.js → BrandLogo-BSwQa2SF.js} +1 -1
- package/dist/web/assets/{ConversationPage-C46RuN9U.js → ConversationPage-DvWjqFF2.js} +1 -1
- package/dist/web/assets/CreateTaskInput-Bric0GeW.js +1 -0
- package/dist/web/assets/{DemoPage-CAZqNag-.js → DemoPage-Cwy3EmOm.js} +1 -1
- package/dist/web/assets/{DesignSystemPage-CjCYC24B.js → DesignSystemPage-C1HrGwpV.js} +1 -1
- package/dist/web/assets/{ExecutionPermissionSelector-CJgc_EVo.js → ExecutionPermissionSelector-BgrxbvBB.js} +1 -1
- package/dist/web/assets/{GeneralSettingsPage-DFT7Cubi.js → GeneralSettingsPage-qdeAdBkW.js} +1 -1
- package/dist/web/assets/{LoadingPreviewPage-CB4VDPAZ.js → LoadingPreviewPage-qeZ8nuiQ.js} +1 -1
- package/dist/web/assets/{McpSettingsPage-CgiyGvkH.js → McpSettingsPage-Bo-auo0X.js} +1 -1
- package/dist/web/assets/{MemberAvatar-Cfz8LU6k.js → MemberAvatar-DBab_9EO.js} +1 -1
- package/dist/web/assets/{MobileTaskDetail-yZNyZMQt.js → MobileTaskDetail-Dm64ie99.js} +2 -2
- package/dist/web/assets/{NotificationSettingsPage-BSMJ45yx.js → NotificationSettingsPage-BVJpo76k.js} +1 -1
- package/dist/web/assets/{ProfileSettingsPage-BwNThOnH.js → ProfileSettingsPage-CbSRYGcp.js} +1 -1
- package/dist/web/assets/{ProjectKanbanPage-DtZW0bOh.js → ProjectKanbanPage-Cp3rdFik.js} +6 -6
- package/dist/web/assets/{ProjectSettingsPage-CMBMkbgI.js → ProjectSettingsPage-DLs5-Gk3.js} +1 -1
- package/dist/web/assets/{ProviderSettingsPage-D759BSRa.js → ProviderSettingsPage-BnBcgAMQ.js} +1 -1
- package/dist/web/assets/{SettingsMasterDetail-DpYUTM-Q.js → SettingsMasterDetail-fu-_yejj.js} +1 -1
- package/dist/web/assets/{TaskDetail-rRHGOvSw.js → TaskDetail-C2_Fg59e.js} +1 -1
- package/dist/web/assets/TaskHandoffPanel-3Y0gcjyN.js +70 -0
- package/dist/web/assets/{TeamSettingsPage-BszQfKp0.js → TeamSettingsPage-CAjitaBe.js} +1 -1
- package/dist/web/assets/{TranslationSettingsPage-lLaxWCy3.js → TranslationSettingsPage-DKD6Uw2F.js} +1 -1
- package/dist/web/assets/{arc-DtgXFw4D.js → arc-BiuUFTzU.js} +1 -1
- package/dist/web/assets/{architectureDiagram-3BPJPVTR-B3p3EMX1.js → architectureDiagram-3BPJPVTR-Dcwk905A.js} +1 -1
- package/dist/web/assets/{at-sign-B8rXgKEE.js → at-sign-CZAKOH3i.js} +1 -1
- package/dist/web/assets/{blockDiagram-GPEHLZMM-BmekCfr0.js → blockDiagram-GPEHLZMM-Cfc5JDN-.js} +1 -1
- package/dist/web/assets/{c4Diagram-AAUBKEIU-CF6hJhuL.js → c4Diagram-AAUBKEIU-B4v5PUdt.js} +1 -1
- package/dist/web/assets/channel-DThSYkmR.js +1 -0
- package/dist/web/assets/check-C3vuSPKz.js +1 -0
- package/dist/web/assets/{chevron-down-Dftc5hr4.js → chevron-down-CtAk9uZw.js} +1 -1
- package/dist/web/assets/{chevron-up-CKRxN6zX.js → chevron-up-DAc3NX1J.js} +1 -1
- package/dist/web/assets/{chip-ZTBHcXU2.js → chip-CDUNxQW2.js} +1 -1
- package/dist/web/assets/{chunk-2J33WTMH-Bjelop4M.js → chunk-2J33WTMH-BYRdUeyt.js} +1 -1
- package/dist/web/assets/{chunk-4BX2VUAB-B1rJPbL6.js → chunk-4BX2VUAB-3si_kPmV.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-B5qfH7Gj.js → chunk-55IACEB6-JiMm9u33.js} +1 -1
- package/dist/web/assets/{chunk-727SXJPM-ClFMbgrH.js → chunk-727SXJPM-CMCFIUyF.js} +1 -1
- package/dist/web/assets/{chunk-AQP2D5EJ-BMFjTO7B.js → chunk-AQP2D5EJ-CzvnZjH5.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-Pr1oOFfR.js → chunk-FMBD7UC4-hsabZkPl.js} +1 -1
- package/dist/web/assets/{chunk-ND2GUHAM-BPm4TRpO.js → chunk-ND2GUHAM-D2o-Reeo.js} +1 -1
- package/dist/web/assets/{chunk-QZHKN3VN-DCPA_U0M.js → chunk-QZHKN3VN-ASJk-E7d.js} +1 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-CjJqgIpK.js +1 -0
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-CjJqgIpK.js +1 -0
- package/dist/web/assets/{code-block-OCS4YCEC-Cx53F4d7.js → code-block-OCS4YCEC-5bkFBowa.js} +1 -1
- package/dist/web/assets/{confirm-dialog-C_j-w4TS.js → confirm-dialog-Bs80kXB9.js} +1 -1
- package/dist/web/assets/{content-DeIfej_n.js → content-DAccroCT.js} +1 -1
- package/dist/web/assets/{copy-B-BaLIlh.js → copy-D1XK3OqK.js} +1 -1
- package/dist/web/assets/{cose-bilkent-S5V4N54A-gIys-0yu.js → cose-bilkent-S5V4N54A-C52UKnOd.js} +1 -1
- package/dist/web/assets/{cssMode-xF0bjbbU.js → cssMode-BFq_c5xU.js} +1 -1
- package/dist/web/assets/{dagre-BM42HDAG-Bwc3Ntc-.js → dagre-BM42HDAG-CeEute93.js} +1 -1
- package/dist/web/assets/{diagram-2AECGRRQ-zkydBsMT.js → diagram-2AECGRRQ-CEcq4W4S.js} +1 -1
- package/dist/web/assets/{diagram-5GNKFQAL-p9As3QtI.js → diagram-5GNKFQAL-DqQe7Rr7.js} +1 -1
- package/dist/web/assets/{diagram-KO2AKTUF-N_pUU-iU.js → diagram-KO2AKTUF-C1KVZphS.js} +1 -1
- package/dist/web/assets/{diagram-LMA3HP47-CA2rl4Gq.js → diagram-LMA3HP47-D1BL7GQh.js} +1 -1
- package/dist/web/assets/{diagram-OG6HWLK6-BoXxBlUC.js → diagram-OG6HWLK6-ngyXooqC.js} +1 -1
- package/dist/web/assets/{dialog-CnjWIdWp.js → dialog-XkZ8wMQa.js} +1 -1
- package/dist/web/assets/{erDiagram-TEJ5UH35-CVBHQTCN.js → erDiagram-TEJ5UH35-D1zIFVqE.js} +1 -1
- package/dist/web/assets/{file-jMLGlXos.js → file-CXCll7Pm.js} +1 -1
- package/dist/web/assets/{flowDiagram-I6XJVG4X-kK7iKiAv.js → flowDiagram-I6XJVG4X-BZu49qcj.js} +1 -1
- package/dist/web/assets/{folder-picker-CR8LiSQf.js → folder-picker-CVkaEJEL.js} +1 -1
- package/dist/web/assets/{freemarker2-CTMcTiBd.js → freemarker2-CmhadAeB.js} +1 -1
- package/dist/web/assets/{ganttDiagram-6RSMTGT7-CJVvLTkW.js → ganttDiagram-6RSMTGT7-eJ8yBxfS.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-PVQCEYII-D8uj_SCw.js → gitGraphDiagram-PVQCEYII-DpeUUyH_.js} +1 -1
- package/dist/web/assets/{globe-FFVKce9-.js → globe-WnxN1JzY.js} +1 -1
- package/dist/web/assets/{handlebars-NHxbmOs3.js → handlebars-DtjmH1qR.js} +1 -1
- package/dist/web/assets/{html-oFqzz32q.js → html-DOYAlzlD.js} +1 -1
- package/dist/web/assets/{htmlMode-sgeetciK.js → htmlMode-ORxd7KRN.js} +1 -1
- package/dist/web/assets/{index-biTPUXAe.js → index-6mINSZng.js} +1 -1
- package/dist/web/assets/{index-C5lNOKJb.js → index-BrjvxKaf.js} +1 -1
- package/dist/web/assets/{index-CwfWGzxi.js → index-CqIyOiVN.js} +4 -4
- package/dist/web/assets/{index-D8TNxwWk.js → index-D9w1zMaz.js} +1 -1
- package/dist/web/assets/{index-Cm_7q6ju.js → index-DHDgbH3t.js} +1 -1
- package/dist/web/assets/{index-9KNEuwGB.js → index-Dz9SKopM.js} +13 -13
- package/dist/web/assets/{index-gqrRO6ZJ.js → index-eIXz5Hbk.js} +1 -1
- package/dist/web/assets/{index-BzqyZD7L.js → index-iOIxdF6J.js} +1 -1
- package/dist/web/assets/{index-C9vIrQ3Q.js → index-wbMiSmsY.js} +1 -1
- package/dist/web/assets/{infoDiagram-5YYISTIA-CExRZE3Y.js → infoDiagram-5YYISTIA-BiVrC__7.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-CsqM2X33.js → ishikawaDiagram-YF4QCWOH-B1kPjO1J.js} +1 -1
- package/dist/web/assets/javascript-CHlWHrtz.js +1 -0
- package/dist/web/assets/{journeyDiagram-JHISSGLW-DX9OMhPD.js → journeyDiagram-JHISSGLW-DoTAPPAQ.js} +1 -1
- package/dist/web/assets/{jsonMode-VQg5cpLV.js → jsonMode-BkeQ_C6g.js} +1 -1
- package/dist/web/assets/{kanban-definition-UN3LZRKU-CWHMx6vc.js → kanban-definition-UN3LZRKU-CBRmLcce.js} +1 -1
- package/dist/web/assets/{kbd-GGofKfKu.js → kbd-CTfS0G5-.js} +1 -1
- package/dist/web/assets/{key-round-p-Fpykfj.js → key-round-B7gTfpDR.js} +1 -1
- package/dist/web/assets/{layers-pbPa_eZq.js → layers-DE0xXedq.js} +1 -1
- package/dist/web/assets/{linear-9VwGhaEA.js → linear-VLiA8Vcw.js} +1 -1
- package/dist/web/assets/{link-CG4UwIS1.js → link-BSE_nRDT.js} +1 -1
- package/dist/web/assets/{liquid-SJInUaiB.js → liquid-BZeg6p1K.js} +1 -1
- package/dist/web/assets/{lspLanguageFeatures-DJOdVyBc.js → lspLanguageFeatures-CuFQ2_f9.js} +1 -1
- package/dist/web/assets/{mdx-CToYr-3b.js → mdx-C7xLyFFX.js} +1 -1
- package/dist/web/assets/{menu-BFQ1mKU7.js → menu-Dp4RDxvP.js} +1 -1
- package/dist/web/assets/{mermaid-NOHMQCX5-BOViobLk.js → mermaid-NOHMQCX5-C2enCJxR.js} +56 -56
- package/dist/web/assets/{message-square-BYZsUsLz.js → message-square-4lyHjyHe.js} +1 -1
- package/dist/web/assets/{mindmap-definition-RKZ34NQL-BTcDnn6X.js → mindmap-definition-RKZ34NQL-C1OOtqma.js} +1 -1
- package/dist/web/assets/{modal-BT_7Lhtw.js → modal-BGglpgrR.js} +1 -1
- package/dist/web/assets/{monaco-DUftz48_.js → monaco-B-6VmJO0.js} +3 -3
- package/dist/web/assets/{nav-row-BjDckaPC.js → nav-row-DaR8yP7p.js} +1 -1
- package/dist/web/assets/{paperclip-CFAH5neE.js → paperclip-DORF2rEM.js} +1 -1
- package/dist/web/assets/{pencil-Bg9TWm_-.js → pencil-BG033B74.js} +1 -1
- package/dist/web/assets/{people-BIQwajM2.js → people-1qyKeYq6.js} +1 -1
- package/dist/web/assets/{pieDiagram-4H26LBE5-CRjqdnP8.js → pieDiagram-4H26LBE5-BYYFVqOS.js} +1 -1
- package/dist/web/assets/{popover-DpYhrrCE.js → popover-CvjMbMb4.js} +1 -1
- package/dist/web/assets/{python-DbmUucgH.js → python-TTfnYnjF.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-W4KKPZXB-uvA8TYC6.js → quadrantDiagram-W4KKPZXB-DTllM2j9.js} +1 -1
- package/dist/web/assets/{razor-B0AJhw7W.js → razor-BFVXAHVd.js} +1 -1
- package/dist/web/assets/{requirementDiagram-4Y6WPE33-BWLugaKX.js → requirementDiagram-4Y6WPE33-DeJDRYUP.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-5OEKKPKP-DHrbZZv8.js → sankeyDiagram-5OEKKPKP-DzTvEKv8.js} +1 -1
- package/dist/web/assets/{search-BH8nze-X.js → search-DDRcBORc.js} +1 -1
- package/dist/web/assets/{select-BegY9RkP.js → select-CXC17bJx.js} +1 -1
- package/dist/web/assets/{select-EcEr5QSS.js → select-CzXL3ZbG.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-3UESZ5HK-CKwEKcTn.js → sequenceDiagram-3UESZ5HK-CIYrA1ww.js} +1 -1
- package/dist/web/assets/{server-BxEUjx0l.js → server-KqeWHfgr.js} +1 -1
- package/dist/web/assets/{stateDiagram-AJRCARHV-vhgmSpa9.js → stateDiagram-AJRCARHV-Dg_UXkEq.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-Lc4r0bC3.js +1 -0
- package/dist/web/assets/{textarea-CvoGGROs.js → textarea-Cmbv5l35.js} +1 -1
- package/dist/web/assets/{timeline-definition-PNZ67QCA-bSDKcwDZ.js → timeline-definition-PNZ67QCA-CfSPMqxF.js} +1 -1
- package/dist/web/assets/{toggles-CEDUD08u.js → toggles-t5v4QKn6.js} +1 -1
- package/dist/web/assets/{tooltip-CKaUbVZ7.js → tooltip-Cp8tovqH.js} +1 -1
- package/dist/web/assets/{track-1qw2cvTy.js → track-C1rUV49K.js} +1 -1
- package/dist/web/assets/{trash-2-ChiXon87.js → trash-2-Ca2ken6q.js} +1 -1
- package/dist/web/assets/{tsMode-bnV8W2Ru.js → tsMode-DBbiXlyu.js} +1 -1
- package/dist/web/assets/{typescript-d1MHIeEx.js → typescript-jv_3P9x_.js} +1 -1
- package/dist/web/assets/{upload-CQ-cQaOz.js → upload-CgGjN1FH.js} +1 -1
- package/dist/web/assets/{use-profiles-CJzoqarX.js → use-profiles-BdL-U8GZ.js} +1 -1
- package/dist/web/assets/{use-providers-S29TCag2.js → use-providers-B6Mj5qeG.js} +1 -1
- package/dist/web/assets/{use-translation-settings-DifNJaCu.js → use-translation-settings-FIP674t9.js} +1 -1
- package/dist/web/assets/{useNormalizedLogs-BVdY8qDk.js → useNormalizedLogs-FpVMUHeq.js} +1 -1
- package/dist/web/assets/useTokenUsage-Ay3Yy0_V.js +1 -0
- package/dist/web/assets/{vennDiagram-CIIHVFJN-D7QbDYzC.js → vennDiagram-CIIHVFJN-DKREAIRT.js} +1 -1
- package/dist/web/assets/{wardley-L42UT6IY-C9aHlNVa.js → wardley-L42UT6IY-BMpDotAz.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-YWT4CUSO-CZhubDRC.js → wardleyDiagram-YWT4CUSO-DAPccQsF.js} +1 -1
- package/dist/web/assets/{xml-DAKKxHAr.js → xml-DnxIQwRS.js} +1 -1
- package/dist/web/assets/{xychartDiagram-2RQKCTM6-BgDlpFBh.js → xychartDiagram-2RQKCTM6-o06g8vo8.js} +1 -1
- package/dist/web/assets/{yaml-D_hSVVz0.js → yaml-BV5yQTRd.js} +1 -1
- package/dist/web/index.html +1 -1
- package/node_modules/@agent-tower/shared/dist/log-adapter.d.ts +4 -0
- package/node_modules/@agent-tower/shared/dist/log-adapter.d.ts.map +1 -1
- package/node_modules/@agent-tower/shared/dist/log-adapter.js +1 -0
- package/node_modules/@agent-tower/shared/dist/log-adapter.js.map +1 -1
- package/node_modules/@agent-tower/shared/dist/translation.d.ts +4 -1
- package/node_modules/@agent-tower/shared/dist/translation.d.ts.map +1 -1
- package/node_modules/@agent-tower/shared/dist/translation.js +4 -1
- package/node_modules/@agent-tower/shared/dist/translation.js.map +1 -1
- package/node_modules/@agent-tower/shared/dist/types.d.ts +38 -2
- 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 +2 -1
- package/prisma/migrations/20261106000000_add_session_wakeups/migration.sql +28 -0
- package/prisma/schema.prisma +28 -0
- package/scripts/postinstall.js +23 -0
- package/dist/web/assets/AttachmentPreview-B9z1Mxb-.js +0 -2
- package/dist/web/assets/CreateTaskInput-4aHJpsfL.js +0 -1
- package/dist/web/assets/TaskHandoffPanel-DBcC1xQW.js +0 -70
- package/dist/web/assets/channel-BdK_fAel.js +0 -1
- package/dist/web/assets/check-DwK55QS2.js +0 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-CFzCq0ml.js +0 -1
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-CFzCq0ml.js +0 -1
- package/dist/web/assets/javascript-COt-61wn.js +0 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-C0z5OTY4.js +0 -1
- package/dist/web/assets/useTokenUsage-nh_KDA3q.js +0 -1
|
@@ -1209,6 +1209,70 @@ describe('SessionManager session status vs real process state', () => {
|
|
|
1209
1209
|
})).toBe(0);
|
|
1210
1210
|
await manager.destroyAll();
|
|
1211
1211
|
});
|
|
1212
|
+
it.each([
|
|
1213
|
+
['start', 'entry'], ['startFollowUp', 'entry'],
|
|
1214
|
+
['start', 'backend'], ['startFollowUp', 'backend'],
|
|
1215
|
+
])('resolves a Claude MCP %s failure with missing %s and permits cleanup and retry', async (method, missing) => {
|
|
1216
|
+
const { ClaudeCodeExecutor } = await import('../../executors/claude-code.executor.js');
|
|
1217
|
+
// Exercise the real configuration builder and CLI Driver; only substitute
|
|
1218
|
+
// the PTY transport after configuration succeeds.
|
|
1219
|
+
class TestClaudeExecutor extends ClaudeCodeExecutor {
|
|
1220
|
+
async spawnWithStdin() { return spawnMock(); }
|
|
1221
|
+
}
|
|
1222
|
+
const executor = new TestClaudeExecutor({ executionPermission: 'FULL_ACCESS' });
|
|
1223
|
+
const provider = {
|
|
1224
|
+
id: 'claude-mcp-recovery', name: 'Claude MCP recovery', agentType: AgentType.CLAUDE_CODE,
|
|
1225
|
+
runtimeType: RuntimeType.CLI, executionPermission: 'FULL_ACCESS',
|
|
1226
|
+
config: {}, env: {}, isDefault: false,
|
|
1227
|
+
};
|
|
1228
|
+
getProviderByIdMock.mockReturnValue(provider);
|
|
1229
|
+
getExecutorByProviderMock.mockReturnValue(executor);
|
|
1230
|
+
const { workspace, session } = await createSessionFixture({ providerId: provider.id, agentType: AgentType.CLAUDE_CODE });
|
|
1231
|
+
const resumeSource = await prisma.session.create({ data: {
|
|
1232
|
+
workspaceId: workspace.id, agentType: AgentType.CLAUDE_CODE, prompt: 'previous turn',
|
|
1233
|
+
status: SessionStatus.COMPLETED, externalSessionId: 'previous-claude-session',
|
|
1234
|
+
} });
|
|
1235
|
+
const entry = path.join(serverRoot, 'src', 'mcp', 'index.ts');
|
|
1236
|
+
const manager = new SessionManager(new EventBus());
|
|
1237
|
+
const pty = new ControlledPty();
|
|
1238
|
+
spawnMock.mockReset();
|
|
1239
|
+
spawnMock.mockResolvedValueOnce(spawnResultFor(pty));
|
|
1240
|
+
vi.stubEnv('AGENT_TOWER_DESKTOP_RUNTIME_MODE', undefined);
|
|
1241
|
+
vi.stubEnv('AGENT_TOWER_MCP_ENTRY', missing === 'entry' ? path.join(testDir, 'missing-mcp.js') : entry);
|
|
1242
|
+
vi.stubEnv('AGENT_TOWER_URL', missing === 'backend' ? undefined : 'http://127.0.0.1:12580');
|
|
1243
|
+
vi.stubEnv('AGENT_TOWER_PORT', undefined);
|
|
1244
|
+
try {
|
|
1245
|
+
const starting = method === 'start' ? manager.start(session.id) : manager.startFollowUp(session.id, resumeSource.id);
|
|
1246
|
+
await expect(starting).rejects.toThrow(missing === 'entry'
|
|
1247
|
+
? 'Agent Tower MCP entry not found'
|
|
1248
|
+
: 'AGENT_TOWER_URL or AGENT_TOWER_PORT is required');
|
|
1249
|
+
expect(spawnMock).not.toHaveBeenCalled();
|
|
1250
|
+
expect(await prisma.executionProcess.count({ where: { sessionId: session.id } })).toBe(0);
|
|
1251
|
+
await expect(prisma.session.findUniqueOrThrow({ where: { id: session.id } })).resolves.toMatchObject({
|
|
1252
|
+
status: SessionStatus.CANCELLED, runtimeLaunchState: 'SAFE_PRE_CHILD_FAILURE',
|
|
1253
|
+
runtimeLaunchClaimCount: 1, runtimeLaunchResolvedCount: 1, runtimeLaunchProcessCount: 0,
|
|
1254
|
+
});
|
|
1255
|
+
expect(await manager.isRuntimeCleanupConfirmed(session.id)).toBe(true);
|
|
1256
|
+
await expect(manager.stop(session.id)).resolves.toMatchObject({ id: session.id });
|
|
1257
|
+
vi.stubEnv('AGENT_TOWER_MCP_ENTRY', entry);
|
|
1258
|
+
vi.stubEnv('AGENT_TOWER_URL', 'http://127.0.0.1:12580');
|
|
1259
|
+
await expect(manager.sendMessage(session.id, 'retry after correcting MCP configuration')).resolves.toMatchObject({ id: session.id });
|
|
1260
|
+
expect(spawnMock).toHaveBeenCalledOnce();
|
|
1261
|
+
await expect(prisma.session.findUniqueOrThrow({ where: { id: session.id } })).resolves.toMatchObject({
|
|
1262
|
+
status: SessionStatus.RUNNING, runtimeLaunchState: 'PROCESS_RECORDED',
|
|
1263
|
+
runtimeLaunchClaimCount: 2, runtimeLaunchResolvedCount: 2, runtimeLaunchProcessCount: 1,
|
|
1264
|
+
});
|
|
1265
|
+
await manager.stop(session.id);
|
|
1266
|
+
expect(pty.killed).toBe(true);
|
|
1267
|
+
expect(await manager.isRuntimeCleanupConfirmed(session.id)).toBe(true);
|
|
1268
|
+
expect(await prisma.executionProcess.findMany({ where: { sessionId: session.id } }))
|
|
1269
|
+
.toMatchObject([{ launchClaimNumber: 2, cleanupState: 'CONFIRMED' }]);
|
|
1270
|
+
}
|
|
1271
|
+
finally {
|
|
1272
|
+
vi.unstubAllEnvs();
|
|
1273
|
+
await manager.destroyAll();
|
|
1274
|
+
}
|
|
1275
|
+
});
|
|
1212
1276
|
it.each(['start', 'startFollowUp'])('revokes a public %s before runtime admission when stop wins during preparation', async (method) => {
|
|
1213
1277
|
const { workspace, session } = await createSessionFixture();
|
|
1214
1278
|
const resumeSource = await prisma.session.create({
|
|
@@ -1358,6 +1422,8 @@ describe('SessionManager session status vs real process state', () => {
|
|
|
1358
1422
|
expect(checkpoint).toHaveBeenCalledWith(session.id);
|
|
1359
1423
|
feed({ type: 'stream_event', event: { type: 'content_block_start', index: 2, content_block: { type: 'text', text: 'B after tool' } } });
|
|
1360
1424
|
feed({ type: 'result', subtype: 'success', num_turns: 1 });
|
|
1425
|
+
// A Claude run ends when its process exits, not at the result.
|
|
1426
|
+
pty.emitExit(0);
|
|
1361
1427
|
await completed;
|
|
1362
1428
|
const row = await prisma.session.findUniqueOrThrow({ where: { id: session.id } });
|
|
1363
1429
|
expect(JSON.parse(row.logSnapshot).entries.at(-1)).toMatchObject({ content: 'B after tool', metadata: { textBlock: { state: 'SEALED', sealedReason: 'TURN_END' } } });
|
|
@@ -1499,6 +1565,78 @@ describe('SessionManager session status vs real process state', () => {
|
|
|
1499
1565
|
expect(snapshot.entries.map((entry) => entry.content))
|
|
1500
1566
|
.toContain('fast logical completion');
|
|
1501
1567
|
});
|
|
1568
|
+
it('keeps a Claude Code session running after its result while background work is pending and completes on exit', async () => {
|
|
1569
|
+
const { session } = await createSessionFixture({ agentType: AgentType.CLAUDE_CODE });
|
|
1570
|
+
const pty = new ControlledPty();
|
|
1571
|
+
spawnMock.mockResolvedValueOnce(spawnResultFor(pty));
|
|
1572
|
+
const eventBus = new EventBus();
|
|
1573
|
+
const manager = new SessionManager(eventBus);
|
|
1574
|
+
const completed = waitForEvent(eventBus, 'session:completed');
|
|
1575
|
+
const states = [];
|
|
1576
|
+
eventBus.on('session:runtime_state_changed', ({ state }) => states.push(state));
|
|
1577
|
+
try {
|
|
1578
|
+
await manager.start(session.id);
|
|
1579
|
+
const line = (message) => pty.emitData(JSON.stringify(message) + '\n');
|
|
1580
|
+
line({ type: 'system', subtype: 'init', session_id: 'claude-native' });
|
|
1581
|
+
line({ type: 'assistant', message: { id: 'm1', role: 'assistant', content: [{ type: 'text', text: 'WAITING for the router' }] } });
|
|
1582
|
+
line({ type: 'system', subtype: 'background_tasks_changed', tasks: [{ task_id: 'bg-1', task_type: 'local_bash', description: 'router watch' }] });
|
|
1583
|
+
line({ type: 'result', subtype: 'success', result: 'WAITING for the router', num_turns: 1, result_index: 0, uuid: 'r0', origin: null });
|
|
1584
|
+
await vi.waitFor(() => {
|
|
1585
|
+
expect(states.some((state) => state.backgroundTasks?.some((task) => task.taskId === 'bg-1'))).toBe(true);
|
|
1586
|
+
}, { timeout: 2000 });
|
|
1587
|
+
await new Promise((resolve) => setTimeout(resolve, 300));
|
|
1588
|
+
expect(manager.hasActiveTurn(session.id)).toBe(true);
|
|
1589
|
+
expect(pty.killed).toBe(false);
|
|
1590
|
+
expect((await prisma.session.findUnique({ where: { id: session.id } }))?.status).toBe(SessionStatus.RUNNING);
|
|
1591
|
+
line({ type: 'system', subtype: 'task_notification', task_id: 'bg-1', status: 'completed', summary: 'Background command "router watch" completed (exit code 0)' });
|
|
1592
|
+
line({ type: 'system', subtype: 'background_tasks_changed', tasks: [] });
|
|
1593
|
+
line({ type: 'system', subtype: 'init', session_id: 'claude-native' });
|
|
1594
|
+
line({ type: 'assistant', message: { id: 'm2', role: 'assistant', content: [{ type: 'text', text: 'FINISHED routing' }] } });
|
|
1595
|
+
line({ type: 'result', subtype: 'success', result: 'FINISHED routing', num_turns: 1, result_index: 1, uuid: 'r1', origin: { kind: 'task-notification' } });
|
|
1596
|
+
pty.emitExit(0);
|
|
1597
|
+
const payload = await completed;
|
|
1598
|
+
expect(payload.status).toBe(SessionStatus.COMPLETED);
|
|
1599
|
+
await vi.waitFor(() => expect(manager.hasActiveTurn(session.id)).toBe(false), { timeout: 2000 });
|
|
1600
|
+
const persisted = await prisma.session.findUnique({ where: { id: session.id } });
|
|
1601
|
+
expect(persisted?.status).toBe(SessionStatus.COMPLETED);
|
|
1602
|
+
const contents = JSON.parse(persisted?.logSnapshot ?? '{}').entries.map((entry) => entry.content);
|
|
1603
|
+
expect(contents).toContain('FINISHED routing');
|
|
1604
|
+
expect(contents).toContain('Background command "router watch" completed (exit code 0)');
|
|
1605
|
+
}
|
|
1606
|
+
finally {
|
|
1607
|
+
await manager.destroyAll();
|
|
1608
|
+
}
|
|
1609
|
+
});
|
|
1610
|
+
it('stops a waiting Claude Code run when a follow-up arrives and tags wake-up messages as system events', async () => {
|
|
1611
|
+
const { session } = await createSessionFixture({ agentType: AgentType.CLAUDE_CODE });
|
|
1612
|
+
const first = new ControlledPty();
|
|
1613
|
+
const second = new ControlledPty();
|
|
1614
|
+
second.pid = 4343;
|
|
1615
|
+
spawnMock.mockResolvedValueOnce(spawnResultFor(first)).mockResolvedValueOnce(spawnResultFor(second));
|
|
1616
|
+
const eventBus = new EventBus();
|
|
1617
|
+
const manager = new SessionManager(eventBus);
|
|
1618
|
+
try {
|
|
1619
|
+
await manager.start(session.id);
|
|
1620
|
+
const line = (pty, message) => pty.emitData(JSON.stringify(message) + '\n');
|
|
1621
|
+
line(first, { type: 'system', subtype: 'background_tasks_changed', tasks: [{ task_id: 'bg-1', description: 'watch' }] });
|
|
1622
|
+
line(first, { type: 'result', subtype: 'success', result: 'WAITING', num_turns: 1, result_index: 0, uuid: 'r0', origin: null });
|
|
1623
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
1624
|
+
expect(first.killed).toBe(false);
|
|
1625
|
+
await manager.sendMessage(session.id, 'wake-up text', undefined, undefined, { origin: 'SYSTEM_EVENT' });
|
|
1626
|
+
expect(first.killed).toBe(true);
|
|
1627
|
+
const completed = waitForEvent(eventBus, 'session:completed');
|
|
1628
|
+
line(second, { type: 'result', subtype: 'success', result: 'done', result_index: 0, uuid: 'r0', origin: null });
|
|
1629
|
+
second.emitExit(0);
|
|
1630
|
+
await completed;
|
|
1631
|
+
const persisted = await prisma.session.findUnique({ where: { id: session.id } });
|
|
1632
|
+
const entries = JSON.parse(persisted?.logSnapshot ?? '{}').entries;
|
|
1633
|
+
const wakeup = entries.find((entry) => entry.content === 'wake-up text');
|
|
1634
|
+
expect(wakeup).toMatchObject({ entryType: 'user_message', metadata: { origin: 'SYSTEM_EVENT' } });
|
|
1635
|
+
}
|
|
1636
|
+
finally {
|
|
1637
|
+
await manager.destroyAll();
|
|
1638
|
+
}
|
|
1639
|
+
});
|
|
1502
1640
|
it('waits for the completed generation auto-commit before starting an immediate follow-up', async () => {
|
|
1503
1641
|
const { session } = await createSessionFixture();
|
|
1504
1642
|
const firstPty = new ControlledPty();
|
|
@@ -1722,7 +1860,7 @@ describe('SessionManager session status vs real process state', () => {
|
|
|
1722
1860
|
expect(spawnMock).toHaveBeenCalledTimes(2);
|
|
1723
1861
|
await manager.destroyAll();
|
|
1724
1862
|
});
|
|
1725
|
-
it.each(['success', 'error_during_execution'])('persists Claude final %s and
|
|
1863
|
+
it.each(['success', 'error_during_execution'])('persists Claude final %s and reclaims a CLI process that lingers after its result', async (subtype) => {
|
|
1726
1864
|
const { task, session } = await createSessionFixture({ agentType: AgentType.CLAUDE_CODE });
|
|
1727
1865
|
const pty = new ControlledPty();
|
|
1728
1866
|
spawnMock.mockResolvedValueOnce(spawnResultFor(pty));
|
|
@@ -1730,6 +1868,9 @@ describe('SessionManager session status vs real process state', () => {
|
|
|
1730
1868
|
const manager = new SessionManager(eventBus);
|
|
1731
1869
|
const completed = waitForEvent(eventBus, 'session:completed');
|
|
1732
1870
|
const expectedStatus = subtype === 'success' ? SessionStatus.COMPLETED : SessionStatus.FAILED;
|
|
1871
|
+
// The process reports no background work and never exits: Tower treats it as hung after the idle grace.
|
|
1872
|
+
const previousGrace = process.env.AGENT_TOWER_CLAUDE_IDLE_EXIT_GRACE_MS;
|
|
1873
|
+
process.env.AGENT_TOWER_CLAUDE_IDLE_EXIT_GRACE_MS = '200';
|
|
1733
1874
|
try {
|
|
1734
1875
|
await manager.start(session.id);
|
|
1735
1876
|
pty.emitData(JSON.stringify({
|
|
@@ -1765,8 +1906,13 @@ describe('SessionManager session status vs real process state', () => {
|
|
|
1765
1906
|
}));
|
|
1766
1907
|
expect((await prisma.task.findUniqueOrThrow({ where: { id: task.id } })).status).not.toBe('IN_REVIEW');
|
|
1767
1908
|
}
|
|
1909
|
+
expect(snapshot.entries).toContainEqual(expect.objectContaining({ entryType: 'warning_message' }));
|
|
1768
1910
|
}
|
|
1769
1911
|
finally {
|
|
1912
|
+
if (previousGrace === undefined)
|
|
1913
|
+
delete process.env.AGENT_TOWER_CLAUDE_IDLE_EXIT_GRACE_MS;
|
|
1914
|
+
else
|
|
1915
|
+
process.env.AGENT_TOWER_CLAUDE_IDLE_EXIT_GRACE_MS = previousGrace;
|
|
1770
1916
|
await manager.destroyAll();
|
|
1771
1917
|
}
|
|
1772
1918
|
});
|