agent-tower 0.7.4 → 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.
Files changed (365) hide show
  1. package/dist/app.d.ts.map +1 -1
  2. package/dist/app.js +6 -1
  3. package/dist/app.js.map +1 -1
  4. package/dist/core/container.d.ts +2 -0
  5. package/dist/core/container.d.ts.map +1 -1
  6. package/dist/core/container.js +25 -0
  7. package/dist/core/container.js.map +1 -1
  8. package/dist/executors/__tests__/base.executor.test.js +19 -0
  9. package/dist/executors/__tests__/base.executor.test.js.map +1 -1
  10. package/dist/executors/__tests__/claude-code-mcp.test.d.ts +2 -0
  11. package/dist/executors/__tests__/claude-code-mcp.test.d.ts.map +1 -0
  12. package/dist/executors/__tests__/claude-code-mcp.test.js +211 -0
  13. package/dist/executors/__tests__/claude-code-mcp.test.js.map +1 -0
  14. package/dist/executors/__tests__/codex-mcp-windows.test.d.ts +2 -0
  15. package/dist/executors/__tests__/codex-mcp-windows.test.d.ts.map +1 -0
  16. package/dist/executors/__tests__/codex-mcp-windows.test.js +128 -0
  17. package/dist/executors/__tests__/codex-mcp-windows.test.js.map +1 -0
  18. package/dist/executors/__tests__/codex.executor.test.js +394 -1
  19. package/dist/executors/__tests__/codex.executor.test.js.map +1 -1
  20. package/dist/executors/base.executor.d.ts.map +1 -1
  21. package/dist/executors/base.executor.js +13 -0
  22. package/dist/executors/base.executor.js.map +1 -1
  23. package/dist/executors/claude-code.executor.d.ts +1 -0
  24. package/dist/executors/claude-code.executor.d.ts.map +1 -1
  25. package/dist/executors/claude-code.executor.js +52 -3
  26. package/dist/executors/claude-code.executor.js.map +1 -1
  27. package/dist/executors/codex.executor.d.ts +6 -6
  28. package/dist/executors/codex.executor.d.ts.map +1 -1
  29. package/dist/executors/codex.executor.js +118 -32
  30. package/dist/executors/codex.executor.js.map +1 -1
  31. package/dist/git/worktree.manager.d.ts.map +1 -1
  32. package/dist/git/worktree.manager.js +5 -2
  33. package/dist/git/worktree.manager.js.map +1 -1
  34. package/dist/mcp/http-client.d.ts +8 -1
  35. package/dist/mcp/http-client.d.ts.map +1 -1
  36. package/dist/mcp/http-client.js +6 -0
  37. package/dist/mcp/http-client.js.map +1 -1
  38. package/dist/mcp/tools/__tests__/workspace-services.test.js +34 -1
  39. package/dist/mcp/tools/__tests__/workspace-services.test.js.map +1 -1
  40. package/dist/mcp/tools/tasks.js +1 -1
  41. package/dist/mcp/tools/tasks.js.map +1 -1
  42. package/dist/mcp/tools/workspace-services.d.ts.map +1 -1
  43. package/dist/mcp/tools/workspace-services.js +39 -2
  44. package/dist/mcp/tools/workspace-services.js.map +1 -1
  45. package/dist/mcp/types.d.ts +20 -0
  46. package/dist/mcp/types.d.ts.map +1 -1
  47. package/dist/mcp/types.js +12 -0
  48. package/dist/mcp/types.js.map +1 -1
  49. package/dist/middleware/__tests__/preview-fallback.test.d.ts +2 -0
  50. package/dist/middleware/__tests__/preview-fallback.test.d.ts.map +1 -0
  51. package/dist/middleware/__tests__/preview-fallback.test.js +93 -0
  52. package/dist/middleware/__tests__/preview-fallback.test.js.map +1 -0
  53. package/dist/middleware/preview-fallback.d.ts +5 -0
  54. package/dist/middleware/preview-fallback.d.ts.map +1 -0
  55. package/dist/middleware/preview-fallback.js +91 -0
  56. package/dist/middleware/preview-fallback.js.map +1 -0
  57. package/dist/output/__tests__/claude-code-parser-continuation.test.d.ts +2 -0
  58. package/dist/output/__tests__/claude-code-parser-continuation.test.d.ts.map +1 -0
  59. package/dist/output/__tests__/claude-code-parser-continuation.test.js +89 -0
  60. package/dist/output/__tests__/claude-code-parser-continuation.test.js.map +1 -0
  61. package/dist/output/__tests__/claude-code-parser-lifecycle.test.js +4 -1
  62. package/dist/output/__tests__/claude-code-parser-lifecycle.test.js.map +1 -1
  63. package/dist/output/claude-code-parser.d.ts +36 -1
  64. package/dist/output/claude-code-parser.d.ts.map +1 -1
  65. package/dist/output/claude-code-parser.js +149 -18
  66. package/dist/output/claude-code-parser.js.map +1 -1
  67. package/dist/output/types.d.ts +2 -0
  68. package/dist/output/types.d.ts.map +1 -1
  69. package/dist/output/types.js.map +1 -1
  70. package/dist/prompts/workspace-background-service-policy.d.ts +6 -2
  71. package/dist/prompts/workspace-background-service-policy.d.ts.map +1 -1
  72. package/dist/prompts/workspace-background-service-policy.js +12 -3
  73. package/dist/prompts/workspace-background-service-policy.js.map +1 -1
  74. package/dist/prompts/workspace-background-service-policy.test.js +11 -0
  75. package/dist/prompts/workspace-background-service-policy.test.js.map +1 -1
  76. package/dist/routes/__tests__/previews.integration.test.js +117 -6
  77. package/dist/routes/__tests__/previews.integration.test.js.map +1 -1
  78. package/dist/routes/__tests__/previews.test.js +223 -194
  79. package/dist/routes/__tests__/previews.test.js.map +1 -1
  80. package/dist/routes/__tests__/task-handoff.test.js +25 -16
  81. package/dist/routes/__tests__/task-handoff.test.js.map +1 -1
  82. package/dist/routes/index.d.ts.map +1 -1
  83. package/dist/routes/index.js +3 -0
  84. package/dist/routes/index.js.map +1 -1
  85. package/dist/routes/previews.d.ts +11 -9
  86. package/dist/routes/previews.d.ts.map +1 -1
  87. package/dist/routes/previews.js +137 -516
  88. package/dist/routes/previews.js.map +1 -1
  89. package/dist/routes/session-wakeups.d.ts +7 -0
  90. package/dist/routes/session-wakeups.d.ts.map +1 -0
  91. package/dist/routes/session-wakeups.js +86 -0
  92. package/dist/routes/session-wakeups.js.map +1 -0
  93. package/dist/routes/tasks.d.ts.map +1 -1
  94. package/dist/routes/tasks.js +3 -1
  95. package/dist/routes/tasks.js.map +1 -1
  96. package/dist/runtime/__tests__/acp-process-manager.test.js +65 -0
  97. package/dist/runtime/__tests__/acp-process-manager.test.js.map +1 -1
  98. package/dist/runtime/__tests__/claude-cli-driver.test.js +96 -2
  99. package/dist/runtime/__tests__/claude-cli-driver.test.js.map +1 -1
  100. package/dist/runtime/__tests__/claude-run-lifecycle.test.d.ts +2 -0
  101. package/dist/runtime/__tests__/claude-run-lifecycle.test.d.ts.map +1 -0
  102. package/dist/runtime/__tests__/claude-run-lifecycle.test.js +88 -0
  103. package/dist/runtime/__tests__/claude-run-lifecycle.test.js.map +1 -0
  104. package/dist/runtime/__tests__/cli-driver-lifecycle.test.js +14 -7
  105. package/dist/runtime/__tests__/cli-driver-lifecycle.test.js.map +1 -1
  106. package/dist/runtime/acp/agents/pi-coding-agent.d.ts.map +1 -1
  107. package/dist/runtime/acp/agents/pi-coding-agent.js +3 -0
  108. package/dist/runtime/acp/agents/pi-coding-agent.js.map +1 -1
  109. package/dist/runtime/claude-run-lifecycle.d.ts +77 -0
  110. package/dist/runtime/claude-run-lifecycle.d.ts.map +1 -0
  111. package/dist/runtime/claude-run-lifecycle.js +147 -0
  112. package/dist/runtime/claude-run-lifecycle.js.map +1 -0
  113. package/dist/runtime/cli-driver.d.ts.map +1 -1
  114. package/dist/runtime/cli-driver.js +89 -3
  115. package/dist/runtime/cli-driver.js.map +1 -1
  116. package/dist/runtime/contracts.d.ts +6 -1
  117. package/dist/runtime/contracts.d.ts.map +1 -1
  118. package/dist/runtime/process-scope/__tests__/process-scope.test.d.ts +2 -0
  119. package/dist/runtime/process-scope/__tests__/process-scope.test.d.ts.map +1 -0
  120. package/dist/runtime/process-scope/__tests__/process-scope.test.js +156 -0
  121. package/dist/runtime/process-scope/__tests__/process-scope.test.js.map +1 -0
  122. package/dist/runtime/process-scope/process-scope.d.ts +46 -0
  123. package/dist/runtime/process-scope/process-scope.d.ts.map +1 -0
  124. package/dist/runtime/process-scope/process-scope.js +68 -0
  125. package/dist/runtime/process-scope/process-scope.js.map +1 -0
  126. package/dist/runtime/process-scope/scope-helper.d.ts +28 -0
  127. package/dist/runtime/process-scope/scope-helper.d.ts.map +1 -0
  128. package/dist/runtime/process-scope/scope-helper.js +78 -0
  129. package/dist/runtime/process-scope/scope-helper.js.map +1 -0
  130. package/dist/runtime/runtime-coordinator.d.ts.map +1 -1
  131. package/dist/runtime/runtime-coordinator.js +6 -0
  132. package/dist/runtime/runtime-coordinator.js.map +1 -1
  133. package/dist/services/__tests__/preview-runtime-manager.test.js +13 -112
  134. package/dist/services/__tests__/preview-runtime-manager.test.js.map +1 -1
  135. package/dist/services/__tests__/preview.service.test.js +13 -14
  136. package/dist/services/__tests__/preview.service.test.js.map +1 -1
  137. package/dist/services/__tests__/session-manager.lifecycle.test.js +147 -1
  138. package/dist/services/__tests__/session-manager.lifecycle.test.js.map +1 -1
  139. package/dist/services/__tests__/session-wakeup.service.test.d.ts +2 -0
  140. package/dist/services/__tests__/session-wakeup.service.test.d.ts.map +1 -0
  141. package/dist/services/__tests__/session-wakeup.service.test.js +173 -0
  142. package/dist/services/__tests__/session-wakeup.service.test.js.map +1 -0
  143. package/dist/services/__tests__/terminal-manager.test.js +129 -51
  144. package/dist/services/__tests__/terminal-manager.test.js.map +1 -1
  145. package/dist/services/__tests__/workspace.service.test.js +31 -0
  146. package/dist/services/__tests__/workspace.service.test.js.map +1 -1
  147. package/dist/services/message-delivery.service.d.ts +3 -2
  148. package/dist/services/message-delivery.service.d.ts.map +1 -1
  149. package/dist/services/message-delivery.service.js +11 -7
  150. package/dist/services/message-delivery.service.js.map +1 -1
  151. package/dist/services/preview-bridge.d.ts +50 -0
  152. package/dist/services/preview-bridge.d.ts.map +1 -0
  153. package/dist/services/preview-bridge.js +537 -0
  154. package/dist/services/preview-bridge.js.map +1 -0
  155. package/dist/services/preview-cookies.d.ts +28 -0
  156. package/dist/services/preview-cookies.d.ts.map +1 -0
  157. package/dist/services/preview-cookies.js +133 -0
  158. package/dist/services/preview-cookies.js.map +1 -0
  159. package/dist/services/preview-proxy.d.ts +71 -0
  160. package/dist/services/preview-proxy.d.ts.map +1 -0
  161. package/dist/services/preview-proxy.js +462 -0
  162. package/dist/services/preview-proxy.js.map +1 -0
  163. package/dist/services/preview-runtime-manager.d.ts +11 -25
  164. package/dist/services/preview-runtime-manager.d.ts.map +1 -1
  165. package/dist/services/preview-runtime-manager.js +46 -363
  166. package/dist/services/preview-runtime-manager.js.map +1 -1
  167. package/dist/services/preview.service.d.ts.map +1 -1
  168. package/dist/services/preview.service.js +11 -9
  169. package/dist/services/preview.service.js.map +1 -1
  170. package/dist/services/project.service.d.ts +13 -13
  171. package/dist/services/session-manager.d.ts +2 -0
  172. package/dist/services/session-manager.d.ts.map +1 -1
  173. package/dist/services/session-manager.js +4 -2
  174. package/dist/services/session-manager.js.map +1 -1
  175. package/dist/services/session-wakeup.service.d.ts +105 -0
  176. package/dist/services/session-wakeup.service.d.ts.map +1 -0
  177. package/dist/services/session-wakeup.service.js +319 -0
  178. package/dist/services/session-wakeup.service.js.map +1 -0
  179. package/dist/services/task-handoff.service.d.ts +3 -2
  180. package/dist/services/task-handoff.service.d.ts.map +1 -1
  181. package/dist/services/task-handoff.service.js +7 -6
  182. package/dist/services/task-handoff.service.js.map +1 -1
  183. package/dist/services/team-room-delivery.d.ts +4 -4
  184. package/dist/services/terminal-manager.d.ts +16 -0
  185. package/dist/services/terminal-manager.d.ts.map +1 -1
  186. package/dist/services/terminal-manager.js +64 -7
  187. package/dist/services/terminal-manager.js.map +1 -1
  188. package/dist/services/workspace-background-service.service.d.ts +15 -1
  189. package/dist/services/workspace-background-service.service.d.ts.map +1 -1
  190. package/dist/services/workspace-background-service.service.js +41 -2
  191. package/dist/services/workspace-background-service.service.js.map +1 -1
  192. package/dist/services/workspace.service.d.ts.map +1 -1
  193. package/dist/services/workspace.service.js +2 -1
  194. package/dist/services/workspace.service.js.map +1 -1
  195. package/dist/utils/database-schema.d.ts.map +1 -1
  196. package/dist/utils/database-schema.js +9 -4
  197. package/dist/utils/database-schema.js.map +1 -1
  198. package/dist/utils/database-schema.test.js +21 -0
  199. package/dist/utils/database-schema.test.js.map +1 -1
  200. package/dist/utils/owned-child-process.d.ts +32 -3
  201. package/dist/utils/owned-child-process.d.ts.map +1 -1
  202. package/dist/utils/owned-child-process.js +138 -1
  203. package/dist/utils/owned-child-process.js.map +1 -1
  204. package/dist/web/assets/{AgentDemoPage-D9bIiALx.js → AgentDemoPage-D6clLNZx.js} +1 -1
  205. package/dist/web/assets/{AgentEnvironmentSettingsPage-BE0RC6fR.js → AgentEnvironmentSettingsPage-O1hlpsgp.js} +1 -1
  206. package/dist/web/assets/AttachmentPreview-hD3g_T_y.js +2 -0
  207. package/dist/web/assets/{BranchSelect-Kv3M1YhZ.js → BranchSelect-BkuXnEG2.js} +1 -1
  208. package/dist/web/assets/{BrandLogo-fR2lCwEo.js → BrandLogo-BSwQa2SF.js} +1 -1
  209. package/dist/web/assets/{ConversationPage-BZiMHI9T.js → ConversationPage-DvWjqFF2.js} +1 -1
  210. package/dist/web/assets/CreateTaskInput-Bric0GeW.js +1 -0
  211. package/dist/web/assets/{DemoPage-DwpThe16.js → DemoPage-Cwy3EmOm.js} +1 -1
  212. package/dist/web/assets/{DesignSystemPage-DH9_cygJ.js → DesignSystemPage-C1HrGwpV.js} +1 -1
  213. package/dist/web/assets/{ExecutionPermissionSelector-C-akTOVg.js → ExecutionPermissionSelector-BgrxbvBB.js} +1 -1
  214. package/dist/web/assets/{GeneralSettingsPage-v2w1eofz.js → GeneralSettingsPage-qdeAdBkW.js} +1 -1
  215. package/dist/web/assets/{LoadingPreviewPage-pgk3PWM9.js → LoadingPreviewPage-qeZ8nuiQ.js} +1 -1
  216. package/dist/web/assets/{McpSettingsPage-w1DOlY5V.js → McpSettingsPage-Bo-auo0X.js} +1 -1
  217. package/dist/web/assets/{MemberAvatar-CJtylxwu.js → MemberAvatar-DBab_9EO.js} +1 -1
  218. package/dist/web/assets/{MobileTaskDetail-D5Czlr2O.js → MobileTaskDetail-Dm64ie99.js} +2 -2
  219. package/dist/web/assets/{NotificationSettingsPage-CkLg4WvT.js → NotificationSettingsPage-BVJpo76k.js} +1 -1
  220. package/dist/web/assets/{ProfileSettingsPage-B3yzbY1V.js → ProfileSettingsPage-CbSRYGcp.js} +1 -1
  221. package/dist/web/assets/{ProjectKanbanPage-CuGSLvrU.js → ProjectKanbanPage-Cp3rdFik.js} +6 -6
  222. package/dist/web/assets/{ProjectSettingsPage-DoklOfna.js → ProjectSettingsPage-DLs5-Gk3.js} +1 -1
  223. package/dist/web/assets/{ProviderSettingsPage-Cm0hbX5n.js → ProviderSettingsPage-BnBcgAMQ.js} +1 -1
  224. package/dist/web/assets/{SettingsMasterDetail-CGCUalkW.js → SettingsMasterDetail-fu-_yejj.js} +1 -1
  225. package/dist/web/assets/{TaskDetail-BiZbuXcE.js → TaskDetail-C2_Fg59e.js} +1 -1
  226. package/dist/web/assets/TaskHandoffPanel-3Y0gcjyN.js +70 -0
  227. package/dist/web/assets/{TeamSettingsPage-CyppRTaY.js → TeamSettingsPage-CAjitaBe.js} +1 -1
  228. package/dist/web/assets/{TranslationSettingsPage-BoQXEZmn.js → TranslationSettingsPage-DKD6Uw2F.js} +1 -1
  229. package/dist/web/assets/{arc-5NPBSbiL.js → arc-BiuUFTzU.js} +1 -1
  230. package/dist/web/assets/{architectureDiagram-3BPJPVTR-CqPT-IsX.js → architectureDiagram-3BPJPVTR-Dcwk905A.js} +1 -1
  231. package/dist/web/assets/{at-sign-Cf39WHCg.js → at-sign-CZAKOH3i.js} +1 -1
  232. package/dist/web/assets/{blockDiagram-GPEHLZMM-BN-1z9KN.js → blockDiagram-GPEHLZMM-Cfc5JDN-.js} +1 -1
  233. package/dist/web/assets/{c4Diagram-AAUBKEIU-CkeLbmQp.js → c4Diagram-AAUBKEIU-B4v5PUdt.js} +1 -1
  234. package/dist/web/assets/channel-DThSYkmR.js +1 -0
  235. package/dist/web/assets/check-C3vuSPKz.js +1 -0
  236. package/dist/web/assets/{chevron-down-Ct7FZbKm.js → chevron-down-CtAk9uZw.js} +1 -1
  237. package/dist/web/assets/{chevron-up-ARFlXMyO.js → chevron-up-DAc3NX1J.js} +1 -1
  238. package/dist/web/assets/{chip-BV_1-tIb.js → chip-CDUNxQW2.js} +1 -1
  239. package/dist/web/assets/{chunk-2J33WTMH-CWR7tRuT.js → chunk-2J33WTMH-BYRdUeyt.js} +1 -1
  240. package/dist/web/assets/{chunk-4BX2VUAB-CAulp4D5.js → chunk-4BX2VUAB-3si_kPmV.js} +1 -1
  241. package/dist/web/assets/{chunk-55IACEB6-DqkKXsbD.js → chunk-55IACEB6-JiMm9u33.js} +1 -1
  242. package/dist/web/assets/{chunk-727SXJPM-B19m45Sq.js → chunk-727SXJPM-CMCFIUyF.js} +1 -1
  243. package/dist/web/assets/{chunk-AQP2D5EJ-CuODwkza.js → chunk-AQP2D5EJ-CzvnZjH5.js} +1 -1
  244. package/dist/web/assets/{chunk-FMBD7UC4-CbUAjtCT.js → chunk-FMBD7UC4-hsabZkPl.js} +1 -1
  245. package/dist/web/assets/{chunk-ND2GUHAM-C54VxArl.js → chunk-ND2GUHAM-D2o-Reeo.js} +1 -1
  246. package/dist/web/assets/{chunk-QZHKN3VN-D54Uw5fD.js → chunk-QZHKN3VN-ASJk-E7d.js} +1 -1
  247. package/dist/web/assets/classDiagram-4FO5ZUOK-CjJqgIpK.js +1 -0
  248. package/dist/web/assets/classDiagram-v2-Q7XG4LA2-CjJqgIpK.js +1 -0
  249. package/dist/web/assets/{code-block-OCS4YCEC-CtAySD1h.js → code-block-OCS4YCEC-5bkFBowa.js} +1 -1
  250. package/dist/web/assets/{confirm-dialog-CCjHVFTv.js → confirm-dialog-Bs80kXB9.js} +1 -1
  251. package/dist/web/assets/{content-DZozZbBD.js → content-DAccroCT.js} +1 -1
  252. package/dist/web/assets/{copy-C-jvx2et.js → copy-D1XK3OqK.js} +1 -1
  253. package/dist/web/assets/{cose-bilkent-S5V4N54A-BaB2EVcU.js → cose-bilkent-S5V4N54A-C52UKnOd.js} +1 -1
  254. package/dist/web/assets/{cssMode-wd7JR1S4.js → cssMode-BFq_c5xU.js} +1 -1
  255. package/dist/web/assets/{dagre-BM42HDAG-C2j1Y8pO.js → dagre-BM42HDAG-CeEute93.js} +1 -1
  256. package/dist/web/assets/{diagram-2AECGRRQ-CF-EvpV9.js → diagram-2AECGRRQ-CEcq4W4S.js} +1 -1
  257. package/dist/web/assets/{diagram-5GNKFQAL-rBNso835.js → diagram-5GNKFQAL-DqQe7Rr7.js} +1 -1
  258. package/dist/web/assets/{diagram-KO2AKTUF-6NW-oos1.js → diagram-KO2AKTUF-C1KVZphS.js} +1 -1
  259. package/dist/web/assets/{diagram-LMA3HP47-DTfRxRLT.js → diagram-LMA3HP47-D1BL7GQh.js} +1 -1
  260. package/dist/web/assets/{diagram-OG6HWLK6-CS4Ae-hD.js → diagram-OG6HWLK6-ngyXooqC.js} +1 -1
  261. package/dist/web/assets/{dialog-DV4wfpNU.js → dialog-XkZ8wMQa.js} +1 -1
  262. package/dist/web/assets/{erDiagram-TEJ5UH35-Dw9QQctN.js → erDiagram-TEJ5UH35-D1zIFVqE.js} +1 -1
  263. package/dist/web/assets/{file-Btui_I8Z.js → file-CXCll7Pm.js} +1 -1
  264. package/dist/web/assets/{flowDiagram-I6XJVG4X-BGZ9q86S.js → flowDiagram-I6XJVG4X-BZu49qcj.js} +1 -1
  265. package/dist/web/assets/{folder-picker-DiR-8Qdl.js → folder-picker-CVkaEJEL.js} +1 -1
  266. package/dist/web/assets/{freemarker2-yVWXzD3l.js → freemarker2-CmhadAeB.js} +1 -1
  267. package/dist/web/assets/{ganttDiagram-6RSMTGT7-CkGun0no.js → ganttDiagram-6RSMTGT7-eJ8yBxfS.js} +1 -1
  268. package/dist/web/assets/{gitGraphDiagram-PVQCEYII-Bz3oiYvi.js → gitGraphDiagram-PVQCEYII-DpeUUyH_.js} +1 -1
  269. package/dist/web/assets/{globe-DAFqpAcW.js → globe-WnxN1JzY.js} +1 -1
  270. package/dist/web/assets/{handlebars-BPf0z6eN.js → handlebars-DtjmH1qR.js} +1 -1
  271. package/dist/web/assets/{html-HCTCjfUg.js → html-DOYAlzlD.js} +1 -1
  272. package/dist/web/assets/{htmlMode-BDkbsknt.js → htmlMode-ORxd7KRN.js} +1 -1
  273. package/dist/web/assets/{index-BMcLxIvZ.js → index-6mINSZng.js} +1 -1
  274. package/dist/web/assets/{index-BPqjxXmH.js → index-BrjvxKaf.js} +1 -1
  275. package/dist/web/assets/{index-B8xoIIa6.js → index-CqIyOiVN.js} +4 -4
  276. package/dist/web/assets/{index-DgUtx9rV.js → index-D9w1zMaz.js} +1 -1
  277. package/dist/web/assets/{index-DkSPjZm4.js → index-DHDgbH3t.js} +1 -1
  278. package/dist/web/assets/{index-BszkzNS4.js → index-Dz9SKopM.js} +13 -13
  279. package/dist/web/assets/{index-GuczxPxb.js → index-eIXz5Hbk.js} +1 -1
  280. package/dist/web/assets/{index-DuM6iAxG.js → index-iOIxdF6J.js} +1 -1
  281. package/dist/web/assets/{index-lZLy5rkr.js → index-wbMiSmsY.js} +1 -1
  282. package/dist/web/assets/{infoDiagram-5YYISTIA-DYFufUYC.js → infoDiagram-5YYISTIA-BiVrC__7.js} +1 -1
  283. package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-IOkrKRwu.js → ishikawaDiagram-YF4QCWOH-B1kPjO1J.js} +1 -1
  284. package/dist/web/assets/javascript-CHlWHrtz.js +1 -0
  285. package/dist/web/assets/{journeyDiagram-JHISSGLW-Btl3yxne.js → journeyDiagram-JHISSGLW-DoTAPPAQ.js} +1 -1
  286. package/dist/web/assets/{jsonMode-DJPdvFcw.js → jsonMode-BkeQ_C6g.js} +1 -1
  287. package/dist/web/assets/{kanban-definition-UN3LZRKU-CDryhPbA.js → kanban-definition-UN3LZRKU-CBRmLcce.js} +1 -1
  288. package/dist/web/assets/{kbd-8RRRm9jd.js → kbd-CTfS0G5-.js} +1 -1
  289. package/dist/web/assets/{key-round-wojrCrDP.js → key-round-B7gTfpDR.js} +1 -1
  290. package/dist/web/assets/{layers-BH_LL4b8.js → layers-DE0xXedq.js} +1 -1
  291. package/dist/web/assets/{linear-BLuwKHze.js → linear-VLiA8Vcw.js} +1 -1
  292. package/dist/web/assets/{link-jWQOSQOQ.js → link-BSE_nRDT.js} +1 -1
  293. package/dist/web/assets/{liquid-1y-xg637.js → liquid-BZeg6p1K.js} +1 -1
  294. package/dist/web/assets/{lspLanguageFeatures-cYkILdCn.js → lspLanguageFeatures-CuFQ2_f9.js} +1 -1
  295. package/dist/web/assets/{mdx-CRg4Q6aP.js → mdx-C7xLyFFX.js} +1 -1
  296. package/dist/web/assets/{menu-CMqbaDni.js → menu-Dp4RDxvP.js} +1 -1
  297. package/dist/web/assets/{mermaid-NOHMQCX5-CYeAhOl-.js → mermaid-NOHMQCX5-C2enCJxR.js} +62 -62
  298. package/dist/web/assets/{message-square-DykJ2lWP.js → message-square-4lyHjyHe.js} +1 -1
  299. package/dist/web/assets/{mindmap-definition-RKZ34NQL-B5wtw1Rv.js → mindmap-definition-RKZ34NQL-C1OOtqma.js} +1 -1
  300. package/dist/web/assets/{modal-BwOwTzij.js → modal-BGglpgrR.js} +1 -1
  301. package/dist/web/assets/{monaco-CcHqpOKe.js → monaco-B-6VmJO0.js} +3 -3
  302. package/dist/web/assets/{nav-row-BmtdNLxR.js → nav-row-DaR8yP7p.js} +1 -1
  303. package/dist/web/assets/{paperclip-C4t49vX2.js → paperclip-DORF2rEM.js} +1 -1
  304. package/dist/web/assets/{pencil-BQ5_raiB.js → pencil-BG033B74.js} +1 -1
  305. package/dist/web/assets/{people-Dr0v8HK0.js → people-1qyKeYq6.js} +1 -1
  306. package/dist/web/assets/{pieDiagram-4H26LBE5-BZ3VoaNI.js → pieDiagram-4H26LBE5-BYYFVqOS.js} +1 -1
  307. package/dist/web/assets/{popover-CTqvKqTR.js → popover-CvjMbMb4.js} +1 -1
  308. package/dist/web/assets/{python-Huq_acyd.js → python-TTfnYnjF.js} +1 -1
  309. package/dist/web/assets/{quadrantDiagram-W4KKPZXB-C6ArHmnG.js → quadrantDiagram-W4KKPZXB-DTllM2j9.js} +1 -1
  310. package/dist/web/assets/{razor-Clc87Ivb.js → razor-BFVXAHVd.js} +1 -1
  311. package/dist/web/assets/{requirementDiagram-4Y6WPE33-DiLzBRQP.js → requirementDiagram-4Y6WPE33-DeJDRYUP.js} +1 -1
  312. package/dist/web/assets/{sankeyDiagram-5OEKKPKP-QlYYd7IZ.js → sankeyDiagram-5OEKKPKP-DzTvEKv8.js} +1 -1
  313. package/dist/web/assets/{search-CMIAPUEt.js → search-DDRcBORc.js} +1 -1
  314. package/dist/web/assets/{select-DqB7YF38.js → select-CXC17bJx.js} +1 -1
  315. package/dist/web/assets/{select-Bg7NI8i0.js → select-CzXL3ZbG.js} +1 -1
  316. package/dist/web/assets/{sequenceDiagram-3UESZ5HK-COKEtqc0.js → sequenceDiagram-3UESZ5HK-CIYrA1ww.js} +1 -1
  317. package/dist/web/assets/{server-D7knl8H9.js → server-KqeWHfgr.js} +1 -1
  318. package/dist/web/assets/{stateDiagram-AJRCARHV-1RZZZdOe.js → stateDiagram-AJRCARHV-Dg_UXkEq.js} +1 -1
  319. package/dist/web/assets/stateDiagram-v2-BHNVJYJU-Lc4r0bC3.js +1 -0
  320. package/dist/web/assets/{textarea-BCY2J2ca.js → textarea-Cmbv5l35.js} +1 -1
  321. package/dist/web/assets/{timeline-definition-PNZ67QCA-IJl1LY6J.js → timeline-definition-PNZ67QCA-CfSPMqxF.js} +1 -1
  322. package/dist/web/assets/{toggles-C4LmZwyo.js → toggles-t5v4QKn6.js} +1 -1
  323. package/dist/web/assets/{tooltip-Cirpotu3.js → tooltip-Cp8tovqH.js} +1 -1
  324. package/dist/web/assets/{track-Cv7h6oaE.js → track-C1rUV49K.js} +1 -1
  325. package/dist/web/assets/{trash-2-BEOQ1ICJ.js → trash-2-Ca2ken6q.js} +1 -1
  326. package/dist/web/assets/{tsMode-CHIbCBQc.js → tsMode-DBbiXlyu.js} +1 -1
  327. package/dist/web/assets/{typescript-CScj0bbb.js → typescript-jv_3P9x_.js} +1 -1
  328. package/dist/web/assets/{upload-tLVD0xMT.js → upload-CgGjN1FH.js} +1 -1
  329. package/dist/web/assets/{use-profiles-TkoP4Yw9.js → use-profiles-BdL-U8GZ.js} +1 -1
  330. package/dist/web/assets/{use-providers-Bz6YNiYj.js → use-providers-B6Mj5qeG.js} +1 -1
  331. package/dist/web/assets/{use-translation-settings-CCpQNS30.js → use-translation-settings-FIP674t9.js} +1 -1
  332. package/dist/web/assets/{useNormalizedLogs-Bstb98cF.js → useNormalizedLogs-FpVMUHeq.js} +1 -1
  333. package/dist/web/assets/useTokenUsage-Ay3Yy0_V.js +1 -0
  334. package/dist/web/assets/{vennDiagram-CIIHVFJN-DzVayy4U.js → vennDiagram-CIIHVFJN-DKREAIRT.js} +1 -1
  335. package/dist/web/assets/{wardley-L42UT6IY-CULSKh55.js → wardley-L42UT6IY-BMpDotAz.js} +1 -1
  336. package/dist/web/assets/{wardleyDiagram-YWT4CUSO-C5_h3lAA.js → wardleyDiagram-YWT4CUSO-DAPccQsF.js} +1 -1
  337. package/dist/web/assets/{xml-XuycSwh6.js → xml-DnxIQwRS.js} +1 -1
  338. package/dist/web/assets/{xychartDiagram-2RQKCTM6-F65naXcR.js → xychartDiagram-2RQKCTM6-o06g8vo8.js} +1 -1
  339. package/dist/web/assets/{yaml-BWm159lw.js → yaml-BV5yQTRd.js} +1 -1
  340. package/dist/web/index.html +1 -1
  341. package/node_modules/@agent-tower/shared/dist/log-adapter.d.ts +4 -0
  342. package/node_modules/@agent-tower/shared/dist/log-adapter.d.ts.map +1 -1
  343. package/node_modules/@agent-tower/shared/dist/log-adapter.js +1 -0
  344. package/node_modules/@agent-tower/shared/dist/log-adapter.js.map +1 -1
  345. package/node_modules/@agent-tower/shared/dist/translation.d.ts +4 -1
  346. package/node_modules/@agent-tower/shared/dist/translation.d.ts.map +1 -1
  347. package/node_modules/@agent-tower/shared/dist/translation.js +4 -1
  348. package/node_modules/@agent-tower/shared/dist/translation.js.map +1 -1
  349. package/node_modules/@agent-tower/shared/dist/types.d.ts +38 -2
  350. package/node_modules/@agent-tower/shared/dist/types.d.ts.map +1 -1
  351. package/node_modules/@agent-tower/shared/dist/types.js.map +1 -1
  352. package/package.json +2 -1
  353. package/prisma/migrations/20261106000000_add_session_wakeups/migration.sql +28 -0
  354. package/prisma/schema.prisma +28 -0
  355. package/scripts/postinstall.js +23 -0
  356. package/dist/web/assets/AttachmentPreview-TPd4gdfb.js +0 -2
  357. package/dist/web/assets/CreateTaskInput-TcZpjBe-.js +0 -1
  358. package/dist/web/assets/TaskHandoffPanel-CJahUKNo.js +0 -70
  359. package/dist/web/assets/channel-CDkuQ_7m.js +0 -1
  360. package/dist/web/assets/check-yNWhPvMH.js +0 -1
  361. package/dist/web/assets/classDiagram-4FO5ZUOK-eHY73FGu.js +0 -1
  362. package/dist/web/assets/classDiagram-v2-Q7XG4LA2-eHY73FGu.js +0 -1
  363. package/dist/web/assets/javascript-DKmxrNeR.js +0 -1
  364. package/dist/web/assets/stateDiagram-v2-BHNVJYJU-CCLmVs34.js +0 -1
  365. package/dist/web/assets/useTokenUsage-D7SEwXb0.js +0 -1
