opendevbrowser 0.0.15 → 0.0.16

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 (568) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +229 -34
  3. package/dist/annotate/direct-annotator.d.ts +22 -0
  4. package/dist/annotate/direct-annotator.d.ts.map +1 -0
  5. package/dist/annotate/output.d.ts +10 -0
  6. package/dist/annotate/output.d.ts.map +1 -0
  7. package/dist/browser/annotation-manager.d.ts +30 -0
  8. package/dist/browser/annotation-manager.d.ts.map +1 -0
  9. package/dist/browser/browser-manager.d.ts +397 -0
  10. package/dist/browser/browser-manager.d.ts.map +1 -0
  11. package/dist/browser/fingerprint/adapters.d.ts +26 -0
  12. package/dist/browser/fingerprint/adapters.d.ts.map +1 -0
  13. package/dist/browser/fingerprint/canary.d.ts +25 -0
  14. package/dist/browser/fingerprint/canary.d.ts.map +1 -0
  15. package/dist/browser/fingerprint/profiles.d.ts +16 -0
  16. package/dist/browser/fingerprint/profiles.d.ts.map +1 -0
  17. package/dist/browser/fingerprint/tier1-coherence.d.ts +36 -0
  18. package/dist/browser/fingerprint/tier1-coherence.d.ts.map +1 -0
  19. package/dist/browser/fingerprint/tier2-runtime.d.ts +40 -0
  20. package/dist/browser/fingerprint/tier2-runtime.d.ts.map +1 -0
  21. package/dist/browser/fingerprint/tier3-adaptive.d.ts +30 -0
  22. package/dist/browser/fingerprint/tier3-adaptive.d.ts.map +1 -0
  23. package/dist/browser/manager-types.d.ts +3 -0
  24. package/dist/browser/manager-types.d.ts.map +1 -0
  25. package/dist/browser/ops-browser-manager.d.ts +131 -0
  26. package/dist/browser/ops-browser-manager.d.ts.map +1 -0
  27. package/dist/browser/ops-client.d.ts +56 -0
  28. package/dist/browser/ops-client.d.ts.map +1 -0
  29. package/dist/browser/parallelism-governor.d.ts +31 -0
  30. package/dist/browser/parallelism-governor.d.ts.map +1 -0
  31. package/dist/browser/script-runner.d.ts +23 -0
  32. package/dist/browser/script-runner.d.ts.map +1 -0
  33. package/dist/browser/session-store.d.ts +63 -0
  34. package/dist/browser/session-store.d.ts.map +1 -0
  35. package/dist/browser/target-manager.d.ts +36 -0
  36. package/dist/browser/target-manager.d.ts.map +1 -0
  37. package/dist/cache/chrome-locator.d.ts +2 -0
  38. package/dist/cache/chrome-locator.d.ts.map +1 -0
  39. package/dist/cache/downloader.d.ts +6 -0
  40. package/dist/cache/downloader.d.ts.map +1 -0
  41. package/dist/cache/paths.d.ts +9 -0
  42. package/dist/cache/paths.d.ts.map +1 -0
  43. package/dist/chunk-7W3SPXIB.js +166 -0
  44. package/dist/chunk-7W3SPXIB.js.map +1 -0
  45. package/dist/chunk-ST7CO5FA.js +18668 -0
  46. package/dist/chunk-ST7CO5FA.js.map +1 -0
  47. package/dist/cli/args.d.ts +25 -0
  48. package/dist/cli/args.d.ts.map +1 -0
  49. package/dist/cli/client.d.ts +2 -0
  50. package/dist/cli/client.d.ts.map +1 -0
  51. package/dist/cli/commands/annotate.d.ts +27 -0
  52. package/dist/cli/commands/annotate.d.ts.map +1 -0
  53. package/dist/cli/commands/artifacts.d.ts +24 -0
  54. package/dist/cli/commands/artifacts.d.ts.map +1 -0
  55. package/dist/cli/commands/daemon.d.ts +35 -0
  56. package/dist/cli/commands/daemon.d.ts.map +1 -0
  57. package/dist/cli/commands/devtools/console-poll.d.ts +7 -0
  58. package/dist/cli/commands/devtools/console-poll.d.ts.map +1 -0
  59. package/dist/cli/commands/devtools/debug-trace-snapshot.d.ts +20 -0
  60. package/dist/cli/commands/devtools/debug-trace-snapshot.d.ts.map +1 -0
  61. package/dist/cli/commands/devtools/network-poll.d.ts +7 -0
  62. package/dist/cli/commands/devtools/network-poll.d.ts.map +1 -0
  63. package/dist/cli/commands/devtools/perf.d.ts +7 -0
  64. package/dist/cli/commands/devtools/perf.d.ts.map +1 -0
  65. package/dist/cli/commands/devtools/screenshot.d.ts +17 -0
  66. package/dist/cli/commands/devtools/screenshot.d.ts.map +1 -0
  67. package/dist/cli/commands/dom/attr.d.ts +7 -0
  68. package/dist/cli/commands/dom/attr.d.ts.map +1 -0
  69. package/dist/cli/commands/dom/checked.d.ts +7 -0
  70. package/dist/cli/commands/dom/checked.d.ts.map +1 -0
  71. package/dist/cli/commands/dom/enabled.d.ts +7 -0
  72. package/dist/cli/commands/dom/enabled.d.ts.map +1 -0
  73. package/dist/cli/commands/dom/html.d.ts +7 -0
  74. package/dist/cli/commands/dom/html.d.ts.map +1 -0
  75. package/dist/cli/commands/dom/text.d.ts +7 -0
  76. package/dist/cli/commands/dom/text.d.ts.map +1 -0
  77. package/dist/cli/commands/dom/value.d.ts +7 -0
  78. package/dist/cli/commands/dom/value.d.ts.map +1 -0
  79. package/dist/cli/commands/dom/visible.d.ts +7 -0
  80. package/dist/cli/commands/dom/visible.d.ts.map +1 -0
  81. package/dist/cli/commands/export/clone-component.d.ts +7 -0
  82. package/dist/cli/commands/export/clone-component.d.ts.map +1 -0
  83. package/dist/cli/commands/export/clone-page.d.ts +7 -0
  84. package/dist/cli/commands/export/clone-page.d.ts.map +1 -0
  85. package/dist/cli/commands/interact/check.d.ts +7 -0
  86. package/dist/cli/commands/interact/check.d.ts.map +1 -0
  87. package/dist/cli/commands/interact/click.d.ts +7 -0
  88. package/dist/cli/commands/interact/click.d.ts.map +1 -0
  89. package/dist/cli/commands/interact/hover.d.ts +7 -0
  90. package/dist/cli/commands/interact/hover.d.ts.map +1 -0
  91. package/dist/cli/commands/interact/press.d.ts +7 -0
  92. package/dist/cli/commands/interact/press.d.ts.map +1 -0
  93. package/dist/cli/commands/interact/scroll-into-view.d.ts +7 -0
  94. package/dist/cli/commands/interact/scroll-into-view.d.ts.map +1 -0
  95. package/dist/cli/commands/interact/scroll.d.ts +7 -0
  96. package/dist/cli/commands/interact/scroll.d.ts.map +1 -0
  97. package/dist/cli/commands/interact/select.d.ts +7 -0
  98. package/dist/cli/commands/interact/select.d.ts.map +1 -0
  99. package/dist/cli/commands/interact/type.d.ts +7 -0
  100. package/dist/cli/commands/interact/type.d.ts.map +1 -0
  101. package/dist/cli/commands/interact/uncheck.d.ts +7 -0
  102. package/dist/cli/commands/interact/uncheck.d.ts.map +1 -0
  103. package/dist/cli/commands/macro-resolve.d.ts +18 -0
  104. package/dist/cli/commands/macro-resolve.d.ts.map +1 -0
  105. package/dist/cli/commands/native.d.ts +82 -0
  106. package/dist/cli/commands/native.d.ts.map +1 -0
  107. package/dist/cli/commands/nav/goto.d.ts +7 -0
  108. package/dist/cli/commands/nav/goto.d.ts.map +1 -0
  109. package/dist/cli/commands/nav/snapshot.d.ts +7 -0
  110. package/dist/cli/commands/nav/snapshot.d.ts.map +1 -0
  111. package/dist/cli/commands/nav/wait.d.ts +7 -0
  112. package/dist/cli/commands/nav/wait.d.ts.map +1 -0
  113. package/dist/cli/commands/pages/close.d.ts +6 -0
  114. package/dist/cli/commands/pages/close.d.ts.map +1 -0
  115. package/dist/cli/commands/pages/list.d.ts +7 -0
  116. package/dist/cli/commands/pages/list.d.ts.map +1 -0
  117. package/dist/cli/commands/pages/open.d.ts +7 -0
  118. package/dist/cli/commands/pages/open.d.ts.map +1 -0
  119. package/dist/cli/commands/product-video.d.ts +25 -0
  120. package/dist/cli/commands/product-video.d.ts.map +1 -0
  121. package/dist/cli/commands/registry.d.ts +5 -0
  122. package/dist/cli/commands/registry.d.ts.map +1 -0
  123. package/dist/cli/commands/research.d.ts +27 -0
  124. package/dist/cli/commands/research.d.ts.map +1 -0
  125. package/dist/cli/commands/rpc.d.ts +28 -0
  126. package/dist/cli/commands/rpc.d.ts.map +1 -0
  127. package/dist/cli/commands/run.d.ts +17 -0
  128. package/dist/cli/commands/run.d.ts.map +1 -0
  129. package/dist/cli/commands/serve.d.ts +59 -0
  130. package/dist/cli/commands/serve.d.ts.map +1 -0
  131. package/dist/cli/commands/session/connect.d.ts +9 -0
  132. package/dist/cli/commands/session/connect.d.ts.map +1 -0
  133. package/dist/cli/commands/session/cookie-import.d.ts +31 -0
  134. package/dist/cli/commands/session/cookie-import.d.ts.map +1 -0
  135. package/dist/cli/commands/session/cookie-list.d.ts +17 -0
  136. package/dist/cli/commands/session/cookie-list.d.ts.map +1 -0
  137. package/dist/cli/commands/session/disconnect.d.ts +6 -0
  138. package/dist/cli/commands/session/disconnect.d.ts.map +1 -0
  139. package/dist/cli/commands/session/launch.d.ts +29 -0
  140. package/dist/cli/commands/session/launch.d.ts.map +1 -0
  141. package/dist/cli/commands/session/status.d.ts +7 -0
  142. package/dist/cli/commands/session/status.d.ts.map +1 -0
  143. package/dist/cli/commands/shopping.d.ts +25 -0
  144. package/dist/cli/commands/shopping.d.ts.map +1 -0
  145. package/dist/cli/commands/status.d.ts +19 -0
  146. package/dist/cli/commands/status.d.ts.map +1 -0
  147. package/dist/cli/commands/targets/close.d.ts +6 -0
  148. package/dist/cli/commands/targets/close.d.ts.map +1 -0
  149. package/dist/cli/commands/targets/list.d.ts +7 -0
  150. package/dist/cli/commands/targets/list.d.ts.map +1 -0
  151. package/dist/cli/commands/targets/new.d.ts +7 -0
  152. package/dist/cli/commands/targets/new.d.ts.map +1 -0
  153. package/dist/cli/commands/targets/use.d.ts +7 -0
  154. package/dist/cli/commands/targets/use.d.ts.map +1 -0
  155. package/dist/cli/commands/types.d.ts +13 -0
  156. package/dist/cli/commands/types.d.ts.map +1 -0
  157. package/dist/cli/commands/uninstall.d.ts +14 -0
  158. package/dist/cli/commands/uninstall.d.ts.map +1 -0
  159. package/dist/cli/commands/update.d.ts +7 -0
  160. package/dist/cli/commands/update.d.ts.map +1 -0
  161. package/dist/cli/daemon-autostart.d.ts +46 -0
  162. package/dist/cli/daemon-autostart.d.ts.map +1 -0
  163. package/dist/cli/daemon-client.d.ts +33 -0
  164. package/dist/cli/daemon-client.d.ts.map +1 -0
  165. package/dist/cli/daemon-commands.d.ts +7 -0
  166. package/dist/cli/daemon-commands.d.ts.map +1 -0
  167. package/dist/cli/daemon-state.d.ts +56 -0
  168. package/dist/cli/daemon-state.d.ts.map +1 -0
  169. package/dist/cli/daemon-status.d.ts +19 -0
  170. package/dist/cli/daemon-status.d.ts.map +1 -0
  171. package/dist/cli/daemon.d.ts +29 -0
  172. package/dist/cli/daemon.d.ts.map +1 -0
  173. package/dist/cli/errors.d.ts +20 -0
  174. package/dist/cli/errors.d.ts.map +1 -0
  175. package/dist/cli/help.d.ts +28 -0
  176. package/dist/cli/help.d.ts.map +1 -0
  177. package/dist/cli/index.d.ts +2 -0
  178. package/dist/cli/index.d.ts.map +1 -0
  179. package/dist/cli/index.js +2205 -267
  180. package/dist/cli/index.js.map +1 -1
  181. package/dist/cli/installers/global.d.ts +9 -0
  182. package/dist/cli/installers/global.d.ts.map +1 -0
  183. package/dist/cli/installers/local.d.ts +9 -0
  184. package/dist/cli/installers/local.d.ts.map +1 -0
  185. package/dist/cli/installers/skills.d.ts +19 -0
  186. package/dist/cli/installers/skills.d.ts.map +1 -0
  187. package/dist/cli/output.d.ts +7 -0
  188. package/dist/cli/output.d.ts.map +1 -0
  189. package/dist/cli/remote-manager.d.ts +96 -0
  190. package/dist/cli/remote-manager.d.ts.map +1 -0
  191. package/dist/cli/remote-relay.d.ts +17 -0
  192. package/dist/cli/remote-relay.d.ts.map +1 -0
  193. package/dist/cli/templates/config.d.ts +7 -0
  194. package/dist/cli/templates/config.d.ts.map +1 -0
  195. package/dist/cli/utils/config.d.ts +20 -0
  196. package/dist/cli/utils/config.d.ts.map +1 -0
  197. package/dist/cli/utils/http.d.ts +5 -0
  198. package/dist/cli/utils/http.d.ts.map +1 -0
  199. package/dist/cli/utils/parse.d.ts +8 -0
  200. package/dist/cli/utils/parse.d.ts.map +1 -0
  201. package/dist/cli/utils/skills.d.ts +12 -0
  202. package/dist/cli/utils/skills.d.ts.map +1 -0
  203. package/dist/config.d.ts +208 -0
  204. package/dist/config.d.ts.map +1 -0
  205. package/dist/core/bootstrap.d.ts +3 -0
  206. package/dist/core/bootstrap.d.ts.map +1 -0
  207. package/dist/core/index.d.ts +3 -0
  208. package/dist/core/index.d.ts.map +1 -0
  209. package/dist/core/logging.d.ts +34 -0
  210. package/dist/core/logging.d.ts.map +1 -0
  211. package/dist/core/types.d.ts +34 -0
  212. package/dist/core/types.d.ts.map +1 -0
  213. package/dist/devtools/console-tracker.d.ts +44 -0
  214. package/dist/devtools/console-tracker.d.ts.map +1 -0
  215. package/dist/devtools/exception-tracker.d.ts +42 -0
  216. package/dist/devtools/exception-tracker.d.ts.map +1 -0
  217. package/dist/devtools/network-tracker.d.ts +34 -0
  218. package/dist/devtools/network-tracker.d.ts.map +1 -0
  219. package/dist/export/css-extract.d.ts +5 -0
  220. package/dist/export/css-extract.d.ts.map +1 -0
  221. package/dist/export/dom-capture.d.ts +15 -0
  222. package/dist/export/dom-capture.d.ts.map +1 -0
  223. package/dist/export/react-emitter.d.ts +11 -0
  224. package/dist/export/react-emitter.d.ts.map +1 -0
  225. package/dist/extension-extractor.d.ts +3 -0
  226. package/dist/extension-extractor.d.ts.map +1 -0
  227. package/dist/index.d.ts +3 -4
  228. package/dist/index.d.ts.map +1 -0
  229. package/dist/index.js +867 -87
  230. package/dist/index.js.map +1 -1
  231. package/dist/macros/execute.d.ts +44 -0
  232. package/dist/macros/execute.d.ts.map +1 -0
  233. package/dist/macros/index.d.ts +9 -0
  234. package/dist/macros/index.d.ts.map +1 -0
  235. package/dist/macros/packs/core.d.ts +3 -0
  236. package/dist/macros/packs/core.d.ts.map +1 -0
  237. package/dist/macros/registry.d.ts +48 -0
  238. package/dist/macros/registry.d.ts.map +1 -0
  239. package/dist/macros-NUBRM44Y.js +399 -0
  240. package/dist/macros-NUBRM44Y.js.map +1 -0
  241. package/dist/opendevbrowser.d.ts +3 -4
  242. package/dist/opendevbrowser.d.ts.map +1 -0
  243. package/dist/opendevbrowser.js +867 -87
  244. package/dist/opendevbrowser.js.map +1 -1
  245. package/dist/providers/adaptive-concurrency.d.ts +42 -0
  246. package/dist/providers/adaptive-concurrency.d.ts.map +1 -0
  247. package/dist/providers/artifacts.d.ts +34 -0
  248. package/dist/providers/artifacts.d.ts.map +1 -0
  249. package/dist/providers/blocker.d.ts +47 -0
  250. package/dist/providers/blocker.d.ts.map +1 -0
  251. package/dist/providers/community/index.d.ts +44 -0
  252. package/dist/providers/community/index.d.ts.map +1 -0
  253. package/dist/providers/enrichment.d.ts +33 -0
  254. package/dist/providers/enrichment.d.ts.map +1 -0
  255. package/dist/providers/errors.d.ts +41 -0
  256. package/dist/providers/errors.d.ts.map +1 -0
  257. package/dist/providers/index.d.ts +121 -0
  258. package/dist/providers/index.d.ts.map +1 -0
  259. package/dist/providers/normalize.d.ts +39 -0
  260. package/dist/providers/normalize.d.ts.map +1 -0
  261. package/dist/providers/policy.d.ts +5 -0
  262. package/dist/providers/policy.d.ts.map +1 -0
  263. package/dist/providers/registry.d.ts +22 -0
  264. package/dist/providers/registry.d.ts.map +1 -0
  265. package/dist/providers/renderer.d.ts +49 -0
  266. package/dist/providers/renderer.d.ts.map +1 -0
  267. package/dist/providers/runtime-factory.d.ts +20 -0
  268. package/dist/providers/runtime-factory.d.ts.map +1 -0
  269. package/dist/providers/safety/prompt-guard.d.ts +34 -0
  270. package/dist/providers/safety/prompt-guard.d.ts.map +1 -0
  271. package/dist/providers/shared/anti-bot-policy.d.ts +51 -0
  272. package/dist/providers/shared/anti-bot-policy.d.ts.map +1 -0
  273. package/dist/providers/shared/post-policy.d.ts +31 -0
  274. package/dist/providers/shared/post-policy.d.ts.map +1 -0
  275. package/dist/providers/shared/request-headers.d.ts +5 -0
  276. package/dist/providers/shared/request-headers.d.ts.map +1 -0
  277. package/dist/providers/shared/traversal-url.d.ts +2 -0
  278. package/dist/providers/shared/traversal-url.d.ts.map +1 -0
  279. package/dist/providers/shopping/index.d.ts +63 -0
  280. package/dist/providers/shopping/index.d.ts.map +1 -0
  281. package/dist/providers/social/bluesky.d.ts +3 -0
  282. package/dist/providers/social/bluesky.d.ts.map +1 -0
  283. package/dist/providers/social/facebook.d.ts +3 -0
  284. package/dist/providers/social/facebook.d.ts.map +1 -0
  285. package/dist/providers/social/index.d.ts +31 -0
  286. package/dist/providers/social/index.d.ts.map +1 -0
  287. package/dist/providers/social/instagram.d.ts +3 -0
  288. package/dist/providers/social/instagram.d.ts.map +1 -0
  289. package/dist/providers/social/linkedin.d.ts +3 -0
  290. package/dist/providers/social/linkedin.d.ts.map +1 -0
  291. package/dist/providers/social/platform.d.ts +40 -0
  292. package/dist/providers/social/platform.d.ts.map +1 -0
  293. package/dist/providers/social/reddit.d.ts +3 -0
  294. package/dist/providers/social/reddit.d.ts.map +1 -0
  295. package/dist/providers/social/threads.d.ts +3 -0
  296. package/dist/providers/social/threads.d.ts.map +1 -0
  297. package/dist/providers/social/tiktok.d.ts +3 -0
  298. package/dist/providers/social/tiktok.d.ts.map +1 -0
  299. package/dist/providers/social/x.d.ts +3 -0
  300. package/dist/providers/social/x.d.ts.map +1 -0
  301. package/dist/providers/social/youtube-resolver.d.ts +78 -0
  302. package/dist/providers/social/youtube-resolver.d.ts.map +1 -0
  303. package/dist/providers/social/youtube.d.ts +34 -0
  304. package/dist/providers/social/youtube.d.ts.map +1 -0
  305. package/dist/providers/tier-router.d.ts +30 -0
  306. package/dist/providers/tier-router.d.ts.map +1 -0
  307. package/dist/providers/timebox.d.ts +20 -0
  308. package/dist/providers/timebox.d.ts.map +1 -0
  309. package/dist/providers/types.d.ts +344 -0
  310. package/dist/providers/types.d.ts.map +1 -0
  311. package/dist/providers/web/crawl-worker.d.ts +36 -0
  312. package/dist/providers/web/crawl-worker.d.ts.map +1 -0
  313. package/dist/providers/web/crawler.d.ts +101 -0
  314. package/dist/providers/web/crawler.d.ts.map +1 -0
  315. package/dist/providers/web/extract.d.ts +11 -0
  316. package/dist/providers/web/extract.d.ts.map +1 -0
  317. package/dist/providers/web/index.d.ts +24 -0
  318. package/dist/providers/web/index.d.ts.map +1 -0
  319. package/dist/providers/web/policy.d.ts +14 -0
  320. package/dist/providers/web/policy.d.ts.map +1 -0
  321. package/dist/providers/workflows.d.ts +67 -0
  322. package/dist/providers/workflows.d.ts.map +1 -0
  323. package/dist/relay/protocol.d.ts +317 -0
  324. package/dist/relay/protocol.d.ts.map +1 -0
  325. package/dist/relay/relay-endpoints.d.ts +16 -0
  326. package/dist/relay/relay-endpoints.d.ts.map +1 -0
  327. package/dist/relay/relay-server.d.ts +111 -0
  328. package/dist/relay/relay-server.d.ts.map +1 -0
  329. package/dist/relay/relay-types.d.ts +9 -0
  330. package/dist/relay/relay-types.d.ts.map +1 -0
  331. package/dist/skills/continuity-nudge.d.ts +12 -0
  332. package/dist/skills/continuity-nudge.d.ts.map +1 -0
  333. package/dist/skills/skill-loader.d.ts +20 -0
  334. package/dist/skills/skill-loader.d.ts.map +1 -0
  335. package/dist/skills/skill-nudge.d.ts +18 -0
  336. package/dist/skills/skill-nudge.d.ts.map +1 -0
  337. package/dist/skills/types.d.ts +12 -0
  338. package/dist/skills/types.d.ts.map +1 -0
  339. package/dist/snapshot/ops-snapshot.d.ts +16 -0
  340. package/dist/snapshot/ops-snapshot.d.ts.map +1 -0
  341. package/dist/snapshot/refs.d.ts +23 -0
  342. package/dist/snapshot/refs.d.ts.map +1 -0
  343. package/dist/snapshot/snapshotter.d.ts +27 -0
  344. package/dist/snapshot/snapshotter.d.ts.map +1 -0
  345. package/dist/tools/annotate.d.ts +4 -0
  346. package/dist/tools/annotate.d.ts.map +1 -0
  347. package/dist/tools/check.d.ts +4 -0
  348. package/dist/tools/check.d.ts.map +1 -0
  349. package/dist/tools/click.d.ts +4 -0
  350. package/dist/tools/click.d.ts.map +1 -0
  351. package/dist/tools/clone_component.d.ts +4 -0
  352. package/dist/tools/clone_component.d.ts.map +1 -0
  353. package/dist/tools/clone_page.d.ts +4 -0
  354. package/dist/tools/clone_page.d.ts.map +1 -0
  355. package/dist/tools/close.d.ts +4 -0
  356. package/dist/tools/close.d.ts.map +1 -0
  357. package/dist/tools/connect.d.ts +4 -0
  358. package/dist/tools/connect.d.ts.map +1 -0
  359. package/dist/tools/console_poll.d.ts +4 -0
  360. package/dist/tools/console_poll.d.ts.map +1 -0
  361. package/dist/tools/cookie_import.d.ts +25 -0
  362. package/dist/tools/cookie_import.d.ts.map +1 -0
  363. package/dist/tools/cookie_list.d.ts +9 -0
  364. package/dist/tools/cookie_list.d.ts.map +1 -0
  365. package/dist/tools/debug_trace_snapshot.d.ts +4 -0
  366. package/dist/tools/debug_trace_snapshot.d.ts.map +1 -0
  367. package/dist/tools/deps.d.ts +26 -0
  368. package/dist/tools/deps.d.ts.map +1 -0
  369. package/dist/tools/disconnect.d.ts +4 -0
  370. package/dist/tools/disconnect.d.ts.map +1 -0
  371. package/dist/tools/dom_get_html.d.ts +4 -0
  372. package/dist/tools/dom_get_html.d.ts.map +1 -0
  373. package/dist/tools/dom_get_text.d.ts +4 -0
  374. package/dist/tools/dom_get_text.d.ts.map +1 -0
  375. package/dist/tools/get_attr.d.ts +4 -0
  376. package/dist/tools/get_attr.d.ts.map +1 -0
  377. package/dist/tools/get_value.d.ts +4 -0
  378. package/dist/tools/get_value.d.ts.map +1 -0
  379. package/dist/tools/goto.d.ts +4 -0
  380. package/dist/tools/goto.d.ts.map +1 -0
  381. package/dist/tools/hover.d.ts +4 -0
  382. package/dist/tools/hover.d.ts.map +1 -0
  383. package/dist/tools/index.d.ts +4 -0
  384. package/dist/tools/index.d.ts.map +1 -0
  385. package/dist/tools/is_checked.d.ts +4 -0
  386. package/dist/tools/is_checked.d.ts.map +1 -0
  387. package/dist/tools/is_enabled.d.ts +4 -0
  388. package/dist/tools/is_enabled.d.ts.map +1 -0
  389. package/dist/tools/is_visible.d.ts +4 -0
  390. package/dist/tools/is_visible.d.ts.map +1 -0
  391. package/dist/tools/launch.d.ts +4 -0
  392. package/dist/tools/launch.d.ts.map +1 -0
  393. package/dist/tools/list.d.ts +4 -0
  394. package/dist/tools/list.d.ts.map +1 -0
  395. package/dist/tools/macro_resolve.d.ts +25 -0
  396. package/dist/tools/macro_resolve.d.ts.map +1 -0
  397. package/dist/tools/network_poll.d.ts +4 -0
  398. package/dist/tools/network_poll.d.ts.map +1 -0
  399. package/dist/tools/page.d.ts +4 -0
  400. package/dist/tools/page.d.ts.map +1 -0
  401. package/dist/tools/perf.d.ts +4 -0
  402. package/dist/tools/perf.d.ts.map +1 -0
  403. package/dist/tools/press.d.ts +4 -0
  404. package/dist/tools/press.d.ts.map +1 -0
  405. package/dist/tools/product_video_run.d.ts +4 -0
  406. package/dist/tools/product_video_run.d.ts.map +1 -0
  407. package/dist/tools/prompting_guide.d.ts +4 -0
  408. package/dist/tools/prompting_guide.d.ts.map +1 -0
  409. package/dist/tools/research_run.d.ts +4 -0
  410. package/dist/tools/research_run.d.ts.map +1 -0
  411. package/dist/tools/response.d.ts +16 -0
  412. package/dist/tools/response.d.ts.map +1 -0
  413. package/dist/tools/run.d.ts +4 -0
  414. package/dist/tools/run.d.ts.map +1 -0
  415. package/dist/tools/screenshot.d.ts +4 -0
  416. package/dist/tools/screenshot.d.ts.map +1 -0
  417. package/dist/tools/scroll.d.ts +4 -0
  418. package/dist/tools/scroll.d.ts.map +1 -0
  419. package/dist/tools/scroll_into_view.d.ts +4 -0
  420. package/dist/tools/scroll_into_view.d.ts.map +1 -0
  421. package/dist/tools/select.d.ts +4 -0
  422. package/dist/tools/select.d.ts.map +1 -0
  423. package/dist/tools/shopping_run.d.ts +4 -0
  424. package/dist/tools/shopping_run.d.ts.map +1 -0
  425. package/dist/tools/skill_list.d.ts +4 -0
  426. package/dist/tools/skill_list.d.ts.map +1 -0
  427. package/dist/tools/skill_load.d.ts +4 -0
  428. package/dist/tools/skill_load.d.ts.map +1 -0
  429. package/dist/tools/snapshot.d.ts +4 -0
  430. package/dist/tools/snapshot.d.ts.map +1 -0
  431. package/dist/tools/status.d.ts +4 -0
  432. package/dist/tools/status.d.ts.map +1 -0
  433. package/dist/tools/target_close.d.ts +4 -0
  434. package/dist/tools/target_close.d.ts.map +1 -0
  435. package/dist/tools/target_new.d.ts +4 -0
  436. package/dist/tools/target_new.d.ts.map +1 -0
  437. package/dist/tools/target_use.d.ts +4 -0
  438. package/dist/tools/target_use.d.ts.map +1 -0
  439. package/dist/tools/targets_list.d.ts +4 -0
  440. package/dist/tools/targets_list.d.ts.map +1 -0
  441. package/dist/tools/type.d.ts +4 -0
  442. package/dist/tools/type.d.ts.map +1 -0
  443. package/dist/tools/uncheck.d.ts +4 -0
  444. package/dist/tools/uncheck.d.ts.map +1 -0
  445. package/dist/tools/wait.d.ts +4 -0
  446. package/dist/tools/wait.d.ts.map +1 -0
  447. package/dist/tools/workflow-runtime.d.ts +4 -0
  448. package/dist/tools/workflow-runtime.d.ts.map +1 -0
  449. package/dist/utils/crypto.d.ts +2 -0
  450. package/dist/utils/crypto.d.ts.map +1 -0
  451. package/dist/utils/endpoint-validation.d.ts +2 -0
  452. package/dist/utils/endpoint-validation.d.ts.map +1 -0
  453. package/dist/utils/fs.d.ts +5 -0
  454. package/dist/utils/fs.d.ts.map +1 -0
  455. package/dist/utils/hub-enabled.d.ts +3 -0
  456. package/dist/utils/hub-enabled.d.ts.map +1 -0
  457. package/extension/dist/background.js +10 -4
  458. package/extension/dist/ops/ops-runtime.js +506 -4
  459. package/extension/dist/ops/ops-session-store.js +16 -2
  460. package/extension/dist/ops/parallelism-governor.js +117 -0
  461. package/extension/dist/ops/snapshot-shared.js +21 -5
  462. package/extension/dist/services/CDPRouter.js +70 -5
  463. package/extension/dist/services/ConnectionManager.js +5 -3
  464. package/extension/icons/icon128.png +0 -0
  465. package/extension/icons/icon16.png +0 -0
  466. package/extension/icons/icon32.png +0 -0
  467. package/extension/icons/icon48.png +0 -0
  468. package/extension/manifest.json +1 -1
  469. package/package.json +25 -16
  470. package/scripts/native/host.cjs +230 -0
  471. package/scripts/native/install.ps1 +73 -0
  472. package/scripts/native/install.sh +66 -0
  473. package/scripts/native/uninstall.ps1 +25 -0
  474. package/scripts/native/uninstall.sh +26 -0
  475. package/skills/AGENTS.md +17 -8
  476. package/skills/opendevbrowser-best-practices/SKILL.md +178 -72
  477. package/skills/opendevbrowser-best-practices/artifacts/browser-agent-known-issues-matrix.md +44 -0
  478. package/skills/opendevbrowser-best-practices/artifacts/command-channel-reference.md +95 -0
  479. package/skills/opendevbrowser-best-practices/artifacts/debug-trace-playbook.md +36 -0
  480. package/skills/opendevbrowser-best-practices/artifacts/fingerprint-tiers.md +36 -0
  481. package/skills/opendevbrowser-best-practices/artifacts/macro-workflows.md +43 -0
  482. package/skills/opendevbrowser-best-practices/artifacts/parity-gates.md +36 -0
  483. package/skills/opendevbrowser-best-practices/artifacts/provider-workflows.md +89 -0
  484. package/skills/opendevbrowser-best-practices/assets/templates/cdp-forward-envelope.json +11 -0
  485. package/skills/opendevbrowser-best-practices/assets/templates/mode-flag-matrix.json +56 -0
  486. package/skills/opendevbrowser-best-practices/assets/templates/ops-request-envelope.json +9 -0
  487. package/skills/opendevbrowser-best-practices/assets/templates/robustness-checklist.json +79 -0
  488. package/skills/opendevbrowser-best-practices/assets/templates/surface-audit-checklist.json +24 -0
  489. package/skills/opendevbrowser-best-practices/scripts/odb-workflow.sh +144 -0
  490. package/skills/opendevbrowser-best-practices/scripts/run-robustness-audit.sh +83 -0
  491. package/skills/opendevbrowser-best-practices/scripts/validate-skill-assets.sh +93 -0
  492. package/skills/opendevbrowser-continuity-ledger/SKILL.md +10 -0
  493. package/skills/opendevbrowser-data-extraction/SKILL.md +126 -0
  494. package/skills/opendevbrowser-data-extraction/artifacts/extraction-workflows.md +31 -0
  495. package/skills/opendevbrowser-data-extraction/assets/templates/compliance-checklist.md +7 -0
  496. package/skills/opendevbrowser-data-extraction/assets/templates/extraction-schema.json +17 -0
  497. package/skills/opendevbrowser-data-extraction/assets/templates/pagination-state.json +11 -0
  498. package/skills/opendevbrowser-data-extraction/assets/templates/quality-gates.json +10 -0
  499. package/skills/opendevbrowser-data-extraction/examples/sample-schema.json +19 -0
  500. package/skills/opendevbrowser-data-extraction/scripts/run-extraction-workflow.sh +83 -0
  501. package/skills/opendevbrowser-data-extraction/scripts/validate-skill-assets.sh +49 -0
  502. package/skills/opendevbrowser-form-testing/SKILL.md +143 -0
  503. package/skills/opendevbrowser-form-testing/artifacts/form-workflows.md +37 -0
  504. package/skills/opendevbrowser-form-testing/assets/templates/a11y-assertions.md +7 -0
  505. package/skills/opendevbrowser-form-testing/assets/templates/challenge-decision-tree.json +16 -0
  506. package/skills/opendevbrowser-form-testing/assets/templates/multi-step-state.json +11 -0
  507. package/skills/opendevbrowser-form-testing/assets/templates/validation-matrix.json +24 -0
  508. package/skills/opendevbrowser-form-testing/examples/sample-validation-matrix.json +29 -0
  509. package/skills/opendevbrowser-form-testing/scripts/run-form-workflow.sh +82 -0
  510. package/skills/opendevbrowser-form-testing/scripts/validate-skill-assets.sh +49 -0
  511. package/skills/opendevbrowser-login-automation/SKILL.md +159 -0
  512. package/skills/opendevbrowser-login-automation/artifacts/login-workflows.md +39 -0
  513. package/skills/opendevbrowser-login-automation/assets/templates/auth-signals.json +21 -0
  514. package/skills/opendevbrowser-login-automation/assets/templates/challenge-checkpoint.md +10 -0
  515. package/skills/opendevbrowser-login-automation/assets/templates/login-scenario-matrix.json +26 -0
  516. package/skills/opendevbrowser-login-automation/examples/sample-auth-signals.json +14 -0
  517. package/skills/opendevbrowser-login-automation/scripts/record-auth-signals.sh +18 -0
  518. package/skills/opendevbrowser-login-automation/scripts/run-login-workflow.sh +99 -0
  519. package/skills/opendevbrowser-login-automation/scripts/validate-skill-assets.sh +50 -0
  520. package/skills/opendevbrowser-product-presentation-asset/SKILL.md +98 -0
  521. package/skills/opendevbrowser-product-presentation-asset/artifacts/asset-pack-assembly.md +23 -0
  522. package/skills/opendevbrowser-product-presentation-asset/artifacts/ugc-creative-guide.md +21 -0
  523. package/skills/opendevbrowser-product-presentation-asset/assets/templates/claims-evidence-map.md +5 -0
  524. package/skills/opendevbrowser-product-presentation-asset/assets/templates/copy.md +5 -0
  525. package/skills/opendevbrowser-product-presentation-asset/assets/templates/features.md +4 -0
  526. package/skills/opendevbrowser-product-presentation-asset/assets/templates/manifest.schema.json +14 -0
  527. package/skills/opendevbrowser-product-presentation-asset/assets/templates/shot-list.md +7 -0
  528. package/skills/opendevbrowser-product-presentation-asset/assets/templates/ugc-concepts.md +17 -0
  529. package/skills/opendevbrowser-product-presentation-asset/assets/templates/user-actions.md +7 -0
  530. package/skills/opendevbrowser-product-presentation-asset/assets/templates/video-assembly.md +18 -0
  531. package/skills/opendevbrowser-product-presentation-asset/examples/sample-input.json +6 -0
  532. package/skills/opendevbrowser-product-presentation-asset/examples/sample-manifest.json +18 -0
  533. package/skills/opendevbrowser-product-presentation-asset/scripts/capture-screenshots.sh +9 -0
  534. package/skills/opendevbrowser-product-presentation-asset/scripts/collect-product.sh +14 -0
  535. package/skills/opendevbrowser-product-presentation-asset/scripts/download-images.sh +9 -0
  536. package/skills/opendevbrowser-product-presentation-asset/scripts/render-video-brief.sh +96 -0
  537. package/skills/opendevbrowser-product-presentation-asset/scripts/validate-skill-assets.sh +56 -0
  538. package/skills/opendevbrowser-product-presentation-asset/scripts/write-manifest.sh +43 -0
  539. package/skills/opendevbrowser-research/SKILL.md +73 -0
  540. package/skills/opendevbrowser-research/artifacts/research-workflows.md +29 -0
  541. package/skills/opendevbrowser-research/assets/templates/compact.md +7 -0
  542. package/skills/opendevbrowser-research/assets/templates/context.json +18 -0
  543. package/skills/opendevbrowser-research/assets/templates/report.md +9 -0
  544. package/skills/opendevbrowser-research/examples/sample-input.json +6 -0
  545. package/skills/opendevbrowser-research/examples/sample-output.md +4 -0
  546. package/skills/opendevbrowser-research/scripts/render-output.sh +12 -0
  547. package/skills/opendevbrowser-research/scripts/run-research.sh +23 -0
  548. package/skills/opendevbrowser-research/scripts/validate-skill-assets.sh +48 -0
  549. package/skills/opendevbrowser-research/scripts/write-artifacts.sh +29 -0
  550. package/skills/opendevbrowser-shopping/SKILL.md +118 -0
  551. package/skills/opendevbrowser-shopping/artifacts/deal-hunting-workflows.md +37 -0
  552. package/skills/opendevbrowser-shopping/assets/templates/deal-thresholds.json +8 -0
  553. package/skills/opendevbrowser-shopping/assets/templates/deals-context.json +9 -0
  554. package/skills/opendevbrowser-shopping/assets/templates/deals-table.md +4 -0
  555. package/skills/opendevbrowser-shopping/assets/templates/market-analysis.json +30 -0
  556. package/skills/opendevbrowser-shopping/examples/sample-deals.md +4 -0
  557. package/skills/opendevbrowser-shopping/examples/sample-query.json +5 -0
  558. package/skills/opendevbrowser-shopping/scripts/analyze-market.sh +307 -0
  559. package/skills/opendevbrowser-shopping/scripts/normalize-offers.sh +28 -0
  560. package/skills/opendevbrowser-shopping/scripts/render-deals.sh +13 -0
  561. package/skills/opendevbrowser-shopping/scripts/run-deal-hunt.sh +32 -0
  562. package/skills/opendevbrowser-shopping/scripts/run-shopping.sh +19 -0
  563. package/skills/opendevbrowser-shopping/scripts/validate-skill-assets.sh +53 -0
  564. package/dist/chunk-JVBMT2O5.js +0 -7173
  565. package/dist/chunk-JVBMT2O5.js.map +0 -1
  566. package/skills/data-extraction/SKILL.md +0 -128
  567. package/skills/form-testing/SKILL.md +0 -106
  568. package/skills/login-automation/SKILL.md +0 -108
