@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,240 @@
1
+ import { waitForDownload } from './downloads.js';
2
+ class CloakActionError extends Error {
3
+ errorCode;
4
+ page;
5
+ errorHint;
6
+ constructor(errorCode, error, page, errorHint) {
7
+ super(error);
8
+ this.errorCode = errorCode;
9
+ this.page = page;
10
+ this.errorHint = errorHint;
11
+ }
12
+ }
13
+ function commandProfileId(command) {
14
+ return command.profileId ?? command.contextId ?? 'default';
15
+ }
16
+ function invalidRequest(command, error) {
17
+ return { id: command.id, ok: false, errorCode: 'invalid_request', error };
18
+ }
19
+ async function resolveLease(manager, command) {
20
+ if (command.page) {
21
+ const existing = manager.findPageById(command.page, { idleTimeout: command.idleTimeout });
22
+ if (existing)
23
+ return existing;
24
+ throw new CloakActionError('stale_page_identity', `Page not found: ${command.page} — stale page identity`);
25
+ }
26
+ return manager.getPage({
27
+ profileId: commandProfileId(command),
28
+ session: command.session,
29
+ surface: command.surface,
30
+ siteSession: command.siteSession,
31
+ idleTimeout: command.idleTimeout,
32
+ });
33
+ }
34
+ function execTarget(page, frameIndex, pageId) {
35
+ if (frameIndex == null)
36
+ return page;
37
+ const frame = page.frames().slice(1)[frameIndex];
38
+ if (!frame)
39
+ throw new CloakActionError('frame_not_found', `Frame not found: ${frameIndex}`, pageId);
40
+ return frame;
41
+ }
42
+ async function applyScreenshotViewport(page, command) {
43
+ const width = Number.isFinite(command.width) && command.width > 0 ? Math.ceil(command.width) : undefined;
44
+ const height = !command.fullPage && Number.isFinite(command.height) && command.height > 0 ? Math.ceil(command.height) : undefined;
45
+ if (width === undefined && height === undefined)
46
+ return null;
47
+ const current = page.viewportSize();
48
+ await page.setViewportSize({
49
+ width: width ?? current?.width ?? 1280,
50
+ height: height ?? current?.height ?? 720,
51
+ });
52
+ return current;
53
+ }
54
+ export async function dispatchCloakAction(manager, command) {
55
+ try {
56
+ switch (command.action) {
57
+ case 'navigate': {
58
+ if (!command.url)
59
+ return invalidRequest(command, 'Missing url');
60
+ const lease = await resolveLease(manager, command);
61
+ await lease.page.goto(command.url, { waitUntil: 'load' });
62
+ return { id: command.id, ok: true, data: { title: await lease.page.title(), url: lease.page.url(), timedOut: false }, page: lease.pageId };
63
+ }
64
+ case 'exec': {
65
+ if (!command.code)
66
+ return invalidRequest(command, 'Missing code');
67
+ const lease = await resolveLease(manager, command);
68
+ const target = execTarget(lease.page, command.frameIndex, lease.pageId);
69
+ const data = await target.evaluate(command.code);
70
+ return { id: command.id, ok: true, data, page: lease.pageId };
71
+ }
72
+ case 'cookies': {
73
+ const lease = await resolveLease(manager, command);
74
+ const cookies = await lease.context.cookies(command.url ? [command.url] : undefined);
75
+ const data = command.domain ? cookies.filter((cookie) => cookie.domain.includes(command.domain)) : cookies;
76
+ return { id: command.id, ok: true, data };
77
+ }
78
+ case 'screenshot': {
79
+ const lease = await resolveLease(manager, command);
80
+ const previousViewport = await applyScreenshotViewport(lease.page, command);
81
+ try {
82
+ const buffer = await lease.page.screenshot({
83
+ type: command.format ?? 'png',
84
+ quality: command.format === 'jpeg' ? command.quality : undefined,
85
+ fullPage: command.fullPage,
86
+ });
87
+ return { id: command.id, ok: true, data: buffer.toString('base64'), page: lease.pageId };
88
+ }
89
+ finally {
90
+ if (previousViewport)
91
+ await lease.page.setViewportSize(previousViewport);
92
+ }
93
+ }
94
+ case 'close-window': {
95
+ if (command.page) {
96
+ const closed = await manager.closePage({ profileId: commandProfileId(command), pageId: command.page });
97
+ return { id: command.id, ok: true, data: { closed: Boolean(closed), page: closed ?? command.page, session: command.session } };
98
+ }
99
+ else {
100
+ await manager.release({
101
+ profileId: commandProfileId(command),
102
+ session: command.session,
103
+ surface: command.surface,
104
+ });
105
+ return { id: command.id, ok: true, data: { closed: true, session: command.session } };
106
+ }
107
+ }
108
+ case 'tabs': {
109
+ switch (command.op ?? 'list') {
110
+ case 'list': {
111
+ const tabs = await manager.listPages({ profileId: commandProfileId(command) });
112
+ return { id: command.id, ok: true, data: tabs };
113
+ }
114
+ case 'new': {
115
+ const lease = await manager.newPage({
116
+ profileId: commandProfileId(command),
117
+ session: command.session,
118
+ surface: command.surface,
119
+ siteSession: command.siteSession,
120
+ idleTimeout: command.idleTimeout,
121
+ url: command.url,
122
+ });
123
+ return { id: command.id, ok: true, data: { title: await lease.page.title(), url: lease.page.url() }, page: lease.pageId };
124
+ }
125
+ case 'select': {
126
+ const lease = await manager.selectPage({ profileId: commandProfileId(command), pageId: command.page, index: command.index });
127
+ if (!lease)
128
+ return { id: command.id, ok: false, errorCode: 'runtime_command_failed', error: 'Tab not found' };
129
+ return { id: command.id, ok: true, data: { selected: true, url: lease.page.url() }, page: lease.pageId };
130
+ }
131
+ case 'close': {
132
+ const closed = await manager.closePage({ profileId: commandProfileId(command), pageId: command.page, index: command.index });
133
+ if (!closed)
134
+ return { id: command.id, ok: false, errorCode: 'runtime_command_failed', error: 'Tab not found' };
135
+ return { id: command.id, ok: true, data: { closed } };
136
+ }
137
+ default:
138
+ return invalidRequest(command, `Unknown tabs op: ${command.op}`);
139
+ }
140
+ }
141
+ case 'set-file-input': {
142
+ if (!command.files?.length)
143
+ return invalidRequest(command, 'Missing or empty files array');
144
+ const lease = await resolveLease(manager, command);
145
+ const locator = lease.page.locator(command.selector ?? 'input[type="file"]').first();
146
+ await locator.setInputFiles(command.files);
147
+ return { id: command.id, ok: true, data: { count: command.files.length }, page: lease.pageId };
148
+ }
149
+ case 'insert-text': {
150
+ if (typeof command.text !== 'string')
151
+ return invalidRequest(command, 'Missing text payload');
152
+ const lease = await resolveLease(manager, command);
153
+ await lease.page.keyboard.insertText(command.text);
154
+ return { id: command.id, ok: true, data: { inserted: true }, page: lease.pageId };
155
+ }
156
+ case 'network-capture-start': {
157
+ const lease = await resolveLease(manager, command);
158
+ manager.networkCapture.start(command.pattern ?? '', lease.page);
159
+ return { id: command.id, ok: true, data: { started: true }, page: lease.pageId };
160
+ }
161
+ case 'network-capture-read': {
162
+ const lease = await resolveLease(manager, command);
163
+ return { id: command.id, ok: true, data: await manager.networkCapture.read(lease.page), page: lease.pageId };
164
+ }
165
+ case 'wait-download': {
166
+ const lease = await resolveLease(manager, command);
167
+ const result = await waitForDownload(lease.page, command.pattern ?? '', command.timeoutMs ?? 30_000);
168
+ return { id: command.id, ok: true, data: result, page: lease.pageId };
169
+ }
170
+ case 'cdp': {
171
+ if (!command.cdpMethod)
172
+ return invalidRequest(command, 'Missing cdpMethod');
173
+ const lease = await resolveLease(manager, command);
174
+ const session = await lease.context.newCDPSession(lease.page);
175
+ const data = await session.send(command.cdpMethod, command.cdpParams ?? {});
176
+ return { id: command.id, ok: true, data, page: lease.pageId };
177
+ }
178
+ case 'frames': {
179
+ const lease = await resolveLease(manager, command);
180
+ const frames = lease.page.frames().slice(1).map((frame, index) => ({
181
+ index,
182
+ frameId: frame.name() || String(index),
183
+ url: frame.url(),
184
+ name: frame.name(),
185
+ }));
186
+ return { id: command.id, ok: true, data: frames, page: lease.pageId };
187
+ }
188
+ case 'bind':
189
+ if (!command.page && command.index == null) {
190
+ return {
191
+ id: command.id,
192
+ ok: false,
193
+ errorCode: 'invalid_request',
194
+ error: 'Bind requires --page or --index for a Cloak runtime tab',
195
+ errorHint: 'Run `webcmd browser <session> tab list`, then retry with `webcmd browser <session> bind --page <page-id>`.',
196
+ };
197
+ }
198
+ {
199
+ const lease = await manager.bindPage({
200
+ profileId: commandProfileId(command),
201
+ session: command.session,
202
+ surface: command.surface,
203
+ siteSession: command.siteSession,
204
+ idleTimeout: command.idleTimeout,
205
+ pageId: command.page,
206
+ index: command.index,
207
+ });
208
+ if (!lease) {
209
+ return {
210
+ id: command.id,
211
+ ok: false,
212
+ errorCode: 'bound_tab_not_found',
213
+ error: 'Cloak tab not found for bind target',
214
+ errorHint: 'Run `webcmd browser <session> tab list` and choose a current Cloak tab id or index.',
215
+ };
216
+ }
217
+ return {
218
+ id: command.id,
219
+ ok: true,
220
+ page: lease.pageId,
221
+ data: {
222
+ bound: true,
223
+ session: command.session,
224
+ page: lease.pageId,
225
+ url: lease.page.url(),
226
+ title: await lease.page.title().catch(() => ''),
227
+ },
228
+ };
229
+ }
230
+ default:
231
+ return { id: command.id, ok: false, errorCode: 'runtime_command_failed', error: `Unknown action: ${command.action}` };
232
+ }
233
+ }
234
+ catch (err) {
235
+ if (err instanceof CloakActionError) {
236
+ return { id: command.id, ok: false, errorCode: err.errorCode, error: err.message, ...(err.page && { page: err.page }), ...(err.errorHint && { errorHint: err.errorHint }) };
237
+ }
238
+ return { id: command.id, ok: false, errorCode: 'runtime_command_failed', error: err instanceof Error ? err.message : String(err) };
239
+ }
240
+ }
@@ -0,0 +1,3 @@
1
+ import type { Page } from 'playwright-core';
2
+ import type { BrowserDownloadWaitResult } from '../../../types.js';
3
+ export declare function waitForDownload(page: Page, pattern: string, timeoutMs: number): Promise<BrowserDownloadWaitResult>;
@@ -0,0 +1,28 @@
1
+ export async function waitForDownload(page, pattern, timeoutMs) {
2
+ const startedAt = Date.now();
3
+ try {
4
+ const download = await page.waitForEvent('download', {
5
+ timeout: timeoutMs,
6
+ predicate: (candidate) => {
7
+ if (!pattern)
8
+ return true;
9
+ return candidate.url().includes(pattern) || candidate.suggestedFilename().includes(pattern);
10
+ },
11
+ });
12
+ const failure = await download.failure();
13
+ return {
14
+ downloaded: !failure,
15
+ filename: download.suggestedFilename(),
16
+ url: download.url(),
17
+ error: failure ?? undefined,
18
+ elapsedMs: Date.now() - startedAt,
19
+ };
20
+ }
21
+ catch (err) {
22
+ return {
23
+ downloaded: false,
24
+ error: err instanceof Error ? err.message : String(err),
25
+ elapsedMs: Date.now() - startedAt,
26
+ };
27
+ }
28
+ }
@@ -0,0 +1,28 @@
1
+ import type { Page } from 'playwright-core';
2
+ export interface NetworkCaptureEntry {
3
+ kind: 'cdp';
4
+ url: string;
5
+ method: string;
6
+ requestHeaders?: Record<string, string>;
7
+ requestBodyKind?: string;
8
+ requestBodyPreview?: string;
9
+ requestBodyFullSize?: number;
10
+ requestBodyTruncated?: boolean;
11
+ responseStatus?: number;
12
+ responseContentType?: string;
13
+ responseHeaders?: Record<string, string>;
14
+ responsePreview?: string;
15
+ responseBodyFullSize?: number;
16
+ responseBodyTruncated?: boolean;
17
+ timestamp: number;
18
+ }
19
+ export declare class CloakNetworkCapture {
20
+ private readonly limit;
21
+ private readonly states;
22
+ constructor(limit?: number);
23
+ start(pattern: string, page: Page): void;
24
+ read(page: Page): Promise<NetworkCaptureEntry[]>;
25
+ stop(page: Page): void;
26
+ private captureResponse;
27
+ private bound;
28
+ }
@@ -0,0 +1,120 @@
1
+ const BODY_LIMIT = 8 * 1024 * 1024;
2
+ export class CloakNetworkCapture {
3
+ limit;
4
+ states = new WeakMap();
5
+ constructor(limit = 200) {
6
+ this.limit = limit;
7
+ }
8
+ start(pattern, page) {
9
+ this.stop(page);
10
+ const entries = [];
11
+ const byRequest = new WeakMap();
12
+ const pending = new Set();
13
+ const state = {
14
+ pattern,
15
+ entries,
16
+ byRequest,
17
+ pending,
18
+ onRequest: (request) => {
19
+ const url = request.url();
20
+ if (pattern && !url.includes(pattern))
21
+ return;
22
+ const body = request.postData() ?? undefined;
23
+ const entry = {
24
+ kind: 'cdp',
25
+ url,
26
+ method: request.method(),
27
+ requestHeaders: request.headers(),
28
+ requestBodyKind: body === undefined ? undefined : 'text',
29
+ requestBodyPreview: body === undefined ? undefined : body.slice(0, BODY_LIMIT),
30
+ requestBodyFullSize: body?.length,
31
+ requestBodyTruncated: body ? body.length > BODY_LIMIT : undefined,
32
+ timestamp: Date.now(),
33
+ };
34
+ entries.push(entry);
35
+ byRequest.set(request, entry);
36
+ this.bound(entries);
37
+ },
38
+ onResponse: (response) => {
39
+ const capture = this.captureResponse(response, pattern, entries, byRequest)
40
+ .finally(() => pending.delete(capture));
41
+ pending.add(capture);
42
+ },
43
+ };
44
+ page.on('request', state.onRequest);
45
+ page.on('response', state.onResponse);
46
+ this.states.set(page, state);
47
+ }
48
+ async read(page) {
49
+ const state = this.states.get(page);
50
+ if (!state)
51
+ return [];
52
+ await Promise.allSettled([...state.pending]);
53
+ return [...state.entries];
54
+ }
55
+ stop(page) {
56
+ const state = this.states.get(page);
57
+ if (!state)
58
+ return;
59
+ page.off('request', state.onRequest);
60
+ page.off('response', state.onResponse);
61
+ this.states.delete(page);
62
+ }
63
+ async captureResponse(response, pattern, entries, byRequest) {
64
+ const url = response.url();
65
+ if (pattern && !url.includes(pattern))
66
+ return;
67
+ const headers = response.headers();
68
+ const contentType = headers['content-type'];
69
+ let preview;
70
+ let fullSize;
71
+ let truncated;
72
+ const contentLength = Number(headers['content-length']);
73
+ if (Number.isFinite(contentLength) && contentLength >= 0)
74
+ fullSize = contentLength;
75
+ if (isTextLikeContentType(contentType)) {
76
+ try {
77
+ const text = await response.text();
78
+ fullSize = text.length;
79
+ truncated = text.length > BODY_LIMIT;
80
+ preview = text.slice(0, BODY_LIMIT);
81
+ }
82
+ catch {
83
+ preview = undefined;
84
+ }
85
+ }
86
+ const responseRequest = typeof response.request === 'function' ? response.request() : undefined;
87
+ const existing = responseRequest
88
+ ? byRequest.get(responseRequest)
89
+ : [...entries].reverse().find((entry) => entry.url === url && entry.responseStatus === undefined);
90
+ const target = existing ?? {
91
+ kind: 'cdp',
92
+ url,
93
+ method: 'GET',
94
+ timestamp: Date.now(),
95
+ };
96
+ target.responseStatus = response.status();
97
+ target.responseContentType = contentType;
98
+ target.responseHeaders = headers;
99
+ target.responsePreview = preview;
100
+ target.responseBodyFullSize = fullSize;
101
+ target.responseBodyTruncated = truncated;
102
+ if (!existing)
103
+ entries.push(target);
104
+ this.bound(entries);
105
+ }
106
+ bound(entries) {
107
+ while (entries.length > this.limit)
108
+ entries.shift();
109
+ }
110
+ }
111
+ function isTextLikeContentType(contentType) {
112
+ if (!contentType)
113
+ return false;
114
+ const normalized = contentType.toLowerCase();
115
+ return normalized.startsWith('text/')
116
+ || normalized.includes('json')
117
+ || normalized.includes('javascript')
118
+ || normalized.includes('xml')
119
+ || normalized.includes('x-www-form-urlencoded');
120
+ }
@@ -0,0 +1,124 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import { CloakNetworkCapture } from './network.js';
4
+ class FakePage extends EventEmitter {
5
+ off(event, listener) {
6
+ this.removeListener(event, listener);
7
+ return this;
8
+ }
9
+ }
10
+ describe('CloakNetworkCapture', () => {
11
+ it('captures matching request and response metadata with a bounded buffer', async () => {
12
+ const page = new FakePage();
13
+ const capture = new CloakNetworkCapture(2);
14
+ capture.start('api.example', page);
15
+ const req = {
16
+ url: () => 'https://api.example/items',
17
+ method: () => 'POST',
18
+ headers: () => ({ accept: 'application/json' }),
19
+ postData: () => '{"x":1}',
20
+ };
21
+ const res = {
22
+ url: () => 'https://api.example/items',
23
+ status: () => 200,
24
+ headers: () => ({ 'content-type': 'application/json' }),
25
+ text: async () => '{"ok":true}',
26
+ };
27
+ page.emit('request', req);
28
+ page.emit('response', res);
29
+ expect(await capture.read(page)).toEqual([expect.objectContaining({
30
+ kind: 'cdp',
31
+ url: 'https://api.example/items',
32
+ method: 'POST',
33
+ responseStatus: 200,
34
+ responsePreview: '{"ok":true}',
35
+ })]);
36
+ });
37
+ it('matches same-url responses to their exact request identity', async () => {
38
+ const page = new FakePage();
39
+ const capture = new CloakNetworkCapture(10);
40
+ capture.start('api.example', page);
41
+ const firstReq = {
42
+ url: () => 'https://api.example/items',
43
+ method: () => 'POST',
44
+ headers: () => ({ 'x-request': 'first' }),
45
+ postData: () => 'first',
46
+ };
47
+ const secondReq = {
48
+ url: () => 'https://api.example/items',
49
+ method: () => 'PUT',
50
+ headers: () => ({ 'x-request': 'second' }),
51
+ postData: () => 'second',
52
+ };
53
+ const firstRes = {
54
+ url: () => 'https://api.example/items',
55
+ request: () => firstReq,
56
+ status: () => 201,
57
+ headers: () => ({ 'content-type': 'application/json' }),
58
+ text: async () => '{"first":true}',
59
+ };
60
+ page.emit('request', firstReq);
61
+ page.emit('request', secondReq);
62
+ page.emit('response', firstRes);
63
+ const entries = await capture.read(page);
64
+ expect(entries).toEqual([
65
+ expect.objectContaining({
66
+ method: 'POST',
67
+ requestBodyPreview: 'first',
68
+ responseStatus: 201,
69
+ responsePreview: '{"first":true}',
70
+ }),
71
+ expect.objectContaining({
72
+ method: 'PUT',
73
+ requestBodyPreview: 'second',
74
+ }),
75
+ ]);
76
+ expect(entries[1]).not.toHaveProperty('responseStatus');
77
+ expect(entries[1]).not.toHaveProperty('responsePreview');
78
+ });
79
+ it('skips response body previews for non-text content types', async () => {
80
+ const page = new FakePage();
81
+ const capture = new CloakNetworkCapture(10);
82
+ capture.start('api.example', page);
83
+ const req = {
84
+ url: () => 'https://api.example/image.png',
85
+ method: () => 'GET',
86
+ headers: () => ({}),
87
+ postData: () => null,
88
+ };
89
+ const text = vi.fn(async () => 'binary-ish body');
90
+ const res = {
91
+ url: () => 'https://api.example/image.png',
92
+ request: () => req,
93
+ status: () => 200,
94
+ headers: () => ({ 'content-type': 'image/png', 'content-length': '15' }),
95
+ text,
96
+ };
97
+ page.emit('request', req);
98
+ page.emit('response', res);
99
+ expect(await capture.read(page)).toEqual([expect.objectContaining({
100
+ responseContentType: 'image/png',
101
+ responseBodyFullSize: 15,
102
+ responseBodyTruncated: undefined,
103
+ responsePreview: undefined,
104
+ })]);
105
+ expect(text).not.toHaveBeenCalled();
106
+ });
107
+ it('evicts older entries when the bounded buffer limit is exceeded', async () => {
108
+ const page = new FakePage();
109
+ const capture = new CloakNetworkCapture(2);
110
+ capture.start('api.example', page);
111
+ for (const id of ['one', 'two', 'three']) {
112
+ page.emit('request', {
113
+ url: () => `https://api.example/${id}`,
114
+ method: () => 'GET',
115
+ headers: () => ({}),
116
+ postData: () => null,
117
+ });
118
+ }
119
+ expect(await capture.read(page)).toEqual([
120
+ expect.objectContaining({ url: 'https://api.example/two' }),
121
+ expect.objectContaining({ url: 'https://api.example/three' }),
122
+ ]);
123
+ });
124
+ });
@@ -0,0 +1,6 @@
1
+ export interface CloakProfileDirOptions {
2
+ baseDir?: string;
3
+ }
4
+ export declare function normalizeProfileId(value: string | undefined | null): string;
5
+ export declare function getWebcmdConfigDir(): string;
6
+ export declare function resolveCloakProfileDir(profileId: string, opts?: CloakProfileDirOptions): string;
@@ -0,0 +1,17 @@
1
+ import path from 'node:path';
2
+ import { CONFIG_DIR_NAME, ENV_PREFIX } from '../../../brand.js';
3
+ import os from 'node:os';
4
+ export function normalizeProfileId(value) {
5
+ const id = value?.trim() || 'default';
6
+ if (!/^[A-Za-z0-9._-]+$/.test(id) || id === '.' || id === '..') {
7
+ throw new Error(`Invalid profile id: ${value ?? ''}`);
8
+ }
9
+ return id;
10
+ }
11
+ export function getWebcmdConfigDir() {
12
+ return process.env[`${ENV_PREFIX}_CONFIG_DIR`] || path.join(os.homedir(), CONFIG_DIR_NAME);
13
+ }
14
+ export function resolveCloakProfileDir(profileId, opts = {}) {
15
+ const safeProfileId = normalizeProfileId(profileId);
16
+ return path.join(opts.baseDir ?? getWebcmdConfigDir(), 'cloak', 'profiles', safeProfileId);
17
+ }
@@ -0,0 +1,19 @@
1
+ import path from 'node:path';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { normalizeProfileId, resolveCloakProfileDir } from './profiles.js';
4
+ describe('cloak profile resolution', () => {
5
+ it('normalizes empty profile ids to default', () => {
6
+ expect(normalizeProfileId(undefined)).toBe('default');
7
+ expect(normalizeProfileId('')).toBe('default');
8
+ expect(normalizeProfileId(' work ')).toBe('work');
9
+ });
10
+ it('rejects path traversal and separators', () => {
11
+ expect(() => normalizeProfileId('../x')).toThrow(/Invalid profile id/);
12
+ expect(() => normalizeProfileId('a/b')).toThrow(/Invalid profile id/);
13
+ expect(() => normalizeProfileId('a\\b')).toThrow(/Invalid profile id/);
14
+ });
15
+ it('resolves under the webcmd cloak profiles directory', () => {
16
+ expect(resolveCloakProfileDir('work', { baseDir: '/tmp/webcmd' }))
17
+ .toBe(path.join('/tmp/webcmd', 'cloak', 'profiles', 'work'));
18
+ });
19
+ });
@@ -0,0 +1,15 @@
1
+ import type { BrowserRuntimeCommand, BrowserRuntimeResult, BrowserRuntimeStatus } from '../../protocol.js';
2
+ import type { BrowserRuntimeProvider, RuntimeStatusOptions } from '../provider.js';
3
+ import type { LaunchPersistentContext } from './session-manager.js';
4
+ export interface LocalCloakRuntimeProviderOptions {
5
+ baseDir?: string;
6
+ launchPersistentContext?: LaunchPersistentContext;
7
+ }
8
+ export declare class LocalCloakRuntimeProvider implements BrowserRuntimeProvider {
9
+ private readonly opts;
10
+ private readonly manager;
11
+ constructor(opts?: LocalCloakRuntimeProviderOptions);
12
+ status(_opts?: RuntimeStatusOptions): Promise<BrowserRuntimeStatus>;
13
+ dispatch(command: BrowserRuntimeCommand): Promise<BrowserRuntimeResult>;
14
+ shutdown(): Promise<void>;
15
+ }
@@ -0,0 +1,27 @@
1
+ import { dispatchCloakAction } from './actions.js';
2
+ import { CloakSessionManager } from './session-manager.js';
3
+ export class LocalCloakRuntimeProvider {
4
+ opts;
5
+ manager;
6
+ constructor(opts = {}) {
7
+ this.opts = opts;
8
+ this.manager = new CloakSessionManager(opts);
9
+ }
10
+ async status(_opts = {}) {
11
+ const profiles = this.manager.profileStatuses();
12
+ return {
13
+ runtimeConnected: true,
14
+ runtimeName: 'cloak',
15
+ runtimeVersion: undefined,
16
+ profiles,
17
+ pending: 0,
18
+ commandResultUnknown: 0,
19
+ };
20
+ }
21
+ async dispatch(command) {
22
+ return dispatchCloakAction(this.manager, command);
23
+ }
24
+ async shutdown() {
25
+ await this.manager.shutdown();
26
+ }
27
+ }