@@ -1,82 +1,30 @@
1
- import { createHash, randomBytes, timingSafeEqual } from 'node:crypto';
1
+ import { randomBytes, timingSafeEqual } from 'node:crypto';
2
2
  import http from 'node:http';
3
3
  import https from 'node:https';
4
- import { Tunnel } from 'cloudflared';
5
- import { AccessAuthService, isAccessAuthCookieName, } from './access-auth.service.js';
6
- import { TUNNEL_SESSION_COOKIE_NAME } from '../utils/tunnel-cookie.js';
7
- import { ensureCloudflaredBinary } from './cloudflared-runtime.js';
8
- import { stopCloudflaredTunnel, trackCloudflaredTunnel, waitForTunnelBinary } from './cloudflared-process.js';
4
+ import { AccessAuthService } from './access-auth.service.js';
5
+ import { buildPreviewBridgeScript, injectPreviewBridge } from './preview-bridge.js';
6
+ import { filterTargetCookieHeader, parseCookieHeader, previewCookieScopeName, rewriteTargetCookie, } from './preview-cookies.js';
7
+ import { classifyPreviewRequest, firstHeaderValue, requestProtocol } from './preview-proxy.js';
9
8
  import { writeErrorLog } from '../utils/error-log.js';
9
+ export { rewriteTargetCookie } from './preview-cookies.js';
10
+ /**
11
+ * Dedicated-origin preview gateways.
12
+ *
13
+ * Each workspace preview opened from a browser that can reach extra ports on
14
+ * the Agent Tower host gets its own root-path HTTP server. The previewed app
15
+ * then owns the whole URL space (`/login`, `/assets`, SPA history, cookies)
16
+ * without any rewriting. Browsers that cannot reach those ports use the
17
+ * same-origin `/view/:workspaceId/` proxy instead (see preview-proxy.ts).
18
+ */
10
19
  export const PREVIEW_GATEWAY_TOKEN_PARAM = '__agent_tower_preview_token';