package/dist/cli/index.js CHANGED
@@ -6,9 +6,11 @@ import {
6
6
  EXIT_USAGE,
7
7
  buildAnnotateResult,
8
8
  callDaemon,
9
+ cleanupExpiredArtifacts,
9
10
  createOpenDevBrowserCore,
10
11
  createUsageError,
11
12
  extractExtension,
13
+ fetchDaemonStatus,
12
14
  fetchDaemonStatusFromMetadata,
13
15
  fetchWithTimeout,
14
16
  formatErrorPayload,
@@ -20,9 +22,68 @@ import {
20
22
  startDaemon,
21
23
  toCliError,
22
24
  writeFileAtomic
23
- } from "../chunk-JVBMT2O5.js";
25
+ } from "../chunk-ST7CO5FA.js";
26
+ import "../chunk-7W3SPXIB.js";
24
27
 
25
28
  // src/cli/args.ts
29
+ var CLI_COMMANDS = [
30
+ "install",
31
+ "update",
32
+ "uninstall",
33
+ "help",
34
+ "version",
35
+ "serve",
36
+ "daemon",
37
+ "native",
38
+ "run",
39
+ "launch",
40
+ "connect",
41
+ "disconnect",
42
+ "status",
43
+ "research",
44
+ "shopping",
45
+ "product-video",
46
+ "artifacts",
47
+ "goto",
48
+ "wait",
49
+ "snapshot",
50
+ "click",
51
+ "hover",
52
+ "press",
53
+ "check",
54
+ "uncheck",
55
+ "type",
56
+ "select",
57
+ "scroll",
58
+ "scroll-into-view",
59
+ "targets-list",
60
+ "target-use",
61
+ "target-new",
62
+ "target-close",
63
+ "page",
64
+ "pages",
65
+ "page-close",
66
+ "dom-html",
67
+ "dom-text",
68
+ "dom-attr",
69
+ "dom-value",
70
+ "dom-visible",
71
+ "dom-enabled",
72
+ "dom-checked",
73
+ "clone-page",
74
+ "clone-component",
75
+ "perf",
76
+ "screenshot",
77
+ "console-poll",
78
+ "network-poll",
79
+ "debug-trace-snapshot",
80
+ "cookie-import",
81
+ "cookie-list",
82
+ "macro-resolve",
83
+ "annotate",
84
+ "rpc"
85
+ ];
86
+ var CLI_COMMAND_SET = new Set(CLI_COMMANDS);
26
87
  var SHORT_FLAGS = {
27
88
  "-g": "--global",
28
89
  "-l": "--local",
@@ -85,12 +146,162 @@ function parseTransport(args) {
85
146
  }
86
147
  throw createUsageError(`Invalid --transport: ${value ?? "missing"}`);
87
148
  }
