@browserbasehq/orca 3.1.0-patch.0 → 3.1.0-patch.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/dist/cjs/cli.js +183 -0
  2. package/dist/cjs/cli.js.map +7 -0
  3. package/dist/cjs/index.d.ts +1 -0
  4. package/dist/cjs/index.js +24956 -0
  5. package/dist/cjs/index.js.map +7 -0
  6. package/dist/cjs/lib/inference.d.ts +65 -0
  7. package/dist/cjs/lib/inferenceLogUtils.d.ts +12 -0
  8. package/dist/cjs/lib/logger.d.ts +69 -0
  9. package/dist/cjs/lib/modelUtils.d.ts +11 -0
  10. package/dist/cjs/lib/prompt.d.ts +14 -0
  11. package/dist/cjs/lib/utils.d.ts +68 -0
  12. package/dist/cjs/lib/v3/agent/AgentClient.d.ts +19 -0
  13. package/dist/cjs/lib/v3/agent/AgentProvider.d.ts +20 -0
  14. package/dist/cjs/lib/v3/agent/AnthropicCUAClient.d.ts +57 -0
  15. package/dist/cjs/lib/v3/agent/GoogleCUAClient.d.ts +74 -0
  16. package/dist/cjs/lib/v3/agent/MicrosoftCUAClient.d.ts +71 -0
  17. package/dist/cjs/lib/v3/agent/OpenAICUAClient.d.ts +69 -0
  18. package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.d.ts +12 -0
  19. package/dist/cjs/lib/v3/agent/tools/act.d.ts +12 -0
  20. package/dist/cjs/lib/v3/agent/tools/ariaTree.d.ts +5 -0
  21. package/dist/cjs/lib/v3/agent/tools/click.d.ts +6 -0
  22. package/dist/cjs/lib/v3/agent/tools/clickAndHold.d.ts +14 -0
  23. package/dist/cjs/lib/v3/agent/tools/dragAndDrop.d.ts +7 -0
  24. package/dist/cjs/lib/v3/agent/tools/extract.d.ts +20 -0
  25. package/dist/cjs/lib/v3/agent/tools/fillFormVision.d.ts +12 -0
  26. package/dist/cjs/lib/v3/agent/tools/fillform.d.ts +12 -0
  27. package/dist/cjs/lib/v3/agent/tools/goto.d.ts +12 -0
  28. package/dist/cjs/lib/v3/agent/tools/index.d.ts +92 -0
  29. package/dist/cjs/lib/v3/agent/tools/keys.d.ts +24 -0
  30. package/dist/cjs/lib/v3/agent/tools/navback.d.ts +6 -0
  31. package/dist/cjs/lib/v3/agent/tools/screenshot.d.ts +6 -0
  32. package/dist/cjs/lib/v3/agent/tools/scroll.d.ts +19 -0
  33. package/dist/cjs/lib/v3/agent/tools/search.d.ts +15 -0
  34. package/dist/cjs/lib/v3/agent/tools/think.d.ts +6 -0
  35. package/dist/cjs/lib/v3/agent/tools/type.d.ts +7 -0
  36. package/dist/cjs/lib/v3/agent/tools/wait.d.ts +5 -0
  37. package/dist/cjs/lib/v3/agent/utils/actionMapping.d.ts +3 -0
  38. package/dist/cjs/lib/v3/agent/utils/coordinateNormalization.d.ts +13 -0
  39. package/dist/cjs/lib/v3/agent/utils/cuaKeyMapping.d.ts +10 -0
  40. package/dist/cjs/lib/v3/agent/utils/googleCustomToolHandler.d.ts +25 -0
  41. package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.d.ts +22 -0
  42. package/dist/cjs/lib/v3/agent/utils/imageCompression.d.ts +53 -0
  43. package/dist/cjs/lib/v3/agent/utils/messageProcessing.d.ts +12 -0
  44. package/dist/cjs/lib/v3/agent/utils/screenshotHandler.d.ts +10 -0
  45. package/dist/cjs/lib/v3/agent/utils/validateExperimentalFeatures.d.ts +26 -0
  46. package/dist/cjs/lib/v3/agent/utils/xpath.d.ts +11 -0
  47. package/dist/cjs/lib/v3/api.d.ts +86 -0
  48. package/dist/cjs/lib/v3/cache/ActCache.d.ts +23 -0
  49. package/dist/cjs/lib/v3/cache/AgentCache.d.ts +109 -0
  50. package/dist/cjs/lib/v3/cache/CacheStorage.d.ts +17 -0
  51. package/dist/cjs/lib/v3/cache/serverAgentCache.d.ts +7 -0
  52. package/dist/cjs/lib/v3/cache/utils.d.ts +15 -0
  53. package/dist/cjs/lib/v3/cli.d.ts +2 -0
  54. package/dist/cjs/lib/v3/dom/a11yScripts/index.d.ts +11 -0
  55. package/dist/cjs/lib/v3/dom/build/a11yScripts.generated.d.ts +16 -0
  56. package/dist/cjs/lib/v3/dom/build/locatorScripts.generated.d.ts +52 -0
  57. package/dist/cjs/lib/v3/dom/build/reRenderScriptContent.d.ts +1 -0
  58. package/dist/cjs/lib/v3/dom/build/rerender-index.d.ts +0 -0
  59. package/dist/cjs/lib/v3/dom/build/rerender-index.js +1 -0
  60. package/dist/cjs/lib/v3/dom/build/screenshotScripts.generated.d.ts +4 -0
  61. package/dist/cjs/lib/v3/dom/build/scriptV3Content.d.ts +1 -0
  62. package/dist/cjs/lib/v3/dom/build/v3-index.d.ts +0 -0
  63. package/dist/cjs/lib/v3/dom/build/v3-index.js +1 -0
  64. package/dist/cjs/lib/v3/dom/genA11yScripts.d.ts +1 -0
  65. package/dist/cjs/lib/v3/dom/genDomScripts.d.ts +1 -0
  66. package/dist/cjs/lib/v3/dom/genLocatorScripts.d.ts +1 -0
  67. package/dist/cjs/lib/v3/dom/genScreenshotScripts.d.ts +1 -0
  68. package/dist/cjs/lib/v3/dom/index.d.ts +1 -0
  69. package/dist/cjs/lib/v3/dom/locatorScripts/counts.d.ts +15 -0
  70. package/dist/cjs/lib/v3/dom/locatorScripts/index.d.ts +4 -0
  71. package/dist/cjs/lib/v3/dom/locatorScripts/scripts.d.ts +37 -0
  72. package/dist/cjs/lib/v3/dom/locatorScripts/selectors.d.ts +4 -0
  73. package/dist/cjs/lib/v3/dom/locatorScripts/waitForSelector.d.ts +19 -0
  74. package/dist/cjs/lib/v3/dom/locatorScripts/xpathParser.d.ts +76 -0
  75. package/dist/cjs/lib/v3/dom/locatorScripts/xpathResolver.d.ts +9 -0
  76. package/dist/cjs/lib/v3/dom/piercer.entry.d.ts +1 -0
  77. package/dist/cjs/lib/v3/dom/piercer.runtime.d.ts +23 -0
  78. package/dist/cjs/lib/v3/dom/rerenderMissingShadows.entry.d.ts +1 -0
  79. package/dist/cjs/lib/v3/dom/rerenderMissingShadows.runtime.d.ts +1 -0
  80. package/dist/cjs/lib/v3/dom/screenshotScripts/index.d.ts +1 -0
  81. package/dist/cjs/lib/v3/dom/screenshotScripts/resolveMaskRect.d.ts +8 -0
  82. package/dist/cjs/lib/v3/external_clients/aisdk.d.ts +11 -0
  83. package/dist/cjs/lib/v3/external_clients/customOpenAI.d.ts +18 -0
  84. package/dist/cjs/lib/v3/flowLogger.d.ts +139 -0
  85. package/dist/cjs/lib/v3/handlers/actHandler.d.ts +21 -0
  86. package/dist/cjs/lib/v3/handlers/extractHandler.d.ts +31 -0
  87. package/dist/cjs/lib/v3/handlers/handlerUtils/actHandlerUtils.d.ts +24 -0
  88. package/dist/cjs/lib/v3/handlers/handlerUtils/timeoutGuard.d.ts +2 -0
  89. package/dist/cjs/lib/v3/handlers/observeHandler.d.ts +17 -0
  90. package/dist/cjs/lib/v3/handlers/v3AgentHandler.d.ts +32 -0
  91. package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.d.ts +33 -0
  92. package/dist/cjs/lib/v3/index.d.ts +18 -0
  93. package/dist/cjs/lib/v3/launch/browserbase.d.ts +7 -0
  94. package/dist/cjs/lib/v3/launch/local.d.ts +15 -0
  95. package/dist/cjs/lib/v3/llm/AnthropicClient.d.ts +16 -0
  96. package/dist/cjs/lib/v3/llm/CerebrasClient.d.ts +17 -0
  97. package/dist/cjs/lib/v3/llm/GoogleClient.d.ts +19 -0
  98. package/dist/cjs/lib/v3/llm/GroqClient.d.ts +17 -0
  99. package/dist/cjs/lib/v3/llm/LLMClient.d.ts +121 -0
  100. package/dist/cjs/lib/v3/llm/LLMProvider.d.ts +13 -0
  101. package/dist/cjs/lib/v3/llm/OpenAIClient.d.ts +15 -0
  102. package/dist/cjs/lib/v3/llm/aisdk.d.ts +15 -0
  103. package/dist/cjs/lib/v3/logger.d.ts +9 -0
  104. package/dist/cjs/lib/v3/mcp/connection.d.ts +11 -0
  105. package/dist/cjs/lib/v3/mcp/utils.d.ts +3 -0
  106. package/dist/cjs/lib/v3/shutdown/cleanupLocal.d.ts +14 -0
  107. package/dist/cjs/lib/v3/shutdown/supervisor.d.ts +11 -0
  108. package/dist/cjs/lib/v3/shutdown/supervisorClient.d.ts +15 -0
  109. package/dist/cjs/lib/v3/tests/agent-abort-signal.spec.js +113 -0
  110. package/dist/cjs/lib/v3/tests/agent-abort-signal.spec.js.map +7 -0
  111. package/dist/cjs/lib/v3/tests/agent-cache-self-heal.spec.js +102 -0
  112. package/dist/cjs/lib/v3/tests/agent-cache-self-heal.spec.js.map +7 -0
  113. package/dist/cjs/lib/v3/tests/agent-callbacks.spec.js +374 -0
  114. package/dist/cjs/lib/v3/tests/agent-callbacks.spec.js.map +7 -0
  115. package/dist/cjs/lib/v3/tests/agent-experimental-validation.spec.js +354 -0
  116. package/dist/cjs/lib/v3/tests/agent-experimental-validation.spec.js.map +7 -0
  117. package/dist/cjs/lib/v3/tests/agent-hybrid-mode.spec.js +247 -0
  118. package/dist/cjs/lib/v3/tests/agent-hybrid-mode.spec.js.map +7 -0
  119. package/dist/cjs/lib/v3/tests/agent-message-continuation.spec.js +105 -0
  120. package/dist/cjs/lib/v3/tests/agent-message-continuation.spec.js.map +7 -0
  121. package/dist/cjs/lib/v3/tests/agent-streaming.spec.js +126 -0
  122. package/dist/cjs/lib/v3/tests/agent-streaming.spec.js.map +7 -0
  123. package/dist/cjs/lib/v3/tests/cdp-session-detached.spec.js +44 -0
  124. package/dist/cjs/lib/v3/tests/cdp-session-detached.spec.js.map +7 -0
  125. package/dist/cjs/lib/v3/tests/click-count.spec.js +147 -0
  126. package/dist/cjs/lib/v3/tests/click-count.spec.js.map +7 -0
  127. package/dist/cjs/lib/v3/tests/connect-to-existing-browser.spec.js +54 -0
  128. package/dist/cjs/lib/v3/tests/connect-to-existing-browser.spec.js.map +7 -0
  129. package/dist/cjs/lib/v3/tests/context-addInitScript.spec.js +176 -0
  130. package/dist/cjs/lib/v3/tests/context-addInitScript.spec.js.map +7 -0
  131. package/dist/cjs/lib/v3/tests/default-page-tracking.spec.js +53 -0
  132. package/dist/cjs/lib/v3/tests/default-page-tracking.spec.js.map +7 -0
  133. package/dist/cjs/lib/v3/tests/downloads.spec.js +80 -0
  134. package/dist/cjs/lib/v3/tests/downloads.spec.js.map +7 -0
  135. package/dist/cjs/lib/v3/tests/frame-get-location-and-click.spec.js +53 -0
  136. package/dist/cjs/lib/v3/tests/frame-get-location-and-click.spec.js.map +7 -0
  137. package/dist/cjs/lib/v3/tests/iframe-ctx-addInitScript.spec.js +493 -0
  138. package/dist/cjs/lib/v3/tests/iframe-ctx-addInitScript.spec.js.map +7 -0
  139. package/dist/cjs/lib/v3/tests/keep-alive.child.js +92 -0
  140. package/dist/cjs/lib/v3/tests/keep-alive.child.js.map +7 -0
  141. package/dist/cjs/lib/v3/tests/keep-alive.helpers.js +568 -0
  142. package/dist/cjs/lib/v3/tests/keep-alive.helpers.js.map +7 -0
  143. package/dist/cjs/lib/v3/tests/keep-alive.spec.js +15 -0
  144. package/dist/cjs/lib/v3/tests/keep-alive.spec.js.map +7 -0
  145. package/dist/cjs/lib/v3/tests/keyboard.spec.js +296 -0
  146. package/dist/cjs/lib/v3/tests/keyboard.spec.js.map +7 -0
  147. package/dist/cjs/lib/v3/tests/locator-backend-node-id.spec.js +159 -0
  148. package/dist/cjs/lib/v3/tests/locator-backend-node-id.spec.js.map +7 -0
  149. package/dist/cjs/lib/v3/tests/locator-content-methods.spec.js +191 -0
  150. package/dist/cjs/lib/v3/tests/locator-content-methods.spec.js.map +7 -0
  151. package/dist/cjs/lib/v3/tests/locator-count-iframe.spec.js +108 -0
  152. package/dist/cjs/lib/v3/tests/locator-count-iframe.spec.js.map +7 -0
  153. package/dist/cjs/lib/v3/tests/locator-count.spec.js +71 -0
  154. package/dist/cjs/lib/v3/tests/locator-count.spec.js.map +7 -0
  155. package/dist/cjs/lib/v3/tests/locator-fill.spec.js +118 -0
  156. package/dist/cjs/lib/v3/tests/locator-fill.spec.js.map +7 -0
  157. package/dist/cjs/lib/v3/tests/locator-input-methods.spec.js +136 -0
  158. package/dist/cjs/lib/v3/tests/locator-input-methods.spec.js.map +7 -0
  159. package/dist/cjs/lib/v3/tests/locator-nth.spec.js +157 -0
  160. package/dist/cjs/lib/v3/tests/locator-nth.spec.js.map +7 -0
  161. package/dist/cjs/lib/v3/tests/locator-select-option.spec.js +242 -0
  162. package/dist/cjs/lib/v3/tests/locator-select-option.spec.js.map +7 -0
  163. package/dist/cjs/lib/v3/tests/logger-initialization.spec.js +547 -0
  164. package/dist/cjs/lib/v3/tests/logger-initialization.spec.js.map +7 -0
  165. package/dist/cjs/lib/v3/tests/multi-instance-logger.spec.js +269 -0
  166. package/dist/cjs/lib/v3/tests/multi-instance-logger.spec.js.map +7 -0
  167. package/dist/cjs/lib/v3/tests/nested-div.spec.js +23 -0
  168. package/dist/cjs/lib/v3/tests/nested-div.spec.js.map +7 -0
  169. package/dist/cjs/lib/v3/tests/page-addInitScript.spec.js +90 -0
  170. package/dist/cjs/lib/v3/tests/page-addInitScript.spec.js.map +7 -0
  171. package/dist/cjs/lib/v3/tests/page-console.spec.js +56 -0
  172. package/dist/cjs/lib/v3/tests/page-console.spec.js.map +7 -0
  173. package/dist/cjs/lib/v3/tests/page-drag-and-drop.spec.js +418 -0
  174. package/dist/cjs/lib/v3/tests/page-drag-and-drop.spec.js.map +7 -0
  175. package/dist/cjs/lib/v3/tests/page-goto-response.spec.js +35 -0
  176. package/dist/cjs/lib/v3/tests/page-goto-response.spec.js.map +7 -0
  177. package/dist/cjs/lib/v3/tests/page-hover.spec.js +167 -0
  178. package/dist/cjs/lib/v3/tests/page-hover.spec.js.map +7 -0
  179. package/dist/cjs/lib/v3/tests/page-screenshot.spec.js +295 -0
  180. package/dist/cjs/lib/v3/tests/page-screenshot.spec.js.map +7 -0
  181. package/dist/cjs/lib/v3/tests/page-scroll.spec.js +182 -0
  182. package/dist/cjs/lib/v3/tests/page-scroll.spec.js.map +7 -0
  183. package/dist/cjs/lib/v3/tests/page-send-cdp.spec.js +46 -0
  184. package/dist/cjs/lib/v3/tests/page-send-cdp.spec.js.map +7 -0
  185. package/dist/cjs/lib/v3/tests/perform-understudy-method.spec.js +98 -0
  186. package/dist/cjs/lib/v3/tests/perform-understudy-method.spec.js.map +7 -0
  187. package/dist/cjs/lib/v3/tests/setinputfiles.spec.js +148 -0
  188. package/dist/cjs/lib/v3/tests/setinputfiles.spec.js.map +7 -0
  189. package/dist/cjs/lib/v3/tests/shadow-iframe-oopif.spec.js +156 -0
  190. package/dist/cjs/lib/v3/tests/shadow-iframe-oopif.spec.js.map +7 -0
  191. package/dist/cjs/lib/v3/tests/shadow-iframe-spif.spec.js +156 -0
  192. package/dist/cjs/lib/v3/tests/shadow-iframe-spif.spec.js.map +7 -0
  193. package/dist/cjs/lib/v3/tests/testUtils.js +54 -0
  194. package/dist/cjs/lib/v3/tests/testUtils.js.map +7 -0
  195. package/dist/cjs/lib/v3/tests/text-selector-innermost.spec.js +100 -0
  196. package/dist/cjs/lib/v3/tests/text-selector-innermost.spec.js.map +7 -0
  197. package/dist/cjs/lib/v3/tests/timeouts.spec.js +32 -0
  198. package/dist/cjs/lib/v3/tests/timeouts.spec.js.map +7 -0
  199. package/dist/cjs/lib/v3/tests/user-data-dir.spec.js +65 -0
  200. package/dist/cjs/lib/v3/tests/user-data-dir.spec.js.map +7 -0
  201. package/dist/cjs/lib/v3/tests/v3.config.js +36 -0
  202. package/dist/cjs/lib/v3/tests/v3.config.js.map +7 -0
  203. package/dist/cjs/lib/v3/tests/v3.dynamic.config.js +67 -0
  204. package/dist/cjs/lib/v3/tests/v3.dynamic.config.js.map +7 -0
  205. package/dist/cjs/lib/v3/tests/v3.playwright.config.js +61 -0
  206. package/dist/cjs/lib/v3/tests/v3.playwright.config.js.map +7 -0
  207. package/dist/cjs/lib/v3/tests/wait-for-selector.spec.js +593 -0
  208. package/dist/cjs/lib/v3/tests/wait-for-selector.spec.js.map +7 -0
  209. package/dist/cjs/lib/v3/tests/wait-for-timeout.spec.js +97 -0
  210. package/dist/cjs/lib/v3/tests/wait-for-timeout.spec.js.map +7 -0
  211. package/dist/cjs/lib/v3/tests/xpath-for-location-deep.spec.js +77 -0
  212. package/dist/cjs/lib/v3/tests/xpath-for-location-deep.spec.js.map +7 -0
  213. package/dist/cjs/lib/v3/timeoutConfig.d.ts +2 -0
  214. package/dist/cjs/lib/v3/types/private/agent.d.ts +6 -0
  215. package/dist/cjs/lib/v3/types/private/api.d.ts +11 -0
  216. package/dist/cjs/lib/v3/types/private/cache.d.ts +128 -0
  217. package/dist/cjs/lib/v3/types/private/evaluator.d.ts +40 -0
  218. package/dist/cjs/lib/v3/types/private/handlers.d.ts +38 -0
  219. package/dist/cjs/lib/v3/types/private/index.d.ts +7 -0
  220. package/dist/cjs/lib/v3/types/private/internal.d.ts +39 -0
  221. package/dist/cjs/lib/v3/types/private/locator.d.ts +9 -0
  222. package/dist/cjs/lib/v3/types/private/network.d.ts +34 -0
  223. package/dist/cjs/lib/v3/types/private/shutdown.d.ts +19 -0
  224. package/dist/cjs/lib/v3/types/private/shutdownErrors.d.ts +12 -0
  225. package/dist/cjs/lib/v3/types/private/snapshot.d.ts +117 -0
  226. package/dist/cjs/lib/v3/types/public/agent.d.ts +595 -0
  227. package/dist/cjs/lib/v3/types/public/api.d.ts +1211 -0
  228. package/dist/cjs/lib/v3/types/public/apiErrors.d.ts +18 -0
  229. package/dist/cjs/lib/v3/types/public/index.d.ts +12 -0
  230. package/dist/cjs/lib/v3/types/public/locator.d.ts +9 -0
  231. package/dist/cjs/lib/v3/types/public/logs.d.ts +23 -0
  232. package/dist/cjs/lib/v3/types/public/methods.d.ts +56 -0
  233. package/dist/cjs/lib/v3/types/public/metrics.d.ts +27 -0
  234. package/dist/cjs/lib/v3/types/public/model.d.ts +65 -0
  235. package/dist/cjs/lib/v3/types/public/options.d.ts +70 -0
  236. package/dist/cjs/lib/v3/types/public/page.d.ts +18 -0
  237. package/dist/cjs/lib/v3/types/public/screenshotTypes.d.ts +25 -0
  238. package/dist/cjs/lib/v3/types/public/sdkErrors.d.ts +152 -0
  239. package/dist/cjs/lib/v3/understudy/a11y/snapshot/a11yTree.d.ts +15 -0
  240. package/dist/cjs/lib/v3/understudy/a11y/snapshot/activeElement.d.ts +8 -0
  241. package/dist/cjs/lib/v3/understudy/a11y/snapshot/capture.d.ts +77 -0
  242. package/dist/cjs/lib/v3/understudy/a11y/snapshot/coordinateResolver.d.ts +7 -0
  243. package/dist/cjs/lib/v3/understudy/a11y/snapshot/domTree.d.ts +46 -0
  244. package/dist/cjs/lib/v3/understudy/a11y/snapshot/focusSelectors.d.ts +24 -0
  245. package/dist/cjs/lib/v3/understudy/a11y/snapshot/index.d.ts +4 -0
  246. package/dist/cjs/lib/v3/understudy/a11y/snapshot/sessions.d.ts +16 -0
  247. package/dist/cjs/lib/v3/understudy/a11y/snapshot/treeFormatUtils.d.ts +28 -0
  248. package/dist/cjs/lib/v3/understudy/a11y/snapshot/xpathUtils.d.ts +26 -0
  249. package/dist/cjs/lib/v3/understudy/a11yInvocation.d.ts +8 -0
  250. package/dist/cjs/lib/v3/understudy/cdp.d.ts +69 -0
  251. package/dist/cjs/lib/v3/understudy/consoleMessage.d.ts +22 -0
  252. package/dist/cjs/lib/v3/understudy/context.d.ts +132 -0
  253. package/dist/cjs/lib/v3/understudy/deepLocator.d.ts +87 -0
  254. package/dist/cjs/lib/v3/understudy/executionContextRegistry.d.ts +15 -0
  255. package/dist/cjs/lib/v3/understudy/fileUploadUtils.d.ts +13 -0
  256. package/dist/cjs/lib/v3/understudy/frame.d.ts +69 -0
  257. package/dist/cjs/lib/v3/understudy/frameLocator.d.ts +50 -0
  258. package/dist/cjs/lib/v3/understudy/frameRegistry.d.ts +101 -0
  259. package/dist/cjs/lib/v3/understudy/initScripts.d.ts +2 -0
  260. package/dist/cjs/lib/v3/understudy/lifecycleWatcher.d.ts +64 -0
  261. package/dist/cjs/lib/v3/understudy/locator.d.ts +194 -0
  262. package/dist/cjs/lib/v3/understudy/locatorInvocation.d.ts +8 -0
  263. package/dist/cjs/lib/v3/understudy/navigationResponseTracker.d.ts +84 -0
  264. package/dist/cjs/lib/v3/understudy/networkManager.d.ts +53 -0
  265. package/dist/cjs/lib/v3/understudy/page.d.ts +354 -0
  266. package/dist/cjs/lib/v3/understudy/piercer.d.ts +4 -0
  267. package/dist/cjs/lib/v3/understudy/response.d.ts +137 -0
  268. package/dist/cjs/lib/v3/understudy/screenshotUtils.d.ts +16 -0
  269. package/dist/cjs/lib/v3/understudy/selectorResolver.d.ts +38 -0
  270. package/dist/cjs/lib/v3/v3.d.ts +191 -0
  271. package/dist/cjs/lib/v3/zodCompat.d.ts +12 -0
  272. package/dist/cjs/lib/v3Evaluator.d.ts +19 -0
  273. package/dist/cjs/lib/version.d.ts +5 -0
  274. package/dist/cjs/package.json +3 -0
  275. package/dist/cjs/tests/browserbase-session-accessors.test.js +101 -0
  276. package/dist/cjs/tests/browserbase-session-accessors.test.js.map +7 -0
  277. package/dist/cjs/tests/cache-llm-resolution.test.js +187 -0
  278. package/dist/cjs/tests/cache-llm-resolution.test.js.map +7 -0
  279. package/dist/cjs/tests/helpers/mockCDPSession.js +50 -0
  280. package/dist/cjs/tests/helpers/mockCDPSession.js.map +7 -0
  281. package/dist/cjs/tests/llm-provider.test.js +57 -0
  282. package/dist/cjs/tests/llm-provider.test.js.map +7 -0
  283. package/dist/cjs/tests/model-deprecation.test.js +132 -0
  284. package/dist/cjs/tests/model-deprecation.test.js.map +7 -0
  285. package/dist/cjs/tests/page-snapshot.test.js +58 -0
  286. package/dist/cjs/tests/page-snapshot.test.js.map +7 -0
  287. package/dist/cjs/tests/public-api/export-surface.test.js +76 -0
  288. package/dist/cjs/tests/public-api/export-surface.test.js.map +7 -0
  289. package/dist/cjs/tests/public-api/llm-and-agents.test.js +150 -0
  290. package/dist/cjs/tests/public-api/llm-and-agents.test.js.map +7 -0
  291. package/dist/cjs/tests/public-api/public-error-types.test.js +104 -0
  292. package/dist/cjs/tests/public-api/public-error-types.test.js.map +7 -0
  293. package/dist/cjs/tests/public-api/public-types.test.js +74 -0
  294. package/dist/cjs/tests/public-api/public-types.test.js.map +7 -0
  295. package/dist/cjs/tests/public-api/runtime-utils.test.js +53 -0
  296. package/dist/cjs/tests/public-api/runtime-utils.test.js.map +7 -0
  297. package/dist/cjs/tests/public-api/schema-utils.test.js +100 -0
  298. package/dist/cjs/tests/public-api/schema-utils.test.js.map +7 -0
  299. package/dist/cjs/tests/public-api/timeout-error-types.test.js +103 -0
  300. package/dist/cjs/tests/public-api/timeout-error-types.test.js.map +7 -0
  301. package/dist/cjs/tests/public-api/tool-type-export.test.js +47 -0
  302. package/dist/cjs/tests/public-api/tool-type-export.test.js.map +7 -0
  303. package/dist/cjs/tests/public-api/v3-core.test.js +104 -0
  304. package/dist/cjs/tests/public-api/v3-core.test.js.map +7 -0
  305. package/dist/cjs/tests/safety-confirmation.test.js +134 -0
  306. package/dist/cjs/tests/safety-confirmation.test.js.map +7 -0
  307. package/dist/cjs/tests/snapshot-a11y-resolvers.test.js +370 -0
  308. package/dist/cjs/tests/snapshot-a11y-resolvers.test.js.map +7 -0
  309. package/dist/cjs/tests/snapshot-a11y-tree-utils.test.js +294 -0
  310. package/dist/cjs/tests/snapshot-a11y-tree-utils.test.js.map +7 -0
  311. package/dist/cjs/tests/snapshot-capture-orchestration.test.js +403 -0
  312. package/dist/cjs/tests/snapshot-capture-orchestration.test.js.map +7 -0
  313. package/dist/cjs/tests/snapshot-cbor.test.js +197 -0
  314. package/dist/cjs/tests/snapshot-cbor.test.js.map +7 -0
  315. package/dist/cjs/tests/snapshot-dom-session-builders.test.js +246 -0
  316. package/dist/cjs/tests/snapshot-dom-session-builders.test.js.map +7 -0
  317. package/dist/cjs/tests/snapshot-dom-tree-utils.test.js +104 -0
  318. package/dist/cjs/tests/snapshot-dom-tree-utils.test.js.map +7 -0
  319. package/dist/cjs/tests/snapshot-focus-selectors-utils.test.js +45 -0
  320. package/dist/cjs/tests/snapshot-focus-selectors-utils.test.js.map +7 -0
  321. package/dist/cjs/tests/snapshot-frame-merge.test.js +388 -0
  322. package/dist/cjs/tests/snapshot-frame-merge.test.js.map +7 -0
  323. package/dist/cjs/tests/snapshot-tree-format-utils.test.js +106 -0
  324. package/dist/cjs/tests/snapshot-tree-format-utils.test.js.map +7 -0
  325. package/dist/cjs/tests/snapshot-xpath-utils.test.js +74 -0
  326. package/dist/cjs/tests/snapshot-xpath-utils.test.js.map +7 -0
  327. package/dist/cjs/tests/timeout-handlers.test.js +864 -0
  328. package/dist/cjs/tests/timeout-handlers.test.js.map +7 -0
  329. package/dist/cjs/tests/xpath-parser.test.js +314 -0
  330. package/dist/cjs/tests/xpath-parser.test.js.map +7 -0
  331. package/dist/cjs/tests/xpath-resolver.test.js +70 -0
  332. package/dist/cjs/tests/xpath-resolver.test.js.map +7 -0
  333. package/dist/cjs/tests/zod-enum-compatibility.test.js +119 -0
  334. package/dist/cjs/tests/zod-enum-compatibility.test.js.map +7 -0
  335. package/dist/esm/lib/modelUtils.d.ts +0 -3
  336. package/dist/esm/lib/modelUtils.js +2 -7
  337. package/dist/esm/lib/modelUtils.js.map +1 -1
  338. package/dist/esm/lib/v3/agent/tools/act.d.ts +1 -2
  339. package/dist/esm/lib/v3/agent/tools/act.js.map +1 -1
  340. package/dist/esm/lib/v3/agent/tools/extract.d.ts +1 -2
  341. package/dist/esm/lib/v3/agent/tools/extract.js.map +1 -1
  342. package/dist/esm/lib/v3/agent/tools/fillform.d.ts +1 -2
  343. package/dist/esm/lib/v3/agent/tools/fillform.js.map +1 -1
  344. package/dist/esm/lib/v3/agent/tools/index.d.ts +2 -2
  345. package/dist/esm/lib/v3/agent/tools/index.js.map +1 -1
  346. package/dist/esm/lib/v3/cli.d.ts +2 -0
  347. package/dist/esm/lib/v3/cli.js +10 -0
  348. package/dist/esm/lib/v3/cli.js.map +1 -0
  349. package/dist/esm/lib/v3/dom/build/rerender-index.d.ts +0 -0
  350. package/dist/esm/lib/v3/dom/build/rerender-index.js.map +1 -0
  351. package/dist/esm/lib/v3/dom/build/v3-index.d.ts +0 -0
  352. package/dist/esm/lib/v3/dom/build/v3-index.js.map +1 -0
  353. package/dist/esm/lib/v3/handlers/v3AgentHandler.d.ts +2 -2
  354. package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
  355. package/dist/esm/lib/v3/index.d.ts +1 -0
  356. package/dist/esm/lib/v3/index.js +1 -0
  357. package/dist/esm/lib/v3/index.js.map +1 -1
  358. package/dist/esm/lib/v3/shutdown/supervisor.d.ts +7 -5
  359. package/dist/esm/lib/v3/shutdown/supervisor.js +62 -52
  360. package/dist/esm/lib/v3/shutdown/supervisor.js.map +1 -1
  361. package/dist/esm/lib/v3/shutdown/supervisorClient.js +48 -52
  362. package/dist/esm/lib/v3/shutdown/supervisorClient.js.map +1 -1
  363. package/dist/esm/lib/v3/tests/click-count.spec.js +47 -12
  364. package/dist/esm/lib/v3/tests/click-count.spec.js.map +2 -2
  365. package/dist/esm/lib/v3/tests/iframe-ctx-addInitScript.spec.js +67 -21
  366. package/dist/esm/lib/v3/tests/iframe-ctx-addInitScript.spec.js.map +2 -2
  367. package/dist/esm/lib/v3/tests/v3.playwright.config.js +3 -60
  368. package/dist/esm/lib/v3/tests/v3.playwright.config.js.map +2 -2
  369. package/dist/esm/lib/v3/types/private/shutdown.d.ts +1 -13
  370. package/dist/esm/lib/v3/types/private/shutdown.js.map +1 -1
  371. package/dist/esm/lib/v3/understudy/context.js +10 -1
  372. package/dist/esm/lib/v3/understudy/context.js.map +1 -1
  373. package/dist/esm/lib/v3/understudy/locator.js +2 -2
  374. package/dist/esm/lib/v3/understudy/locator.js.map +1 -1
  375. package/dist/esm/lib/v3/understudy/page.js +2 -1
  376. package/dist/esm/lib/v3/understudy/page.js.map +1 -1
  377. package/dist/esm/lib/v3/v3.js +10 -13
  378. package/dist/esm/lib/v3/v3.js.map +1 -1
  379. package/dist/esm/tests/public-api/export-surface.test.js +1 -0
  380. package/dist/esm/tests/public-api/export-surface.test.js.map +2 -2
  381. package/package.json +13 -9
  382. package/dist/esm/lib/v3/tests/envReporter.js +0 -57
  383. package/dist/esm/lib/v3/tests/envReporter.js.map +0 -7
  384. package/dist/esm/tests/agent-execution-model.test.js +0 -139
  385. package/dist/esm/tests/agent-execution-model.test.js.map +0 -7
  386. package/dist/esm/tests/model-utils.test.js +0 -43
  387. package/dist/esm/tests/model-utils.test.js.map +0 -7
