@descryy/mcp 0.11.5 → 0.11.7

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 (445) hide show
  1. package/dist/action-handshake.d.ts +38 -0
  2. package/dist/action-handshake.d.ts.map +1 -0
  3. package/dist/action-handshake.js +127 -0
  4. package/dist/action-handshake.js.map +1 -0
  5. package/dist/bin/descry-mcp.d.ts +7 -0
  6. package/dist/bin/descry-mcp.d.ts.map +1 -0
  7. package/dist/bin/descry-mcp.js +73 -0
  8. package/dist/bin/descry-mcp.js.map +1 -0
  9. package/dist/browser/auth.d.ts +84 -0
  10. package/dist/browser/auth.d.ts.map +1 -0
  11. package/dist/browser/auth.js +233 -0
  12. package/dist/browser/auth.js.map +1 -0
  13. package/dist/browser/capability-probe.d.ts +109 -0
  14. package/dist/browser/capability-probe.d.ts.map +1 -0
  15. package/dist/browser/capability-probe.js +201 -0
  16. package/dist/browser/capability-probe.js.map +1 -0
  17. package/dist/browser/driver.d.ts +591 -0
  18. package/dist/browser/driver.d.ts.map +1 -0
  19. package/dist/browser/driver.js +116 -0
  20. package/dist/browser/driver.js.map +1 -0
  21. package/dist/browser/evidence.d.ts +28 -0
  22. package/dist/browser/evidence.d.ts.map +1 -0
  23. package/dist/browser/evidence.js +82 -0
  24. package/dist/browser/evidence.js.map +1 -0
  25. package/dist/browser/fake-driver.d.ts +116 -0
  26. package/dist/browser/fake-driver.d.ts.map +1 -0
  27. package/dist/browser/fake-driver.js +416 -0
  28. package/dist/browser/fake-driver.js.map +1 -0
  29. package/dist/browser/fault-attribution.d.ts +178 -0
  30. package/dist/browser/fault-attribution.d.ts.map +1 -0
  31. package/dist/browser/fault-attribution.js +266 -0
  32. package/dist/browser/fault-attribution.js.map +1 -0
  33. package/dist/browser/graph-write.d.ts +45 -0
  34. package/dist/browser/graph-write.d.ts.map +1 -0
  35. package/dist/browser/graph-write.js +103 -0
  36. package/dist/browser/graph-write.js.map +1 -0
  37. package/dist/browser/identity-graph-write.d.ts +55 -0
  38. package/dist/browser/identity-graph-write.d.ts.map +1 -0
  39. package/dist/browser/identity-graph-write.js +45 -0
  40. package/dist/browser/identity-graph-write.js.map +1 -0
  41. package/dist/browser/page-probe.d.ts +81 -0
  42. package/dist/browser/page-probe.d.ts.map +1 -0
  43. package/dist/browser/page-probe.js +202 -0
  44. package/dist/browser/page-probe.js.map +1 -0
  45. package/dist/browser/playwright-driver.d.ts +115 -0
  46. package/dist/browser/playwright-driver.d.ts.map +1 -0
  47. package/dist/browser/playwright-driver.js +1545 -0
  48. package/dist/browser/playwright-driver.js.map +1 -0
  49. package/dist/browser/provider.d.ts +26 -0
  50. package/dist/browser/provider.d.ts.map +1 -0
  51. package/dist/browser/provider.js +14 -0
  52. package/dist/browser/provider.js.map +1 -0
  53. package/dist/browser/reach-recording-session.d.ts +44 -0
  54. package/dist/browser/reach-recording-session.d.ts.map +1 -0
  55. package/dist/browser/reach-recording-session.js +151 -0
  56. package/dist/browser/reach-recording-session.js.map +1 -0
  57. package/dist/browser/reachability.d.ts +168 -0
  58. package/dist/browser/reachability.d.ts.map +1 -0
  59. package/dist/browser/reachability.js +294 -0
  60. package/dist/browser/reachability.js.map +1 -0
  61. package/dist/browser/registry.d.ts +126 -0
  62. package/dist/browser/registry.d.ts.map +1 -0
  63. package/dist/browser/registry.js +177 -0
  64. package/dist/browser/registry.js.map +1 -0
  65. package/dist/browser/scenario-provenance.d.ts +23 -0
  66. package/dist/browser/scenario-provenance.d.ts.map +1 -0
  67. package/dist/browser/scenario-provenance.js +73 -0
  68. package/dist/browser/scenario-provenance.js.map +1 -0
  69. package/dist/browser/scenario-resolve.d.ts +28 -0
  70. package/dist/browser/scenario-resolve.d.ts.map +1 -0
  71. package/dist/browser/scenario-resolve.js +96 -0
  72. package/dist/browser/scenario-resolve.js.map +1 -0
  73. package/dist/browser/scenario-runner.d.ts +72 -0
  74. package/dist/browser/scenario-runner.d.ts.map +1 -0
  75. package/dist/browser/scenario-runner.js +353 -0
  76. package/dist/browser/scenario-runner.js.map +1 -0
  77. package/dist/browser/stack-parser.d.ts +19 -0
  78. package/dist/browser/stack-parser.d.ts.map +1 -0
  79. package/dist/browser/stack-parser.js +85 -0
  80. package/dist/browser/stack-parser.js.map +1 -0
  81. package/dist/browser/tool-support.d.ts +71 -0
  82. package/dist/browser/tool-support.d.ts.map +1 -0
  83. package/dist/browser/tool-support.js +216 -0
  84. package/dist/browser/tool-support.js.map +1 -0
  85. package/dist/browser/url-scheme.d.ts +14 -0
  86. package/dist/browser/url-scheme.d.ts.map +1 -0
  87. package/dist/browser/url-scheme.js +38 -0
  88. package/dist/browser/url-scheme.js.map +1 -0
  89. package/dist/browser/wait-target.d.ts +37 -0
  90. package/dist/browser/wait-target.d.ts.map +1 -0
  91. package/dist/browser/wait-target.js +54 -0
  92. package/dist/browser/wait-target.js.map +1 -0
  93. package/dist/cancellation.d.ts +20 -0
  94. package/dist/cancellation.d.ts.map +1 -0
  95. package/dist/cancellation.js +41 -0
  96. package/dist/cancellation.js.map +1 -0
  97. package/dist/capped.d.ts +39 -0
  98. package/dist/capped.d.ts.map +1 -0
  99. package/dist/capped.js +43 -0
  100. package/dist/capped.js.map +1 -0
  101. package/dist/credential-store.d.ts +22 -0
  102. package/dist/credential-store.d.ts.map +1 -0
  103. package/dist/credential-store.js +33 -0
  104. package/dist/credential-store.js.map +1 -0
  105. package/dist/disclosure-ledger.d.ts +14 -0
  106. package/dist/disclosure-ledger.d.ts.map +1 -0
  107. package/dist/disclosure-ledger.js +18 -0
  108. package/dist/disclosure-ledger.js.map +1 -0
  109. package/dist/evidence/observed-route-evidence.d.ts +25 -0
  110. package/dist/evidence/observed-route-evidence.d.ts.map +1 -0
  111. package/dist/evidence/observed-route-evidence.js +76 -0
  112. package/dist/evidence/observed-route-evidence.js.map +1 -0
  113. package/dist/heap.d.ts +61 -0
  114. package/dist/heap.d.ts.map +1 -0
  115. package/dist/heap.js +82 -0
  116. package/dist/heap.js.map +1 -0
  117. package/dist/heartbeat.d.ts +46 -0
  118. package/dist/heartbeat.d.ts.map +1 -0
  119. package/dist/heartbeat.js +66 -0
  120. package/dist/heartbeat.js.map +1 -0
  121. package/dist/index.d.ts +32 -0
  122. package/dist/index.d.ts.map +1 -0
  123. package/dist/index.js +19 -0
  124. package/dist/index.js.map +1 -0
  125. package/dist/module-trust.d.ts +37 -0
  126. package/dist/module-trust.d.ts.map +1 -0
  127. package/dist/module-trust.js +77 -0
  128. package/dist/module-trust.js.map +1 -0
  129. package/dist/path-confinement.d.ts +31 -0
  130. package/dist/path-confinement.d.ts.map +1 -0
  131. package/dist/path-confinement.js +44 -0
  132. package/dist/path-confinement.js.map +1 -0
  133. package/dist/planner/predict-then-propose.d.ts +134 -0
  134. package/dist/planner/predict-then-propose.d.ts.map +1 -0
  135. package/dist/planner/predict-then-propose.js +138 -0
  136. package/dist/planner/predict-then-propose.js.map +1 -0
  137. package/dist/planner/propose-journey.d.ts +75 -0
  138. package/dist/planner/propose-journey.d.ts.map +1 -0
  139. package/dist/planner/propose-journey.js +96 -0
  140. package/dist/planner/propose-journey.js.map +1 -0
  141. package/dist/protocol.d.ts +57 -0
  142. package/dist/protocol.d.ts.map +1 -0
  143. package/dist/protocol.js +90 -0
  144. package/dist/protocol.js.map +1 -0
  145. package/dist/ready-checks.d.ts +12 -0
  146. package/dist/ready-checks.d.ts.map +1 -0
  147. package/dist/ready-checks.js +43 -0
  148. package/dist/ready-checks.js.map +1 -0
  149. package/dist/registry.d.ts +103 -0
  150. package/dist/registry.d.ts.map +1 -0
  151. package/dist/registry.js +327 -0
  152. package/dist/registry.js.map +1 -0
  153. package/dist/render.d.ts +623 -0
  154. package/dist/render.d.ts.map +1 -0
  155. package/dist/render.js +968 -0
  156. package/dist/render.js.map +1 -0
  157. package/dist/runtime-registry.d.ts +22 -0
  158. package/dist/runtime-registry.d.ts.map +1 -0
  159. package/dist/runtime-registry.js +142 -0
  160. package/dist/runtime-registry.js.map +1 -0
  161. package/dist/sandbox-defaults.d.ts +41 -0
  162. package/dist/sandbox-defaults.d.ts.map +1 -0
  163. package/dist/sandbox-defaults.js +14 -0
  164. package/dist/sandbox-defaults.js.map +1 -0
  165. package/dist/scenarios/browser-run-plan-projection.d.ts +161 -0
  166. package/dist/scenarios/browser-run-plan-projection.d.ts.map +1 -0
  167. package/dist/scenarios/browser-run-plan-projection.js +264 -0
  168. package/dist/scenarios/browser-run-plan-projection.js.map +1 -0
  169. package/dist/scenarios/credential-ref.d.ts +102 -0
  170. package/dist/scenarios/credential-ref.d.ts.map +1 -0
  171. package/dist/scenarios/credential-ref.js +148 -0
  172. package/dist/scenarios/credential-ref.js.map +1 -0
  173. package/dist/scenarios/index.d.ts +7 -0
  174. package/dist/scenarios/index.d.ts.map +1 -0
  175. package/dist/scenarios/index.js +7 -0
  176. package/dist/scenarios/index.js.map +1 -0
  177. package/dist/scenarios/parse.d.ts +18 -0
  178. package/dist/scenarios/parse.d.ts.map +1 -0
  179. package/dist/scenarios/parse.js +212 -0
  180. package/dist/scenarios/parse.js.map +1 -0
  181. package/dist/scenarios/scenario.d.ts +93 -0
  182. package/dist/scenarios/scenario.d.ts.map +1 -0
  183. package/dist/scenarios/scenario.js +27 -0
  184. package/dist/scenarios/scenario.js.map +1 -0
  185. package/dist/scenarios/secret-ref.d.ts +86 -0
  186. package/dist/scenarios/secret-ref.d.ts.map +1 -0
  187. package/dist/scenarios/secret-ref.js +125 -0
  188. package/dist/scenarios/secret-ref.js.map +1 -0
  189. package/dist/scenarios/storage.d.ts +21 -0
  190. package/dist/scenarios/storage.d.ts.map +1 -0
  191. package/dist/scenarios/storage.js +103 -0
  192. package/dist/scenarios/storage.js.map +1 -0
  193. package/dist/server.d.ts +61 -0
  194. package/dist/server.d.ts.map +1 -0
  195. package/dist/server.js +642 -0
  196. package/dist/server.js.map +1 -0
  197. package/dist/session.d.ts +356 -0
  198. package/dist/session.d.ts.map +1 -0
  199. package/dist/session.js +779 -0
  200. package/dist/session.js.map +1 -0
  201. package/dist/tools/alias-kit.d.ts +29 -0
  202. package/dist/tools/alias-kit.d.ts.map +1 -0
  203. package/dist/tools/alias-kit.js +21 -0
  204. package/dist/tools/alias-kit.js.map +1 -0
  205. package/dist/tools/aliases.d.ts +42 -0
  206. package/dist/tools/aliases.d.ts.map +1 -0
  207. package/dist/tools/aliases.js +52 -0
  208. package/dist/tools/aliases.js.map +1 -0
  209. package/dist/tools/analyze-workspace.d.ts +52 -0
  210. package/dist/tools/analyze-workspace.d.ts.map +1 -0
  211. package/dist/tools/analyze-workspace.js +207 -0
  212. package/dist/tools/analyze-workspace.js.map +1 -0
  213. package/dist/tools/analyze.d.ts +163 -0
  214. package/dist/tools/analyze.d.ts.map +1 -0
  215. package/dist/tools/analyze.js +724 -0
  216. package/dist/tools/analyze.js.map +1 -0
  217. package/dist/tools/browser-click.d.ts +18 -0
  218. package/dist/tools/browser-click.d.ts.map +1 -0
  219. package/dist/tools/browser-click.js +110 -0
  220. package/dist/tools/browser-click.js.map +1 -0
  221. package/dist/tools/browser-close-session.d.ts +39 -0
  222. package/dist/tools/browser-close-session.d.ts.map +1 -0
  223. package/dist/tools/browser-close-session.js +120 -0
  224. package/dist/tools/browser-close-session.js.map +1 -0
  225. package/dist/tools/browser-fill.d.ts +18 -0
  226. package/dist/tools/browser-fill.d.ts.map +1 -0
  227. package/dist/tools/browser-fill.js +117 -0
  228. package/dist/tools/browser-fill.js.map +1 -0
  229. package/dist/tools/browser-navigate.d.ts +15 -0
  230. package/dist/tools/browser-navigate.d.ts.map +1 -0
  231. package/dist/tools/browser-navigate.js +106 -0
  232. package/dist/tools/browser-navigate.js.map +1 -0
  233. package/dist/tools/browser-read.d.ts +33 -0
  234. package/dist/tools/browser-read.d.ts.map +1 -0
  235. package/dist/tools/browser-read.js +105 -0
  236. package/dist/tools/browser-read.js.map +1 -0
  237. package/dist/tools/browser-run-scenario.d.ts +28 -0
  238. package/dist/tools/browser-run-scenario.d.ts.map +1 -0
  239. package/dist/tools/browser-run-scenario.js +238 -0
  240. package/dist/tools/browser-run-scenario.js.map +1 -0
  241. package/dist/tools/browser-save-scenario.d.ts +19 -0
  242. package/dist/tools/browser-save-scenario.d.ts.map +1 -0
  243. package/dist/tools/browser-save-scenario.js +447 -0
  244. package/dist/tools/browser-save-scenario.js.map +1 -0
  245. package/dist/tools/browser-select.d.ts +20 -0
  246. package/dist/tools/browser-select.d.ts.map +1 -0
  247. package/dist/tools/browser-select.js +120 -0
  248. package/dist/tools/browser-select.js.map +1 -0
  249. package/dist/tools/browser-snapshot.d.ts +46 -0
  250. package/dist/tools/browser-snapshot.d.ts.map +1 -0
  251. package/dist/tools/browser-snapshot.js +127 -0
  252. package/dist/tools/browser-snapshot.js.map +1 -0
  253. package/dist/tools/browser-start-session.d.ts +24 -0
  254. package/dist/tools/browser-start-session.d.ts.map +1 -0
  255. package/dist/tools/browser-start-session.js +653 -0
  256. package/dist/tools/browser-start-session.js.map +1 -0
  257. package/dist/tools/browser-submit.d.ts +18 -0
  258. package/dist/tools/browser-submit.d.ts.map +1 -0
  259. package/dist/tools/browser-submit.js +106 -0
  260. package/dist/tools/browser-submit.js.map +1 -0
  261. package/dist/tools/browser-type.d.ts +18 -0
  262. package/dist/tools/browser-type.d.ts.map +1 -0
  263. package/dist/tools/browser-type.js +115 -0
  264. package/dist/tools/browser-type.js.map +1 -0
  265. package/dist/tools/browser-wait-for.d.ts +45 -0
  266. package/dist/tools/browser-wait-for.d.ts.map +1 -0
  267. package/dist/tools/browser-wait-for.js +164 -0
  268. package/dist/tools/browser-wait-for.js.map +1 -0
  269. package/dist/tools/browser.d.ts +69 -0
  270. package/dist/tools/browser.d.ts.map +1 -0
  271. package/dist/tools/browser.js +326 -0
  272. package/dist/tools/browser.js.map +1 -0
  273. package/dist/tools/chain.d.ts +41 -0
  274. package/dist/tools/chain.d.ts.map +1 -0
  275. package/dist/tools/chain.js +101 -0
  276. package/dist/tools/chain.js.map +1 -0
  277. package/dist/tools/change-scope.d.ts +25 -0
  278. package/dist/tools/change-scope.d.ts.map +1 -0
  279. package/dist/tools/change-scope.js +103 -0
  280. package/dist/tools/change-scope.js.map +1 -0
  281. package/dist/tools/code-context.d.ts +83 -0
  282. package/dist/tools/code-context.d.ts.map +1 -0
  283. package/dist/tools/code-context.js +432 -0
  284. package/dist/tools/code-context.js.map +1 -0
  285. package/dist/tools/contracts.d.ts +74 -0
  286. package/dist/tools/contracts.d.ts.map +1 -0
  287. package/dist/tools/contracts.js +214 -0
  288. package/dist/tools/contracts.js.map +1 -0
  289. package/dist/tools/cross-pr.d.ts +178 -0
  290. package/dist/tools/cross-pr.d.ts.map +1 -0
  291. package/dist/tools/cross-pr.js +362 -0
  292. package/dist/tools/cross-pr.js.map +1 -0
  293. package/dist/tools/disclosure.d.ts +75 -0
  294. package/dist/tools/disclosure.d.ts.map +1 -0
  295. package/dist/tools/disclosure.js +325 -0
  296. package/dist/tools/disclosure.js.map +1 -0
  297. package/dist/tools/draw-conclusion.d.ts +55 -0
  298. package/dist/tools/draw-conclusion.d.ts.map +1 -0
  299. package/dist/tools/draw-conclusion.js +243 -0
  300. package/dist/tools/draw-conclusion.js.map +1 -0
  301. package/dist/tools/git-context.d.ts +39 -0
  302. package/dist/tools/git-context.d.ts.map +1 -0
  303. package/dist/tools/git-context.js +374 -0
  304. package/dist/tools/git-context.js.map +1 -0
  305. package/dist/tools/git-diff.d.ts +45 -0
  306. package/dist/tools/git-diff.d.ts.map +1 -0
  307. package/dist/tools/git-diff.js +338 -0
  308. package/dist/tools/git-diff.js.map +1 -0
  309. package/dist/tools/git-history.d.ts +16 -0
  310. package/dist/tools/git-history.d.ts.map +1 -0
  311. package/dist/tools/git-history.js +106 -0
  312. package/dist/tools/git-history.js.map +1 -0
  313. package/dist/tools/history.d.ts +34 -0
  314. package/dist/tools/history.d.ts.map +1 -0
  315. package/dist/tools/history.js +121 -0
  316. package/dist/tools/history.js.map +1 -0
  317. package/dist/tools/impact.d.ts +46 -0
  318. package/dist/tools/impact.d.ts.map +1 -0
  319. package/dist/tools/impact.js +225 -0
  320. package/dist/tools/impact.js.map +1 -0
  321. package/dist/tools/index.d.ts +59 -0
  322. package/dist/tools/index.d.ts.map +1 -0
  323. package/dist/tools/index.js +70 -0
  324. package/dist/tools/index.js.map +1 -0
  325. package/dist/tools/kit.d.ts +165 -0
  326. package/dist/tools/kit.d.ts.map +1 -0
  327. package/dist/tools/kit.js +153 -0
  328. package/dist/tools/kit.js.map +1 -0
  329. package/dist/tools/link-workspace.d.ts +24 -0
  330. package/dist/tools/link-workspace.d.ts.map +1 -0
  331. package/dist/tools/link-workspace.js +131 -0
  332. package/dist/tools/link-workspace.js.map +1 -0
  333. package/dist/tools/lookup.d.ts +19 -0
  334. package/dist/tools/lookup.d.ts.map +1 -0
  335. package/dist/tools/lookup.js +63 -0
  336. package/dist/tools/lookup.js.map +1 -0
  337. package/dist/tools/mark-incident.d.ts +28 -0
  338. package/dist/tools/mark-incident.d.ts.map +1 -0
  339. package/dist/tools/mark-incident.js +171 -0
  340. package/dist/tools/mark-incident.js.map +1 -0
  341. package/dist/tools/merged-browser.d.ts +11 -0
  342. package/dist/tools/merged-browser.d.ts.map +1 -0
  343. package/dist/tools/merged-browser.js +20 -0
  344. package/dist/tools/merged-browser.js.map +1 -0
  345. package/dist/tools/merged-context.d.ts +11 -0
  346. package/dist/tools/merged-context.d.ts.map +1 -0
  347. package/dist/tools/merged-context.js +21 -0
  348. package/dist/tools/merged-context.js.map +1 -0
  349. package/dist/tools/merged-observe.d.ts +13 -0
  350. package/dist/tools/merged-observe.d.ts.map +1 -0
  351. package/dist/tools/merged-observe.js +21 -0
  352. package/dist/tools/merged-observe.js.map +1 -0
  353. package/dist/tools/merged-workspace.d.ts +14 -0
  354. package/dist/tools/merged-workspace.d.ts.map +1 -0
  355. package/dist/tools/merged-workspace.js +21 -0
  356. package/dist/tools/merged-workspace.js.map +1 -0
  357. package/dist/tools/observe-runtime.d.ts +262 -0
  358. package/dist/tools/observe-runtime.d.ts.map +1 -0
  359. package/dist/tools/observe-runtime.js +1966 -0
  360. package/dist/tools/observe-runtime.js.map +1 -0
  361. package/dist/tools/observe-tests.d.ts +57 -0
  362. package/dist/tools/observe-tests.d.ts.map +1 -0
  363. package/dist/tools/observe-tests.js +391 -0
  364. package/dist/tools/observe-tests.js.map +1 -0
  365. package/dist/tools/observe.d.ts +28 -0
  366. package/dist/tools/observe.d.ts.map +1 -0
  367. package/dist/tools/observe.js +291 -0
  368. package/dist/tools/observe.js.map +1 -0
  369. package/dist/tools/pr-analysis.d.ts +189 -0
  370. package/dist/tools/pr-analysis.d.ts.map +1 -0
  371. package/dist/tools/pr-analysis.js +365 -0
  372. package/dist/tools/pr-analysis.js.map +1 -0
  373. package/dist/tools/pre-push.d.ts +168 -0
  374. package/dist/tools/pre-push.d.ts.map +1 -0
  375. package/dist/tools/pre-push.js +416 -0
  376. package/dist/tools/pre-push.js.map +1 -0
  377. package/dist/tools/predict-reach.d.ts +57 -0
  378. package/dist/tools/predict-reach.d.ts.map +1 -0
  379. package/dist/tools/predict-reach.js +183 -0
  380. package/dist/tools/predict-reach.js.map +1 -0
  381. package/dist/tools/propagation.d.ts +37 -0
  382. package/dist/tools/propagation.d.ts.map +1 -0
  383. package/dist/tools/propagation.js +162 -0
  384. package/dist/tools/propagation.js.map +1 -0
  385. package/dist/tools/propose-journey.d.ts +16 -0
  386. package/dist/tools/propose-journey.d.ts.map +1 -0
  387. package/dist/tools/propose-journey.js +132 -0
  388. package/dist/tools/propose-journey.js.map +1 -0
  389. package/dist/tools/prove-reach.d.ts +74 -0
  390. package/dist/tools/prove-reach.d.ts.map +1 -0
  391. package/dist/tools/prove-reach.js +274 -0
  392. package/dist/tools/prove-reach.js.map +1 -0
  393. package/dist/tools/questions.d.ts +30 -0
  394. package/dist/tools/questions.d.ts.map +1 -0
  395. package/dist/tools/questions.js +230 -0
  396. package/dist/tools/questions.js.map +1 -0
  397. package/dist/tools/refusal-fetch.d.ts +35 -0
  398. package/dist/tools/refusal-fetch.d.ts.map +1 -0
  399. package/dist/tools/refusal-fetch.js +123 -0
  400. package/dist/tools/refusal-fetch.js.map +1 -0
  401. package/dist/tools/runtime-incident.d.ts +33 -0
  402. package/dist/tools/runtime-incident.d.ts.map +1 -0
  403. package/dist/tools/runtime-incident.js +67 -0
  404. package/dist/tools/runtime-incident.js.map +1 -0
  405. package/dist/tools/runtime-journey-drive.d.ts +102 -0
  406. package/dist/tools/runtime-journey-drive.d.ts.map +1 -0
  407. package/dist/tools/runtime-journey-drive.js +247 -0
  408. package/dist/tools/runtime-journey-drive.js.map +1 -0
  409. package/dist/tools/scope.d.ts +45 -0
  410. package/dist/tools/scope.d.ts.map +1 -0
  411. package/dist/tools/scope.js +217 -0
  412. package/dist/tools/scope.js.map +1 -0
  413. package/dist/tools/similar-incidents.d.ts +43 -0
  414. package/dist/tools/similar-incidents.d.ts.map +1 -0
  415. package/dist/tools/similar-incidents.js +190 -0
  416. package/dist/tools/similar-incidents.js.map +1 -0
  417. package/dist/tools/validate.d.ts +133 -0
  418. package/dist/tools/validate.d.ts.map +1 -0
  419. package/dist/tools/validate.js +488 -0
  420. package/dist/tools/validate.js.map +1 -0
  421. package/dist/tools/verb.d.ts +46 -0
  422. package/dist/tools/verb.d.ts.map +1 -0
  423. package/dist/tools/verb.js +78 -0
  424. package/dist/tools/verb.js.map +1 -0
  425. package/dist/tools/verification-status.d.ts +38 -0
  426. package/dist/tools/verification-status.d.ts.map +1 -0
  427. package/dist/tools/verification-status.js +203 -0
  428. package/dist/tools/verification-status.js.map +1 -0
  429. package/dist/tools/verify-claim.d.ts +29 -0
  430. package/dist/tools/verify-claim.d.ts.map +1 -0
  431. package/dist/tools/verify-claim.js +218 -0
  432. package/dist/tools/verify-claim.js.map +1 -0
  433. package/dist/tools/workspace.d.ts +28 -0
  434. package/dist/tools/workspace.d.ts.map +1 -0
  435. package/dist/tools/workspace.js +94 -0
  436. package/dist/tools/workspace.js.map +1 -0
  437. package/dist/transport.d.ts +32 -0
  438. package/dist/transport.d.ts.map +1 -0
  439. package/dist/transport.js +85 -0
  440. package/dist/transport.js.map +1 -0
  441. package/dist/workspace-index.d.ts +164 -0
  442. package/dist/workspace-index.d.ts.map +1 -0
  443. package/dist/workspace-index.js +381 -0
  444. package/dist/workspace-index.js.map +1 -0
  445. package/package.json +5 -5