11
- export const PREVIEW_BRIDGE_PATH = '/__agent_tower_preview_bridge.js';
12
20
  export const PREVIEW_HEARTBEAT_PATH = '/__agent_tower_preview_heartbeat';
13
21
  const DEFAULT_IDLE_TTL_MS = 10 * 60 * 1000;
14
22
  const DEFAULT_LEASE_TTL_MS = 3 * 60 * 1000;
15
23
  const DEFAULT_SWEEP_INTERVAL_MS = 30 * 1000;
16
- const TUNNEL_STARTUP_TIMEOUT_MS = 30 * 1000;
17
24
  const PREVIEW_COOKIE_MAX_AGE_SECONDS = 7 * 24 * 60 * 60;
18
- const QUICK_TUNNEL_OPTIONS = { '--no-autoupdate': true };
19
- const PREVIEW_BRIDGE_SCRIPT = `(() => {
20
- const previewSource = 'agent-tower-preview';
21
- const hostSource = 'agent-tower-preview-host';
22
- const loopbackHosts = new Set(['localhost', '127.0.0.1', '::1', '[::1]', '0.0.0.0']);
23
- const post = (message) => {
24
- if (window.parent !== window) window.parent.postMessage({ source: previewSource, ...message }, '*');
25
- };
26
- const sendLocation = () => post({ type: 'location', href: window.location.href, title: document.title });
27
- const scheduleLocation = () => window.setTimeout(sendLocation, 0);
28
-
29
- const nativePushState = History.prototype.pushState;
30
- const nativeReplaceState = History.prototype.replaceState;
31
- History.prototype.pushState = function(...args) {
32
- const result = nativePushState.apply(this, args);
33
- scheduleLocation();
34
- return result;
35
- };
36
- History.prototype.replaceState = function(...args) {
37
- const result = nativeReplaceState.apply(this, args);
38
- scheduleLocation();
39
- return result;
40
- };
41
-
42
- window.addEventListener('popstate', scheduleLocation);
43
- window.addEventListener('hashchange', scheduleLocation);
44
- window.addEventListener('pageshow', scheduleLocation);
45
- document.addEventListener('click', (event) => {
46
- if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
47
- const anchor = event.target instanceof Element ? event.target.closest('a[href]') : null;
48
- if (!anchor || anchor.hasAttribute('download')) return;
49
- let url;
50
- try { url = new URL(anchor.href, window.location.href); } catch { return; }
51
- if (!loopbackHosts.has(url.hostname.toLowerCase()) || url.origin === window.location.origin) return;
52
- event.preventDefault();
53
- post({ type: 'navigate-loopback', href: url.toString(), newTab: anchor.target === '_blank' });
54
- }, true);
55
-
56
- window.addEventListener('message', (event) => {
57
- const message = event.data;
58
- if (!message || message.source !== hostSource) return;
59
- if (message.action === 'back') window.history.back();
60
- else if (message.action === 'forward') window.history.forward();
61
- else if (message.action === 'reload') window.location.reload();
62
- else if (message.action === 'stop') window.stop();
63
- });
64
-
65
- const heartbeat = () => fetch(${JSON.stringify(PREVIEW_HEARTBEAT_PATH)}, {
66
- credentials: 'include',
67
- cache: 'no-store',
68
- }).catch(() => {});
69
- window.setInterval(heartbeat, 30000);
70
- heartbeat();
71
- sendLocation();
72
- })();`;
73
25
  function nowIso(value) {
74
26
  return new Date(value).toISOString();
75
27
  }