@@ -11,6 +11,7 @@ export { V3Evaluator } from "../v3Evaluator.js";
11
11
  export { tool } from "ai";
12
12
  export { getAISDKLanguageModel } from "./llm/LLMProvider.js";
13
13
  export { __internalCreateInMemoryAgentCacheHandle } from "./cache/serverAgentCache.js";
14
+ export { maybeRunShutdownSupervisorFromArgv as __internalMaybeRunShutdownSupervisorFromArgv } from "./shutdown/supervisor.js";
14
15
  export type { ServerAgentCacheHandle } from "./cache/serverAgentCache.js";
15
16
  export type { ChatMessage, ChatMessageContent, ChatMessageImageContent, ChatMessageTextContent, ChatCompletionOptions, LLMResponse, CreateChatCompletionOptions, LLMUsage, LLMParsedResponse, } from "./llm/LLMClient.js";
16
17
  export type { StagehandZodSchema, StagehandZodObject, InferStagehandSchema, JsonSchemaDocument, } from "./zodCompat.js";
@@ -10,4 +10,5 @@ export { V3Evaluator } from "../v3Evaluator.js";
10
10
  export { tool } from "ai";
11
11
  export { getAISDKLanguageModel } from "./llm/LLMProvider.js";
12
12
  export { __internalCreateInMemoryAgentCacheHandle } from "./cache/serverAgentCache.js";
