@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,121 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
2
+ import * as fs from 'node:fs';
3
+ import * as os from 'node:os';
4
+ import * as path from 'node:path';
5
+ import { buildTraceReceipt, exportObservationSession, getTraceDirectory } from './artifact.js';
6
+ import { ObservationSession } from './session.js';
7
+ describe('observation artifact', () => {
8
+ let baseDir;
9
+ beforeEach(() => {
10
+ baseDir = fs.mkdtempSync(path.join(os.tmpdir(), 'webcmd-trace-'));
11
+ });
12
+ afterEach(() => {
13
+ fs.rmSync(baseDir, { recursive: true, force: true });
14
+ });
15
+ it('writes artifacts under profile-scoped trace directory', () => {
16
+ const session = new ObservationSession({
17
+ id: 'trace-1',
18
+ scope: {
19
+ contextId: 'work',
20
+ session: 'site:demo',
21
+ site: 'demo',
22
+ command: 'demo/run',
23
+ adapterSourcePath: '/tmp/clis/demo/run.js',
24
+ },
25
+ now: () => 1_700_000_000_000,
26
+ });
27
+ session.record({ stream: 'action', name: 'command', phase: 'start' });
28
+ session.record({ stream: 'screenshot', format: 'png', data: Buffer.from('png-bytes').toString('base64'), label: 'final' });
29
+ session.record({
30
+ stream: 'network',
31
+ url: 'https://api.test/data?token=secret',
32
+ method: 'GET',
33
+ status: 500,
34
+ requestHeaders: { authorization: 'Bearer secret' },
35
+ responseBody: { ok: false },
36
+ });
37
+ session.record({ stream: 'console', level: 'error', text: 'boom password=supersecret' });
38
+ const result = exportObservationSession(session, { baseDir, error: new Error('failed') });
39
+ expect(result.dir).toBe(getTraceDirectory('work', 'trace-1', baseDir));
40
+ expect(fs.existsSync(path.join(result.dir, 'trace.jsonl'))).toBe(true);
41
+ expect(fs.existsSync(path.join(result.dir, 'network.jsonl'))).toBe(true);
42
+ expect(fs.existsSync(path.join(result.dir, 'console.jsonl'))).toBe(true);
43
+ expect(fs.existsSync(result.receiptPath)).toBe(true);
44
+ expect(fs.readFileSync(path.join(result.dir, 'screenshots', '0001.png'), 'utf-8')).toBe('png-bytes');
45
+ const trace = fs.readFileSync(path.join(result.dir, 'trace.jsonl'), 'utf-8');
46
+ expect(trace).toContain('token=[REDACTED]');
47
+ expect(trace).toContain('"authorization":"[REDACTED]"');
48
+ expect(trace).not.toContain('supersecret');
49
+ const summary = fs.readFileSync(result.summaryPath, 'utf-8');
50
+ expect(summary).toContain('schemaVersion: 1');
51
+ expect(summary).toContain('webcmdVersion:');
52
+ expect(summary).toContain('expiresAt:');
53
+ expect(summary).toContain('status: failure');
54
+ expect(summary).toContain('contextId: "work"');
55
+ expect(summary).toContain('adapterSourcePath: "/tmp/clis/demo/run.js"');
56
+ expect(summary).toContain('adapterSourcePathExists: false');
57
+ expect(summary).toContain('## Failed Network');
58
+ expect(summary).toContain('500 GET https://api.test/data?token=[REDACTED]');
59
+ expect(summary).toContain('network: 1');
60
+ const receipt = JSON.parse(fs.readFileSync(result.receiptPath, 'utf-8'));
61
+ expect(receipt).toMatchObject({
62
+ schemaVersion: 1,
63
+ webcmdVersion: expect.any(String),
64
+ traceId: 'trace-1',
65
+ traceDir: result.dir,
66
+ summaryPath: result.summaryPath,
67
+ receiptPath: result.receiptPath,
68
+ status: 'failure',
69
+ expiresAt: expect.any(String),
70
+ scope: {
71
+ contextId: 'work',
72
+ session: 'site:demo',
73
+ site: 'demo',
74
+ command: 'demo/run',
75
+ adapterSourcePath: '/tmp/clis/demo/run.js',
76
+ },
77
+ error: { message: 'failed' },
78
+ });
79
+ });
80
+ it('builds a compact trace receipt', () => {
81
+ const receipt = buildTraceReceipt({
82
+ traceId: 'trace-1',
83
+ dir: '/tmp/webcmd/profiles/work/traces/trace-1',
84
+ summaryPath: '/tmp/webcmd/profiles/work/traces/trace-1/summary.md',
85
+ receiptPath: '/tmp/webcmd/profiles/work/traces/trace-1/receipt.json',
86
+ }, 'failure', new Error('failed with token=secret'), {
87
+ createdAt: '2026-05-03T00:00:00.000Z',
88
+ retentionPolicy: { maxAgeDays: 7 },
89
+ });
90
+ expect(receipt).toMatchObject({
91
+ schemaVersion: 1,
92
+ webcmdVersion: expect.any(String),
93
+ traceId: 'trace-1',
94
+ traceDir: '/tmp/webcmd/profiles/work/traces/trace-1',
95
+ receiptPath: '/tmp/webcmd/profiles/work/traces/trace-1/receipt.json',
96
+ status: 'failure',
97
+ expiresAt: '2026-05-10T00:00:00.000Z',
98
+ });
99
+ expect(receipt.error?.message).toContain('token=[REDACTED]');
100
+ });
101
+ it('prunes older traces after export while protecting the exported trace', () => {
102
+ const oldTraceDir = getTraceDirectory('work', 'old-trace', baseDir);
103
+ fs.mkdirSync(oldTraceDir, { recursive: true });
104
+ fs.writeFileSync(path.join(oldTraceDir, 'receipt.json'), JSON.stringify({
105
+ createdAt: '2026-04-01T00:00:00.000Z',
106
+ }), 'utf-8');
107
+ fs.writeFileSync(path.join(oldTraceDir, 'trace.jsonl'), '{}\n', 'utf-8');
108
+ const session = new ObservationSession({
109
+ id: 'new-trace',
110
+ scope: { contextId: 'work', session: 'site:demo' },
111
+ now: () => Date.parse('2026-05-03T00:00:00.000Z'),
112
+ });
113
+ session.record({ stream: 'action', name: 'command', phase: 'start' });
114
+ const result = exportObservationSession(session, {
115
+ baseDir,
116
+ retentionPolicy: { maxAgeDays: 365, maxCountPerProfile: 1, maxBytesPerProfile: '500MB' },
117
+ });
118
+ expect(fs.existsSync(oldTraceDir)).toBe(false);
119
+ expect(fs.existsSync(result.dir)).toBe(true);
120
+ });
121
+ });
@@ -0,0 +1,89 @@
1
+ export type ObservationStream = 'action' | 'network' | 'console' | 'screenshot' | 'state' | 'error';
2
+ export interface ObservationScope {
3
+ contextId?: string;
4
+ session: string;
5
+ target?: string;
6
+ site?: string;
7
+ command?: string;
8
+ adapterSourcePath?: string;
9
+ }
10
+ interface BaseObservationEvent {
11
+ id: string;
12
+ ts: number;
13
+ stream: ObservationStream;
14
+ }
15
+ export interface ActionObservationEvent extends BaseObservationEvent {
16
+ stream: 'action';
17
+ name: string;
18
+ phase?: 'start' | 'end' | 'error';
19
+ data?: Record<string, unknown>;
20
+ }
21
+ export interface NetworkObservationEvent extends BaseObservationEvent {
22
+ stream: 'network';
23
+ url: string;
24
+ method?: string;
25
+ status?: number;
26
+ contentType?: string;
27
+ size?: number;
28
+ requestHeaders?: Record<string, unknown>;
29
+ responseHeaders?: Record<string, unknown>;
30
+ requestBody?: unknown;
31
+ responseBody?: unknown;
32
+ }
33
+ export interface ConsoleObservationEvent extends BaseObservationEvent {
34
+ stream: 'console';
35
+ level: string;
36
+ text: string;
37
+ source?: string;
38
+ }
39
+ export interface ScreenshotObservationEvent extends BaseObservationEvent {
40
+ stream: 'screenshot';
41
+ format: 'png' | 'jpeg';
42
+ data: string;
43
+ label?: string;
44
+ }
45
+ export interface StateObservationEvent extends BaseObservationEvent {
46
+ stream: 'state';
47
+ url?: string | null;
48
+ target?: string;
49
+ snapshot?: unknown;
50
+ label?: string;
51
+ }
52
+ export interface ErrorObservationEvent extends BaseObservationEvent {
53
+ stream: 'error';
54
+ code?: string;
55
+ message: string;
56
+ stack?: string;
57
+ hint?: string;
58
+ }
59
+ export type ObservationEvent = ActionObservationEvent | NetworkObservationEvent | ConsoleObservationEvent | ScreenshotObservationEvent | StateObservationEvent | ErrorObservationEvent;
60
+ export type ObservationEventInput = ObservationEvent extends infer T ? T extends ObservationEvent ? Omit<T, 'id' | 'ts'> & Partial<Pick<T, 'id' | 'ts'>> : never : never;
61
+ export interface ObservationExportResult {
62
+ traceId: string;
63
+ dir: string;
64
+ summaryPath: string;
65
+ receiptPath: string;
66
+ receipt: ObservationTraceReceipt;
67
+ }
68
+ export type ObservationExportStatus = 'success' | 'failure';
69
+ export interface ObservationTraceReceipt {
70
+ schemaVersion: 1;
71
+ webcmdVersion: string;
72
+ traceId: string;
73
+ traceDir: string;
74
+ summaryPath: string;
75
+ receiptPath: string;
76
+ status: ObservationExportStatus;
77
+ createdAt: string;
78
+ /** Advisory only; actual deletion is governed by current trace retention budgets. */
79
+ expiresAt?: string;
80
+ scope?: ObservationScope;
81
+ error?: {
82
+ name?: string;
83
+ code?: string;
84
+ message: string;
85
+ hint?: string;
86
+ exitCode?: number;
87
+ };
88
+ }
89
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ export * from './events.js';
2
+ export * from './ring-buffer.js';
3
+ export * from './redaction.js';
4
+ export * from './session.js';
5
+ export * from './manager.js';
6
+ export * from './artifact.js';
7
+ export * from './retention.js';
@@ -0,0 +1,7 @@
1
+ export * from './events.js';
2
+ export * from './ring-buffer.js';
3
+ export * from './redaction.js';
4
+ export * from './session.js';
5
+ export * from './manager.js';
6
+ export * from './artifact.js';
7
+ export * from './retention.js';
@@ -0,0 +1,9 @@
1
+ import { ObservationSession, type ObservationSessionOptions } from './session.js';
2
+ import type { ObservationScope } from './events.js';
3
+ export declare class ObservationManager {
4
+ private readonly sessions;
5
+ start(opts: ObservationSessionOptions): ObservationSession;
6
+ get(id: string): ObservationSession | undefined;
7
+ stop(id: string): ObservationSession | undefined;
8
+ findByScope(scope: ObservationScope): ObservationSession[];
9
+ }
@@ -0,0 +1,27 @@
1
+ import { ObservationSession } from './session.js';
2
+ export class ObservationManager {
3
+ sessions = new Map();
4
+ start(opts) {
5
+ const session = new ObservationSession(opts);
6
+ this.sessions.set(session.id, session);
7
+ return session;
8
+ }
9
+ get(id) {
10
+ return this.sessions.get(id);
11
+ }
12
+ stop(id) {
13
+ const session = this.sessions.get(id);
14
+ this.sessions.delete(id);
15
+ return session;
16
+ }
17
+ findByScope(scope) {
18
+ return [...this.sessions.values()].filter((session) => scopeMatches(session.scope, scope));
19
+ }
20
+ }
21
+ function scopeMatches(actual, expected) {
22
+ return actual.session === expected.session
23
+ && (expected.contextId === undefined || actual.contextId === expected.contextId)
24
+ && (expected.target === undefined || actual.target === expected.target)
25
+ && (expected.site === undefined || actual.site === expected.site)
26
+ && (expected.command === undefined || actual.command === expected.command);
27
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { ObservationManager } from './manager.js';
3
+ describe('ObservationManager', () => {
4
+ it('indexes sessions by id and scope', () => {
5
+ const manager = new ObservationManager();
6
+ const work = manager.start({ id: 'work-1', scope: { contextId: 'work', session: 'site:x', target: 'tab-1' } });
7
+ manager.start({ id: 'personal-1', scope: { contextId: 'personal', session: 'site:x', target: 'tab-2' } });
8
+ expect(manager.get('work-1')).toBe(work);
9
+ expect(manager.findByScope({ contextId: 'work', session: 'site:x' }).map((session) => session.id)).toEqual(['work-1']);
10
+ expect(manager.stop('work-1')).toBe(work);
11
+ expect(manager.get('work-1')).toBeUndefined();
12
+ });
13
+ });
@@ -0,0 +1,11 @@
1
+ export interface RedactionOptions {
2
+ allowlist?: string[];
3
+ maxStringLength?: number;
4
+ maxDepth?: number;
5
+ maxArrayItems?: number;
6
+ maxObjectFields?: number;
7
+ }
8
+ export declare function redactUrl(url: string): string;
9
+ export declare function redactHeaders(headers: Record<string, unknown> | undefined, opts?: RedactionOptions): Record<string, unknown> | undefined;
10
+ export declare function redactText(text: string, opts?: RedactionOptions): string;
11
+ export declare function redactValue(value: unknown, opts?: RedactionOptions, keyHint?: string, depth?: number): unknown;
@@ -0,0 +1,81 @@
1
+ const DEFAULT_REDACTION = '[REDACTED]';
2
+ const SENSITIVE_HEADER_NAMES = new Set([
3
+ 'authorization',
4
+ 'cookie',
5
+ 'set-cookie',
6
+ 'proxy-authorization',
7
+ 'x-api-key',
8
+ 'x-auth-token',
9
+ 'x-csrf-token',
10
+ 'x-xsrf-token',
11
+ ]);
12
+ const SENSITIVE_FIELD_PATTERN = /(password|passwd|pwd|token|secret|authorization|cookie|set-cookie|api[_-]?key|access[_-]?token|refresh[_-]?token|session[_-]?id|csrf|xsrf)/i;
13
+ const SENSITIVE_URL_PARAMS = /([?&])(token|key|secret|password|auth|access_token|api_key|session_id|csrf|xsrf)=[^&]*/gi;
14
+ export function redactUrl(url) {
15
+ return url.replace(SENSITIVE_URL_PARAMS, '$1$2=[REDACTED]');
16
+ }
17
+ export function redactHeaders(headers, opts = {}) {
18
+ if (!headers)
19
+ return headers;
20
+ const allow = new Set((opts.allowlist ?? []).map((key) => key.toLowerCase()));
21
+ const out = {};
22
+ for (const [key, value] of Object.entries(headers)) {
23
+ const lower = key.toLowerCase();
24
+ out[key] = SENSITIVE_HEADER_NAMES.has(lower) && !allow.has(lower)
25
+ ? DEFAULT_REDACTION
26
+ : redactValue(value, opts, key);
27
+ }
28
+ return out;
29
+ }
30
+ export function redactText(text, opts = {}) {
31
+ const max = opts.maxStringLength ?? 50_000;
32
+ let out = text
33
+ .replace(/Bearer\s+[A-Za-z0-9\-._~+/]+=*/gi, 'Bearer [REDACTED]')
34
+ .replace(/(["'])(password|passwd|pwd|token|secret|api_key|apikey|access_token|session_id)\1\s*:\s*(["'])(.*?)\3/gi, '$1$2$1:$3[REDACTED]$3')
35
+ .replace(/(token|secret|password|api_key|apikey|access_token|session_id)[=:]\s*['"]?[^'"\s,;}&]+['"]?/gi, '$1=[REDACTED]')
36
+ .replace(/(cookie[=:]\s*)[^\n;]{3,}/gi, '$1[REDACTED]')
37
+ .replace(/eyJ[A-Za-z0-9_-]{10,}\.eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}/g, '[REDACTED_JWT]');
38
+ if (out.length > max)
39
+ out = out.slice(0, max) + `\n...[truncated, ${out.length - max} chars omitted]`;
40
+ return out;
41
+ }
42
+ export function redactValue(value, opts = {}, keyHint, depth = 0) {
43
+ const allow = new Set((opts.allowlist ?? []).map((key) => key.toLowerCase()));
44
+ if (keyHint && SENSITIVE_FIELD_PATTERN.test(keyHint) && !allow.has(keyHint.toLowerCase())) {
45
+ return DEFAULT_REDACTION;
46
+ }
47
+ if (typeof value === 'string') {
48
+ return keyHint === 'url' ? redactUrl(value) : redactText(value, opts);
49
+ }
50
+ if (value === null || typeof value === 'number' || typeof value === 'boolean')
51
+ return value;
52
+ const maxDepth = opts.maxDepth ?? 5;
53
+ if (depth >= maxDepth)
54
+ return '[truncated: max depth reached]';
55
+ if (Array.isArray(value)) {
56
+ const max = opts.maxArrayItems ?? 100;
57
+ const items = value.slice(0, max).map((item) => redactValue(item, opts, undefined, depth + 1));
58
+ if (value.length > max)
59
+ items.push(`[truncated, ${value.length - max} items omitted]`);
60
+ return items;
61
+ }
62
+ if (typeof value === 'object') {
63
+ const entries = Object.entries(value);
64
+ const max = opts.maxObjectFields ?? 100;
65
+ const out = {};
66
+ for (const [key, child] of entries.slice(0, max)) {
67
+ if (key.toLowerCase() === 'url' && typeof child === 'string')
68
+ out[key] = redactUrl(child);
69
+ else if (key.toLowerCase().includes('headers') && child && typeof child === 'object' && !Array.isArray(child)) {
70
+ out[key] = redactHeaders(child, opts);
71
+ }
72
+ else {
73
+ out[key] = redactValue(child, opts, key, depth + 1);
74
+ }
75
+ }
76
+ if (entries.length > max)
77
+ out.__truncated__ = `[${entries.length - max} fields omitted]`;
78
+ return out;
79
+ }
80
+ return value;
81
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,32 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { redactHeaders, redactUrl, redactValue } from './redaction.js';
3
+ describe('observation redaction', () => {
4
+ it('redacts sensitive headers by default', () => {
5
+ expect(redactHeaders({
6
+ authorization: 'Bearer secret-token',
7
+ cookie: 'sid=abc',
8
+ 'set-cookie': 'sid=abc',
9
+ accept: 'application/json',
10
+ })).toEqual({
11
+ authorization: '[REDACTED]',
12
+ cookie: '[REDACTED]',
13
+ 'set-cookie': '[REDACTED]',
14
+ accept: 'application/json',
15
+ });
16
+ });
17
+ it('redacts sensitive url query params', () => {
18
+ expect(redactUrl('https://x.test/api?token=abc&ok=1&password=secret'))
19
+ .toBe('https://x.test/api?token=[REDACTED]&ok=1&password=[REDACTED]');
20
+ });
21
+ it('redacts password and token fields recursively', () => {
22
+ expect(redactValue({
23
+ user: 'alice',
24
+ password: 'secret',
25
+ nested: { access_token: 'abc123456789', value: 'safe' },
26
+ })).toEqual({
27
+ user: 'alice',
28
+ password: '[REDACTED]',
29
+ nested: { access_token: '[REDACTED]', value: 'safe' },
30
+ });
31
+ });
32
+ });
@@ -0,0 +1,32 @@
1
+ export interface TraceRetentionPolicyInput {
2
+ maxAgeDays?: number;
3
+ maxCountPerProfile?: number;
4
+ maxBytesPerProfile?: string | number;
5
+ }
6
+ export interface ResolvedTraceRetentionPolicy {
7
+ maxAgeDays: number;
8
+ maxAgeMs: number;
9
+ maxCountPerProfile: number;
10
+ maxBytesPerProfile: number;
11
+ }
12
+ export interface TraceRetentionPruneResult {
13
+ scanned: number;
14
+ deleted: string[];
15
+ kept: string[];
16
+ totalBytesBefore: number;
17
+ totalBytesAfter: number;
18
+ }
19
+ export declare const DEFAULT_TRACE_RETENTION_POLICY: {
20
+ maxAgeDays: number;
21
+ maxCountPerProfile: number;
22
+ maxBytesPerProfile: string;
23
+ };
24
+ export declare function parseByteSize(value: string | number): number;
25
+ export declare function resolveTraceRetentionPolicy(input?: TraceRetentionPolicyInput): ResolvedTraceRetentionPolicy;
26
+ export declare function traceExpiresAt(createdAt: string, policyInput?: TraceRetentionPolicyInput): string;
27
+ export declare function pruneTraceArtifacts(tracesDir: string, opts?: {
28
+ policy?: TraceRetentionPolicyInput;
29
+ protectedTraceDirs?: string[];
30
+ now?: () => number;
31
+ warn?: (message: string) => void;
32
+ }): TraceRetentionPruneResult;
@@ -0,0 +1,160 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { log } from '../logger.js';
4
+ export const DEFAULT_TRACE_RETENTION_POLICY = {
5
+ maxAgeDays: 7,
6
+ maxCountPerProfile: 20,
7
+ maxBytesPerProfile: '500MB',
8
+ };
9
+ const BYTES_UNITS = {
10
+ B: 1,
11
+ KB: 1024,
12
+ MB: 1024 ** 2,
13
+ GB: 1024 ** 3,
14
+ };
15
+ export function parseByteSize(value) {
16
+ if (typeof value === 'number') {
17
+ if (!Number.isFinite(value) || value < 0)
18
+ throw new Error(`Invalid byte size: ${value}`);
19
+ return Math.floor(value);
20
+ }
21
+ const match = value.trim().match(/^(\d+(?:\.\d+)?)\s*(B|KB|MB|GB)?$/i);
22
+ if (!match)
23
+ throw new Error(`Invalid byte size: ${value}`);
24
+ const amount = Number(match[1]);
25
+ const unit = (match[2] ?? 'B').toUpperCase();
26
+ return Math.floor(amount * BYTES_UNITS[unit]);
27
+ }
28
+ export function resolveTraceRetentionPolicy(input = {}) {
29
+ const maxAgeDays = input.maxAgeDays ?? DEFAULT_TRACE_RETENTION_POLICY.maxAgeDays;
30
+ const maxCountPerProfile = input.maxCountPerProfile ?? DEFAULT_TRACE_RETENTION_POLICY.maxCountPerProfile;
31
+ if (!Number.isFinite(maxAgeDays) || maxAgeDays < 0)
32
+ throw new Error(`Invalid trace maxAgeDays: ${maxAgeDays}`);
33
+ if (!Number.isInteger(maxCountPerProfile) || maxCountPerProfile < 0) {
34
+ throw new Error(`Invalid trace maxCountPerProfile: ${maxCountPerProfile}`);
35
+ }
36
+ return {
37
+ maxAgeDays,
38
+ maxAgeMs: maxAgeDays * 24 * 60 * 60 * 1000,
39
+ maxCountPerProfile,
40
+ maxBytesPerProfile: parseByteSize(input.maxBytesPerProfile ?? DEFAULT_TRACE_RETENTION_POLICY.maxBytesPerProfile),
41
+ };
42
+ }
43
+ export function traceExpiresAt(createdAt, policyInput = {}) {
44
+ const policy = resolveTraceRetentionPolicy(policyInput);
45
+ const createdAtMs = Date.parse(createdAt);
46
+ const base = Number.isFinite(createdAtMs) ? createdAtMs : Date.now();
47
+ return new Date(base + policy.maxAgeMs).toISOString();
48
+ }
49
+ export function pruneTraceArtifacts(tracesDir, opts = {}) {
50
+ const warn = opts.warn ?? ((message) => log.warn(`[trace] ${message}`));
51
+ const policy = resolveTraceRetentionPolicy(opts.policy);
52
+ const now = opts.now ?? Date.now;
53
+ const protectedDirs = new Set((opts.protectedTraceDirs ?? []).map((dir) => path.resolve(dir)));
54
+ const entries = readTraceEntries(tracesDir, protectedDirs, warn);
55
+ const totalBytesBefore = entries.reduce((sum, entry) => sum + entry.sizeBytes, 0);
56
+ const deleted = new Set();
57
+ const sorted = [...entries].sort((a, b) => a.createdAtMs - b.createdAtMs || a.dir.localeCompare(b.dir));
58
+ const cutoff = now() - policy.maxAgeMs;
59
+ for (const entry of sorted) {
60
+ if (!entry.protected && entry.createdAtMs < cutoff)
61
+ deleted.add(entry.dir);
62
+ }
63
+ let remaining = sorted.filter((entry) => !deleted.has(entry.dir));
64
+ while (remaining.length > policy.maxCountPerProfile) {
65
+ const victim = remaining.find((entry) => !entry.protected);
66
+ if (!victim)
67
+ break;
68
+ deleted.add(victim.dir);
69
+ remaining = remaining.filter((entry) => entry.dir !== victim.dir);
70
+ }
71
+ let remainingBytes = remaining.reduce((sum, entry) => sum + entry.sizeBytes, 0);
72
+ while (remainingBytes > policy.maxBytesPerProfile) {
73
+ const victim = remaining.find((entry) => !entry.protected);
74
+ if (!victim)
75
+ break;
76
+ deleted.add(victim.dir);
77
+ remaining = remaining.filter((entry) => entry.dir !== victim.dir);
78
+ remainingBytes -= victim.sizeBytes;
79
+ }
80
+ const deletedDirs = [];
81
+ for (const dir of sorted.map((entry) => entry.dir).filter((dir) => deleted.has(dir))) {
82
+ try {
83
+ fs.rmSync(dir, { recursive: true, force: true });
84
+ deletedDirs.push(dir);
85
+ }
86
+ catch (err) {
87
+ warn(`Failed to prune trace artifact ${dir}: ${err instanceof Error ? err.message : String(err)}`);
88
+ }
89
+ }
90
+ const keptEntries = entries.filter((entry) => !deletedDirs.includes(entry.dir));
91
+ return {
92
+ scanned: entries.length,
93
+ deleted: deletedDirs,
94
+ kept: keptEntries.map((entry) => entry.dir),
95
+ totalBytesBefore,
96
+ totalBytesAfter: keptEntries.reduce((sum, entry) => sum + entry.sizeBytes, 0),
97
+ };
98
+ }
99
+ function readTraceEntries(tracesDir, protectedDirs, warn) {
100
+ let names;
101
+ try {
102
+ names = fs.readdirSync(tracesDir);
103
+ }
104
+ catch (err) {
105
+ if (isEnoent(err))
106
+ return [];
107
+ warn(`Failed to list trace artifacts in ${tracesDir}: ${err instanceof Error ? err.message : String(err)}`);
108
+ return [];
109
+ }
110
+ const entries = [];
111
+ for (const name of names) {
112
+ const dir = path.join(tracesDir, name);
113
+ try {
114
+ const stat = fs.statSync(dir);
115
+ if (!stat.isDirectory())
116
+ continue;
117
+ entries.push({
118
+ dir,
119
+ createdAtMs: readCreatedAtMs(dir, stat.mtimeMs),
120
+ sizeBytes: directorySize(dir),
121
+ protected: protectedDirs.has(path.resolve(dir)),
122
+ });
123
+ }
124
+ catch (err) {
125
+ if (!isEnoent(err)) {
126
+ warn(`Failed to inspect trace artifact ${dir}: ${err instanceof Error ? err.message : String(err)}`);
127
+ }
128
+ }
129
+ }
130
+ return entries;
131
+ }
132
+ function readCreatedAtMs(dir, fallbackMs) {
133
+ try {
134
+ const receipt = JSON.parse(fs.readFileSync(path.join(dir, 'receipt.json'), 'utf-8'));
135
+ if (typeof receipt.createdAt === 'string') {
136
+ const parsed = Date.parse(receipt.createdAt);
137
+ if (Number.isFinite(parsed))
138
+ return parsed;
139
+ }
140
+ }
141
+ catch {
142
+ // Older or hand-edited trace directories may not have a receipt.
143
+ }
144
+ return fallbackMs;
145
+ }
146
+ function directorySize(dir) {
147
+ let total = 0;
148
+ for (const name of fs.readdirSync(dir)) {
149
+ const item = path.join(dir, name);
150
+ const stat = fs.lstatSync(item);
151
+ if (stat.isDirectory())
152
+ total += directorySize(item);
153
+ else
154
+ total += stat.size;
155
+ }
156
+ return total;
157
+ }
158
+ function isEnoent(err) {
159
+ return typeof err === 'object' && err !== null && 'code' in err && err.code === 'ENOENT';
160
+ }
@@ -0,0 +1 @@
1
+ export {};