@arnilo/prism-tools 0.0.0-stage → 0.13.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 (331) hide show
  1. package/CHANGELOG.md +410 -0
  2. package/LICENSE +21 -0
  3. package/README.md +44 -2
  4. package/browser/README.md +98 -0
  5. package/browser/skills/browser-automation/SKILL.md +14 -0
  6. package/browser/src/actions/cdp.ts +131 -0
  7. package/browser/src/actions/dialog.ts +25 -0
  8. package/browser/src/actions/download_release.ts +22 -0
  9. package/browser/src/actions/index.ts +37 -0
  10. package/browser/src/actions/locator.ts +70 -0
  11. package/browser/src/actions/navigate.ts +23 -0
  12. package/browser/src/actions/screenshot.ts +27 -0
  13. package/browser/src/actions/scroll.ts +24 -0
  14. package/browser/src/actions/select_page.ts +21 -0
  15. package/browser/src/actions/types.ts +114 -0
  16. package/browser/src/actions/upload.ts +44 -0
  17. package/browser/src/actions/wait.ts +45 -0
  18. package/browser/src/browser.ts +197 -0
  19. package/browser/src/cdp.ts +178 -0
  20. package/browser/src/checkpoint.ts +189 -0
  21. package/browser/src/config.ts +72 -0
  22. package/browser/src/downloads.ts +253 -0
  23. package/browser/src/errors.ts +31 -0
  24. package/browser/src/evaluate.ts +101 -0
  25. package/browser/src/index.ts +129 -0
  26. package/browser/src/limits.ts +271 -0
  27. package/browser/src/manager.ts +730 -0
  28. package/browser/src/network.ts +263 -0
  29. package/browser/src/observe.ts +178 -0
  30. package/browser/src/policy.ts +133 -0
  31. package/browser/src/screenshot.ts +107 -0
  32. package/browser/src/shared-sandbox.ts +53 -0
  33. package/browser/src/snapshot.ts +99 -0
  34. package/browser/src/targets.ts +165 -0
  35. package/browser/src/tools.ts +480 -0
  36. package/browser/src/types.ts +316 -0
  37. package/browser/src/uploads.ts +174 -0
  38. package/coding/README.md +337 -0
  39. package/coding/src/agent/acp-operations.ts +146 -0
  40. package/coding/src/agent/artifacts.ts +38 -0
  41. package/coding/src/agent/ask-user-decision.ts +623 -0
  42. package/coding/src/agent/atomic-write.ts +23 -0
  43. package/coding/src/agent/bounded-file.ts +21 -0
  44. package/coding/src/agent/checks.ts +301 -0
  45. package/coding/src/agent/coding-checkpoint.ts +828 -0
  46. package/coding/src/agent/delete.ts +237 -0
  47. package/coding/src/agent/diagnostics-tool.ts +163 -0
  48. package/coding/src/agent/diagnostics.ts +262 -0
  49. package/coding/src/agent/edit-diff.ts +382 -0
  50. package/coding/src/agent/edit.ts +322 -0
  51. package/coding/src/agent/effects.ts +102 -0
  52. package/coding/src/agent/env.ts +28 -0
  53. package/coding/src/agent/execution-policy.ts +89 -0
  54. package/coding/src/agent/file-mutation-queue.ts +72 -0
  55. package/coding/src/agent/forge/github.ts +603 -0
  56. package/coding/src/agent/forge/index.ts +16 -0
  57. package/coding/src/agent/forge/types.ts +185 -0
  58. package/coding/src/agent/git-aware-repository.ts +305 -0
  59. package/coding/src/agent/git-exec.ts +326 -0
  60. package/coding/src/agent/git-status.ts +177 -0
  61. package/coding/src/agent/git-tools.ts +360 -0
  62. package/coding/src/agent/git.ts +1074 -0
  63. package/coding/src/agent/glob-match.ts +146 -0
  64. package/coding/src/agent/glob.ts +182 -0
  65. package/coding/src/agent/goal-verify.ts +385 -0
  66. package/coding/src/agent/grep-worker.ts +74 -0
  67. package/coding/src/agent/grep.ts +459 -0
  68. package/coding/src/agent/identity.ts +48 -0
  69. package/coding/src/agent/index.ts +676 -0
  70. package/coding/src/agent/language/client.ts +429 -0
  71. package/coding/src/agent/language/framing.ts +190 -0
  72. package/coding/src/agent/language/index.ts +23 -0
  73. package/coding/src/agent/language/intelligence.ts +682 -0
  74. package/coding/src/agent/language/types.ts +187 -0
  75. package/coding/src/agent/lifecycle-events.ts +121 -0
  76. package/coding/src/agent/lifecycle.ts +166 -0
  77. package/coding/src/agent/limits.ts +214 -0
  78. package/coding/src/agent/move.ts +178 -0
  79. package/coding/src/agent/mutation-path.ts +52 -0
  80. package/coding/src/agent/output-accumulator.ts +304 -0
  81. package/coding/src/agent/path-utils.ts +120 -0
  82. package/coding/src/agent/process/index.ts +58 -0
  83. package/coding/src/agent/process/recovery.ts +508 -0
  84. package/coding/src/agent/process/sessions-host.ts +222 -0
  85. package/coding/src/agent/process/sessions-monitor.ts +141 -0
  86. package/coding/src/agent/process/sessions-recovery.ts +241 -0
  87. package/coding/src/agent/process/sessions-spawn.ts +613 -0
  88. package/coding/src/agent/process/sessions-teardown.ts +281 -0
  89. package/coding/src/agent/process/sessions.ts +30 -0
  90. package/coding/src/agent/process/types.ts +358 -0
  91. package/coding/src/agent/read-path-set.ts +126 -0
  92. package/coding/src/agent/read.ts +713 -0
  93. package/coding/src/agent/repository/glob.ts +147 -0
  94. package/coding/src/agent/repository/indexed-search.ts +480 -0
  95. package/coding/src/agent/repository/list.ts +131 -0
  96. package/coding/src/agent/repository/operations.ts +22 -0
  97. package/coding/src/agent/repository/path.ts +98 -0
  98. package/coding/src/agent/repository/search.ts +277 -0
  99. package/coding/src/agent/repository/types.ts +243 -0
  100. package/coding/src/agent/repository/walk.ts +126 -0
  101. package/coding/src/agent/repository.ts +12 -0
  102. package/coding/src/agent/shell-background.ts +264 -0
  103. package/coding/src/agent/shell-output.ts +75 -0
  104. package/coding/src/agent/shell.ts +526 -0
  105. package/coding/src/agent/todo.ts +399 -0
  106. package/coding/src/agent/truncate.ts +251 -0
  107. package/coding/src/agent/write.ts +170 -0
  108. package/coding/src/ask-user-host.ts +48 -0
  109. package/coding/src/config.ts +278 -0
  110. package/coding/src/hard-deny.ts +97 -0
  111. package/coding/src/index.ts +318 -0
  112. package/coding/src/principal-guard.ts +84 -0
  113. package/coding/src/sandbox.ts +92 -0
  114. package/coding/src/security/approval.ts +144 -0
  115. package/coding/src/security/command-rules.ts +57 -0
  116. package/coding/src/security/docker-cli.ts +222 -0
  117. package/coding/src/security/docker-sandbox.ts +1205 -0
  118. package/coding/src/security/e2b-sandbox.ts +853 -0
  119. package/coding/src/security/egress/dns-pin.ts +88 -0
  120. package/coding/src/security/egress/index.ts +32 -0
  121. package/coding/src/security/egress/limits.ts +57 -0
  122. package/coding/src/security/egress/policy.ts +137 -0
  123. package/coding/src/security/egress/proxy.ts +599 -0
  124. package/coding/src/security/egress/types.ts +30 -0
  125. package/coding/src/security/index.ts +199 -0
  126. package/coding/src/security/native-sandbox.ts +639 -0
  127. package/coding/src/security/path-containment.ts +55 -0
  128. package/coding/src/security/sandbox-coding-operations.ts +392 -0
  129. package/coding/src/security/sandbox-fs-operations.ts +644 -0
  130. package/coding/src/security/sandbox-limits.ts +147 -0
  131. package/coding/src/security/sandbox-tar.ts +308 -0
  132. package/coding/src/security/sandbox.ts +179 -0
  133. package/coding/src/security/semaphore.ts +55 -0
  134. package/coding/src/targets.ts +110 -0
  135. package/coding/src/workspace/diff.ts +78 -0
  136. package/coding/src/workspace/errors.ts +28 -0
  137. package/coding/src/workspace/index.ts +5 -0
  138. package/coding/src/workspace/merge.ts +151 -0
  139. package/coding/src/workspace/routing.ts +76 -0
  140. package/coding/src/workspace/service.ts +545 -0
  141. package/computer-use/README.md +105 -0
  142. package/computer-use/skills/computer-use-linux/SKILL.md +17 -0
  143. package/computer-use/src/classify.ts +53 -0
  144. package/computer-use/src/command.ts +29 -0
  145. package/computer-use/src/config.ts +69 -0
  146. package/computer-use/src/create.ts +170 -0
  147. package/computer-use/src/devices.ts +247 -0
  148. package/computer-use/src/env.ts +28 -0
  149. package/computer-use/src/index.ts +157 -0
  150. package/computer-use/src/skill.ts +21 -0
  151. package/openapi/README.md +97 -0
  152. package/openapi/src/compile.ts +386 -0
  153. package/openapi/src/config.ts +73 -0
  154. package/openapi/src/errors.ts +16 -0
  155. package/openapi/src/execute.ts +241 -0
  156. package/openapi/src/index.ts +124 -0
  157. package/openapi/src/limits.ts +63 -0
  158. package/openapi/src/specs.ts +86 -0
  159. package/openapi/src/tools.ts +60 -0
  160. package/openapi/src/types.ts +61 -0
  161. package/package.json +171 -4
  162. package/research/README.md +72 -0
  163. package/research/skills/research-report/SKILL.md +12 -0
  164. package/research/skills/research-scoping/SKILL.md +10 -0
  165. package/research/skills/research-synthesis/SKILL.md +10 -0
  166. package/research/skills/source-triage/SKILL.md +10 -0
  167. package/research/src/check.ts +71 -0
  168. package/research/src/config.ts +41 -0
  169. package/research/src/index.ts +147 -0
  170. package/research/src/ledger.ts +157 -0
  171. package/research/src/urls.ts +21 -0
  172. package/web/README.md +287 -0
  173. package/web/skills/web-research/SKILL.md +17 -0
  174. package/web/src/brave.ts +66 -0
  175. package/web/src/cache.ts +151 -0
  176. package/web/src/config.ts +210 -0
  177. package/web/src/controls.ts +128 -0
  178. package/web/src/domains.ts +114 -0
  179. package/web/src/exa.ts +60 -0
  180. package/web/src/firecrawl.ts +160 -0
  181. package/web/src/index.ts +387 -0
  182. package/web/src/kagi.ts +73 -0
  183. package/web/src/limits.ts +55 -0
  184. package/web/src/native/convert.ts +84 -0
  185. package/web/src/native/fetch.ts +226 -0
  186. package/web/src/normalize.ts +131 -0
  187. package/web/src/obscura/cdp.ts +201 -0
  188. package/web/src/obscura/classify.ts +35 -0
  189. package/web/src/obscura/cli.ts +254 -0
  190. package/web/src/obscura/errors.ts +8 -0
  191. package/web/src/obscura/index.ts +59 -0
  192. package/web/src/obscura/limits.ts +92 -0
  193. package/web/src/obscura/mcp.ts +104 -0
  194. package/web/src/obscura/playwright.ts +133 -0
  195. package/web/src/obscura/process.ts +235 -0
  196. package/web/src/obscura/search-profile.ts +73 -0
  197. package/web/src/obscura/types.ts +48 -0
  198. package/web/src/obscura/web.ts +419 -0
  199. package/web/src/prompt-fetch.ts +88 -0
  200. package/web/src/render.ts +75 -0
  201. package/web/src/searxng.ts +78 -0
  202. package/web/src/slice.ts +139 -0
  203. package/web/src/tavily.ts +77 -0
  204. package/web/src/tools.ts +182 -0
  205. package/web/src/transport.ts +310 -0
  206. package/web/src/types.ts +199 -0
  207. package/work/README.md +77 -0
  208. package/work/THIRD_PARTY_NOTICES +24 -0
  209. package/work/docling/ocr.py +150 -0
  210. package/work/sandbox/Dockerfile +36 -0
  211. package/work/sandbox/soffice.sh +12 -0
  212. package/work/src/command.ts +29 -0
  213. package/work/src/config.ts +138 -0
  214. package/work/src/connectors/cli.ts +343 -0
  215. package/work/src/connectors/drafts.ts +647 -0
  216. package/work/src/connectors/errors.ts +8 -0
  217. package/work/src/connectors/file-bytes.ts +149 -0
  218. package/work/src/connectors/google-workspace-http.ts +399 -0
  219. package/work/src/connectors/google-workspace.ts +465 -0
  220. package/work/src/connectors/gws-tools.ts +378 -0
  221. package/work/src/connectors/http.ts +123 -0
  222. package/work/src/connectors/idempotency.ts +235 -0
  223. package/work/src/connectors/identity.ts +34 -0
  224. package/work/src/connectors/index.ts +93 -0
  225. package/work/src/connectors/limits.ts +50 -0
  226. package/work/src/connectors/m365-tools.ts +308 -0
  227. package/work/src/connectors/microsoft365-http.ts +428 -0
  228. package/work/src/connectors/microsoft365.ts +402 -0
  229. package/work/src/connectors/normalize.ts +120 -0
  230. package/work/src/connectors/tool-helpers.ts +398 -0
  231. package/work/src/connectors/tools.ts +42 -0
  232. package/work/src/connectors/types.ts +399 -0
  233. package/work/src/diagrams/canonicalize.ts +166 -0
  234. package/work/src/diagrams/caps.ts +52 -0
  235. package/work/src/diagrams/embed.ts +340 -0
  236. package/work/src/diagrams/errors.ts +76 -0
  237. package/work/src/diagrams/index.ts +81 -0
  238. package/work/src/diagrams/messages.ts +150 -0
  239. package/work/src/diagrams/origin.ts +52 -0
  240. package/work/src/diagrams/telemetry.ts +34 -0
  241. package/work/src/diagrams/xml.ts +267 -0
  242. package/work/src/document-extraction/index.ts +563 -0
  243. package/work/src/document-reader/ambient.d.ts +2 -0
  244. package/work/src/document-reader/errors.ts +7 -0
  245. package/work/src/document-reader/index.ts +181 -0
  246. package/work/src/document-reader/mistral-ocr.ts +318 -0
  247. package/work/src/document-reader/parsers.ts +171 -0
  248. package/work/src/documents/caps.ts +135 -0
  249. package/work/src/documents/diff.ts +269 -0
  250. package/work/src/documents/errors.ts +44 -0
  251. package/work/src/documents/fidelity.ts +98 -0
  252. package/work/src/documents/generate.ts +96 -0
  253. package/work/src/documents/hash.ts +8 -0
  254. package/work/src/documents/index.ts +14 -0
  255. package/work/src/documents/model-schema.ts +639 -0
  256. package/work/src/documents/parse.ts +252 -0
  257. package/work/src/documents/patch-history.ts +81 -0
  258. package/work/src/documents/patch.ts +476 -0
  259. package/work/src/documents/preview-html.ts +245 -0
  260. package/work/src/documents/preview.ts +227 -0
  261. package/work/src/documents/telemetry.ts +36 -0
  262. package/work/src/documents/translate/docx.ts +292 -0
  263. package/work/src/documents/translate/pptx.ts +304 -0
  264. package/work/src/documents/translate/xlsx.ts +137 -0
  265. package/work/src/documents/types.ts +188 -0
  266. package/work/src/index.ts +311 -0
  267. package/work/src/runtime/worker-pool-entry.ts +102 -0
  268. package/work/src/runtime/worker-pool.ts +267 -0
  269. package/work/src/sandbox/composition.ts +212 -0
  270. package/work/src/sandbox/image.ts +6 -0
  271. package/work/src/sandbox/index.ts +14 -0
  272. package/work/src/sheets/caps.ts +68 -0
  273. package/work/src/sheets/csv.ts +351 -0
  274. package/work/src/sheets/decimal.ts +388 -0
  275. package/work/src/sheets/errors.ts +52 -0
  276. package/work/src/sheets/index.ts +62 -0
  277. package/work/src/sheets/inference.ts +378 -0
  278. package/work/src/sheets/telemetry.ts +34 -0
  279. package/work/src/sheets/types.ts +162 -0
  280. package/work/src/sheets/xlsx.ts +388 -0
  281. package/work/src/skills/index.ts +8 -0
  282. package/work/src/skills/load.ts +43 -0
  283. package/work/src/tools/filesystem.ts +21 -0
  284. package/work/src/tools/index.ts +1 -0
  285. package/work/src/tools/local-filesystem.ts +33 -0
  286. package/work/src/tools/office.ts +311 -0
  287. package/work/vendor/hermes-agent/LICENSE +21 -0
  288. package/work/vendor/hermes-agent/skills/productivity/docx/LICENSE +21 -0
  289. package/work/vendor/hermes-agent/skills/productivity/docx/SKILL.md +196 -0
  290. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_comments.py +289 -0
  291. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_common.py +94 -0
  292. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_create.py +177 -0
  293. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_edit.py +250 -0
  294. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_read.py +149 -0
  295. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_revisions.py +147 -0
  296. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_template.py +70 -0
  297. package/work/vendor/hermes-agent/skills/productivity/docx/scripts/docx_validate.py +156 -0
  298. package/work/vendor/hermes-agent/skills/productivity/pdf/LICENSE +21 -0
  299. package/work/vendor/hermes-agent/skills/productivity/pdf/SKILL.md +125 -0
  300. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/_raster.py +76 -0
  301. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_marker.py +88 -0
  302. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/extract_pymupdf.py +101 -0
  303. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_create.py +130 -0
  304. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_fill_form.py +97 -0
  305. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_form_layout.py +168 -0
  306. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_make_form.py +145 -0
  307. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_merge.py +50 -0
  308. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_meta.py +115 -0
  309. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_page_image.py +99 -0
  310. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_read.py +153 -0
  311. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_secure.py +71 -0
  312. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_split.py +84 -0
  313. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_stamp.py +143 -0
  314. package/work/vendor/hermes-agent/skills/productivity/pdf/scripts/pdf_watermark.py +51 -0
  315. package/work/vendor/hermes-agent/skills/productivity/powerpoint/LICENSE +21 -0
  316. package/work/vendor/hermes-agent/skills/productivity/powerpoint/SKILL.md +220 -0
  317. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_create.py +214 -0
  318. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_edit.py +436 -0
  319. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_from_template.py +88 -0
  320. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_read.py +131 -0
  321. package/work/vendor/hermes-agent/skills/productivity/powerpoint/scripts/pptx_render.py +93 -0
  322. package/work/vendor/hermes-agent/skills/productivity/xlsx/LICENSE +21 -0
  323. package/work/vendor/hermes-agent/skills/productivity/xlsx/SKILL.md +196 -0
  324. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/csv_to_xlsx.py +104 -0
  325. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_create.py +259 -0
  326. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_edit.py +263 -0
  327. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_read.py +160 -0
  328. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_recalc.py +111 -0
  329. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_restructure.py +337 -0
  330. package/work/vendor/hermes-agent/skills/productivity/xlsx/scripts/xlsx_to_csv.py +69 -0
  331. package/work/vendor-lock.json +11 -0
