@agentrhq/webcmd 0.1.1 → 0.1.2

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 (415) hide show
  1. package/README.md +317 -24
  2. package/dist/src/adapter-shadow.d.ts +11 -0
  3. package/dist/src/adapter-shadow.js +72 -0
  4. package/dist/src/adapter-shadow.test.d.ts +1 -0
  5. package/dist/src/adapter-shadow.test.js +49 -0
  6. package/dist/src/adapter-source.d.ts +11 -0
  7. package/dist/src/adapter-source.js +24 -0
  8. package/dist/src/adapter-source.test.d.ts +1 -0
  9. package/dist/src/adapter-source.test.js +29 -0
  10. package/dist/src/brand.d.ts +9 -0
  11. package/dist/src/brand.js +9 -0
  12. package/dist/src/brand.test.d.ts +1 -0
  13. package/dist/src/brand.test.js +15 -0
  14. package/dist/src/browser/analyze.d.ts +118 -0
  15. package/dist/src/browser/analyze.js +405 -0
  16. package/dist/src/browser/analyze.test.d.ts +1 -0
  17. package/dist/src/browser/analyze.test.js +209 -0
  18. package/dist/src/browser/article-extract.d.ts +57 -0
  19. package/dist/src/browser/article-extract.e2e.test.d.ts +1 -0
  20. package/dist/src/browser/article-extract.e2e.test.js +105 -0
  21. package/dist/src/browser/article-extract.js +169 -0
  22. package/dist/src/browser/article-extract.test.d.ts +1 -0
  23. package/dist/src/browser/article-extract.test.js +94 -0
  24. package/dist/src/browser/ax-snapshot.d.ts +37 -0
  25. package/dist/src/browser/ax-snapshot.js +217 -0
  26. package/dist/src/browser/ax-snapshot.test.d.ts +1 -0
  27. package/dist/src/browser/ax-snapshot.test.js +91 -0
  28. package/dist/src/browser/base-page.d.ts +151 -0
  29. package/dist/src/browser/base-page.js +1060 -0
  30. package/dist/src/browser/base-page.test.d.ts +1 -0
  31. package/dist/src/browser/base-page.test.js +803 -0
  32. package/dist/src/browser/bridge-readiness.d.ts +14 -0
  33. package/dist/src/browser/bridge-readiness.js +24 -0
  34. package/dist/src/browser/bridge-readiness.test.d.ts +1 -0
  35. package/dist/src/browser/bridge-readiness.test.js +58 -0
  36. package/dist/src/browser/bridge.d.ts +26 -0
  37. package/dist/src/browser/bridge.js +58 -0
  38. package/dist/src/browser/cdp-click-fixture.test.d.ts +1 -0
  39. package/dist/src/browser/cdp-click-fixture.test.js +87 -0
  40. package/dist/src/browser/cdp.d.ts +46 -0
  41. package/dist/src/browser/cdp.js +536 -0
  42. package/dist/src/browser/cdp.test.d.ts +1 -0
  43. package/dist/src/browser/cdp.test.js +79 -0
  44. package/dist/src/browser/compound.d.ts +59 -0
  45. package/dist/src/browser/compound.js +112 -0
  46. package/dist/src/browser/compound.test.d.ts +1 -0
  47. package/dist/src/browser/compound.test.js +175 -0
  48. package/dist/src/browser/config.d.ts +2 -0
  49. package/dist/src/browser/config.js +14 -0
  50. package/dist/src/browser/daemon-client.d.ts +32 -0
  51. package/dist/src/browser/daemon-client.js +135 -0
  52. package/dist/src/browser/daemon-client.test.d.ts +1 -0
  53. package/dist/src/browser/daemon-client.test.js +326 -0
  54. package/dist/src/browser/daemon-lifecycle.d.ts +37 -0
  55. package/dist/src/browser/daemon-lifecycle.js +147 -0
  56. package/dist/src/browser/daemon-transport.d.ts +54 -0
  57. package/dist/src/browser/daemon-transport.js +68 -0
  58. package/dist/src/browser/daemon-version.d.ts +4 -0
  59. package/dist/src/browser/daemon-version.js +12 -0
  60. package/dist/src/browser/dom-helpers.d.ts +41 -0
  61. package/dist/src/browser/dom-helpers.js +239 -0
  62. package/dist/src/browser/dom-helpers.test.d.ts +1 -0
  63. package/dist/src/browser/dom-helpers.test.js +106 -0
  64. package/dist/src/browser/dom-snapshot.d.ts +93 -0
  65. package/dist/src/browser/dom-snapshot.js +894 -0
  66. package/dist/src/browser/dom-snapshot.test.d.ts +11 -0
  67. package/dist/src/browser/dom-snapshot.test.js +313 -0
  68. package/dist/src/browser/errors.d.ts +38 -0
  69. package/dist/src/browser/errors.js +79 -0
  70. package/dist/src/browser/errors.test.d.ts +1 -0
  71. package/dist/src/browser/errors.test.js +60 -0
  72. package/dist/src/browser/extract.d.ts +69 -0
  73. package/dist/src/browser/extract.js +132 -0
  74. package/dist/src/browser/extract.test.d.ts +1 -0
  75. package/dist/src/browser/extract.test.js +129 -0
  76. package/dist/src/browser/find.d.ts +84 -0
  77. package/dist/src/browser/find.js +398 -0
  78. package/dist/src/browser/find.test.d.ts +1 -0
  79. package/dist/src/browser/find.test.js +180 -0
  80. package/dist/src/browser/html-tree.d.ts +75 -0
  81. package/dist/src/browser/html-tree.js +112 -0
  82. package/dist/src/browser/html-tree.test.d.ts +1 -0
  83. package/dist/src/browser/html-tree.test.js +181 -0
  84. package/dist/src/browser/index.d.ts +14 -0
  85. package/dist/src/browser/index.js +12 -0
  86. package/dist/src/browser/network-cache.d.ts +49 -0
  87. package/dist/src/browser/network-cache.js +78 -0
  88. package/dist/src/browser/network-cache.test.d.ts +1 -0
  89. package/dist/src/browser/network-cache.test.js +75 -0
  90. package/dist/src/browser/network-interceptor.d.ts +11 -0
  91. package/dist/src/browser/network-interceptor.js +11 -0
  92. package/dist/src/browser/network-key.d.ts +22 -0
  93. package/dist/src/browser/network-key.js +66 -0
  94. package/dist/src/browser/network-key.test.d.ts +1 -0
  95. package/dist/src/browser/network-key.test.js +49 -0
  96. package/dist/src/browser/page.d.ts +83 -0
  97. package/dist/src/browser/page.js +453 -0
  98. package/dist/src/browser/page.test.d.ts +1 -0
  99. package/dist/src/browser/page.test.js +406 -0
  100. package/dist/src/browser/profile.d.ts +14 -0
  101. package/dist/src/browser/profile.js +86 -0
  102. package/dist/src/browser/protocol.d.ts +63 -0
  103. package/dist/src/browser/protocol.js +1 -0
  104. package/dist/src/browser/runtime/local-cloak/actions.d.ts +3 -0
  105. package/dist/src/browser/runtime/local-cloak/actions.js +240 -0
  106. package/dist/src/browser/runtime/local-cloak/downloads.d.ts +3 -0
  107. package/dist/src/browser/runtime/local-cloak/downloads.js +28 -0
  108. package/dist/src/browser/runtime/local-cloak/network.d.ts +28 -0
  109. package/dist/src/browser/runtime/local-cloak/network.js +120 -0
  110. package/dist/src/browser/runtime/local-cloak/network.test.d.ts +1 -0
  111. package/dist/src/browser/runtime/local-cloak/network.test.js +124 -0
  112. package/dist/src/browser/runtime/local-cloak/profiles.d.ts +6 -0
  113. package/dist/src/browser/runtime/local-cloak/profiles.js +17 -0
  114. package/dist/src/browser/runtime/local-cloak/profiles.test.d.ts +1 -0
  115. package/dist/src/browser/runtime/local-cloak/profiles.test.js +19 -0
  116. package/dist/src/browser/runtime/local-cloak/provider.d.ts +15 -0
  117. package/dist/src/browser/runtime/local-cloak/provider.js +27 -0
  118. package/dist/src/browser/runtime/local-cloak/provider.test.d.ts +1 -0
  119. package/dist/src/browser/runtime/local-cloak/provider.test.js +244 -0
  120. package/dist/src/browser/runtime/local-cloak/session-manager.d.ts +77 -0
  121. package/dist/src/browser/runtime/local-cloak/session-manager.js +280 -0
  122. package/dist/src/browser/runtime/local-cloak/session-manager.test.d.ts +1 -0
  123. package/dist/src/browser/runtime/local-cloak/session-manager.test.js +92 -0
  124. package/dist/src/browser/runtime/provider.d.ts +9 -0
  125. package/dist/src/browser/runtime/provider.js +1 -0
  126. package/dist/src/browser/runtime/provider.test.d.ts +2 -0
  127. package/dist/src/browser/runtime/provider.test.js +49 -0
  128. package/dist/src/browser/shape-filter.d.ts +52 -0
  129. package/dist/src/browser/shape-filter.js +101 -0
  130. package/dist/src/browser/shape-filter.test.d.ts +1 -0
  131. package/dist/src/browser/shape-filter.test.js +101 -0
  132. package/dist/src/browser/shape.d.ts +23 -0
  133. package/dist/src/browser/shape.js +95 -0
  134. package/dist/src/browser/shape.test.d.ts +1 -0
  135. package/dist/src/browser/shape.test.js +82 -0
  136. package/dist/src/browser/stealth.d.ts +11 -0
  137. package/dist/src/browser/stealth.js +359 -0
  138. package/dist/src/browser/stealth.test.d.ts +1 -0
  139. package/dist/src/browser/stealth.test.js +134 -0
  140. package/dist/src/browser/tabs.d.ts +13 -0
  141. package/dist/src/browser/tabs.js +70 -0
  142. package/dist/src/browser/target-errors.d.ts +39 -0
  143. package/dist/src/browser/target-errors.js +45 -0
  144. package/dist/src/browser/target-errors.test.d.ts +1 -0
  145. package/dist/src/browser/target-errors.test.js +94 -0
  146. package/dist/src/browser/target-resolver.d.ts +158 -0
  147. package/dist/src/browser/target-resolver.js +570 -0
  148. package/dist/src/browser/target-resolver.test.d.ts +1 -0
  149. package/dist/src/browser/target-resolver.test.js +118 -0
  150. package/dist/src/browser/utils.d.ts +20 -0
  151. package/dist/src/browser/utils.js +64 -0
  152. package/dist/src/browser/utils.test.d.ts +1 -0
  153. package/dist/src/browser/utils.test.js +29 -0
  154. package/dist/src/browser/verify-fixture.d.ts +65 -0
  155. package/dist/src/browser/verify-fixture.js +318 -0
  156. package/dist/src/browser/verify-fixture.test.d.ts +1 -0
  157. package/dist/src/browser/verify-fixture.test.js +219 -0
  158. package/dist/src/browser/visual-refs.d.ts +11 -0
  159. package/dist/src/browser/visual-refs.js +108 -0
  160. package/dist/src/browser.test.d.ts +1 -0
  161. package/dist/src/browser.test.js +297 -0
  162. package/dist/src/build-manifest.d.ts +103 -0
  163. package/dist/src/build-manifest.js +363 -0
  164. package/dist/src/build-manifest.test.d.ts +1 -0
  165. package/dist/src/build-manifest.test.js +341 -0
  166. package/dist/src/capabilityRouting.d.ts +19 -0
  167. package/dist/src/capabilityRouting.js +56 -0
  168. package/dist/src/capabilityRouting.test.d.ts +1 -0
  169. package/dist/src/capabilityRouting.test.js +63 -0
  170. package/dist/src/cli-argv-preprocess.d.ts +63 -0
  171. package/dist/src/cli-argv-preprocess.js +303 -0
  172. package/dist/src/cli-argv-preprocess.test.d.ts +1 -0
  173. package/dist/src/cli-argv-preprocess.test.js +304 -0
  174. package/dist/src/cli.d.ts +79 -0
  175. package/dist/src/cli.js +3350 -0
  176. package/dist/src/cli.test.d.ts +1 -0
  177. package/dist/src/cli.test.js +3041 -0
  178. package/dist/src/commanderAdapter.d.ts +21 -0
  179. package/dist/src/commanderAdapter.js +208 -0
  180. package/dist/src/commanderAdapter.test.d.ts +1 -0
  181. package/dist/src/commanderAdapter.test.js +352 -0
  182. package/dist/src/commands/auth.d.ts +40 -0
  183. package/dist/src/commands/auth.js +434 -0
  184. package/dist/src/commands/auth.test.d.ts +1 -0
  185. package/dist/src/commands/auth.test.js +252 -0
  186. package/dist/src/commands/daemon.d.ts +9 -0
  187. package/dist/src/commands/daemon.js +91 -0
  188. package/dist/src/commands/daemon.test.d.ts +1 -0
  189. package/dist/src/commands/daemon.test.js +293 -0
  190. package/dist/src/completion-fast.d.ts +22 -0
  191. package/dist/src/completion-fast.js +88 -0
  192. package/dist/src/completion-shared.d.ts +13 -0
  193. package/dist/src/completion-shared.js +61 -0
  194. package/dist/src/completion.d.ts +21 -0
  195. package/dist/src/completion.js +68 -0
  196. package/dist/src/completion.test.d.ts +1 -0
  197. package/dist/src/completion.test.js +24 -0
  198. package/dist/src/constants.d.ts +18 -0
  199. package/dist/src/constants.js +41 -0
  200. package/dist/src/convention-audit.d.ts +50 -0
  201. package/dist/src/convention-audit.js +553 -0
  202. package/dist/src/convention-audit.test.d.ts +1 -0
  203. package/dist/src/convention-audit.test.js +255 -0
  204. package/dist/src/daemon/server.d.ts +13 -0
  205. package/dist/src/daemon/server.js +185 -0
  206. package/dist/src/daemon/server.test.d.ts +1 -0
  207. package/dist/src/daemon/server.test.js +132 -0
  208. package/dist/src/daemon-utils.d.ts +18 -0
  209. package/dist/src/daemon-utils.js +37 -0
  210. package/dist/src/daemon.d.ts +1 -0
  211. package/dist/src/daemon.js +27 -0
  212. package/dist/src/daemon.test.d.ts +1 -0
  213. package/dist/src/daemon.test.js +60 -0
  214. package/dist/src/discovery.d.ts +46 -0
  215. package/dist/src/discovery.js +341 -0
  216. package/dist/src/doctor.d.ts +39 -0
  217. package/dist/src/doctor.js +168 -0
  218. package/dist/src/doctor.test.d.ts +1 -0
  219. package/dist/src/doctor.test.js +302 -0
  220. package/dist/src/download/article-download.d.ts +72 -0
  221. package/dist/src/download/article-download.js +305 -0
  222. package/dist/src/download/article-download.test.d.ts +1 -0
  223. package/dist/src/download/article-download.test.js +235 -0
  224. package/dist/src/download/index.d.ts +71 -0
  225. package/dist/src/download/index.js +363 -0
  226. package/dist/src/download/index.test.d.ts +1 -0
  227. package/dist/src/download/index.test.js +174 -0
  228. package/dist/src/download/media-download.d.ts +49 -0
  229. package/dist/src/download/media-download.js +127 -0
  230. package/dist/src/download/media-download.test.d.ts +1 -0
  231. package/dist/src/download/media-download.test.js +112 -0
  232. package/dist/src/download/progress.d.ts +36 -0
  233. package/dist/src/download/progress.js +120 -0
  234. package/dist/src/download/progress.test.d.ts +1 -0
  235. package/dist/src/download/progress.test.js +36 -0
  236. package/dist/src/electron-apps.d.ts +31 -0
  237. package/dist/src/electron-apps.js +91 -0
  238. package/dist/src/electron-apps.test.d.ts +1 -0
  239. package/dist/src/electron-apps.test.js +76 -0
  240. package/dist/src/engine.test.d.ts +1 -0
  241. package/dist/src/engine.test.js +312 -0
  242. package/dist/src/errors.d.ts +114 -0
  243. package/dist/src/errors.js +174 -0
  244. package/dist/src/errors.test.d.ts +1 -0
  245. package/dist/src/errors.test.js +109 -0
  246. package/dist/src/execution.d.ts +24 -0
  247. package/dist/src/execution.js +509 -0
  248. package/dist/src/execution.test.d.ts +1 -0
  249. package/dist/src/execution.test.js +645 -0
  250. package/dist/src/external.d.ts +49 -0
  251. package/dist/src/external.js +211 -0
  252. package/dist/src/external.test.d.ts +1 -0
  253. package/dist/src/external.test.js +110 -0
  254. package/dist/src/help.d.ts +88 -0
  255. package/dist/src/help.js +556 -0
  256. package/dist/src/help.test.d.ts +1 -0
  257. package/dist/src/help.test.js +58 -0
  258. package/dist/src/hooks.d.ts +46 -0
  259. package/dist/src/hooks.js +58 -0
  260. package/dist/src/hooks.test.d.ts +4 -0
  261. package/dist/src/hooks.test.js +92 -0
  262. package/dist/src/interceptor.d.ts +44 -0
  263. package/dist/src/interceptor.js +183 -0
  264. package/dist/src/interceptor.test.d.ts +4 -0
  265. package/dist/src/interceptor.test.js +81 -0
  266. package/dist/src/launcher.d.ts +41 -0
  267. package/dist/src/launcher.js +226 -0
  268. package/dist/src/launcher.test.d.ts +1 -0
  269. package/dist/src/launcher.test.js +153 -0
  270. package/dist/src/logger.d.ts +26 -0
  271. package/dist/src/logger.js +49 -0
  272. package/dist/src/main.d.ts +5 -0
  273. package/dist/src/main.js +177 -0
  274. package/dist/src/manifest-types.d.ts +43 -0
  275. package/dist/src/manifest-types.js +9 -0
  276. package/dist/src/node-network.d.ts +10 -0
  277. package/dist/src/node-network.js +174 -0
  278. package/dist/src/node-network.test.d.ts +1 -0
  279. package/dist/src/node-network.test.js +55 -0
  280. package/dist/src/observation/artifact.d.ts +16 -0
  281. package/dist/src/observation/artifact.js +260 -0
  282. package/dist/src/observation/artifact.test.d.ts +1 -0
  283. package/dist/src/observation/artifact.test.js +121 -0
  284. package/dist/src/observation/events.d.ts +89 -0
  285. package/dist/src/observation/events.js +1 -0
  286. package/dist/src/observation/index.d.ts +7 -0
  287. package/dist/src/observation/index.js +7 -0
  288. package/dist/src/observation/manager.d.ts +9 -0
  289. package/dist/src/observation/manager.js +27 -0
  290. package/dist/src/observation/manager.test.d.ts +1 -0
  291. package/dist/src/observation/manager.test.js +13 -0
  292. package/dist/src/observation/redaction.d.ts +11 -0
  293. package/dist/src/observation/redaction.js +81 -0
  294. package/dist/src/observation/redaction.test.d.ts +1 -0
  295. package/dist/src/observation/redaction.test.js +32 -0
  296. package/dist/src/observation/retention.d.ts +32 -0
  297. package/dist/src/observation/retention.js +160 -0
  298. package/dist/src/observation/retention.test.d.ts +1 -0
  299. package/dist/src/observation/retention.test.js +118 -0
  300. package/dist/src/observation/ring-buffer.d.ts +22 -0
  301. package/dist/src/observation/ring-buffer.js +45 -0
  302. package/dist/src/observation/ring-buffer.test.d.ts +1 -0
  303. package/dist/src/observation/ring-buffer.test.js +22 -0
  304. package/dist/src/observation/session.d.ts +25 -0
  305. package/dist/src/observation/session.js +50 -0
  306. package/dist/src/output.d.ts +14 -0
  307. package/dist/src/output.js +152 -0
  308. package/dist/src/output.test.d.ts +1 -0
  309. package/dist/src/output.test.js +53 -0
  310. package/dist/src/package-exports.test.d.ts +1 -0
  311. package/dist/src/package-exports.test.js +112 -0
  312. package/dist/src/package-paths.d.ts +8 -0
  313. package/dist/src/package-paths.js +41 -0
  314. package/dist/src/pipeline/executor.d.ts +11 -0
  315. package/dist/src/pipeline/executor.js +93 -0
  316. package/dist/src/pipeline/executor.test.d.ts +4 -0
  317. package/dist/src/pipeline/executor.test.js +182 -0
  318. package/dist/src/pipeline/index.d.ts +5 -0
  319. package/dist/src/pipeline/index.js +5 -0
  320. package/dist/src/pipeline/registry.d.ts +28 -0
  321. package/dist/src/pipeline/registry.js +55 -0
  322. package/dist/src/pipeline/steps/browser.d.ts +13 -0
  323. package/dist/src/pipeline/steps/browser.js +86 -0
  324. package/dist/src/pipeline/steps/download.d.ts +18 -0
  325. package/dist/src/pipeline/steps/download.js +252 -0
  326. package/dist/src/pipeline/steps/download.test.d.ts +1 -0
  327. package/dist/src/pipeline/steps/download.test.js +102 -0
  328. package/dist/src/pipeline/steps/fetch.d.ts +5 -0
  329. package/dist/src/pipeline/steps/fetch.js +122 -0
  330. package/dist/src/pipeline/steps/fetch.test.d.ts +1 -0
  331. package/dist/src/pipeline/steps/fetch.test.js +117 -0
  332. package/dist/src/pipeline/steps/intercept.d.ts +5 -0
  333. package/dist/src/pipeline/steps/intercept.js +50 -0
  334. package/dist/src/pipeline/steps/tap.d.ts +12 -0
  335. package/dist/src/pipeline/steps/tap.js +93 -0
  336. package/dist/src/pipeline/steps/transform.d.ts +9 -0
  337. package/dist/src/pipeline/steps/transform.js +70 -0
  338. package/dist/src/pipeline/template.d.ts +17 -0
  339. package/dist/src/pipeline/template.js +344 -0
  340. package/dist/src/pipeline/template.test.d.ts +4 -0
  341. package/dist/src/pipeline/template.test.js +197 -0
  342. package/dist/src/pipeline/transform.test.d.ts +4 -0
  343. package/dist/src/pipeline/transform.test.js +133 -0
  344. package/dist/src/plugin-manifest.d.ts +70 -0
  345. package/dist/src/plugin-manifest.js +160 -0
  346. package/dist/src/plugin-manifest.test.d.ts +4 -0
  347. package/dist/src/plugin-manifest.test.js +179 -0
  348. package/dist/src/plugin-scaffold.d.ts +28 -0
  349. package/dist/src/plugin-scaffold.js +143 -0
  350. package/dist/src/plugin-scaffold.test.d.ts +4 -0
  351. package/dist/src/plugin-scaffold.test.js +83 -0
  352. package/dist/src/plugin.d.ts +146 -0
  353. package/dist/src/plugin.js +1303 -0
  354. package/dist/src/plugin.test.d.ts +4 -0
  355. package/dist/src/plugin.test.js +1363 -0
  356. package/dist/src/registry-api.d.ts +13 -0
  357. package/dist/src/registry-api.js +10 -0
  358. package/dist/src/registry.d.ts +123 -0
  359. package/dist/src/registry.js +125 -0
  360. package/dist/src/registry.test.d.ts +4 -0
  361. package/dist/src/registry.test.js +209 -0
  362. package/dist/src/runtime-copy.test.d.ts +1 -0
  363. package/dist/src/runtime-copy.test.js +29 -0
  364. package/dist/src/runtime-detect.d.ts +31 -0
  365. package/dist/src/runtime-detect.js +47 -0
  366. package/dist/src/runtime-detect.test.d.ts +1 -0
  367. package/dist/src/runtime-detect.test.js +39 -0
  368. package/dist/src/runtime-identity.test.d.ts +1 -0
  369. package/dist/src/runtime-identity.test.js +18 -0
  370. package/dist/src/runtime.d.ts +47 -0
  371. package/dist/src/runtime.js +54 -0
  372. package/dist/src/scripts/framework.d.ts +7 -0
  373. package/dist/src/scripts/framework.js +25 -0
  374. package/dist/src/scripts/interact.d.ts +4 -0
  375. package/dist/src/scripts/interact.js +20 -0
  376. package/dist/src/scripts/store.d.ts +13 -0
  377. package/dist/src/scripts/store.js +48 -0
  378. package/dist/src/serialization.d.ts +42 -0
  379. package/dist/src/serialization.js +103 -0
  380. package/dist/src/serialization.test.d.ts +1 -0
  381. package/dist/src/serialization.test.js +78 -0
  382. package/dist/src/skills.d.ts +14 -0
  383. package/dist/src/skills.js +127 -0
  384. package/dist/src/skills.test.d.ts +1 -0
  385. package/dist/src/skills.test.js +71 -0
  386. package/dist/src/snapshotFormatter.d.ts +11 -0
  387. package/dist/src/snapshotFormatter.js +338 -0
  388. package/dist/src/snapshotFormatter.test.d.ts +7 -0
  389. package/dist/src/snapshotFormatter.test.js +521 -0
  390. package/dist/src/tui.d.ts +28 -0
  391. package/dist/src/tui.js +179 -0
  392. package/dist/src/tui.test.d.ts +1 -0
  393. package/dist/src/tui.test.js +19 -0
  394. package/dist/src/types.d.ts +236 -0
  395. package/dist/src/types.js +7 -0
  396. package/dist/src/update-check.d.ts +66 -0
  397. package/dist/src/update-check.js +206 -0
  398. package/dist/src/update-check.test.d.ts +1 -0
  399. package/dist/src/update-check.test.js +117 -0
  400. package/dist/src/utils.d.ts +57 -0
  401. package/dist/src/utils.js +152 -0
  402. package/dist/src/utils.test.d.ts +1 -0
  403. package/dist/src/utils.test.js +155 -0
  404. package/dist/src/validate.d.ts +21 -0
  405. package/dist/src/validate.js +130 -0
  406. package/dist/src/validate.test.d.ts +9 -0
  407. package/dist/src/validate.test.js +90 -0
  408. package/dist/src/verify.d.ts +26 -0
  409. package/dist/src/verify.js +67 -0
  410. package/dist/src/version.d.ts +4 -0
  411. package/dist/src/version.js +22 -0
  412. package/dist/src/weixin-download.test.d.ts +1 -0
  413. package/dist/src/weixin-download.test.js +45 -0
  414. package/package.json +4 -3
  415. package/scripts/check-package-bin.mjs +95 -0