13
+ export { maybeRunShutdownSupervisorFromArgv as __internalMaybeRunShutdownSupervisorFromArgv } from "./shutdown/supervisor.js";
13
14
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/v3/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,EAAE,IAAI,SAAS,EAAE,MAAM,SAAS,CAAC;AAE1C,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EACL,aAAa,EACb,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AASlC,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,UAAU,EACV,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wCAAwC,EAAE,MAAM,6BAA6B,CAAC","sourcesContent":["export { V3 } from \"./v3.js\";\nexport { V3 as Stagehand } from \"./v3.js\";\n\nexport * from \"./types/public/index.js\";\nexport { AnnotatedScreenshotText, LLMClient } from \"./llm/LLMClient.js\";\n\nexport {\n AgentProvider,\n modelToAgentProviderMap,\n} from \"./agent/AgentProvider.js\";\nexport type {\n AgentTools,\n AgentToolTypesMap,\n AgentUITools,\n AgentToolCall,\n AgentToolResult,\n} from \"./agent/tools/index.js\";\n\nexport {\n validateZodSchema,\n isRunningInBun,\n toGeminiSchema,\n getZodType,\n transformSchema,\n injectUrls,\n providerEnvVarMap,\n loadApiKeyFromEnv,\n trimTrailingTextNode,\n jsonSchemaToZod,\n} from \"../utils.js\";\nexport { isZod4Schema, isZod3Schema, toJsonSchema } from \"./zodCompat.js\";\n\nexport { connectToMCPServer } from \"./mcp/connection.js\";\nexport { V3Evaluator } from \"../v3Evaluator.js\";\nexport { tool } from \"ai\";\nexport { getAISDKLanguageModel } from \"./llm/LLMProvider.js\";\nexport { __internalCreateInMemoryAgentCacheHandle } from \"./cache/serverAgentCache.js\";\nexport type { ServerAgentCacheHandle } from \"./cache/serverAgentCache.js\";\n\nexport type {\n ChatMessage,\n ChatMessageContent,\n ChatMessageImageContent,\n ChatMessageTextContent,\n ChatCompletionOptions,\n LLMResponse,\n CreateChatCompletionOptions,\n LLMUsage,\n LLMParsedResponse,\n} from \"./llm/LLMClient.js\";\n\nexport type {\n StagehandZodSchema,\n StagehandZodObject,\n InferStagehandSchema,\n JsonSchemaDocument,\n} from \"./zodCompat.js\";\n\nexport type { JsonSchema, JsonSchemaProperty } from \"../utils.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/v3/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EAAE,EAAE,IAAI,SAAS,EAAE,MAAM,SAAS,CAAC;AAE1C,cAAc,yBAAyB,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EACL,aAAa,EACb,uBAAuB,GACxB,MAAM,0BAA0B,CAAC;AASlC,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,UAAU,EACV,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC1B,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wCAAwC,EAAE,MAAM,6BAA6B,CAAC;AACvF,OAAO,EAAE,kCAAkC,IAAI,4CAA4C,EAAE,MAAM,0BAA0B,CAAC","sourcesContent":["export { V3 } from \"./v3.js\";\nexport { V3 as Stagehand } from \"./v3.js\";\n\nexport * from \"./types/public/index.js\";\nexport { AnnotatedScreenshotText, LLMClient } from \"./llm/LLMClient.js\";\n\nexport {\n AgentProvider,\n modelToAgentProviderMap,\n} from \"./agent/AgentProvider.js\";\nexport type {\n AgentTools,\n AgentToolTypesMap,\n AgentUITools,\n AgentToolCall,\n AgentToolResult,\n} from \"./agent/tools/index.js\";\n\nexport {\n validateZodSchema,\n isRunningInBun,\n toGeminiSchema,\n getZodType,\n transformSchema,\n injectUrls,\n providerEnvVarMap,\n loadApiKeyFromEnv,\n trimTrailingTextNode,\n jsonSchemaToZod,\n} from \"../utils.js\";\nexport { isZod4Schema, isZod3Schema, toJsonSchema } from \"./zodCompat.js\";\n\nexport { connectToMCPServer } from \"./mcp/connection.js\";\nexport { V3Evaluator } from \"../v3Evaluator.js\";\nexport { tool } from \"ai\";\nexport { getAISDKLanguageModel } from \"./llm/LLMProvider.js\";\nexport { __internalCreateInMemoryAgentCacheHandle } from \"./cache/serverAgentCache.js\";\nexport { maybeRunShutdownSupervisorFromArgv as __internalMaybeRunShutdownSupervisorFromArgv } from \"./shutdown/supervisor.js\";\nexport type { ServerAgentCacheHandle } from \"./cache/serverAgentCache.js\";\n\nexport type {\n ChatMessage,\n ChatMessageContent,\n ChatMessageImageContent,\n ChatMessageTextContent,\n ChatCompletionOptions,\n LLMResponse,\n CreateChatCompletionOptions,\n LLMUsage,\n LLMParsedResponse,\n} from \"./llm/LLMClient.js\";\n\nexport type {\n StagehandZodSchema,\n StagehandZodObject,\n InferStagehandSchema,\n JsonSchemaDocument,\n} from \"./zodCompat.js\";\n\nexport type { JsonSchema, JsonSchemaProperty } from \"../utils.js\";\n"]}
@@ -1,9 +1,11 @@
1
1
  /**
2
2
  * Shutdown supervisor process.
3
3
  *
4
- * This process watches a lifeline (stdin/IPC). When the parent dies, the
5
- * lifeline closes and the supervisor performs best-effort cleanup:
6
- * - LOCAL: kill Chrome + remove temp profile (when keepAlive is false)
7
- * - STAGEHAND_API: request session release (when keepAlive is false)
4
+ * This process watches a stdin lifeline. When the parent dies, stdin closes
5
+ * and the supervisor performs best-effort cleanup:
6
+ * - LOCAL: kill Chrome + remove temp profile
7
+ * - STAGEHAND_API: request session release
8
8
  */
