@reticlehq/server 2.0.0

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 (483) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +17 -0
  3. package/dist/bridge-security.d.ts +23 -0
  4. package/dist/bridge-security.d.ts.map +1 -0
  5. package/dist/bridge-security.js +44 -0
  6. package/dist/bridge-security.js.map +1 -0
  7. package/dist/bridge.d.ts +42 -0
  8. package/dist/bridge.d.ts.map +1 -0
  9. package/dist/bridge.js +281 -0
  10. package/dist/bridge.js.map +1 -0
  11. package/dist/bridge.test-harness.d.ts +42 -0
  12. package/dist/bridge.test-harness.d.ts.map +1 -0
  13. package/dist/bridge.test-harness.js +192 -0
  14. package/dist/bridge.test-harness.js.map +1 -0
  15. package/dist/cli-launch.d.ts +53 -0
  16. package/dist/cli-launch.d.ts.map +1 -0
  17. package/dist/cli-launch.js +109 -0
  18. package/dist/cli-launch.js.map +1 -0
  19. package/dist/cli-parse.d.ts +74 -0
  20. package/dist/cli-parse.d.ts.map +1 -0
  21. package/dist/cli-parse.js +321 -0
  22. package/dist/cli-parse.js.map +1 -0
  23. package/dist/cli-port.d.ts +26 -0
  24. package/dist/cli-port.d.ts.map +1 -0
  25. package/dist/cli-port.js +57 -0
  26. package/dist/cli-port.js.map +1 -0
  27. package/dist/cli-verify.d.ts +46 -0
  28. package/dist/cli-verify.d.ts.map +1 -0
  29. package/dist/cli-verify.js +181 -0
  30. package/dist/cli-verify.js.map +1 -0
  31. package/dist/cli.d.ts +6 -0
  32. package/dist/cli.d.ts.map +1 -0
  33. package/dist/cli.js +337 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/cloud/cloud-sync.d.ts +50 -0
  36. package/dist/cloud/cloud-sync.d.ts.map +1 -0
  37. package/dist/cloud/cloud-sync.js +47 -0
  38. package/dist/cloud/cloud-sync.js.map +1 -0
  39. package/dist/crawl/crawl-tools.d.ts +8 -0
  40. package/dist/crawl/crawl-tools.d.ts.map +1 -0
  41. package/dist/crawl/crawl-tools.js +61 -0
  42. package/dist/crawl/crawl-tools.js.map +1 -0
  43. package/dist/crawl/crawl.d.ts +45 -0
  44. package/dist/crawl/crawl.d.ts.map +1 -0
  45. package/dist/crawl/crawl.js +106 -0
  46. package/dist/crawl/crawl.js.map +1 -0
  47. package/dist/daemon-resilience.d.ts +17 -0
  48. package/dist/daemon-resilience.d.ts.map +1 -0
  49. package/dist/daemon-resilience.js +23 -0
  50. package/dist/daemon-resilience.js.map +1 -0
  51. package/dist/daemon.d.ts +26 -0
  52. package/dist/daemon.d.ts.map +1 -0
  53. package/dist/daemon.js +122 -0
  54. package/dist/daemon.js.map +1 -0
  55. package/dist/domain/domain-model.d.ts +64 -0
  56. package/dist/domain/domain-model.d.ts.map +1 -0
  57. package/dist/domain/domain-model.js +127 -0
  58. package/dist/domain/domain-model.js.map +1 -0
  59. package/dist/domain/domain-tools.d.ts +9 -0
  60. package/dist/domain/domain-tools.d.ts.map +1 -0
  61. package/dist/domain/domain-tools.js +66 -0
  62. package/dist/domain/domain-tools.js.map +1 -0
  63. package/dist/domain/flow-risk.d.ts +34 -0
  64. package/dist/domain/flow-risk.d.ts.map +1 -0
  65. package/dist/domain/flow-risk.js +81 -0
  66. package/dist/domain/flow-risk.js.map +1 -0
  67. package/dist/ee/audit-log.d.ts +15 -0
  68. package/dist/ee/audit-log.d.ts.map +1 -0
  69. package/dist/ee/audit-log.js +12 -0
  70. package/dist/ee/audit-log.js.map +1 -0
  71. package/dist/events/event-filters.d.ts +65 -0
  72. package/dist/events/event-filters.d.ts.map +1 -0
  73. package/dist/events/event-filters.js +98 -0
  74. package/dist/events/event-filters.js.map +1 -0
  75. package/dist/events/predicate-eval.d.ts +91 -0
  76. package/dist/events/predicate-eval.d.ts.map +1 -0
  77. package/dist/events/predicate-eval.js +299 -0
  78. package/dist/events/predicate-eval.js.map +1 -0
  79. package/dist/events/predicate.d.ts +19 -0
  80. package/dist/events/predicate.d.ts.map +1 -0
  81. package/dist/events/predicate.js +188 -0
  82. package/dist/events/predicate.js.map +1 -0
  83. package/dist/events/reaction.d.ts +34 -0
  84. package/dist/events/reaction.d.ts.map +1 -0
  85. package/dist/events/reaction.js +60 -0
  86. package/dist/events/reaction.js.map +1 -0
  87. package/dist/events/ring-buffer.d.ts +32 -0
  88. package/dist/events/ring-buffer.d.ts.map +1 -0
  89. package/dist/events/ring-buffer.js +75 -0
  90. package/dist/events/ring-buffer.js.map +1 -0
  91. package/dist/flows/annotate-tools.d.ts +16 -0
  92. package/dist/flows/annotate-tools.d.ts.map +1 -0
  93. package/dist/flows/annotate-tools.js +136 -0
  94. package/dist/flows/annotate-tools.js.map +1 -0
  95. package/dist/flows/annotate.d.ts +22 -0
  96. package/dist/flows/annotate.d.ts.map +1 -0
  97. package/dist/flows/annotate.js +134 -0
  98. package/dist/flows/annotate.js.map +1 -0
  99. package/dist/flows/annotation-store.d.ts +23 -0
  100. package/dist/flows/annotation-store.d.ts.map +1 -0
  101. package/dist/flows/annotation-store.js +51 -0
  102. package/dist/flows/annotation-store.js.map +1 -0
  103. package/dist/flows/decision.d.ts +13 -0
  104. package/dist/flows/decision.d.ts.map +1 -0
  105. package/dist/flows/decision.js +111 -0
  106. package/dist/flows/decision.js.map +1 -0
  107. package/dist/flows/flow-classify.d.ts +52 -0
  108. package/dist/flows/flow-classify.d.ts.map +1 -0
  109. package/dist/flows/flow-classify.js +99 -0
  110. package/dist/flows/flow-classify.js.map +1 -0
  111. package/dist/flows/flow-replay-run.d.ts +15 -0
  112. package/dist/flows/flow-replay-run.d.ts.map +1 -0
  113. package/dist/flows/flow-replay-run.js +120 -0
  114. package/dist/flows/flow-replay-run.js.map +1 -0
  115. package/dist/flows/flow-replay.d.ts +49 -0
  116. package/dist/flows/flow-replay.d.ts.map +1 -0
  117. package/dist/flows/flow-replay.js +391 -0
  118. package/dist/flows/flow-replay.js.map +1 -0
  119. package/dist/flows/flow-report.d.ts +23 -0
  120. package/dist/flows/flow-report.d.ts.map +1 -0
  121. package/dist/flows/flow-report.js +106 -0
  122. package/dist/flows/flow-report.js.map +1 -0
  123. package/dist/flows/flow-scope.d.ts +25 -0
  124. package/dist/flows/flow-scope.d.ts.map +1 -0
  125. package/dist/flows/flow-scope.js +32 -0
  126. package/dist/flows/flow-scope.js.map +1 -0
  127. package/dist/flows/flow-success.d.ts +33 -0
  128. package/dist/flows/flow-success.d.ts.map +1 -0
  129. package/dist/flows/flow-success.js +131 -0
  130. package/dist/flows/flow-success.js.map +1 -0
  131. package/dist/flows/flow-tools.d.ts +4 -0
  132. package/dist/flows/flow-tools.d.ts.map +1 -0
  133. package/dist/flows/flow-tools.js +460 -0
  134. package/dist/flows/flow-tools.js.map +1 -0
  135. package/dist/flows/flows.d.ts +86 -0
  136. package/dist/flows/flows.d.ts.map +1 -0
  137. package/dist/flows/flows.js +319 -0
  138. package/dist/flows/flows.js.map +1 -0
  139. package/dist/flows/heal.d.ts +43 -0
  140. package/dist/flows/heal.d.ts.map +1 -0
  141. package/dist/flows/heal.js +98 -0
  142. package/dist/flows/heal.js.map +1 -0
  143. package/dist/flows/recordings.d.ts +46 -0
  144. package/dist/flows/recordings.d.ts.map +1 -0
  145. package/dist/flows/recordings.js +43 -0
  146. package/dist/flows/recordings.js.map +1 -0
  147. package/dist/flows/replay.d.ts +23 -0
  148. package/dist/flows/replay.d.ts.map +1 -0
  149. package/dist/flows/replay.js +160 -0
  150. package/dist/flows/replay.js.map +1 -0
  151. package/dist/http-server.d.ts +39 -0
  152. package/dist/http-server.d.ts.map +1 -0
  153. package/dist/http-server.js +145 -0
  154. package/dist/http-server.js.map +1 -0
  155. package/dist/idle-shutdown.d.ts +34 -0
  156. package/dist/idle-shutdown.d.ts.map +1 -0
  157. package/dist/idle-shutdown.js +68 -0
  158. package/dist/idle-shutdown.js.map +1 -0
  159. package/dist/index.d.ts +135 -0
  160. package/dist/index.d.ts.map +1 -0
  161. package/dist/index.js +371 -0
  162. package/dist/index.js.map +1 -0
  163. package/dist/init/cursor.d.ts +25 -0
  164. package/dist/init/cursor.d.ts.map +1 -0
  165. package/dist/init/cursor.js +49 -0
  166. package/dist/init/cursor.js.map +1 -0
  167. package/dist/init/detect.d.ts +49 -0
  168. package/dist/init/detect.d.ts.map +1 -0
  169. package/dist/init/detect.js +84 -0
  170. package/dist/init/detect.js.map +1 -0
  171. package/dist/init/mcp.d.ts +40 -0
  172. package/dist/init/mcp.d.ts.map +1 -0
  173. package/dist/init/mcp.js +55 -0
  174. package/dist/init/mcp.js.map +1 -0
  175. package/dist/init/node-io.d.ts +8 -0
  176. package/dist/init/node-io.d.ts.map +1 -0
  177. package/dist/init/node-io.js +57 -0
  178. package/dist/init/node-io.js.map +1 -0
  179. package/dist/init/plan.d.ts +72 -0
  180. package/dist/init/plan.d.ts.map +1 -0
  181. package/dist/init/plan.js +280 -0
  182. package/dist/init/plan.js.map +1 -0
  183. package/dist/init/project-id.d.ts +17 -0
  184. package/dist/init/project-id.d.ts.map +1 -0
  185. package/dist/init/project-id.js +38 -0
  186. package/dist/init/project-id.js.map +1 -0
  187. package/dist/init/run.d.ts +42 -0
  188. package/dist/init/run.d.ts.map +1 -0
  189. package/dist/init/run.js +171 -0
  190. package/dist/init/run.js.map +1 -0
  191. package/dist/init/snippets.d.ts +33 -0
  192. package/dist/init/snippets.d.ts.map +1 -0
  193. package/dist/init/snippets.js +117 -0
  194. package/dist/init/snippets.js.map +1 -0
  195. package/dist/init/vite-config.d.ts +25 -0
  196. package/dist/init/vite-config.d.ts.map +1 -0
  197. package/dist/init/vite-config.js +45 -0
  198. package/dist/init/vite-config.js.map +1 -0
  199. package/dist/input/network-mock-tools.d.ts +3 -0
  200. package/dist/input/network-mock-tools.d.ts.map +1 -0
  201. package/dist/input/network-mock-tools.js +94 -0
  202. package/dist/input/network-mock-tools.js.map +1 -0
  203. package/dist/input/network-mock.d.ts +55 -0
  204. package/dist/input/network-mock.d.ts.map +1 -0
  205. package/dist/input/network-mock.js +62 -0
  206. package/dist/input/network-mock.js.map +1 -0
  207. package/dist/input/real-input.d.ts +174 -0
  208. package/dist/input/real-input.d.ts.map +1 -0
  209. package/dist/input/real-input.js +289 -0
  210. package/dist/input/real-input.js.map +1 -0
  211. package/dist/input/scroll-find.d.ts +41 -0
  212. package/dist/input/scroll-find.d.ts.map +1 -0
  213. package/dist/input/scroll-find.js +59 -0
  214. package/dist/input/scroll-find.js.map +1 -0
  215. package/dist/input/scroll-tools.d.ts +8 -0
  216. package/dist/input/scroll-tools.d.ts.map +1 -0
  217. package/dist/input/scroll-tools.js +68 -0
  218. package/dist/input/scroll-tools.js.map +1 -0
  219. package/dist/input/viewport-tools.d.ts +3 -0
  220. package/dist/input/viewport-tools.d.ts.map +1 -0
  221. package/dist/input/viewport-tools.js +65 -0
  222. package/dist/input/viewport-tools.js.map +1 -0
  223. package/dist/license/license.d.ts +108 -0
  224. package/dist/license/license.d.ts.map +1 -0
  225. package/dist/license/license.js +203 -0
  226. package/dist/license/license.js.map +1 -0
  227. package/dist/log.d.ts +6 -0
  228. package/dist/log.d.ts.map +1 -0
  229. package/dist/log.js +9 -0
  230. package/dist/log.js.map +1 -0
  231. package/dist/mcp-proxy.d.ts +16 -0
  232. package/dist/mcp-proxy.d.ts.map +1 -0
  233. package/dist/mcp-proxy.js +168 -0
  234. package/dist/mcp-proxy.js.map +1 -0
  235. package/dist/mcp.d.ts +14 -0
  236. package/dist/mcp.d.ts.map +1 -0
  237. package/dist/mcp.js +101 -0
  238. package/dist/mcp.js.map +1 -0
  239. package/dist/pairing-token.d.ts +28 -0
  240. package/dist/pairing-token.d.ts.map +1 -0
  241. package/dist/pairing-token.js +62 -0
  242. package/dist/pairing-token.js.map +1 -0
  243. package/dist/pool/browser-pool.d.ts +90 -0
  244. package/dist/pool/browser-pool.d.ts.map +1 -0
  245. package/dist/pool/browser-pool.js +221 -0
  246. package/dist/pool/browser-pool.js.map +1 -0
  247. package/dist/pool/lease-reaper.d.ts +16 -0
  248. package/dist/pool/lease-reaper.d.ts.map +1 -0
  249. package/dist/pool/lease-reaper.js +41 -0
  250. package/dist/pool/lease-reaper.js.map +1 -0
  251. package/dist/pool/playwright-launcher.d.ts +19 -0
  252. package/dist/pool/playwright-launcher.d.ts.map +1 -0
  253. package/dist/pool/playwright-launcher.js +51 -0
  254. package/dist/pool/playwright-launcher.js.map +1 -0
  255. package/dist/project/baselines.d.ts +22 -0
  256. package/dist/project/baselines.d.ts.map +1 -0
  257. package/dist/project/baselines.js +45 -0
  258. package/dist/project/baselines.js.map +1 -0
  259. package/dist/project/fs-port.d.ts +27 -0
  260. package/dist/project/fs-port.d.ts.map +1 -0
  261. package/dist/project/fs-port.js +32 -0
  262. package/dist/project/fs-port.js.map +1 -0
  263. package/dist/project/project-store.d.ts +32 -0
  264. package/dist/project/project-store.d.ts.map +1 -0
  265. package/dist/project/project-store.js +127 -0
  266. package/dist/project/project-store.js.map +1 -0
  267. package/dist/project/project-tools.d.ts +9 -0
  268. package/dist/project/project-tools.d.ts.map +1 -0
  269. package/dist/project/project-tools.js +118 -0
  270. package/dist/project/project-tools.js.map +1 -0
  271. package/dist/project/reticle-dir.d.ts +61 -0
  272. package/dist/project/reticle-dir.d.ts.map +1 -0
  273. package/dist/project/reticle-dir.js +144 -0
  274. package/dist/project/reticle-dir.js.map +1 -0
  275. package/dist/runs/build-verification-run.d.ts +30 -0
  276. package/dist/runs/build-verification-run.d.ts.map +1 -0
  277. package/dist/runs/build-verification-run.js +71 -0
  278. package/dist/runs/build-verification-run.js.map +1 -0
  279. package/dist/runs/profile-redact.d.ts +16 -0
  280. package/dist/runs/profile-redact.d.ts.map +1 -0
  281. package/dist/runs/profile-redact.js +32 -0
  282. package/dist/runs/profile-redact.js.map +1 -0
  283. package/dist/runs/render-report.d.ts +9 -0
  284. package/dist/runs/render-report.d.ts.map +1 -0
  285. package/dist/runs/render-report.js +70 -0
  286. package/dist/runs/render-report.js.map +1 -0
  287. package/dist/runs/repair-prompt.d.ts +15 -0
  288. package/dist/runs/repair-prompt.d.ts.map +1 -0
  289. package/dist/runs/repair-prompt.js +59 -0
  290. package/dist/runs/repair-prompt.js.map +1 -0
  291. package/dist/runs/replay-mapping.d.ts +12 -0
  292. package/dist/runs/replay-mapping.d.ts.map +1 -0
  293. package/dist/runs/replay-mapping.js +35 -0
  294. package/dist/runs/replay-mapping.js.map +1 -0
  295. package/dist/runs/reticle-runner.d.ts +48 -0
  296. package/dist/runs/reticle-runner.d.ts.map +1 -0
  297. package/dist/runs/reticle-runner.js +56 -0
  298. package/dist/runs/reticle-runner.js.map +1 -0
  299. package/dist/runs/risk-classify.d.ts +27 -0
  300. package/dist/runs/risk-classify.d.ts.map +1 -0
  301. package/dist/runs/risk-classify.js +76 -0
  302. package/dist/runs/risk-classify.js.map +1 -0
  303. package/dist/runs/run-store.d.ts +40 -0
  304. package/dist/runs/run-store.d.ts.map +1 -0
  305. package/dist/runs/run-store.js +118 -0
  306. package/dist/runs/run-store.js.map +1 -0
  307. package/dist/runs/run-tools.d.ts +10 -0
  308. package/dist/runs/run-tools.d.ts.map +1 -0
  309. package/dist/runs/run-tools.js +69 -0
  310. package/dist/runs/run-tools.js.map +1 -0
  311. package/dist/runs/runner-port.d.ts +14 -0
  312. package/dist/runs/runner-port.d.ts.map +1 -0
  313. package/dist/runs/runner-port.js +23 -0
  314. package/dist/runs/runner-port.js.map +1 -0
  315. package/dist/runs/verify-http.d.ts +34 -0
  316. package/dist/runs/verify-http.d.ts.map +1 -0
  317. package/dist/runs/verify-http.js +102 -0
  318. package/dist/runs/verify-http.js.map +1 -0
  319. package/dist/runs/verify-server.d.ts +26 -0
  320. package/dist/runs/verify-server.d.ts.map +1 -0
  321. package/dist/runs/verify-server.js +99 -0
  322. package/dist/runs/verify-server.js.map +1 -0
  323. package/dist/server-version.d.ts +3 -0
  324. package/dist/server-version.d.ts.map +1 -0
  325. package/dist/server-version.js +5 -0
  326. package/dist/server-version.js.map +1 -0
  327. package/dist/session/control-envelope.d.ts +49 -0
  328. package/dist/session/control-envelope.d.ts.map +1 -0
  329. package/dist/session/control-envelope.js +44 -0
  330. package/dist/session/control-envelope.js.map +1 -0
  331. package/dist/session/live-control-tools.d.ts +16 -0
  332. package/dist/session/live-control-tools.d.ts.map +1 -0
  333. package/dist/session/live-control-tools.js +204 -0
  334. package/dist/session/live-control-tools.js.map +1 -0
  335. package/dist/session/output-budget.d.ts +41 -0
  336. package/dist/session/output-budget.d.ts.map +1 -0
  337. package/dist/session/output-budget.js +54 -0
  338. package/dist/session/output-budget.js.map +1 -0
  339. package/dist/session/presenter-args.d.ts +8 -0
  340. package/dist/session/presenter-args.d.ts.map +1 -0
  341. package/dist/session/presenter-args.js +15 -0
  342. package/dist/session/presenter-args.js.map +1 -0
  343. package/dist/session/review-store.d.ts +40 -0
  344. package/dist/session/review-store.d.ts.map +1 -0
  345. package/dist/session/review-store.js +61 -0
  346. package/dist/session/review-store.js.map +1 -0
  347. package/dist/session/session-health.d.ts +22 -0
  348. package/dist/session/session-health.d.ts.map +1 -0
  349. package/dist/session/session-health.js +26 -0
  350. package/dist/session/session-health.js.map +1 -0
  351. package/dist/session/session-manager.d.ts +43 -0
  352. package/dist/session/session-manager.d.ts.map +1 -0
  353. package/dist/session/session-manager.js +155 -0
  354. package/dist/session/session-manager.js.map +1 -0
  355. package/dist/session/session-readiness.d.ts +35 -0
  356. package/dist/session/session-readiness.d.ts.map +1 -0
  357. package/dist/session/session-readiness.js +32 -0
  358. package/dist/session/session-readiness.js.map +1 -0
  359. package/dist/session/session-reaper.d.ts +37 -0
  360. package/dist/session/session-reaper.d.ts.map +1 -0
  361. package/dist/session/session-reaper.js +94 -0
  362. package/dist/session/session-reaper.js.map +1 -0
  363. package/dist/session/session-recommendation.d.ts +18 -0
  364. package/dist/session/session-recommendation.d.ts.map +1 -0
  365. package/dist/session/session-recommendation.js +14 -0
  366. package/dist/session/session-recommendation.js.map +1 -0
  367. package/dist/session/session-tools.d.ts +9 -0
  368. package/dist/session/session-tools.d.ts.map +1 -0
  369. package/dist/session/session-tools.js +43 -0
  370. package/dist/session/session-tools.js.map +1 -0
  371. package/dist/session/session.d.ts +166 -0
  372. package/dist/session/session.d.ts.map +1 -0
  373. package/dist/session/session.js +408 -0
  374. package/dist/session/session.js.map +1 -0
  375. package/dist/session/state-select.d.ts +8 -0
  376. package/dist/session/state-select.d.ts.map +1 -0
  377. package/dist/session/state-select.js +8 -0
  378. package/dist/session/state-select.js.map +1 -0
  379. package/dist/token-auth.d.ts +24 -0
  380. package/dist/token-auth.d.ts.map +1 -0
  381. package/dist/token-auth.js +71 -0
  382. package/dist/token-auth.js.map +1 -0
  383. package/dist/tools/act-tools.d.ts +3 -0
  384. package/dist/tools/act-tools.d.ts.map +1 -0
  385. package/dist/tools/act-tools.js +327 -0
  386. package/dist/tools/act-tools.js.map +1 -0
  387. package/dist/tools/act-view.d.ts +19 -0
  388. package/dist/tools/act-view.d.ts.map +1 -0
  389. package/dist/tools/act-view.js +46 -0
  390. package/dist/tools/act-view.js.map +1 -0
  391. package/dist/tools/assert-grade.d.ts +21 -0
  392. package/dist/tools/assert-grade.d.ts.map +1 -0
  393. package/dist/tools/assert-grade.js +52 -0
  394. package/dist/tools/assert-grade.js.map +1 -0
  395. package/dist/tools/browser-tools.d.ts +3 -0
  396. package/dist/tools/browser-tools.d.ts.map +1 -0
  397. package/dist/tools/browser-tools.js +52 -0
  398. package/dist/tools/browser-tools.js.map +1 -0
  399. package/dist/tools/contract-tools.d.ts +8 -0
  400. package/dist/tools/contract-tools.d.ts.map +1 -0
  401. package/dist/tools/contract-tools.js +62 -0
  402. package/dist/tools/contract-tools.js.map +1 -0
  403. package/dist/tools/dynamic-tools.d.ts +7 -0
  404. package/dist/tools/dynamic-tools.d.ts.map +1 -0
  405. package/dist/tools/dynamic-tools.js +103 -0
  406. package/dist/tools/dynamic-tools.js.map +1 -0
  407. package/dist/tools/error-recovery.d.ts +31 -0
  408. package/dist/tools/error-recovery.d.ts.map +1 -0
  409. package/dist/tools/error-recovery.js +52 -0
  410. package/dist/tools/error-recovery.js.map +1 -0
  411. package/dist/tools/invoke-tool.d.ts +23 -0
  412. package/dist/tools/invoke-tool.d.ts.map +1 -0
  413. package/dist/tools/invoke-tool.js +99 -0
  414. package/dist/tools/invoke-tool.js.map +1 -0
  415. package/dist/tools/lease-tools.d.ts +31 -0
  416. package/dist/tools/lease-tools.d.ts.map +1 -0
  417. package/dist/tools/lease-tools.js +164 -0
  418. package/dist/tools/lease-tools.js.map +1 -0
  419. package/dist/tools/observe-tools.d.ts +3 -0
  420. package/dist/tools/observe-tools.d.ts.map +1 -0
  421. package/dist/tools/observe-tools.js +259 -0
  422. package/dist/tools/observe-tools.js.map +1 -0
  423. package/dist/tools/profiles.d.ts +33 -0
  424. package/dist/tools/profiles.d.ts.map +1 -0
  425. package/dist/tools/profiles.js +105 -0
  426. package/dist/tools/profiles.js.map +1 -0
  427. package/dist/tools/query-paginate.d.ts +15 -0
  428. package/dist/tools/query-paginate.d.ts.map +1 -0
  429. package/dist/tools/query-paginate.js +31 -0
  430. package/dist/tools/query-paginate.js.map +1 -0
  431. package/dist/tools/read-tools.d.ts +3 -0
  432. package/dist/tools/read-tools.d.ts.map +1 -0
  433. package/dist/tools/read-tools.js +329 -0
  434. package/dist/tools/read-tools.js.map +1 -0
  435. package/dist/tools/snapshot-delta.d.ts +59 -0
  436. package/dist/tools/snapshot-delta.d.ts.map +1 -0
  437. package/dist/tools/snapshot-delta.js +0 -0
  438. package/dist/tools/snapshot-delta.js.map +1 -0
  439. package/dist/tools/tool-invoker.d.ts +15 -0
  440. package/dist/tools/tool-invoker.d.ts.map +1 -0
  441. package/dist/tools/tool-invoker.js +20 -0
  442. package/dist/tools/tool-invoker.js.map +1 -0
  443. package/dist/tools/tool-kit.d.ts +60 -0
  444. package/dist/tools/tool-kit.d.ts.map +1 -0
  445. package/dist/tools/tool-kit.js +33 -0
  446. package/dist/tools/tool-kit.js.map +1 -0
  447. package/dist/tools/tool-names.d.ts +89 -0
  448. package/dist/tools/tool-names.d.ts.map +1 -0
  449. package/dist/tools/tool-names.js +88 -0
  450. package/dist/tools/tool-names.js.map +1 -0
  451. package/dist/tools/tools-helpers.d.ts +12 -0
  452. package/dist/tools/tools-helpers.d.ts.map +1 -0
  453. package/dist/tools/tools-helpers.js +22 -0
  454. package/dist/tools/tools-helpers.js.map +1 -0
  455. package/dist/tools/tools.d.ts +4 -0
  456. package/dist/tools/tools.d.ts.map +1 -0
  457. package/dist/tools/tools.js +268 -0
  458. package/dist/tools/tools.js.map +1 -0
  459. package/dist/update/update-checker.d.ts +20 -0
  460. package/dist/update/update-checker.d.ts.map +1 -0
  461. package/dist/update/update-checker.js +94 -0
  462. package/dist/update/update-checker.js.map +1 -0
  463. package/dist/update/update-tools.d.ts +3 -0
  464. package/dist/update/update-tools.d.ts.map +1 -0
  465. package/dist/update/update-tools.js +94 -0
  466. package/dist/update/update-tools.js.map +1 -0
  467. package/dist/update/updater.d.ts +31 -0
  468. package/dist/update/updater.d.ts.map +1 -0
  469. package/dist/update/updater.js +120 -0
  470. package/dist/update/updater.js.map +1 -0
  471. package/dist/visual/visual-diff.d.ts +46 -0
  472. package/dist/visual/visual-diff.d.ts.map +1 -0
  473. package/dist/visual/visual-diff.js +100 -0
  474. package/dist/visual/visual-diff.js.map +1 -0
  475. package/dist/visual/visual-store.d.ts +22 -0
  476. package/dist/visual/visual-store.d.ts.map +1 -0
  477. package/dist/visual/visual-store.js +60 -0
  478. package/dist/visual/visual-store.js.map +1 -0
  479. package/dist/visual/visual-tools.d.ts +9 -0
  480. package/dist/visual/visual-tools.d.ts.map +1 -0
  481. package/dist/visual/visual-tools.js +182 -0
  482. package/dist/visual/visual-tools.js.map +1 -0
  483. package/package.json +68 -0