@@ -0,0 +1,326 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { fetchDaemonStatus, getDaemonHealth, requestDaemonShutdown, sendCommand, } from './daemon-client.js';
3
+ import * as daemonLifecycle from './daemon-lifecycle.js';
4
+ describe('daemon-client', () => {
5
+ beforeEach(() => {
6
+ vi.stubGlobal('fetch', vi.fn());
7
+ });
8
+ afterEach(() => {
9
+ vi.restoreAllMocks();
10
+ vi.unstubAllEnvs();
11
+ });
12
+ it('fetchDaemonStatus sends the shared status request and returns parsed data', async () => {
13
+ const status = {
14
+ ok: true,
15
+ pid: 123,
16
+ uptime: 10,
17
+ runtimeConnected: true,
18
+ runtimeName: 'fake',
19
+ runtimeVersion: '1.2.3',
20
+ pending: 0,
21
+ memoryMB: 32,
22
+ port: 19825,
23
+ };
24
+ const fetchMock = vi.mocked(fetch);
25
+ fetchMock.mockResolvedValue({
26
+ ok: true,
27
+ json: () => Promise.resolve(status),
28
+ });
29
+ await expect(fetchDaemonStatus()).resolves.toEqual(status);
30
+ expect(fetchMock).toHaveBeenCalledWith(expect.stringMatching(/\/status$/), expect.objectContaining({
31
+ headers: expect.objectContaining({ 'X-Webcmd': '1' }),
32
+ }));
33
+ });
34
+ it('fetchDaemonStatus returns null on network failure', async () => {
35
+ vi.mocked(fetch).mockRejectedValue(new Error('ECONNREFUSED'));
36
+ await expect(fetchDaemonStatus()).resolves.toBeNull();
37
+ });
38
+ it('requestDaemonShutdown POSTs to the shared shutdown endpoint', async () => {
39
+ const fetchMock = vi.mocked(fetch);
40
+ fetchMock.mockResolvedValue({ ok: true });
41
+ await expect(requestDaemonShutdown()).resolves.toBe(true);
42
+ expect(fetchMock).toHaveBeenCalledWith(expect.stringMatching(/\/shutdown$/), expect.objectContaining({
43
+ method: 'POST',
44
+ headers: expect.objectContaining({ 'X-Webcmd': '1' }),
45
+ }));
46
+ });
47
+ it('getDaemonHealth returns stopped when daemon is not reachable', async () => {
48
+ vi.mocked(fetch).mockRejectedValue(new Error('ECONNREFUSED'));
49
+ await expect(getDaemonHealth()).resolves.toEqual({ state: 'stopped', status: null });
50
+ });
51
+ it('getDaemonHealth returns no-runtime when daemon is running but runtime disconnected', async () => {
52
+ const status = {
53
+ ok: true,
54
+ pid: 123,
55
+ uptime: 10,
56
+ runtimeConnected: false,
57
+ runtimeName: 'fake',
58
+ pending: 0,
59
+ memoryMB: 16,
60
+ port: 19825,
61
+ };
62
+ vi.mocked(fetch).mockResolvedValue({
63
+ ok: true,
64
+ json: () => Promise.resolve(status),
65
+ });
66
+ await expect(getDaemonHealth()).resolves.toEqual({ state: 'no-runtime', status });
67
+ });
68
+ it('getDaemonHealth returns ready when daemon and runtime are both connected', async () => {
69
+ const status = {
70
+ ok: true,
71
+ pid: 123,
72
+ uptime: 10,
73
+ runtimeConnected: true,
74
+ runtimeName: 'fake',
75
+ runtimeVersion: '1.2.3',
76
+ pending: 0,
77
+ memoryMB: 32,
78
+ port: 19825,
79
+ };
80
+ vi.mocked(fetch).mockResolvedValue({
81
+ ok: true,
82
+ json: () => Promise.resolve(status),
83
+ });
84
+ await expect(getDaemonHealth()).resolves.toEqual({ state: 'ready', status });
85
+ });
86
+ it('getDaemonHealth returns profile-required when multiple profiles are connected without a selection', async () => {
87
+ const status = {
88
+ ok: true,
89
+ pid: 123,
90
+ uptime: 10,
91
+ runtimeConnected: false,
92
+ runtimeName: 'fake',
93
+ profileRequired: true,
94
+ profiles: [
95
+ { contextId: 'work', runtimeConnected: true, pending: 0 },
96
+ { contextId: 'personal', runtimeConnected: true, pending: 0 },
97
+ ],
98
+ pending: 0,
99
+ memoryMB: 32,
100
+ port: 19825,
101
+ };
102
+ vi.mocked(fetch).mockResolvedValue({
103
+ ok: true,
104
+ json: () => Promise.resolve(status),
105
+ });
106
+ await expect(getDaemonHealth()).resolves.toEqual({ state: 'profile-required', status });
107
+ });
108
+ it('fetchDaemonStatus includes contextId in the status query', async () => {
109
+ vi.mocked(fetch).mockResolvedValue({
110
+ ok: true,
111
+ json: () => Promise.resolve({
112
+ ok: true,
113
+ pid: 1,
114
+ uptime: 0,
115
+ runtimeConnected: true,
116
+ runtimeName: 'fake',
117
+ pending: 0,
118
+ memoryMB: 1,
119
+ port: 19825,
120
+ }),
121
+ });
122
+ await fetchDaemonStatus({ contextId: 'work' });
123
+ expect(vi.mocked(fetch).mock.calls[0][0]).toMatch(/\/status\?contextId=work$/);
124
+ });
125
+ it('rejects WEBCMD_DAEMON_PORT so CLI and extension cannot split bridge ports', async () => {
126
+ vi.resetModules();
127
+ vi.stubEnv('WEBCMD_DAEMON_PORT', '19999');
128
+ vi.mocked(fetch).mockResolvedValue({
129
+ ok: true,
130
+ json: () => Promise.resolve({
131
+ ok: true,
132
+ pid: 1,
133
+ uptime: 0,
134
+ runtimeConnected: true,
135
+ runtimeName: 'fake',
136
+ pending: 0,
137
+ memoryMB: 1,
138
+ port: 19825,
139
+ }),
140
+ });
141
+ const freshClient = await import('./daemon-client.js');
142
+ await expect(freshClient.fetchDaemonStatus()).rejects.toThrow('WEBCMD_DAEMON_PORT is no longer supported');
143
+ expect(vi.mocked(fetch)).not.toHaveBeenCalled();
144
+ });
145
+ it('sendCommand includes the current pid in generated command ids', async () => {
146
+ vi.spyOn(Date, 'now').mockReturnValue(1_763_000_000_000);
147
+ vi.mocked(fetch).mockResolvedValue({
148
+ status: 200,
149
+ json: () => Promise.resolve({ id: 'server', ok: true, data: 'ok' }),
150
+ });
151
+ await expect(sendCommand('exec', { code: '1 + 1' })).resolves.toBe('ok');
152
+ await expect(sendCommand('exec', { code: '2 + 2' })).resolves.toBe('ok');
153
+ const ids = vi.mocked(fetch).mock.calls.map(([, init]) => {
154
+ const body = JSON.parse(String(init?.body));
155
+ return body.id;
156
+ });
157
+ expect(ids).toHaveLength(2);
158
+ expect(ids[0]).toMatch(new RegExp(`^cmd_${process.pid}_1763000000000_\\d+$`));
159
+ expect(ids[1]).toMatch(new RegExp(`^cmd_${process.pid}_1763000000000_\\d+$`));
160
+ expect(ids[0]).not.toBe(ids[1]);
161
+ });
162
+ it('sendCommand forwards WEBCMD_PROFILE as command contextId', async () => {
163
+ vi.stubEnv('WEBCMD_PROFILE', 'work');
164
+ vi.spyOn(Date, 'now').mockReturnValue(1_763_000_000_000);
165
+ vi.mocked(fetch).mockResolvedValue({
166
+ status: 200,
167
+ json: () => Promise.resolve({ id: 'server', ok: true, data: 'ok' }),
168
+ });
169
+ await sendCommand('exec', { code: '1 + 1' });
170
+ const body = JSON.parse(String(vi.mocked(fetch).mock.calls[0][1]?.body));
171
+ expect(body.contextId).toBe('work');
172
+ });
173
+ it('sendCommand uses explicit windowMode before WEBCMD_WINDOW env fallback', async () => {
174
+ vi.stubEnv('WEBCMD_WINDOW', 'foreground');
175
+ vi.mocked(fetch).mockResolvedValue({
176
+ status: 200,
177
+ json: () => Promise.resolve({ id: 'server', ok: true, data: 'ok' }),
178
+ });
179
+ await sendCommand('exec', { code: '1 + 1', windowMode: 'background' });
180
+ const body = JSON.parse(String(vi.mocked(fetch).mock.calls[0][1]?.body));
181
+ expect(body.windowMode).toBe('background');
182
+ });
183
+ it('sendCommand retries with a new id when daemon reports a duplicate pending id', async () => {
184
+ vi.spyOn(Date, 'now').mockReturnValue(1_763_000_000_123);
185
+ const fetchMock = vi.mocked(fetch);
186
+ fetchMock
187
+ .mockResolvedValueOnce({
188
+ ok: false,
189
+ status: 409,
190
+ json: () => Promise.resolve({ ok: false, error: 'Duplicate command id already pending; retry' }),
191
+ })
192
+ .mockResolvedValueOnce({
193
+ ok: true,
194
+ status: 200,
195
+ json: () => Promise.resolve({ id: 'server', ok: true, data: 42 }),
196
+ });
197
+ await expect(sendCommand('exec', { code: '6 * 7' })).resolves.toBe(42);
198
+ expect(fetchMock).toHaveBeenCalledTimes(2);
199
+ const ids = fetchMock.mock.calls.map(([, init]) => {
200
+ const body = JSON.parse(String(init?.body));
201
+ return body.id;
202
+ });
203
+ expect(ids[0]).not.toBe(ids[1]);
204
+ });
205
+ it('sendCommand does not retry command_result_unknown even when the message looks transient', async () => {
206
+ const fetchMock = vi.mocked(fetch);
207
+ fetchMock.mockResolvedValue({
208
+ ok: false,
209
+ status: 503,
210
+ json: () => Promise.resolve({
211
+ id: 'server',
212
+ ok: false,
213
+ errorCode: 'command_result_unknown',
214
+ error: 'Extension disconnected after command timeout',
215
+ errorHint: 'Inspect state before retrying.',
216
+ }),
217
+ });
218
+ await expect(sendCommand('exec', { code: 'window.__mutate = true' })).rejects.toMatchObject({
219
+ name: 'BrowserCommandError',
220
+ code: 'command_result_unknown',
221
+ hint: 'Inspect state before retrying.',
222
+ });
223
+ expect(fetchMock).toHaveBeenCalledTimes(1);
224
+ });
225
+ it('sendCommand runs full bridge ensure on a pre-dispatch failure, then resends with a fresh id', async () => {
226
+ vi.spyOn(Date, 'now').mockReturnValue(1_763_000_000_321);
227
+ const ensureSpy = vi.spyOn(daemonLifecycle, 'ensureBrowserBridgeReady').mockResolvedValue({
228
+ health: {
229
+ state: 'ready',
230
+ status: {
231
+ ok: true,
232
+ pid: 1,
233
+ uptime: 1,
234
+ runtimeConnected: true,
235
+ runtimeName: 'fake',
236
+ pending: 0,
237
+ memoryMB: 0,
238
+ port: 19825,
239
+ },
240
+ },
241
+ spawnedProcess: null,
242
+ });
243
+ const fetchMock = vi.mocked(fetch);
244
+ fetchMock
245
+ .mockResolvedValueOnce({
246
+ ok: false,
247
+ status: 503,
248
+ json: () => Promise.resolve({
249
+ ok: false,
250
+ errorCode: 'extension_not_connected',
251
+ error: 'Extension not connected.',
252
+ }),
253
+ })
254
+ .mockResolvedValueOnce({
255
+ ok: true,
256
+ status: 200,
257
+ json: () => Promise.resolve({ id: 'server', ok: true, data: 7 }),
258
+ });
259
+ await expect(sendCommand('exec', { code: '1 + 6', contextId: 'work' })).resolves.toBe(7);
260
+ expect(ensureSpy).toHaveBeenCalledWith(expect.objectContaining({ contextId: 'work', verbose: false }));
261
+ const ids = fetchMock.mock.calls.map(([, init]) => JSON.parse(String(init?.body)).id);
262
+ expect(ids).toHaveLength(2);
263
+ expect(ids[0]).not.toBe(ids[1]);
264
+ });
265
+ it('sendCommand runs full bridge ensure on a local TypeError before resending', async () => {
266
+ const ensureSpy = vi.spyOn(daemonLifecycle, 'ensureBrowserBridgeReady').mockResolvedValue({
267
+ health: {
268
+ state: 'ready',
269
+ status: {
270
+ ok: true,
271
+ pid: 1,
272
+ uptime: 1,
273
+ runtimeConnected: true,
274
+ runtimeName: 'fake',
275
+ pending: 0,
276
+ memoryMB: 0,
277
+ port: 19825,
278
+ },
279
+ },
280
+ spawnedProcess: null,
281
+ });
282
+ const fetchMock = vi.mocked(fetch);
283
+ fetchMock
284
+ .mockRejectedValueOnce(new TypeError('fetch failed'))
285
+ .mockResolvedValueOnce({
286
+ ok: true,
287
+ status: 200,
288
+ json: () => Promise.resolve({ id: 'server', ok: true, data: 'ok' }),
289
+ });
290
+ await expect(sendCommand('exec', { code: 'document.title' })).resolves.toBe('ok');
291
+ expect(ensureSpy).toHaveBeenCalledWith(expect.objectContaining({ verbose: false }));
292
+ expect(fetchMock).toHaveBeenCalledTimes(2);
293
+ });
294
+ it('sendCommand does NOT wait when the bridge reports profile_required', async () => {
295
+ const ensureSpy = vi.spyOn(daemonLifecycle, 'ensureBrowserBridgeReady');
296
+ const fetchMock = vi.mocked(fetch);
297
+ fetchMock.mockResolvedValueOnce({
298
+ ok: false,
299
+ status: 409,
300
+ json: () => Promise.resolve({
301
+ ok: false,
302
+ errorCode: 'profile_required',
303
+ error: 'Multiple browser runtime profiles are connected; choose one with --profile.',
304
+ errorHint: 'Run webcmd profile list, then webcmd profile use <name>.',
305
+ }),
306
+ });
307
+ await expect(sendCommand('exec', { code: '1' })).rejects.toMatchObject({
308
+ name: 'BrowserCommandError',
309
+ code: 'profile_required',
310
+ });
311
+ expect(ensureSpy).not.toHaveBeenCalled();
312
+ expect(fetchMock).toHaveBeenCalledTimes(1);
313
+ });
314
+ it('sendCommand surfaces an AbortError as command_result_unknown without ensure or resend', async () => {
315
+ const ensureSpy = vi.spyOn(daemonLifecycle, 'ensureBrowserBridgeReady');
316
+ const abortErr = new Error('The operation was aborted');
317
+ abortErr.name = 'AbortError';
318
+ vi.mocked(fetch).mockRejectedValueOnce(abortErr);
319
+ await expect(sendCommand('exec', { code: 'window.__mutate = true' })).rejects.toMatchObject({
320
+ name: 'BrowserCommandError',
321
+ code: 'command_result_unknown',
322
+ });
323
+ expect(ensureSpy).not.toHaveBeenCalled();
324
+ expect(fetch).toHaveBeenCalledTimes(1);
325
+ });
326
+ });
@@ -0,0 +1,37 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ import { DEFAULT_DAEMON_PORT } from '../constants.js';
3
+ import { requestDaemonShutdown, type DaemonHealth, type DaemonStatus } from './daemon-transport.js';
4
+ export interface DaemonLaunchSpec {
5
+ binary: string;
6
+ args: string[];
7
+ scriptPath: string;
8
+ }
9
+ export interface DaemonRestartResult {
10
+ previousStatus: DaemonStatus | null;
11
+ status: DaemonStatus | null;
12
+ stopped: boolean;
13
+ spawned: boolean;
14
+ }
15
+ export interface EnsureBrowserBridgeReadyResult {
16
+ health: DaemonHealth;
17
+ spawnedProcess: ChildProcess | null;
18
+ }
19
+ export declare function resolveDaemonLaunchSpec(): DaemonLaunchSpec;
20
+ export declare function spawnDaemonProcess(): ChildProcess;
21
+ export declare function waitForDaemonStop(timeoutMs: number): Promise<boolean>;
22
+ export declare function waitForDaemonStatus(timeoutMs: number): Promise<DaemonStatus | null>;
23
+ export declare const daemonLifecycleHooks: {
24
+ requestDaemonShutdown: typeof requestDaemonShutdown;
25
+ spawnDaemonProcess: typeof spawnDaemonProcess;
26
+ waitForDaemonStop: typeof waitForDaemonStop;
27
+ };
28
+ export declare function restartDaemon(opts?: {
29
+ stopTimeoutMs?: number;
30
+ startTimeoutMs?: number;
31
+ }): Promise<DaemonRestartResult>;
32
+ export declare function ensureBrowserBridgeReady(opts?: {
33
+ timeoutSeconds?: number;
34
+ contextId?: string;
35
+ verbose?: boolean;
36
+ }): Promise<EnsureBrowserBridgeReadyResult>;
37
+ export { DEFAULT_DAEMON_PORT };
@@ -0,0 +1,147 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { fileURLToPath } from 'node:url';
3
+ import * as fs from 'node:fs';
4
+ import * as path from 'node:path';
5
+ import { DEFAULT_DAEMON_PORT } from '../constants.js';
6
+ import { BrowserConnectError } from '../errors.js';
7
+ import { PKG_VERSION } from '../version.js';
8
+ import { waitForBridgeReady } from './bridge-readiness.js';
9
+ import { fetchDaemonStatus, getDaemonHealth, requestDaemonShutdown } from './daemon-transport.js';
10
+ export function resolveDaemonLaunchSpec() {
11
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
+ const parentDir = path.resolve(__dirname, '..');
13
+ const daemonTs = path.join(parentDir, 'daemon.ts');
14
+ const daemonJs = path.join(parentDir, 'daemon.js');
15
+ const isTs = fs.existsSync(daemonTs);
16
+ const scriptPath = isTs ? daemonTs : daemonJs;
17
+ return {
18
+ binary: process.execPath,
19
+ args: isTs ? ['--import', 'tsx/esm', scriptPath] : [scriptPath],
20
+ scriptPath,
21
+ };
22
+ }
23
+ export function spawnDaemonProcess() {
24
+ const launch = resolveDaemonLaunchSpec();
25
+ const proc = spawn(launch.binary, launch.args, {
26
+ detached: true,
27
+ stdio: 'ignore',
28
+ env: { ...process.env },
29
+ });
30
+ proc.unref();
31
+ return proc;
32
+ }
33
+ export async function waitForDaemonStop(timeoutMs) {
34
+ const deadline = Date.now() + timeoutMs;
35
+ while (Date.now() < deadline) {
36
+ await sleep(200);
37
+ const h = await getDaemonHealth();
38
+ if (h.state === 'stopped')
39
+ return true;
40
+ }
41
+ return false;
42
+ }
43
+ export async function waitForDaemonStatus(timeoutMs) {
44
+ const deadline = Date.now() + timeoutMs;
45
+ while (Date.now() < deadline) {
46
+ const status = await fetchDaemonStatus({ timeout: Math.min(1000, Math.max(100, deadline - Date.now())) });
47
+ if (status)
48
+ return status;
49
+ await sleep(200);
50
+ }
51
+ return null;
52
+ }
53
+ export const daemonLifecycleHooks = {
54
+ requestDaemonShutdown,
55
+ spawnDaemonProcess,
56
+ waitForDaemonStop,
57
+ };
58
+ export async function restartDaemon(opts = {}) {
59
+ const previousStatus = await fetchDaemonStatus();
60
+ let stopped = previousStatus === null;
61
+ if (previousStatus) {
62
+ const shutdownAccepted = await requestDaemonShutdown();
63
+ stopped = shutdownAccepted && await waitForDaemonStop(opts.stopTimeoutMs ?? 3000);
64
+ if (!stopped) {
65
+ return { previousStatus, status: previousStatus, stopped: false, spawned: false };
66
+ }
67
+ }
68
+ spawnDaemonProcess();
69
+ const status = await waitForDaemonStatus(opts.startTimeoutMs ?? 5000);
70
+ return { previousStatus, status, stopped, spawned: true };
71
+ }
72
+ export async function ensureBrowserBridgeReady(opts = {}) {
73
+ const timeoutSeconds = opts.timeoutSeconds && opts.timeoutSeconds > 0 ? opts.timeoutSeconds : 10;
74
+ const timeoutMs = timeoutSeconds * 1000;
75
+ const verbose = opts.verbose ?? true;
76
+ const contextId = opts.contextId;
77
+ const health = await getDaemonHealth({ contextId });
78
+ const daemonVersion = health.status?.daemonVersion;
79
+ const isStale = !!health.status && (!daemonVersion || daemonVersion !== PKG_VERSION);
80
+ let staleDaemonReplaced = false;
81
+ let spawnedProcess = null;
82
+ if (isStale) {
83
+ const reason = daemonVersion
84
+ ? `v${daemonVersion} ≠ v${PKG_VERSION}`
85
+ : `pre-version daemon, CLI is v${PKG_VERSION}`;
86
+ if (verbose && (process.env.WEBCMD_VERBOSE || process.stderr.isTTY)) {
87
+ process.stderr.write(`⚠️ Stale daemon detected (${reason}). Restarting...\n`);
88
+ }
89
+ const shutdownAccepted = await daemonLifecycleHooks.requestDaemonShutdown();
90
+ let portReleased = shutdownAccepted && await daemonLifecycleHooks.waitForDaemonStop(3000);
91
+ if (!portReleased) {
92
+ const stalePid = health.status?.pid;
93
+ if (typeof stalePid === 'number' && Number.isInteger(stalePid) && stalePid > 0) {
94
+ try {
95
+ process.kill(stalePid, 'SIGKILL');
96
+ }
97
+ catch {
98
+ // EPERM / ESRCH are both resolved by polling the fixed daemon port.
99
+ }
100
+ portReleased = await daemonLifecycleHooks.waitForDaemonStop(2000);
101
+ }
102
+ }
103
+ if (!portReleased) {
104
+ throw new BrowserConnectError('Stale daemon could not be replaced', `A stale daemon (${reason}) is running but did not shut down (graceful + SIGKILL both failed).\n` +
105
+ ' Run manually: webcmd daemon stop', 'daemon-not-running');
106
+ }
107
+ staleDaemonReplaced = true;
108
+ }
109
+ if (!staleDaemonReplaced && health.state === 'ready') {
110
+ return { health, spawnedProcess };
111
+ }
112
+ if (!staleDaemonReplaced && health.state === 'profile-required') {
113
+ throw browserConnectErrorFromHealth(health, contextId);
114
+ }
115
+ if (staleDaemonReplaced || health.state === 'stopped') {
116
+ if (verbose && (process.env.WEBCMD_VERBOSE || process.stderr.isTTY)) {
117
+ process.stderr.write('⏳ Starting daemon...\n');
118
+ }
119
+ spawnedProcess = daemonLifecycleHooks.spawnDaemonProcess();
120
+ }
121
+ else if (verbose && (process.env.WEBCMD_VERBOSE || process.stderr.isTTY)) {
122
+ process.stderr.write('⏳ Waiting for Cloak runtime to connect...\n');
123
+ process.stderr.write(' Make sure Chrome or Chromium is open and Cloak is enabled.\n');
124
+ }
125
+ const finalHealth = await waitForBridgeReady(getDaemonHealth, { timeoutMs, contextId });
126
+ if (finalHealth.state === 'ready')
127
+ return { health: finalHealth, spawnedProcess };
128
+ throw browserConnectErrorFromHealth(finalHealth, contextId);
129
+ }
130
+ function browserConnectErrorFromHealth(health, contextId) {
131
+ if (health.state === 'profile-required') {
132
+ return new BrowserConnectError('Multiple browser profiles are connected', 'Select one with --profile <name>, WEBCMD_PROFILE=<name>, or webcmd profile use <name>.\n' +
133
+ 'Run webcmd profile list to see connected profiles.', 'profile-required');
134
+ }
135
+ if (health.state === 'profile-disconnected') {
136
+ const label = contextId ?? health.status.contextId ?? 'unknown';
137
+ return new BrowserConnectError(`Browser profile "${label}" is not connected`, 'Open the matching Chrome profile and make sure Cloak is enabled, or choose another profile with webcmd profile use <name>.', 'profile-disconnected');
138
+ }
139
+ if (health.state === 'no-runtime') {
140
+ return new BrowserConnectError('Browser runtime is not ready', 'Run `webcmd daemon restart`. If CloakBrowser is downloading its browser binary, wait for it to finish and retry.', 'runtime-not-ready');
141
+ }
142
+ return new BrowserConnectError('Failed to start webcmd daemon', `Try running manually:\n node ${resolveDaemonLaunchSpec().scriptPath}\nMake sure port ${DEFAULT_DAEMON_PORT} is available.`, 'daemon-not-running');
143
+ }
144
+ function sleep(ms) {
145
+ return new Promise((resolve) => setTimeout(resolve, ms));
146
+ }
147
+ export { DEFAULT_DAEMON_PORT };
@@ -0,0 +1,54 @@
1
+ export interface DaemonStatus {
2
+ ok: boolean;
3
+ pid: number;
4
+ uptime: number;
5
+ daemonVersion?: string;
6
+ runtimeConnected: boolean;
7
+ runtimeName: string;
8
+ runtimeVersion?: string;
9
+ contextId?: string;
10
+ profileRequired?: boolean;
11
+ profileDisconnected?: boolean;
12
+ profiles?: BrowserProfileStatus[];
13
+ pending: number;
14
+ commandResultUnknown?: number;
15
+ memoryMB: number;
16
+ port: number;
17
+ }
18
+ export interface BrowserProfileStatus {
19
+ contextId: string;
20
+ runtimeConnected: boolean;
21
+ runtimeVersion?: string;
22
+ pending: number;
23
+ lastSeenAt?: number;
24
+ }
25
+ export type DaemonHealth = {
26
+ state: 'stopped';
27
+ status: null;
28
+ } | {
29
+ state: 'no-runtime';
30
+ status: DaemonStatus;
31
+ } | {
32
+ state: 'profile-required';
33
+ status: DaemonStatus;
34
+ } | {
35
+ state: 'profile-disconnected';
36
+ status: DaemonStatus;
37
+ } | {
38
+ state: 'ready';
39
+ status: DaemonStatus;
40
+ };
41
+ export declare function requestDaemon(pathname: string, init?: RequestInit & {
42
+ timeout?: number;
43
+ }): Promise<Response>;
44
+ export declare function fetchDaemonStatus(opts?: {
45
+ timeout?: number;
46
+ contextId?: string;
47
+ }): Promise<DaemonStatus | null>;
48
+ export declare function getDaemonHealth(opts?: {
49
+ timeout?: number;
50
+ contextId?: string;
51
+ }): Promise<DaemonHealth>;
52
+ export declare function requestDaemonShutdown(opts?: {
53
+ timeout?: number;
54
+ }): Promise<boolean>;
@@ -0,0 +1,68 @@
1
+ import { DAEMON_HEADER_NAME, DEFAULT_DAEMON_PORT, unsupportedDaemonPortEnvMessage } from '../constants.js';
2
+ const DAEMON_PORT = DEFAULT_DAEMON_PORT;
3
+ const DAEMON_URL = `http://127.0.0.1:${DAEMON_PORT}`;
4
+ const WEBCMD_HEADERS = { [DAEMON_HEADER_NAME]: '1' };
5
+ class UnsupportedDaemonPortEnvError extends Error {
6
+ constructor(value) {
7
+ super(unsupportedDaemonPortEnvMessage(value));
8
+ this.name = 'UnsupportedDaemonPortEnvError';
9
+ }
10
+ }
11
+ function assertSupportedDaemonPortEnv() {
12
+ const value = process.env.WEBCMD_DAEMON_PORT;
13
+ if (value !== undefined && value !== '')
14
+ throw new UnsupportedDaemonPortEnvError(value);
15
+ }
16
+ export async function requestDaemon(pathname, init) {
17
+ assertSupportedDaemonPortEnv();
18
+ const { timeout = 2000, headers, ...rest } = init ?? {};
19
+ const controller = new AbortController();
20
+ const timer = setTimeout(() => controller.abort(), timeout);
21
+ try {
22
+ return await fetch(`${DAEMON_URL}${pathname}`, {
23
+ ...rest,
24
+ headers: { ...WEBCMD_HEADERS, ...headers },
25
+ signal: controller.signal,
26
+ });
27
+ }
28
+ finally {
29
+ clearTimeout(timer);
30
+ }
31
+ }
32
+ export async function fetchDaemonStatus(opts) {
33
+ try {
34
+ const params = opts?.contextId ? `?contextId=${encodeURIComponent(opts.contextId)}` : '';
35
+ const res = await requestDaemon(`/status${params}`, { timeout: opts?.timeout ?? 2000 });
36
+ if (!res.ok)
37
+ return null;
38
+ return await res.json();
39
+ }
40
+ catch (err) {
41
+ if (err instanceof UnsupportedDaemonPortEnvError)
42
+ throw err;
43
+ return null;
44
+ }
45
+ }
46
+ export async function getDaemonHealth(opts) {
47
+ const status = await fetchDaemonStatus(opts);
48
+ if (!status)
49
+ return { state: 'stopped', status: null };
50
+ if (status.profileRequired)
51
+ return { state: 'profile-required', status };
52
+ if (status.profileDisconnected)
53
+ return { state: 'profile-disconnected', status };
54
+ if (!status.runtimeConnected)
55
+ return { state: 'no-runtime', status };
56
+ return { state: 'ready', status };
57
+ }
58
+ export async function requestDaemonShutdown(opts) {
59
+ try {
60
+ const res = await requestDaemon('/shutdown', { method: 'POST', timeout: opts?.timeout ?? 5000 });
61
+ return res.ok;
62
+ }
63
+ catch (err) {
64
+ if (err instanceof UnsupportedDaemonPortEnvError)
65
+ throw err;
66
+ return false;
67
+ }
68
+ }
@@ -0,0 +1,4 @@
1
+ import type { DaemonStatus } from './daemon-transport.js';
2
+ export declare function isDaemonStale(status: Pick<DaemonStatus, 'daemonVersion'> | null | undefined, cliVersion?: string): boolean;
3
+ export declare function formatDaemonVersion(status: Pick<DaemonStatus, 'daemonVersion'> | null | undefined): string;
4
+ export declare function staleDaemonIssue(status: Pick<DaemonStatus, 'daemonVersion'> | null | undefined, cliVersion: string): string;
@@ -0,0 +1,12 @@
1
+ export function isDaemonStale(status, cliVersion) {
2
+ if (!status || !cliVersion)
3
+ return false;
4
+ return !status.daemonVersion || status.daemonVersion !== cliVersion;
5
+ }
6
+ export function formatDaemonVersion(status) {
7
+ return status?.daemonVersion ? `v${status.daemonVersion}` : 'version unknown';
8
+ }
9
+ export function staleDaemonIssue(status, cliVersion) {
10
+ return `Stale daemon detected: daemon ${formatDaemonVersion(status)} != CLI v${cliVersion}.\n` +
11
+ ' Run: webcmd daemon restart';
12
+ }