9
- export {};
9
+ import type { ShutdownSupervisorConfig } from "../types/private/shutdown.js";
10
+ export declare const runShutdownSupervisor: (initialConfig: ShutdownSupervisorConfig) => void;
11
+ export declare const maybeRunShutdownSupervisorFromArgv: (argv?: readonly string[]) => boolean;
@@ -1,19 +1,20 @@
1
1
  /**
2
2
  * Shutdown supervisor process.
3
3
  *
4
- * This process watches a lifeline (stdin/IPC). When the parent dies, the
5
- * lifeline closes and the supervisor performs best-effort cleanup:
6
- * - LOCAL: kill Chrome + remove temp profile (when keepAlive is false)
7
- * - STAGEHAND_API: request session release (when keepAlive is false)
4
+ * This process watches a stdin lifeline. When the parent dies, stdin closes
5
+ * and the supervisor performs best-effort cleanup:
6
+ * - LOCAL: kill Chrome + remove temp profile
7
+ * - STAGEHAND_API: request session release
8
8
  */
9
9
  import Browserbase from "@browserbasehq/sdk";
10
10
  import { cleanupLocalBrowser } from "./cleanupLocal.js";
11
- const SIGKILL_POLL_MS = 500;
12
- const SIGKILL_TIMEOUT_MS = 10_000;
11
+ const SIGKILL_POLL_MS = 250;
12
+ const SIGKILL_TIMEOUT_MS = 7_000;
13
13
  const PID_POLL_INTERVAL_MS = 500;