@@ -0,0 +1,480 @@
1
+ /**
2
+ * Model-facing browser tools: browser_open, browser_snapshot, browser_act, browser_close.
3
+ * All tools are statically exclusive; the manager also serializes per-run.
4
+ */
5
+ import {
6
+ UNTRUSTED_EXTERNAL_TRUST,
7
+ type ContentBlock,
8
+ type JsonObject,
9
+ type ToolCapabilityKind,
10
+ type ToolDefinition,
11
+ type ToolExecutionContext,
12
+ type ToolResult,
13
+ } from "@arnilo/prism";
14
+ import type { BrowserDownloadOptions } from "./downloads.js";
15
+ import { BrowserError } from "./errors.js";
16
+ import type { BrowserLimitOptions } from "./limits.js";
17
+ import { type BrowserManager, type CreateBrowserManagerOptions, createBrowserManager } from "./manager.js";
18
+ import type { BrowserNetworkPolicy } from "./network.js";
19
+ import { classifyBrowserOperation, classifyBrowserToolEffect } from "./policy.js";
20
+ import type {
21
+ BrowserActionName,
22
+ BrowserActRequest,
23
+ BrowserCdpOptions,
24
+ BrowserEvaluateRequest,
25
+ BrowserObserveResult,
26
+ PlaywrightBrowser,
27
+ } from "./types.js";
28
+ import type { BrowserUploadOptions } from "./uploads.js";
29
+
30
+ export interface BrowserToolsOptions {
31
+ readonly browser?: PlaywrightBrowser;
32
+ readonly manager?: BrowserManager;
33
+ readonly limits?: BrowserLimitOptions;
34
+ readonly networkPolicy?: BrowserNetworkPolicy;
35
+ readonly uploads?: BrowserUploadOptions;
36
+ readonly downloads?: BrowserDownloadOptions;
37
+ /** CDP capability gating (default "auto": enabled on Chromium hosts). */
38
+ readonly cdp?: BrowserCdpOptions;
39
+ readonly beforeSideEffect?: CreateBrowserManagerOptions["beforeSideEffect"];
40
+ }
41
+
42
+ const ACTION_NAMES = new Set<BrowserActionName>([
43
+ "navigate",
44
+ "click",
45
+ "type",
46
+ "fill",
47
+ "select",
48
+ "check",
49
+ "uncheck",
50
+ "scroll",
51
+ "wait",
52
+ "dialog",
53
+ "select_page",
54
+ "upload",
55
+ "screenshot",
56
+ "download_release",
57
+ "block_urls",
58
+ "unblock_urls",
59
+ "throttle",
60
+ "emulate",
61
+ ]);
62
+
63
+ function errorResult(toolName: string, toolCallId: string, message: string): ToolResult {
64
+ return {
65
+ toolCallId,
66
+ name: toolName,
67
+ content: [{ type: "text", text: message }],
68
+ error: { message },
69
+ };
70
+ }
71
+
72
+ function messageOf(error: unknown): string {
73
+ if (error instanceof BrowserError) return error.message;
74
+ if (error instanceof Error) return error.message;
75
+ return String(error);
76
+ }
77
+
78
+ function resolveManager(options: BrowserToolsOptions = {}): BrowserManager {
79
+ if (options.manager) return options.manager;
80
+ if (!options.browser) {
81
+ throw new BrowserError("ERR_PRISM_BROWSER_INPUT", "createBrowserTools requires browser or manager");
82
+ }
83
+ const managerOptions: CreateBrowserManagerOptions = {
84
+ browser: options.browser,
85
+ limits: options.limits,
86
+ networkPolicy: options.networkPolicy,
87
+ uploads: options.uploads,
88
+ downloads: options.downloads,
89
+ cdp: options.cdp,
90
+ beforeSideEffect: options.beforeSideEffect,
91
+ };
92
+ return createBrowserManager(managerOptions);
93
+ }
94
+
95
+ function parseActRequest(args: JsonObject): BrowserActRequest {
96
+ const action = args.action;
97
+ if (typeof action !== "string" || !ACTION_NAMES.has(action as BrowserActionName)) {
98
+ throw new BrowserError("ERR_PRISM_BROWSER_INPUT", "browser_act requires a supported action");
99
+ }
100
+ const clip = args.clip && typeof args.clip === "object" && !Array.isArray(args.clip) ? (args.clip as Record<string, unknown>) : undefined;
101
+ const request: BrowserActRequest = {
102
+ action: action as BrowserActionName,
103
+ ...(args.target !== undefined ? { target: args.target as BrowserActRequest["target"] } : {}),
104
+ ...(typeof args.snapshotId === "string" ? { snapshotId: args.snapshotId } : {}),
105
+ ...(typeof args.pageId === "string" ? { pageId: args.pageId } : {}),
106
+ ...(typeof args.url === "string" ? { url: args.url } : {}),
107
+ ...(typeof args.text === "string" ? { text: args.text } : {}),
108
+ ...(Array.isArray(args.values) ? { values: args.values.map(String) } : {}),
109
+ ...(Array.isArray(args.paths) ? { paths: args.paths.map(String) } : {}),
110
+ ...(typeof args.downloadId === "string" ? { downloadId: args.downloadId } : {}),
111
+ ...(args.fullPage === true ? { fullPage: true } : {}),
112
+ ...(clip &&
113
+ typeof clip.x === "number" &&
114
+ typeof clip.y === "number" &&
115
+ typeof clip.width === "number" &&
116
+ typeof clip.height === "number"
117
+ ? { clip: { x: clip.x, y: clip.y, width: clip.width, height: clip.height } }
118
+ : {}),
119
+ ...(args.direction === "up" || args.direction === "down" ? { direction: args.direction } : {}),
120
+ ...(typeof args.amount === "number" ? { amount: args.amount } : {}),
121
+ ...(typeof args.timeoutMs === "number" ? { timeoutMs: args.timeoutMs } : {}),
122
+ ...(args.dialogResponse === "accept" || args.dialogResponse === "dismiss" ? { dialogResponse: args.dialogResponse } : {}),
123
+ ...(typeof args.promptText === "string" ? { promptText: args.promptText } : {}),
124
+ ...(Array.isArray(args.patterns) ? { patterns: args.patterns.map(String) } : {}),
125
+ ...(args.offline === true ? { offline: true } : {}),
126
+ ...(typeof args.latencyMs === "number" ? { latencyMs: args.latencyMs } : {}),
127
+ ...(typeof args.downloadKbps === "number" ? { downloadKbps: args.downloadKbps } : {}),
128
+ ...(typeof args.uploadKbps === "number" ? { uploadKbps: args.uploadKbps } : {}),
129
+ ...(args.reset === true ? { reset: true } : {}),
130
+ ...(typeof args.width === "number" ? { width: args.width } : {}),
131
+ ...(typeof args.height === "number" ? { height: args.height } : {}),
132
+ ...(args.mobile === true ? { mobile: true } : {}),
133
+ ...(typeof args.deviceScaleFactor === "number" ? { deviceScaleFactor: args.deviceScaleFactor } : {}),
134
+ ...(typeof args.userAgent === "string" ? { userAgent: args.userAgent } : {}),
135
+ };
136
+ return request;
137
+ }
138
+
139
+ // Capability declarations for tool.call hooks: browser tools reach the network (navigation and
140
+ // observation); browser_act additionally writes (uploads, downloads, screenshots); evaluate runs
141
+ // page-context code; close is local teardown.
142
+ const NETWORK: readonly ToolCapabilityKind[] = ["network"];
143
+ const NETWORK_WRITE: readonly ToolCapabilityKind[] = ["network", "write"];
144
+ const EVALUATE: readonly ToolCapabilityKind[] = ["execute", "network"];
145
+ const NONE: readonly ToolCapabilityKind[] = [];
146
+
147
+ export function createBrowserTools(options: BrowserToolsOptions = {}): ToolDefinition[] {
148
+ const manager = resolveManager(options);
149
+
150
+ const browserOpen: ToolDefinition = {
151
+ name: "browser_open",
152
+ effects: NETWORK,
153
+ effect: (args) => classifyBrowserToolEffect("open", { hasUrl: typeof args.url === "string" }),
154
+ description:
155
+ "Open or reuse the run-owned non-persistent browser context. Optionally navigate to an absolute http(s) URL. Host supplies the Playwright browser; Prism never launches or downloads browsers. External egress requires host contained-proxy attestation.",
156
+ exclusive: true,
157
+ parameters: {
158
+ type: "object",
159
+ properties: {
160
+ url: { type: "string", description: "Optional absolute http(s) URL to open" },
161
+ },
162
+ additionalProperties: false,
163
+ } as JsonObject,
164
+ async execute(args, context: ToolExecutionContext): Promise<ToolResult> {
165
+ const toolCallId = context.toolCallId;
166
+ if (context.signal?.aborted) return errorResult("browser_open", toolCallId, "Operation aborted");
167
+ const url = typeof args.url === "string" ? args.url : undefined;
168
+ try {
169
+ const result = await manager.open(context.runId, { url, signal: context.signal });
170
+ return {
171
+ toolCallId,
172
+ name: "browser_open",
173
+ content: [
174
+ {
175
+ type: "text",
176
+ text: `Opened browser run=${result.runId} page=${result.pageId} url=${result.url || "(blank)"}`,
177
+ },
178
+ ],
179
+ value: result,
180
+ metadata: { trust: UNTRUSTED_EXTERNAL_TRUST, pageId: result.pageId },
181
+ };
182
+ } catch (error) {
183
+ return errorResult("browser_open", toolCallId, messageOf(error));
184
+ }
185
+ },
186
+ };
187
+
188
+ const browserSnapshot: ToolDefinition = {
189
+ name: "browser_snapshot",
190
+ effects: NETWORK,
191
+ effect: { kind: "none", idempotency: "none" },
192
+ description:
193
+ "Capture a bounded AI-mode accessibility snapshot with snapshot-scoped refs. Refs are invalid after navigation or action; re-snapshot before interacting by ref. Snapshot text is untrusted external content.",
194
+ exclusive: true,
195
+ parameters: {
196
+ type: "object",
197
+ properties: {
198
+ pageId: { type: "string", description: "Optional page id; defaults to the active page" },
199
+ },
200
+ additionalProperties: false,
201
+ } as JsonObject,
202
+ async execute(args, context: ToolExecutionContext): Promise<ToolResult> {
203
+ const toolCallId = context.toolCallId;
204
+ if (context.signal?.aborted) return errorResult("browser_snapshot", toolCallId, "Operation aborted");
205
+ const pageId = typeof args.pageId === "string" ? args.pageId : undefined;
206
+ try {
207
+ const result = await manager.snapshot(context.runId, { pageId, signal: context.signal });
208
+ const header = [
209
+ `snapshotId=${result.snapshotId}`,
210
+ `pageId=${result.pageId}`,
211
+ `url=${result.url}`,
212
+ `title=${result.title}`,
213
+ `refs=${result.refCount}`,
214
+ result.truncated ? `truncatedBy=${result.truncatedBy ?? "yes"}` : "truncated=false",
215
+ "",
216
+ result.ariaSnapshot,
217
+ ].join("\n");
218
+ return {
219
+ toolCallId,
220
+ name: "browser_snapshot",
221
+ content: [{ type: "text", text: header }],
222
+ value: result,
223
+ metadata: {
224
+ trust: UNTRUSTED_EXTERNAL_TRUST,
225
+ snapshotId: result.snapshotId,
226
+ pageId: result.pageId,
227
+ truncated: result.truncated,
228
+ },
229
+ };
230
+ } catch (error) {
231
+ return errorResult("browser_snapshot", toolCallId, messageOf(error));
232
+ }
233
+ },
234
+ };
235
+
236
+ const browserAct: ToolDefinition = {
237
+ name: "browser_act",
238
+ effects: NETWORK_WRITE,
239
+ effect: (args) =>
240
+ classifyBrowserToolEffect(typeof args.action === "string" ? args.action : "invalid", {
241
+ dialogResponse: args.dialogResponse === "accept" || args.dialogResponse === "dismiss" ? args.dialogResponse : undefined,
242
+ }),
243
+ description:
244
+ "Perform one ordered browser action (navigate/click/type/fill/select/check/uncheck/scroll/wait/dialog/select_page/upload/screenshot/download_release, plus CDP block_urls/unblock_urls/throttle/emulate on Chromium hosts). Prefer { role, name } or { label } targets: they need no snapshotId and stay valid across actions, so one form takes one call per field. A { ref } target needs the snapshotId of the latest browser_snapshot and any action makes that snapshot stale. Also supported: testId, text, and raw { css } / { xpath }. Mutations are gated by the host approval hook over the declared effects.",
245
+ exclusive: true,
246
+ parameters: {
247
+ type: "object",
248
+ properties: {
249
+ action: {
250
+ type: "string",
251
+ enum: [...ACTION_NAMES],
252
+ },
253
+ target: {
254
+ type: "object",
255
+ description: "ref | role(+name) | label | testId | text | css | xpath target",
256
+ additionalProperties: true,
257
+ },
258
+ snapshotId: { type: "string", description: "Required for a { ref } target: the id of the latest browser_snapshot" },
259
+ pageId: { type: "string" },
260
+ url: { type: "string" },
261
+ text: { type: "string" },
262
+ values: { type: "array", items: { type: "string" } },
263
+ paths: { type: "array", items: { type: "string" }, description: "Absolute upload paths under approved roots" },
264
+ downloadId: { type: "string" },
265
+ fullPage: { type: "boolean" },
266
+ clip: {
267
+ type: "object",
268
+ properties: {
269
+ x: { type: "number" },
270
+ y: { type: "number" },
271
+ width: { type: "number" },
272
+ height: { type: "number" },
273
+ },
274
+ additionalProperties: false,
275
+ },
276
+ direction: { type: "string", enum: ["up", "down"] },
277
+ amount: { type: "number" },
278
+ timeoutMs: { type: "number" },
279
+ dialogResponse: { type: "string", enum: ["accept", "dismiss"] },
280
+ promptText: { type: "string" },
281
+ patterns: { type: "array", items: { type: "string" }, description: "URL patterns to block (block_urls)" },
282
+ offline: { type: "boolean", description: "throttle: go offline" },
283
+ latencyMs: { type: "number", description: "throttle: latency in ms (0..120000)" },
284
+ downloadKbps: { type: "number", description: "throttle: download throughput kbps (0..1000000)" },
285
+ uploadKbps: { type: "number", description: "throttle: upload throughput kbps (0..1000000)" },
286
+ reset: { type: "boolean", description: "throttle/emulate: reset to defaults" },
287
+ width: { type: "number", description: "emulate: viewport width px" },
288
+ height: { type: "number", description: "emulate: viewport height px" },
289
+ mobile: { type: "boolean", description: "emulate: mobile viewport" },
290
+ deviceScaleFactor: { type: "number", description: "emulate: device scale factor (0.01..10)" },
291
+ userAgent: { type: "string", description: "emulate: user-agent override (only when explicitly supplied)" },
292
+ },
293
+ required: ["action"],
294
+ additionalProperties: false,
295
+ } as JsonObject,
296
+ async execute(args, context: ToolExecutionContext): Promise<ToolResult> {
297
+ const toolCallId = context.toolCallId;
298
+ if (context.signal?.aborted) return errorResult("browser_act", toolCallId, "Operation aborted");
299
+ let request: BrowserActRequest;
300
+ try {
301
+ request = parseActRequest(args);
302
+ } catch (error) {
303
+ return errorResult("browser_act", toolCallId, messageOf(error));
304
+ }
305
+ const classified = classifyBrowserOperation(request.action, {
306
+ dialogResponse: request.dialogResponse,
307
+ hasUrl: Boolean(request.url),
308
+ });
309
+ try {
310
+ const result = await manager.act(context.runId, request, { signal: context.signal });
311
+ const content: ContentBlock[] = [
312
+ {
313
+ type: "text",
314
+ text: `action=${result.action} page=${result.pageId} url=${result.url || "(blank)"}`,
315
+ },
316
+ ];
317
+ if (result.image) content.push(result.image);
318
+ return {
319
+ toolCallId,
320
+ name: "browser_act",
321
+ content,
322
+ value: result,
323
+ metadata: {
324
+ trust: UNTRUSTED_EXTERNAL_TRUST,
325
+ action: result.action,
326
+ pageId: result.pageId,
327
+ effect: classified.effect,
328
+ ...(result.download ? { downloadId: result.download.downloadId, released: result.download.released } : {}),
329
+ ...(result.screenshotBytes !== undefined ? { screenshotBytes: result.screenshotBytes } : {}),
330
+ },
331
+ };
332
+ } catch (error) {
333
+ return errorResult("browser_act", toolCallId, messageOf(error));
334
+ }
335
+ },
336
+ };
337
+
338
+ const browserClose: ToolDefinition = {
339
+ name: "browser_close",
340
+ effects: NONE,
341
+ effect: { kind: "none", idempotency: "none" },
342
+ description:
343
+ "Close the run-owned browser context, pages, listeners, quarantined downloads, and snapshot state. Idempotent. Does not close the host Playwright Browser process.",
344
+ exclusive: true,
345
+ parameters: {
346
+ type: "object",
347
+ properties: {},
348
+ additionalProperties: false,
349
+ } as JsonObject,
350
+ async execute(_args, context: ToolExecutionContext): Promise<ToolResult> {
351
+ const toolCallId = context.toolCallId;
352
+ try {
353
+ await manager.closeRun(context.runId);
354
+ return {
355
+ toolCallId,
356
+ name: "browser_close",
357
+ content: [{ type: "text", text: `Closed browser context for run ${context.runId}` }],
358
+ value: { runId: context.runId, closed: true },
359
+ };
360
+ } catch (error) {
361
+ return errorResult("browser_close", toolCallId, messageOf(error));
362
+ }
363
+ },
364
+ };
365
+
366
+ const browserEvaluate: ToolDefinition = {
367
+ name: "browser_evaluate",
368
+ effects: EVALUATE,
369
+ effect: () => classifyBrowserToolEffect("evaluate"),
370
+ description:
371
+ "Evaluate a bounded JavaScript expression in the page context via Chrome DevTools Protocol (Chromium hosts; cdp mode auto/on). Arbitrary code execution: the host approval hook sees effects [execute, network]. Result is JSON-serializable and capped at maxEvaluateResultBytes; expression capped at maxActionInputBytes.",
372
+ exclusive: true,
373
+ parameters: {
374
+ type: "object",
375
+ properties: {
376
+ pageId: { type: "string", description: "Optional page id; defaults to the active page" },
377
+ expression: { type: "string", description: "JavaScript expression to evaluate in the page context" },
378
+ awaitPromise: { type: "boolean", description: "Await promise resolution before returning" },
379
+ timeoutMs: { type: "number", description: "Per-action timeout, clamped to actionTimeoutMs" },
380
+ },
381
+ required: ["expression"],
382
+ additionalProperties: false,
383
+ } as JsonObject,
384
+ async execute(args, context: ToolExecutionContext): Promise<ToolResult> {
385
+ const toolCallId = context.toolCallId;
386
+ if (context.signal?.aborted) return errorResult("browser_evaluate", toolCallId, "Operation aborted");
387
+ const expression = typeof args.expression === "string" ? args.expression : undefined;
388
+ if (!expression) return errorResult("browser_evaluate", toolCallId, "expression is required");
389
+ const request: BrowserEvaluateRequest = {
390
+ expression,
391
+ ...(typeof args.pageId === "string" ? { pageId: args.pageId } : {}),
392
+ ...(args.awaitPromise === true ? { awaitPromise: true } : {}),
393
+ ...(typeof args.timeoutMs === "number" ? { timeoutMs: args.timeoutMs } : {}),
394
+ };
395
+ try {
396
+ const result = await manager.evaluate(context.runId, request, { signal: context.signal });
397
+ const valueText =
398
+ result.value !== undefined
399
+ ? `value=${typeof result.value === "string" ? result.value : JSON.stringify(result.value)}`
400
+ : "value=undefined";
401
+ const lines = [
402
+ `evaluate page=${result.pageId} url=${result.url || "(blank)"}`,
403
+ result.truncated ? `${valueText} (truncated)` : valueText,
404
+ ];
405
+ if (result.exception) lines.push(`exception=${result.exception}`);
406
+ return {
407
+ toolCallId,
408
+ name: "browser_evaluate",
409
+ content: [{ type: "text", text: lines.join("\n") }],
410
+ value: result,
411
+ metadata: {
412
+ trust: UNTRUSTED_EXTERNAL_TRUST,
413
+ pageId: result.pageId,
414
+ ...(result.truncated ? { truncated: true } : {}),
415
+ ...(result.exception !== undefined ? { exception: true } : {}),
416
+ },
417
+ };
418
+ } catch (error) {
419
+ return errorResult("browser_evaluate", toolCallId, messageOf(error));
420
+ }
421
+ },
422
+ };
423
+
424
+ const browserObserve: ToolDefinition = {
425
+ name: "browser_observe",
426
+ effects: NETWORK,
427
+ effect: { kind: "none", idempotency: "none" },
428
+ description:
429
+ "Drain bounded console and network observations since the previous call (CDP Runtime/Network domains; Chromium hosts). Never captures request/response bodies, cookies, or auth headers. Entries are untrusted external content.",
430
+ exclusive: true,
431
+ parameters: {
432
+ type: "object",
433
+ properties: {
434
+ pageId: { type: "string", description: "Optional page id; defaults to the active page" },
435
+ },
436
+ additionalProperties: false,
437
+ } as JsonObject,
438
+ async execute(args, context: ToolExecutionContext): Promise<ToolResult> {
439
+ const toolCallId = context.toolCallId;
440
+ if (context.signal?.aborted) return errorResult("browser_observe", toolCallId, "Operation aborted");
441
+ const pageId = typeof args.pageId === "string" ? args.pageId : undefined;
442
+ try {
443
+ const result: BrowserObserveResult = await manager.observe(context.runId, { pageId, signal: context.signal });
444
+ const lines = [
445
+ `observe page=${result.pageId} url=${result.url || "(blank)"} console=${result.console.length} network=${result.network.length}`,
446
+ ];
447
+ for (const entry of result.console.slice(0, 50)) {
448
+ lines.push(`console [${entry.seq}] ${entry.type}: ${entry.args.join(" ").slice(0, 200)}`);
449
+ }
450
+ for (const entry of result.network.slice(0, 50)) {
451
+ const detail =
452
+ entry.phase === "response"
453
+ ? `status=${entry.status}`
454
+ : entry.phase === "failed"
455
+ ? `error=${entry.errorText ?? "unknown"}`
456
+ : `method=${entry.method ?? "?"}`;
457
+ lines.push(`network [${entry.seq}] ${entry.phase} ${detail} ${entry.url.slice(0, 200)}`);
458
+ }
459
+ const remaining = Math.max(0, result.console.length - 50) + Math.max(0, result.network.length - 50);
460
+ if (remaining > 0) lines.push(`(${remaining} more entries in value)`);
461
+ if (result.truncated) lines.push("(ring truncated: earliest entries evicted)");
462
+ return {
463
+ toolCallId,
464
+ name: "browser_observe",
465
+ content: [{ type: "text", text: lines.join("\n") }],
466
+ value: result,
467
+ metadata: { trust: UNTRUSTED_EXTERNAL_TRUST, pageId: result.pageId, truncated: result.truncated },
468
+ };
469
+ } catch (error) {
470
+ return errorResult("browser_observe", toolCallId, messageOf(error));
471
+ }
472
+ },
473
+ };
474
+
475
+ return [browserOpen, browserSnapshot, browserAct, browserClose, browserEvaluate, browserObserve];
476
+ }
477
+
478
+ export function getBrowserManagerFromTools(options: BrowserToolsOptions): BrowserManager {
479
+ return resolveManager(options);
480
+ }