@@ -0,0 +1,653 @@
1
+ /**
2
+ * `browser_start_session` — opens a real browser (DEC-380: consent lives here only,
3
+ * bound to the target URL's origin — `browser_navigate` refuses to leave it). Class
4
+ * `action`: the only browser tool that mints a token; the verbs it consents for
5
+ * redeem nothing, since the session is already confirmed. */
6
+ import { CANCELLED_STATE, cancellationHeadline, cancellationNotes } from "../cancellation.js";
7
+ import { browserAnswer, emptyEvidence, observeAndCorrelate, reachNotes } from "../browser/tool-support.js";
8
+ import { NO_GRAPH_WRITE } from "../browser/graph-write.js";
9
+ import { isAbsolute, join } from "node:path";
10
+ import { runPreflight } from "@descryy/runtime-controller";
11
+ import { loadStackParser, StackParserLoadError } from "../browser/stack-parser.js";
12
+ import { headerSecrets, loadStorageStateFile, parseStorageStateJson, resolveSavePath, storageStateSecrets } from "../browser/auth.js";
13
+ import { checkUrlScheme } from "../browser/url-scheme.js";
14
+ import { buildBrowserToolReadyChecks } from "../ready-checks.js";
15
+ import { optionalBoolean, optionalEnum, optionalString, requiredString, ToolInputError } from "./kit.js";
16
+ const SCHEMA = {
17
+ type: "object",
18
+ properties: {
19
+ targetUrl: {
20
+ type: "string",
21
+ description: "REQUIRED. The URL to open, including scheme and port — \"http://localhost:3000/invoices\". " +
22
+ "This is also what consent is granted for: the browser may be driven anywhere on this URL's " +
23
+ "origin for the life of the session, and navigating off it refuses rather than asking again.",
24
+ },
25
+ headless: {
26
+ type: "boolean",
27
+ description: "Run without a visible window. Defaults to true; pass false to watch it happen.",
28
+ },
29
+ stackParser: {
30
+ type: "object",
31
+ description: "The module that can parse this application's stack traces, named the way observe_runtime names a " +
32
+ "runtime adapter. Without one, requests are still observed and the endpoints they reached are still " +
33
+ "named, but NO frontend→backend caller edge is written — a parsed call site is what the confirmation " +
34
+ "needs, and there is no way to guess one. The reply says so rather than reporting a run that found " +
35
+ "nothing.\n\n" +
36
+ 'WORKED EXAMPLE: the module to name is "@descryy/runtime-adapter-<language>" — one such package ' +
37
+ "exists per frontend language (never guess a name; a wrong one refuses rather than silently doing " +
38
+ 'nothing), each exporting a single "create<Name>StackTraceParser" factory, so most calls need only ' +
39
+ '{ "module": "@descryy/runtime-adapter-<language>" } with no "export". Pick the package matching the ' +
40
+ "language the *frontend* is written in, not the backend. The intuitively-named " +
41
+ "@descryy/runtime-browser is never the right answer here — despite the name, it exports no " +
42
+ 'stack-trace parser at all. A package exporting more than one factory (one per web framework it ' +
43
+ 'covers) requires "export" to say which.',
44
+ properties: {
45
+ module: { type: "string", description: "Module specifier to import, e.g. a runtime adapter package for the language your frontend is written in." },
46
+ export: { type: "string", description: "Named export to call. Defaults to the module's single create*StackTraceParser factory; two matches is an error rather than a guess." },
47
+ },
48
+ required: ["module"],
49
+ additionalProperties: false,
50
+ },
51
+ documentRoot: {
52
+ type: "string",
53
+ description: "The directory on disk that the target URL's origin serves files from, if it is not the repository " +
54
+ "root. Absolute, or relative to the repository. THIS IS THE ONE THAT SILENTLY BREAKS THE ARROW: a " +
55
+ "server that serves scripts out of \"public/\" makes public/ the document root while the repo root is " +
56
+ "one level above it, and getting it wrong resolves a script URL to a path that does not exist, which " +
57
+ "degrades the call-site stack to nothing and produces a run that looks clean and confirmed no edges. " +
58
+ "Defaults to the repository root.",
59
+ },
60
+ environment: {
61
+ type: "object",
62
+ description: "The environment profile this session runs against, if you have one. Its safetyLevel governs " +
63
+ "whether the session may change the application: \"readOnly\" refuses browser_click, browser_type " +
64
+ "and browser_fill while still permitting browser_navigate and browser_snapshot. Declared once here " +
65
+ "rather than per call, and it is the same profile observe_runtime takes — a browser run and a " +
66
+ "runtime run must not hold two different opinions about the same environment (DEC-270). Omit it and " +
67
+ "the session's own consent is the only authorization, which still means this call had to be confirmed.",
68
+ properties: {
69
+ name: { type: "string", description: "The profile's name, free-form. Named back to you in any refusal it causes." },
70
+ safetyLevel: {
71
+ type: "string",
72
+ enum: ["readOnly", "write", "destructiveWithApproval"],
73
+ description: "\"readOnly\" refuses every action that could change the application, whatever the profile is " +
74
+ "called — a profile named \"local\" with safetyLevel \"readOnly\" is read-only too.",
75
+ },
76
+ },
77
+ required: ["name", "safetyLevel"],
78
+ additionalProperties: true,
79
+ },
80
+ storageState: {
81
+ type: "object",
82
+ description: "11.4-b: an already-authenticated session to seed before the first navigation. Without this, " +
83
+ "browser_click/type/fill can drive a login form within the consented origin, but cannot reach a " +
84
+ "screen that requires an existing session, and every fresh session re-authenticates from scratch. " +
85
+ "Both fields are scoped to targetUrl's own origin by construction — there is no way to name a " +
86
+ "second origin here, so this cannot widen the session's consent.",
87
+ properties: {
88
+ cookies: {
89
+ type: "array",
90
+ description: "Cookies to set before navigating, scoped to targetUrl's own origin.",
91
+ items: {
92
+ type: "object",
93
+ properties: {
94
+ name: { type: "string" },
95
+ value: { type: "string" },
96
+ path: { type: "string", description: "Defaults to \"/\"." },
97
+ httpOnly: { type: "boolean" },
98
+ secure: { type: "boolean" },
99
+ sameSite: { type: "string", enum: ["Strict", "Lax", "None"] },
100
+ },
101
+ required: ["name", "value"],
102
+ additionalProperties: false,
103
+ },
104
+ },
105
+ localStorage: {
106
+ type: "object",
107
+ description: "localStorage entries to set for targetUrl's own origin before navigating, as string values.",
108
+ additionalProperties: { type: "string" },
109
+ },
110
+ },
111
+ additionalProperties: false,
112
+ },
113
+ storageStatePath: {
114
+ type: "string",
115
+ description: "A FILE holding a saved browser storage state, instead of naming cookies inline. Absolute, or " +
116
+ "relative to the repository root. This is the practical way to reach a logged-in screen: start one " +
117
+ "session with headless false and saveStorageStateTo, log in by hand, close it — every later session " +
118
+ "seeds from that file and nobody logs in again. Anything in the file outside this session's " +
119
+ "consented origin is REFUSED by name, not quietly dropped.",
120
+ },
121
+ storageStateCredential: {
122
+ type: "string",
123
+ description: "The NAME of a credential holding a saved browser storage state (the same JSON shape " +
124
+ "storageStatePath reads: a \"cookies\" array and an \"origins\" array), instead of a file on disk. " +
125
+ "Reused a logged-in session without a login-form step or a live file. Set with `descry credential " +
126
+ "set <name>`, reading the JSON from stdin. Refuses by name when no credential store is configured on " +
127
+ "this server, when nothing is stored under the name, or when the value isn't a storage state this " +
128
+ "session's origin can use — never quietly falls back to an unauthenticated session. Anything in it " +
129
+ "outside this session's consented origin is REFUSED by name, not quietly dropped, exactly as " +
130
+ "storageStatePath's own file check does.",
131
+ },
132
+ extraHttpHeaders: {
133
+ type: "object",
134
+ description: "Headers added to every request this session makes TO THE CONSENTED ORIGIN — typically " +
135
+ "{\"Authorization\": \"Bearer ...\"} for an application whose credential is a token rather than a " +
136
+ "cookie. Deliberately NOT sent to any other host: headers set on a whole browser travel with every " +
137
+ "request it makes, which on an ordinary page means handing your token to every third-party script, " +
138
+ "font and analytics endpoint the page loads.",
139
+ additionalProperties: { type: "string" },
140
+ },
141
+ saveStorageStateTo: {
142
+ type: "string",
143
+ description: "Write this session's cookies and stored data to this file when the session closes, so a login done " +
144
+ "once here can seed later sessions with storageStatePath. Must be an ABSOLUTE PATH OUTSIDE THE " +
145
+ "REPOSITORY — the file is a live credential, and one written into a working tree is one `git add .` " +
146
+ "from being committed.",
147
+ },
148
+ confirmToken: {
149
+ type: "string",
150
+ description: "The token returned by a previous call. Starting a browser session takes two calls: the first " +
151
+ "returns a token and launches nothing, the second redeems it — with the arguments frozen when the " +
152
+ "token was minted, never whatever the second call supplies, so changing targetUrl, stackParser or " +
153
+ "any other field on the confirming call is discarded rather than applied, and the reply discloses " +
154
+ "that it was; call again without confirmToken for a fresh " +
155
+ "token if something needs to change. A token is single-use, expires, and is only valid for this " +
156
+ "tool. Consent is granted once here — the click, type and fill tools need no token of their own.",
157
+ },
158
+ },
159
+ required: ["targetUrl"],
160
+ additionalProperties: false,
161
+ };
162
+ const SAFETY_LEVELS = ["readOnly", "write", "destructiveWithApproval"];
163
+ /** Reads the profile, doesn't re-derive it — only the 2 fields this surface consults.
164
+ * `additionalProperties: true` lets a caller pass the same object it gives
165
+ * `observe_runtime` without trimming a second copy. */
166
+ function readProfile(args) {
167
+ const raw = args["environment"];
168
+ if (raw === undefined || raw === null)
169
+ return null;
170
+ if (typeof raw !== "object" || Array.isArray(raw))
171
+ throw new ToolInputError('"environment" must be an object');
172
+ const fields = raw;
173
+ const name = requiredString(fields, "name");
174
+ const safetyLevel = optionalEnum(fields, "safetyLevel", SAFETY_LEVELS);
175
+ if (safetyLevel === undefined) {
176
+ throw new ToolInputError('"environment.safetyLevel" is required when an environment is given — a profile with no declared ' +
177
+ "safety level would be read as permitting everything, which is the one reading it must never get by default");
178
+ }
179
+ return { name, safetyLevel };
180
+ }
181
+ const COOKIE_SAME_SITE = ["Strict", "Lax", "None"];
182
+ /**
183
+ * 11.4-b: an already-authenticated session to seed before the first navigation.
184
+ * No "domain" field is read from a cookie — not merely ignored, refused — so a
185
+ * caller cannot silently widen a session's consent to a second origin the way
186
+ * accepting and dropping one would risk if a future reader trusted the field
187
+ * existed. The driver scopes every seeded cookie to `targetUrl`'s own origin.
188
+ */
189
+ function readStorageState(args) {
190
+ const raw = args["storageState"];
191
+ if (raw === undefined || raw === null)
192
+ return null;
193
+ if (typeof raw !== "object" || Array.isArray(raw))
194
+ throw new ToolInputError('"storageState" must be an object');
195
+ const fields = raw;
196
+ const rawCookies = fields["cookies"];
197
+ let cookies;
198
+ if (rawCookies !== undefined) {
199
+ if (!Array.isArray(rawCookies))
200
+ throw new ToolInputError('"storageState.cookies" must be an array');
201
+ cookies = rawCookies.map((entry, index) => {
202
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
203
+ throw new ToolInputError(`"storageState.cookies[${index}]" must be an object`);
204
+ }
205
+ const cookie = entry;
206
+ if ("domain" in cookie) {
207
+ throw new ToolInputError(`"storageState.cookies[${index}].domain" is not accepted — a seeded cookie is always scoped to ` +
208
+ "targetUrl's own origin, never a domain the caller names, so a session's consent cannot be " +
209
+ "silently widened to a second origin.");
210
+ }
211
+ const name = requiredString(cookie, "name");
212
+ const value = requiredString(cookie, "value");
213
+ const path = optionalString(cookie, "path");
214
+ const httpOnly = optionalBoolean(cookie, "httpOnly");
215
+ const secure = optionalBoolean(cookie, "secure");
216
+ const sameSite = optionalEnum(cookie, "sameSite", COOKIE_SAME_SITE);
217
+ return {
218
+ name,
219
+ value,
220
+ ...(path === undefined ? {} : { path }),
221
+ ...(httpOnly === undefined ? {} : { httpOnly }),
222
+ ...(secure === undefined ? {} : { secure }),
223
+ ...(sameSite === undefined ? {} : { sameSite }),
224
+ };
225
+ });
226
+ }
227
+ const rawLocalStorage = fields["localStorage"];
228
+ let localStorage;
229
+ if (rawLocalStorage !== undefined) {
230
+ if (typeof rawLocalStorage !== "object" || rawLocalStorage === null || Array.isArray(rawLocalStorage)) {
231
+ throw new ToolInputError('"storageState.localStorage" must be an object of string values');
232
+ }
233
+ for (const [key, value] of Object.entries(rawLocalStorage)) {
234
+ if (typeof value !== "string")
235
+ throw new ToolInputError(`"storageState.localStorage.${key}" must be a string`);
236
+ }
237
+ localStorage = rawLocalStorage;
238
+ }
239
+ if (cookies === undefined && localStorage === undefined)
240
+ return null;
241
+ return { ...(cookies === undefined ? {} : { cookies }), ...(localStorage === undefined ? {} : { localStorage }) };
242
+ }
243
+ /**
244
+ * Resolves `storageStateCredential` against `Session.credentialStore` — the smaller of the two
245
+ * reuse mechanisms RG-1(4)'s "signin" lane chose to build (the other, wiring
246
+ * `BrowserPageSession.injectStorageState` into scenario replay, would need a new step kind in
247
+ * the scenario schema and its own projection/replay path; this reuses the storage-state
248
+ * machinery `loadStorageStateFile` already established for the file case).
249
+ *
250
+ * Same refusal discipline as a missing/malformed file: named, before anything launches, never a
251
+ * silent fall-through to an unauthenticated session.
252
+ */
253
+ async function readStorageStateCredential(name, origin, ctx) {
254
+ if (ctx.session.credentialStore === undefined) {
255
+ throw new ToolInputError(`"storageStateCredential" named "${name}", but no credential store is configured on this server. Set one ` +
256
+ 'up and store the value with `descry credential set ${name}` (piped through stdin, never typed as an ' +
257
+ "argument), reading the JSON that a session started with saveStorageStateTo already wrote.");
258
+ }
259
+ const value = await ctx.session.credentialStore.retrieve(name);
260
+ if (value === null) {
261
+ throw new ToolInputError(`"storageStateCredential" named "${name}", and nothing is stored under that name. Store a saved storage ` +
262
+ `state there first: start a session with headless false and saveStorageStateTo, log in by hand, close ` +
263
+ `it, then \`descry credential set ${name}\` < that file.`);
264
+ }
265
+ if (value === "") {
266
+ throw new ToolInputError(`the credential "${name}" is stored and empty. An empty storage state is refused rather than used — it ` +
267
+ "would seed a session with nothing, which reads as an ordinary logged-out run rather than the " +
268
+ "misconfiguration it actually is.");
269
+ }
270
+ return parseStorageStateJson(value, `credential "${name}"`, { consentedOrigin: origin, repoPath: ctx.session.repoPath });
271
+ }
272
+ /**
273
+ * Extra headers, or null. Values are checked but never echoed.
274
+ */
275
+ function readExtraHttpHeaders(args) {
276
+ const raw = args["extraHttpHeaders"];
277
+ if (raw === undefined || raw === null)
278
+ return null;
279
+ if (typeof raw !== "object" || Array.isArray(raw))
280
+ throw new ToolInputError('"extraHttpHeaders" must be an object');
281
+ const headers = {};
282
+ for (const [name, value] of Object.entries(raw)) {
283
+ if (typeof value !== "string")
284
+ throw new ToolInputError(`"extraHttpHeaders.${name}" must be a string`);
285
+ headers[name] = value;
286
+ }
287
+ if (Object.keys(headers).length === 0)
288
+ throw new ToolInputError('"extraHttpHeaders" was given with no headers in it');
289
+ return headers;
290
+ }
291
+ function readStackParserSpec(args) {
292
+ const raw = args["stackParser"];
293
+ if (raw === undefined || raw === null)
294
+ return null;
295
+ if (typeof raw !== "object" || Array.isArray(raw))
296
+ throw new ToolInputError('"stackParser" must be an object');
297
+ const fields = raw;
298
+ const module = requiredString(fields, "module");
299
+ const named = optionalString(fields, "export");
300
+ return named === undefined ? { module } : { module, export: named };
301
+ }
302
+ function parseTarget(args) {
303
+ const raw = requiredString(args, "targetUrl");
304
+ let url;
305
+ try {
306
+ url = new URL(raw);
307
+ }
308
+ catch {
309
+ throw new ToolInputError(`"targetUrl" must be an absolute URL including scheme — got "${raw}". A bare host or path cannot be ` +
310
+ "opened, and cannot be turned into the origin this session's consent is bound to.");
311
+ }
312
+ // file:/data: (untrusted schemes) resolve to origin "null", collapsing
313
+ // tool-support.ts's same-origin containment — see url-scheme.ts.
314
+ const scheme = checkUrlScheme(url);
315
+ if (!scheme.allowed)
316
+ throw new ToolInputError(scheme.reason);
317
+ return url;
318
+ }
319
+ function cancelledBeforeLaunch(ctx, target, safetyLevel) {
320
+ return browserAnswer({
321
+ ctx,
322
+ state: CANCELLED_STATE,
323
+ headline: cancellationHeadline("no browser session is open"),
324
+ notes: cancellationNotes("No browser was left running.", "If a browser had already opened when the cancellation arrived, it has been closed and whatever it " +
325
+ "had observed was flushed with it."),
326
+ data: {
327
+ sessionId: "",
328
+ url: target.href,
329
+ title: "",
330
+ consentedOrigin: target.origin,
331
+ safetyLevel,
332
+ totalElements: 0,
333
+ evidence: emptyEvidence(),
334
+ graph: NO_GRAPH_WRITE,
335
+ },
336
+ });
337
+ }
338
+ async function run(args, ctx) {
339
+ const target = parseTarget(args);
340
+ const headless = optionalBoolean(args, "headless") ?? true;
341
+ const profile = readProfile(args);
342
+ const inlineState = readStorageState(args);
343
+ const statePath = optionalString(args, "storageStatePath");
344
+ const stateCredential = optionalString(args, "storageStateCredential");
345
+ const stateSourcesGiven = [inlineState !== null, statePath !== undefined, stateCredential !== undefined].filter(Boolean).length;
346
+ if (stateSourcesGiven > 1) {
347
+ throw new ToolInputError('"storageState", "storageStatePath" and "storageStateCredential" — more than one was given. There is no ' +
348
+ "precedence rule between them on purpose — picking one silently is how a session ends up seeded from a " +
349
+ "source the caller believed they had overridden. Give exactly one.");
350
+ }
351
+ // Read before anything launches, for the same reason the stack parser below
352
+ // is: an unreadable file, an unresolvable credential, or a cookie for
353
+ // another host is a refusal the caller can fix, and discovering it after a
354
+ // browser is open would mean a session that silently drove the logged-out
355
+ // surface instead.
356
+ const storageState = statePath !== undefined
357
+ ? loadStorageStateFile(statePath, { consentedOrigin: target.origin, repoPath: ctx.session.repoPath })
358
+ : stateCredential !== undefined
359
+ ? await readStorageStateCredential(stateCredential, target.origin, ctx)
360
+ : inlineState;
361
+ const extraHttpHeaders = readExtraHttpHeaders(args);
362
+ const rawSavePath = optionalString(args, "saveStorageStateTo");
363
+ const saveStorageStateTo = rawSavePath === undefined ? undefined : resolveSavePath(rawSavePath, ctx.session.repoPath);
364
+ // Registered before the launch, not after: if the launch throws, these are
365
+ // still the values anything this server writes must refuse to carry.
366
+ ctx.session.noteBrowserSecrets([...storageStateSecrets(storageState), ...headerSecrets(extraHttpHeaders)]);
367
+ const parserSpec = readStackParserSpec(args);
368
+ const documentRoot = optionalString(args, "documentRoot");
369
+ const backend = ctx.session.browserBackend();
370
+ // Before anything launches — a browser opened for a caller who's already gone is
371
+ // one nothing will ever close (its session id never reaches a suppressed reply);
372
+ // only the 5-minute idle reaper would eventually catch it.
373
+ if (ctx.signal.aborted)
374
+ return cancelledBeforeLaunch(ctx, target, null);
375
+ if (!backend.available) {
376
+ return browserAnswer({
377
+ ctx,
378
+ state: "refused",
379
+ headline: "This build cannot open a browser.",
380
+ notes: [backend.reason, `Remedy: ${backend.remedy}`],
381
+ data: { sessionId: "", url: target.href, title: "", consentedOrigin: target.origin, safetyLevel: null, totalElements: 0, evidence: emptyEvidence(), graph: NO_GRAPH_WRITE },
382
+ });
383
+ }
384
+ // Parser loaded before anything launches — a bad parser is a fixable refusal here;
385
+ // discovering it after a browser is open means tearing it down or running a
386
+ // session that silently can't write the edge it opened for.
387
+ let parser;
388
+ try {
389
+ parser = parserSpec === null ? undefined : await loadStackParser(parserSpec);
390
+ }
391
+ catch (error) {
392
+ if (!(error instanceof StackParserLoadError))
393
+ throw error;
394
+ return browserAnswer({
395
+ ctx,
396
+ state: "refused",
397
+ headline: `Could not load the stack-trace parser "${error.specifier}".`,
398
+ notes: [error.message],
399
+ data: { sessionId: "", url: target.href, title: "", consentedOrigin: target.origin, safetyLevel: null, totalElements: 0, evidence: emptyEvidence(), graph: NO_GRAPH_WRITE },
400
+ });
401
+ }
402
+ // Closed here rather than left to a caller: the origin driven must map to
403
+ // the directory actually serving its scripts — `documentRoot` overrides the repo
404
+ // root for the `public/` case the schema describes.
405
+ const servedFrom = documentRoot === undefined
406
+ ? ctx.session.repoPath
407
+ : isAbsolute(documentRoot)
408
+ ? documentRoot
409
+ : join(ctx.session.repoPath, documentRoot);
410
+ const resolveSourceRoot = (origin) => origin === target.origin
411
+ ? { found: true, root: { serviceName: ctx.session.config.repo, declaredCwd: servedFrom } }
412
+ : { found: false, refusal: "noProcessOnPort", message: `${origin} is not the origin this session was opened against` };
413
+ ctx.progress(`Opening a browser at ${target.href}`);
414
+ const driver = await backend.createDriver({
415
+ ...(parser === undefined ? {} : { stackParser: parser }),
416
+ resolveSourceRoot,
417
+ service: ctx.session.config.repo,
418
+ });
419
+ // RT-263: ready check before a real Chromium is spent learning the same thing the
420
+ // slow way -- the "the port is free, or the app answers (for attach)" bullet of
421
+ // Build A. Every `browser_start_session` call is the attach case: this tool never
422
+ // boots a service of its own, it only opens a browser against one the caller says
423
+ // is already running. Optional on the port (`driver.probeTargetReachable`) so the
424
+ // fake driver `packages/mcp/test`'s suites use -- pointed at made-up ports nothing
425
+ // really listens on -- never runs a real network probe; only the real Chromium
426
+ // driver (`playwright-driver.ts`) implements it.
427
+ const reachability = await driver.probeTargetReachable?.(target.href);
428
+ if (reachability !== undefined && reachability !== null && !reachability.reachable) {
429
+ return browserAnswer({
430
+ ctx,
431
+ state: "refused",
432
+ headline: `Cannot open a browser session at ${target.href} — the target does not answer.`,
433
+ notes: [reachability.message],
434
+ data: { sessionId: "", url: target.href, title: "", consentedOrigin: target.origin, safetyLevel: null, totalElements: 0, evidence: emptyEvidence(), graph: NO_GRAPH_WRITE },
435
+ });
436
+ }
437
+ const ready = await runPreflight(buildBrowserToolReadyChecks(ctx.session));
438
+ if (ready.status === "broken") {
439
+ return browserAnswer({
440
+ ctx,
441
+ state: "refused",
442
+ headline: `Cannot open a browser session at ${target.href} — the environment is not ready.`,
443
+ notes: ready.checks.filter((check) => check.required && !check.ok).map((check) => `${check.label} — ${check.message}`),
444
+ data: { sessionId: "", url: target.href, title: "", consentedOrigin: target.origin, safetyLevel: null, totalElements: 0, evidence: emptyEvidence(), graph: NO_GRAPH_WRITE },
445
+ });
446
+ }
447
+ const opened = await ctx.session.browserSessions().open(driver, {
448
+ targetUrl: target.href,
449
+ headless,
450
+ profile,
451
+ ...(storageState === null ? {} : { storageState }),
452
+ ...(extraHttpHeaders === null ? {} : { extraHttpHeaders }),
453
+ ...(saveStorageStateTo === undefined ? {} : { saveStorageStateTo }),
454
+ });
455
+ if (!opened.opened) {
456
+ const notes = opened.kind === "atCapacity"
457
+ ? [opened.reason]
458
+ : // Remedy travels verbatim — "could not launch" and stopping there is a
459
+ // refusal the developer has to go research themselves.
460
+ [opened.message, `Remedy: ${opened.remedy}`, `Expected the browser at ${opened.expectedExecutablePath}.`];
461
+ return browserAnswer({
462
+ ctx,
463
+ state: "refused",
464
+ headline: opened.kind === "atCapacity" ? "Too many browser sessions are already open." : "No browser is installed.",
465
+ notes,
466
+ data: { sessionId: "", url: target.href, title: "", consentedOrigin: target.origin, safetyLevel: profile?.safetyLevel ?? null, totalElements: 0, evidence: emptyEvidence(), graph: NO_GRAPH_WRITE },
467
+ });
468
+ }
469
+ // The race actually lost in practice: caller cancelled while Chromium was
470
+ // starting, so the launch succeeded for nobody. Closes the session just opened
471
+ // — the one resource this call started, the only one it may tear down.
472
+ if (ctx.signal.aborted) {
473
+ await ctx.session.browserSessions().close(opened.entry.sessionId);
474
+ return cancelledBeforeLaunch(ctx, target, profile?.safetyLevel ?? null);
475
+ }
476
+ const { entry } = opened;
477
+ const snapshot = await entry.page.snapshot();
478
+ const observed = await observeAndCorrelate(ctx, entry);
479
+ const evidence = observed.evidence;
480
+ return browserAnswer({
481
+ ctx,
482
+ headline: `Browser session ${entry.sessionId} open at ${snapshot.url} (${snapshot.totalElements} elements).`,
483
+ notes: [
484
+ ...ready.disclosures,
485
+ ...reachNotes(snapshot),
486
+ `Consent covers ${entry.consentedOrigin} for the life of this session — click, type and fill need no ` +
487
+ "further confirmation, and navigating to another origin will refuse. The session is torn down after " +
488
+ "five idle minutes, when the client disconnects, or when browser_close_session is called.",
489
+ // Names what was seeded, never the values themselves — a cookie or localStorage
490
+ // value is a credential, and this disclosure exists so a caller can tell an
491
+ // authenticated run from an anonymous one without this reply repeating it back.
492
+ ...(storageState === null
493
+ ? []
494
+ : [
495
+ `Storage state was seeded before the first navigation: ${storageState.cookies?.length ?? 0} ` +
496
+ `cookie(s), ${Object.keys(storageState.localStorage ?? {}).length} localStorage key(s) — both ` +
497
+ `scoped to ${entry.consentedOrigin}. No value is printed here or kept in this session's ` +
498
+ "recorded arguments.",
499
+ ]),
500
+ ...(extraHttpHeaders === null
501
+ ? []
502
+ : [
503
+ `Extra request header(s) ${Object.keys(extraHttpHeaders).join(", ")} will be sent on ` +
504
+ `${entry.consentedOrigin} and on no other host — a credential set on the whole browser would ` +
505
+ "travel to every third-party script the page loads. Values are not printed.",
506
+ ]),
507
+ ...(saveStorageStateTo === undefined
508
+ ? []
509
+ : [
510
+ `This session's cookies and stored data will be written to ${saveStorageStateTo} when it closes, ` +
511
+ "so a login performed here can seed later sessions with storageStatePath. That file is a live " +
512
+ "credential; it is outside the repository for that reason.",
513
+ ]),
514
+ // Rule 7: an unauthenticated run is a real, disclosed limit on what was
515
+ // tested, not a neutral default to leave a caller to infer from silence.
516
+ ...(storageState === null && extraHttpHeaders === null
517
+ ? [
518
+ "No authentication material was given, so this session sees what a logged-out visitor sees. " +
519
+ "Anything behind a login was not reached and is not reported on — pass storageStatePath, " +
520
+ "storageState or extraHttpHeaders to reach it.",
521
+ ]
522
+ : []),
523
+ ...(parserSpec === null
524
+ ? [
525
+ "No stackParser was named, so requests will be observed and the endpoints they reach will be " +
526
+ "named, but no frontend→backend caller edge can be written from this session. That is a gap " +
527
+ "in what this run can confirm, not a finding about your application.",
528
+ ]
529
+ : []),
530
+ ...(entry.profile === null
531
+ ? []
532
+ : [
533
+ `Running under environment profile "${entry.profile.name}" (safetyLevel ` +
534
+ `"${entry.profile.safetyLevel}").` +
535
+ (entry.profile.safetyLevel === "readOnly"
536
+ ? " Clicking, typing and filling will be refused; navigate and snapshot remain available."
537
+ : ""),
538
+ ]),
539
+ ...observed.notes,
540
+ ],
541
+ data: {
542
+ sessionId: entry.sessionId,
543
+ url: snapshot.url,
544
+ title: snapshot.title,
545
+ consentedOrigin: entry.consentedOrigin,
546
+ safetyLevel: entry.profile?.safetyLevel ?? null,
547
+ totalElements: snapshot.totalElements,
548
+ evidence,
549
+ graph: observed.graph,
550
+ },
551
+ });
552
+ }
553
+ export const browserStartSessionTool = {
554
+ name: "browser_start_session",
555
+ title: "Open a browser session",
556
+ description: "Open a real browser at a URL in your running application and return a session id the other browser " +
557
+ "tools take. This is where consent is granted: confirming it allows Descry to drive a browser anywhere " +
558
+ "on that URL's origin until the session ends, so the click, type and fill tools do not ask again. " +
559
+ "Reports what the page produced — console errors, failed requests — raw and untriaged; deciding which " +
560
+ "of them matter is yours.",
561
+ class: "action",
562
+ tier: "evidence",
563
+ version: "1.0.0",
564
+ inputSchema: SCHEMA,
565
+ run,
566
+ describeAction(args) {
567
+ const target = parseTarget(args);
568
+ // Same parse the run path uses to enforce the gate (`mutationRefusal` in
569
+ // `tool-support.ts`) — read here, not re-derived, so what's confirmed matches
570
+ // what's enforced.
571
+ const profile = readProfile(args);
572
+ if (profile?.safetyLevel === "readOnly") {
573
+ return (`Descry may navigate, snapshot and wait anywhere on ${target.origin}. Clicking, typing, filling, ` +
574
+ `choosing an option and submitting a form will be refused. It may not leave that origin.`);
575
+ }
576
+ const grant = `Launch a browser and open ${target.href}. For as long as the session lives, Descry may navigate, ` +
577
+ `click, type, fill, choose an option and submit a form anywhere on ${target.origin} without asking ` +
578
+ "again — including actions that change data in that application. It may not leave that origin.";
579
+ // UAT phase 5 §7/B9: absent an explicit safety level, the enforcement really
580
+ // is unrestricted (`mutationRefusal`: no profile ⇒ no refusal) — but the
581
+ // prompt must say that is *because no profile was supplied*, not state
582
+ // unrestricted authority as though it had been deliberately chosen. A
583
+ // consent prompt that reads the same whether a level was set or omitted
584
+ // hides the one piece of information that would tell a caller to go set one.
585
+ // B1: credentials change what is being approved, so they change this
586
+ // text. The unseeded sentence already warns that data may change; a
587
+ // seeded session changes *whose* data — every action runs as the account
588
+ // whose session was handed over. A prompt that read identically either
589
+ // way would be asking for consent to something it had not mentioned.
590
+ const seeded = args["storageState"] !== undefined ||
591
+ args["storageStatePath"] !== undefined ||
592
+ args["storageStateCredential"] !== undefined ||
593
+ args["extraHttpHeaders"] !== undefined;
594
+ const asUser = seeded
595
+ ? " The session will be started ALREADY LOGGED IN, from the authentication material in this call: " +
596
+ "everything it does will be done as that user, with whatever that account is permitted to do, on " +
597
+ "screens a logged-out visitor could not reach. The credential itself is not shown here and will " +
598
+ "not appear in any reply."
599
+ : "";
600
+ return profile === null
601
+ ? `No environment profile was supplied, so nothing here restricts what Descry may do. ${grant}${asUser}`
602
+ : `Environment profile "${profile.name}" declares safetyLevel "${profile.safetyLevel}". ${grant}${asUser}`;
603
+ },
604
+ /**
605
+ * What may be remembered about this call — B1's secrets rule, at the one
606
+ * place a credential enters this server.
607
+ *
608
+ * `server.ts` records every completed call's arguments on the `Session` so
609
+ * `verify_claim` can check a citation against them. This is the only tool
610
+ * whose arguments can be a credential, so it is the only one that
611
+ * implements this.
612
+ *
613
+ * Structural rather than a known-value substitution, deliberately: this
614
+ * runs on the arguments **as the caller sent them**, including for a call
615
+ * refused before any state was built, so there is no validated seed to take
616
+ * a value list from. Names are kept — a reader of a recorded call must
617
+ * still be able to see that a session was seeded and with what kind of
618
+ * material.
619
+ */
620
+ redactArgs(args) {
621
+ const out = { ...args };
622
+ let touched = false;
623
+ if (out["storageState"] !== undefined && out["storageState"] !== null) {
624
+ out["storageState"] = redactStorageStateArgument(out["storageState"]);
625
+ touched = true;
626
+ }
627
+ if (typeof out["extraHttpHeaders"] === "object" && out["extraHttpHeaders"] !== null) {
628
+ out["extraHttpHeaders"] = Object.fromEntries(Object.keys(out["extraHttpHeaders"]).map((name) => [name, REDACTED]));
629
+ touched = true;
630
+ }
631
+ // A path is not a credential, and it is the one thing a reader needs in
632
+ // order to reproduce a run or clean up after it. Left intact.
633
+ return touched ? out : args;
634
+ },
635
+ };
636
+ const REDACTED = "[REDACTED]";
637
+ function redactStorageStateArgument(raw) {
638
+ if (typeof raw !== "object" || raw === null)
639
+ return REDACTED;
640
+ const fields = raw;
641
+ const cookies = Array.isArray(fields["cookies"])
642
+ ? fields["cookies"].map((cookie) => typeof cookie === "object" && cookie !== null ? { ...cookie, value: REDACTED } : REDACTED)
643
+ : fields["cookies"];
644
+ const stored = typeof fields["localStorage"] === "object" && fields["localStorage"] !== null
645
+ ? Object.fromEntries(Object.keys(fields["localStorage"]).map((key) => [key, REDACTED]))
646
+ : fields["localStorage"];
647
+ return {
648
+ ...fields,
649
+ ...(cookies === undefined ? {} : { cookies }),
650
+ ...(stored === undefined ? {} : { localStorage: stored }),
651
+ };
652
+ }
653
+ //# sourceMappingURL=browser-start-session.js.map