package/LICENSE ADDED
@@ -0,0 +1,105 @@
1
+ # Functional Source License, Version 1.1, ALv2 Future License
2
+
3
+ ## Abbreviation
4
+
5
+ FSL-1.1-ALv2
6
+
7
+ ## Notice
8
+
9
+ Copyright 2026 Reticle Labs
10
+
11
+ ## Terms and Conditions
12
+
13
+ ### Licensor ("We")
14
+
15
+ The party offering the Software under these Terms and Conditions.
16
+
17
+ ### The Software
18
+
19
+ The "Software" is each version of the software that we make available under
20
+ these Terms and Conditions, as indicated by our inclusion of these Terms and
21
+ Conditions with the Software.
22
+
23
+ ### License Grant
24
+
25
+ Subject to your compliance with this License Grant and the Patents,
26
+ Redistribution and Trademark clauses below, we hereby grant you the right to
27
+ use, copy, modify, create derivative works, publicly perform, publicly display
28
+ and redistribute the Software for any Permitted Purpose identified below.
29
+
30
+ ### Permitted Purpose
31
+
32
+ A Permitted Purpose is any purpose other than a Competing Use. A Competing Use
33
+ means making the Software available to others in a commercial product or
34
+ service that:
35
+
36
+ 1. substitutes for the Software;
37
+
38
+ 2. substitutes for any other product or service we offer using the Software
39
+ that exists as of the date we make the Software available; or
40
+
41
+ 3. offers the same or substantially similar functionality as the Software.
42
+
43
+ Permitted Purposes specifically include using the Software:
44
+
45
+ 1. for your internal use and access;
46
+
47
+ 2. for non-commercial education;
48
+
49
+ 3. for non-commercial research; and
50
+
51
+ 4. in connection with professional services that you provide to a licensee
52
+ using the Software in accordance with these Terms and Conditions.
53
+
54
+ ### Patents
55
+
56
+ To the extent your use for a Permitted Purpose would necessarily infringe our
57
+ patents, the license grant above includes a license under our patents. If you
58
+ make a claim against any party that the Software infringes or contributes to
59
+ the infringement of any patent, then your patent license to the Software ends
60
+ immediately.
61
+
62
+ ### Redistribution
63
+
64
+ The Terms and Conditions apply to all copies, modifications and derivatives of
65
+ the Software.
66
+
67
+ If you redistribute any copies, modifications or derivatives of the Software,
68
+ you must include a copy of or a link to these Terms and Conditions and not
69
+ remove any copyright notices provided in or with the Software.
70
+
71
+ ### Disclaimer
72
+
73
+ THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR
74
+ IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF FITNESS FOR A PARTICULAR
75
+ PURPOSE, MERCHANTABILITY, TITLE OR NON-INFRINGEMENT.
76
+
77
+ IN NO EVENT WILL WE HAVE ANY LIABILITY TO YOU ARISING OUT OF OR RELATED TO THE
78
+ SOFTWARE, INCLUDING INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES,
79
+ EVEN IF WE HAVE BEEN INFORMED OF THEIR POSSIBILITY IN ADVANCE.
80
+
81
+ ### Trademarks
82
+
83
+ Except for displaying the License Details and identifying us as the origin of
84
+ the Software, you have no right under these Terms and Conditions to use our
85
+ trademarks, trade names, service marks or product names.
86
+
87
+ ## Grant of Future License
88
+
89
+ We hereby irrevocably grant you an additional license to use the Software under
90
+ the Apache License, Version 2.0 that is effective on the second anniversary of
91
+ the date we make the Software available. On or after that date, you may use the
92
+ Software under the Apache License, Version 2.0, in which case the following
93
+ will apply:
94
+
95
+ Licensed under the Apache License, Version 2.0 (the "License"); you may not use
96
+ this file except in compliance with the License.
97
+
98
+ You may obtain a copy of the License at
99
+
100
+ http://www.apache.org/licenses/LICENSE-2.0
101
+
102
+ Unless required by applicable law or agreed to in writing, software distributed
103
+ under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
104
+ CONDITIONS OF ANY KIND, either express or implied. See the License for the
105
+ specific language governing permissions and limitations under the License.
package/README.md ADDED
@@ -0,0 +1,17 @@
1
+ # @reticlehq/server
2
+
3
+ The [Reticle](https://github.com/reticlehq/reticle) bridge + MCP server. It hosts a localhost WebSocket endpoint your app's `@reticlehq/browser` SDK connects to, and exposes MCP tools your coding agent uses to look at, act on, observe, and assert against the live app.
4
+
5
+ ```bash
6
+ npx @reticlehq/server # bridge on ws://localhost:4400, MCP over stdio
7
+ ```
8
+
9
+ Point your agent at it (e.g. Claude Code `.mcp.json`):
10
+
11
+ ```jsonc
12
+ { "mcpServers": { "reticle": { "command": "npx", "args": ["@reticlehq/server", "mcp"] } } }
13
+ ```
14
+
15
+ Tools: `reticle_snapshot`, `reticle_query`, `reticle_inspect`, `reticle_act`, `reticle_act_sequence`, `reticle_observe`, `reticle_wait_for`, `reticle_assert`, `reticle_network`, `reticle_console`, `reticle_animations`, `reticle_baseline_save`/`_list`, `reticle_diff`, `reticle_record_start`/`_stop`, `reticle_explore`, `reticle_sessions`.
16
+
17
+ See the [main README](https://github.com/reticlehq/reticle). MIT.
@@ -0,0 +1,23 @@
1
+ import type { StartOptions } from './index.js';
2
+ /** The security contract the bridge/daemon enforce: bind host, pairing token, and WS origin allow-list. */
3
+ interface BridgeSecurity {
4
+ host?: string;
5
+ token?: string;
6
+ allowedOrigins?: string[];
7
+ }
8
+ /**
9
+ * Resolve the bridge's security options from explicit options first, then the environment. Shared by
10
+ * both `start()` and `startDaemon()` so the token/host/origin contract is enforced identically on
11
+ * every entrypoint — a past divergence let daemon mode silently run with auth disabled.
12
+ */
13
+ export declare function resolveBridgeSecurity(options: StartOptions): BridgeSecurity;
14
+ /**
15
+ * Same as `resolveBridgeSecurity`, but when no explicit/env token is set it auto-provisions one from
16
+ * ~/.reticle/pairing-token so the bridge always requires a secret by default — this is what closes the
17
+ * "any loopback origin is trusted" gap (a rogue localhost app can't read the file to present it). The
18
+ * build plugins read the same file and inject it, so plugin-served apps stay zero-config. Best-effort:
19
+ * if provisioning fails, the daemon degrades to the prior tokenless behavior rather than failing to start.
20
+ */
21
+ export declare function resolveBridgeSecurityWithAutoToken(options: StartOptions): Promise<BridgeSecurity>;
22
+ export {};
23
+ //# sourceMappingURL=bridge-security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-security.d.ts","sourceRoot":"","sources":["../src/bridge-security.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C,2GAA2G;AAC3G,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,GAAG,cAAc,CAiB3E;AAED;;;;;;GAMG;AACH,wBAAsB,kCAAkC,CACtD,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,cAAc,CAAC,CAUzB"}
@@ -0,0 +1,44 @@
1
+ import { ReticleEnv } from '@reticlehq/core';
2
+ import { defaultPairingTokenDir, nodePairingTokenDeps, readOrCreatePairingToken, } from './pairing-token.js';
3
+ import { log } from './log.js';
4
+ /**
5
+ * Resolve the bridge's security options from explicit options first, then the environment. Shared by
6
+ * both `start()` and `startDaemon()` so the token/host/origin contract is enforced identically on
7
+ * every entrypoint — a past divergence let daemon mode silently run with auth disabled.
8
+ */
9
+ export function resolveBridgeSecurity(options) {
10
+ const envToken = process.env[ReticleEnv.TOKEN];
11
+ const envOrigins = process.env[ReticleEnv.ALLOWED_ORIGINS];
12
+ const host = options.host ?? process.env[ReticleEnv.HOST];
13
+ const token = options.token ?? (envToken !== undefined && envToken.length > 0 ? envToken : undefined);
14
+ const allowedOrigins = options.allowedOrigins ??
15
+ envOrigins
16
+ ?.split(',')
17
+ .map((origin) => origin.trim())
18
+ .filter((origin) => origin.length > 0);
19
+ return {
20
+ ...(host === undefined ? {} : { host }),
21
+ ...(token === undefined ? {} : { token }),
22
+ ...(allowedOrigins === undefined ? {} : { allowedOrigins }),
23
+ };
24
+ }
25
+ /**
26
+ * Same as `resolveBridgeSecurity`, but when no explicit/env token is set it auto-provisions one from
27
+ * ~/.reticle/pairing-token so the bridge always requires a secret by default — this is what closes the
28
+ * "any loopback origin is trusted" gap (a rogue localhost app can't read the file to present it). The
29
+ * build plugins read the same file and inject it, so plugin-served apps stay zero-config. Best-effort:
30
+ * if provisioning fails, the daemon degrades to the prior tokenless behavior rather than failing to start.
31
+ */
32
+ export async function resolveBridgeSecurityWithAutoToken(options) {
33
+ const security = resolveBridgeSecurity(options);
34
+ if (security.token !== undefined)
35
+ return security;
36
+ const dir = options.pairingTokenDir ?? defaultPairingTokenDir();
37
+ const token = await readOrCreatePairingToken(dir, nodePairingTokenDeps());
38
+ if (token === undefined) {
39
+ log('pairing_token_provision_failed', { dir });
40
+ return security;
41
+ }
42
+ return { ...security, token };
43
+ }
44
+ //# sourceMappingURL=bridge-security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge-security.js","sourceRoot":"","sources":["../src/bridge-security.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAS/B;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,OAAqB;IACzD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;IAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC1D,MAAM,KAAK,GACT,OAAO,CAAC,KAAK,IAAI,CAAC,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC1F,MAAM,cAAc,GAClB,OAAO,CAAC,cAAc;QACtB,UAAU;YACR,EAAE,KAAK,CAAC,GAAG,CAAC;aACX,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;aAC9B,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC3C,OAAO;QACL,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACvC,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QACzC,GAAG,CAAC,cAAc,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC;KAC5D,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,kCAAkC,CACtD,OAAqB;IAErB,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,QAAQ,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IAClD,MAAM,GAAG,GAAG,OAAO,CAAC,eAAe,IAAI,sBAAsB,EAAE,CAAC;IAChE,MAAM,KAAK,GAAG,MAAM,wBAAwB,CAAC,GAAG,EAAE,oBAAoB,EAAE,CAAC,CAAC;IAC1E,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,GAAG,CAAC,gCAAgC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/C,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,EAAE,GAAG,QAAQ,EAAE,KAAK,EAAE,CAAC;AAChC,CAAC"}
@@ -0,0 +1,42 @@
1
+ import * as http from 'node:http';
2
+ import { Session, SessionManager } from './session/session.js';
3
+ /** A human clicked ▶ on a saved flow in the panel — replay it with no agent. Wired by the daemon. */
4
+ type ReplayRequestHandler = (sessionId: string, flowName: string) => void;
5
+ /** Called once a browser session connects, so the daemon can push it the replayable-flow list. */
6
+ type SessionReadyHandler = (session: Session) => void;
7
+ interface BridgeOptions {
8
+ port: number;
9
+ host?: string;
10
+ token?: string;
11
+ allowedOrigins?: string[];
12
+ maxMessagesPerSecond?: number;
13
+ maxSessions?: number;
14
+ maxPendingConnections?: number;
15
+ helloTimeoutMs?: number;
16
+ clock?: () => number;
17
+ /**
18
+ * When set, the WebSocket server attaches to this HTTP server instead of binding standalone.
19
+ * Used in daemon mode where a single HTTP server handles both WS and SSE MCP traffic.
20
+ * `port` and `host` are ignored for binding when this is provided.
21
+ */
22
+ server?: http.Server;
23
+ }
24
+ /**
25
+ * The browser-facing half of the relay: a localhost WebSocket server. Each connection
26
+ * announces itself with HELLO (registering a Session), then streams EVENTs and replies to
27
+ * COMMANDs.
28
+ */
29
+ export declare class Bridge {
30
+ #private;
31
+ readonly sessions: SessionManager;
32
+ /** Resolves with the actually-bound port once the server is listening. */
33
+ readonly ready: Promise<number>;
34
+ constructor(options: BridgeOptions);
35
+ /** Register the daemon's handler for a panel ▶ replay (it owns the flow store). */
36
+ attachReplay(handler: ReplayRequestHandler): void;
37
+ /** Register a callback fired when a browser session connects (to push it the replayable flows). */
38
+ attachSessionReady(handler: SessionReadyHandler): void;
39
+ close(): Promise<void>;
40
+ }
41
+ export {};
42
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAalC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAI/D,qGAAqG;AACrG,KAAK,oBAAoB,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;AAC1E,kGAAkG;AAClG,KAAK,mBAAmB,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;AAqBtD,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC;CACtB;AAkBD;;;;GAIG;AACH,qBAAa,MAAM;;IACjB,QAAQ,CAAC,QAAQ,iBAAwB;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;gBAapB,OAAO,EAAE,aAAa;IAyMlC,mFAAmF;IACnF,YAAY,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAIjD,mGAAmG;IACnG,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAItD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQvB"}
package/dist/bridge.js ADDED
@@ -0,0 +1,281 @@
1
+ import * as http from 'node:http';
2
+ import { WebSocketServer } from 'ws';
3
+ import { EventType, HumanControlKind, RETICLE_WS_PATH, ReticleMessageSchema, LOOPBACK_HOST, MessageKind, TRANSPORT_LIMITS, isLoopbackHostname, } from '@reticlehq/core';
4
+ import { Session, SessionManager } from './session/session.js';
5
+ import { tokensMatch } from './token-auth.js';
6
+ import { log } from './log.js';
7
+ /** WS close codes + reasons the bridge sends to the SDK (1008 = policy violation, 1013 = try again later). */
8
+ const WS_CLOSE = {
9
+ TOO_MANY_HANDSHAKES: [1013, 'too many pending handshakes'],
10
+ HELLO_TIMEOUT: [1008, 'hello timeout'],
11
+ RATE_EXCEEDED: [1008, 'message rate exceeded'],
12
+ INVALID_MESSAGE: [1008, 'invalid message'],
13
+ HELLO_DUPLICATE: [1008, 'hello already received'],
14
+ AUTH_FAILED: [1008, 'authentication failed'],
15
+ SESSION_LIMIT: [1013, 'session limit reached'],
16
+ };
17
+ /** The flow name if this event is a panel ▶ replay request, else undefined. Pure boundary narrowing. */
18
+ function replayRequest(event) {
19
+ if (event.type !== EventType.HUMAN_CONTROL)
20
+ return undefined;
21
+ if (event.data['kind'] !== HumanControlKind.REPLAY)
22
+ return undefined;
23
+ const name = event.data['text'];
24
+ return typeof name === 'string' && name.length > 0 ? name : undefined;
25
+ }
26
+ function normalizeOrigin(origin) {
27
+ try {
28
+ return new URL(origin).origin;
29
+ }
30
+ catch {
31
+ return null;
32
+ }
33
+ }
34
+ /** Normalize ws RawData (string | Buffer | Buffer[] | ArrayBuffer) into a UTF-8 string. */
35
+ function rawToString(raw) {
36
+ if (typeof raw === 'string')
37
+ return raw;
38
+ if (Array.isArray(raw))
39
+ return Buffer.concat(raw).toString('utf8');
40
+ if (raw instanceof ArrayBuffer)
41
+ return Buffer.from(raw).toString('utf8');
42
+ return raw.toString('utf8');
43
+ }
44
+ /**
45
+ * The browser-facing half of the relay: a localhost WebSocket server. Each connection
46
+ * announces itself with HELLO (registering a Session), then streams EVENTs and replies to
47
+ * COMMANDs.
48
+ */
49
+ export class Bridge {
50
+ sessions = new SessionManager();
51
+ /** Resolves with the actually-bound port once the server is listening. */
52
+ ready;
53
+ #wss;
54
+ #clock;
55
+ #token;
56
+ #allowedOrigins;
57
+ #maxMessagesPerSecond;
58
+ #maxSessions;
59
+ #maxPendingConnections;
60
+ #helloTimeoutMs;
61
+ #pendingConnections = 0;
62
+ #onReplay;
63
+ #onSessionReady;
64
+ constructor(options) {
65
+ const host = options.host ?? LOOPBACK_HOST;
66
+ if ((options.token?.length ?? 0) > TRANSPORT_LIMITS.MAX_TOKEN_LENGTH) {
67
+ throw new Error(`Reticle pairing token exceeds ${String(TRANSPORT_LIMITS.MAX_TOKEN_LENGTH)} characters`);
68
+ }
69
+ if (!isLoopbackHostname(host) && (options.token === undefined || options.token.length === 0)) {
70
+ throw new Error('a pairing token is required when the Reticle bridge binds beyond localhost');
71
+ }
72
+ this.#clock = options.clock ?? (() => Date.now());
73
+ this.#token =
74
+ options.token !== undefined && options.token.length > 0 ? options.token : undefined;
75
+ this.#allowedOrigins = new Set((options.allowedOrigins ?? [])
76
+ .map(normalizeOrigin)
77
+ .filter((origin) => origin !== null));
78
+ this.#maxMessagesPerSecond =
79
+ options.maxMessagesPerSecond ?? TRANSPORT_LIMITS.MAX_MESSAGES_PER_SECOND;
80
+ this.#maxSessions = options.maxSessions ?? TRANSPORT_LIMITS.MAX_SESSIONS;
81
+ this.#maxPendingConnections =
82
+ options.maxPendingConnections ?? TRANSPORT_LIMITS.MAX_PENDING_CONNECTIONS;
83
+ this.#helloTimeoutMs = options.helloTimeoutMs ?? TRANSPORT_LIMITS.HELLO_TIMEOUT_MS;
84
+ if (options.server !== undefined) {
85
+ const srv = options.server;
86
+ this.#wss = new WebSocketServer({
87
+ server: srv,
88
+ path: RETICLE_WS_PATH,
89
+ maxPayload: TRANSPORT_LIMITS.MAX_MESSAGE_BYTES,
90
+ verifyClient: ({ origin }, done) => {
91
+ const allowed = this.#originAllowed(origin);
92
+ if (!allowed)
93
+ log('origin_rejected', { origin: origin ?? 'missing' });
94
+ done(allowed, 403, 'Forbidden');
95
+ },
96
+ });
97
+ // In shared-server mode the daemon owns listen(); but a WebSocketServer bound to a server that
98
+ // fails to listen (EADDRINUSE) surfaces the error on the WS instance too. Without a listener
99
+ // that is an unhandled 'error' that can crash/hang the process — so absorb it here and reject
100
+ // `ready`, mirroring the standalone branch. The daemon's own listen handler reports the failure.
101
+ this.ready = new Promise((resolve, reject) => {
102
+ this.#wss.once('error', reject);
103
+ if (srv.listening) {
104
+ this.#wss.removeListener('error', reject);
105
+ resolve(srv.address().port);
106
+ }
107
+ else {
108
+ srv.once('listening', () => {
109
+ this.#wss.removeListener('error', reject);
110
+ resolve(srv.address().port);
111
+ });
112
+ }
113
+ });
114
+ }
115
+ else {
116
+ this.#wss = new WebSocketServer({
117
+ port: options.port,
118
+ host,
119
+ path: RETICLE_WS_PATH,
120
+ maxPayload: TRANSPORT_LIMITS.MAX_MESSAGE_BYTES,
121
+ verifyClient: ({ origin }, done) => {
122
+ const allowed = this.#originAllowed(origin);
123
+ if (!allowed)
124
+ log('origin_rejected', { origin: origin ?? 'missing' });
125
+ done(allowed, 403, 'Forbidden');
126
+ },
127
+ });
128
+ // Reject on 'error' as well as resolve on 'listening'. A port collision (EADDRINUSE) emits
129
+ // 'error'; with no listener that becomes an unhandled 'error' (process crash) AND leaves
130
+ // `ready` pending forever. Surfacing it lets the CLI print "port already in use" cleanly.
131
+ this.ready = new Promise((resolve, reject) => {
132
+ this.#wss.once('error', reject);
133
+ this.#wss.on('listening', () => {
134
+ this.#wss.removeListener('error', reject);
135
+ resolve(this.#wss.address().port);
136
+ });
137
+ });
138
+ }
139
+ this.#wss.on('connection', (socket) => {
140
+ this.#onConnection(socket);
141
+ });
142
+ }
143
+ #onConnection(socket) {
144
+ if (this.#pendingConnections >= this.#maxPendingConnections) {
145
+ socket.close(...WS_CLOSE.TOO_MANY_HANDSHAKES);
146
+ return;
147
+ }
148
+ this.#pendingConnections += 1;
149
+ let awaitingHello = true;
150
+ let session;
151
+ let messageWindowStartedAt = this.#clock();
152
+ let messagesInWindow = 0;
153
+ const releasePending = () => {
154
+ if (!awaitingHello)
155
+ return;
156
+ awaitingHello = false;
157
+ this.#pendingConnections -= 1;
158
+ };
159
+ const helloTimer = setTimeout(() => {
160
+ if (!awaitingHello)
161
+ return;
162
+ releasePending();
163
+ socket.close(...WS_CLOSE.HELLO_TIMEOUT);
164
+ }, this.#helloTimeoutMs);
165
+ socket.on('message', (raw) => {
166
+ const now = this.#clock();
167
+ if (now - messageWindowStartedAt >= 1000) {
168
+ messageWindowStartedAt = now;
169
+ messagesInWindow = 0;
170
+ }
171
+ messagesInWindow += 1;
172
+ if (messagesInWindow > this.#maxMessagesPerSecond) {
173
+ log('message_rate_exceeded', {});
174
+ socket.close(...WS_CLOSE.RATE_EXCEEDED);
175
+ return;
176
+ }
177
+ const parsed = this.#parse(rawToString(raw));
178
+ if (parsed === null) {
179
+ socket.close(...WS_CLOSE.INVALID_MESSAGE);
180
+ return;
181
+ }
182
+ if (parsed.kind === MessageKind.HELLO) {
183
+ if (session !== undefined) {
184
+ socket.close(...WS_CLOSE.HELLO_DUPLICATE);
185
+ return;
186
+ }
187
+ if (this.#token !== undefined && !tokensMatch(this.#token, parsed.token)) {
188
+ log('authentication_failed', {});
189
+ socket.close(...WS_CLOSE.AUTH_FAILED);
190
+ return;
191
+ }
192
+ const existing = this.sessions.get(parsed.sessionId);
193
+ if (existing === undefined && this.sessions.count() >= this.#maxSessions) {
194
+ socket.close(...WS_CLOSE.SESSION_LIMIT);
195
+ return;
196
+ }
197
+ clearTimeout(helloTimer);
198
+ releasePending();
199
+ session = new Session(parsed, socket, this.#clock);
200
+ const replaced = this.sessions.add(session);
201
+ replaced?.disconnect('session replaced by a newer connection');
202
+ log('session_connected', { sessionId: session.id, url: session.url });
203
+ this.#onSessionReady?.(session); // daemon pushes the replayable-flow list to the panel
204
+ return;
205
+ }
206
+ if (session === undefined)
207
+ return;
208
+ session.touch();
209
+ if (parsed.kind === MessageKind.EVENT) {
210
+ // A panel ▶ replay needs the daemon's flow store, which the Session can't reach — route it to
211
+ // the daemon-wired handler instead of the in-session control path. Everything else is normal.
212
+ const replay = replayRequest(parsed.event);
213
+ if (replay !== undefined)
214
+ this.#onReplay?.(session.id, replay);
215
+ else
216
+ session.pushEvent(parsed.event);
217
+ }
218
+ else if (parsed.kind === MessageKind.COMMAND_RESULT) {
219
+ session.handleResult(parsed);
220
+ }
221
+ });
222
+ socket.on('close', () => {
223
+ clearTimeout(helloTimer);
224
+ releasePending();
225
+ if (session !== undefined) {
226
+ if (this.sessions.remove(session)) {
227
+ log('session_disconnected', { sessionId: session.id });
228
+ }
229
+ }
230
+ });
231
+ socket.on('error', (err) => {
232
+ log('socket_error', { error: err.message });
233
+ });
234
+ }
235
+ #originAllowed(origin) {
236
+ // A real browser SDK connection always carries an Origin. A missing Origin means a non-browser
237
+ // local process (another app, a malicious npm postinstall, an extension's native host) — untrusted
238
+ // unless a pairing token is required, in which case the HELLO token check is the real gate.
239
+ if (origin === undefined)
240
+ return this.#token !== undefined;
241
+ const normalized = normalizeOrigin(origin);
242
+ if (normalized === null)
243
+ return false;
244
+ if (this.#allowedOrigins.has(normalized))
245
+ return true;
246
+ return isLoopbackHostname(new URL(normalized).hostname);
247
+ }
248
+ #parse(text) {
249
+ let json;
250
+ try {
251
+ json = JSON.parse(text);
252
+ }
253
+ catch {
254
+ return null;
255
+ }
256
+ const result = ReticleMessageSchema.safeParse(json);
257
+ if (!result.success) {
258
+ log('bad_message', { issues: result.error.issues.length });
259
+ return null;
260
+ }
261
+ return result.data;
262
+ }
263
+ /** Register the daemon's handler for a panel ▶ replay (it owns the flow store). */
264
+ attachReplay(handler) {
265
+ this.#onReplay = handler;
266
+ }
267
+ /** Register a callback fired when a browser session connects (to push it the replayable flows). */
268
+ attachSessionReady(handler) {
269
+ this.#onSessionReady = handler;
270
+ }
271
+ close() {
272
+ return new Promise((resolve) => {
273
+ for (const client of this.#wss.clients)
274
+ client.terminate();
275
+ this.#wss.close(() => {
276
+ resolve();
277
+ });
278
+ });
279
+ }
280
+ }
281
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { type ElementQuery } from '@reticlehq/core';
2
+ import type { Bridge } from './bridge.js';
3
+ import { type ToolDeps } from './tools/tools.js';
4
+ /** The app-advertised testable surface a FakeBrowser reports for an reticle_capabilities round-trip. */
5
+ export declare const FAKE_CAPABILITIES: {
6
+ testids: string[];
7
+ signals: string[];
8
+ stores: string[];
9
+ flows: {
10
+ name: string;
11
+ steps: string[];
12
+ }[];
13
+ };
14
+ /** A stand-in for the real @reticlehq/browser SDK: replies to commands and emits events. */
15
+ export declare class FakeBrowser {
16
+ #private;
17
+ private readonly sessionId;
18
+ private readonly hasCapabilities;
19
+ matcher: (query: ElementQuery) => boolean;
20
+ /** When false, the browser pretends it has no CAPABILITIES handler (older build). */
21
+ handlesCapabilities: boolean;
22
+ /** When false, ACT results omit a testid (element has no data-testid → unstable step). */
23
+ actHasTestid: boolean;
24
+ /** when false, ACT reports settled:false + settleReason:'timeout' (throttled-tab path). */
25
+ actSettled: boolean;
26
+ /** When false, QUERY by testid returns no match (testid not in current DOM at replay). */
27
+ queryResolves: boolean;
28
+ /** Records every command the bridge sent (for replay assertions). */
29
+ readonly received: {
30
+ name: string;
31
+ args: Record<string, unknown>;
32
+ }[];
33
+ constructor(port: number, sessionId: string, hasCapabilities?: boolean);
34
+ open(): Promise<void>;
35
+ emit(type: string, data: Record<string, unknown>, ref?: string): void;
36
+ close(): void;
37
+ }
38
+ export declare function waitUntil(cond: () => boolean, timeoutMs?: number): Promise<void>;
39
+ export declare const callTool: (deps: ToolDeps, name: string, args?: Record<string, unknown>) => Promise<unknown>;
40
+ /** Builds the ToolDeps wired to a running bridge, with a frozen clock for deterministic tests. */
41
+ export declare function makeDeps(bridge: Bridge): ToolDeps;
42
+ //# sourceMappingURL=bridge.test-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.test-harness.d.ts","sourceRoot":"","sources":["../src/bridge.test-harness.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAO1C,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAExD,wGAAwG;AACxG,eAAO,MAAM,iBAAiB;;;;;;;;CAK7B,CAAC;AAEF,4FAA4F;AAC5F,qBAAa,WAAW;;IAgBpB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,eAAe;IAflC,OAAO,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,OAAO,CAAe;IACxD,qFAAqF;IACrF,mBAAmB,UAAQ;IAC3B,0FAA0F;IAC1F,YAAY,UAAQ;IACpB,2FAA2F;IAC3F,UAAU,UAAQ;IAClB,0FAA0F;IAC1F,aAAa,UAAQ;IACrB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,EAAE,CAAM;gBAGxE,IAAI,EAAE,MAAM,EACK,SAAS,EAAE,MAAM,EACjB,eAAe,UAAQ;IAQ1C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBrB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAOrE,KAAK,IAAI,IAAI;CAwFd;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,OAAO,EAAE,SAAS,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAU9E;AAED,eAAO,MAAM,QAAQ,GACnB,MAAM,QAAQ,EACd,MAAM,MAAM,EACZ,OAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,KACjC,OAAO,CAAC,OAAO,CAIjB,CAAC;AAEF,kGAAkG;AAClG,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,QAAQ,CAcjD"}