14
- let armed = false;
14
+ // `cleanupPromise` guarantees we execute cleanup at most once.
15
15
  let config = null;
16
16
  let cleanupPromise = null;
17
+ let started = false;
17
18
  const exit = (code = 0) => {
18
19
  try {
19
20
  process.exit(code);
@@ -22,14 +23,18 @@ const exit = (code = 0) => {
22
23
  // ignore
23
24
  }
24
25
  };
25
- const safeKill = async (pid) => {
26
+ // Best-effort two-phase kill: SIGTERM first, then SIGKILL after timeout.
27
+ // Treat only ESRCH as "already gone"; other errors should not imply dead.
28
+ const politeKill = async (pid) => {
26
29
  const isAlive = () => {
27
30
  try {
28
31
  process.kill(pid, 0);
29
32
  return true;
30
33
  }
31
- catch {
32
- return false;
34
+ catch (error) {
35
+ const err = error;
36
+ // ESRCH = "No such process" (PID is already gone).
37
+ return err.code !== "ESRCH";
33
38
  }
34
39
  };
35
40
  if (!isAlive())
@@ -37,8 +42,11 @@ const safeKill = async (pid) => {
37
42
  try {
38
43
  process.kill(pid, "SIGTERM");
39
44
  }
40
- catch {
41
- return;
45
+ catch (error) {
46
+ const err = error;
47
+ // ESRCH = process already exited; no further action needed.
48
+ if (err.code === "ESRCH")
49
+ return;
42
50
  }
43
51
  const deadline = Date.now() + SIGKILL_TIMEOUT_MS;
44
52
  while (Date.now() < deadline) {
@@ -53,8 +61,8 @@ const safeKill = async (pid) => {
53
61
  // best-effort
54
62
  }
55
63
  };
56
- let pidGone = false;
57
64
  let pidPollTimer = null;
65
+ // Local-only fallback: if Chrome dies while parent still lives, run cleanup and exit.
58
66
  const startPidPolling = (pid) => {
59
67
  if (pidPollTimer)
60
68
  return;
@@ -63,27 +71,23 @@ const startPidPolling = (pid) => {
63
71
  process.kill(pid, 0);
64
72
  }
65
73
  catch {
66
- pidGone = true;
67
74
  if (pidPollTimer) {
68
75
  clearInterval(pidPollTimer);
69
76
  pidPollTimer = null;
70
77
  }
78
+ void runCleanup().finally(() => exit(0));
71
79
  }
72
80
  }, PID_POLL_INTERVAL_MS);
73
81
  };
74
82
  const cleanupLocal = async (cfg) => {
75
- if (cfg.keepAlive)
76
- return;
77
83
  await cleanupLocalBrowser({
78
- killChrome: cfg.pid && !pidGone ? () => safeKill(cfg.pid) : undefined,
84
+ killChrome: cfg.pid ? () => politeKill(cfg.pid) : undefined,
79
85
  userDataDir: cfg.userDataDir,
80
86
  createdTempProfile: cfg.createdTempProfile,
81
87
  preserveUserDataDir: cfg.preserveUserDataDir,
82
88
  });
83
89
  };
84
90
  const cleanupBrowserbase = async (cfg) => {
85
- if (cfg.keepAlive)
86
- return;
87
91
  if (!cfg.apiKey || !cfg.projectId || !cfg.sessionId)
88
92
  return;
89
93
  try {
@@ -97,13 +101,13 @@ const cleanupBrowserbase = async (cfg) => {
97
101
  // best-effort cleanup
98
102
  }
99
103
  };
104
+ // Idempotent cleanup entrypoint used by all supervisor shutdown paths.
100
105
  const runCleanup = () => {
101
106
  if (!cleanupPromise) {
102
107
  cleanupPromise = (async () => {
103
108
  const cfg = config;
104
- if (!cfg || !armed)
109
+ if (!cfg)
105
110
  return;
106
- armed = false;
107
111
  if (cfg.kind === "LOCAL") {
108
112
  await cleanupLocal(cfg);
109
113
  return;
@@ -115,42 +119,48 @@ const runCleanup = () => {
115
119
  }
116
120
  return cleanupPromise;
117
121
  };
122
+ const applyConfig = (nextConfig) => {
123
+ config = nextConfig;
124
+ if (config.kind === "LOCAL" && config.pid) {
125
+ startPidPolling(config.pid);
126
+ }
127
+ };
118
128
  const onLifelineClosed = () => {
119
129
  void runCleanup().finally(() => exit(0));
120
130
  };
121
- const onMessage = (raw) => {
122
- if (!raw || typeof raw !== "object")
123
- return;
124
- const msg = raw;
125
- if (msg.type === "config") {
126
- config = msg.config ?? null;
127
- armed = Boolean(config) && config?.keepAlive === false;
128
- if (armed && config?.kind === "LOCAL" && config?.pid) {
129
- startPidPolling(config.pid);
130
- }
131
- try {
132
- process.send?.({ type: "ready" });
133
- }
134
- catch {
135
- // ignore IPC failures
136
- }
131
+ const parseConfigFromArgv = (argv = process.argv.slice(2)) => {
132
+ const prefix = "--supervisor-config=";
133
+ const raw = argv.find((arg) => arg.startsWith(prefix))?.slice(prefix.length);
134
+ if (!argv.includes("--supervisor") || !raw)
135
+ return null;
136
+ try {
137
+ return JSON.parse(raw);
138
+ }
139
+ catch {
140
+ return null;
141
+ }
142
+ };
143
+ export const runShutdownSupervisor = (initialConfig) => {
144
+ if (started)
137
145
  return;
146
+ started = true;
147
+ applyConfig(initialConfig);
148
+ // Stdin is the lifeline; losing it means parent is gone.
149
+ try {
150
+ process.stdin.resume();
151
+ process.stdin.on("end", onLifelineClosed);
152
+ process.stdin.on("close", onLifelineClosed);
153
+ process.stdin.on("error", onLifelineClosed);
138
154
  }
139
- if (msg.type === "exit") {
140
- armed = false;
141
- exit(0);
155
+ catch {
156
+ // ignore
142
157
  }
143
158
  };
144
- // Keep stdin open as a lifeline to the parent process.
145
- try {
146
- process.stdin.resume();
147
- process.stdin.on("end", onLifelineClosed);
148
- process.stdin.on("close", onLifelineClosed);
149
- process.stdin.on("error", onLifelineClosed);
150
- }
151
- catch {
152
- // ignore
153
- }
154
- process.on("disconnect", onLifelineClosed);
155
- process.on("message", onMessage);
159
+ export const maybeRunShutdownSupervisorFromArgv = (argv = process.argv.slice(2)) => {
160
+ const parsed = parseConfigFromArgv(argv);
161
+ if (!parsed)
162
+ return false;
163
+ runShutdownSupervisor(parsed);
164
+ return true;
165
+ };
156
166
  //# sourceMappingURL=supervisor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../../../../../lib/v3/shutdown/supervisor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shutdown supervisor process.\n *\n * This process watches a lifeline (stdin/IPC). When the parent dies, the\n * lifeline closes and the supervisor performs best-effort cleanup:\n * - LOCAL: kill Chrome + remove temp profile (when keepAlive is false)\n * - STAGEHAND_API: request session release (when keepAlive is false)\n */\n\nimport Browserbase from \"@browserbasehq/sdk\";\nimport type {\n ShutdownSupervisorConfig,\n ShutdownSupervisorMessage,\n} from \"../types/private/shutdown.js\";\nimport { cleanupLocalBrowser } from \"./cleanupLocal.js\";\n\nconst SIGKILL_POLL_MS = 500;\nconst SIGKILL_TIMEOUT_MS = 10_000;\nconst PID_POLL_INTERVAL_MS = 500;\n\nlet armed = false;\nlet config: ShutdownSupervisorConfig | null = null;\nlet cleanupPromise: Promise<void> | null = null;\n\nconst exit = (code = 0): void => {\n try {\n process.exit(code);\n } catch {\n // ignore\n }\n};\n\nconst safeKill = async (pid: number): Promise<void> => {\n const isAlive = (): boolean => {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n };\n\n if (!isAlive()) return;\n try {\n process.kill(pid, \"SIGTERM\");\n } catch {\n return;\n }\n\n const deadline = Date.now() + SIGKILL_TIMEOUT_MS;\n while (Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, SIGKILL_POLL_MS));\n if (!isAlive()) return;\n }\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {\n // best-effort\n }\n};\n\nlet pidGone = false;\nlet pidPollTimer: NodeJS.Timeout | null = null;\n\nconst startPidPolling = (pid: number): void => {\n if (pidPollTimer) return;\n pidPollTimer = setInterval(() => {\n try {\n process.kill(pid, 0);\n } catch {\n pidGone = true;\n if (pidPollTimer) {\n clearInterval(pidPollTimer);\n pidPollTimer = null;\n }\n }\n }, PID_POLL_INTERVAL_MS);\n};\n\nconst cleanupLocal = async (\n cfg: Extract<ShutdownSupervisorConfig, { kind: \"LOCAL\" }>,\n) => {\n if (cfg.keepAlive) return;\n await cleanupLocalBrowser({\n killChrome: cfg.pid && !pidGone ? () => safeKill(cfg.pid) : undefined,\n userDataDir: cfg.userDataDir,\n createdTempProfile: cfg.createdTempProfile,\n preserveUserDataDir: cfg.preserveUserDataDir,\n });\n};\n\nconst cleanupBrowserbase = async (\n cfg: Extract<ShutdownSupervisorConfig, { kind: \"STAGEHAND_API\" }>,\n) => {\n if (cfg.keepAlive) return;\n if (!cfg.apiKey || !cfg.projectId || !cfg.sessionId) return;\n try {\n const bb = new Browserbase({ apiKey: cfg.apiKey });\n await bb.sessions.update(cfg.sessionId, {\n status: \"REQUEST_RELEASE\",\n projectId: cfg.projectId,\n });\n } catch {\n // best-effort cleanup\n }\n};\n\nconst runCleanup = (): Promise<void> => {\n if (!cleanupPromise) {\n cleanupPromise = (async () => {\n const cfg = config;\n if (!cfg || !armed) return;\n armed = false;\n if (cfg.kind === \"LOCAL\") {\n await cleanupLocal(cfg);\n return;\n }\n if (cfg.kind === \"STAGEHAND_API\") {\n await cleanupBrowserbase(cfg);\n }\n })();\n }\n return cleanupPromise;\n};\n\nconst onLifelineClosed = () => {\n void runCleanup().finally(() => exit(0));\n};\n\nconst onMessage = (raw: unknown) => {\n if (!raw || typeof raw !== \"object\") return;\n const msg = raw as ShutdownSupervisorMessage;\n if (msg.type === \"config\") {\n config = msg.config ?? null;\n armed = Boolean(config) && config?.keepAlive === false;\n if (armed && config?.kind === \"LOCAL\" && config?.pid) {\n startPidPolling(config.pid);\n }\n try {\n process.send?.({ type: \"ready\" });\n } catch {\n // ignore IPC failures\n }\n return;\n }\n if (msg.type === \"exit\") {\n armed = false;\n exit(0);\n }\n};\n\n// Keep stdin open as a lifeline to the parent process.\ntry {\n process.stdin.resume();\n process.stdin.on(\"end\", onLifelineClosed);\n process.stdin.on(\"close\", onLifelineClosed);\n process.stdin.on(\"error\", onLifelineClosed);\n} catch {\n // ignore\n}\n\nprocess.on(\"disconnect\", onLifelineClosed);\nprocess.on(\"message\", onMessage);\n"]}
1
+ {"version":3,"file":"supervisor.js","sourceRoot":"","sources":["../../../../../lib/v3/shutdown/supervisor.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shutdown supervisor process.\n *\n * This process watches a stdin lifeline. When the parent dies, stdin closes\n * and the supervisor performs best-effort cleanup:\n * - LOCAL: kill Chrome + remove temp profile\n * - STAGEHAND_API: request session release\n */\n\nimport Browserbase from \"@browserbasehq/sdk\";\nimport type { ShutdownSupervisorConfig } from \"../types/private/shutdown.js\";\nimport { cleanupLocalBrowser } from \"./cleanupLocal.js\";\n\nconst SIGKILL_POLL_MS = 250;\nconst SIGKILL_TIMEOUT_MS = 7_000;\nconst PID_POLL_INTERVAL_MS = 500;\n\n// `cleanupPromise` guarantees we execute cleanup at most once.\nlet config: ShutdownSupervisorConfig | null = null;\nlet cleanupPromise: Promise<void> | null = null;\nlet started = false;\n\nconst exit = (code = 0): void => {\n try {\n process.exit(code);\n } catch {\n // ignore\n }\n};\n\n// Best-effort two-phase kill: SIGTERM first, then SIGKILL after timeout.\n// Treat only ESRCH as \"already gone\"; other errors should not imply dead.\nconst politeKill = async (pid: number): Promise<void> => {\n const isAlive = (): boolean => {\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n // ESRCH = \"No such process\" (PID is already gone).\n return err.code !== \"ESRCH\";\n }\n };\n\n if (!isAlive()) return;\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (error) {\n const err = error as NodeJS.ErrnoException;\n // ESRCH = process already exited; no further action needed.\n if (err.code === \"ESRCH\") return;\n }\n\n const deadline = Date.now() + SIGKILL_TIMEOUT_MS;\n while (Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, SIGKILL_POLL_MS));\n if (!isAlive()) return;\n }\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {\n // best-effort\n }\n};\n\nlet pidPollTimer: NodeJS.Timeout | null = null;\n\n// Local-only fallback: if Chrome dies while parent still lives, run cleanup and exit.\nconst startPidPolling = (pid: number): void => {\n if (pidPollTimer) return;\n pidPollTimer = setInterval(() => {\n try {\n process.kill(pid, 0);\n } catch {\n if (pidPollTimer) {\n clearInterval(pidPollTimer);\n pidPollTimer = null;\n }\n void runCleanup().finally(() => exit(0));\n }\n }, PID_POLL_INTERVAL_MS);\n};\n\nconst cleanupLocal = async (\n cfg: Extract<ShutdownSupervisorConfig, { kind: \"LOCAL\" }>,\n) => {\n await cleanupLocalBrowser({\n killChrome: cfg.pid ? () => politeKill(cfg.pid) : undefined,\n userDataDir: cfg.userDataDir,\n createdTempProfile: cfg.createdTempProfile,\n preserveUserDataDir: cfg.preserveUserDataDir,\n });\n};\n\nconst cleanupBrowserbase = async (\n cfg: Extract<ShutdownSupervisorConfig, { kind: \"STAGEHAND_API\" }>,\n) => {\n if (!cfg.apiKey || !cfg.projectId || !cfg.sessionId) return;\n try {\n const bb = new Browserbase({ apiKey: cfg.apiKey });\n await bb.sessions.update(cfg.sessionId, {\n status: \"REQUEST_RELEASE\",\n projectId: cfg.projectId,\n });\n } catch {\n // best-effort cleanup\n }\n};\n\n// Idempotent cleanup entrypoint used by all supervisor shutdown paths.\nconst runCleanup = (): Promise<void> => {\n if (!cleanupPromise) {\n cleanupPromise = (async () => {\n const cfg = config;\n if (!cfg) return;\n if (cfg.kind === \"LOCAL\") {\n await cleanupLocal(cfg);\n return;\n }\n if (cfg.kind === \"STAGEHAND_API\") {\n await cleanupBrowserbase(cfg);\n }\n })();\n }\n return cleanupPromise;\n};\n\nconst applyConfig = (nextConfig: ShutdownSupervisorConfig): void => {\n config = nextConfig;\n if (config.kind === \"LOCAL\" && config.pid) {\n startPidPolling(config.pid);\n }\n};\n\nconst onLifelineClosed = () => {\n void runCleanup().finally(() => exit(0));\n};\n\nconst parseConfigFromArgv = (\n argv: readonly string[] = process.argv.slice(2),\n): ShutdownSupervisorConfig | null => {\n const prefix = \"--supervisor-config=\";\n const raw = argv.find((arg) => arg.startsWith(prefix))?.slice(prefix.length);\n if (!argv.includes(\"--supervisor\") || !raw) return null;\n try {\n return JSON.parse(raw) as ShutdownSupervisorConfig;\n } catch {\n return null;\n }\n};\n\nexport const runShutdownSupervisor = (\n initialConfig: ShutdownSupervisorConfig,\n): void => {\n if (started) return;\n started = true;\n applyConfig(initialConfig);\n\n // Stdin is the lifeline; losing it means parent is gone.\n try {\n process.stdin.resume();\n process.stdin.on(\"end\", onLifelineClosed);\n process.stdin.on(\"close\", onLifelineClosed);\n process.stdin.on(\"error\", onLifelineClosed);\n } catch {\n // ignore\n }\n};\n\nexport const maybeRunShutdownSupervisorFromArgv = (\n argv: readonly string[] = process.argv.slice(2),\n): boolean => {\n const parsed = parseConfigFromArgv(argv);\n if (!parsed) return false;\n runShutdownSupervisor(parsed);\n return true;\n};\n"]}
@@ -6,37 +6,66 @@
6
6
  * session release) when keepAlive is false.
7
7
  */
8
8
  import fs from "node:fs";
9
- import path from "node:path";
10
9
  import { spawn } from "node:child_process";
10
+ import { createRequire } from "node:module";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import { ShutdownSupervisorResolveError, ShutdownSupervisorSpawnError, } from "../types/private/shutdownErrors.js";
13
- const READY_TIMEOUT_MS = 500;
14
- // Prefer import.meta.url always correct per-module in ESM.
15
- // __dirname may be an incorrect polyfill in some tsx / loader configurations.
16
- const thisDir = path.dirname(fileURLToPath(import.meta.url));
17
- const resolveSupervisorScript = () => {
18
- const jsPath = path.resolve(thisDir, "supervisor.js");
19
- if (fs.existsSync(jsPath)) {
20
- return { command: process.execPath, args: [jsPath] };
13
+ // Resolve module path for both CJS and ESM builds.
14
+ const normalizedFilename = typeof __filename === "string" ? __filename.replaceAll("\\", "/") : "";
15
+ const hasAbsoluteFilename = normalizedFilename.startsWith("/") || /^[A-Za-z]:\//.test(normalizedFilename);
16
+ const modulePath = hasAbsoluteFilename
17
+ ? __filename
18
+ : fileURLToPath(import.meta.url);
19
+ const normalizedModulePath = modulePath.replaceAll("\\", "/");
20
+ const moduleDir = normalizedModulePath.slice(0, normalizedModulePath.lastIndexOf("/"));
21
+ const require = createRequire(modulePath);
22
+ const isSeaRuntime = () => {
23
+ try {
24
+ const sea = require("node:sea");
25
+ return Boolean(sea.isSea?.());
26
+ }
27
+ catch {
28
+ return false;
21
29
  }
22
- const tsPath = path.resolve(thisDir, "supervisor.ts");
23
- if (fs.existsSync(tsPath)) {
24
- return { command: process.execPath, args: ["--import", "tsx", tsPath] };
30
+ };
31
+ // SEA: re-exec current binary with supervisor args.
32
+ // Non-SEA: execute Stagehand CLI entrypoint with supervisor args.
33
+ const resolveSupervisorCommand = (config) => {
34
+ const baseArgs = ["--supervisor", serializeConfigArg(config)];
35
+ if (isSeaRuntime()) {
36
+ return { command: process.execPath, args: baseArgs };
25
37
  }
26
- return null;
38
+ const cliPathCandidates = [`${moduleDir}/../cli.js`, `${moduleDir}/cli.js`];
39
+ const cliPath = cliPathCandidates.find((candidate) => fs.existsSync(candidate)) ?? null;
40
+ if (!cliPath)
41
+ return null;
42
+ const needsTsxLoader = fs.existsSync(`${moduleDir}/supervisor.ts`) &&
43
+ !fs.existsSync(`${moduleDir}/supervisor.js`);
44
+ return {
45
+ command: process.execPath,
46
+ args: needsTsxLoader
47
+ ? ["--import", "tsx", cliPath, ...baseArgs]
48
+ : [cliPath, ...baseArgs],
49
+ };
27
50
  };
51
+ // Single JSON arg keeps supervisor bootstrap parsing tiny and versionable.
52
+ const serializeConfigArg = (config) => `--supervisor-config=${JSON.stringify({
53
+ ...config,
54
+ parentPid: process.pid,
55
+ })}`;
28
56
  /**
29
57
  * Start a supervisor process for crash cleanup. Returns a handle that can
30
58
  * stop the supervisor during a normal shutdown.
31
59
  */
32
60
  export function startShutdownSupervisor(config, opts) {
33
- const resolved = resolveSupervisorScript();
61
+ const resolved = resolveSupervisorCommand(config);
34
62
  if (!resolved) {
35
- opts?.onError?.(new ShutdownSupervisorResolveError(`Shutdown supervisor script missing (searched ${thisDir} for supervisor.js or supervisor.ts).`), "resolve");
63
+ opts?.onError?.(new ShutdownSupervisorResolveError("Shutdown supervisor entry missing (expected Stagehand CLI entrypoint)."), "resolve");
36
64
  return null;
37
65
  }
38
66
  const child = spawn(resolved.command, resolved.args, {
39
- stdio: ["pipe", "ignore", "ignore", "ipc"],
67
+ // stdin is the parent lifeline.
68
+ stdio: ["pipe", "ignore", "ignore"],
40
69
  detached: true,
41
70
  });
42
71
  child.on("error", (error) => {
@@ -50,48 +79,15 @@ export function startShutdownSupervisor(config, opts) {
50
79
  catch {
51
80
  // best-effort: avoid keeping the event loop alive
52
81
  }
53
- try {
54
- const message = { type: "config", config };
55
- child.send?.(message);
56
- }
57
- catch {
58
- // ignore IPC failures
59
- }
60
- const ready = new Promise((resolve) => {
61
- let resolved = false;
62
- const done = () => {
63
- if (resolved)
64
- return;
65
- resolved = true;
66
- clearTimeout(timer);
67
- child.off("message", onMessage);
68
- resolve();
69
- };
70
- const timer = setTimeout(done, READY_TIMEOUT_MS);
71
- const onMessage = (msg) => {
72
- const payload = msg;
73
- if (payload?.type === "ready") {
74
- done();
75
- }
76
- };
77
- child.on("message", onMessage);
78
- child.on("exit", done);
79
- });
80
82
  const stop = () => {
83
+ // Normal close path: terminate supervisor directly.
81
84
  try {
82
- const message = { type: "exit" };
83
- child.send?.(message);
84
- }
85
- catch {
86
- // ignore
87
- }
88
- try {
89
- child.disconnect?.();
85
+ child.kill("SIGTERM");
90
86
  }
91
87
  catch {
92
88
  // ignore
93
89
  }
94
90
  };
95
- return { stop, ready };
91
+ return { stop };
96
92
  }
97
93
  //# sourceMappingURL=supervisorClient.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"supervisorClient.js","sourceRoot":"","sources":["../../../../../lib/v3/shutdown/supervisorClient.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Parent-side helper for spawning the shutdown supervisor process.\n *\n * The supervisor runs out-of-process and watches a lifeline pipe. If the parent\n * dies, the supervisor performs best-effort cleanup (Chrome kill or Browserbase\n * session release) when keepAlive is false.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n ShutdownSupervisorConfig,\n ShutdownSupervisorHandle,\n ShutdownSupervisorMessage,\n} from \"../types/private/shutdown.js\";\nimport {\n ShutdownSupervisorResolveError,\n ShutdownSupervisorSpawnError,\n} from \"../types/private/shutdownErrors.js\";\n\nconst READY_TIMEOUT_MS = 500;\n// Prefer import.meta.url always correct per-module in ESM.\n// __dirname may be an incorrect polyfill in some tsx / loader configurations.\nconst thisDir = path.dirname(fileURLToPath(import.meta.url));\n\nconst resolveSupervisorScript = (): {\n command: string;\n args: string[];\n} | null => {\n const jsPath = path.resolve(thisDir, \"supervisor.js\");\n if (fs.existsSync(jsPath)) {\n return { command: process.execPath, args: [jsPath] };\n }\n const tsPath = path.resolve(thisDir, \"supervisor.ts\");\n if (fs.existsSync(tsPath)) {\n return { command: process.execPath, args: [\"--import\", \"tsx\", tsPath] };\n }\n return null;\n};\n\n/**\n * Start a supervisor process for crash cleanup. Returns a handle that can\n * stop the supervisor during a normal shutdown.\n */\nexport function startShutdownSupervisor(\n config: ShutdownSupervisorConfig,\n opts?: { onError?: (error: Error, context: string) => void },\n): ShutdownSupervisorHandle | null {\n const resolved = resolveSupervisorScript();\n if (!resolved) {\n opts?.onError?.(\n new ShutdownSupervisorResolveError(\n `Shutdown supervisor script missing (searched ${thisDir} for supervisor.js or supervisor.ts).`,\n ),\n \"resolve\",\n );\n return null;\n }\n\n const child = spawn(resolved.command, resolved.args, {\n stdio: [\"pipe\", \"ignore\", \"ignore\", \"ipc\"],\n detached: true,\n });\n child.on(\"error\", (error) => {\n opts?.onError?.(\n new ShutdownSupervisorSpawnError(\n `Shutdown supervisor failed to start: ${error.message}`,\n ),\n \"spawn\",\n );\n });\n\n try {\n child.unref();\n const stdin = child.stdin as unknown as { unref?: () => void } | null;\n stdin?.unref?.();\n } catch {\n // best-effort: avoid keeping the event loop alive\n }\n\n try {\n const message: ShutdownSupervisorMessage = { type: \"config\", config };\n child.send?.(message);\n } catch {\n // ignore IPC failures\n }\n\n const ready = new Promise<void>((resolve) => {\n let resolved = false;\n const done = () => {\n if (resolved) return;\n resolved = true;\n clearTimeout(timer);\n child.off(\"message\", onMessage);\n resolve();\n };\n const timer = setTimeout(done, READY_TIMEOUT_MS);\n const onMessage = (msg: unknown) => {\n const payload = msg as ShutdownSupervisorMessage;\n if (payload?.type === \"ready\") {\n done();\n }\n };\n child.on(\"message\", onMessage);\n child.on(\"exit\", done);\n });\n\n const stop = () => {\n try {\n const message: ShutdownSupervisorMessage = { type: \"exit\" };\n child.send?.(message);\n } catch {\n // ignore\n }\n try {\n child.disconnect?.();\n } catch {\n // ignore\n }\n };\n\n return { stop, ready };\n}\n"]}
1
+ {"version":3,"file":"supervisorClient.js","sourceRoot":"","sources":["../../../../../lib/v3/shutdown/supervisorClient.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Parent-side helper for spawning the shutdown supervisor process.\n *\n * The supervisor runs out-of-process and watches a lifeline pipe. If the parent\n * dies, the supervisor performs best-effort cleanup (Chrome kill or Browserbase\n * session release) when keepAlive is false.\n */\n\nimport fs from \"node:fs\";\nimport { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport { fileURLToPath } from \"node:url\";\nimport type {\n ShutdownSupervisorConfig,\n ShutdownSupervisorHandle,\n} from \"../types/private/shutdown.js\";\nimport {\n ShutdownSupervisorResolveError,\n ShutdownSupervisorSpawnError,\n} from \"../types/private/shutdownErrors.js\";\n// Resolve module path for both CJS and ESM builds.\nconst normalizedFilename =\n typeof __filename === \"string\" ? __filename.replaceAll(\"\\\\\", \"/\") : \"\";\nconst hasAbsoluteFilename =\n normalizedFilename.startsWith(\"/\") || /^[A-Za-z]:\\//.test(normalizedFilename);\nconst modulePath = hasAbsoluteFilename\n ? __filename\n : fileURLToPath(import.meta.url);\nconst normalizedModulePath = modulePath.replaceAll(\"\\\\\", \"/\");\nconst moduleDir = normalizedModulePath.slice(\n 0,\n normalizedModulePath.lastIndexOf(\"/\"),\n);\nconst require = createRequire(modulePath);\n\nconst isSeaRuntime = (): boolean => {\n try {\n const sea = require(\"node:sea\") as { isSea?: () => boolean };\n return Boolean(sea.isSea?.());\n } catch {\n return false;\n }\n};\n\n// SEA: re-exec current binary with supervisor args.\n// Non-SEA: execute Stagehand CLI entrypoint with supervisor args.\nconst resolveSupervisorCommand = (\n config: ShutdownSupervisorConfig,\n): {\n command: string;\n args: string[];\n} | null => {\n const baseArgs = [\"--supervisor\", serializeConfigArg(config)];\n\n if (isSeaRuntime()) {\n return { command: process.execPath, args: baseArgs };\n }\n\n const cliPathCandidates = [`${moduleDir}/../cli.js`, `${moduleDir}/cli.js`];\n const cliPath =\n cliPathCandidates.find((candidate) => fs.existsSync(candidate)) ?? null;\n if (!cliPath) return null;\n const needsTsxLoader =\n fs.existsSync(`${moduleDir}/supervisor.ts`) &&\n !fs.existsSync(`${moduleDir}/supervisor.js`);\n return {\n command: process.execPath,\n args: needsTsxLoader\n ? [\"--import\", \"tsx\", cliPath, ...baseArgs]\n : [cliPath, ...baseArgs],\n };\n};\n\n// Single JSON arg keeps supervisor bootstrap parsing tiny and versionable.\nconst serializeConfigArg = (config: ShutdownSupervisorConfig): string =>\n `--supervisor-config=${JSON.stringify({\n ...config,\n parentPid: process.pid,\n })}`;\n\n/**\n * Start a supervisor process for crash cleanup. Returns a handle that can\n * stop the supervisor during a normal shutdown.\n */\nexport function startShutdownSupervisor(\n config: ShutdownSupervisorConfig,\n opts?: { onError?: (error: Error, context: string) => void },\n): ShutdownSupervisorHandle | null {\n const resolved = resolveSupervisorCommand(config);\n if (!resolved) {\n opts?.onError?.(\n new ShutdownSupervisorResolveError(\n \"Shutdown supervisor entry missing (expected Stagehand CLI entrypoint).\",\n ),\n \"resolve\",\n );\n return null;\n }\n\n const child = spawn(resolved.command, resolved.args, {\n // stdin is the parent lifeline.\n stdio: [\"pipe\", \"ignore\", \"ignore\"],\n detached: true,\n });\n child.on(\"error\", (error) => {\n opts?.onError?.(\n new ShutdownSupervisorSpawnError(\n `Shutdown supervisor failed to start: ${error.message}`,\n ),\n \"spawn\",\n );\n });\n\n try {\n child.unref();\n const stdin = child.stdin as unknown as { unref?: () => void } | null;\n stdin?.unref?.();\n } catch {\n // best-effort: avoid keeping the event loop alive\n }\n\n const stop = () => {\n // Normal close path: terminate supervisor directly.\n try {\n child.kill(\"SIGTERM\");\n } catch {\n // ignore\n }\n };\n\n return { stop };\n}\n"]}
@@ -1,6 +1,37 @@
1
1
  import { test, expect } from "@playwright/test";
2
2
  import { V3 } from "../v3.js";
3
3
  import { v3TestConfig } from "./v3.config.js";
4
+ const doubleClickFixtureUrl = `data:text/html,${encodeURIComponent(`<!DOCTYPE html>
5
+ <html>
6
+ <body>
7
+ <div id="target" style="width: 240px; height: 120px; border: 1px solid #000;">target</div>
8
+ <input id="clickCount" value="0" readonly />
9
+ <input id="dblClickCount" value="0" readonly />
10
+ <input id="lastClickDetail" value="0" readonly />
11
+ <input id="lastDblClickDetail" value="0" readonly />
12
+ <script>
13
+ const target = document.getElementById("target");
14
+ const clickCount = document.getElementById("clickCount");
15
+ const dblClickCount = document.getElementById("dblClickCount");
16
+ const lastClickDetail = document.getElementById("lastClickDetail");
17
+ const lastDblClickDetail = document.getElementById("lastDblClickDetail");
18
+ let clicks = 0;
19
+ let dblClicks = 0;
20
+
21
+ target.addEventListener("click", (event) => {
22
+ clicks += 1;
23
+ clickCount.value = String(clicks);
24
+ lastClickDetail.value = String(event.detail);
25
+ });
26
+
27
+ target.addEventListener("dblclick", (event) => {
28
+ dblClicks += 1;
29
+ dblClickCount.value = String(dblClicks);
30
+ lastDblClickDetail.value = String(event.detail);
31
+ });
32
+ </script>
33
+ </body>
34
+ </html>`)}`;
4
35
  test.describe("Locator and Page click methods", () => {
5
36
  let v3;
6
37
  test.beforeEach(async () => {
@@ -27,22 +58,24 @@ test.describe("Locator and Page click methods", () => {
27
58
  });
28
59
  test("locator.click() with clickCount: 2 performs double-click", async () => {
29
60
  const page = v3.context.pages()[0];
30
- await page.goto(
31
- "https://browserbase.github.io/stagehand-eval-sites/sites/click-test/"
32
- );
61
+ await page.goto(doubleClickFixtureUrl);
33
62
  await page.waitForLoadState("domcontentloaded");
34
- const countDisplay = page.locator("#count");
35
- const dcCountDisplay = page.locator("#dcCount");
63
+ const countDisplay = page.locator("#clickCount");
64
+ const dcCountDisplay = page.locator("#dblClickCount");
65
+ const clickDetailDisplay = page.locator("#lastClickDetail");
66
+ const dblClickDetailDisplay = page.locator("#lastDblClickDetail");
36
67
  const initialCount = await countDisplay.inputValue();
37
68
  const initialDcCount = await dcCountDisplay.inputValue();
38
69
  expect(initialCount).toBe("0");
39
70
  expect(initialDcCount).toBe("0");
40
- const clickArea = page.locator("#textarea");
71
+ const clickArea = page.locator("#target");
41
72
  await clickArea.click({ clickCount: 2 });
42
73
  const newCount = await countDisplay.inputValue();
43
74
  expect(newCount).toBe("2");
44
75
  const newDcCount = await dcCountDisplay.inputValue();
45
76
  expect(newDcCount).toBe("1");
77
+ expect(await clickDetailDisplay.inputValue()).toBe("2");
78
+ expect(await dblClickDetailDisplay.inputValue()).toBe("2");
46
79
  });
47
80
  test("locator.click() with clickCount: 3 performs triple-click", async () => {
48
81
  const page = v3.context.pages()[0];
@@ -75,23 +108,25 @@ test.describe("Locator and Page click methods", () => {
75
108
  });
76
109
  test("page.click() with clickCount: 2 performs double-click", async () => {
77
110
  const page = v3.context.pages()[0];
78
- await page.goto(
79
- "https://browserbase.github.io/stagehand-eval-sites/sites/click-test/"
80
- );
111
+ await page.goto(doubleClickFixtureUrl);
81
112
  await page.waitForLoadState("domcontentloaded");
82
- const countDisplay = page.locator("#count");
83
- const dcCountDisplay = page.locator("#dcCount");
113
+ const countDisplay = page.locator("#clickCount");
114
+ const dcCountDisplay = page.locator("#dblClickCount");
115
+ const clickDetailDisplay = page.locator("#lastClickDetail");
116
+ const dblClickDetailDisplay = page.locator("#lastDblClickDetail");
84
117
  const initialCount = await countDisplay.inputValue();
85
118
  const initialDcCount = await dcCountDisplay.inputValue();
86
119
  expect(initialCount).toBe("0");
87
120
  expect(initialDcCount).toBe("0");
88
- const clickArea = page.locator("#textarea");
121
+ const clickArea = page.locator("#target");
89
122
  const { x, y } = await clickArea.centroid();
90
123
  await page.click(x, y, { clickCount: 2 });
91
124
  const newCount = await countDisplay.inputValue();
92
125
  expect(newCount).toBe("2");
93
126
  const newDcCount = await dcCountDisplay.inputValue();
94
127
  expect(newDcCount).toBe("1");
128
+ expect(await clickDetailDisplay.inputValue()).toBe("2");
129
+ expect(await dblClickDetailDisplay.inputValue()).toBe("2");
95
130
  });
96
131
  test("page.click() with clickCount: 3 performs triple-click", async () => {
97
132
  const page = v3.context.pages()[0];