149
+ var VALID_FLAGS = [
150
+ "--global",
151
+ "--local",
152
+ "--update",
153
+ "--uninstall",
154
+ "--help",
155
+ "--version",
156
+ "--with-config",
157
+ "--no-prompt",
158
+ "--no-interactive",
159
+ "--quiet",
160
+ "--output-format",
161
+ "--full",
162
+ "--port",
163
+ "--token",
164
+ "--stop",
165
+ "--script",
166
+ "--headless",
167
+ "--profile",
168
+ "--persist-profile",
169
+ "--chrome-path",
170
+ "--start-url",
171
+ "--flag",
172
+ "--session-id",
173
+ "--close-browser",
174
+ "--ws-endpoint",
175
+ "--host",
176
+ "--cdp-port",
177
+ "--url",
178
+ "--wait-until",
179
+ "--timeout-ms",
180
+ "--ref",
181
+ "--state",
182
+ "--until",
183
+ "--mode",
184
+ "--max-chars",
185
+ "--cursor",
186
+ "--text",
187
+ "--clear",
188
+ "--submit",
189
+ "--values",
190
+ "--dy",
191
+ "--key",
192
+ "--attr",
193
+ "--name",
194
+ "--target-id",
195
+ "--tab-id",
196
+ "--include-urls",
197
+ "--path",
198
+ "--since-seq",
199
+ "--max",
200
+ "--since-console-seq",
201
+ "--since-network-seq",
202
+ "--since-exception-seq",
203
+ "--request-id",
204
+ "--cookies",
205
+ "--cookies-file",
206
+ "--strict",
207
+ "--expression",
208
+ "--default-provider",
209
+ "--include-catalog",
210
+ "--execute",
211
+ "--params",
212
+ "--params-file",
213
+ "--unsafe-internal",
214
+ "--daemon",
215
+ "--transport",
216
+ "--no-extension",
217
+ "--extension-only",
218
+ "--extension-legacy",
219
+ "--wait-for-extension",
220
+ "--wait-timeout-ms",
221
+ "--skills-global",
222
+ "--skills-local",
223
+ "--no-skills",
224
+ "--screenshot-mode",
225
+ "--debug",
226
+ "--context",
227
+ "--topic",
228
+ "--days",
229
+ "--from",
230
+ "--to",
231
+ "--source-selection",
232
+ "--sources",
233
+ "--include-engagement",
234
+ "--limit-per-source",
235
+ "--query",
236
+ "--providers",
237
+ "--budget",
238
+ "--region",
239
+ "--sort",
240
+ "--product-url",
241
+ "--product-name",
242
+ "--provider-hint",
243
+ "--include-screenshots",
244
+ "--include-all-images",
245
+ "--include-copy",
246
+ "--output-dir",
247
+ "--ttl-hours",
248
+ "--expired-only"
249
+ ];
250
+ var VALID_FLAG_SET = new Set(VALID_FLAGS);
251
+ var VALID_EQUALS_FLAGS = [
252
+ "--output-format",
253
+ "--transport",
254
+ "--session-id",
255
+ "--url",
256
+ "--screenshot-mode",
257
+ "--context",
258
+ "--timeout-ms",
259
+ "--since-seq",
260
+ "--since-console-seq",
261
+ "--since-network-seq",
262
+ "--since-exception-seq",
263
+ "--max",
264
+ "--target-id",
265
+ "--tab-id",
266
+ "--name",
267
+ "--cookies",
268
+ "--cookies-file",
269
+ "--persist-profile",
270
+ "--expression",
271
+ "--default-provider",
272
+ "--request-id",
273
+ "--strict",
274
+ "--params",
275
+ "--params-file",
276
+ "--topic",
277
+ "--days",
278
+ "--from",
279
+ "--to",
280
+ "--source-selection",
281
+ "--sources",
282
+ "--mode",
283
+ "--limit-per-source",
284
+ "--query",
285
+ "--providers",
286
+ "--budget",
287
+ "--region",
288
+ "--sort",
289
+ "--product-url",
290
+ "--product-name",
291
+ "--provider-hint",
292
+ "--include-screenshots",
293
+ "--include-all-images",
294
+ "--include-copy",
295
+ "--output-dir",
296
+ "--ttl-hours"
297
+ ];
298
+ var VALID_EQUALS_FLAG_SET = new Set(VALID_EQUALS_FLAGS);
88
299
  function parseArgs(argv) {
89
300
  let args = expandShortFlags(argv.slice(2));
90
301
  let commandOverride = null;
91
302
  if (args[0] && !args[0].startsWith("-")) {
92
303
  const candidate = args[0];
93
- if (candidate === "install" || candidate === "update" || candidate === "uninstall" || candidate === "help" || candidate === "version" || candidate === "serve" || candidate === "daemon" || candidate === "native" || candidate === "run" || candidate === "launch" || candidate === "connect" || candidate === "disconnect" || candidate === "status" || candidate === "goto" || candidate === "wait" || candidate === "snapshot" || candidate === "click" || candidate === "hover" || candidate === "press" || candidate === "check" || candidate === "uncheck" || candidate === "type" || candidate === "select" || candidate === "scroll" || candidate === "scroll-into-view" || candidate === "targets-list" || candidate === "target-use" || candidate === "target-new" || candidate === "target-close" || candidate === "page" || candidate === "pages" || candidate === "page-close" || candidate === "dom-html" || candidate === "dom-text" || candidate === "dom-attr" || candidate === "dom-value" || candidate === "dom-visible" || candidate === "dom-enabled" || candidate === "dom-checked" || candidate === "clone-page" || candidate === "clone-component" || candidate === "perf" || candidate === "screenshot" || candidate === "console-poll" || candidate === "network-poll" || candidate === "annotate") {
304
+ if (CLI_COMMAND_SET.has(candidate)) {
94
305
  commandOverride = candidate;
95
306
  args = args.slice(1);
96
307
  } else {
@@ -179,87 +390,11 @@ function parseArgs(argv) {
179
390
  } else if (noPrompt) {
180
391
  mode = "global";
181
392
  }
182
- const validFlags = /* @__PURE__ */ new Set([
183
- "--global",
184
- "--local",
185
- "--update",
186
- "--uninstall",
187
- "--help",
188
- "--version",
189
- "--with-config",
190
- "--no-prompt",
191
- "--no-interactive",
192
- "--quiet",
193
- "--output-format",
194
- "--full",
195
- "--port",
196
- "--token",
197
- "--stop",
198
- "--script",
199
- "--headless",
200
- "--profile",
201
- "--persist-profile",
202
- "--chrome-path",
203
- "--start-url",
204
- "--flag",
205
- "--session-id",
206
- "--close-browser",
207
- "--ws-endpoint",
208
- "--host",
209
- "--cdp-port",
210
- "--url",
211
- "--wait-until",
212
- "--timeout-ms",
213
- "--ref",
214
- "--state",
215
- "--until",
216
- "--mode",
217
- "--max-chars",
218
- "--cursor",
219
- "--text",
220
- "--clear",
221
- "--submit",
222
- "--values",
223
- "--dy",
224
- "--key",
225
- "--attr",
226
- "--name",
227
- "--target-id",
228
- "--tab-id",
229
- "--include-urls",
230
- "--path",
231
- "--since-seq",
232
- "--max",
233
- "--daemon",
234
- "--transport",
235
- "--no-extension",
236
- "--extension-only",
237
- "--extension-legacy",
238
- "--wait-for-extension",
239
- "--wait-timeout-ms",
240
- "--skills-global",
241
- "--skills-local",
242
- "--no-skills",
243
- "--screenshot-mode",
244
- "--debug",
245
- "--context"
246
- ]);
247
- const validEqualsFlags = /* @__PURE__ */ new Set([
248
- "--output-format",
249
- "--transport",
250
- "--session-id",
251
- "--url",
252
- "--screenshot-mode",
253
- "--context",
254
- "--timeout-ms",
255
- "--target-id",
256
- "--tab-id"
257
- ]);
258
393
  for (const arg of args) {
259
- if (arg.startsWith("--") && !validFlags.has(arg)) {
394
+ if (arg.startsWith("--") && !VALID_FLAG_SET.has(arg)) {
260
395
  if (arg.includes("=")) {
261
396
  const baseFlag = arg.split("=", 2)[0] ?? "";
262
- if (validEqualsFlags.has(baseFlag)) {
397
+ if (VALID_EQUALS_FLAG_SET.has(baseFlag)) {
263
398
  continue;
264
399
  }
265
400
  }
@@ -283,94 +418,6 @@ function parseArgs(argv) {
283
418
  rawArgs: args
284
419
  };
285
420
  }
286
- function getHelpText() {
287
- return `
288
- OpenDevBrowser CLI - Install and manage the OpenDevBrowser plugin
289
-
290
- USAGE:
291
- npx opendevbrowser [command] [options]
292
-
293
- COMMANDS:
294
- install Install the plugin (default if no command specified)
295
- update Clear cached plugin to trigger reinstall
296
- uninstall Remove plugin from config
297
- serve Start or stop the local daemon
298
- daemon Install/uninstall/status daemon auto-start
299
- native Install/uninstall/status native messaging host
300
- run Execute a JSON script in a single process
301
- launch Launch a managed browser session via daemon
302
- connect Connect to an existing browser via daemon
303
- disconnect Disconnect a daemon session
304
- status Get daemon status (or session status with --session-id)
305
- goto Navigate current session to a URL
306
- wait Wait for load or a ref to appear
307
- snapshot Capture a snapshot of the active page
308
- click Click an element by ref
309
- hover Hover an element by ref
310
- press Press a keyboard key
311
- check Check a checkbox by ref
312
- uncheck Uncheck a checkbox by ref
313
- type Type into an element by ref
314
- select Select values in a select by ref
315
- scroll Scroll the page or element by ref
316
- scroll-into-view Scroll an element into view by ref
317
- targets-list List page targets
318
- target-use Focus a target by id
319
- target-new Open a new target
320
- target-close Close a target by id
321
- page Open or focus a named page
322
- pages List named pages
323
- page-close Close a named page
324
- dom-html Capture HTML for a ref
325
- dom-text Capture text for a ref
326
- dom-attr Capture attribute value for a ref
327
- dom-value Capture input value for a ref
328
- dom-visible Check visibility for a ref
329
- dom-enabled Check enabled state for a ref
330
- dom-checked Check checked state for a ref
331
- clone-page Clone the active page to React
332
- clone-component Clone a component by ref
333
- perf Capture performance metrics
334
- screenshot Capture a screenshot
335
- console-poll Poll console events
336
- network-poll Poll network events
337
- annotate Request interactive annotations (direct or relay)
338
- help Show this help message
339
- version Show version
340
-
341
- ALIASES:
342
- --update, -u Same as update
343
- --uninstall Same as uninstall
344
- --help, -h Same as help
345
- --version, -v Same as version
346
-
347
- INSTALL OPTIONS:
348
- --global, -g Install to ~/.config/opencode/opencode.json
349
- --local, -l Install to ./opencode.json (project-local)
350
- --with-config Also create opendevbrowser.jsonc with defaults
351
- --full, -f Create config and pre-extract extension assets
352
- --no-prompt Skip prompts, use defaults (global install)
353
- --no-interactive Alias of --no-prompt
354
- --quiet Suppress non-error output
355
- --output-format Output format: text (default), json, stream-json
356
- --transport Transport: relay (default) or native
357
- --skills-global Install bundled skills to ~/.config/opencode/skill (default)
358
- --skills-local Install bundled skills to ./.opencode/skill
359
- --no-skills Skip installing bundled skills
360
-
361
- EXAMPLES:
362
- npx opendevbrowser # Interactive install
363
- npx opendevbrowser --global # Global install
364
- npx opendevbrowser --local # Project install
365
- npx opendevbrowser --full # Install + config + extension assets
366
- npx opendevbrowser -g --with-config # Global + config file
367
- npx opendevbrowser --skills-local # Install skills locally
368
- npx opendevbrowser --no-skills # Skip skill installation
369
- npx opendevbrowser --update # Update plugin
370
- npx opendevbrowser --uninstall --global # Remove from global config
371
- npx opendevbrowser native install <extension-id> # Install native host
372
- `.trim();
373
- }
374
421
  function detectOutputFormat(argv) {
375
422
  const args = expandShortFlags(argv.slice(2));
376
423
  try {
@@ -388,6 +435,374 @@ function registerCommand(definition) {
388
435
  function getCommand(name) {
389
436
  return registry.get(name);
390
437
  }
438
+ function listCommands() {
439
+ return Array.from(registry.values());
440
+ }
441
+
442
+ // src/cli/help.ts
443
+ var LABEL_WIDTH = 42;
444
+ var EXPECTED_TOOL_COUNT = 48;
445
+ var COMMAND_SET = new Set(CLI_COMMANDS);
446
+ var FLAG_SET = new Set(VALID_FLAGS);
447
+ var HELP_COMMAND_GROUPS = [
448
+ {
449
+ title: "Install & Lifecycle",
450
+ summary: "Install, remove, and inspect CLI basics.",
451
+ commands: ["install", "update", "uninstall", "help", "version"]
452
+ },
453
+ {
454
+ title: "Daemon & Runtime",
455
+ summary: "Run daemon services and single-process scripts.",
456
+ commands: ["serve", "daemon", "native", "run"]
457
+ },
458
+ {
459
+ title: "Session Lifecycle",
460
+ summary: "Launch/connect sessions and manage browser state.",
461
+ commands: ["launch", "connect", "disconnect", "status", "cookie-import", "cookie-list"]
462
+ },
463
+ {
464
+ title: "Provider Workflows",
465
+ summary: "Run research/shopping/media workflows and macro plans.",
466
+ commands: ["research", "shopping", "product-video", "artifacts", "macro-resolve"]
467
+ },
468
+ {
469
+ title: "Navigation",
470
+ summary: "Move through pages and capture fresh refs.",
471
+ commands: ["goto", "wait", "snapshot"]
472
+ },
473
+ {
474
+ title: "Interaction",
475
+ summary: "Perform ref-based interactions in the active page.",
476
+ commands: ["click", "hover", "press", "check", "uncheck", "type", "select", "scroll", "scroll-into-view"]
477
+ },
478
+ {
479
+ title: "Targets & Pages",
480
+ summary: "Manage tabs/targets and named pages.",
481
+ commands: ["targets-list", "target-use", "target-new", "target-close", "page", "pages", "page-close"]
482
+ },
483
+ {
484
+ title: "DOM & Export",
485
+ summary: "Read DOM state and export page/component code.",
486
+ commands: ["dom-html", "dom-text", "dom-attr", "dom-value", "dom-visible", "dom-enabled", "dom-checked", "clone-page", "clone-component"]
487
+ },
488
+ {
489
+ title: "Diagnostics & Annotation",
490
+ summary: "Collect runtime diagnostics and annotation payloads.",
491
+ commands: ["perf", "screenshot", "console-poll", "network-poll", "debug-trace-snapshot", "annotate"]
492
+ },
493
+ {
494
+ title: "Power",
495
+ summary: "Unsafe internal command passthrough.",
496
+ commands: ["rpc"]
497
+ }
498
+ ];
499
+ var HELP_FLAG_GROUPS = [
500
+ {
501
+ title: "Install/Global Flags",
502
+ summary: "Control installation scope and setup behavior.",
503
+ flags: [
504
+ { flag: "--global", alias: "-g", description: "Install into ~/.config/opencode/opencode.json." },
505
+ { flag: "--local", alias: "-l", description: "Install into ./opencode.json for this project." },
506
+ { flag: "--update", alias: "-u", description: "Alias for the update command." },
507
+ { flag: "--uninstall", description: "Alias for the uninstall command." },
508
+ { flag: "--with-config", description: "Also create opendevbrowser.jsonc defaults." },
509
+ { flag: "--full", alias: "-f", description: "Install config and pre-extract extension assets." },
510
+ { flag: "--no-prompt", description: "Run non-interactively using defaults." },
511
+ { flag: "--no-interactive", description: "Alias of --no-prompt." },
512
+ { flag: "--quiet", description: "Suppress non-error text output." },
513
+ { flag: "--skills-global", description: "Install bundled skills into global agent directories." },
514
+ { flag: "--skills-local", description: "Install bundled skills into local project agent directories." },
515
+ { flag: "--no-skills", description: "Skip bundled skill installation." }
516
+ ]
517
+ },
518
+ {
519
+ title: "Help/Output Flags",
520
+ summary: "Inspect help/version and control output transport.",
521
+ flags: [
522
+ { flag: "--help", alias: "-h", description: "Show CLI help output." },
523
+ { flag: "--version", alias: "-v", description: "Show CLI version." },
524
+ { flag: "--output-format", description: "Output mode: text, json, stream-json." },
525
+ { flag: "--transport", description: "Annotation transport: relay (default) or native." }
526
+ ]
527
+ },
528
+ {
529
+ title: "Daemon/Session/Launch Flags",
530
+ summary: "Control daemon binding, connect, and launch behavior.",
531
+ flags: [
532
+ { flag: "--port", description: "Daemon or relay port override." },
533
+ { flag: "--token", description: "Relay/daemon auth token override." },
534
+ { flag: "--stop", description: "Stop a running daemon." },
535
+ { flag: "--daemon", description: "Target daemon status mode where supported." },
536
+ { flag: "--script", description: "Path to a run-script JSON file." },
537
+ { flag: "--session-id", description: "Target an existing daemon session." },
538
+ { flag: "--close-browser", description: "Close managed browser on disconnect." },
539
+ { flag: "--ws-endpoint", description: "Connect using explicit CDP WebSocket endpoint." },
540
+ { flag: "--host", description: "CDP host for host/port connect mode." },
541
+ { flag: "--cdp-port", description: "CDP port for host/port connect mode." },
542
+ { flag: "--headless", description: "Launch managed browser in headless mode." },
543
+ { flag: "--profile", description: "Use a named browser profile directory." },
544
+ { flag: "--persist-profile", description: "Keep generated profile directory after exit." },
545
+ { flag: "--chrome-path", description: "Use a specific Chrome/Chromium binary." },
546
+ { flag: "--start-url", description: "Open this URL immediately after launch." },
547
+ { flag: "--flag", description: "Pass one or more extra Chrome CLI flags." },
548
+ { flag: "--no-extension", description: "Force managed mode without extension relay." },
549
+ { flag: "--extension-only", description: "Fail unless extension relay is connected." },
550
+ { flag: "--extension-legacy", description: "Use legacy /cdp relay mode instead of /ops." },
551
+ { flag: "--wait-for-extension", description: "Wait for extension handshake before returning." },
552
+ { flag: "--wait-timeout-ms", description: "Handshake wait timeout in milliseconds." }
553
+ ]
554
+ },
555
+ {
556
+ title: "Navigation/Interaction/Diagnostics Flags",
557
+ summary: "Command-specific flags for page actions and diagnostics.",
558
+ flags: [
559
+ { flag: "--url", description: "Target URL for navigation, connect, or workflow commands." },
560
+ { flag: "--wait-until", description: "Navigation wait strategy (load, domcontentloaded, etc.)." },
561
+ { flag: "--timeout-ms", description: "Operation timeout in milliseconds (for example goto, wait, screenshot, annotate, rpc, and macro-resolve)." },
562
+ { flag: "--ref", description: "Snapshot ref id for element-targeted commands." },
563
+ { flag: "--state", description: "Wait state selector for wait-style commands." },
564
+ { flag: "--until", description: "Wait condition selector for wait-style commands." },
565
+ { flag: "--mode", description: "Mode selector for commands that accept variants." },
566
+ { flag: "--max-chars", description: "Maximum text characters to return for DOM reads." },
567
+ { flag: "--cursor", description: "Cursor token for paginated list commands." },
568
+ { flag: "--text", description: "Text payload for type and related commands." },
569
+ { flag: "--clear", description: "Clear existing input value before typing." },
570
+ { flag: "--submit", description: "Submit form/input after typing." },
571
+ { flag: "--values", description: "CSV values for select commands." },
572
+ { flag: "--dy", description: "Vertical scroll delta for scroll commands." },
573
+ { flag: "--key", description: "Keyboard key for press command." },
574
+ { flag: "--attr", description: "DOM attribute name for dom-attr command." },
575
+ { flag: "--name", description: "Named page identifier for page commands." },
576
+ { flag: "--target-id", description: "Browser target id for target commands." },
577
+ { flag: "--tab-id", description: "Browser tab id override for extension/annotation commands." },
578
+ { flag: "--include-urls", description: "Include page URLs in list output where supported." },
579
+ { flag: "--path", description: "Filesystem path for command output/artifacts." },
580
+ { flag: "--since-seq", description: "Poll from sequence id across diagnostics streams." },
581
+ { flag: "--max", description: "Maximum number of records/items to return." },
582
+ { flag: "--since-console-seq", description: "Console sequence cursor for debug trace snapshots." },
583
+ { flag: "--since-network-seq", description: "Network sequence cursor for debug trace snapshots." },
584
+ { flag: "--since-exception-seq", description: "Exception sequence cursor for debug trace snapshots." },
585
+ { flag: "--request-id", description: "Attach/lookup request id for correlateable output." },
586
+ { flag: "--cookies", description: "Inline cookie payload for cookie-import command." },
587
+ { flag: "--cookies-file", description: "File path containing cookies for cookie-import." },
588
+ { flag: "--strict", description: "Fail cookie import on invalid entries." },
589
+ { flag: "--screenshot-mode", description: "Annotation screenshot mode: crop, full, or none." },
590
+ { flag: "--debug", description: "Enable debug-level annotation capture extras." },
591
+ { flag: "--context", description: "Free-form annotation context for reviewers/agents." }
592
+ ]
593
+ },
594
+ {
595
+ title: "Macro/Provider/Power Flags",
596
+ summary: "Workflow filters, provider selectors, and unsafe RPC options.",
597
+ flags: [
598
+ { flag: "--expression", description: "Macro expression to resolve/execute." },
599
+ { flag: "--default-provider", description: "Provider fallback for shorthand macro expressions." },
600
+ { flag: "--include-catalog", description: "Include macro catalog metadata in response." },
601
+ { flag: "--execute", description: "Execute resolved macro action after planning (pair with --timeout-ms on slow runs)." },
602
+ { flag: "--params", description: "Inline JSON params for rpc command." },
603
+ { flag: "--params-file", description: "Path to JSON params file for rpc command." },
604
+ { flag: "--unsafe-internal", description: "Required safety gate for rpc command." },
605
+ { flag: "--topic", description: "Research topic input." },
606
+ { flag: "--days", description: "Lookback window in days for research commands." },
607
+ { flag: "--from", description: "Start date boundary for research commands." },
608
+ { flag: "--to", description: "End date boundary for research commands." },
609
+ { flag: "--source-selection", description: "Research source-family selector." },
610
+ { flag: "--sources", description: "Explicit source selectors within a source family." },
611
+ { flag: "--include-engagement", description: "Include engagement metrics in research output." },
612
+ { flag: "--limit-per-source", description: "Per-source result cap for research runs." },
613
+ { flag: "--query", description: "Shopping query input." },
614
+ { flag: "--providers", description: "Comma-separated provider ids for shopping/artifacts." },
615
+ { flag: "--budget", description: "Budget filter for shopping workflows." },
616
+ { flag: "--region", description: "Region/country hint for provider selection." },
617
+ { flag: "--sort", description: "Sort mode for shopping results." },
618
+ { flag: "--product-url", description: "Target product URL for product-video/artifacts workflows." },
619
+ { flag: "--product-name", description: "Product name override for media workflows." },
620
+ { flag: "--provider-hint", description: "Provider hint override for product workflows." },
621
+ { flag: "--include-screenshots", description: "Include screenshots in product presentation output." },
622
+ { flag: "--include-all-images", description: "Include all discovered product images." },
623
+ { flag: "--include-copy", description: "Include product marketing copy metadata." },
624
+ { flag: "--output-dir", description: "Directory where generated artifacts are written." },
625
+ { flag: "--ttl-hours", description: "Artifact cache time-to-live in hours." },
626
+ { flag: "--expired-only", description: "List only expired artifacts in artifacts commands." }
627
+ ]
628
+ }
629
+ ];
630
+ var HELP_TOOL_ENTRIES = [
631
+ { name: "opendevbrowser_launch", description: "Launch a managed browser session." },
632
+ { name: "opendevbrowser_connect", description: "Connect to an existing browser session." },
633
+ { name: "opendevbrowser_disconnect", description: "Disconnect a managed or connected session." },
634
+ { name: "opendevbrowser_status", description: "Inspect session and relay status." },
635
+ { name: "opendevbrowser_targets_list", description: "List available page targets/tabs." },
636
+ { name: "opendevbrowser_target_use", description: "Switch active target by id." },
637
+ { name: "opendevbrowser_target_new", description: "Create a new target/tab." },
638
+ { name: "opendevbrowser_target_close", description: "Close target/tab by id." },
639
+ { name: "opendevbrowser_page", description: "Open or focus a named page." },
640
+ { name: "opendevbrowser_list", description: "List named pages in the session." },
641
+ { name: "opendevbrowser_close", description: "Close a named page." },
642
+ { name: "opendevbrowser_goto", description: "Navigate to a URL." },
643
+ { name: "opendevbrowser_wait", description: "Wait for load/ref/state conditions." },
644
+ { name: "opendevbrowser_snapshot", description: "Capture AX-tree refs for actions." },
645
+ { name: "opendevbrowser_click", description: "Click an element by ref." },
646
+ { name: "opendevbrowser_hover", description: "Hover an element by ref." },
647
+ { name: "opendevbrowser_press", description: "Send a keyboard key." },
648
+ { name: "opendevbrowser_check", description: "Check checkbox/radio by ref." },
649
+ { name: "opendevbrowser_uncheck", description: "Uncheck checkbox/radio by ref." },
650
+ { name: "opendevbrowser_type", description: "Type text into an input by ref." },
651
+ { name: "opendevbrowser_select", description: "Set select values by ref." },
652
+ { name: "opendevbrowser_scroll", description: "Scroll page or element." },
653
+ { name: "opendevbrowser_scroll_into_view", description: "Scroll target element into view." },
654
+ { name: "opendevbrowser_dom_get_html", description: "Get HTML for page or ref." },
655
+ { name: "opendevbrowser_dom_get_text", description: "Get text for page or ref." },
656
+ { name: "opendevbrowser_get_attr", description: "Read a DOM attribute by ref." },
657
+ { name: "opendevbrowser_get_value", description: "Read form/control value by ref." },
658
+ { name: "opendevbrowser_is_visible", description: "Check ref visibility." },
659
+ { name: "opendevbrowser_is_enabled", description: "Check ref enabled state." },
660
+ { name: "opendevbrowser_is_checked", description: "Check ref checked state." },
661
+ { name: "opendevbrowser_run", description: "Execute multi-action automation scripts." },
662
+ { name: "opendevbrowser_prompting_guide", description: "Return best-practice prompting guidance." },
663
+ { name: "opendevbrowser_console_poll", description: "Poll redacted console events." },
664
+ { name: "opendevbrowser_network_poll", description: "Poll redacted network events." },
665
+ { name: "opendevbrowser_debug_trace_snapshot", description: "Capture page + console + network diagnostics." },
666
+ { name: "opendevbrowser_cookie_import", description: "Import validated cookies into session." },
667
+ { name: "opendevbrowser_cookie_list", description: "List cookies in session with optional URL filters." },
668
+ { name: "opendevbrowser_macro_resolve", description: "Resolve/execute provider macro expressions." },
669
+ { name: "opendevbrowser_research_run", description: "Run research workflow directly." },
670
+ { name: "opendevbrowser_shopping_run", description: "Run shopping workflow directly." },
671
+ { name: "opendevbrowser_product_video_run", description: "Run product-video asset workflow directly." },
672
+ { name: "opendevbrowser_clone_page", description: "Export active page into React code." },
673
+ { name: "opendevbrowser_clone_component", description: "Export component by ref into React code." },
674
+ { name: "opendevbrowser_perf", description: "Collect browser performance metrics." },
675
+ { name: "opendevbrowser_screenshot", description: "Capture page screenshot." },
676
+ { name: "opendevbrowser_annotate", description: "Capture interactive annotations." },
677
+ { name: "opendevbrowser_skill_list", description: "List available skill packs." },
678
+ { name: "opendevbrowser_skill_load", description: "Load a specific skill pack." }
679
+ ];
680
+ var HELP_REFERENCE_ENTRIES = [
681
+ { label: "docs/CLI.md", description: "Full command docs, flag matrix, and examples." },
682
+ { label: "docs/SURFACE_REFERENCE.md", description: "Canonical CLI/tool/channel inventory matrix." },
683
+ { label: "src/tools/index.ts", description: "Code-level tool registry (source of truth)." },
684
+ { label: "opendevbrowser --help", description: "Always safe first command for quick discovery." }
685
+ ];
686
+ function formatRows(rows) {
687
+ return rows.map((row) => ` ${row.label.padEnd(LABEL_WIDTH)} ${row.description}`).join("\n");
688
+ }
689
+ function getCommandDescriptions() {
690
+ const descriptions = /* @__PURE__ */ new Map();
691
+ for (const definition of listCommands()) {
692
+ descriptions.set(definition.name, definition.description);
693
+ }
694
+ return descriptions;
695
+ }
696
+ function assertCommandCoverage(commandDescriptions) {
697
+ const seen = /* @__PURE__ */ new Set();
698
+ for (const group of HELP_COMMAND_GROUPS) {
699
+ for (const command of group.commands) {
700
+ if (!COMMAND_SET.has(command)) {
701
+ throw new Error(`Help references unknown CLI command: ${command}`);
702
+ }
703
+ if (!commandDescriptions.has(command)) {
704
+ throw new Error(`Help references unregistered CLI command: ${command}`);
705
+ }
706
+ if (seen.has(command)) {
707
+ throw new Error(`Help command appears multiple times: ${command}`);
708
+ }
709
+ seen.add(command);
710
+ }
711
+ }
712
+ if (seen.size !== CLI_COMMANDS.length) {
713
+ const missing = CLI_COMMANDS.filter((command) => !seen.has(command));
714
+ throw new Error(`Help command coverage mismatch; missing: ${missing.join(", ")}`);
715
+ }
716
+ }
717
+ function assertFlagCoverage() {
718
+ const seen = /* @__PURE__ */ new Set();
719
+ for (const group of HELP_FLAG_GROUPS) {
720
+ for (const entry of group.flags) {
721
+ if (!FLAG_SET.has(entry.flag)) {
722
+ throw new Error(`Help references unknown CLI flag: ${entry.flag}`);
723
+ }
724
+ if (seen.has(entry.flag)) {
725
+ throw new Error(`Help flag appears multiple times: ${entry.flag}`);
726
+ }
727
+ seen.add(entry.flag);
728
+ }
729
+ }
730
+ if (seen.size !== VALID_FLAGS.length) {
731
+ const missing = VALID_FLAGS.filter((flag) => !seen.has(flag));
732
+ throw new Error(`Help flag coverage mismatch; missing: ${missing.join(", ")}`);
733
+ }
734
+ }
735
+ function assertToolCoverage() {
736
+ if (HELP_TOOL_ENTRIES.length !== EXPECTED_TOOL_COUNT) {
737
+ throw new Error(`Help tool inventory must list ${EXPECTED_TOOL_COUNT} tools; got ${HELP_TOOL_ENTRIES.length}`);
738
+ }
739
+ const seen = /* @__PURE__ */ new Set();
740
+ for (const entry of HELP_TOOL_ENTRIES) {
741
+ if (seen.has(entry.name)) {
742
+ throw new Error(`Help tool appears multiple times: ${entry.name}`);
743
+ }
744
+ if (!entry.name.startsWith("opendevbrowser_")) {
745
+ throw new Error(`Invalid tool name in help inventory: ${entry.name}`);
746
+ }
747
+ seen.add(entry.name);
748
+ }
749
+ }
750
+ function formatCommandGroups(commandDescriptions) {
751
+ return HELP_COMMAND_GROUPS.map((group) => {
752
+ const rows = group.commands.map((command) => ({
753
+ label: command,
754
+ description: commandDescriptions.get(command) ?? "Missing command description."
755
+ }));
756
+ return `${group.title}: ${group.summary}
757
+ ${formatRows(rows)}`;
758
+ }).join("\n\n");
759
+ }
760
+ function formatFlagGroups() {
761
+ return HELP_FLAG_GROUPS.map((group) => {
762
+ const rows = group.flags.map((entry) => ({
763
+ label: entry.alias ? `${entry.flag} (${entry.alias})` : entry.flag,
764
+ description: entry.description
765
+ }));
766
+ return `${group.title}: ${group.summary}
767
+ ${formatRows(rows)}`;
768
+ }).join("\n\n");
769
+ }
770
+ function formatToolEntries() {
771
+ return formatRows(HELP_TOOL_ENTRIES.map((entry) => ({
772
+ label: entry.name,
773
+ description: entry.description
774
+ })));
775
+ }
776
+ function formatReferenceEntries() {
777
+ return formatRows(HELP_REFERENCE_ENTRIES.map((entry) => ({
778
+ label: entry.label,
779
+ description: entry.description
780
+ })));
781
+ }
782
+ function getHelpText() {
783
+ const commandDescriptions = getCommandDescriptions();
784
+ assertCommandCoverage(commandDescriptions);
785
+ assertFlagCoverage();
786
+ assertToolCoverage();
787
+ return [
788
+ "OpenDevBrowser CLI",
789
+ "",
790
+ "Usage:",
791
+ " npx opendevbrowser <command> [options]",
792
+ "",
793
+ `Command Inventory (all ${CLI_COMMANDS.length} commands):`,
794
+ formatCommandGroups(commandDescriptions),
795
+ "",
796
+ "Flag Inventory (all supported flags):",
797
+ formatFlagGroups(),
798
+ "",
799
+ `Tool Inventory (all ${EXPECTED_TOOL_COUNT} opendevbrowser_* tools):`,
800
+ formatToolEntries(),
801
+ "",
802
+ "Reference Pointers:",
803
+ formatReferenceEntries()
804
+ ].join("\n");
805
+ }
391
806
 
392
807
  // src/cli/installers/global.ts
393
808
  import * as fs3 from "fs";
@@ -504,7 +919,7 @@ function buildConfigTemplate(relayToken, daemonToken) {
504
919
  "skills": {
505
920
  "nudge": {
506
921
  "enabled": true,
507
- "keywords": ["login", "form", "extract"],
922
+ "keywords": ["quick start", "getting started", "launch", "connect", "setup"],
508
923
  "maxAgeMs": 60000
509
924
  }
510
925
  },
@@ -655,6 +1070,7 @@ import * as os3 from "os";
655
1070
  import { fileURLToPath } from "url";
656
1071
  var PACKAGE_NAME = "opendevbrowser";
657
1072
  var SKILL_DIR_NAME = "skill";
1073
+ var SKILLS_DIR_NAME = "skills";
658
1074
  var cachedPackageRoot = null;
659
1075
  function findPackageRoot(startDir) {
660
1076
  let current = startDir;
@@ -697,33 +1113,108 @@ function getGlobalSkillDir() {
697
1113
  function getLocalSkillDir() {
698
1114
  return path3.join(process.cwd(), ".opencode", SKILL_DIR_NAME);
699
1115
  }
1116
+ function getCodexHomeDir() {
1117
+ return process.env.CODEX_HOME || path3.join(os3.homedir(), ".codex");
1118
+ }
1119
+ function getClaudeCodeHomeDir() {
1120
+ return process.env.CLAUDECODE_HOME || process.env.CLAUDE_HOME || path3.join(os3.homedir(), ".claude");
1121
+ }
1122
+ function getAmpHomeDir() {
1123
+ return process.env.AMPCLI_HOME || process.env.AMP_CLI_HOME || process.env.AMP_HOME || path3.join(os3.homedir(), ".amp");
1124
+ }
1125
+ function dedupeTargets(targets) {
1126
+ const deduped = /* @__PURE__ */ new Map();
1127
+ for (const target of targets) {
1128
+ const key = path3.resolve(target.dir);
1129
+ const existing = deduped.get(key);
1130
+ if (existing) {
1131
+ if (!existing.agents.includes(target.agent)) {
1132
+ existing.agents.push(target.agent);
1133
+ }
1134
+ continue;
1135
+ }
1136
+ deduped.set(key, { agents: [target.agent], dir: target.dir });
1137
+ }
1138
+ return Array.from(deduped.values());
1139
+ }
1140
+ function getGlobalSkillTargets() {
1141
+ const claudeSkillsDir = path3.join(getClaudeCodeHomeDir(), SKILLS_DIR_NAME);
1142
+ const ampSkillsDir = path3.join(getAmpHomeDir(), SKILLS_DIR_NAME);
1143
+ return dedupeTargets([
1144
+ { agent: "opencode", dir: getGlobalSkillDir() },
1145
+ { agent: "codex", dir: path3.join(getCodexHomeDir(), SKILLS_DIR_NAME) },
1146
+ { agent: "claudecode", dir: claudeSkillsDir },
1147
+ { agent: "claude", dir: claudeSkillsDir },
1148
+ { agent: "ampcli", dir: ampSkillsDir },
1149
+ { agent: "amp", dir: ampSkillsDir }
1150
+ ]);
1151
+ }
1152
+ function getLocalSkillTargets() {
1153
+ const localClaudeSkillsDir = path3.join(process.cwd(), ".claude", SKILLS_DIR_NAME);
1154
+ const localAmpSkillsDir = path3.join(process.cwd(), ".amp", SKILLS_DIR_NAME);
1155
+ return dedupeTargets([
1156
+ { agent: "opencode", dir: getLocalSkillDir() },
1157
+ { agent: "codex", dir: path3.join(process.cwd(), ".codex", SKILLS_DIR_NAME) },
1158
+ { agent: "claudecode", dir: localClaudeSkillsDir },
1159
+ { agent: "claude", dir: localClaudeSkillsDir },
1160
+ { agent: "ampcli", dir: localAmpSkillsDir },
1161
+ { agent: "amp", dir: localAmpSkillsDir }
1162
+ ]);
1163
+ }
700
1164
 
701
1165
  // src/cli/installers/skills.ts
702
1166
  function installSkills(mode) {
703
- const targetDir = mode === "global" ? getGlobalSkillDir() : getLocalSkillDir();
704
- const installed = [];
705
- const skipped = [];
1167
+ const targets = mode === "global" ? getGlobalSkillTargets() : getLocalSkillTargets();
1168
+ const targetResults = [];
706
1169
  try {
707
1170
  const sourceDir = getBundledSkillsDir();
708
1171
  const entries = fs6.readdirSync(sourceDir, { withFileTypes: true });
709
- ensureDir(targetDir);
710
- for (const entry of entries) {
711
- if (!entry.isDirectory()) continue;
712
- const skillName = entry.name;
713
- const sourcePath = path4.join(sourceDir, skillName);
714
- const targetPath = path4.join(targetDir, skillName);
715
- if (fs6.existsSync(targetPath)) {
716
- skipped.push(skillName);
717
- continue;
1172
+ for (const target of targets) {
1173
+ const installed2 = [];
1174
+ const skipped2 = [];
1175
+ try {
1176
+ ensureDir(target.dir);
1177
+ for (const entry of entries) {
1178
+ if (!entry.isDirectory()) continue;
1179
+ const skillName = entry.name;
1180
+ const sourcePath = path4.join(sourceDir, skillName);
1181
+ const targetPath = path4.join(target.dir, skillName);
1182
+ if (fs6.existsSync(targetPath)) {
1183
+ skipped2.push(skillName);
1184
+ continue;
1185
+ }
1186
+ fs6.cpSync(sourcePath, targetPath, { recursive: true });
1187
+ installed2.push(skillName);
1188
+ }
1189
+ targetResults.push({
1190
+ agents: target.agents,
1191
+ targetDir: target.dir,
1192
+ installed: installed2,
1193
+ skipped: skipped2,
1194
+ success: true
1195
+ });
1196
+ } catch (error) {
1197
+ const message = error instanceof Error ? error.message : String(error);
1198
+ targetResults.push({
1199
+ agents: target.agents,
1200
+ targetDir: target.dir,
1201
+ installed: installed2,
1202
+ skipped: skipped2,
1203
+ success: false,
1204
+ error: message
1205
+ });
718
1206
  }
719
- fs6.cpSync(sourcePath, targetPath, { recursive: true });
720
- installed.push(skillName);
721
1207
  }
722
- const summary = `Skills ${mode} install: ${installed.length} installed${skipped.length ? `, ${skipped.length} skipped` : ""} (${targetDir})`;
1208
+ const installed = targetResults.flatMap((result) => result.installed);
1209
+ const skipped = targetResults.flatMap((result) => result.skipped);
1210
+ const failures = targetResults.filter((result) => !result.success);
1211
+ const failedSummary = failures.length > 0 ? `, ${failures.length} failed` : "";
1212
+ const summary = `Skills ${mode} install: ${installed.length} installed${skipped.length ? `, ${skipped.length} skipped` : ""}${failedSummary} across ${targetResults.length} targets`;
723
1213
  return {
724
- success: true,
1214
+ success: failures.length === 0,
725
1215
  message: summary,
726
- targetDir,
1216
+ mode,
1217
+ targets: targetResults,
727
1218
  installed,
728
1219
  skipped
729
1220
  };
@@ -732,9 +1223,10 @@ function installSkills(mode) {
732
1223
  return {
733
1224
  success: false,
734
1225
  message: `Failed to install skills (${mode}): ${message}`,
735
- targetDir,
736
- installed,
737
- skipped
1226
+ mode,
1227
+ targets: targetResults,
1228
+ installed: targetResults.flatMap((result) => result.installed),
1229
+ skipped: targetResults.flatMap((result) => result.skipped)
738
1230
  };
739
1231
  }
740
1232
  }
@@ -866,6 +1358,9 @@ function findInstalledConfigs() {
866
1358
  return { global, local };
867
1359
  }
868
1360
 
1361
+ // src/cli/commands/serve.ts
1362
+ import { spawnSync } from "child_process";
1363
+
869
1364
  // src/cli/utils/parse.ts
870
1365
  function parseNumberFlag(value, flag, options = {}) {
871
1366
  const parsed = Number(value);
@@ -1175,7 +1670,7 @@ function discoverExtensionId() {
1175
1670
  return { extensionId: match.id, matchedBy: match.matchedBy };
1176
1671
  }
1177
1672
  if (!nameFallback) {
1178
- nameFallback = match;
1673
+ nameFallback = { id: match.id, matchedBy: "name" };
1179
1674
  }
1180
1675
  }
1181
1676
  if (!commandFallback) {
@@ -1259,6 +1754,19 @@ async function runNativeCommand(args) {
1259
1754
 
1260
1755
  // src/cli/commands/serve.ts
1261
1756
  var daemonHandle = null;
1757
+ var PS_MAX_BUFFER = 8 * 1024 * 1024;
1758
+ function resolveTokenCandidates(requestedToken, metadataToken, configToken) {
1759
+ return Array.from(new Set([requestedToken, metadataToken, configToken].filter((token) => typeof token === "string" && token.trim().length > 0)));
1760
+ }
1761
+ async function resolveExistingDaemon(port, tokens) {
1762
+ for (const token of tokens) {
1763
+ const status = await fetchDaemonStatus(port, token);
1764
+ if (status?.ok) {
1765
+ return { token, status };
1766
+ }
1767
+ }
1768
+ return null;
1769
+ }
1262
1770
  function parseServeArgs(rawArgs) {
1263
1771
  const parsed = { stop: false };
1264
1772
  for (let i = 0; i < rawArgs.length; i += 1) {
@@ -1304,11 +1812,64 @@ function parseServeArgs(rawArgs) {
1304
1812
  }
1305
1813
  return parsed;
1306
1814
  }
1815
+ function listServeProcessPids() {
1816
+ const result = spawnSync("ps", ["-ax", "-o", "pid=,command="], {
1817
+ encoding: "utf-8",
1818
+ maxBuffer: PS_MAX_BUFFER
1819
+ });
1820
+ if ((result.status ?? 1) !== 0) {
1821
+ return [];
1822
+ }
1823
+ const servePattern = /\b(opendevbrowser|dist\/cli\/index\.js)\b.*\bserve\b/;
1824
+ const lines = String(result.stdout ?? "").split(/\r?\n/);
1825
+ const pids = /* @__PURE__ */ new Set();
1826
+ for (const line of lines) {
1827
+ const trimmed = line.trim();
1828
+ if (!trimmed) continue;
1829
+ const match = trimmed.match(/^(\d+)\s+(.+)$/);
1830
+ if (!match) continue;
1831
+ const pidText = match[1];
1832
+ if (!pidText) continue;
1833
+ const pid = Number.parseInt(pidText, 10);
1834
+ const command = match[2] ?? "";
1835
+ if (!Number.isInteger(pid) || pid <= 0) continue;
1836
+ if (pid === process.pid || pid === process.ppid) continue;
1837
+ if (!servePattern.test(command)) continue;
1838
+ pids.add(pid);
1839
+ }
1840
+ return [...pids];
1841
+ }
1842
+ function terminateProcess(pid) {
1843
+ if (!Number.isInteger(pid) || pid <= 0 || pid === process.pid || pid === process.ppid) {
1844
+ return false;
1845
+ }
1846
+ try {
1847
+ process.kill(pid, "SIGTERM");
1848
+ } catch {
1849
+ return false;
1850
+ }
1851
+ try {
1852
+ process.kill(pid, "SIGKILL");
1853
+ } catch {
1854
+ }
1855
+ return true;
1856
+ }
1857
+ function cleanupStaleServeProcesses(keepPid) {
1858
+ const candidates = listServeProcessPids();
1859
+ let cleaned = 0;
1860
+ for (const pid of candidates) {
1861
+ if (Number.isInteger(keepPid) && pid === keepPid) continue;
1862
+ if (terminateProcess(pid)) {
1863
+ cleaned += 1;
1864
+ }
1865
+ }
1866
+ return cleaned;
1867
+ }
1307
1868
  async function runServe(args) {
1308
1869
  const serveArgs = parseServeArgs(args.rawArgs);
1309
1870
  if (serveArgs.stop) {
1310
- const metadata = readDaemonMetadata();
1311
- if (!metadata) {
1871
+ const metadata2 = readDaemonMetadata();
1872
+ if (!metadata2) {
1312
1873
  if (daemonHandle) {
1313
1874
  await daemonHandle.stop();
1314
1875
  daemonHandle = null;
@@ -1317,9 +1878,9 @@ async function runServe(args) {
1317
1878
  return { success: false, message: "Daemon not running.", exitCode: EXIT_DISCONNECTED };
1318
1879
  }
1319
1880
  try {
1320
- const response = await fetchWithTimeout(`http://127.0.0.1:${metadata.port}/stop`, {
1881
+ const response = await fetchWithTimeout(`http://127.0.0.1:${metadata2.port}/stop`, {
1321
1882
  method: "POST",
1322
- headers: { Authorization: `Bearer ${metadata.token}` }
1883
+ headers: { Authorization: `Bearer ${metadata2.token}` }
1323
1884
  });
1324
1885
  if (!response.ok) {
1325
1886
  throw new Error(`Stop failed (${response.status})`);
@@ -1331,6 +1892,29 @@ async function runServe(args) {
1331
1892
  }
1332
1893
  }
1333
1894
  const config = loadGlobalConfig();
1895
+ const requestedPort = serveArgs.port ?? config.daemonPort;
1896
+ const metadata = readDaemonMetadata();
1897
+ const metadataToken = metadata?.port === requestedPort ? metadata.token : void 0;
1898
+ const tokenCandidates = resolveTokenCandidates(serveArgs.token, metadataToken, config.daemonToken);
1899
+ const existingDaemon = await resolveExistingDaemon(requestedPort, tokenCandidates);
1900
+ const staleCleared = cleanupStaleServeProcesses(existingDaemon?.status.pid);
1901
+ if (existingDaemon) {
1902
+ const relayPort = existingDaemon.status.relay.port ?? config.relayPort;
1903
+ const staleNote2 = staleCleared > 0 ? ` Cleared ${staleCleared} stale daemon process${staleCleared === 1 ? "" : "es"}.` : "";
1904
+ return {
1905
+ success: true,
1906
+ message: `Daemon already running on 127.0.0.1:${requestedPort} (pid=${existingDaemon.status.pid}, relay ${relayPort}).${staleNote2}`,
1907
+ data: {
1908
+ port: requestedPort,
1909
+ pid: existingDaemon.status.pid,
1910
+ relayPort,
1911
+ alreadyRunning: true,
1912
+ staleDaemonsCleared: staleCleared,
1913
+ relay: existingDaemon.status.relay
1914
+ },
1915
+ exitCode: null
1916
+ };
1917
+ }
1334
1918
  let nativeStatus = getNativeStatusSnapshot();
1335
1919
  let nativeMessage = null;
1336
1920
  if (!nativeStatus.installed) {
@@ -1350,20 +1934,55 @@ async function runServe(args) {
1350
1934
  nativeMessage = "Native host not installed. Set nativeExtensionId in opendevbrowser.jsonc to auto-install.";
1351
1935
  }
1352
1936
  }
1353
- const handle = await startDaemon({
1354
- port: serveArgs.port,
1355
- token: serveArgs.token,
1356
- config
1357
- });
1937
+ let handle;
1938
+ try {
1939
+ handle = await startDaemon({
1940
+ port: serveArgs.port,
1941
+ token: serveArgs.token,
1942
+ config
1943
+ });
1944
+ } catch (error) {
1945
+ const message2 = error instanceof Error ? error.message : String(error);
1946
+ if (message2.includes("EADDRINUSE") || message2.includes("in use")) {
1947
+ const runningDaemon = await resolveExistingDaemon(requestedPort, tokenCandidates);
1948
+ if (runningDaemon) {
1949
+ const relayPort = runningDaemon.status.relay.port ?? config.relayPort;
1950
+ return {
1951
+ success: true,
1952
+ message: `Daemon already running on 127.0.0.1:${requestedPort} (pid=${runningDaemon.status.pid}, relay ${relayPort}).`,
1953
+ data: {
1954
+ port: requestedPort,
1955
+ pid: runningDaemon.status.pid,
1956
+ relayPort,
1957
+ alreadyRunning: true,
1958
+ relay: runningDaemon.status.relay
1959
+ },
1960
+ exitCode: null
1961
+ };
1962
+ }
1963
+ return {
1964
+ success: false,
1965
+ message: `Daemon port ${requestedPort} is already in use by another process. If this is an existing daemon, run \`opendevbrowser status --daemon\` or \`opendevbrowser serve --stop\`.`,
1966
+ exitCode: EXIT_EXECUTION
1967
+ };
1968
+ }
1969
+ return {
1970
+ success: false,
1971
+ message: `Failed to start daemon: ${message2}`,
1972
+ exitCode: EXIT_EXECUTION
1973
+ };
1974
+ }
1358
1975
  daemonHandle = handle;
1359
1976
  const { state } = handle;
1360
1977
  const baseMessage = `Daemon running on 127.0.0.1:${state.port} (relay ${state.relayPort})`;
1978
+ const staleNote = staleCleared > 0 ? `
1979
+ Cleared ${staleCleared} stale daemon process${staleCleared === 1 ? "" : "es"}.` : "";
1361
1980
  const message = nativeMessage ? `${baseMessage}
1362
- ${nativeMessage}` : baseMessage;
1981
+ ${nativeMessage}${staleNote}` : `${baseMessage}${staleNote}`;
1363
1982
  return {
1364
1983
  success: true,
1365
1984
  message,
1366
- data: { port: state.port, pid: state.pid, relayPort: state.relayPort, native: nativeStatus },
1985
+ data: { port: state.port, pid: state.pid, relayPort: state.relayPort, native: nativeStatus, staleDaemonsCleared: staleCleared },
1367
1986
  exitCode: null
1368
1987
  };
1369
1988
  }
@@ -1372,7 +1991,7 @@ ${nativeMessage}` : baseMessage;
1372
1991
  import { execFileSync as execFileSync2 } from "child_process";
1373
1992
  import { existsSync as existsSync8, mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "fs";
1374
1993
  import { homedir as homedir7 } from "os";
1375
- import { dirname as dirname5, join as join8, resolve as resolve3 } from "path";
1994
+ import { dirname as dirname5, join as join8, resolve as resolve4 } from "path";
1376
1995
  import { fileURLToPath as fileURLToPath3 } from "url";
1377
1996
  var MAC_LABEL = "com.opendevbrowser.daemon";
1378
1997
  var WIN_TASK_NAME = "OpenDevBrowser Daemon";
@@ -1390,7 +2009,7 @@ var defaultDeps = () => ({
1390
2009
  });
1391
2010
  var resolveCliPathFromModule = (moduleUrl, exists) => {
1392
2011
  const modulePath = fileURLToPath3(moduleUrl);
1393
- const candidate = resolve3(dirname5(modulePath), "..", "index.js");
2012
+ const candidate = resolve4(dirname5(modulePath), "..", "index.js");
1394
2013
  if (!exists(candidate)) {
1395
2014
  throw new Error(`CLI entrypoint not found at ${candidate}`);
1396
2015
  }
@@ -1401,7 +2020,7 @@ var resolveCliEntrypoint = (deps = {}) => {
1401
2020
  const exists = resolved.existsSync;
1402
2021
  let cliPath = null;
1403
2022
  if (resolved.argv1) {
1404
- const candidate = resolve3(resolved.argv1);
2023
+ const candidate = resolve4(resolved.argv1);
1405
2024
  if (exists(candidate)) {
1406
2025
  cliPath = candidate;
1407
2026
  }
@@ -1687,6 +2306,75 @@ async function runDaemonCommand(args) {
1687
2306
  };
1688
2307
  }
1689
2308
 
2309
+ // src/cli/commands/artifacts.ts
2310
+ import { join as join9, resolve as resolve5 } from "path";
2311
+ import { tmpdir } from "os";
2312
+ var usageError = () => {
2313
+ throw createUsageError("Usage: opendevbrowser artifacts cleanup --expired-only [--output-dir <path>]");
2314
+ };
2315
+ var requireValue = (rawArgs, index, flag) => {
2316
+ const value = rawArgs[index + 1];
2317
+ if (!value) {
2318
+ throw createUsageError(`Missing value for ${flag}`);
2319
+ }
2320
+ return value;
2321
+ };
2322
+ var parseArtifactsArgs = (rawArgs) => {
2323
+ const [candidate, ...rest] = rawArgs;
2324
+ if (candidate !== "cleanup") {
2325
+ usageError();
2326
+ }
2327
+ const subcommand = "cleanup";
2328
+ let expiredOnly = false;
2329
+ let outputDir;
2330
+ for (let index = 0; index < rest.length; index += 1) {
2331
+ const arg = rest[index];
2332
+ if (arg === "--expired-only") {
2333
+ expiredOnly = true;
2334
+ continue;
2335
+ }
2336
+ if (arg === "--output-dir") {
2337
+ outputDir = requireValue(rest, index, "--output-dir");
2338
+ index += 1;
2339
+ continue;
2340
+ }
2341
+ if (arg?.startsWith("--output-dir=")) {
2342
+ const value = arg.split("=", 2)[1];
2343
+ if (!value) {
2344
+ throw createUsageError("Missing value for --output-dir");
2345
+ }
2346
+ outputDir = value;
2347
+ continue;
2348
+ }
2349
+ throw createUsageError(`Unknown artifacts flag: ${arg}`);
2350
+ }
2351
+ if (!expiredOnly) {
2352
+ usageError();
2353
+ }
2354
+ return {
2355
+ subcommand,
2356
+ expiredOnly,
2357
+ outputDir
2358
+ };
2359
+ };
2360
+ async function runArtifactsCommand(args) {
2361
+ const parsed = parseArtifactsArgs(args.rawArgs);
2362
+ const rootDir = parsed.outputDir ? resolve5(parsed.outputDir) : join9(tmpdir(), "opendevbrowser");
2363
+ const cleaned = await cleanupExpiredArtifacts(rootDir);
2364
+ return {
2365
+ success: true,
2366
+ message: `Artifact cleanup completed. Removed ${cleaned.removed.length} expired run(s).`,
2367
+ data: {
2368
+ rootDir,
2369
+ expiredOnly: parsed.expiredOnly,
2370
+ removed: cleaned.removed,
2371
+ skipped: cleaned.skipped,
2372
+ removedCount: cleaned.removed.length,
2373
+ skippedCount: cleaned.skipped.length
2374
+ }
2375
+ };
2376
+ }
2377
+
1690
2378
  // src/cli/commands/run.ts
1691
2379
  import { readFileSync as readFileSync4 } from "fs";
1692
2380
 
@@ -1790,13 +2478,13 @@ function parseRunArgs(rawArgs) {
1790
2478
  return parsed;
1791
2479
  }
1792
2480
  function readScriptFromStdin() {
1793
- return new Promise((resolve4, reject) => {
2481
+ return new Promise((resolve6, reject) => {
1794
2482
  let data = "";
1795
2483
  process.stdin.setEncoding("utf8");
1796
2484
  process.stdin.on("data", (chunk) => {
1797
2485
  data += chunk;
1798
2486
  });
1799
- process.stdin.on("end", () => resolve4(data));
2487
+ process.stdin.on("end", () => resolve6(data));
1800
2488
  process.stdin.on("error", reject);
1801
2489
  });
1802
2490
  }
@@ -1851,6 +2539,14 @@ async function runScriptCommand(args) {
1851
2539
  }
1852
2540
 
1853
2541
  // src/cli/commands/session/launch.ts
2542
+ var MIN_LAUNCH_CALL_TIMEOUT_MS = 3e4;
2543
+ var LAUNCH_CALL_TIMEOUT_BUFFER_MS = 5e3;
2544
+ var parseBooleanFlag = (value, flag) => {
2545
+ const normalized = value.trim().toLowerCase();
2546
+ if (normalized === "true" || normalized === "1") return true;
2547
+ if (normalized === "false" || normalized === "0") return false;
2548
+ throw createUsageError(`Invalid ${flag}: ${value}`);
2549
+ };
1854
2550
  function parseLaunchArgs(rawArgs) {
1855
2551
  const parsed = { flags: [] };
1856
2552
  for (let i = 0; i < rawArgs.length; i += 1) {
@@ -1893,7 +2589,19 @@ function parseLaunchArgs(rawArgs) {
1893
2589
  continue;
1894
2590
  }
1895
2591
  if (arg === "--persist-profile") {
1896
- parsed.persistProfile = true;
2592
+ const value = rawArgs[i + 1];
2593
+ if (value && !value.startsWith("--")) {
2594
+ parsed.persistProfile = parseBooleanFlag(value, "--persist-profile");
2595
+ i += 1;
2596
+ } else {
2597
+ parsed.persistProfile = true;
2598
+ }
2599
+ continue;
2600
+ }
2601
+ if (arg?.startsWith("--persist-profile=")) {
2602
+ const value = arg.split("=", 2)[1];
2603
+ if (!value) throw createUsageError("Missing value for --persist-profile");
2604
+ parsed.persistProfile = parseBooleanFlag(value, "--persist-profile");
1897
2605
  continue;
1898
2606
  }
1899
2607
  if (arg === "--no-extension") {
@@ -1941,10 +2649,15 @@ function parseLaunchArgs(rawArgs) {
1941
2649
  }
1942
2650
  return parsed;
1943
2651
  }
2652
+ function deriveLaunchCallTimeoutMs(launchArgs) {
2653
+ const waitHintMs = typeof launchArgs.waitTimeoutMs === "number" ? launchArgs.waitTimeoutMs + LAUNCH_CALL_TIMEOUT_BUFFER_MS : 0;
2654
+ return Math.max(MIN_LAUNCH_CALL_TIMEOUT_MS, waitHintMs);
2655
+ }
1944
2656
  async function runSessionLaunch(args) {
1945
2657
  const launchArgs = parseLaunchArgs(args.rawArgs);
2658
+ const launchCallTimeoutMs = deriveLaunchCallTimeoutMs(launchArgs);
1946
2659
  try {
1947
- const result = await callDaemon("session.launch", launchArgs);
2660
+ const result = await callDaemon("session.launch", launchArgs, { timeoutMs: launchCallTimeoutMs });
1948
2661
  return {
1949
2662
  success: true,
1950
2663
  message: `Session launched: ${result.sessionId}`,
@@ -1966,7 +2679,8 @@ async function runSessionLaunch(args) {
1966
2679
  );
1967
2680
  if (retry) {
1968
2681
  try {
1969
- const result = await callDaemon("session.launch", { ...launchArgs, waitForExtension: true });
2682
+ const retryArgs = { ...launchArgs, waitForExtension: true };
2683
+ const result = await callDaemon("session.launch", retryArgs, { timeoutMs: deriveLaunchCallTimeoutMs(retryArgs) });
1970
2684
  return {
1971
2685
  success: true,
1972
2686
  message: `Session launched: ${result.sessionId}`,
@@ -1979,11 +2693,12 @@ async function runSessionLaunch(args) {
1979
2693
  const proceedManaged = await promptYesNo("Proceed with a managed session (headed)?", false);
1980
2694
  if (proceedManaged) {
1981
2695
  const useHeadless = await promptYesNo("Run headless instead?", false);
1982
- const result = await callDaemon("session.launch", {
2696
+ const managedArgs = {
1983
2697
  ...launchArgs,
1984
2698
  noExtension: true,
1985
2699
  headless: useHeadless ? true : false
1986
- });
2700
+ };
2701
+ const result = await callDaemon("session.launch", managedArgs, { timeoutMs: deriveLaunchCallTimeoutMs(managedArgs) });
1987
2702
  return {
1988
2703
  success: true,
1989
2704
  message: `Session launched: ${result.sessionId}`,
@@ -2007,16 +2722,16 @@ function promptYesNo(question, defaultYes) {
2007
2722
  return Promise.resolve(false);
2008
2723
  }
2009
2724
  const suffix = defaultYes ? " [Y/n] " : " [y/N] ";
2010
- return new Promise((resolve4) => {
2725
+ return new Promise((resolve6) => {
2011
2726
  process.stdout.write(`${question}${suffix}`);
2012
2727
  process.stdin.setEncoding("utf8");
2013
2728
  process.stdin.once("data", (data) => {
2014
2729
  const input = data.toString().trim().toLowerCase();
2015
2730
  if (!input) {
2016
- resolve4(defaultYes);
2731
+ resolve6(defaultYes);
2017
2732
  return;
2018
2733
  }
2019
- resolve4(input === "y" || input === "yes");
2734
+ resolve6(input === "y" || input === "yes");
2020
2735
  });
2021
2736
  });
2022
2737
  }
@@ -2067,6 +2782,10 @@ function parseConnectArgs(rawArgs) {
2067
2782
  parsed.extensionLegacy = true;
2068
2783
  continue;
2069
2784
  }
2785
+ if (arg === "--headless") {
2786
+ parsed.headless = true;
2787
+ continue;
2788
+ }
2070
2789
  }
2071
2790
  return parsed;
2072
2791
  }
@@ -2404,7 +3123,7 @@ async function runSnapshot(args) {
2404
3123
  }
2405
3124
 
2406
3125
  // src/cli/commands/annotate.ts
2407
- var requireValue = (value, flag) => {
3126
+ var requireValue2 = (value, flag) => {
2408
3127
  if (!value) throw createUsageError(`Missing value for ${flag}`);
2409
3128
  return value;
2410
3129
  };
@@ -2425,68 +3144,68 @@ var parseAnnotateArgs = (rawArgs) => {
2425
3144
  for (let i = 0; i < rawArgs.length; i += 1) {
2426
3145
  const arg = rawArgs[i];
2427
3146
  if (arg === "--session-id") {
2428
- const value = requireValue(rawArgs[i + 1], "--session-id");
3147
+ const value = requireValue2(rawArgs[i + 1], "--session-id");
2429
3148
  parsed.sessionId = value;
2430
3149
  i += 1;
2431
3150
  continue;
2432
3151
  }
2433
3152
  if (arg?.startsWith("--session-id=")) {
2434
- const value = requireValue(arg.split("=", 2)[1], "--session-id");
3153
+ const value = requireValue2(arg.split("=", 2)[1], "--session-id");
2435
3154
  parsed.sessionId = value;
2436
3155
  continue;
2437
3156
  }
2438
3157
  if (arg === "--url") {
2439
- const value = requireValue(rawArgs[i + 1], "--url");
3158
+ const value = requireValue2(rawArgs[i + 1], "--url");
2440
3159
  parsed.url = value;
2441
3160
  i += 1;
2442
3161
  continue;
2443
3162
  }
2444
3163
  if (arg?.startsWith("--url=")) {
2445
- const value = requireValue(arg.split("=", 2)[1], "--url");
3164
+ const value = requireValue2(arg.split("=", 2)[1], "--url");
2446
3165
  parsed.url = value;
2447
3166
  continue;
2448
3167
  }
2449
3168
  if (arg === "--screenshot-mode") {
2450
- const value = requireValue(rawArgs[i + 1], "--screenshot-mode");
3169
+ const value = requireValue2(rawArgs[i + 1], "--screenshot-mode");
2451
3170
  parsed.screenshotMode = requireScreenshotMode(value);
2452
3171
  i += 1;
2453
3172
  continue;
2454
3173
  }
2455
3174
  if (arg?.startsWith("--screenshot-mode=")) {
2456
- const value = requireValue(arg.split("=", 2)[1], "--screenshot-mode");
3175
+ const value = requireValue2(arg.split("=", 2)[1], "--screenshot-mode");
2457
3176
  parsed.screenshotMode = requireScreenshotMode(value);
2458
3177
  continue;
2459
3178
  }
2460
3179
  if (arg === "--transport") {
2461
- const value = requireValue(rawArgs[i + 1], "--transport");
3180
+ const value = requireValue2(rawArgs[i + 1], "--transport");
2462
3181
  parsed.transport = requireTransport(value);
2463
3182
  i += 1;
2464
3183
  continue;
2465
3184
  }
2466
3185
  if (arg?.startsWith("--transport=")) {
2467
- const value = requireValue(arg.split("=", 2)[1], "--transport");
3186
+ const value = requireValue2(arg.split("=", 2)[1], "--transport");
2468
3187
  parsed.transport = requireTransport(value);
2469
3188
  continue;
2470
3189
  }
2471
3190
  if (arg === "--target-id") {
2472
- const value = requireValue(rawArgs[i + 1], "--target-id");
3191
+ const value = requireValue2(rawArgs[i + 1], "--target-id");
2473
3192
  parsed.targetId = value;
2474
3193
  i += 1;
2475
3194
  continue;
2476
3195
  }
2477
3196
  if (arg?.startsWith("--target-id=")) {
2478
- const value = requireValue(arg.split("=", 2)[1], "--target-id");
3197
+ const value = requireValue2(arg.split("=", 2)[1], "--target-id");
2479
3198
  parsed.targetId = value;
2480
3199
  continue;
2481
3200
  }
2482
3201
  if (arg === "--tab-id") {
2483
- const value = requireValue(rawArgs[i + 1], "--tab-id");
3202
+ const value = requireValue2(rawArgs[i + 1], "--tab-id");
2484
3203
  parsed.tabId = parseNumberFlag(value, "--tab-id", { min: 1 });
2485
3204
  i += 1;
2486
3205
  continue;
2487
3206
  }
2488
3207
  if (arg?.startsWith("--tab-id=")) {
2489
- const value = requireValue(arg.split("=", 2)[1], "--tab-id");
3208
+ const value = requireValue2(arg.split("=", 2)[1], "--tab-id");
2490
3209
  parsed.tabId = parseNumberFlag(value, "--tab-id", { min: 1 });
2491
3210
  continue;
2492
3211
  }
@@ -2495,24 +3214,24 @@ var parseAnnotateArgs = (rawArgs) => {
2495
3214
  continue;
2496
3215
  }
2497
3216
  if (arg === "--context") {
2498
- const value = requireValue(rawArgs[i + 1], "--context");
3217
+ const value = requireValue2(rawArgs[i + 1], "--context");
2499
3218
  parsed.context = value;
2500
3219
  i += 1;
2501
3220
  continue;
2502
3221
  }
2503
3222
  if (arg?.startsWith("--context=")) {
2504
- const value = requireValue(arg.split("=", 2)[1], "--context");
3223
+ const value = requireValue2(arg.split("=", 2)[1], "--context");
2505
3224
  parsed.context = value;
2506
3225
  continue;
2507
3226
  }
2508
3227
  if (arg === "--timeout-ms") {
2509
- const value = requireValue(rawArgs[i + 1], "--timeout-ms");
3228
+ const value = requireValue2(rawArgs[i + 1], "--timeout-ms");
2510
3229
  parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
2511
3230
  i += 1;
2512
3231
  continue;
2513
3232
  }
2514
3233
  if (arg?.startsWith("--timeout-ms=")) {
2515
- const value = requireValue(arg.split("=", 2)[1], "--timeout-ms");
3234
+ const value = requireValue2(arg.split("=", 2)[1], "--timeout-ms");
2516
3235
  parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
2517
3236
  continue;
2518
3237
  }
@@ -2548,6 +3267,131 @@ async function runAnnotate(args) {
2548
3267
  }
2549
3268
  }
2550
3269
 
3270
+ // src/cli/commands/rpc.ts
3271
+ import { readFileSync as readFileSync5 } from "fs";
3272
+ var requireValue3 = (value, flag) => {
3273
+ if (!value) throw createUsageError(`Missing value for ${flag}`);
3274
+ return value;
3275
+ };
3276
+ var parseJsonObject = (raw, source) => {
3277
+ let parsed;
3278
+ try {
3279
+ parsed = JSON.parse(raw);
3280
+ } catch (error) {
3281
+ const message = error instanceof Error ? error.message : "Invalid JSON";
3282
+ throw createUsageError(`Invalid JSON from ${source}: ${message}`);
3283
+ }
3284
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
3285
+ throw createUsageError(`Invalid JSON from ${source}: expected object`);
3286
+ }
3287
+ return parsed;
3288
+ };
3289
+ var parseRpcArgs = (rawArgs) => {
3290
+ const parsed = {};
3291
+ for (let i = 0; i < rawArgs.length; i += 1) {
3292
+ const arg = rawArgs[i];
3293
+ if (arg === "--unsafe-internal") {
3294
+ parsed.unsafeInternal = true;
3295
+ continue;
3296
+ }
3297
+ if (arg === "--name") {
3298
+ parsed.name = requireValue3(rawArgs[i + 1], "--name");
3299
+ i += 1;
3300
+ continue;
3301
+ }
3302
+ if (arg?.startsWith("--name=")) {
3303
+ parsed.name = requireValue3(arg.split("=", 2)[1], "--name");
3304
+ continue;
3305
+ }
3306
+ if (arg === "--params") {
3307
+ parsed.params = requireValue3(rawArgs[i + 1], "--params");
3308
+ i += 1;
3309
+ continue;
3310
+ }
3311
+ if (arg?.startsWith("--params=")) {
3312
+ parsed.params = requireValue3(arg.split("=", 2)[1], "--params");
3313
+ continue;
3314
+ }
3315
+ if (arg === "--params-file") {
3316
+ parsed.paramsFile = requireValue3(rawArgs[i + 1], "--params-file");
3317
+ i += 1;
3318
+ continue;
3319
+ }
3320
+ if (arg?.startsWith("--params-file=")) {
3321
+ parsed.paramsFile = requireValue3(arg.split("=", 2)[1], "--params-file");
3322
+ continue;
3323
+ }
3324
+ if (arg === "--timeout-ms") {
3325
+ const value = requireValue3(rawArgs[i + 1], "--timeout-ms");
3326
+ parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
3327
+ i += 1;
3328
+ continue;
3329
+ }
3330
+ if (arg?.startsWith("--timeout-ms=")) {
3331
+ const value = requireValue3(arg.split("=", 2)[1], "--timeout-ms");
3332
+ parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
3333
+ continue;
3334
+ }
3335
+ }
3336
+ return parsed;
3337
+ };
3338
+ var resolveRpcParams = (rpcArgs) => {
3339
+ const hasParamsArg = typeof rpcArgs.params === "string";
3340
+ const hasParamsFile = typeof rpcArgs.paramsFile === "string";
3341
+ const inputCount = Number(hasParamsArg) + Number(hasParamsFile);
3342
+ if (inputCount > 1) {
3343
+ throw createUsageError("Provide only one params source: --params or --params-file.");
3344
+ }
3345
+ if (hasParamsArg) {
3346
+ return parseJsonObject(rpcArgs.params ?? "", "--params");
3347
+ }
3348
+ if (hasParamsFile) {
3349
+ let raw = "";
3350
+ try {
3351
+ raw = readFileSync5(rpcArgs.paramsFile ?? "", "utf8");
3352
+ } catch (error) {
3353
+ const message = error instanceof Error ? error.message : "Unable to read file";
3354
+ throw createUsageError(`Invalid --params-file: ${message}`);
3355
+ }
3356
+ if (!raw.trim()) {
3357
+ throw createUsageError("Invalid JSON from --params-file: empty input");
3358
+ }
3359
+ return parseJsonObject(raw, "--params-file");
3360
+ }
3361
+ return {};
3362
+ };
3363
+ async function runRpc(args) {
3364
+ const rpcArgs = parseRpcArgs(args.rawArgs);
3365
+ if (!rpcArgs.unsafeInternal) {
3366
+ throw createUsageError(
3367
+ "Missing --unsafe-internal. rpc is a power-user command that executes internal daemon commands and can mutate session state."
3368
+ );
3369
+ }
3370
+ if (!rpcArgs.name) {
3371
+ throw createUsageError("Missing --name");
3372
+ }
3373
+ const params = resolveRpcParams(rpcArgs);
3374
+ const client = new DaemonClient({ autoRenew: true });
3375
+ try {
3376
+ const result = await client.call(rpcArgs.name, params, { timeoutMs: rpcArgs.timeoutMs });
3377
+ if (args.outputFormat === "text") {
3378
+ const output = typeof result === "string" ? result : JSON.stringify(result, null, 2);
3379
+ return { success: true, message: output };
3380
+ }
3381
+ return {
3382
+ success: true,
3383
+ message: `RPC executed: ${rpcArgs.name}`,
3384
+ data: {
3385
+ name: rpcArgs.name,
3386
+ result
3387
+ }
3388
+ };
3389
+ } finally {
3390
+ await client.releaseBinding().catch(() => {
3391
+ });
3392
+ }
3393
+ }
3394
+
2551
3395
  // src/cli/commands/interact/click.ts
2552
3396
  function parseClickArgs(rawArgs) {
2553
3397
  const parsed = {};
@@ -3592,39 +4436,49 @@ async function runPerf(args) {
3592
4436
  }
3593
4437
 
3594
4438
  // src/cli/commands/devtools/screenshot.ts
4439
+ var requireValue4 = (value, flag) => {
4440
+ if (!value) throw createUsageError(`Missing value for ${flag}`);
4441
+ return value;
4442
+ };
3595
4443
  function parseScreenshotArgs(rawArgs) {
3596
4444
  const parsed = {};
3597
4445
  for (let i = 0; i < rawArgs.length; i += 1) {
3598
4446
  const arg = rawArgs[i];
3599
4447
  if (arg === "--session-id") {
3600
- const value = rawArgs[i + 1];
3601
- if (!value) throw createUsageError("Missing value for --session-id");
3602
- parsed.sessionId = value;
4448
+ parsed.sessionId = requireValue4(rawArgs[i + 1], "--session-id");
3603
4449
  i += 1;
3604
4450
  continue;
3605
4451
  }
3606
4452
  if (arg?.startsWith("--session-id=")) {
3607
- parsed.sessionId = arg.split("=", 2)[1];
4453
+ parsed.sessionId = requireValue4(arg.split("=", 2)[1], "--session-id");
3608
4454
  continue;
3609
4455
  }
3610
4456
  if (arg === "--path") {
3611
- const value = rawArgs[i + 1];
3612
- if (!value) throw createUsageError("Missing value for --path");
3613
- parsed.path = value;
4457
+ parsed.path = requireValue4(rawArgs[i + 1], "--path");
3614
4458
  i += 1;
3615
4459
  continue;
3616
4460
  }
3617
4461
  if (arg?.startsWith("--path=")) {
3618
- parsed.path = arg.split("=", 2)[1];
4462
+ parsed.path = requireValue4(arg.split("=", 2)[1], "--path");
4463
+ continue;
4464
+ }
4465
+ if (arg === "--timeout-ms") {
4466
+ parsed.timeoutMs = parseNumberFlag(requireValue4(rawArgs[i + 1], "--timeout-ms"), "--timeout-ms", { min: 1 });
4467
+ i += 1;
4468
+ continue;
4469
+ }
4470
+ if (arg?.startsWith("--timeout-ms=")) {
4471
+ parsed.timeoutMs = parseNumberFlag(requireValue4(arg.split("=", 2)[1], "--timeout-ms"), "--timeout-ms", { min: 1 });
3619
4472
  continue;
3620
4473
  }
3621
4474
  }
3622
4475
  return parsed;
3623
4476
  }
3624
4477
  async function runScreenshot(args) {
3625
- const { sessionId, path: path8 } = parseScreenshotArgs(args.rawArgs);
4478
+ const { sessionId, path: path8, timeoutMs } = parseScreenshotArgs(args.rawArgs);
3626
4479
  if (!sessionId) throw createUsageError("Missing --session-id");
3627
- const result = await callDaemon("page.screenshot", { sessionId, path: path8 });
4480
+ const params = { sessionId, path: path8 };
4481
+ const result = typeof timeoutMs === "number" ? await callDaemon("page.screenshot", params, { timeoutMs }) : await callDaemon("page.screenshot", params);
3628
4482
  return { success: true, message: "Screenshot captured.", data: result };
3629
4483
  }
3630
4484
 
@@ -3724,23 +4578,1062 @@ async function runNetworkPoll(args) {
3724
4578
  return { success: true, message: "Network events polled.", data: result };
3725
4579
  }
3726
4580
 
3727
- // src/cli/index.ts
3728
- var VERSION = "0.1.0";
3729
- async function promptInstallMode() {
3730
- if (!process.stdin.isTTY) {
3731
- console.log("Non-interactive mode detected. Using global install.");
3732
- return "global";
3733
- }
3734
- return new Promise((resolve4) => {
3735
- console.log("\nWhere would you like to install opendevbrowser?\n");
3736
- console.log(" 1. Global (~/.config/opencode/opencode.json)");
3737
- console.log(" 2. Local (./opencode.json in this project)\n");
3738
- process.stdout.write("Enter choice [1]: ");
3739
- process.stdin.setEncoding("utf8");
3740
- let resolved = false;
3741
- let timeoutId = null;
3742
- const cleanup = () => {
3743
- if (timeoutId !== null) {
4581
+ // src/cli/commands/devtools/debug-trace-snapshot.ts
4582
+ function parseDebugTraceSnapshotArgs(rawArgs) {
4583
+ const parsed = {};
4584
+ for (let index = 0; index < rawArgs.length; index += 1) {
4585
+ const arg = rawArgs[index];
4586
+ if (arg === "--session-id") {
4587
+ const value = rawArgs[index + 1];
4588
+ if (!value) throw createUsageError("Missing value for --session-id");
4589
+ parsed.sessionId = value;
4590
+ index += 1;
4591
+ continue;
4592
+ }
4593
+ if (arg?.startsWith("--session-id=")) {
4594
+ parsed.sessionId = arg.split("=", 2)[1];
4595
+ continue;
4596
+ }
4597
+ if (arg === "--since-console-seq") {
4598
+ const value = rawArgs[index + 1];
4599
+ if (!value) throw createUsageError("Missing value for --since-console-seq");
4600
+ parsed.sinceConsoleSeq = parseNumberFlag(value, "--since-console-seq", { min: 0 });
4601
+ index += 1;
4602
+ continue;
4603
+ }
4604
+ if (arg?.startsWith("--since-console-seq=")) {
4605
+ const value = arg.split("=", 2)[1];
4606
+ if (!value) throw createUsageError("Missing value for --since-console-seq");
4607
+ parsed.sinceConsoleSeq = parseNumberFlag(value, "--since-console-seq", { min: 0 });
4608
+ continue;
4609
+ }
4610
+ if (arg === "--since-network-seq") {
4611
+ const value = rawArgs[index + 1];
4612
+ if (!value) throw createUsageError("Missing value for --since-network-seq");
4613
+ parsed.sinceNetworkSeq = parseNumberFlag(value, "--since-network-seq", { min: 0 });
4614
+ index += 1;
4615
+ continue;
4616
+ }
4617
+ if (arg?.startsWith("--since-network-seq=")) {
4618
+ const value = arg.split("=", 2)[1];
4619
+ if (!value) throw createUsageError("Missing value for --since-network-seq");
4620
+ parsed.sinceNetworkSeq = parseNumberFlag(value, "--since-network-seq", { min: 0 });
4621
+ continue;
4622
+ }
4623
+ if (arg === "--since-exception-seq") {
4624
+ const value = rawArgs[index + 1];
4625
+ if (!value) throw createUsageError("Missing value for --since-exception-seq");
4626
+ parsed.sinceExceptionSeq = parseNumberFlag(value, "--since-exception-seq", { min: 0 });
4627
+ index += 1;
4628
+ continue;
4629
+ }
4630
+ if (arg?.startsWith("--since-exception-seq=")) {
4631
+ const value = arg.split("=", 2)[1];
4632
+ if (!value) throw createUsageError("Missing value for --since-exception-seq");
4633
+ parsed.sinceExceptionSeq = parseNumberFlag(value, "--since-exception-seq", { min: 0 });
4634
+ continue;
4635
+ }
4636
+ if (arg === "--max") {
4637
+ const value = rawArgs[index + 1];
4638
+ if (!value) throw createUsageError("Missing value for --max");
4639
+ parsed.max = parseNumberFlag(value, "--max", { min: 1 });
4640
+ index += 1;
4641
+ continue;
4642
+ }
4643
+ if (arg?.startsWith("--max=")) {
4644
+ const value = arg.split("=", 2)[1];
4645
+ if (!value) throw createUsageError("Missing value for --max");
4646
+ parsed.max = parseNumberFlag(value, "--max", { min: 1 });
4647
+ continue;
4648
+ }
4649
+ if (arg === "--request-id") {
4650
+ const value = rawArgs[index + 1];
4651
+ if (!value) throw createUsageError("Missing value for --request-id");
4652
+ parsed.requestId = value;
4653
+ index += 1;
4654
+ continue;
4655
+ }
4656
+ if (arg?.startsWith("--request-id=")) {
4657
+ const value = arg.split("=", 2)[1];
4658
+ if (!value) throw createUsageError("Missing value for --request-id");
4659
+ parsed.requestId = value;
4660
+ continue;
4661
+ }
4662
+ }
4663
+ return parsed;
4664
+ }
4665
+ async function runDebugTraceSnapshot(args) {
4666
+ const parsed = parseDebugTraceSnapshotArgs(args.rawArgs);
4667
+ if (!parsed.sessionId) {
4668
+ throw createUsageError("Missing --session-id");
4669
+ }
4670
+ const result = await callDaemon("devtools.debugTraceSnapshot", {
4671
+ sessionId: parsed.sessionId,
4672
+ sinceConsoleSeq: parsed.sinceConsoleSeq,
4673
+ sinceNetworkSeq: parsed.sinceNetworkSeq,
4674
+ sinceExceptionSeq: parsed.sinceExceptionSeq,
4675
+ max: parsed.max,
4676
+ requestId: parsed.requestId
4677
+ });
4678
+ return {
4679
+ success: true,
4680
+ message: "Debug trace snapshot captured.",
4681
+ data: result
4682
+ };
4683
+ }
4684
+
4685
+ // src/cli/commands/session/cookie-import.ts
4686
+ import { readFileSync as readFileSync6 } from "fs";
4687
+ var requireValue5 = (value, flag) => {
4688
+ if (!value) {
4689
+ throw createUsageError(`Missing value for ${flag}`);
4690
+ }
4691
+ return value;
4692
+ };
4693
+ var parseStrictValue = (value, flag) => {
4694
+ const normalized = value.trim().toLowerCase();
4695
+ if (normalized === "true") return true;
4696
+ if (normalized === "false") return false;
4697
+ throw createUsageError(`Invalid ${flag}: ${value}`);
4698
+ };
4699
+ var parseCookieImportArgs = (rawArgs) => {
4700
+ const parsed = {};
4701
+ for (let index = 0; index < rawArgs.length; index += 1) {
4702
+ const arg = rawArgs[index];
4703
+ if (arg === "--session-id") {
4704
+ parsed.sessionId = requireValue5(rawArgs[index + 1], "--session-id");
4705
+ index += 1;
4706
+ continue;
4707
+ }
4708
+ if (arg?.startsWith("--session-id=")) {
4709
+ parsed.sessionId = requireValue5(arg.split("=", 2)[1], "--session-id");
4710
+ continue;
4711
+ }
4712
+ if (arg === "--cookies") {
4713
+ parsed.cookies = requireValue5(rawArgs[index + 1], "--cookies");
4714
+ index += 1;
4715
+ continue;
4716
+ }
4717
+ if (arg?.startsWith("--cookies=")) {
4718
+ parsed.cookies = requireValue5(arg.split("=", 2)[1], "--cookies");
4719
+ continue;
4720
+ }
4721
+ if (arg === "--cookies-file") {
4722
+ parsed.cookiesFile = requireValue5(rawArgs[index + 1], "--cookies-file");
4723
+ index += 1;
4724
+ continue;
4725
+ }
4726
+ if (arg?.startsWith("--cookies-file=")) {
4727
+ parsed.cookiesFile = requireValue5(arg.split("=", 2)[1], "--cookies-file");
4728
+ continue;
4729
+ }
4730
+ if (arg === "--strict") {
4731
+ parsed.strict = true;
4732
+ continue;
4733
+ }
4734
+ if (arg?.startsWith("--strict=")) {
4735
+ parsed.strict = parseStrictValue(requireValue5(arg.split("=", 2)[1], "--strict"), "--strict");
4736
+ continue;
4737
+ }
4738
+ if (arg === "--request-id") {
4739
+ parsed.requestId = requireValue5(rawArgs[index + 1], "--request-id");
4740
+ index += 1;
4741
+ continue;
4742
+ }
4743
+ if (arg?.startsWith("--request-id=")) {
4744
+ parsed.requestId = requireValue5(arg.split("=", 2)[1], "--request-id");
4745
+ continue;
4746
+ }
4747
+ }
4748
+ return parsed;
4749
+ };
4750
+ var parseCookiesJson = (raw, source) => {
4751
+ let parsed;
4752
+ try {
4753
+ parsed = JSON.parse(raw);
4754
+ } catch (error) {
4755
+ const message = error instanceof Error ? error.message : "Invalid JSON";
4756
+ throw createUsageError(`Invalid JSON from ${source}: ${message}`);
4757
+ }
4758
+ if (!Array.isArray(parsed)) {
4759
+ throw createUsageError(`Invalid JSON from ${source}: expected array`);
4760
+ }
4761
+ const cookies = [];
4762
+ for (const entry of parsed) {
4763
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
4764
+ throw createUsageError(`Invalid JSON from ${source}: expected cookie object entries`);
4765
+ }
4766
+ const cookie = entry;
4767
+ if (typeof cookie.name !== "string" || typeof cookie.value !== "string") {
4768
+ throw createUsageError(`Invalid JSON from ${source}: each cookie requires string name and value`);
4769
+ }
4770
+ if (typeof cookie.sameSite !== "undefined" && cookie.sameSite !== "Strict" && cookie.sameSite !== "Lax" && cookie.sameSite !== "None") {
4771
+ throw createUsageError(`Invalid JSON from ${source}: sameSite must be Strict, Lax, or None`);
4772
+ }
4773
+ cookies.push({
4774
+ name: cookie.name,
4775
+ value: cookie.value,
4776
+ ...typeof cookie.url === "string" ? { url: cookie.url } : {},
4777
+ ...typeof cookie.domain === "string" ? { domain: cookie.domain } : {},
4778
+ ...typeof cookie.path === "string" ? { path: cookie.path } : {},
4779
+ ...typeof cookie.expires === "number" ? { expires: cookie.expires } : {},
4780
+ ...typeof cookie.httpOnly === "boolean" ? { httpOnly: cookie.httpOnly } : {},
4781
+ ...typeof cookie.secure === "boolean" ? { secure: cookie.secure } : {},
4782
+ ...cookie.sameSite ? { sameSite: cookie.sameSite } : {}
4783
+ });
4784
+ }
4785
+ return cookies;
4786
+ };
4787
+ var resolveCookies = (parsed) => {
4788
+ const hasInline = typeof parsed.cookies === "string";
4789
+ const hasFile = typeof parsed.cookiesFile === "string";
4790
+ if (!hasInline && !hasFile) {
4791
+ throw createUsageError("Missing --cookies or --cookies-file");
4792
+ }
4793
+ if (hasInline && hasFile) {
4794
+ throw createUsageError("Provide only one cookies source: --cookies or --cookies-file.");
4795
+ }
4796
+ if (hasInline) {
4797
+ return parseCookiesJson(parsed.cookies ?? "", "--cookies");
4798
+ }
4799
+ let raw = "";
4800
+ try {
4801
+ raw = readFileSync6(parsed.cookiesFile ?? "", "utf8");
4802
+ } catch (error) {
4803
+ const message = error instanceof Error ? error.message : "Unable to read file";
4804
+ throw createUsageError(`Invalid --cookies-file: ${message}`);
4805
+ }
4806
+ if (!raw.trim()) {
4807
+ throw createUsageError("Invalid JSON from --cookies-file: empty input");
4808
+ }
4809
+ return parseCookiesJson(raw, "--cookies-file");
4810
+ };
4811
+ async function runCookieImport(args) {
4812
+ const parsed = parseCookieImportArgs(args.rawArgs);
4813
+ if (!parsed.sessionId) {
4814
+ throw createUsageError("Missing --session-id");
4815
+ }
4816
+ const cookies = resolveCookies(parsed);
4817
+ const result = await callDaemon("session.cookieImport", {
4818
+ sessionId: parsed.sessionId,
4819
+ cookies,
4820
+ strict: parsed.strict ?? true,
4821
+ requestId: parsed.requestId
4822
+ });
4823
+ const imported = typeof result.imported === "number" ? result.imported : cookies.length;
4824
+ return {
4825
+ success: true,
4826
+ message: `Cookies imported: ${imported}`,
4827
+ data: result
4828
+ };
4829
+ }
4830
+
4831
+ // src/cli/commands/session/cookie-list.ts
4832
+ var requireValue6 = (value, flag) => {
4833
+ if (!value) {
4834
+ throw createUsageError(`Missing value for ${flag}`);
4835
+ }
4836
+ return value;
4837
+ };
4838
+ var normalizeCookieUrls = (values) => {
4839
+ const normalized = [];
4840
+ const seen = /* @__PURE__ */ new Set();
4841
+ for (const value of values) {
4842
+ const trimmed = value.trim();
4843
+ if (!trimmed) {
4844
+ continue;
4845
+ }
4846
+ let parsedUrl;
4847
+ try {
4848
+ parsedUrl = new URL(trimmed);
4849
+ } catch {
4850
+ throw createUsageError(`Invalid --url value: ${trimmed}`);
4851
+ }
4852
+ if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
4853
+ throw createUsageError(`Invalid --url protocol: ${trimmed}`);
4854
+ }
4855
+ const normalizedUrl = parsedUrl.toString();
4856
+ if (seen.has(normalizedUrl)) {
4857
+ continue;
4858
+ }
4859
+ seen.add(normalizedUrl);
4860
+ normalized.push(normalizedUrl);
4861
+ }
4862
+ return normalized;
4863
+ };
4864
+ var parseCookieListArgs = (rawArgs) => {
4865
+ const parsed = { urls: [] };
4866
+ for (let index = 0; index < rawArgs.length; index += 1) {
4867
+ const arg = rawArgs[index];
4868
+ if (arg === "--session-id") {
4869
+ parsed.sessionId = requireValue6(rawArgs[index + 1], "--session-id");
4870
+ index += 1;
4871
+ continue;
4872
+ }
4873
+ if (arg?.startsWith("--session-id=")) {
4874
+ parsed.sessionId = requireValue6(arg.split("=", 2)[1], "--session-id");
4875
+ continue;
4876
+ }
4877
+ if (arg === "--url") {
4878
+ const rawValue = requireValue6(rawArgs[index + 1], "--url");
4879
+ parsed.urls.push(...rawValue.split(","));
4880
+ index += 1;
4881
+ continue;
4882
+ }
4883
+ if (arg?.startsWith("--url=")) {
4884
+ parsed.urls.push(...requireValue6(arg.split("=", 2)[1], "--url").split(","));
4885
+ continue;
4886
+ }
4887
+ if (arg === "--request-id") {
4888
+ parsed.requestId = requireValue6(rawArgs[index + 1], "--request-id");
4889
+ index += 1;
4890
+ continue;
4891
+ }
4892
+ if (arg?.startsWith("--request-id=")) {
4893
+ parsed.requestId = requireValue6(arg.split("=", 2)[1], "--request-id");
4894
+ continue;
4895
+ }
4896
+ }
4897
+ parsed.urls = normalizeCookieUrls(parsed.urls);
4898
+ return parsed;
4899
+ };
4900
+ async function runCookieList(args) {
4901
+ const parsed = parseCookieListArgs(args.rawArgs);
4902
+ if (!parsed.sessionId) {
4903
+ throw createUsageError("Missing --session-id");
4904
+ }
4905
+ const result = await callDaemon("session.cookieList", {
4906
+ sessionId: parsed.sessionId,
4907
+ ...parsed.urls.length > 0 ? { urls: parsed.urls } : {},
4908
+ requestId: parsed.requestId
4909
+ });
4910
+ const count = typeof result.count === "number" ? result.count : Array.isArray(result.cookies) ? result.cookies.length : 0;
4911
+ return {
4912
+ success: true,
4913
+ message: `Cookies listed: ${count}`,
4914
+ data: result
4915
+ };
4916
+ }
4917
+
4918
+ // src/cli/commands/macro-resolve.ts
4919
+ var requireValue7 = (value, flag) => {
4920
+ if (!value) {
4921
+ throw createUsageError(`Missing value for ${flag}`);
4922
+ }
4923
+ return value;
4924
+ };
4925
+ var parseMacroResolveArgs = (rawArgs) => {
4926
+ const parsed = {};
4927
+ for (let index = 0; index < rawArgs.length; index += 1) {
4928
+ const arg = rawArgs[index];
4929
+ if (arg === "--expression") {
4930
+ parsed.expression = requireValue7(rawArgs[index + 1], "--expression");
4931
+ index += 1;
4932
+ continue;
4933
+ }
4934
+ if (arg?.startsWith("--expression=")) {
4935
+ parsed.expression = requireValue7(arg.split("=", 2)[1], "--expression");
4936
+ continue;
4937
+ }
4938
+ if (arg === "--default-provider") {
4939
+ parsed.defaultProvider = requireValue7(rawArgs[index + 1], "--default-provider");
4940
+ index += 1;
4941
+ continue;
4942
+ }
4943
+ if (arg?.startsWith("--default-provider=")) {
4944
+ parsed.defaultProvider = requireValue7(arg.split("=", 2)[1], "--default-provider");
4945
+ continue;
4946
+ }
4947
+ if (arg === "--include-catalog") {
4948
+ parsed.includeCatalog = true;
4949
+ continue;
4950
+ }
4951
+ if (arg === "--execute") {
4952
+ parsed.execute = true;
4953
+ continue;
4954
+ }
4955
+ if (arg === "--timeout-ms") {
4956
+ const value = requireValue7(rawArgs[index + 1], "--timeout-ms");
4957
+ parsed.timeoutMs = parseNumberFlag(value, "--timeout-ms", { min: 1 });
4958
+ index += 1;
4959
+ continue;
4960
+ }
4961
+ if (arg?.startsWith("--timeout-ms=")) {
4962
+ parsed.timeoutMs = parseNumberFlag(requireValue7(arg.split("=", 2)[1], "--timeout-ms"), "--timeout-ms", { min: 1 });
4963
+ continue;
4964
+ }
4965
+ }
4966
+ return parsed;
4967
+ };
4968
+ async function runMacroResolve(args) {
4969
+ const parsed = parseMacroResolveArgs(args.rawArgs);
4970
+ if (!parsed.expression) {
4971
+ throw createUsageError("Missing --expression");
4972
+ }
4973
+ const params = {
4974
+ expression: parsed.expression,
4975
+ defaultProvider: parsed.defaultProvider,
4976
+ includeCatalog: parsed.includeCatalog ?? false,
4977
+ execute: parsed.execute ?? false
4978
+ };
4979
+ const result = typeof parsed.timeoutMs === "number" ? await callDaemon("macro.resolve", params, { timeoutMs: parsed.timeoutMs }) : await callDaemon("macro.resolve", params);
4980
+ return {
4981
+ success: true,
4982
+ message: parsed.execute ? "Macro resolved and executed." : "Macro resolved.",
4983
+ data: result
4984
+ };
4985
+ }
4986
+
4987
+ // src/cli/commands/research.ts
4988
+ var SOURCE_VALUES = /* @__PURE__ */ new Set(["web", "community", "social", "shopping"]);
4989
+ var SOURCE_SELECTION_VALUES = /* @__PURE__ */ new Set(["auto", "web", "community", "social", "shopping", "all"]);
4990
+ var MODE_VALUES = /* @__PURE__ */ new Set(["compact", "json", "md", "context", "path"]);
4991
+ var COOKIE_POLICY_VALUES = /* @__PURE__ */ new Set(["off", "auto", "required"]);
4992
+ var requireValue8 = (rawArgs, index, flag) => {
4993
+ const value = rawArgs[index + 1];
4994
+ if (!value) {
4995
+ throw createUsageError(`Missing value for ${flag}`);
4996
+ }
4997
+ return value;
4998
+ };
4999
+ var parseBoolean = (value, flag) => {
5000
+ if (value === "true") return true;
5001
+ if (value === "false") return false;
5002
+ throw createUsageError(`Invalid ${flag}: ${value}`);
5003
+ };
5004
+ var parseSources = (raw) => {
5005
+ const parsed = raw.split(",").map((entry) => entry.trim().toLowerCase()).filter(Boolean);
5006
+ if (parsed.length === 0) {
5007
+ throw createUsageError("--sources requires at least one source");
5008
+ }
5009
+ const deduped = [...new Set(parsed)];
5010
+ for (const source of deduped) {
5011
+ if (!SOURCE_VALUES.has(source)) {
5012
+ throw createUsageError(`Invalid --sources value: ${source}`);
5013
+ }
5014
+ }
5015
+ return deduped;
5016
+ };
5017
+ var parseResearchRunArgs = (rawArgs) => {
5018
+ const parsed = {};
5019
+ for (let index = 0; index < rawArgs.length; index += 1) {
5020
+ const arg = rawArgs[index];
5021
+ if (arg === "--topic") {
5022
+ parsed.topic = requireValue8(rawArgs, index, "--topic");
5023
+ index += 1;
5024
+ continue;
5025
+ }
5026
+ if (arg?.startsWith("--topic=")) {
5027
+ parsed.topic = arg.split("=", 2)[1];
5028
+ continue;
5029
+ }
5030
+ if (arg === "--days") {
5031
+ parsed.days = parseNumberFlag(requireValue8(rawArgs, index, "--days"), "--days", { min: 1, max: 365 });
5032
+ index += 1;
5033
+ continue;
5034
+ }
5035
+ if (arg?.startsWith("--days=")) {
5036
+ parsed.days = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--days", { min: 1, max: 365 });
5037
+ continue;
5038
+ }
5039
+ if (arg === "--from") {
5040
+ parsed.from = requireValue8(rawArgs, index, "--from");
5041
+ index += 1;
5042
+ continue;
5043
+ }
5044
+ if (arg?.startsWith("--from=")) {
5045
+ parsed.from = arg.split("=", 2)[1];
5046
+ continue;
5047
+ }
5048
+ if (arg === "--to") {
5049
+ parsed.to = requireValue8(rawArgs, index, "--to");
5050
+ index += 1;
5051
+ continue;
5052
+ }
5053
+ if (arg?.startsWith("--to=")) {
5054
+ parsed.to = arg.split("=", 2)[1];
5055
+ continue;
5056
+ }
5057
+ if (arg === "--source-selection") {
5058
+ const value = requireValue8(rawArgs, index, "--source-selection").toLowerCase();
5059
+ if (!SOURCE_SELECTION_VALUES.has(value)) {
5060
+ throw createUsageError(`Invalid --source-selection: ${value}`);
5061
+ }
5062
+ parsed.sourceSelection = value;
5063
+ index += 1;
5064
+ continue;
5065
+ }
5066
+ if (arg?.startsWith("--source-selection=")) {
5067
+ const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
5068
+ if (!SOURCE_SELECTION_VALUES.has(value)) {
5069
+ throw createUsageError(`Invalid --source-selection: ${value}`);
5070
+ }
5071
+ parsed.sourceSelection = value;
5072
+ continue;
5073
+ }
5074
+ if (arg === "--sources") {
5075
+ parsed.sources = parseSources(requireValue8(rawArgs, index, "--sources"));
5076
+ index += 1;
5077
+ continue;
5078
+ }
5079
+ if (arg?.startsWith("--sources=")) {
5080
+ parsed.sources = parseSources(arg.split("=", 2)[1] ?? "");
5081
+ continue;
5082
+ }
5083
+ if (arg === "--mode") {
5084
+ const value = requireValue8(rawArgs, index, "--mode").toLowerCase();
5085
+ if (!MODE_VALUES.has(value)) {
5086
+ throw createUsageError(`Invalid --mode: ${value}`);
5087
+ }
5088
+ parsed.mode = value;
5089
+ index += 1;
5090
+ continue;
5091
+ }
5092
+ if (arg?.startsWith("--mode=")) {
5093
+ const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
5094
+ if (!MODE_VALUES.has(value)) {
5095
+ throw createUsageError(`Invalid --mode: ${value}`);
5096
+ }
5097
+ parsed.mode = value;
5098
+ continue;
5099
+ }
5100
+ if (arg === "--include-engagement") {
5101
+ parsed.includeEngagement = true;
5102
+ continue;
5103
+ }
5104
+ if (arg === "--limit-per-source") {
5105
+ parsed.limitPerSource = parseNumberFlag(requireValue8(rawArgs, index, "--limit-per-source"), "--limit-per-source", { min: 1, max: 100 });
5106
+ index += 1;
5107
+ continue;
5108
+ }
5109
+ if (arg?.startsWith("--limit-per-source=")) {
5110
+ parsed.limitPerSource = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--limit-per-source", { min: 1, max: 100 });
5111
+ continue;
5112
+ }
5113
+ if (arg === "--output-dir") {
5114
+ parsed.outputDir = requireValue8(rawArgs, index, "--output-dir");
5115
+ index += 1;
5116
+ continue;
5117
+ }
5118
+ if (arg?.startsWith("--output-dir=")) {
5119
+ parsed.outputDir = arg.split("=", 2)[1];
5120
+ continue;
5121
+ }
5122
+ if (arg === "--ttl-hours") {
5123
+ parsed.ttlHours = parseNumberFlag(requireValue8(rawArgs, index, "--ttl-hours"), "--ttl-hours", { min: 1, max: 168 });
5124
+ index += 1;
5125
+ continue;
5126
+ }
5127
+ if (arg?.startsWith("--ttl-hours=")) {
5128
+ parsed.ttlHours = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--ttl-hours", { min: 1, max: 168 });
5129
+ continue;
5130
+ }
5131
+ if (arg === "--use-cookies") {
5132
+ parsed.useCookies = true;
5133
+ continue;
5134
+ }
5135
+ if (arg?.startsWith("--use-cookies=")) {
5136
+ parsed.useCookies = parseBoolean(arg.split("=", 2)[1] ?? "", "--use-cookies");
5137
+ continue;
5138
+ }
5139
+ if (arg === "--cookie-policy-override" || arg === "--cookie-policy") {
5140
+ const value = requireValue8(rawArgs, index, arg).toLowerCase();
5141
+ if (!COOKIE_POLICY_VALUES.has(value)) {
5142
+ throw createUsageError(`Invalid ${arg}: ${value}`);
5143
+ }
5144
+ parsed.cookiePolicyOverride = value;
5145
+ index += 1;
5146
+ continue;
5147
+ }
5148
+ if (arg?.startsWith("--cookie-policy-override=") || arg?.startsWith("--cookie-policy=")) {
5149
+ const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
5150
+ if (!COOKIE_POLICY_VALUES.has(value)) {
5151
+ throw createUsageError(`Invalid --cookie-policy-override: ${value}`);
5152
+ }
5153
+ parsed.cookiePolicyOverride = value;
5154
+ continue;
5155
+ }
5156
+ }
5157
+ return parsed;
5158
+ };
5159
+ async function runResearchCommand(args) {
5160
+ const [subcommand, ...rest] = args.rawArgs;
5161
+ if (subcommand !== "run") {
5162
+ throw createUsageError("Usage: opendevbrowser research run --topic <value> [options]");
5163
+ }
5164
+ const parsed = parseResearchRunArgs(rest);
5165
+ if (!parsed.topic?.trim()) {
5166
+ throw createUsageError("Missing --topic");
5167
+ }
5168
+ const data = await callDaemon("research.run", {
5169
+ topic: parsed.topic,
5170
+ days: parsed.days,
5171
+ from: parsed.from,
5172
+ to: parsed.to,
5173
+ sourceSelection: parsed.sourceSelection,
5174
+ sources: parsed.sources,
5175
+ mode: parsed.mode ?? "compact",
5176
+ includeEngagement: parsed.includeEngagement ?? false,
5177
+ limitPerSource: parsed.limitPerSource,
5178
+ outputDir: parsed.outputDir,
5179
+ ttlHours: parsed.ttlHours,
5180
+ useCookies: parsed.useCookies,
5181
+ cookiePolicyOverride: parsed.cookiePolicyOverride
5182
+ });
5183
+ return {
5184
+ success: true,
5185
+ message: "Research workflow completed.",
5186
+ data
5187
+ };
5188
+ }
5189
+
5190
+ // src/cli/commands/shopping.ts
5191
+ var SORT_VALUES = /* @__PURE__ */ new Set(["best_deal", "lowest_price", "highest_rating", "fastest_shipping"]);
5192
+ var MODE_VALUES2 = /* @__PURE__ */ new Set(["compact", "json", "md", "context", "path"]);
5193
+ var COOKIE_POLICY_VALUES2 = /* @__PURE__ */ new Set(["off", "auto", "required"]);
5194
+ var requireValue9 = (rawArgs, index, flag) => {
5195
+ const value = rawArgs[index + 1];
5196
+ if (!value) {
5197
+ throw createUsageError(`Missing value for ${flag}`);
5198
+ }
5199
+ return value;
5200
+ };
5201
+ var parseBoolean2 = (value, flag) => {
5202
+ if (value === "true") return true;
5203
+ if (value === "false") return false;
5204
+ throw createUsageError(`Invalid ${flag}: ${value}`);
5205
+ };
5206
+ var parseProviders = (raw) => {
5207
+ const providers = raw.split(",").map((entry) => entry.trim()).filter(Boolean);
5208
+ if (providers.length === 0) {
5209
+ throw createUsageError("--providers requires at least one provider");
5210
+ }
5211
+ return [...new Set(providers)];
5212
+ };
5213
+ var parseShoppingRunArgs = (rawArgs) => {
5214
+ const parsed = {};
5215
+ for (let index = 0; index < rawArgs.length; index += 1) {
5216
+ const arg = rawArgs[index];
5217
+ if (arg === "--query") {
5218
+ parsed.query = requireValue9(rawArgs, index, "--query");
5219
+ index += 1;
5220
+ continue;
5221
+ }
5222
+ if (arg?.startsWith("--query=")) {
5223
+ parsed.query = arg.split("=", 2)[1];
5224
+ continue;
5225
+ }
5226
+ if (arg === "--providers") {
5227
+ parsed.providers = parseProviders(requireValue9(rawArgs, index, "--providers"));
5228
+ index += 1;
5229
+ continue;
5230
+ }
5231
+ if (arg?.startsWith("--providers=")) {
5232
+ parsed.providers = parseProviders(arg.split("=", 2)[1] ?? "");
5233
+ continue;
5234
+ }
5235
+ if (arg === "--budget") {
5236
+ parsed.budget = parseNumberFlag(requireValue9(rawArgs, index, "--budget"), "--budget", { min: 1, integer: false });
5237
+ index += 1;
5238
+ continue;
5239
+ }
5240
+ if (arg?.startsWith("--budget=")) {
5241
+ parsed.budget = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--budget", { min: 1, integer: false });
5242
+ continue;
5243
+ }
5244
+ if (arg === "--region") {
5245
+ parsed.region = requireValue9(rawArgs, index, "--region");
5246
+ index += 1;
5247
+ continue;
5248
+ }
5249
+ if (arg?.startsWith("--region=")) {
5250
+ parsed.region = arg.split("=", 2)[1];
5251
+ continue;
5252
+ }
5253
+ if (arg === "--sort") {
5254
+ const value = requireValue9(rawArgs, index, "--sort").toLowerCase();
5255
+ if (!SORT_VALUES.has(value)) {
5256
+ throw createUsageError(`Invalid --sort: ${value}`);
5257
+ }
5258
+ parsed.sort = value;
5259
+ index += 1;
5260
+ continue;
5261
+ }
5262
+ if (arg?.startsWith("--sort=")) {
5263
+ const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
5264
+ if (!SORT_VALUES.has(value)) {
5265
+ throw createUsageError(`Invalid --sort: ${value}`);
5266
+ }
5267
+ parsed.sort = value;
5268
+ continue;
5269
+ }
5270
+ if (arg === "--mode") {
5271
+ const value = requireValue9(rawArgs, index, "--mode").toLowerCase();
5272
+ if (!MODE_VALUES2.has(value)) {
5273
+ throw createUsageError(`Invalid --mode: ${value}`);
5274
+ }
5275
+ parsed.mode = value;
5276
+ index += 1;
5277
+ continue;
5278
+ }
5279
+ if (arg?.startsWith("--mode=")) {
5280
+ const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
5281
+ if (!MODE_VALUES2.has(value)) {
5282
+ throw createUsageError(`Invalid --mode: ${value}`);
5283
+ }
5284
+ parsed.mode = value;
5285
+ continue;
5286
+ }
5287
+ if (arg === "--timeout-ms") {
5288
+ parsed.timeoutMs = parseNumberFlag(requireValue9(rawArgs, index, "--timeout-ms"), "--timeout-ms", { min: 1 });
5289
+ index += 1;
5290
+ continue;
5291
+ }
5292
+ if (arg?.startsWith("--timeout-ms=")) {
5293
+ parsed.timeoutMs = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--timeout-ms", { min: 1 });
5294
+ continue;
5295
+ }
5296
+ if (arg === "--output-dir") {
5297
+ parsed.outputDir = requireValue9(rawArgs, index, "--output-dir");
5298
+ index += 1;
5299
+ continue;
5300
+ }
5301
+ if (arg?.startsWith("--output-dir=")) {
5302
+ parsed.outputDir = arg.split("=", 2)[1];
5303
+ continue;
5304
+ }
5305
+ if (arg === "--ttl-hours") {
5306
+ parsed.ttlHours = parseNumberFlag(requireValue9(rawArgs, index, "--ttl-hours"), "--ttl-hours", { min: 1, max: 168 });
5307
+ index += 1;
5308
+ continue;
5309
+ }
5310
+ if (arg?.startsWith("--ttl-hours=")) {
5311
+ parsed.ttlHours = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--ttl-hours", { min: 1, max: 168 });
5312
+ continue;
5313
+ }
5314
+ if (arg === "--use-cookies") {
5315
+ parsed.useCookies = true;
5316
+ continue;
5317
+ }
5318
+ if (arg?.startsWith("--use-cookies=")) {
5319
+ parsed.useCookies = parseBoolean2(arg.split("=", 2)[1] ?? "", "--use-cookies");
5320
+ continue;
5321
+ }
5322
+ if (arg === "--cookie-policy-override" || arg === "--cookie-policy") {
5323
+ const value = requireValue9(rawArgs, index, arg).toLowerCase();
5324
+ if (!COOKIE_POLICY_VALUES2.has(value)) {
5325
+ throw createUsageError(`Invalid ${arg}: ${value}`);
5326
+ }
5327
+ parsed.cookiePolicyOverride = value;
5328
+ index += 1;
5329
+ continue;
5330
+ }
5331
+ if (arg?.startsWith("--cookie-policy-override=") || arg?.startsWith("--cookie-policy=")) {
5332
+ const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
5333
+ if (!COOKIE_POLICY_VALUES2.has(value)) {
5334
+ throw createUsageError(`Invalid --cookie-policy-override: ${value}`);
5335
+ }
5336
+ parsed.cookiePolicyOverride = value;
5337
+ continue;
5338
+ }
5339
+ }
5340
+ return parsed;
5341
+ };
5342
+ async function runShoppingCommand(args) {
5343
+ const [subcommand, ...rest] = args.rawArgs;
5344
+ if (subcommand !== "run") {
5345
+ throw createUsageError("Usage: opendevbrowser shopping run --query <value> [options]");
5346
+ }
5347
+ const parsed = parseShoppingRunArgs(rest);
5348
+ if (!parsed.query?.trim()) {
5349
+ throw createUsageError("Missing --query");
5350
+ }
5351
+ const payload = {
5352
+ query: parsed.query,
5353
+ providers: parsed.providers,
5354
+ budget: parsed.budget,
5355
+ region: parsed.region,
5356
+ sort: parsed.sort,
5357
+ mode: parsed.mode ?? "compact",
5358
+ ...typeof parsed.timeoutMs === "number" ? { timeoutMs: parsed.timeoutMs } : {},
5359
+ outputDir: parsed.outputDir,
5360
+ ttlHours: parsed.ttlHours,
5361
+ useCookies: parsed.useCookies,
5362
+ cookiePolicyOverride: parsed.cookiePolicyOverride
5363
+ };
5364
+ const data = typeof parsed.timeoutMs === "number" ? await callDaemon("shopping.run", payload, { timeoutMs: parsed.timeoutMs }) : await callDaemon("shopping.run", payload);
5365
+ return {
5366
+ success: true,
5367
+ message: "Shopping workflow completed.",
5368
+ data
5369
+ };
5370
+ }
5371
+
5372
+ // src/cli/commands/product-video.ts
5373
+ var requireValue10 = (rawArgs, index, flag) => {
5374
+ const value = rawArgs[index + 1];
5375
+ if (!value) {
5376
+ throw createUsageError(`Missing value for ${flag}`);
5377
+ }
5378
+ return value;
5379
+ };
5380
+ var parseBoolean3 = (value, flag) => {
5381
+ if (value === "true") return true;
5382
+ if (value === "false") return false;
5383
+ throw createUsageError(`Invalid ${flag}: ${value}`);
5384
+ };
5385
+ var COOKIE_POLICY_VALUES3 = /* @__PURE__ */ new Set(["off", "auto", "required"]);
5386
+ var parseProductVideoArgs = (rawArgs) => {
5387
+ const parsed = {};
5388
+ for (let index = 0; index < rawArgs.length; index += 1) {
5389
+ const arg = rawArgs[index];
5390
+ if (arg === "--product-url") {
5391
+ parsed.productUrl = requireValue10(rawArgs, index, "--product-url");
5392
+ index += 1;
5393
+ continue;
5394
+ }
5395
+ if (arg?.startsWith("--product-url=")) {
5396
+ parsed.productUrl = arg.split("=", 2)[1];
5397
+ continue;
5398
+ }
5399
+ if (arg === "--product-name") {
5400
+ parsed.productName = requireValue10(rawArgs, index, "--product-name");
5401
+ index += 1;
5402
+ continue;
5403
+ }
5404
+ if (arg?.startsWith("--product-name=")) {
5405
+ parsed.productName = arg.split("=", 2)[1];
5406
+ continue;
5407
+ }
5408
+ if (arg === "--provider-hint") {
5409
+ parsed.providerHint = requireValue10(rawArgs, index, "--provider-hint");
5410
+ index += 1;
5411
+ continue;
5412
+ }
5413
+ if (arg?.startsWith("--provider-hint=")) {
5414
+ parsed.providerHint = arg.split("=", 2)[1];
5415
+ continue;
5416
+ }
5417
+ if (arg === "--include-screenshots") {
5418
+ parsed.includeScreenshots = true;
5419
+ continue;
5420
+ }
5421
+ if (arg?.startsWith("--include-screenshots=")) {
5422
+ parsed.includeScreenshots = parseBoolean3(arg.split("=", 2)[1] ?? "", "--include-screenshots");
5423
+ continue;
5424
+ }
5425
+ if (arg === "--include-all-images") {
5426
+ parsed.includeAllImages = true;
5427
+ continue;
5428
+ }
5429
+ if (arg?.startsWith("--include-all-images=")) {
5430
+ parsed.includeAllImages = parseBoolean3(arg.split("=", 2)[1] ?? "", "--include-all-images");
5431
+ continue;
5432
+ }
5433
+ if (arg === "--include-copy") {
5434
+ parsed.includeCopy = true;
5435
+ continue;
5436
+ }
5437
+ if (arg?.startsWith("--include-copy=")) {
5438
+ parsed.includeCopy = parseBoolean3(arg.split("=", 2)[1] ?? "", "--include-copy");
5439
+ continue;
5440
+ }
5441
+ if (arg === "--output-dir") {
5442
+ parsed.outputDir = requireValue10(rawArgs, index, "--output-dir");
5443
+ index += 1;
5444
+ continue;
5445
+ }
5446
+ if (arg?.startsWith("--output-dir=")) {
5447
+ parsed.outputDir = arg.split("=", 2)[1];
5448
+ continue;
5449
+ }
5450
+ if (arg === "--ttl-hours") {
5451
+ parsed.ttlHours = parseNumberFlag(requireValue10(rawArgs, index, "--ttl-hours"), "--ttl-hours", { min: 1, max: 168 });
5452
+ index += 1;
5453
+ continue;
5454
+ }
5455
+ if (arg?.startsWith("--ttl-hours=")) {
5456
+ parsed.ttlHours = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--ttl-hours", { min: 1, max: 168 });
5457
+ continue;
5458
+ }
5459
+ if (arg === "--timeout-ms") {
5460
+ parsed.timeoutMs = parseNumberFlag(requireValue10(rawArgs, index, "--timeout-ms"), "--timeout-ms", { min: 1 });
5461
+ index += 1;
5462
+ continue;
5463
+ }
5464
+ if (arg?.startsWith("--timeout-ms=")) {
5465
+ parsed.timeoutMs = parseNumberFlag(arg.split("=", 2)[1] ?? "", "--timeout-ms", { min: 1 });
5466
+ continue;
5467
+ }
5468
+ if (arg === "--use-cookies") {
5469
+ parsed.useCookies = true;
5470
+ continue;
5471
+ }
5472
+ if (arg?.startsWith("--use-cookies=")) {
5473
+ parsed.useCookies = parseBoolean3(arg.split("=", 2)[1] ?? "", "--use-cookies");
5474
+ continue;
5475
+ }
5476
+ if (arg === "--cookie-policy-override" || arg === "--cookie-policy") {
5477
+ const value = requireValue10(rawArgs, index, arg).toLowerCase();
5478
+ if (!COOKIE_POLICY_VALUES3.has(value)) {
5479
+ throw createUsageError(`Invalid ${arg}: ${value}`);
5480
+ }
5481
+ parsed.cookiePolicyOverride = value;
5482
+ index += 1;
5483
+ continue;
5484
+ }
5485
+ if (arg?.startsWith("--cookie-policy-override=") || arg?.startsWith("--cookie-policy=")) {
5486
+ const value = (arg.split("=", 2)[1] ?? "").toLowerCase();
5487
+ if (!COOKIE_POLICY_VALUES3.has(value)) {
5488
+ throw createUsageError(`Invalid --cookie-policy-override: ${value}`);
5489
+ }
5490
+ parsed.cookiePolicyOverride = value;
5491
+ continue;
5492
+ }
5493
+ }
5494
+ return parsed;
5495
+ };
5496
+ async function runProductVideoCommand(args) {
5497
+ const [subcommand, ...rest] = args.rawArgs;
5498
+ if (subcommand !== "run") {
5499
+ throw createUsageError("Usage: opendevbrowser product-video run --product-url <url> | --product-name <name>");
5500
+ }
5501
+ const parsed = parseProductVideoArgs(rest);
5502
+ if (!parsed.productUrl && !parsed.productName) {
5503
+ throw createUsageError("Missing --product-url or --product-name");
5504
+ }
5505
+ const timeoutMs = parsed.timeoutMs ?? 12e4;
5506
+ const data = await callDaemon("product.video.run", {
5507
+ product_url: parsed.productUrl,
5508
+ product_name: parsed.productName,
5509
+ provider_hint: parsed.providerHint,
5510
+ include_screenshots: parsed.includeScreenshots,
5511
+ include_all_images: parsed.includeAllImages,
5512
+ include_copy: parsed.includeCopy,
5513
+ output_dir: parsed.outputDir,
5514
+ ttl_hours: parsed.ttlHours,
5515
+ useCookies: parsed.useCookies,
5516
+ cookiePolicyOverride: parsed.cookiePolicyOverride
5517
+ }, { timeoutMs });
5518
+ return {
5519
+ success: true,
5520
+ message: "Product video asset workflow completed.",
5521
+ data
5522
+ };
5523
+ }
5524
+
5525
+ // package.json
5526
+ var package_default = {
5527
+ name: "opendevbrowser",
5528
+ version: "0.0.16",
5529
+ description: "OpenCode plugin for browser automation via CDP with snapshot-refs-actions workflow",
5530
+ type: "module",
5531
+ main: "dist/index.js",
5532
+ types: "dist/index.d.ts",
5533
+ bin: {
5534
+ opendevbrowser: "dist/cli/index.js"
5535
+ },
5536
+ files: [
5537
+ "dist",
5538
+ "skills",
5539
+ "scripts/native",
5540
+ "extension/manifest.json",
5541
+ "extension/popup.html",
5542
+ "extension/dist",
5543
+ "extension/icons"
5544
+ ],
5545
+ keywords: [
5546
+ "opencode",
5547
+ "plugin",
5548
+ "browser",
5549
+ "automation",
5550
+ "cdp",
5551
+ "playwright",
5552
+ "testing",
5553
+ "web-scraping",
5554
+ "chrome"
5555
+ ],
5556
+ license: "MIT",
5557
+ repository: {
5558
+ type: "git",
5559
+ url: "git+https://github.com/freshtechbro/opendevbrowser.git"
5560
+ },
5561
+ engines: {
5562
+ node: ">=18"
5563
+ },
5564
+ scripts: {
5565
+ build: `tsup src/index.ts src/cli/index.ts --format esm --clean --sourcemap && tsc --emitDeclarationOnly --declaration --declarationMap -p tsconfig.json && node --input-type=module -e "import { copyFileSync, existsSync } from 'node:fs';
5566
+ import { resolve } from 'node:path';
5567
+ const dist = resolve('dist');
5568
+ const pairs = [
5569
+ ['index.js', 'opendevbrowser.js'],
5570
+ ['index.js.map', 'opendevbrowser.js.map'],
5571
+ ['index.d.ts', 'opendevbrowser.d.ts'],
5572
+ ['index.d.ts.map', 'opendevbrowser.d.ts.map'],
5573
+ ];
5574
+ for (const [src, dst] of pairs) {
5575
+ const from = resolve(dist, src);
5576
+ const to = resolve(dist, dst);
5577
+ if (existsSync(from)) copyFileSync(from, to);
5578
+ }"`,
5579
+ dev: "tsup src/index.ts src/cli/index.ts --format esm --dts --watch",
5580
+ lint: 'eslint "src/**/*.ts" "tests/**/*.ts"',
5581
+ typecheck: "tsc --noEmit -p tsconfig.json",
5582
+ test: "vitest run --coverage",
5583
+ "test:release-gate": "node scripts/release-gate-test-groups.mjs",
5584
+ "test:release-gate:g1": "node scripts/release-gate-test-groups.mjs --group 1",
5585
+ "test:release-gate:g2": "node scripts/release-gate-test-groups.mjs --group 2",
5586
+ "test:release-gate:g3": "node scripts/release-gate-test-groups.mjs --group 3",
5587
+ "test:release-gate:g4": "node scripts/release-gate-test-groups.mjs --group 4",
5588
+ "test:release-gate:g5": "node scripts/release-gate-test-groups.mjs --group 5",
5589
+ "extension:sync": "node scripts/sync-extension-version.mjs",
5590
+ "extension:build": "npm run extension:sync && tsc -p extension/tsconfig.json && node scripts/copy-extension-assets.mjs",
5591
+ "extension:pack": "cd extension && zip -r ../opendevbrowser-extension.zip manifest.json popup.html dist/ icons/",
5592
+ "extension:store": "node scripts/chrome-store-publish.mjs",
5593
+ "version:check": "node scripts/verify-versions.mjs",
5594
+ prepack: "npm run version:check && npm run build && npm run extension:build"
5595
+ },
5596
+ dependencies: {
5597
+ "@opencode-ai/plugin": "^1.2.11",
5598
+ "@puppeteer/browsers": "^2.13.0",
5599
+ "async-mutex": "^0.5.0",
5600
+ "jsonc-parser": "^3.2.0",
5601
+ "playwright-core": "^1.58.2",
5602
+ ws: "^8.19.0",
5603
+ zod: "^3.25.76"
5604
+ },
5605
+ devDependencies: {
5606
+ "@types/chrome": "^0.1.37",
5607
+ "@types/node": "^20.19.35",
5608
+ "@types/ws": "^8.18.1",
5609
+ "@typescript-eslint/eslint-plugin": "^8.56.1",
5610
+ "@typescript-eslint/parser": "^8.56.1",
5611
+ "@vitest/coverage-v8": "^4.0.18",
5612
+ eslint: "^9.39.3",
5613
+ "happy-dom": "^20.7.0",
5614
+ tsup: "^8.5.1",
5615
+ typescript: "^5.9.3",
5616
+ vitest: "^4.0.18"
5617
+ }
5618
+ };
5619
+
5620
+ // src/cli/index.ts
5621
+ var VERSION = typeof package_default.version === "string" ? package_default.version : "0.0.0";
5622
+ async function promptInstallMode() {
5623
+ if (!process.stdin.isTTY) {
5624
+ console.log("Non-interactive mode detected. Using global install.");
5625
+ return "global";
5626
+ }
5627
+ return new Promise((resolve6) => {
5628
+ console.log("\nWhere would you like to install opendevbrowser?\n");
5629
+ console.log(" 1. Global (~/.config/opencode/opencode.json)");
5630
+ console.log(" 2. Local (./opencode.json in this project)\n");
5631
+ process.stdout.write("Enter choice [1]: ");
5632
+ process.stdin.setEncoding("utf8");
5633
+ let resolved = false;
5634
+ let timeoutId = null;
5635
+ const cleanup = () => {
5636
+ if (timeoutId !== null) {
3744
5637
  clearTimeout(timeoutId);
3745
5638
  timeoutId = null;
3746
5639
  }
@@ -3751,23 +5644,23 @@ async function promptInstallMode() {
3751
5644
  resolved = true;
3752
5645
  const input = data.toString().trim();
3753
5646
  if (input === "2") {
3754
- resolve4("local");
5647
+ resolve6("local");
3755
5648
  } else {
3756
- resolve4("global");
5649
+ resolve6("global");
3757
5650
  }
3758
5651
  });
3759
5652
  process.stdin.once("close", () => {
3760
5653
  cleanup();
3761
5654
  if (resolved) return;
3762
5655
  resolved = true;
3763
- resolve4("global");
5656
+ resolve6("global");
3764
5657
  });
3765
5658
  timeoutId = setTimeout(() => {
3766
5659
  timeoutId = null;
3767
5660
  if (resolved) return;
3768
5661
  resolved = true;
3769
5662
  console.log("\nTimeout - using global install.");
3770
- resolve4("global");
5663
+ resolve6("global");
3771
5664
  }, 3e4);
3772
5665
  });
3773
5666
  }
@@ -3787,7 +5680,7 @@ async function promptUninstallMode() {
3787
5680
  console.log("Plugin found in both global and local configs. Use --global or --local flag.");
3788
5681
  return null;
3789
5682
  }
3790
- return new Promise((resolve4) => {
5683
+ return new Promise((resolve6) => {
3791
5684
  console.log("\nopendevbrowser is installed in multiple locations:\n");
3792
5685
  console.log(" 1. Global (~/.config/opencode/opencode.json)");
3793
5686
  console.log(" 2. Local (./opencode.json)");
@@ -3797,15 +5690,15 @@ async function promptUninstallMode() {
3797
5690
  process.stdin.once("data", (data) => {
3798
5691
  const input = data.toString().trim();
3799
5692
  if (input === "1") {
3800
- resolve4("global");
5693
+ resolve6("global");
3801
5694
  } else if (input === "2") {
3802
- resolve4("local");
5695
+ resolve6("local");
3803
5696
  } else {
3804
- resolve4(null);
5697
+ resolve6(null);
3805
5698
  }
3806
5699
  });
3807
5700
  process.stdin.once("close", () => {
3808
- resolve4(null);
5701
+ resolve6(null);
3809
5702
  });
3810
5703
  });
3811
5704
  }
@@ -4046,6 +5939,11 @@ async function main() {
4046
5939
  description: "Request interactive annotations (extension relay)",
4047
5940
  run: async () => runAnnotate(args)
4048
5941
  });
5942
+ registerCommand({
5943
+ name: "rpc",
5944
+ description: "Execute an internal daemon RPC command (power-user)",
5945
+ run: async () => runRpc(args)
5946
+ });
4049
5947
  registerCommand({
4050
5948
  name: "click",
4051
5949
  description: "Click an element by ref",
@@ -4191,6 +6089,46 @@ async function main() {
4191
6089
  description: "Poll network events",
4192
6090
  run: async () => runNetworkPoll(args)
4193
6091
  });
6092
+ registerCommand({
6093
+ name: "debug-trace-snapshot",
6094
+ description: "Capture page + console + network + exception diagnostics",
6095
+ run: async () => runDebugTraceSnapshot(args)
6096
+ });
6097
+ registerCommand({
6098
+ name: "cookie-import",
6099
+ description: "Import validated cookies into a session",
6100
+ run: async () => runCookieImport(args)
6101
+ });
6102
+ registerCommand({
6103
+ name: "cookie-list",
6104
+ description: "List cookies for a session (optionally filtered by URL)",
6105
+ run: async () => runCookieList(args)
6106
+ });
6107
+ registerCommand({
6108
+ name: "macro-resolve",
6109
+ description: "Resolve or execute a macro expression via provider actions",
6110
+ run: async () => runMacroResolve(args)
6111
+ });
6112
+ registerCommand({
6113
+ name: "research",
6114
+ description: "Run research workflows",
6115
+ run: async () => runResearchCommand(args)
6116
+ });
6117
+ registerCommand({
6118
+ name: "shopping",
6119
+ description: "Run shopping workflows",
6120
+ run: async () => runShoppingCommand(args)
6121
+ });
6122
+ registerCommand({
6123
+ name: "product-video",
6124
+ description: "Run product presentation asset workflows",
6125
+ run: async () => runProductVideoCommand(args)
6126
+ });
6127
+ registerCommand({
6128
+ name: "artifacts",
6129
+ description: "Manage workflow artifact lifecycle",
6130
+ run: async () => runArtifactsCommand(args)
6131
+ });
4194
6132
  const command = getCommand(args.command);
4195
6133
  if (!command) {
4196
6134
  throw new Error(`Unknown command: ${args.command}`);