76
- function cookieNameForWorkspace(workspaceId) {
77
- const suffix = createHash('sha256').update(workspaceId).digest('hex').slice(0, 16);
78
- return `agent-tower-preview-${suffix}`;
79
- }
80
28
  function newSecret() {
81
29
  return randomBytes(32).toString('base64url');
82
30
  }
@@ -85,46 +33,6 @@ function safeEqual(left, right) {
85
33
  const b = Buffer.from(right);
86
34
  return a.length === b.length && timingSafeEqual(a, b);
87
35
  }
88
- function parseCookies(header) {
89
- const cookies = new Map();
90
- if (!header)
91
- return cookies;
92
- for (const part of header.split(';')) {
93
- const [rawName, ...rawValue] = part.trim().split('=');
94
- if (!rawName)
95
- continue;
96
- try {
97
- cookies.set(rawName, decodeURIComponent(rawValue.join('=')));
98
- }
99
- catch {
100
- cookies.set(rawName, rawValue.join('='));
101
- }
102
- }
103
- return cookies;
104
- }
105
- function firstHeaderValue(value) {
106
- return Array.isArray(value) ? value[0] : value;
107
- }
108
- function requestProtocol(headers) {
109
- const forwarded = firstHeaderValue(headers['x-forwarded-proto']);
110
- if (forwarded?.split(',')[0]?.trim().toLowerCase() === 'https')
111
- return 'https';
112
- const cfVisitor = firstHeaderValue(headers['cf-visitor']);
113
- if (cfVisitor) {
114
- try {
115
- if (JSON.parse(cfVisitor).scheme === 'https')
116
- return 'https';
117
- }
118
- catch {
119
- // Ignore malformed Cloudflare metadata.
120
- }
121
- }
122
- return 'http';
123
- }
124
- function isRemoteGatewayRequest(headers) {
125
- return Boolean(headers['cf-connecting-ip'] || headers['cf-ray'])
126
- || requestProtocol(headers) === 'https';
127
- }
128
36
  function requestOrigin(headers) {
129
37
  const host = firstHeaderValue(headers.host)
130
38
  || firstHeaderValue(headers['x-forwarded-host'])?.split(',')[0]?.trim()
@@ -152,47 +60,6 @@ function removeQueryParameter(rawUrl, parameter) {
152
60
  url.searchParams.delete(parameter);
153
61
  return `${url.pathname}${url.search}${url.hash}`;
154
62
  }
155
- function scopedTargetCookieName(runtimeCookieName, targetCookieName) {
156
- return `${runtimeCookieName}-target-${Buffer.from(targetCookieName).toString('base64url')}`;
157
- }
158
- function isInternalCookieName(name) {
159
- return name === TUNNEL_SESSION_COOKIE_NAME || isAccessAuthCookieName(name);
160
- }
161
- function unscopedTargetCookieName(runtimeCookieName, cookieName) {
162
- const prefix = `${runtimeCookieName}-target-`;
163
- if (!cookieName.startsWith(prefix))
164
- return null;
165
- try {
166
- const targetCookieName = Buffer.from(cookieName.slice(prefix.length), 'base64url').toString('utf8');
167
- return isInternalCookieName(targetCookieName) ? targetCookieName : null;
168
- }
169
- catch {
170
- return null;
171
- }
172
- }
173
- function filterCookieHeader(cookieHeader, runtimeCookieName) {
174
- if (!cookieHeader)
175
- return undefined;
176
- const cookies = [];
177
- for (const rawPart of cookieHeader.split(';')) {
178
- const part = rawPart.trim();
179
- if (!part)
180
- continue;
181
- const separator = part.indexOf('=');
182
- const name = separator === -1 ? part : part.slice(0, separator);
183
- if (!name || name === runtimeCookieName)
184
- continue;
185
- const targetName = unscopedTargetCookieName(runtimeCookieName, name);
186
- if (targetName) {
187
- cookies.push(`${targetName}${separator === -1 ? '' : part.slice(separator)}`);
188
- continue;
189
- }
190
- if (isInternalCookieName(name))
191
- continue;
192
- cookies.push(part);
193
- }
194
- return cookies.length > 0 ? cookies.join('; ') : undefined;
195
- }
196
63
  function joinTargetPath(target, requestUrl) {
197
64
  const parsed = new URL(requestUrl, 'http://preview.local');
198
65
  const suffix = parsed.pathname.startsWith('/') ? parsed.pathname : `/${parsed.pathname}`;
@@ -214,7 +81,7 @@ function rewriteRequestHeaders(headers, runtime, targetPath) {
214
81
  if (key.toLowerCase().startsWith('cf-'))
215
82
  delete next[key];
216
83
  }
217
- const cookie = filterCookieHeader(headers.cookie, runtime.cookieName);
84
+ const cookie = filterTargetCookieHeader(headers.cookie, runtime.cookieName);
218
85
  if (cookie)
219
86
  next.cookie = cookie;
220
87
  else
@@ -247,41 +114,6 @@ function rewriteLocation(value, runtime, requestHeaders) {
247
114
  return value;
248
115
  }
249
116
  }
250
- export function rewriteTargetCookie(value, target, runtimeCookieName, secureGateway) {
251
- let next = value.replace(/;\s*domain=[^;]*/gi, '');
252
- const separator = next.indexOf('=');
253
- if (separator > 0) {
254
- const cookieName = next.slice(0, separator).trim();
255
- if (isInternalCookieName(cookieName)) {
256
- next = `${scopedTargetCookieName(runtimeCookieName, cookieName)}${next.slice(separator)}`;
257
- }
258
- }
259
- if (target.basePath && /;\s*path=/i.test(next)) {
260
- next = next.replace(/;\s*path=([^;]*)/i, (_match, rawPath) => {
261
- const path = rawPath.trim();
262
- if (path === target.basePath)
263
- return '; Path=/';
264
- if (path.startsWith(`${target.basePath}/`)) {
265
- return `; Path=${path.slice(target.basePath.length) || '/'}`;
266
- }
267
- return `; Path=${path || '/'}`;
268
- });
269
- }
270
- if (secureGateway) {
271
- next = next
272
- .replace(/;\s*secure(?=;|$)/gi, '')
273
- .replace(/;\s*samesite=[^;]*/gi, '')
274
- .replace(/;\s*partitioned(?=;|$)/gi, '');
275
- return `${next}; Secure; SameSite=None; Partitioned`;
276
- }
277
- next = next
278
- .replace(/;\s*secure(?=;|$)/gi, '')
279
- .replace(/;\s*partitioned(?=;|$)/gi, '');
280
- if (/;\s*samesite=none(?=;|$)/i.test(next)) {
281
- next = next.replace(/;\s*samesite=none(?=;|$)/i, '; SameSite=Lax');
282
- }
283
- return next;
284
- }
285
117
  function rewriteResponseHeaders(headers, runtime, requestHeaders, injectBridge) {
286
118
  const next = {};
287
119
  for (const [key, value] of Object.entries(headers)) {
@@ -313,14 +145,16 @@ function isHtmlResponse(headers) {
313
145
  const contentType = firstHeaderValue(headers['content-type'])?.toLowerCase() ?? '';
314
146
  return contentType.includes('text/html');
315
147
  }
316
- function injectBridgeScript(body) {
317
- if (body.includes('data-agent-tower-preview-bridge'))
318
- return body;
319
- const script = `<script data-agent-tower-preview-bridge src="${PREVIEW_BRIDGE_PATH}"></script>`;
320
- const head = /<head(?:\s[^>]*)?>/i;
321
- if (head.test(body))
322
- return body.replace(head, (match) => `${match}${script}`);
323
- return `${script}${body}`;
148
+ function gatewayBridgeTag(runtime) {
149
+ return buildPreviewBridgeScript({
150
+ mode: 'gateway',
151
+ prefix: '',
152
+ workspaceId: runtime.workspaceId,
153
+ targetOrigin: runtime.target.origin,
154
+ targetBasePath: runtime.target.basePath,
155
+ serviceWorker: false,
156
+ heartbeatPath: PREVIEW_HEARTBEAT_PATH,
157
+ });
324
158
  }
325
159
  function writeUnauthorized(response) {
326
160
  response.writeHead(401, {
@@ -381,18 +215,12 @@ export class PreviewRuntimeManager {
381
215
  leaseTtlMs;
382
216
  listenHost;
383
217
  now;
384
- createTunnel;
385
- ensureTunnelBinary;
386
218
  sweepTimer;
387
219
  constructor(options = {}) {
388
220
  this.idleTtlMs = options.idleTtlMs ?? DEFAULT_IDLE_TTL_MS;
389
221
  this.leaseTtlMs = options.leaseTtlMs ?? DEFAULT_LEASE_TTL_MS;
390
222
  this.listenHost = options.listenHost ?? process.env.AGENT_TOWER_HOST ?? '0.0.0.0';
391
223
  this.now = options.now ?? (() => Date.now());
392
- this.createTunnel = options.createTunnel
393
- ?? ((targetUrl) => Tunnel.quick(targetUrl, QUICK_TUNNEL_OPTIONS));
394
- this.ensureTunnelBinary = options.ensureTunnelBinary
395
- ?? (options.createTunnel ? async () => { } : ensureCloudflaredBinary);
396
224
  this.sweepTimer = setInterval(() => {
397
225
  void this.sweep().catch((error) => {
398
226
  writeErrorLog({ level: 'error', source: 'preview.cleanup', message: 'Failed to reclaim preview runtime', error });
@@ -400,25 +228,18 @@ export class PreviewRuntimeManager {
400
228
  }, options.sweepIntervalMs ?? DEFAULT_SWEEP_INTERVAL_MS);
401
229
  this.sweepTimer.unref?.();
402
230
  }
403
- async acquire(workspaceId, target, mode, localHostname) {
231
+ async acquire(workspaceId, target, localHostname) {
404
232
  const runtime = await this.ensureRuntime(workspaceId, target);
405
233
  this.assertRuntimeActive(runtime);
406
234
  const now = this.now();
407
235
  const lease = {
408
236
  id: randomBytes(16).toString('base64url'),
409
- mode,
410
237
  localHostname,
411
238
  expiresAtMs: now + this.leaseTtlMs,
412
239
  };
413
240
  runtime.leases.set(lease.id, lease);
414
241
  runtime.lastActivityAtMs = now;
415
- if (mode === 'remote')
416
- runtime.tunnelLastActivityAtMs = now;
417
- const viewBaseUrl = mode === 'remote'
418
- ? await this.ensureTunnel(runtime)
419
- : `http://${formatHostname(localHostname)}:${runtime.port}`;
420
- this.assertRuntimeActive(runtime);
421
- return this.toSession(runtime, lease, viewBaseUrl);
242
+ return this.toSession(runtime, lease);
422
243
  }
423
244
  async heartbeat(workspaceId, leaseId) {
424
245
  const runtime = this.runtimes.get(workspaceId);
@@ -428,13 +249,8 @@ export class PreviewRuntimeManager {
428
249
  const now = this.now();
429
250
  lease.expiresAtMs = now + this.leaseTtlMs;
430
251
  runtime.lastActivityAtMs = now;
431
- if (lease.mode === 'remote')
432
- runtime.tunnelLastActivityAtMs = now;
433
- const viewBaseUrl = lease.mode === 'remote'
434
- ? await this.ensureTunnel(runtime)
435
- : `http://${formatHostname(lease.localHostname)}:${runtime.port}`;
436
252
  this.assertRuntimeActive(runtime);
437
- return this.toSession(runtime, lease, viewBaseUrl);
253
+ return this.toSession(runtime, lease);
438
254
  }
439
255
  release(workspaceId, leaseId) {
440
256
  this.runtimes.get(workspaceId)?.leases.delete(leaseId);
@@ -443,7 +259,7 @@ export class PreviewRuntimeManager {
443
259
  const runtime = this.runtimes.get(workspaceId);
444
260
  if (!runtime)
445
261
  return;
446
- await this.stopRuntime(runtime);
262
+ await closeServer(runtime);
447
263
  if (this.runtimes.get(workspaceId) === runtime)
448
264
  this.runtimes.delete(workspaceId);
449
265
  }
@@ -455,13 +271,12 @@ export class PreviewRuntimeManager {
455
271
  if (failure)
456
272
  throw failure.reason;
457
273
  }
458
- toSession(runtime, lease, viewBaseUrl) {
274
+ toSession(runtime, lease) {
459
275
  return {
460
276
  id: lease.id,
461
277
  workspaceId: runtime.workspaceId,
462
278
  target: runtime.target.target,
463
- mode: lease.mode,
464
- viewBaseUrl,
279
+ viewBaseUrl: `http://${formatHostname(lease.localHostname)}:${runtime.port}`,
465
280
  expiresAt: nowIso(lease.expiresAtMs),
466
281
  };
467
282
  }
@@ -492,19 +307,13 @@ export class PreviewRuntimeManager {
492
307
  server,
493
308
  port: 0,
494
309
  ready: Promise.resolve(0),
495
- cookieName: cookieNameForWorkspace(workspaceId),
310
+ cookieName: previewCookieScopeName(workspaceId),
496
311
  accessSecret: newSecret(),
497
312
  accessGeneration: AccessAuthService.getSessionSecretGeneration(),
498
313
  leases: new Map(),
499
314
  lastActivityAtMs: this.now(),
500
- tunnelLastActivityAtMs: this.now(),
501
315
  activeConnections: 0,
502
- activeRemoteConnections: 0,
503
316
  sockets: new Set(),
504
- tunnel: null,
505
- tunnelUrl: null,
506
- tunnelStartPromise: null,
507
- tunnelStartController: null,
508
317
  stopped: false,
509
318
  });
510
319
  server.on('connection', (socket) => {
@@ -526,7 +335,7 @@ export class PreviewRuntimeManager {
526
335
  return runtime;
527
336
  }
528
337
  catch (error) {
529
- await this.stopRuntime(runtime);
338
+ await closeServer(runtime);
530
339
  if (this.runtimes.get(workspaceId) === runtime)
531
340
  this.runtimes.delete(workspaceId);
532
341
  throw error;
@@ -541,14 +350,11 @@ export class PreviewRuntimeManager {
541
350
  }
542
351
  hasGatewayCookie(runtime, request) {
543
352
  this.rotateAccessSecretIfNeeded(runtime);
544
- const candidate = parseCookies(request.headers.cookie).get(runtime.cookieName);
353
+ const candidate = parseCookieHeader(request.headers.cookie).get(runtime.cookieName);
545
354
  return Boolean(candidate && safeEqual(candidate, runtime.accessSecret));
546
355
  }
547
- touchRuntime(runtime, headers) {
548
- const now = this.now();
549
- runtime.lastActivityAtMs = now;
550
- if (isRemoteGatewayRequest(headers))
551
- runtime.tunnelLastActivityAtMs = now;
356
+ touchRuntime(runtime) {
357
+ runtime.lastActivityAtMs = this.now();
552
358
  }
553
359
  async authorizeBootstrap(runtime, request, response) {
554
360
  const parsed = new URL(request.url ?? '/', 'http://preview.local');
@@ -557,7 +363,7 @@ export class PreviewRuntimeManager {
557
363
  return false;
558
364
  }
559
365
  this.rotateAccessSecretIfNeeded(runtime);
560
- this.touchRuntime(runtime, request.headers);
366
+ this.touchRuntime(runtime);
561
367
  response.setHeader('set-cookie', serializeGatewayCookie(runtime, request.headers));
562
368
  if (request.method === 'GET' || request.method === 'HEAD') {
563
369
  response.writeHead(302, {
@@ -585,15 +391,7 @@ export class PreviewRuntimeManager {
585
391
  writeUnauthorized(response);
586
392
  return;
587
393
  }
588
- this.touchRuntime(runtime, request.headers);
589
- if (parsed.pathname === PREVIEW_BRIDGE_PATH) {
590
- response.writeHead(200, {
591
- 'content-type': 'application/javascript; charset=utf-8',
592
- 'cache-control': 'no-store',
593
- });
594
- response.end(PREVIEW_BRIDGE_SCRIPT);
595
- return;
596
- }
394
+ this.touchRuntime(runtime);
597
395
  if (parsed.pathname === PREVIEW_HEARTBEAT_PATH) {
598
396
  response.writeHead(204, { 'cache-control': 'no-store' });
599
397
  response.end();
@@ -604,6 +402,7 @@ export class PreviewRuntimeManager {
604
402
  async proxyHttpRequest(runtime, request, response) {
605
403
  const targetUrl = new URL(runtime.target.origin);
606
404
  const targetPath = joinTargetPath(runtime.target, request.url ?? '/');
405
+ const context = classifyPreviewRequest(request.method ?? 'GET', request.headers, new URL(request.url ?? '/', 'http://preview.local').search);
607
406
  const options = {
608
407
  protocol: targetUrl.protocol,
609
408
  hostname: targetUrl.hostname,
@@ -619,6 +418,7 @@ export class PreviewRuntimeManager {
619
418
  const injectBridge = request.method !== 'HEAD'
620
419
  && proxyResponse.statusCode !== 204
621
420
  && proxyResponse.statusCode !== 304
421
+ && context.document
622
422
  && isHtmlResponse(proxyResponse.headers);
623
423
  const headers = rewriteResponseHeaders(proxyResponse.headers, runtime, request.headers, injectBridge);
624
424
  response.statusCode = proxyResponse.statusCode ?? 502;
@@ -640,7 +440,7 @@ export class PreviewRuntimeManager {
640
440
  chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
641
441
  });
642
442
  proxyResponse.once('end', () => {
643
- response.end(injectBridgeScript(Buffer.concat(chunks).toString('utf8')));
443
+ response.end(injectPreviewBridge(Buffer.concat(chunks), gatewayBridgeTag(runtime)));
644
444
  resolve();
645
445
  });
646
446
  proxyResponse.once('error', () => {
@@ -663,8 +463,7 @@ export class PreviewRuntimeManager {
663
463
  writeUpgradeError(socket, 401, 'Unauthorized');
664
464
  return;
665
465
  }
666
- this.touchRuntime(runtime, request.headers);
667
- const remoteConnection = isRemoteGatewayRequest(request.headers);
466
+ this.touchRuntime(runtime);
668
467
  const targetUrl = new URL(runtime.target.origin);
669
468
  const targetPath = joinTargetPath(runtime.target, request.url ?? '/');
670
469
  const headers = rewriteRequestHeaders(request.headers, runtime, targetPath);
@@ -683,24 +482,15 @@ export class PreviewRuntimeManager {
683
482
  const proxyRequest = transport.request(options);
684
483
  proxyRequest.once('upgrade', (proxyResponse, proxySocket, proxyHead) => {
685
484
  runtime.activeConnections += 1;
686
- if (remoteConnection)
687
- runtime.activeRemoteConnections += 1;
688
485
  runtime.sockets.add(proxySocket);
689
486
  const close = () => {
690
487
  runtime.activeConnections = Math.max(0, runtime.activeConnections - 1);
691
- if (remoteConnection) {
692
- runtime.activeRemoteConnections = Math.max(0, runtime.activeRemoteConnections - 1);
693
- }
694
488
  runtime.sockets.delete(proxySocket);
695
- this.touchRuntime(runtime, request.headers);
489
+ this.touchRuntime(runtime);
696
490
  };
697
491
  proxySocket.once('close', close);
698
- proxySocket.on('data', () => {
699
- this.touchRuntime(runtime, request.headers);
700
- });
701
- socket.on('data', () => {
702
- this.touchRuntime(runtime, request.headers);
703
- });
492
+ proxySocket.on('data', () => this.touchRuntime(runtime));
493
+ socket.on('data', () => this.touchRuntime(runtime));
704
494
  const headerLines = [
705
495
  `HTTP/1.1 ${proxyResponse.statusCode} ${proxyResponse.statusMessage}`,
706
496
  ...Object.entries(proxyResponse.headers).flatMap(([key, value]) => {
@@ -730,88 +520,6 @@ export class PreviewRuntimeManager {
730
520
  throw new Error('Preview runtime was invalidated');
731
521
  }
732
522
  }
733
- async ensureTunnel(runtime) {
734
- this.assertRuntimeActive(runtime);
735
- if (runtime.tunnel && runtime.tunnelUrl)
736
- return runtime.tunnelUrl;
737
- if (runtime.tunnelStartPromise)
738
- return runtime.tunnelStartPromise;
739
- if (runtime.tunnel)
740
- throw new Error('Previous preview tunnel cleanup must finish before starting');
741
- const controller = new AbortController();
742
- runtime.tunnelStartController = controller;
743
- let startedTunnel = null;
744
- const startPromise = (async () => {
745
- await waitForTunnelBinary(this.ensureTunnelBinary(), controller.signal);
746
- this.assertRuntimeActive(runtime);
747
- return new Promise((resolve, reject) => {
748
- const tunnel = this.createTunnel(`http://127.0.0.1:${runtime.port}`);
749
- startedTunnel = tunnel;
750
- trackCloudflaredTunnel(tunnel);
751
- runtime.tunnel = tunnel;
752
- let settled = false;
753
- const timer = setTimeout(() => settle(reject, new Error('Preview tunnel startup timed out')), TUNNEL_STARTUP_TIMEOUT_MS);
754
- const cleanup = () => {
755
- clearTimeout(timer);
756
- tunnel.off('url', onUrl);
757
- tunnel.off('error', onError);
758
- tunnel.off('exit', onExitBeforeReady);
759
- controller.signal.removeEventListener('abort', onAbort);
760
- };
761
- const settle = (done, value) => {
762
- if (settled)
763
- return;
764
- settled = true;
765
- cleanup();
766
- done(value);
767
- };
768
- const onAbort = () => settle(reject, controller.signal.reason);
769
- const onUrl = (url) => {
770
- runtime.tunnelUrl = url.replace(/\/$/, '');
771
- settle(resolve, runtime.tunnelUrl);
772
- };
773
- const onError = (error) => settle(reject, error);
774
- const onExitBeforeReady = (code, signal) => {
775
- settle(reject, new Error(`Preview tunnel exited before ready (${code ?? signal ?? 'unknown'})`));
776
- };
777
- controller.signal.addEventListener('abort', onAbort, { once: true });
778
- tunnel.once('url', onUrl);
779
- tunnel.once('error', onError);
780
- tunnel.once('exit', onExitBeforeReady);
781
- tunnel.on('error', () => {
782
- // The session heartbeat will recreate a failed tunnel when needed.
783
- });
784
- tunnel.on('exit', () => {
785
- if (runtime.tunnel !== tunnel)
786
- return;
787
- runtime.tunnel = null;
788
- runtime.tunnelUrl = null;
789
- });
790
- });
791
- })();
792
- runtime.tunnelStartPromise = startPromise;
793
- try {
794
- const url = await startPromise;
795
- controller.signal.throwIfAborted();
796
- this.assertRuntimeActive(runtime);
797
- return url;
798
- }
799
- catch (error) {
800
- if (startedTunnel) {
801
- await stopCloudflaredTunnel(startedTunnel);
802
- if (runtime.tunnel === startedTunnel)
803
- runtime.tunnel = null;
804
- }
805
- runtime.tunnelUrl = null;
806
- throw error;
807
- }
808
- finally {
809
- if (runtime.tunnelStartPromise === startPromise) {
810
- runtime.tunnelStartPromise = null;
811
- runtime.tunnelStartController = null;
812
- }
813
- }
814
- }
815
523
  async sweep() {
816
524
  const now = this.now();
817
525
  const expired = [];
@@ -820,13 +528,6 @@ export class PreviewRuntimeManager {
820
528
  if (lease.expiresAtMs <= now)
821
529
  runtime.leases.delete(leaseId);
822
530
  }
823
- const hasRemoteLease = [...runtime.leases.values()].some((lease) => lease.mode === 'remote');
824
- if (runtime.tunnel
825
- && !hasRemoteLease
826
- && runtime.activeRemoteConnections === 0
827
- && now - runtime.tunnelLastActivityAtMs >= this.idleTtlMs) {
828
- await this.stopTunnel(runtime);
829
- }
830
531
  if (runtime.leases.size === 0
831
532
  && runtime.activeConnections === 0
832
533
  && now - runtime.lastActivityAtMs >= this.idleTtlMs) {
@@ -839,23 +540,5 @@ export class PreviewRuntimeManager {
839
540
  await this.invalidate(runtime.workspaceId);
840
541
  }));
841
542
  }
842
- async stopRuntime(runtime) {
843
- runtime.stopped = true;
844
- const results = await Promise.allSettled([this.stopTunnel(runtime), closeServer(runtime)]);
845
- const failure = results.find((result) => result.status === 'rejected');
846
- if (failure)
847
- throw failure.reason;
848
- }
849
- async stopTunnel(runtime) {
850
- runtime.tunnelStartController?.abort(new Error('Preview tunnel startup cancelled'));
851
- runtime.tunnelUrl = null;
852
- await runtime.tunnelStartPromise?.catch(() => undefined);
853
- const tunnel = runtime.tunnel;
854
- if (tunnel) {
855
- await stopCloudflaredTunnel(tunnel);
856
- if (runtime.tunnel === tunnel)
857
- runtime.tunnel = null;
858
- }
859
- }
860
543
  }
861
544
  //# sourceMappingURL=preview-runtime-manager.js.map