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
package/dist/routes/previews.js
CHANGED
|
@@ -1,31 +1,20 @@
|
|
|
1
1
|
import { registerApplicationProcessCleanup } from '../runtime/application-process-cleanup.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import http from 'node:http';
|
|
4
|
-
import https from 'node:https';
|
|
5
3
|
import { PreviewService } from '../services/preview.service.js';
|
|
6
4
|
import { ServiceError } from '../errors.js';
|
|
7
5
|
import { TunnelService } from '../services/tunnel.service.js';
|
|
8
|
-
import {
|
|
9
|
-
import { AccessAuthService
|
|
6
|
+
import { extractTunnelSessionTokenFromCookieHeader } from '../utils/tunnel-cookie.js';
|
|
7
|
+
import { AccessAuthService } from '../services/access-auth.service.js';
|
|
10
8
|
import { INTERNAL_API_TOKEN_HEADER, validateInternalApiToken, } from '../utils/internal-api-token.js';
|
|
11
|
-
import { buildPreviewPathPrefix, parsePreviewPath
|
|
9
|
+
import { buildPreviewPathPrefix, parsePreviewPath } from '../utils/preview-path.js';
|
|
12
10
|
import { addPreviewAccessToken, PreviewRuntimeManager, } from '../services/preview-runtime-manager.js';
|
|
11
|
+
import { classifyPreviewRequest, previewServiceWorkerSegment, proxyPreviewHttpRequest, proxyPreviewWebSocket, shouldServeBootstrap, writeBootstrapPage, writeServiceWorkerScript, writeUpgradeError, } from '../services/preview-proxy.js';
|
|
13
12
|
import { isTunnelRequest } from '../middleware/tunnel-auth.js';
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
'allow-popups',
|
|
20
|
-
'allow-popups-to-escape-sandbox',
|
|
21
|
-
'allow-modals',
|
|
22
|
-
'allow-downloads',
|
|
23
|
-
'allow-pointer-lock',
|
|
24
|
-
'allow-presentation',
|
|
25
|
-
'allow-top-navigation-by-user-activation',
|
|
26
|
-
].join(' ');
|
|
27
|
-
const PREVIEW_CORS_ALLOW_METHODS = 'GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS';
|
|
28
|
-
const PREVIEW_CORS_DEFAULT_ALLOW_HEADERS = 'Content-Type, Accept, Authorization, X-Requested-With';
|
|
13
|
+
export { PREVIEW_SANDBOX_CSP } from '../services/preview-proxy.js';
|
|
14
|
+
/** Session id returned for the same-origin proxy; it needs no lease or heartbeat. */
|
|
15
|
+
export const SAME_ORIGIN_PREVIEW_SESSION_ID = 'same-origin';
|
|
16
|
+
const SAME_ORIGIN_SESSION_TTL_MS = 24 * 60 * 60 * 1000;
|
|
17
|
+
const PROXY_BODY_LIMIT_BYTES = 256 * 1024 * 1024;
|
|
29
18
|
const configSchema = z.object({
|
|
30
19
|
target: z.string().nullable(),
|
|
31
20
|
});
|
|
@@ -47,305 +36,25 @@ function errorResponse(error, reply) {
|
|
|
47
36
|
reply.log.error(error);
|
|
48
37
|
return reply.code(500).send({ error: 'Internal server error', code: 'INTERNAL_ERROR' });
|
|
49
38
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
39
|
+
/**
|
|
40
|
+
* Docker and other deployments whose dynamic gateway port is not reachable by
|
|
41
|
+
* browsers force the same-origin proxy. `AGENT_TOWER_PREVIEW_FORCE_TUNNEL` is
|
|
42
|
+
* the previous name of the same switch and is still honoured.
|
|
43
|
+
*/
|
|
44
|
+
export function forceSameOriginPreview(env = process.env) {
|
|
45
|
+
return env.AGENT_TOWER_PREVIEW_FORCE_SAME_ORIGIN === 'true'
|
|
46
|
+
|| env.AGENT_TOWER_PREVIEW_FORCE_TUNNEL === 'true';
|
|
55
47
|
}
|
|
56
|
-
function
|
|
57
|
-
if (!cookieHeader)
|
|
58
|
-
return undefined;
|
|
59
|
-
const cookies = cookieHeader
|
|
60
|
-
.split(';')
|
|
61
|
-
.map((part) => part.trim())
|
|
62
|
-
.filter(Boolean)
|
|
63
|
-
.filter((part) => {
|
|
64
|
-
const [name] = part.split('=');
|
|
65
|
-
return name
|
|
66
|
-
&& name !== TUNNEL_SESSION_COOKIE_NAME
|
|
67
|
-
&& !isAccessAuthCookieName(name);
|
|
68
|
-
});
|
|
69
|
-
return cookies.length > 0 ? cookies.join('; ') : undefined;
|
|
70
|
-
}
|
|
71
|
-
export function proxyRequestHeaders(headers, targetUrl, targetPath = '/') {
|
|
72
|
-
const next = { ...headers };
|
|
73
|
-
delete next.host;
|
|
74
|
-
delete next.connection;
|
|
75
|
-
delete next['content-length'];
|
|
76
|
-
delete next['accept-encoding'];
|
|
77
|
-
const cookie = filterCookieHeader(headers.cookie);
|
|
78
|
-
if (cookie)
|
|
79
|
-
next.cookie = cookie;
|
|
80
|
-
else
|
|
81
|
-
delete next.cookie;
|
|
82
|
-
next.host = targetUrl.host;
|
|
83
|
-
next['accept-encoding'] = 'identity';
|
|
84
|
-
next['x-forwarded-host'] = targetUrl.host;
|
|
85
|
-
next['x-forwarded-proto'] = targetUrl.protocol.slice(0, -1);
|
|
86
|
-
if (headers.origin) {
|
|
87
|
-
next.origin = targetUrl.origin;
|
|
88
|
-
}
|
|
89
|
-
if (headers.referer) {
|
|
90
|
-
next.referer = new URL(targetPath, targetUrl).toString();
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
delete next.referer;
|
|
94
|
-
}
|
|
95
|
-
return next;
|
|
96
|
-
}
|
|
97
|
-
function firstHeaderValue(value) {
|
|
98
|
-
return Array.isArray(value) ? value[0] : value;
|
|
99
|
-
}
|
|
100
|
-
function normalizeRequestedHeaders(value) {
|
|
101
|
-
if (!value)
|
|
102
|
-
return PREVIEW_CORS_DEFAULT_ALLOW_HEADERS;
|
|
103
|
-
const headers = value
|
|
104
|
-
.split(',')
|
|
105
|
-
.map((item) => item.trim())
|
|
106
|
-
.filter(Boolean);
|
|
107
|
-
return headers.length > 0 ? headers.join(', ') : PREVIEW_CORS_DEFAULT_ALLOW_HEADERS;
|
|
108
|
-
}
|
|
109
|
-
export function previewCorsHeaders(requestHeaders) {
|
|
48
|
+
export function sameOriginPreviewSession(workspaceId, target, now = Date.now()) {
|
|
110
49
|
return {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
50
|
+
id: SAME_ORIGIN_PREVIEW_SESSION_ID,
|
|
51
|
+
target: target.target,
|
|
52
|
+
mode: 'remote',
|
|
53
|
+
kind: 'same-origin',
|
|
54
|
+
viewUrl: `${buildPreviewPathPrefix(workspaceId)}/`,
|
|
55
|
+
expiresAt: new Date(now + SAME_ORIGIN_SESSION_TTL_MS).toISOString(),
|
|
116
56
|
};
|
|
117
57
|
}
|
|
118
|
-
export function rewriteLocationHeader(value, workspaceId, target, previewToken) {
|
|
119
|
-
const prefix = buildPreviewPathPrefix(workspaceId, previewToken);
|
|
120
|
-
try {
|
|
121
|
-
const location = new URL(value, target.origin);
|
|
122
|
-
if (location.origin !== target.origin)
|
|
123
|
-
return value;
|
|
124
|
-
if (isSameOrChildPath(location.pathname, prefix)) {
|
|
125
|
-
return `${location.pathname}${location.search}${location.hash}`;
|
|
126
|
-
}
|
|
127
|
-
const basePath = target.basePath;
|
|
128
|
-
const isUnderBasePath = basePath
|
|
129
|
-
? location.pathname === basePath || location.pathname.startsWith(`${basePath}/`)
|
|
130
|
-
: true;
|
|
131
|
-
const path = isUnderBasePath
|
|
132
|
-
? location.pathname.slice(target.basePath.length || 0) || '/'
|
|
133
|
-
: location.pathname;
|
|
134
|
-
return `${prefix}${path}${location.search}${location.hash}`;
|
|
135
|
-
}
|
|
136
|
-
catch {
|
|
137
|
-
if (isSameOrChildPath(getPathname(value), prefix))
|
|
138
|
-
return value;
|
|
139
|
-
if (value.startsWith('/'))
|
|
140
|
-
return `${prefix}${value}`;
|
|
141
|
-
return value;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
export function rewriteSetCookieHeader(value, workspaceId, previewToken) {
|
|
145
|
-
const prefix = `${buildPreviewPathPrefix(workspaceId, previewToken)}/`;
|
|
146
|
-
const withoutDomain = value.replace(/;\s*domain=[^;]*/gi, '');
|
|
147
|
-
if (/;\s*path=/i.test(withoutDomain)) {
|
|
148
|
-
return withoutDomain.replace(/;\s*path=([^;]*)/i, `; Path=${prefix}`);
|
|
149
|
-
}
|
|
150
|
-
return `${withoutDomain}; Path=${prefix}`;
|
|
151
|
-
}
|
|
152
|
-
export function proxyResponseHeaders(headers, workspaceId, target, requestHeaders, previewToken) {
|
|
153
|
-
const next = {};
|
|
154
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
155
|
-
const lower = key.toLowerCase();
|
|
156
|
-
if (lower === 'connection'
|
|
157
|
-
|| lower === 'content-length'
|
|
158
|
-
|| lower === 'content-encoding'
|
|
159
|
-
|| lower === 'transfer-encoding'
|
|
160
|
-
|| lower === 'x-frame-options') {
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
if (lower === 'content-security-policy') {
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
if (lower.startsWith('access-control-')) {
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
if (lower === 'location' && typeof value === 'string') {
|
|
170
|
-
next[key] = rewriteLocationHeader(value, workspaceId, target, previewToken);
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
if (lower === 'set-cookie') {
|
|
174
|
-
const cookies = Array.isArray(value) ? value : typeof value === 'string' ? [value] : [];
|
|
175
|
-
next[key] = cookies.map((cookie) => rewriteSetCookieHeader(cookie, workspaceId, previewToken));
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
if (value !== undefined)
|
|
179
|
-
next[key] = value;
|
|
180
|
-
}
|
|
181
|
-
next['content-security-policy'] = PREVIEW_SANDBOX_CSP;
|
|
182
|
-
Object.assign(next, previewCorsHeaders(requestHeaders));
|
|
183
|
-
next['cross-origin-resource-policy'] = 'cross-origin';
|
|
184
|
-
return next;
|
|
185
|
-
}
|
|
186
|
-
function isRewritableContent(contentType) {
|
|
187
|
-
const value = Array.isArray(contentType) ? contentType.join(';') : contentType ?? '';
|
|
188
|
-
const lower = value.toLowerCase();
|
|
189
|
-
return lower.includes('text/html')
|
|
190
|
-
|| lower.includes('text/css')
|
|
191
|
-
|| lower.includes('javascript')
|
|
192
|
-
|| lower.includes('application/ecmascript');
|
|
193
|
-
}
|
|
194
|
-
function isSameOrChildPath(pathname, basePath) {
|
|
195
|
-
return pathname === basePath || pathname.startsWith(`${basePath}/`);
|
|
196
|
-
}
|
|
197
|
-
function getPathname(value) {
|
|
198
|
-
const end = value.search(/[?#]/);
|
|
199
|
-
return end === -1 ? value : value.slice(0, end);
|
|
200
|
-
}
|
|
201
|
-
function hasStaticFileExtension(pathname) {
|
|
202
|
-
const segment = pathname.split('/').pop() ?? '';
|
|
203
|
-
return /\.(?:avif|bmp|css|eot|gif|html?|ico|jpe?g|js|json|map|mjs|png|svg|ttf|txt|wasm|webp|woff2?)$/i.test(segment);
|
|
204
|
-
}
|
|
205
|
-
function shouldRewriteJavaScriptPath(value, prefix) {
|
|
206
|
-
if (!value.startsWith('/') || value.startsWith('//') || value === '/')
|
|
207
|
-
return false;
|
|
208
|
-
const pathname = getPathname(value);
|
|
209
|
-
if (isSameOrChildPath(pathname, prefix) || pathname.startsWith(`${PREVIEW_PREFIX}/`))
|
|
210
|
-
return false;
|
|
211
|
-
if (isSameOrChildPath(pathname, '/api')
|
|
212
|
-
|| isSameOrChildPath(pathname, '/socket.io')
|
|
213
|
-
|| isSameOrChildPath(pathname, '/ws')) {
|
|
214
|
-
return true;
|
|
215
|
-
}
|
|
216
|
-
if (isSameOrChildPath(pathname, '/assets'))
|
|
217
|
-
return true;
|
|
218
|
-
return hasStaticFileExtension(pathname);
|
|
219
|
-
}
|
|
220
|
-
function rewriteJavaScriptPathLiterals(body, prefix) {
|
|
221
|
-
return body.replace(/(["'`])\/(?!\/)([^"'`\r\n]*)\1/g, (match, quote, rest) => {
|
|
222
|
-
const value = `/${rest}`;
|
|
223
|
-
if (!shouldRewriteJavaScriptPath(value, prefix))
|
|
224
|
-
return match;
|
|
225
|
-
return `${quote}${prefix}${value}${quote}`;
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
function rewriteJavaScriptRouterBasenameDefaults(body, prefix) {
|
|
229
|
-
return body
|
|
230
|
-
.replace(/(\bbasename\s*:\s*[A-Za-z_$][\w$]*\s*=\s*)(["'`])\/\2/g, (_match, before, quote) => `${before}${quote}${prefix}${quote}`)
|
|
231
|
-
.replace(/(\bbasename\s*=\s*)(["'`])\/\2/g, (_match, before, quote) => `${before}${quote}${prefix}${quote}`)
|
|
232
|
-
.replace(/(\bbasename\s*:\s*)(["'`])\/\2/g, (_match, before, quote) => `${before}${quote}${prefix}${quote}`)
|
|
233
|
-
.replace(/(\b[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)?\.basename\s*\|\|\s*)(["'`])\/\2/g, (_match, before, quote) => `${before}${quote}${prefix}${quote}`)
|
|
234
|
-
.replace(/(\b[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)?\.basename\s*\?\?\s*)(["'`])\/\2/g, (_match, before, quote) => `${before}${quote}${prefix}${quote}`);
|
|
235
|
-
}
|
|
236
|
-
function injectPreviewRuntimeBridge(body, prefix, target) {
|
|
237
|
-
const script = `<script data-agent-tower-preview-bridge>(() => {
|
|
238
|
-
const prefix = ${JSON.stringify(prefix)};
|
|
239
|
-
const targetOrigin = ${JSON.stringify(target.origin)};
|
|
240
|
-
const targetBasePath = ${JSON.stringify(target.basePath)};
|
|
241
|
-
const loopbackHosts = new Set(['localhost', '127.0.0.1', '::1', '[::1]', '0.0.0.0']);
|
|
242
|
-
const normalizeProtocol = (protocol) => protocol === 'ws:' ? 'http:' : protocol === 'wss:' ? 'https:' : protocol;
|
|
243
|
-
const normalizeHost = (hostname) => loopbackHosts.has(hostname.toLowerCase()) ? 'loopback' : hostname.toLowerCase();
|
|
244
|
-
const effectivePort = (url) => url.port || (normalizeProtocol(url.protocol) === 'https:' ? '443' : '80');
|
|
245
|
-
const sameEndpoint = (left, right) => normalizeProtocol(left.protocol) === normalizeProtocol(right.protocol)
|
|
246
|
-
&& normalizeHost(left.hostname) === normalizeHost(right.hostname)
|
|
247
|
-
&& effectivePort(left) === effectivePort(right);
|
|
248
|
-
const isPrefixed = (pathname) => pathname === prefix || pathname.startsWith(prefix + '/');
|
|
249
|
-
const rewrite = (value) => {
|
|
250
|
-
if (value === undefined || value === null) return value;
|
|
251
|
-
const raw = value instanceof URL ? value.toString() : String(value);
|
|
252
|
-
let url;
|
|
253
|
-
try {
|
|
254
|
-
url = new URL(raw, window.location.href);
|
|
255
|
-
} catch {
|
|
256
|
-
return value;
|
|
257
|
-
}
|
|
258
|
-
if (isPrefixed(url.pathname)) return raw;
|
|
259
|
-
|
|
260
|
-
const browserUrl = new URL(window.location.href);
|
|
261
|
-
const localTarget = new URL(targetOrigin);
|
|
262
|
-
const isRootRelative = raw.startsWith('/') && !raw.startsWith('//');
|
|
263
|
-
const isBrowserEndpoint = sameEndpoint(url, browserUrl);
|
|
264
|
-
const isTargetEndpoint = sameEndpoint(url, localTarget);
|
|
265
|
-
if (!isRootRelative && !isTargetEndpoint) return value;
|
|
266
|
-
if (isBrowserEndpoint && !isRootRelative) return value;
|
|
267
|
-
|
|
268
|
-
let pathname = url.pathname;
|
|
269
|
-
if (isTargetEndpoint && targetBasePath) {
|
|
270
|
-
const underBasePath = pathname === targetBasePath || pathname.startsWith(targetBasePath + '/');
|
|
271
|
-
if (underBasePath) pathname = pathname.slice(targetBasePath.length) || '/';
|
|
272
|
-
}
|
|
273
|
-
const protocol = url.protocol === 'ws:' || url.protocol === 'wss:'
|
|
274
|
-
? (window.location.protocol === 'https:' ? 'wss:' : 'ws:')
|
|
275
|
-
: window.location.protocol;
|
|
276
|
-
return protocol + '//' + window.location.host + prefix + pathname + url.search + url.hash;
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
const nativePushState = History.prototype.pushState;
|
|
280
|
-
const nativeReplaceState = History.prototype.replaceState;
|
|
281
|
-
History.prototype.pushState = function(state, unused, url) {
|
|
282
|
-
return nativePushState.call(this, state, unused, url == null ? url : rewrite(url));
|
|
283
|
-
};
|
|
284
|
-
History.prototype.replaceState = function(state, unused, url) {
|
|
285
|
-
return nativeReplaceState.call(this, state, unused, url == null ? url : rewrite(url));
|
|
286
|
-
};
|
|
287
|
-
|
|
288
|
-
const nativeFetch = window.fetch.bind(window);
|
|
289
|
-
window.fetch = (input, init) => {
|
|
290
|
-
if (typeof input === 'string' || input instanceof URL) return nativeFetch(rewrite(input), init);
|
|
291
|
-
if (input instanceof Request) return nativeFetch(new Request(rewrite(input.url), input), init);
|
|
292
|
-
return nativeFetch(input, init);
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
const nativeXhrOpen = XMLHttpRequest.prototype.open;
|
|
296
|
-
XMLHttpRequest.prototype.open = function(method, url, ...rest) {
|
|
297
|
-
return nativeXhrOpen.call(this, method, rewrite(url), ...rest);
|
|
298
|
-
};
|
|
299
|
-
|
|
300
|
-
const NativeWebSocket = window.WebSocket;
|
|
301
|
-
function PreviewWebSocket(url, protocols) {
|
|
302
|
-
const nextUrl = rewrite(url);
|
|
303
|
-
return protocols === undefined ? new NativeWebSocket(nextUrl) : new NativeWebSocket(nextUrl, protocols);
|
|
304
|
-
}
|
|
305
|
-
PreviewWebSocket.prototype = NativeWebSocket.prototype;
|
|
306
|
-
Object.setPrototypeOf(PreviewWebSocket, NativeWebSocket);
|
|
307
|
-
window.WebSocket = PreviewWebSocket;
|
|
308
|
-
|
|
309
|
-
const NativeEventSource = window.EventSource;
|
|
310
|
-
if (NativeEventSource) {
|
|
311
|
-
function PreviewEventSource(url, options) {
|
|
312
|
-
return new NativeEventSource(rewrite(url), options);
|
|
313
|
-
}
|
|
314
|
-
PreviewEventSource.prototype = NativeEventSource.prototype;
|
|
315
|
-
Object.setPrototypeOf(PreviewEventSource, NativeEventSource);
|
|
316
|
-
window.EventSource = PreviewEventSource;
|
|
317
|
-
}
|
|
318
|
-
})();</script>`;
|
|
319
|
-
const head = /<head(?:\s[^>]*)?>/i;
|
|
320
|
-
if (head.test(body))
|
|
321
|
-
return body.replace(head, (match) => `${match}${script}`);
|
|
322
|
-
return `${script}${body}`;
|
|
323
|
-
}
|
|
324
|
-
export function rewritePreviewBody(body, workspaceId, contentType, previewToken, target) {
|
|
325
|
-
const prefix = buildPreviewPathPrefix(workspaceId, previewToken);
|
|
326
|
-
const value = Array.isArray(contentType) ? contentType.join(';') : contentType ?? '';
|
|
327
|
-
const lower = value.toLowerCase();
|
|
328
|
-
let next = body;
|
|
329
|
-
if (lower.includes('text/html')) {
|
|
330
|
-
next = next
|
|
331
|
-
.replace(/(\s(?:src|href|action|poster|data|content)=["'])\/(?!\/|view\/)([^"']*)/gi, `$1${prefix}/$2`)
|
|
332
|
-
.replace(/(\s(?:srcset)=["'])([^"']*)(["'])/gi, (_match, before, srcset, after) => {
|
|
333
|
-
const rewritten = srcset.replace(/(^|,\s*)\/(?!\/|view\/)([^\s,]+)/g, `$1${prefix}/$2`);
|
|
334
|
-
return `${before}${rewritten}${after}`;
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
if (lower.includes('text/css') || lower.includes('text/html')) {
|
|
338
|
-
next = next.replace(/url\((['"]?)\/(?!\/|view\/)([^)'"]+)\1\)/g, `url($1${prefix}/$2$1)`);
|
|
339
|
-
}
|
|
340
|
-
if (lower.includes('javascript') || lower.includes('ecmascript') || lower.includes('text/html')) {
|
|
341
|
-
next = rewriteJavaScriptRouterBasenameDefaults(next, prefix);
|
|
342
|
-
next = rewriteJavaScriptPathLiterals(next, prefix);
|
|
343
|
-
}
|
|
344
|
-
if (lower.includes('text/html') && target) {
|
|
345
|
-
next = injectPreviewRuntimeBridge(next, prefix, target);
|
|
346
|
-
}
|
|
347
|
-
return next;
|
|
348
|
-
}
|
|
349
58
|
function requestBodyBuffer(request) {
|
|
350
59
|
const method = request.method.toUpperCase();
|
|
351
60
|
if (method === 'GET' || method === 'HEAD')
|
|
@@ -359,180 +68,49 @@ function requestBodyBuffer(request) {
|
|
|
359
68
|
return Buffer.from(body);
|
|
360
69
|
return Buffer.from(JSON.stringify(body));
|
|
361
70
|
}
|
|
362
|
-
async function
|
|
363
|
-
const
|
|
364
|
-
if (
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
71
|
+
async function authorizeWebSocketUpgrade(req, socket, workspaceId, previewToken) {
|
|
72
|
+
const isTunnel = Boolean(req.headers['cf-connecting-ip'] || req.headers['cf-ray']);
|
|
73
|
+
if (isTunnel && TunnelService.isRunning()) {
|
|
74
|
+
const token = extractTunnelSessionTokenFromCookieHeader(req.headers.cookie);
|
|
75
|
+
if (!token || !TunnelService.validateToken(token)) {
|
|
76
|
+
writeUpgradeError(socket, 401, 'Unauthorized');
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
368
79
|
}
|
|
369
|
-
const
|
|
370
|
-
const
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
hostname: targetUrl.hostname,
|
|
378
|
-
port: targetUrl.port,
|
|
379
|
-
method: request.method,
|
|
380
|
-
path: targetPath,
|
|
381
|
-
headers,
|
|
382
|
-
rejectUnauthorized: false,
|
|
383
|
-
};
|
|
384
|
-
const transport = targetUrl.protocol === 'https:' ? https : http;
|
|
385
|
-
await new Promise((resolve) => {
|
|
386
|
-
const proxyReq = transport.request(options, (proxyRes) => {
|
|
387
|
-
const headers = proxyResponseHeaders(proxyRes.headers, workspaceId, target, request.headers, previewToken);
|
|
388
|
-
response.statusCode = proxyRes.statusCode ?? 502;
|
|
389
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
390
|
-
if (value !== undefined)
|
|
391
|
-
response.setHeader(key, value);
|
|
392
|
-
}
|
|
393
|
-
if (!isRewritableContent(proxyRes.headers['content-type'])) {
|
|
394
|
-
proxyRes.pipe(response);
|
|
395
|
-
proxyRes.on('end', resolve);
|
|
396
|
-
proxyRes.on('error', () => {
|
|
397
|
-
if (!response.headersSent)
|
|
398
|
-
response.writeHead(502);
|
|
399
|
-
response.end('Preview proxy response failed');
|
|
400
|
-
resolve();
|
|
401
|
-
});
|
|
402
|
-
return;
|
|
403
|
-
}
|
|
404
|
-
const chunks = [];
|
|
405
|
-
proxyRes.on('data', (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
406
|
-
proxyRes.on('end', () => {
|
|
407
|
-
const text = Buffer.concat(chunks).toString('utf8');
|
|
408
|
-
response.end(rewritePreviewBody(text, workspaceId, proxyRes.headers['content-type'], previewToken, target));
|
|
409
|
-
resolve();
|
|
410
|
-
});
|
|
411
|
-
proxyRes.on('error', () => {
|
|
412
|
-
if (!response.headersSent)
|
|
413
|
-
response.writeHead(502);
|
|
414
|
-
response.end('Preview proxy response failed');
|
|
415
|
-
resolve();
|
|
416
|
-
});
|
|
417
|
-
});
|
|
418
|
-
proxyReq.on('error', (err) => {
|
|
419
|
-
if (!response.headersSent) {
|
|
420
|
-
response.writeHead(502, { 'content-type': 'application/json' });
|
|
421
|
-
}
|
|
422
|
-
response.end(JSON.stringify({ error: err.message, code: 'PREVIEW_PROXY_ERROR' }));
|
|
423
|
-
resolve();
|
|
424
|
-
});
|
|
425
|
-
proxyReq.end(body ?? undefined);
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
function writeUpgradeError(socket, statusCode, message) {
|
|
429
|
-
if (socket.destroyed)
|
|
430
|
-
return;
|
|
431
|
-
socket.write(`HTTP/1.1 ${statusCode} ${message}\r\nConnection: close\r\n\r\n`);
|
|
432
|
-
socket.destroy();
|
|
433
|
-
}
|
|
434
|
-
function proxyWebSocketRequest(req, socket, head, workspaceId, target) {
|
|
435
|
-
const parsed = parsePreviewPath(req.url ?? '');
|
|
436
|
-
if (!parsed) {
|
|
437
|
-
writeUpgradeError(socket, 404, 'Not Found');
|
|
438
|
-
return;
|
|
80
|
+
const internalToken = req.headers[INTERNAL_API_TOKEN_HEADER];
|
|
81
|
+
const normalizedInternalToken = Array.isArray(internalToken) ? internalToken[0] : internalToken;
|
|
82
|
+
if (internalToken !== undefined) {
|
|
83
|
+
if (!validateInternalApiToken(normalizedInternalToken)) {
|
|
84
|
+
writeUpgradeError(socket, 401, 'Invalid Internal Token');
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
439
88
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
const options = {
|
|
450
|
-
protocol: targetUrl.protocol,
|
|
451
|
-
hostname: targetUrl.hostname,
|
|
452
|
-
port: targetUrl.port,
|
|
453
|
-
method: 'GET',
|
|
454
|
-
path: targetPath,
|
|
455
|
-
headers,
|
|
456
|
-
rejectUnauthorized: false,
|
|
457
|
-
};
|
|
458
|
-
const transport = targetUrl.protocol === 'https:' ? https : http;
|
|
459
|
-
const proxyReq = transport.request(options);
|
|
460
|
-
proxyReq.on('upgrade', (proxyRes, proxySocket, proxyHead) => {
|
|
461
|
-
const closeClient = () => {
|
|
462
|
-
if (!socket.destroyed)
|
|
463
|
-
socket.destroy();
|
|
464
|
-
};
|
|
465
|
-
const closeTarget = () => {
|
|
466
|
-
if (!proxySocket.destroyed)
|
|
467
|
-
proxySocket.destroy();
|
|
468
|
-
};
|
|
469
|
-
socket.once('close', closeTarget);
|
|
470
|
-
socket.once('error', closeTarget);
|
|
471
|
-
proxySocket.once('close', closeClient);
|
|
472
|
-
proxySocket.once('error', closeClient);
|
|
473
|
-
const headerLines = [
|
|
474
|
-
`HTTP/1.1 ${proxyRes.statusCode} ${proxyRes.statusMessage}`,
|
|
475
|
-
...Object.entries(proxyRes.headers).flatMap(([key, value]) => {
|
|
476
|
-
if (Array.isArray(value))
|
|
477
|
-
return value.map((item) => `${key}: ${item}`);
|
|
478
|
-
return value === undefined ? [] : [`${key}: ${value}`];
|
|
479
|
-
}),
|
|
480
|
-
'',
|
|
481
|
-
'',
|
|
482
|
-
];
|
|
483
|
-
socket.write(headerLines.join('\r\n'));
|
|
484
|
-
if (proxyHead.length > 0)
|
|
485
|
-
socket.write(proxyHead);
|
|
486
|
-
if (head.length > 0)
|
|
487
|
-
proxySocket.write(head);
|
|
488
|
-
proxySocket.pipe(socket);
|
|
489
|
-
socket.pipe(proxySocket);
|
|
490
|
-
});
|
|
491
|
-
proxyReq.on('response', (res) => {
|
|
492
|
-
writeUpgradeError(socket, res.statusCode ?? 502, res.statusMessage ?? 'Bad Gateway');
|
|
493
|
-
});
|
|
494
|
-
proxyReq.on('error', () => {
|
|
495
|
-
writeUpgradeError(socket, 502, 'Bad Gateway');
|
|
496
|
-
});
|
|
497
|
-
proxyReq.end();
|
|
89
|
+
if (previewToken && await AccessAuthService.validatePreviewAccessToken(previewToken, workspaceId)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
const accessToken = AccessAuthService.extractCookieFromHeader(req.headers.cookie);
|
|
93
|
+
if (!await AccessAuthService.validateSessionToken(accessToken)) {
|
|
94
|
+
writeUpgradeError(socket, 401, 'Unauthorized');
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
498
98
|
}
|
|
499
99
|
function registerPreviewWebSocketProxy(app, previewService) {
|
|
500
|
-
app.server.on('upgrade',
|
|
100
|
+
app.server.on('upgrade', (req, socket, head) => {
|
|
501
101
|
const parsed = parsePreviewPath(req.url ?? '');
|
|
502
102
|
if (!parsed)
|
|
503
103
|
return;
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
const token = extractTunnelSessionTokenFromCookieHeader(req.headers.cookie);
|
|
507
|
-
if (!token || !TunnelService.validateToken(token)) {
|
|
508
|
-
writeUpgradeError(socket, 401, 'Unauthorized');
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
const internalToken = req.headers[INTERNAL_API_TOKEN_HEADER];
|
|
513
|
-
const normalizedInternalToken = Array.isArray(internalToken) ? internalToken[0] : internalToken;
|
|
514
|
-
if (internalToken !== undefined) {
|
|
515
|
-
if (!validateInternalApiToken(normalizedInternalToken)) {
|
|
516
|
-
writeUpgradeError(socket, 401, 'Invalid Internal Token');
|
|
104
|
+
void (async () => {
|
|
105
|
+
if (!await authorizeWebSocketUpgrade(req, socket, parsed.workspaceId, parsed.previewToken))
|
|
517
106
|
return;
|
|
518
|
-
|
|
519
|
-
}
|
|
520
|
-
else if (!parsed.previewToken || !await AccessAuthService.validatePreviewAccessToken(parsed.previewToken, parsed.workspaceId)) {
|
|
521
|
-
const accessToken = AccessAuthService.extractCookieFromHeader(req.headers.cookie);
|
|
522
|
-
if (!await AccessAuthService.validateSessionToken(accessToken)) {
|
|
523
|
-
writeUpgradeError(socket, 401, 'Unauthorized');
|
|
524
|
-
return;
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
previewService.getTarget(parsed.workspaceId)
|
|
528
|
-
.then((target) => {
|
|
107
|
+
const target = await previewService.getTarget(parsed.workspaceId);
|
|
529
108
|
if (!target) {
|
|
530
109
|
writeUpgradeError(socket, 404, 'Not Found');
|
|
531
110
|
return;
|
|
532
111
|
}
|
|
533
|
-
|
|
534
|
-
})
|
|
535
|
-
.catch(() => {
|
|
112
|
+
proxyPreviewWebSocket(req, socket, head, { workspaceId: parsed.workspaceId, target, previewToken: parsed.previewToken }, parsed.suffix, parsed.search);
|
|
113
|
+
})().catch(() => {
|
|
536
114
|
writeUpgradeError(socket, 502, 'Bad Gateway');
|
|
537
115
|
});
|
|
538
116
|
});
|
|
@@ -546,12 +124,13 @@ export async function previewRoutes(app) {
|
|
|
546
124
|
};
|
|
547
125
|
const unregisterCleanup = registerApplicationProcessCleanup(cleanupPreview);
|
|
548
126
|
registerPreviewWebSocketProxy(app, previewService);
|
|
549
|
-
const
|
|
127
|
+
const gatewaySessionResponse = async (session) => {
|
|
550
128
|
const accessToken = await AccessAuthService.createPreviewAccessToken(session.workspaceId);
|
|
551
129
|
return {
|
|
552
130
|
id: session.id,
|
|
553
131
|
target: session.target,
|
|
554
|
-
mode:
|
|
132
|
+
mode: 'local',
|
|
133
|
+
kind: 'gateway',
|
|
555
134
|
viewUrl: addPreviewAccessToken(session.viewBaseUrl, accessToken),
|
|
556
135
|
expiresAt: session.expiresAt,
|
|
557
136
|
};
|
|
@@ -590,10 +169,15 @@ export async function previewRoutes(app) {
|
|
|
590
169
|
code: 'PREVIEW_NOT_CONFIGURED',
|
|
591
170
|
});
|
|
592
171
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
172
|
+
// Browsers that can only reach Agent Tower itself (tunnel, HTTPS reverse
|
|
173
|
+
// proxy, Docker) use the same-origin proxy; everything else gets a
|
|
174
|
+
// dedicated gateway origin on the Agent Tower host.
|
|
175
|
+
const sameOrigin = body.mode === 'remote' || isTunnelRequest(request) || forceSameOriginPreview();
|
|
176
|
+
if (sameOrigin) {
|
|
177
|
+
return sameOriginPreviewSession(request.params.workspaceId, target);
|
|
178
|
+
}
|
|
179
|
+
const session = await previewRuntimeManager.acquire(request.params.workspaceId, target, body.localHostname);
|
|
180
|
+
return await gatewaySessionResponse(session);
|
|
597
181
|
}
|
|
598
182
|
catch (err) {
|
|
599
183
|
return errorResponse(err, reply);
|
|
@@ -601,6 +185,16 @@ export async function previewRoutes(app) {
|
|
|
601
185
|
});
|
|
602
186
|
app.post('/api/previews/:workspaceId/sessions/:sessionId/heartbeat', async (request, reply) => {
|
|
603
187
|
try {
|
|
188
|
+
if (request.params.sessionId === SAME_ORIGIN_PREVIEW_SESSION_ID) {
|
|
189
|
+
const target = await previewService.getTarget(request.params.workspaceId);
|
|
190
|
+
if (!target) {
|
|
191
|
+
return reply.code(404).send({
|
|
192
|
+
error: 'Preview target is not configured',
|
|
193
|
+
code: 'PREVIEW_NOT_CONFIGURED',
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return sameOriginPreviewSession(request.params.workspaceId, target);
|
|
197
|
+
}
|
|
604
198
|
const session = await previewRuntimeManager.heartbeat(request.params.workspaceId, request.params.sessionId);
|
|
605
199
|
if (!session) {
|
|
606
200
|
return reply.code(404).send({
|
|
@@ -608,49 +202,76 @@ export async function previewRoutes(app) {
|
|
|
608
202
|
code: 'PREVIEW_SESSION_EXPIRED',
|
|
609
203
|
});
|
|
610
204
|
}
|
|
611
|
-
return
|
|
205
|
+
return await gatewaySessionResponse(session);
|
|
612
206
|
}
|
|
613
207
|
catch (err) {
|
|
614
208
|
return errorResponse(err, reply);
|
|
615
209
|
}
|
|
616
210
|
});
|
|
617
211
|
app.delete('/api/previews/:workspaceId/sessions/:sessionId', async (request, reply) => {
|
|
618
|
-
|
|
212
|
+
if (request.params.sessionId !== SAME_ORIGIN_PREVIEW_SESSION_ID) {
|
|
213
|
+
previewRuntimeManager.release(request.params.workspaceId, request.params.sessionId);
|
|
214
|
+
}
|
|
619
215
|
return reply.code(204).send();
|
|
620
216
|
});
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
217
|
+
// The proxy must forward request bodies of any content type untouched.
|
|
218
|
+
await app.register(async (proxyApp) => {
|
|
219
|
+
proxyApp.removeAllContentTypeParsers();
|
|
220
|
+
proxyApp.addContentTypeParser('*', { parseAs: 'buffer', bodyLimit: PROXY_BODY_LIMIT_BYTES }, (_request, body, done) => {
|
|
221
|
+
done(null, body);
|
|
222
|
+
});
|
|
223
|
+
const handler = async (request, reply) => {
|
|
224
|
+
const parsed = parsePreviewPath(request.raw.url ?? '');
|
|
225
|
+
if (!parsed)
|
|
226
|
+
return reply.code(404).send({ error: 'Preview route not found', code: 'NOT_FOUND' });
|
|
227
|
+
try {
|
|
228
|
+
const target = await previewService.getTarget(parsed.workspaceId);
|
|
229
|
+
if (!target) {
|
|
230
|
+
return reply.code(404).send({ error: 'Preview target is not configured', code: 'PREVIEW_NOT_CONFIGURED' });
|
|
231
|
+
}
|
|
232
|
+
const scope = {
|
|
233
|
+
workspaceId: parsed.workspaceId,
|
|
234
|
+
target,
|
|
235
|
+
previewToken: parsed.previewToken,
|
|
236
|
+
};
|
|
237
|
+
const context = classifyPreviewRequest(request.method, request.headers, parsed.search);
|
|
238
|
+
reply.hijack();
|
|
239
|
+
if (request.method.toUpperCase() === 'GET' && previewServiceWorkerSegment(parsed.suffix)) {
|
|
240
|
+
writeServiceWorkerScript(reply.raw);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (shouldServeBootstrap(context, request.method)) {
|
|
244
|
+
writeBootstrapPage(reply.raw, scope);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
await proxyPreviewHttpRequest({
|
|
248
|
+
request: request.raw,
|
|
249
|
+
response: reply.raw,
|
|
250
|
+
scope,
|
|
251
|
+
suffix: parsed.suffix,
|
|
252
|
+
search: parsed.search,
|
|
253
|
+
context,
|
|
254
|
+
body: requestBodyBuffer(request),
|
|
255
|
+
});
|
|
631
256
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
257
|
+
catch (err) {
|
|
258
|
+
if (!reply.sent)
|
|
259
|
+
return errorResponse(err, reply);
|
|
260
|
+
reply.raw.end();
|
|
635
261
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
});
|
|
650
|
-
app.route({
|
|
651
|
-
method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'],
|
|
652
|
-
url: '/view/:workspaceId/*',
|
|
653
|
-
handler,
|
|
262
|
+
};
|
|
263
|
+
proxyApp.route({
|
|
264
|
+
method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'],
|
|
265
|
+
url: '/view/:workspaceId',
|
|
266
|
+
bodyLimit: PROXY_BODY_LIMIT_BYTES,
|
|
267
|
+
handler,
|
|
268
|
+
});
|
|
269
|
+
proxyApp.route({
|
|
270
|
+
method: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS', 'HEAD'],
|
|
271
|
+
url: '/view/:workspaceId/*',
|
|
272
|
+
bodyLimit: PROXY_BODY_LIMIT_BYTES,
|
|
273
|
+
handler,
|
|
274
|
+
});
|
|
654
275
|
});
|
|
655
276
|
}
|
|
656
277
|
//# sourceMappingURL=previews.js.map
|