@rainhole/rain-code 1.1.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 (496) hide show
  1. package/README.md +172 -0
  2. package/dist/chunk-06b2745w.js +3583 -0
  3. package/dist/chunk-06saje2v.js +39 -0
  4. package/dist/chunk-07069jq1.js +30 -0
  5. package/dist/chunk-0731m51q.js +8 -0
  6. package/dist/chunk-0bs2528v.js +192 -0
  7. package/dist/chunk-0fj1d707.js +313 -0
  8. package/dist/chunk-0gdkvtx4.js +117 -0
  9. package/dist/chunk-0jd8rpt4.js +34257 -0
  10. package/dist/chunk-0paqc2yw.js +15 -0
  11. package/dist/chunk-0pk0w4j1.js +332 -0
  12. package/dist/chunk-0rpb2bdp.js +8 -0
  13. package/dist/chunk-0rvwew67.js +9300 -0
  14. package/dist/chunk-0sa1g8jf.js +318 -0
  15. package/dist/chunk-0vkfrmqm.js +690 -0
  16. package/dist/chunk-0xgxxqhr.js +708 -0
  17. package/dist/chunk-0xjaqda8.js +1124 -0
  18. package/dist/chunk-0zep39v0.js +81 -0
  19. package/dist/chunk-1141xmr4.js +8 -0
  20. package/dist/chunk-12hn2mhy.js +17 -0
  21. package/dist/chunk-12rjry89.js +81 -0
  22. package/dist/chunk-168xb8v1.js +436 -0
  23. package/dist/chunk-1cwdhk7a.js +969 -0
  24. package/dist/chunk-1cx0fd76.js +132 -0
  25. package/dist/chunk-1erfksyp.js +107 -0
  26. package/dist/chunk-1h1tc4mw.js +126 -0
  27. package/dist/chunk-1h2famwb.js +49 -0
  28. package/dist/chunk-1jnbys9f.js +1811 -0
  29. package/dist/chunk-1k4fp6ft.js +389 -0
  30. package/dist/chunk-1mjn8xxc.js +22 -0
  31. package/dist/chunk-1mn6r4y2.js +747 -0
  32. package/dist/chunk-1p8myfza.js +1568 -0
  33. package/dist/chunk-1vthytca.js +79 -0
  34. package/dist/chunk-1y32rx73.js +145 -0
  35. package/dist/chunk-200781fd.js +64 -0
  36. package/dist/chunk-205mmm67.js +100 -0
  37. package/dist/chunk-209eh6ak.js +9381 -0
  38. package/dist/chunk-21mfpnva.js +85 -0
  39. package/dist/chunk-238g70xa.js +36 -0
  40. package/dist/chunk-24k6t9fa.js +151 -0
  41. package/dist/chunk-29gg6hx0.js +2992 -0
  42. package/dist/chunk-2a42s11t.js +412 -0
  43. package/dist/chunk-2ekjxh7d.js +289 -0
  44. package/dist/chunk-2eykm0j0.js +20 -0
  45. package/dist/chunk-2fwze72g.js +24 -0
  46. package/dist/chunk-2gzv8nrw.js +205 -0
  47. package/dist/chunk-2k995y2x.js +880 -0
  48. package/dist/chunk-2nayx6q1.js +63 -0
  49. package/dist/chunk-2pg9pmvc.js +182 -0
  50. package/dist/chunk-2qp2hc02.js +36 -0
  51. package/dist/chunk-2rj0dnps.js +436 -0
  52. package/dist/chunk-2t0xa4dt.js +145 -0
  53. package/dist/chunk-2ym6tnww.js +216 -0
  54. package/dist/chunk-30bpz5m2.js +34 -0
  55. package/dist/chunk-30rst83v.js +168 -0
  56. package/dist/chunk-36b2q5fg.js +1299 -0
  57. package/dist/chunk-3c25bcsw.js +17 -0
  58. package/dist/chunk-3ewzhjyb.js +207 -0
  59. package/dist/chunk-3h8a89gy.js +46 -0
  60. package/dist/chunk-3nk79af8.js +8 -0
  61. package/dist/chunk-3sfr7j85.js +884 -0
  62. package/dist/chunk-3w6s9m5w.js +16 -0
  63. package/dist/chunk-3x52v1wb.js +660 -0
  64. package/dist/chunk-404qm8xt.js +1715 -0
  65. package/dist/chunk-42fjay4q.js +141 -0
  66. package/dist/chunk-48649h96.js +8590 -0
  67. package/dist/chunk-495d85x1.js +8066 -0
  68. package/dist/chunk-4anj5saq.js +111 -0
  69. package/dist/chunk-4asynmj4.js +259 -0
  70. package/dist/chunk-4ck9wve9.js +225 -0
  71. package/dist/chunk-4cp6193g.js +9076 -0
  72. package/dist/chunk-4g3v8y12.js +23 -0
  73. package/dist/chunk-4geyher8.js +244 -0
  74. package/dist/chunk-4hv90qcz.js +8 -0
  75. package/dist/chunk-4jhr03e7.js +61 -0
  76. package/dist/chunk-4jm600zv.js +13 -0
  77. package/dist/chunk-4nspekjp.js +69 -0
  78. package/dist/chunk-4ptqcw4p.js +16 -0
  79. package/dist/chunk-4qj8cqbh.js +173 -0
  80. package/dist/chunk-4wxsg6a0.js +122 -0
  81. package/dist/chunk-4zfkzkt6.js +37 -0
  82. package/dist/chunk-54dckh8a.js +1169 -0
  83. package/dist/chunk-54y13759.js +650 -0
  84. package/dist/chunk-54yf6e8d.js +91 -0
  85. package/dist/chunk-57qz90z8.js +154 -0
  86. package/dist/chunk-59k0mjnc.js +120 -0
  87. package/dist/chunk-59p9jye4.js +104 -0
  88. package/dist/chunk-5c753bd4.js +64 -0
  89. package/dist/chunk-5cw6zwep.js +106 -0
  90. package/dist/chunk-5eaf3j24.js +133 -0
  91. package/dist/chunk-5me7398b.js +81 -0
  92. package/dist/chunk-5pevjsyw.js +118 -0
  93. package/dist/chunk-5q3c2rf4.js +107 -0
  94. package/dist/chunk-5xwtnq4g.js +146 -0
  95. package/dist/chunk-5z28bqne.js +6748 -0
  96. package/dist/chunk-613f6fbv.js +63 -0
  97. package/dist/chunk-641hawvm.js +95 -0
  98. package/dist/chunk-64c1avct.js +13 -0
  99. package/dist/chunk-64hks9ax.js +456 -0
  100. package/dist/chunk-677as3nh.js +15 -0
  101. package/dist/chunk-6bd8brc4.js +48 -0
  102. package/dist/chunk-6cs6mmez.js +112 -0
  103. package/dist/chunk-6dj5t602.js +341 -0
  104. package/dist/chunk-6e8vht4y.js +780 -0
  105. package/dist/chunk-6gr3c3w9.js +378 -0
  106. package/dist/chunk-6hkd32eh.js +83 -0
  107. package/dist/chunk-6jqxvef0.js +198 -0
  108. package/dist/chunk-6mh3vfa4.js +115 -0
  109. package/dist/chunk-6mpw9h55.js +1071 -0
  110. package/dist/chunk-6p4cyhb3.js +16 -0
  111. package/dist/chunk-6qvgnepd.js +26 -0
  112. package/dist/chunk-6r2bhsvt.js +6956 -0
  113. package/dist/chunk-6tq2v3rk.js +186 -0
  114. package/dist/chunk-7316m01k.js +125 -0
  115. package/dist/chunk-73rpbt04.js +1947 -0
  116. package/dist/chunk-75zk7zr1.js +309 -0
  117. package/dist/chunk-760252na.js +101 -0
  118. package/dist/chunk-764ec4ja.js +173 -0
  119. package/dist/chunk-76vgnv24.js +108 -0
  120. package/dist/chunk-7739pg2c.js +4261 -0
  121. package/dist/chunk-7a7hxy3d.js +167 -0
  122. package/dist/chunk-7aw745vx.js +40175 -0
  123. package/dist/chunk-7b6bg1r4.js +16128 -0
  124. package/dist/chunk-7ca4qskp.js +99 -0
  125. package/dist/chunk-7deph26x.js +311 -0
  126. package/dist/chunk-7ds8zqar.js +108 -0
  127. package/dist/chunk-7fqxw3d2.js +479 -0
  128. package/dist/chunk-7nysf9yd.js +266 -0
  129. package/dist/chunk-7tascxe2.js +90 -0
  130. package/dist/chunk-7wm5s02e.js +216 -0
  131. package/dist/chunk-7xmw2tcz.js +277 -0
  132. package/dist/chunk-7xyswgjh.js +8 -0
  133. package/dist/chunk-7zkhadkb.js +220 -0
  134. package/dist/chunk-8225arm6.js +6374 -0
  135. package/dist/chunk-83hfzbx3.js +10 -0
  136. package/dist/chunk-85tag8nv.js +1391 -0
  137. package/dist/chunk-8bd8q5xw.js +359 -0
  138. package/dist/chunk-8bwqtasa.js +213 -0
  139. package/dist/chunk-8g5pe1gr.js +37 -0
  140. package/dist/chunk-8g747a8x.js +26 -0
  141. package/dist/chunk-8h6sdj66.js +447 -0
  142. package/dist/chunk-8mm8b6dd.js +19 -0
  143. package/dist/chunk-8ndwn6st.js +120 -0
  144. package/dist/chunk-8pn8tvgg.js +637 -0
  145. package/dist/chunk-8tnn9kcb.js +131 -0
  146. package/dist/chunk-8tnsngw2.js +31 -0
  147. package/dist/chunk-8x5w267y.js +112 -0
  148. package/dist/chunk-8y12jxg8.js +10 -0
  149. package/dist/chunk-8ymf4e6z.js +48 -0
  150. package/dist/chunk-90mt0m1w.js +102 -0
  151. package/dist/chunk-90wp6wez.js +10510 -0
  152. package/dist/chunk-91ew1d6f.js +2689 -0
  153. package/dist/chunk-97jsc1kn.js +231 -0
  154. package/dist/chunk-993pnm45.js +4521 -0
  155. package/dist/chunk-9a0rsdre.js +46 -0
  156. package/dist/chunk-9d7fmqkw.js +41 -0
  157. package/dist/chunk-9dgaq0g4.js +667 -0
  158. package/dist/chunk-9f52phb8.js +138 -0
  159. package/dist/chunk-9fbpqghc.js +105 -0
  160. package/dist/chunk-9hzxd5q3.js +122 -0
  161. package/dist/chunk-9kyrssch.js +28 -0
  162. package/dist/chunk-9q93n4w6.js +308 -0
  163. package/dist/chunk-9s0xs06y.js +581 -0
  164. package/dist/chunk-9x5zgy22.js +12 -0
  165. package/dist/chunk-9zdcb9jy.js +105 -0
  166. package/dist/chunk-a136cvvz.js +27 -0
  167. package/dist/chunk-a4psxnr1.js +224 -0
  168. package/dist/chunk-a4twdmhf.js +45 -0
  169. package/dist/chunk-a7rhvq9b.js +106 -0
  170. package/dist/chunk-a8ejc632.js +3094 -0
  171. package/dist/chunk-a9vdeb6y.js +258 -0
  172. package/dist/chunk-a9zh40sj.js +48 -0
  173. package/dist/chunk-aawg48hh.js +4102 -0
  174. package/dist/chunk-ad2f3890.js +65 -0
  175. package/dist/chunk-ae7ar1jk.js +105 -0
  176. package/dist/chunk-ak3hdbe4.js +234 -0
  177. package/dist/chunk-as4e9g8f.js +298 -0
  178. package/dist/chunk-ase86y73.js +15 -0
  179. package/dist/chunk-awb4vc41.js +69 -0
  180. package/dist/chunk-b4bep0aq.js +5041 -0
  181. package/dist/chunk-b4wg70y1.js +54 -0
  182. package/dist/chunk-b81hd3m6.js +32 -0
  183. package/dist/chunk-b9knmzt0.js +106 -0
  184. package/dist/chunk-besmz4ym.js +32 -0
  185. package/dist/chunk-bgpkemkg.js +65 -0
  186. package/dist/chunk-bj8x29tz.js +54 -0
  187. package/dist/chunk-bkqsnwrq.js +239 -0
  188. package/dist/chunk-bnf662he.js +359 -0
  189. package/dist/chunk-bq00fcsd.js +165 -0
  190. package/dist/chunk-brz2c4cq.js +275 -0
  191. package/dist/chunk-bsa118r4.js +502 -0
  192. package/dist/chunk-bsengrbt.js +2737 -0
  193. package/dist/chunk-bt64sq5y.js +19 -0
  194. package/dist/chunk-bxcfz5gy.js +56 -0
  195. package/dist/chunk-bxs2a71m.js +213 -0
  196. package/dist/chunk-byv2p9hn.js +397 -0
  197. package/dist/chunk-c03am3es.js +29 -0
  198. package/dist/chunk-c2ahb7yg.js +105 -0
  199. package/dist/chunk-c2qm0t6p.js +111 -0
  200. package/dist/chunk-c42h9gzx.js +71 -0
  201. package/dist/chunk-c47xbxqw.js +38 -0
  202. package/dist/chunk-c5vkve4j.js +68 -0
  203. package/dist/chunk-c6sjhj89.js +1284 -0
  204. package/dist/chunk-ca147npg.js +27 -0
  205. package/dist/chunk-caxx597g.js +71 -0
  206. package/dist/chunk-cbrt5vsb.js +31 -0
  207. package/dist/chunk-ce0z23ct.js +443 -0
  208. package/dist/chunk-cefsp8h1.js +155 -0
  209. package/dist/chunk-cfv996bs.js +22 -0
  210. package/dist/chunk-cgfdkzhb.js +12 -0
  211. package/dist/chunk-chsyvavm.js +3435 -0
  212. package/dist/chunk-cmsknj6n.js +28228 -0
  213. package/dist/chunk-cn8bkmvj.js +264 -0
  214. package/dist/chunk-crmjpsqe.js +68 -0
  215. package/dist/chunk-cthpw4pj.js +849 -0
  216. package/dist/chunk-cwy9nj4y.js +134 -0
  217. package/dist/chunk-cyagce56.js +155 -0
  218. package/dist/chunk-cynewytp.js +227 -0
  219. package/dist/chunk-cznf6k4g.js +46 -0
  220. package/dist/chunk-d0954t9j.js +267 -0
  221. package/dist/chunk-d1qhftze.js +118 -0
  222. package/dist/chunk-d4mdda98.js +94 -0
  223. package/dist/chunk-d4rnqevg.js +41 -0
  224. package/dist/chunk-d7886r6a.js +13870 -0
  225. package/dist/chunk-dd1qvamk.js +678 -0
  226. package/dist/chunk-dg4je8qj.js +183 -0
  227. package/dist/chunk-dggvswz1.js +104 -0
  228. package/dist/chunk-dgqrcy74.js +48 -0
  229. package/dist/chunk-dm3n2qgd.js +24 -0
  230. package/dist/chunk-dnh7jtpb.js +37 -0
  231. package/dist/chunk-dsenyfax.js +105 -0
  232. package/dist/chunk-dtf0a7rr.js +655 -0
  233. package/dist/chunk-dxdb7bs1.js +60 -0
  234. package/dist/chunk-e0pth8g7.js +79 -0
  235. package/dist/chunk-e36y0q82.js +109 -0
  236. package/dist/chunk-ef55cwrv.js +267 -0
  237. package/dist/chunk-efh644hv.js +915 -0
  238. package/dist/chunk-ehtwnxpg.js +1591 -0
  239. package/dist/chunk-ejahyhd8.js +120 -0
  240. package/dist/chunk-ejk1bpzz.js +472 -0
  241. package/dist/chunk-emef71ea.js +202 -0
  242. package/dist/chunk-en7v028t.js +333 -0
  243. package/dist/chunk-eqp1rfft.js +17 -0
  244. package/dist/chunk-ewadzrm8.js +103 -0
  245. package/dist/chunk-exh7z6tv.js +132 -0
  246. package/dist/chunk-f0npbgyf.js +340 -0
  247. package/dist/chunk-f2qkc8ce.js +229 -0
  248. package/dist/chunk-f49sb3q7.js +40 -0
  249. package/dist/chunk-f5ma3nh5.js +3436 -0
  250. package/dist/chunk-fbv4apne.js +51 -0
  251. package/dist/chunk-fday7sfg.js +269 -0
  252. package/dist/chunk-feyzykye.js +10 -0
  253. package/dist/chunk-fgqwr70t.js +241 -0
  254. package/dist/chunk-fhy7zs1w.js +943 -0
  255. package/dist/chunk-fmw3f68k.js +432 -0
  256. package/dist/chunk-fmwqvpqm.js +506 -0
  257. package/dist/chunk-fn1apgre.js +66 -0
  258. package/dist/chunk-fpy4nam9.js +21933 -0
  259. package/dist/chunk-fqy0erkw.js +908 -0
  260. package/dist/chunk-ftqwza3a.js +43 -0
  261. package/dist/chunk-fyc5fepv.js +10 -0
  262. package/dist/chunk-fz0ch109.js +329 -0
  263. package/dist/chunk-fzhn8z8j.js +253 -0
  264. package/dist/chunk-g12brv6y.js +321 -0
  265. package/dist/chunk-g338npwr.js +1061 -0
  266. package/dist/chunk-g5tpks28.js +795 -0
  267. package/dist/chunk-g63tgj4f.js +58 -0
  268. package/dist/chunk-g827r0mk.js +266 -0
  269. package/dist/chunk-g8wzsxgc.js +2534 -0
  270. package/dist/chunk-gey7mwcw.js +36 -0
  271. package/dist/chunk-gghb9pks.js +120 -0
  272. package/dist/chunk-grdpaf1p.js +606 -0
  273. package/dist/chunk-gx8016vp.js +125 -0
  274. package/dist/chunk-h0qngp9w.js +157 -0
  275. package/dist/chunk-h0rbjg6x.js +55 -0
  276. package/dist/chunk-h1mr3371.js +121 -0
  277. package/dist/chunk-h3xwdgpd.js +68 -0
  278. package/dist/chunk-h4b85amj.js +2331 -0
  279. package/dist/chunk-h6d137aa.js +20 -0
  280. package/dist/chunk-h9n7z00d.js +95 -0
  281. package/dist/chunk-hakdhagh.js +16606 -0
  282. package/dist/chunk-hd8531ec.js +685 -0
  283. package/dist/chunk-heq3rn8t.js +33068 -0
  284. package/dist/chunk-hfvxc9fd.js +542 -0
  285. package/dist/chunk-hgpd0qmm.js +371 -0
  286. package/dist/chunk-hh7cmy4k.js +20 -0
  287. package/dist/chunk-hhjs87wh.js +1407 -0
  288. package/dist/chunk-hjtvdvgj.js +208 -0
  289. package/dist/chunk-hk9xz7gk.js +118 -0
  290. package/dist/chunk-hknbjky3.js +160798 -0
  291. package/dist/chunk-htsbqyf9.js +338 -0
  292. package/dist/chunk-htx7jmxk.js +78 -0
  293. package/dist/chunk-hzhe8ygc.js +547 -0
  294. package/dist/chunk-j2k4p94p.js +55 -0
  295. package/dist/chunk-j3a4p81y.js +184 -0
  296. package/dist/chunk-j46rb9m9.js +544 -0
  297. package/dist/chunk-j5bth84e.js +97 -0
  298. package/dist/chunk-j64ga6ta.js +8035 -0
  299. package/dist/chunk-j6jh72hw.js +140 -0
  300. package/dist/chunk-j9gxwbe3.js +349 -0
  301. package/dist/chunk-jaaxk89e.js +113 -0
  302. package/dist/chunk-jd32zbps.js +15 -0
  303. package/dist/chunk-jdgeec04.js +4249 -0
  304. package/dist/chunk-jk826edv.js +174 -0
  305. package/dist/chunk-jnhkref0.js +30 -0
  306. package/dist/chunk-jsx72hep.js +208 -0
  307. package/dist/chunk-jx817w05.js +11 -0
  308. package/dist/chunk-jzmz18nn.js +65 -0
  309. package/dist/chunk-k0p9w03v.js +4957 -0
  310. package/dist/chunk-k3s4yk22.js +477 -0
  311. package/dist/chunk-kfd89dsd.js +21 -0
  312. package/dist/chunk-kgfz4522.js +126 -0
  313. package/dist/chunk-kn6zg6bd.js +524 -0
  314. package/dist/chunk-kp9vkzj6.js +120 -0
  315. package/dist/chunk-kraf793v.js +118 -0
  316. package/dist/chunk-kw0r30h3.js +208 -0
  317. package/dist/chunk-kwekc97v.js +18 -0
  318. package/dist/chunk-m2bcpk8j.js +30 -0
  319. package/dist/chunk-m2kp5f7p.js +4389 -0
  320. package/dist/chunk-m74w3187.js +164 -0
  321. package/dist/chunk-m88q4jmb.js +61 -0
  322. package/dist/chunk-man6wb4n.js +1456 -0
  323. package/dist/chunk-mdk3xgya.js +42 -0
  324. package/dist/chunk-mf4g439x.js +82 -0
  325. package/dist/chunk-mg8g0xqs.js +71 -0
  326. package/dist/chunk-mkwzrqvf.js +38 -0
  327. package/dist/chunk-mn61mk4v.js +351 -0
  328. package/dist/chunk-ms09sxcj.js +908 -0
  329. package/dist/chunk-mtn1anwe.js +2351 -0
  330. package/dist/chunk-mv0zm0qj.js +65 -0
  331. package/dist/chunk-mx28h61f.js +1147 -0
  332. package/dist/chunk-mxbf8ajn.js +1067 -0
  333. package/dist/chunk-n0qaeaa5.js +256 -0
  334. package/dist/chunk-n34z5cw8.js +74 -0
  335. package/dist/chunk-n55ehz77.js +120 -0
  336. package/dist/chunk-n7ttdtk0.js +641 -0
  337. package/dist/chunk-n9ktjngj.js +336 -0
  338. package/dist/chunk-nb2ntesh.js +149 -0
  339. package/dist/chunk-netzwgv1.js +154 -0
  340. package/dist/chunk-nh3cd07f.js +14358 -0
  341. package/dist/chunk-nka1g8f4.js +773 -0
  342. package/dist/chunk-nm97cw83.js +458 -0
  343. package/dist/chunk-nq0fxyxh.js +752 -0
  344. package/dist/chunk-nt837qt9.js +21 -0
  345. package/dist/chunk-nx87c0vw.js +250 -0
  346. package/dist/chunk-nxw6y6xm.js +862 -0
  347. package/dist/chunk-nzt717xg.js +32 -0
  348. package/dist/chunk-p2816w9z.js +1486 -0
  349. package/dist/chunk-p2d5nh3g.js +342 -0
  350. package/dist/chunk-p9cdykwf.js +72 -0
  351. package/dist/chunk-paxw1ryd.js +227 -0
  352. package/dist/chunk-ph5g4d1j.js +109 -0
  353. package/dist/chunk-pp42p8y3.js +574 -0
  354. package/dist/chunk-ppdn71n4.js +400 -0
  355. package/dist/chunk-ppwjyveh.js +8 -0
  356. package/dist/chunk-ps49ymvj.js +43 -0
  357. package/dist/chunk-pshjyzq4.js +17656 -0
  358. package/dist/chunk-pw8nf9rt.js +126 -0
  359. package/dist/chunk-pwwa7s62.js +11 -0
  360. package/dist/chunk-py3zxq5j.js +129 -0
  361. package/dist/chunk-pyz1qswz.js +300 -0
  362. package/dist/chunk-q50q8mc5.js +157 -0
  363. package/dist/chunk-q7tpyeb3.js +39 -0
  364. package/dist/chunk-q82r31er.js +151 -0
  365. package/dist/chunk-qajrkk97.js +298 -0
  366. package/dist/chunk-qcpxnyeh.js +110 -0
  367. package/dist/chunk-qeabchwr.js +132 -0
  368. package/dist/chunk-qm7nbd10.js +755 -0
  369. package/dist/chunk-qm8j7kxr.js +280 -0
  370. package/dist/chunk-qmwgg5zy.js +136 -0
  371. package/dist/chunk-qnfx3qtx.js +617 -0
  372. package/dist/chunk-qp2qdcda.js +100 -0
  373. package/dist/chunk-qphaajd7.js +305 -0
  374. package/dist/chunk-qt21xxgm.js +419 -0
  375. package/dist/chunk-qy2z2p0b.js +122 -0
  376. package/dist/chunk-qyz8q0dj.js +689 -0
  377. package/dist/chunk-qz2x630m.js +49145 -0
  378. package/dist/chunk-qzq5n1yn.js +76 -0
  379. package/dist/chunk-r0ya57xw.js +170 -0
  380. package/dist/chunk-r7j395t6.js +122 -0
  381. package/dist/chunk-r7trcrs7.js +62 -0
  382. package/dist/chunk-re4yh70t.js +1095 -0
  383. package/dist/chunk-rhte1r8g.js +272 -0
  384. package/dist/chunk-rhw4ayb1.js +6851 -0
  385. package/dist/chunk-rn0v1hk8.js +34 -0
  386. package/dist/chunk-rphakhme.js +281 -0
  387. package/dist/chunk-rrtzz2pv.js +32 -0
  388. package/dist/chunk-rtnjk8ge.js +726 -0
  389. package/dist/chunk-rwhswkma.js +87 -0
  390. package/dist/chunk-rxd4kn2g.js +308 -0
  391. package/dist/chunk-s083x8ry.js +2840 -0
  392. package/dist/chunk-s16sn02n.js +365 -0
  393. package/dist/chunk-s1s8qfdh.js +182 -0
  394. package/dist/chunk-s2bwz69v.js +473 -0
  395. package/dist/chunk-s3pzvdss.js +50 -0
  396. package/dist/chunk-s9y6t0mt.js +291 -0
  397. package/dist/chunk-sd36yzx8.js +954 -0
  398. package/dist/chunk-se8xzw8h.js +87 -0
  399. package/dist/chunk-sg66v252.js +1648 -0
  400. package/dist/chunk-sg7gf3hj.js +1585 -0
  401. package/dist/chunk-spx24x6j.js +98 -0
  402. package/dist/chunk-sybxpy18.js +73 -0
  403. package/dist/chunk-szj5wvdy.js +28 -0
  404. package/dist/chunk-t0gb304x.js +182 -0
  405. package/dist/chunk-t3fr4skc.js +165 -0
  406. package/dist/chunk-t58wfamm.js +5368 -0
  407. package/dist/chunk-t6s2kkm3.js +104 -0
  408. package/dist/chunk-t8hv0x81.js +116 -0
  409. package/dist/chunk-tezak8rx.js +6157 -0
  410. package/dist/chunk-th5y3hj5.js +189 -0
  411. package/dist/chunk-tj0d3870.js +180 -0
  412. package/dist/chunk-tjgsawpx.js +40 -0
  413. package/dist/chunk-ts2p6bv1.js +224 -0
  414. package/dist/chunk-ttk5dzz8.js +25 -0
  415. package/dist/chunk-tv9pcdnz.js +51 -0
  416. package/dist/chunk-ty99rgvw.js +122 -0
  417. package/dist/chunk-tzgp8av2.js +61 -0
  418. package/dist/chunk-v1kzp02e.js +785 -0
  419. package/dist/chunk-v2c9dq7t.js +275 -0
  420. package/dist/chunk-v3aq3heg.js +620 -0
  421. package/dist/chunk-v78fj8by.js +145 -0
  422. package/dist/chunk-v9smspw2.js +4301 -0
  423. package/dist/chunk-var1et7e.js +66 -0
  424. package/dist/chunk-vchrkvet.js +120 -0
  425. package/dist/chunk-vest0y6x.js +3830 -0
  426. package/dist/chunk-vf5sd1nq.js +12 -0
  427. package/dist/chunk-vf612n57.js +472 -0
  428. package/dist/chunk-vgpy9md6.js +339 -0
  429. package/dist/chunk-vkzt82ry.js +644 -0
  430. package/dist/chunk-vsh80y0c.js +100 -0
  431. package/dist/chunk-vxkdxhyk.js +103 -0
  432. package/dist/chunk-vxt6ywm9.js +485 -0
  433. package/dist/chunk-vyjeh50y.js +2149 -0
  434. package/dist/chunk-vytdzvqs.js +1181 -0
  435. package/dist/chunk-w0qks2ja.js +1030 -0
  436. package/dist/chunk-wfz0qffj.js +3939 -0
  437. package/dist/chunk-wp1568nt.js +828 -0
  438. package/dist/chunk-wpckhx7b.js +66 -0
  439. package/dist/chunk-wpvkvwvc.js +41 -0
  440. package/dist/chunk-ws5d6qs4.js +655 -0
  441. package/dist/chunk-wsnxrrb5.js +986 -0
  442. package/dist/chunk-wyavftcj.js +103 -0
  443. package/dist/chunk-wybh0bvv.js +121 -0
  444. package/dist/chunk-wzpdet3m.js +843 -0
  445. package/dist/chunk-x2dp18yj.js +74 -0
  446. package/dist/chunk-x6r4v44b.js +8 -0
  447. package/dist/chunk-x7r5k0hf.js +423 -0
  448. package/dist/chunk-xahk20z8.js +877 -0
  449. package/dist/chunk-xajwdaxm.js +295 -0
  450. package/dist/chunk-xkt36p6r.js +61 -0
  451. package/dist/chunk-xnav6j8h.js +490 -0
  452. package/dist/chunk-xrj294jg.js +440 -0
  453. package/dist/chunk-xsq9ae7x.js +90 -0
  454. package/dist/chunk-xt9z9t7b.js +40 -0
  455. package/dist/chunk-xv3era3s.js +8 -0
  456. package/dist/chunk-y1784krc.js +19 -0
  457. package/dist/chunk-y289fz8y.js +116 -0
  458. package/dist/chunk-y3r7v9pq.js +336 -0
  459. package/dist/chunk-y98z50mm.js +158 -0
  460. package/dist/chunk-yhce3x0q.js +64 -0
  461. package/dist/chunk-yhhf6n9p.js +338 -0
  462. package/dist/chunk-ykr34msh.js +411 -0
  463. package/dist/chunk-yks9ggzn.js +103 -0
  464. package/dist/chunk-ym5r3jnk.js +2007 -0
  465. package/dist/chunk-ypa349qq.js +148 -0
  466. package/dist/chunk-yzx3mhfd.js +110 -0
  467. package/dist/chunk-z1bs6d7k.js +24 -0
  468. package/dist/chunk-z2dp53wn.js +17 -0
  469. package/dist/chunk-z3k0k30d.js +882 -0
  470. package/dist/chunk-z42cqdtf.js +107 -0
  471. package/dist/chunk-z7asrz6j.js +259 -0
  472. package/dist/chunk-za09fhhh.js +716 -0
  473. package/dist/chunk-zae0t3p4.js +252 -0
  474. package/dist/chunk-zbsw794g.js +259 -0
  475. package/dist/chunk-ze6zvkg6.js +22820 -0
  476. package/dist/chunk-zejm280k.js +39 -0
  477. package/dist/chunk-zk2wsm7d.js +15 -0
  478. package/dist/chunk-znf2b75k.js +113 -0
  479. package/dist/chunk-zqpnvsdz.js +24 -0
  480. package/dist/chunk-zs2gdkj5.js +433 -0
  481. package/dist/chunk-zseb1639.js +37 -0
  482. package/dist/chunk-zsgha506.js +63 -0
  483. package/dist/chunk-zvsfgmq8.js +146 -0
  484. package/dist/chunk-zw5xd7m9.js +160 -0
  485. package/dist/chunk-zzm33q8x.js +8 -0
  486. package/dist/cli.js +97 -0
  487. package/dist/download-ripgrep.js +24821 -0
  488. package/dist/vendor/audio-capture/arm64-darwin/audio-capture.node +0 -0
  489. package/dist/vendor/audio-capture/arm64-linux/audio-capture.node +0 -0
  490. package/dist/vendor/audio-capture/arm64-win32/audio-capture.node +0 -0
  491. package/dist/vendor/audio-capture/x64-darwin/audio-capture.node +0 -0
  492. package/dist/vendor/audio-capture/x64-linux/audio-capture.node +0 -0
  493. package/dist/vendor/audio-capture/x64-win32/audio-capture.node +0 -0
  494. package/package.json +178 -0
  495. package/scripts/download-ripgrep.ts +335 -0
  496. package/scripts/postinstall.cjs +319 -0
@@ -0,0 +1,3435 @@
1
+ // @bun
2
+ import {
3
+ CallToolRequestSchema,
4
+ ListToolsRequestSchema,
5
+ Server,
6
+ init_server,
7
+ init_types
8
+ } from "./chunk-4cp6193g.js";
9
+ import {
10
+ __esm
11
+ } from "./chunk-qp2qdcda.js";
12
+
13
+ // packages/@ant/computer-use-mcp/src/imageResize.ts
14
+ function nTokensForPx(px, pxPerToken) {
15
+ return Math.floor((px - 1) / pxPerToken) + 1;
16
+ }
17
+ function nTokensForImg(width, height, pxPerToken) {
18
+ return nTokensForPx(width, pxPerToken) * nTokensForPx(height, pxPerToken);
19
+ }
20
+ function targetImageSize(width, height, params) {
21
+ const { pxPerToken, maxTargetPx, maxTargetTokens } = params;
22
+ if (width <= maxTargetPx && height <= maxTargetPx && nTokensForImg(width, height, pxPerToken) <= maxTargetTokens) {
23
+ return [width, height];
24
+ }
25
+ if (height > width) {
26
+ const [w, h] = targetImageSize(height, width, params);
27
+ return [h, w];
28
+ }
29
+ const aspectRatio = width / height;
30
+ let upperBoundWidth = width;
31
+ let lowerBoundWidth = 1;
32
+ for (;; ) {
33
+ if (lowerBoundWidth + 1 === upperBoundWidth) {
34
+ return [
35
+ lowerBoundWidth,
36
+ Math.max(Math.round(lowerBoundWidth / aspectRatio), 1)
37
+ ];
38
+ }
39
+ const middleWidth = Math.floor((lowerBoundWidth + upperBoundWidth) / 2);
40
+ const middleHeight = Math.max(Math.round(middleWidth / aspectRatio), 1);
41
+ if (middleWidth <= maxTargetPx && nTokensForImg(middleWidth, middleHeight, pxPerToken) <= maxTargetTokens) {
42
+ lowerBoundWidth = middleWidth;
43
+ } else {
44
+ upperBoundWidth = middleWidth;
45
+ }
46
+ }
47
+ }
48
+ var API_RESIZE_PARAMS;
49
+ var init_imageResize = __esm(() => {
50
+ API_RESIZE_PARAMS = {
51
+ pxPerToken: 28,
52
+ maxTargetPx: 1568,
53
+ maxTargetTokens: 1568
54
+ };
55
+ });
56
+
57
+ // packages/@ant/computer-use-mcp/src/tools.ts
58
+ function buildComputerUseTools(caps, coordinateMode, installedAppNames) {
59
+ const coord = COORD_DESC[coordinateMode];
60
+ const installedAppsHint = installedAppNames && installedAppNames.length > 0 ? ` Available applications on this machine: ${installedAppNames.join(", ")}.` : "";
61
+ const coordinateTuple = {
62
+ type: "array",
63
+ items: { type: "number" },
64
+ minItems: 2,
65
+ maxItems: 2,
66
+ description: `(x, y): ${coord.x}`
67
+ };
68
+ const clickModifierText = {
69
+ type: "string",
70
+ description: 'Modifier keys to hold during the click (e.g. "shift", "ctrl+shift"). Supports the same syntax as the key tool.'
71
+ };
72
+ const screenshotDesc = caps.screenshotFiltering === "native" ? "Take a screenshot of the primary display. Applications not in the session allowlist are excluded at the compositor level \u2014 only granted apps and the desktop are visible." : "Take a screenshot of the primary display. On this platform, screenshots are NOT filtered \u2014 all open windows are visible. Input actions targeting apps not in the session allowlist are rejected.";
73
+ return [
74
+ {
75
+ name: "request_access",
76
+ description: "Request user permission to control a set of applications for this session. Must be called before any other tool in this server. " + "The user sees a single dialog listing all requested apps and either allows the whole set or denies it. " + "Call this again mid-session to add more apps; previously granted apps remain granted. " + "Returns the granted apps, denied apps, and screenshot filtering capability.",
77
+ inputSchema: {
78
+ type: "object",
79
+ properties: {
80
+ apps: {
81
+ type: "array",
82
+ items: { type: "string" },
83
+ description: 'Application display names (e.g. "Slack", "Calendar") or bundle identifiers (e.g. "com.tinyspeck.slackmacgap"). Display names are resolved case-insensitively against installed apps.' + installedAppsHint
84
+ },
85
+ reason: {
86
+ type: "string",
87
+ description: "One-sentence explanation shown to the user in the approval dialog. Explain the task, not the mechanism."
88
+ },
89
+ clipboardRead: {
90
+ type: "boolean",
91
+ description: "Also request permission to read the user's clipboard (separate checkbox in the dialog)."
92
+ },
93
+ clipboardWrite: {
94
+ type: "boolean",
95
+ description: "Also request permission to write the user's clipboard. When granted, multi-line `type` calls use the clipboard fast path."
96
+ },
97
+ systemKeyCombos: {
98
+ type: "boolean",
99
+ description: "Also request permission to send system-level key combos (quit app, switch app, lock screen). Without this, those specific combos are blocked."
100
+ }
101
+ },
102
+ required: ["apps", "reason"]
103
+ }
104
+ },
105
+ {
106
+ name: "screenshot",
107
+ description: screenshotDesc + " Returns an error if the allowlist is empty. The returned image is what subsequent click coordinates are relative to.",
108
+ inputSchema: {
109
+ type: "object",
110
+ properties: {
111
+ save_to_disk: {
112
+ type: "boolean",
113
+ description: "Save the image to disk so it can be attached to a message for the user. Returns the saved path in the tool result. Only set this when you intend to share the image \u2014 screenshots you're just looking at don't need saving."
114
+ }
115
+ },
116
+ required: []
117
+ }
118
+ },
119
+ {
120
+ name: "zoom",
121
+ description: "Take a higher-resolution screenshot of a specific region of the last full-screen screenshot. Use this liberally to inspect small text, button labels, or fine UI details that are hard to read in the downsampled full-screen image. " + "IMPORTANT: Coordinates in subsequent click calls always refer to the full-screen screenshot, never the zoomed image. This tool is read-only for inspecting detail.",
122
+ inputSchema: {
123
+ type: "object",
124
+ properties: {
125
+ region: {
126
+ type: "array",
127
+ items: { type: "integer" },
128
+ minItems: 4,
129
+ maxItems: 4,
130
+ description: "(x0, y0, x1, y1): Rectangle to zoom into, in the coordinate space of the most recent full-screen screenshot. x0,y0 = top-left, x1,y1 = bottom-right."
131
+ },
132
+ save_to_disk: {
133
+ type: "boolean",
134
+ description: "Save the image to disk so it can be attached to a message for the user. Returns the saved path in the tool result. Only set this when you intend to share the image."
135
+ }
136
+ },
137
+ required: ["region"]
138
+ }
139
+ },
140
+ {
141
+ name: "left_click",
142
+ description: `Left-click at the given coordinates. ${FRONTMOST_GATE_DESC}`,
143
+ inputSchema: {
144
+ type: "object",
145
+ properties: {
146
+ coordinate: coordinateTuple,
147
+ text: clickModifierText
148
+ },
149
+ required: ["coordinate"]
150
+ }
151
+ },
152
+ {
153
+ name: "double_click",
154
+ description: `Double-click at the given coordinates. Selects a word in most text editors. ${FRONTMOST_GATE_DESC}`,
155
+ inputSchema: {
156
+ type: "object",
157
+ properties: {
158
+ coordinate: coordinateTuple,
159
+ text: clickModifierText
160
+ },
161
+ required: ["coordinate"]
162
+ }
163
+ },
164
+ {
165
+ name: "triple_click",
166
+ description: `Triple-click at the given coordinates. Selects a line in most text editors. ${FRONTMOST_GATE_DESC}`,
167
+ inputSchema: {
168
+ type: "object",
169
+ properties: {
170
+ coordinate: coordinateTuple,
171
+ text: clickModifierText
172
+ },
173
+ required: ["coordinate"]
174
+ }
175
+ },
176
+ {
177
+ name: "right_click",
178
+ description: `Right-click at the given coordinates. Opens a context menu in most applications. ${FRONTMOST_GATE_DESC}`,
179
+ inputSchema: {
180
+ type: "object",
181
+ properties: {
182
+ coordinate: coordinateTuple,
183
+ text: clickModifierText
184
+ },
185
+ required: ["coordinate"]
186
+ }
187
+ },
188
+ {
189
+ name: "middle_click",
190
+ description: `Middle-click (scroll-wheel click) at the given coordinates. ${FRONTMOST_GATE_DESC}`,
191
+ inputSchema: {
192
+ type: "object",
193
+ properties: {
194
+ coordinate: coordinateTuple,
195
+ text: clickModifierText
196
+ },
197
+ required: ["coordinate"]
198
+ }
199
+ },
200
+ {
201
+ name: "type",
202
+ description: `Type text into whatever currently has keyboard focus. ${FRONTMOST_GATE_DESC} Newlines are supported. For keyboard shortcuts use \`key\` instead.`,
203
+ inputSchema: {
204
+ type: "object",
205
+ properties: {
206
+ text: { type: "string", description: "Text to type." }
207
+ },
208
+ required: ["text"]
209
+ }
210
+ },
211
+ {
212
+ name: "key",
213
+ description: `Press a key or key combination (e.g. "return", "escape", "cmd+a", "ctrl+shift+tab"). ${FRONTMOST_GATE_DESC} ` + "System-level combos (quit app, switch app, lock screen) require the `systemKeyCombos` grant \u2014 without it they return an error. All other combos work.",
214
+ inputSchema: {
215
+ type: "object",
216
+ properties: {
217
+ text: {
218
+ type: "string",
219
+ description: 'Modifiers joined with "+", e.g. "cmd+shift+a".'
220
+ },
221
+ repeat: {
222
+ type: "integer",
223
+ minimum: 1,
224
+ maximum: 100,
225
+ description: "Number of times to repeat the key press. Default is 1."
226
+ }
227
+ },
228
+ required: ["text"]
229
+ }
230
+ },
231
+ {
232
+ name: "scroll",
233
+ description: `Scroll at the given coordinates. ${FRONTMOST_GATE_DESC}`,
234
+ inputSchema: {
235
+ type: "object",
236
+ properties: {
237
+ coordinate: coordinateTuple,
238
+ scroll_direction: {
239
+ type: "string",
240
+ enum: ["up", "down", "left", "right"],
241
+ description: "Direction to scroll."
242
+ },
243
+ scroll_amount: {
244
+ type: "integer",
245
+ minimum: 0,
246
+ maximum: 100,
247
+ description: "Number of scroll ticks."
248
+ }
249
+ },
250
+ required: ["coordinate", "scroll_direction", "scroll_amount"]
251
+ }
252
+ },
253
+ {
254
+ name: "left_click_drag",
255
+ description: `Press, move to target, and release. ${FRONTMOST_GATE_DESC}`,
256
+ inputSchema: {
257
+ type: "object",
258
+ properties: {
259
+ coordinate: {
260
+ ...coordinateTuple,
261
+ description: `(x, y) end point: ${coord.x}`
262
+ },
263
+ start_coordinate: {
264
+ ...coordinateTuple,
265
+ description: `(x, y) start point. If omitted, drags from the current cursor position. ${coord.x}`
266
+ }
267
+ },
268
+ required: ["coordinate"]
269
+ }
270
+ },
271
+ {
272
+ name: "mouse_move",
273
+ description: `Move the mouse cursor without clicking. Useful for triggering hover states. ${FRONTMOST_GATE_DESC}`,
274
+ inputSchema: {
275
+ type: "object",
276
+ properties: {
277
+ coordinate: coordinateTuple
278
+ },
279
+ required: ["coordinate"]
280
+ }
281
+ },
282
+ {
283
+ name: "open_application",
284
+ description: "Bring an application to the front, launching it if necessary. The target application must already be in the session allowlist \u2014 call request_access first.",
285
+ inputSchema: {
286
+ type: "object",
287
+ properties: {
288
+ app: {
289
+ type: "string",
290
+ description: 'Display name (e.g. "Slack") or bundle identifier (e.g. "com.tinyspeck.slackmacgap").'
291
+ }
292
+ },
293
+ required: ["app"]
294
+ }
295
+ },
296
+ ...caps.platform === "win32" ? [
297
+ {
298
+ name: "window_management",
299
+ description: "Manage the bound application window via Win32 API calls (ShowWindow, SetWindowPos, SendMessage). " + "All operations target the bound HWND directly \u2014 NO global shortcuts (Win+Down, Alt+F4, etc.). " + "The window must have been opened via open_application first. " + "Actions: minimize (hide to taskbar), maximize (fill screen), restore (undo min/max), " + "close (graceful WM_CLOSE), focus (bring to front), move_offscreen (move to -32000,-32000 for background operation). " + "Use move_resize to reposition or resize the window to specific coordinates.",
300
+ inputSchema: {
301
+ type: "object",
302
+ properties: {
303
+ action: {
304
+ type: "string",
305
+ enum: ["minimize", "maximize", "restore", "close", "focus", "move_offscreen", "move_resize", "get_rect"],
306
+ description: "minimize: ShowWindow(SW_MINIMIZE). " + "maximize: ShowWindow(SW_MAXIMIZE). " + "restore: ShowWindow(SW_RESTORE) \u2014 undo minimize or maximize. " + "close: SendMessage(WM_CLOSE) \u2014 graceful close. " + "focus: SetForegroundWindow + BringWindowToTop. " + "move_offscreen: SetWindowPos(-32000,-32000) \u2014 keeps window usable by SendMessage/PrintWindow but invisible. " + "move_resize: SetWindowPos to specific x,y,width,height. " + "get_rect: GetWindowRect \u2014 returns current position and size."
307
+ },
308
+ x: { type: "integer", description: "X position for move_resize." },
309
+ y: { type: "integer", description: "Y position for move_resize." },
310
+ width: { type: "integer", description: "Width for move_resize." },
311
+ height: { type: "integer", description: "Height for move_resize." }
312
+ },
313
+ required: ["action"]
314
+ }
315
+ },
316
+ {
317
+ name: "click_element",
318
+ description: "Click a GUI element by its accessible name, role, or automationId \u2014 no pixel coordinates needed. " + "Uses Windows UI Automation to find the element and InvokePattern to click it. " + "Prefer this over left_click when the element name is visible in the accessibility snapshot. " + "Falls back to BoundingRect center-click if InvokePattern is not supported.",
319
+ inputSchema: {
320
+ type: "object",
321
+ properties: {
322
+ name: {
323
+ type: "string",
324
+ description: 'Accessible name of the element (e.g. "Save", "File", "Search..."). Case-insensitive partial match.'
325
+ },
326
+ role: {
327
+ type: "string",
328
+ description: 'Control type (e.g. "Button", "MenuItem", "Edit", "Link"). Optional \u2014 narrows the search.'
329
+ },
330
+ automationId: {
331
+ type: "string",
332
+ description: "Exact automationId from the accessibility snapshot. Most precise selector."
333
+ }
334
+ },
335
+ required: []
336
+ }
337
+ },
338
+ {
339
+ name: "type_into_element",
340
+ description: "Type text into a named GUI element using Windows UI Automation ValuePattern. " + "Finds the element by name/role/automationId, then sets its value directly \u2014 " + "no need to click first or use pixel coordinates. Works on Edit, ComboBox, and other value-holding controls.",
341
+ inputSchema: {
342
+ type: "object",
343
+ properties: {
344
+ name: { type: "string", description: "Accessible name of the target element." },
345
+ role: { type: "string", description: 'Control type (optional, e.g. "Edit").' },
346
+ automationId: { type: "string", description: "Exact automationId." },
347
+ text: { type: "string", description: "Text to type/set into the element." }
348
+ },
349
+ required: ["text"]
350
+ }
351
+ },
352
+ {
353
+ name: "open_terminal",
354
+ description: "Open a new terminal window and launch an AI agent CLI. " + "This is a workflow tool that automates: open terminal \u2192 type startup command \u2192 press Enter \u2192 wait \u2192 verify. " + "Supported agents: claude (runs 'claude'), codex (runs 'codex'), gemini (runs 'gemini'), " + "or any custom command. After launching, the tool binds to the new terminal window " + "and takes a screenshot to verify the agent started successfully. " + "Use this when the user says: 'open Claude Code', 'start a Codex terminal', 'launch Gemini', etc.",
355
+ inputSchema: {
356
+ type: "object",
357
+ properties: {
358
+ agent: {
359
+ type: "string",
360
+ enum: ["claude", "codex", "gemini", "custom"],
361
+ description: "Which agent to launch. " + "claude: runs 'claude' command. " + "codex: runs 'codex' command. " + "gemini: runs 'gemini' command. " + "custom: runs the command specified in 'command' parameter."
362
+ },
363
+ command: {
364
+ type: "string",
365
+ description: "Custom command to run in the terminal. Only used when agent='custom'. Example: 'python app.py'"
366
+ },
367
+ terminal: {
368
+ type: "string",
369
+ enum: ["wt", "powershell", "cmd"],
370
+ description: "Which terminal to open. Default: 'wt' (Windows Terminal). 'powershell' for PowerShell window, 'cmd' for Command Prompt."
371
+ },
372
+ working_directory: {
373
+ type: "string",
374
+ description: "Working directory for the terminal. If omitted, uses current directory."
375
+ }
376
+ },
377
+ required: ["agent"]
378
+ }
379
+ },
380
+ {
381
+ name: "bind_window",
382
+ description: "Bind to a specific window for all subsequent operations (screenshot, click, type, etc.). " + "Once bound, screenshots capture only that window via PrintWindow, and all input goes through SendMessageW \u2014 " + "no cursor movement, no focus steal, no interference with the user's desktop. " + "Actions: bind (by title, hwnd, or pid), unbind (release binding), status (show current binding), list (show all visible windows). " + "Use 'list' first to see available windows, then 'bind' with a title or hwnd. " + "open_application auto-binds the launched window, but use this tool to bind to already-running windows or switch between windows.",
383
+ inputSchema: {
384
+ type: "object",
385
+ properties: {
386
+ action: {
387
+ type: "string",
388
+ enum: ["bind", "unbind", "status", "list"],
389
+ description: "bind: Bind to a window (specify title, hwnd, or pid). " + "unbind: Release the current binding, return to full-screen mode. " + "status: Show the currently bound window (hwnd, title, rect). " + "list: List all visible windows with hwnd, pid, and title."
390
+ },
391
+ title: {
392
+ type: "string",
393
+ description: "Window title to search for (partial match, case-insensitive). For 'bind' action."
394
+ },
395
+ hwnd: {
396
+ type: "string",
397
+ description: "Exact window handle from 'list' output. For 'bind' action."
398
+ },
399
+ pid: {
400
+ type: "integer",
401
+ description: "Process ID to find window for. For 'bind' action."
402
+ }
403
+ },
404
+ required: ["action"]
405
+ }
406
+ },
407
+ {
408
+ name: "activate_window",
409
+ description: "Activate the bound window: bring it to foreground, click to ensure keyboard focus, " + "and optionally send an initial key sequence. Use this before any input operations to guarantee " + "the window is ready to receive keyboard/mouse events. " + "Combines SetForegroundWindow + BringWindowToTop + SendMessage(WM_LBUTTONDOWN) in one call.",
410
+ inputSchema: {
411
+ type: "object",
412
+ properties: {
413
+ click_x: { type: "integer", description: "X coordinate to click after activation (client-area). If omitted, clicks center of window." },
414
+ click_y: { type: "integer", description: "Y coordinate to click after activation (client-area). If omitted, clicks center of window." }
415
+ },
416
+ required: []
417
+ }
418
+ },
419
+ {
420
+ name: "prompt_respond",
421
+ description: "Handle interactive CLI/terminal prompts (Yes/No, selection menus, confirmations). " + "Sends a sequence of key events to the bound window to navigate and confirm a prompt. " + "This is a convenience wrapper around bound-window keyboard input for common prompt flows. " + "Typical flows: " + "1) Yes/No prompt \u2192 send 'y' or 'n' + Enter. " + "2) Arrow-key selection menu \u2192 send arrow_down/arrow_up N times + Enter. " + "3) Text input prompt \u2192 type the response + Enter. " + "After responding, take a screenshot to verify the result.",
422
+ inputSchema: {
423
+ type: "object",
424
+ properties: {
425
+ response_type: {
426
+ type: "string",
427
+ enum: ["yes", "no", "enter", "escape", "select", "type"],
428
+ description: "yes: send 'y' + Enter. " + "no: send 'n' + Enter. " + "enter: send Enter only. " + "escape: send Escape (cancel). " + "select: use arrow keys to navigate to an option, then Enter. Requires 'arrow_count'. " + "type: type custom text then Enter. Requires 'text'."
429
+ },
430
+ arrow_direction: {
431
+ type: "string",
432
+ enum: ["up", "down"],
433
+ description: "Arrow key direction for 'select' type. Default: 'down'."
434
+ },
435
+ arrow_count: {
436
+ type: "integer",
437
+ description: "Number of arrow key presses for 'select' type. Default: 1.",
438
+ minimum: 0,
439
+ maximum: 50
440
+ },
441
+ text: {
442
+ type: "string",
443
+ description: "Text to type for 'type' response_type."
444
+ }
445
+ },
446
+ required: ["response_type"]
447
+ }
448
+ },
449
+ {
450
+ name: "status_indicator",
451
+ description: "Control the visual status indicator overlay on the bound window. " + "The indicator is a small floating label at the bottom of the window that shows what Computer Use is doing. " + "It auto-shows during click/type/key/scroll operations, but you can also send custom messages. " + "Actions: show (display a custom message), hide (dismiss), status (check if active).",
452
+ inputSchema: {
453
+ type: "object",
454
+ properties: {
455
+ action: {
456
+ type: "string",
457
+ enum: ["show", "hide", "status"],
458
+ description: "show: display a custom message on the indicator. hide: dismiss the indicator. status: check if indicator is active."
459
+ },
460
+ message: {
461
+ type: "string",
462
+ description: "Custom message to display (for 'show' action). Supports emoji. Auto-fades after 2 seconds."
463
+ }
464
+ },
465
+ required: ["action"]
466
+ }
467
+ },
468
+ {
469
+ name: "virtual_keyboard",
470
+ description: "Send keyboard input directly to the bound window via SendMessageW \u2014 independent of the physical keyboard. " + "The user can keep typing on their own keyboard without interference. " + "Supports: single keys, key combinations (Ctrl+S, Alt+F4), text input, and hold-key operations. " + "All input targets the bound HWND only \u2014 no global keyboard events.",
471
+ inputSchema: {
472
+ type: "object",
473
+ properties: {
474
+ action: {
475
+ type: "string",
476
+ enum: ["type", "combo", "press", "release", "hold"],
477
+ description: "type: Send text string via WM_CHAR (Unicode, supports Chinese/emoji). " + "combo: Send a key combination like ctrl+s, alt+f4, ctrl+shift+a (press all, release in reverse). " + "press: Press a key down and hold it (pair with 'release'). " + "release: Release a previously pressed key. " + "hold: Press key(s) for a duration then release."
478
+ },
479
+ text: {
480
+ type: "string",
481
+ description: "For 'type': the text to input. For 'combo': key combination string (e.g. 'ctrl+s', 'alt+tab', 'ctrl+shift+a'). For 'press'/'release': single key name (e.g. 'shift', 'ctrl', 'a')."
482
+ },
483
+ duration: {
484
+ type: "number",
485
+ description: "For 'hold': seconds to hold the key(s) before releasing. Default: 1."
486
+ },
487
+ repeat: {
488
+ type: "integer",
489
+ description: "Number of times to repeat the action. Default: 1.",
490
+ minimum: 1,
491
+ maximum: 100
492
+ }
493
+ },
494
+ required: ["action", "text"]
495
+ }
496
+ },
497
+ {
498
+ name: "virtual_mouse",
499
+ description: "Control a virtual mouse on the bound window via SendMessageW \u2014 independent of the physical mouse. " + "The user's real cursor stays free. All operations target the bound HWND only.",
500
+ inputSchema: {
501
+ type: "object",
502
+ properties: {
503
+ action: {
504
+ type: "string",
505
+ enum: ["click", "double_click", "right_click", "move", "drag", "down", "up"],
506
+ description: "click: left-click at coordinate. " + "double_click: double left-click. " + "right_click: right-click. " + "move: move virtual cursor (visual only, no click). " + "drag: press at start, move to end, release. Requires coordinate (end) and start_coordinate. " + "down: press left button at coordinate (hold). " + "up: release left button at coordinate."
507
+ },
508
+ coordinate: {
509
+ type: "array",
510
+ items: { type: "number" },
511
+ minItems: 2,
512
+ maxItems: 2,
513
+ description: "(x, y) client-area coordinate on the bound window."
514
+ },
515
+ start_coordinate: {
516
+ type: "array",
517
+ items: { type: "number" },
518
+ minItems: 2,
519
+ maxItems: 2,
520
+ description: "(x, y) start point for drag. If omitted, drags from current virtual cursor position."
521
+ }
522
+ },
523
+ required: ["action", "coordinate"]
524
+ }
525
+ },
526
+ {
527
+ name: "mouse_wheel",
528
+ description: "Scroll inside the bound window using mouse wheel (WM_MOUSEWHEEL / WM_MOUSEHWHEEL). " + "Unlike the generic 'scroll' tool which uses WM_VSCROLL (only works on scrollbar controls), " + "mouse_wheel simulates the physical mouse wheel and works on Excel spreadsheets, web pages, " + "code editors, PDF viewers, and any modern UI. " + "Specify the click point within the window where the scroll should occur \u2014 " + "this determines which panel/pane/element receives the scroll.",
529
+ inputSchema: {
530
+ type: "object",
531
+ properties: {
532
+ coordinate: {
533
+ type: "array",
534
+ items: { type: "number" },
535
+ minItems: 2,
536
+ maxItems: 2,
537
+ description: "(x, y) client-area coordinate where the scroll should occur. Determines which element receives the scroll."
538
+ },
539
+ delta: {
540
+ type: "integer",
541
+ description: "Scroll amount in 'clicks'. Positive = scroll up, negative = scroll down. Each click = 3 lines typically. Use -3 to -5 for page-like scrolling."
542
+ },
543
+ direction: {
544
+ type: "string",
545
+ enum: ["vertical", "horizontal"],
546
+ description: "Scroll direction. Default: 'vertical'. Use 'horizontal' for side-scrolling (e.g. wide Excel sheets, timeline views)."
547
+ }
548
+ },
549
+ required: ["coordinate", "delta"]
550
+ }
551
+ }
552
+ ] : [],
553
+ {
554
+ name: "switch_display",
555
+ description: "Switch which monitor subsequent screenshots capture. Use this when the " + "application you need is on a different monitor than the one shown. " + "The screenshot tool tells you which monitor it captured and lists " + "other attached monitors by name \u2014 pass one of those names here. " + "After switching, call screenshot to see the new monitor. " + 'Pass "auto" to return to automatic monitor selection.',
556
+ inputSchema: {
557
+ type: "object",
558
+ properties: {
559
+ display: {
560
+ type: "string",
561
+ description: 'Monitor name from the screenshot note (e.g. "Built-in Retina Display", ' + '"LG UltraFine"), or "auto" to re-enable automatic selection.'
562
+ }
563
+ },
564
+ required: ["display"]
565
+ }
566
+ },
567
+ {
568
+ name: "list_granted_applications",
569
+ description: "List the applications currently in the session allowlist, plus the active grant flags and coordinate mode. No side effects.",
570
+ inputSchema: {
571
+ type: "object",
572
+ properties: {},
573
+ required: []
574
+ }
575
+ },
576
+ {
577
+ name: "read_clipboard",
578
+ description: "Read the current clipboard contents as text. Requires the `clipboardRead` grant.",
579
+ inputSchema: {
580
+ type: "object",
581
+ properties: {},
582
+ required: []
583
+ }
584
+ },
585
+ {
586
+ name: "write_clipboard",
587
+ description: "Write text to the clipboard. Requires the `clipboardWrite` grant.",
588
+ inputSchema: {
589
+ type: "object",
590
+ properties: {
591
+ text: { type: "string" }
592
+ },
593
+ required: ["text"]
594
+ }
595
+ },
596
+ {
597
+ name: "wait",
598
+ description: "Wait for a specified duration.",
599
+ inputSchema: {
600
+ type: "object",
601
+ properties: {
602
+ duration: {
603
+ type: "number",
604
+ description: "Duration in seconds (0\u2013100)."
605
+ }
606
+ },
607
+ required: ["duration"]
608
+ }
609
+ },
610
+ {
611
+ name: "cursor_position",
612
+ description: "Get the current mouse cursor position. Returns image-pixel coordinates relative to the most recent screenshot, or logical points if no screenshot has been taken.",
613
+ inputSchema: {
614
+ type: "object",
615
+ properties: {},
616
+ required: []
617
+ }
618
+ },
619
+ {
620
+ name: "hold_key",
621
+ description: `Press and hold a key or key combination for the specified duration, then release. ${FRONTMOST_GATE_DESC} ` + "System-level combos require the `systemKeyCombos` grant.",
622
+ inputSchema: {
623
+ type: "object",
624
+ properties: {
625
+ text: {
626
+ type: "string",
627
+ description: 'Key or chord to hold, e.g. "space", "shift+down".'
628
+ },
629
+ duration: {
630
+ type: "number",
631
+ description: "Duration in seconds (0\u2013100)."
632
+ }
633
+ },
634
+ required: ["text", "duration"]
635
+ }
636
+ },
637
+ {
638
+ name: "left_mouse_down",
639
+ description: `Press the left mouse button at the current cursor position and leave it held. ${FRONTMOST_GATE_DESC} ` + "Use mouse_move first to position the cursor. Call left_mouse_up to release. Errors if the button is already held.",
640
+ inputSchema: {
641
+ type: "object",
642
+ properties: {},
643
+ required: []
644
+ }
645
+ },
646
+ {
647
+ name: "left_mouse_up",
648
+ description: `Release the left mouse button at the current cursor position. ${FRONTMOST_GATE_DESC} ` + "Pairs with left_mouse_down. Safe to call even if the button is not currently held.",
649
+ inputSchema: {
650
+ type: "object",
651
+ properties: {},
652
+ required: []
653
+ }
654
+ },
655
+ {
656
+ name: "computer_batch",
657
+ description: "Execute a sequence of actions in ONE tool call. Each individual tool call requires a model\u2192API round trip (seconds); " + "batching a predictable sequence eliminates all but one. Use this whenever you can predict the outcome of several actions ahead \u2014 " + "e.g. click a field, type into it, press Return. Actions execute sequentially and stop on the first error. " + `${FRONTMOST_GATE_DESC} The frontmost check runs before EACH action inside the batch \u2014 if an action opens a non-allowed app, the next action's gate fires and the batch stops there. ` + "Mid-batch screenshot actions are allowed for inspection but coordinates in subsequent clicks always refer to the PRE-BATCH full-screen screenshot.",
658
+ inputSchema: {
659
+ type: "object",
660
+ properties: {
661
+ actions: {
662
+ type: "array",
663
+ minItems: 1,
664
+ items: BATCH_ACTION_ITEM_SCHEMA,
665
+ description: 'List of actions. Example: [{"action":"left_click","coordinate":[100,200]},{"action":"type","text":"hello"},{"action":"key","text":"Return"}]'
666
+ }
667
+ },
668
+ required: ["actions"]
669
+ }
670
+ },
671
+ ...caps.teachMode ? buildTeachTools(coord, installedAppsHint) : []
672
+ ];
673
+ }
674
+ function buildTeachTools(coord, installedAppsHint) {
675
+ const teachStepProperties = {
676
+ explanation: {
677
+ type: "string",
678
+ description: "Tooltip body text. Explain what the user is looking at and why it matters. " + "This is the ONLY place the user sees your words \u2014 be complete but concise."
679
+ },
680
+ next_preview: {
681
+ type: "string",
682
+ description: "One line describing exactly what will happen when the user clicks Next. " + `Example: "Next: I'll click Create Bucket and type the name." ` + "Shown below the explanation in a smaller font."
683
+ },
684
+ anchor: {
685
+ type: "array",
686
+ items: { type: "number" },
687
+ minItems: 2,
688
+ maxItems: 2,
689
+ description: `(x, y) \u2014 where the tooltip arrow points. ${coord.x} ` + "Omit to center the tooltip with no arrow (for general-context steps)."
690
+ },
691
+ actions: {
692
+ type: "array",
693
+ items: BATCH_ACTION_ITEM_SCHEMA,
694
+ description: "Actions to execute when the user clicks Next. Same item schema as computer_batch.actions. " + "Empty array is valid for purely explanatory steps. Actions run sequentially and stop on first error."
695
+ }
696
+ };
697
+ return [
698
+ {
699
+ name: "request_teach_access",
700
+ description: "Request permission to guide the user through a task step-by-step with on-screen tooltips. " + "Use this INSTEAD OF request_access when the user wants to LEARN how to do something " + '(phrases like "teach me", "walk me through", "show me how", "help me learn"). ' + "On approval the main Claude window hides and a fullscreen tooltip overlay appears. " + "You then call teach_step repeatedly; each call shows one tooltip and waits for the user to click Next. " + "Same app-allowlist semantics as request_access, but no clipboard/system-key flags. " + "Teach mode ends automatically when your turn ends.",
701
+ inputSchema: {
702
+ type: "object",
703
+ properties: {
704
+ apps: {
705
+ type: "array",
706
+ items: { type: "string" },
707
+ description: 'Application display names (e.g. "Slack", "Calendar") or bundle identifiers. Resolved case-insensitively against installed apps.' + installedAppsHint
708
+ },
709
+ reason: {
710
+ type: "string",
711
+ description: 'What you will be teaching. Shown in the approval dialog as "Claude wants to guide you through {reason}". Keep it short and task-focused.'
712
+ }
713
+ },
714
+ required: ["apps", "reason"]
715
+ }
716
+ },
717
+ {
718
+ name: "teach_step",
719
+ description: "Show one guided-tour tooltip and wait for the user to click Next. On Next, execute the actions, " + "take a fresh screenshot, and return both \u2014 you do NOT need a separate screenshot call between steps. " + "The returned image shows the state after your actions ran; anchor the next teach_step against it. " + "IMPORTANT \u2014 the user only sees the tooltip during teach mode. Put ALL narration in `explanation`. " + "Text you emit outside teach_step calls is NOT visible until teach mode ends. " + "Pack as many actions as possible into each step's `actions` array \u2014 the user waits through " + "the whole round trip between clicks, so one step that fills a form beats five steps that fill one field each. " + "Returns {exited:true} if the user clicks Exit \u2014 do not call teach_step again after that. " + "Take an initial screenshot before your FIRST teach_step to anchor it.",
720
+ inputSchema: {
721
+ type: "object",
722
+ properties: teachStepProperties,
723
+ required: ["explanation", "next_preview", "actions"]
724
+ }
725
+ },
726
+ {
727
+ name: "teach_batch",
728
+ description: "Queue multiple teach steps in one tool call. Parallels computer_batch: " + "N steps \u2192 one model\u2194API round trip instead of N. Each step still shows a tooltip " + "and waits for the user's Next click, but YOU aren't waiting for a round trip between steps. " + "You can call teach_batch multiple times in one tour \u2014 treat each batch as one predictable " + "SEGMENT (typically: all the steps on one page). The returned screenshot shows the state " + "after the batch's final actions; anchor the NEXT teach_batch against it. " + "WITHIN a batch, all anchors and click coordinates refer to the PRE-BATCH screenshot " + "(same invariant as computer_batch) \u2014 for steps 2+ in a batch, either omit anchor " + "(centered tooltip) or target elements you know won't have moved. " + "Good pattern: batch 5 tooltips on page A (last step navigates) \u2192 read returned screenshot \u2192 " + "batch 3 tooltips on page B \u2192 done. " + "Returns {exited:true, stepsCompleted:N} if the user clicks Exit \u2014 do NOT call again after that; " + "{stepsCompleted, stepFailed, ...} if an action errors mid-batch; " + "otherwise {stepsCompleted, results:[...]} plus a final screenshot. " + "Fall back to individual teach_step calls when you need to react to each intermediate screenshot.",
729
+ inputSchema: {
730
+ type: "object",
731
+ properties: {
732
+ steps: {
733
+ type: "array",
734
+ minItems: 1,
735
+ items: {
736
+ type: "object",
737
+ properties: teachStepProperties,
738
+ required: ["explanation", "next_preview", "actions"]
739
+ },
740
+ description: "Ordered steps. Validated upfront \u2014 a typo in step 5 errors before any tooltip shows."
741
+ }
742
+ },
743
+ required: ["steps"]
744
+ }
745
+ }
746
+ ];
747
+ }
748
+ var COORD_DESC, FRONTMOST_GATE_DESC = "The frontmost application must be in the session allowlist at the time of this call, or this tool returns an error and does nothing.", BATCH_ACTION_ITEM_SCHEMA;
749
+ var init_tools = __esm(() => {
750
+ COORD_DESC = {
751
+ pixels: {
752
+ x: "Horizontal pixel position read directly from the most recent screenshot image, measured from the left edge. The server handles all scaling.",
753
+ y: "Vertical pixel position read directly from the most recent screenshot image, measured from the top edge. The server handles all scaling."
754
+ },
755
+ normalized_0_100: {
756
+ x: "Horizontal position as a percentage of screen width, 0.0\u2013100.0 (0 = left edge, 100 = right edge).",
757
+ y: "Vertical position as a percentage of screen height, 0.0\u2013100.0 (0 = top edge, 100 = bottom edge)."
758
+ }
759
+ };
760
+ BATCH_ACTION_ITEM_SCHEMA = {
761
+ type: "object",
762
+ properties: {
763
+ action: {
764
+ type: "string",
765
+ enum: [
766
+ "key",
767
+ "type",
768
+ "mouse_move",
769
+ "left_click",
770
+ "left_click_drag",
771
+ "right_click",
772
+ "middle_click",
773
+ "double_click",
774
+ "triple_click",
775
+ "scroll",
776
+ "hold_key",
777
+ "screenshot",
778
+ "cursor_position",
779
+ "left_mouse_down",
780
+ "left_mouse_up",
781
+ "wait"
782
+ ],
783
+ description: "The action to perform."
784
+ },
785
+ coordinate: {
786
+ type: "array",
787
+ items: { type: "number" },
788
+ minItems: 2,
789
+ maxItems: 2,
790
+ description: "(x, y) for click/mouse_move/scroll/left_click_drag end point."
791
+ },
792
+ start_coordinate: {
793
+ type: "array",
794
+ items: { type: "number" },
795
+ minItems: 2,
796
+ maxItems: 2,
797
+ description: "(x, y) drag start \u2014 left_click_drag only. Omit to drag from current cursor."
798
+ },
799
+ text: {
800
+ type: "string",
801
+ description: "For type: the text. For key/hold_key: the chord string. For click/scroll: modifier keys to hold."
802
+ },
803
+ scroll_direction: {
804
+ type: "string",
805
+ enum: ["up", "down", "left", "right"]
806
+ },
807
+ scroll_amount: { type: "integer", minimum: 0, maximum: 100 },
808
+ duration: {
809
+ type: "number",
810
+ description: "Seconds (0\u2013100). For hold_key/wait."
811
+ },
812
+ repeat: {
813
+ type: "integer",
814
+ minimum: 1,
815
+ maximum: 100,
816
+ description: "For key: repeat count."
817
+ }
818
+ },
819
+ required: ["action"]
820
+ };
821
+ });
822
+
823
+ // packages/@ant/computer-use-mcp/src/deniedApps.ts
824
+ function categoryToTier(category) {
825
+ if (category === "browser" || category === "trading")
826
+ return "read";
827
+ if (category === "terminal")
828
+ return "click";
829
+ return "full";
830
+ }
831
+ function isPolicyDenied(bundleId, displayName) {
832
+ if (bundleId && POLICY_DENIED_BUNDLE_IDS.has(bundleId))
833
+ return true;
834
+ const lower = displayName.toLowerCase();
835
+ for (const sub of POLICY_DENIED_NAME_SUBSTRINGS) {
836
+ if (lower.includes(sub))
837
+ return true;
838
+ }
839
+ return false;
840
+ }
841
+ function getDeniedCategory(bundleId) {
842
+ if (BROWSER_BUNDLE_IDS.has(bundleId))
843
+ return "browser";
844
+ if (TERMINAL_BUNDLE_IDS.has(bundleId))
845
+ return "terminal";
846
+ if (TRADING_BUNDLE_IDS.has(bundleId))
847
+ return "trading";
848
+ return null;
849
+ }
850
+ function getDeniedCategoryByDisplayName(name) {
851
+ const lower = name.toLowerCase();
852
+ for (const sub of TRADING_NAME_SUBSTRINGS) {
853
+ if (lower.includes(sub))
854
+ return "trading";
855
+ }
856
+ for (const sub of BROWSER_NAME_SUBSTRINGS) {
857
+ if (lower.includes(sub))
858
+ return "browser";
859
+ }
860
+ for (const sub of TERMINAL_NAME_SUBSTRINGS) {
861
+ if (lower.includes(sub))
862
+ return "terminal";
863
+ }
864
+ return null;
865
+ }
866
+ function getDeniedCategoryForApp(bundleId, displayName) {
867
+ if (bundleId) {
868
+ const byId = getDeniedCategory(bundleId);
869
+ if (byId)
870
+ return byId;
871
+ }
872
+ return getDeniedCategoryByDisplayName(displayName);
873
+ }
874
+ function getDefaultTierForApp(bundleId, displayName) {
875
+ return categoryToTier(getDeniedCategoryForApp(bundleId, displayName));
876
+ }
877
+ var BROWSER_BUNDLE_IDS, TERMINAL_BUNDLE_IDS, TRADING_BUNDLE_IDS, POLICY_DENIED_BUNDLE_IDS, POLICY_DENIED_NAME_SUBSTRINGS, BROWSER_NAME_SUBSTRINGS, TERMINAL_NAME_SUBSTRINGS, TRADING_NAME_SUBSTRINGS;
878
+ var init_deniedApps = __esm(() => {
879
+ BROWSER_BUNDLE_IDS = new Set([
880
+ "com.apple.Safari",
881
+ "com.apple.SafariTechnologyPreview",
882
+ "com.google.Chrome",
883
+ "com.google.Chrome.beta",
884
+ "com.google.Chrome.dev",
885
+ "com.google.Chrome.canary",
886
+ "com.microsoft.edgemac",
887
+ "com.microsoft.edgemac.Beta",
888
+ "com.microsoft.edgemac.Dev",
889
+ "com.microsoft.edgemac.Canary",
890
+ "org.mozilla.firefox",
891
+ "org.mozilla.firefoxdeveloperedition",
892
+ "org.mozilla.nightly",
893
+ "org.chromium.Chromium",
894
+ "com.brave.Browser",
895
+ "com.brave.Browser.beta",
896
+ "com.brave.Browser.nightly",
897
+ "com.operasoftware.Opera",
898
+ "com.operasoftware.OperaGX",
899
+ "com.operasoftware.OperaDeveloper",
900
+ "com.vivaldi.Vivaldi",
901
+ "company.thebrowser.Browser",
902
+ "company.thebrowser.dia",
903
+ "org.torproject.torbrowser",
904
+ "com.duckduckgo.macos.browser",
905
+ "ru.yandex.desktop.yandex-browser",
906
+ "ai.perplexity.comet",
907
+ "com.sigmaos.sigmaos.macos",
908
+ "com.kagi.kagimacOS"
909
+ ]);
910
+ TERMINAL_BUNDLE_IDS = new Set([
911
+ "com.apple.Terminal",
912
+ "com.googlecode.iterm2",
913
+ "dev.warp.Warp-Stable",
914
+ "dev.warp.Warp-Beta",
915
+ "com.github.wez.wezterm",
916
+ "org.alacritty",
917
+ "io.alacritty",
918
+ "net.kovidgoyal.kitty",
919
+ "co.zeit.hyper",
920
+ "com.mitchellh.ghostty",
921
+ "org.tabby",
922
+ "com.termius-dmg.mac",
923
+ "com.microsoft.VSCode",
924
+ "com.microsoft.VSCodeInsiders",
925
+ "com.vscodium",
926
+ "com.todesktop.230313mzl4w4u92",
927
+ "com.exafunction.windsurf",
928
+ "dev.zed.Zed",
929
+ "dev.zed.Zed-Preview",
930
+ "com.jetbrains.intellij",
931
+ "com.jetbrains.intellij.ce",
932
+ "com.jetbrains.pycharm",
933
+ "com.jetbrains.pycharm.ce",
934
+ "com.jetbrains.WebStorm",
935
+ "com.jetbrains.CLion",
936
+ "com.jetbrains.goland",
937
+ "com.jetbrains.rubymine",
938
+ "com.jetbrains.PhpStorm",
939
+ "com.jetbrains.datagrip",
940
+ "com.jetbrains.rider",
941
+ "com.jetbrains.AppCode",
942
+ "com.jetbrains.rustrover",
943
+ "com.jetbrains.fleet",
944
+ "com.google.android.studio",
945
+ "com.axosoft.gitkraken",
946
+ "com.sublimetext.4",
947
+ "com.sublimetext.3",
948
+ "org.vim.MacVim",
949
+ "com.neovim.neovim",
950
+ "org.gnu.Emacs",
951
+ "com.apple.dt.Xcode",
952
+ "org.eclipse.platform.ide",
953
+ "org.netbeans.ide",
954
+ "com.microsoft.visual-studio",
955
+ "com.apple.ScriptEditor2",
956
+ "com.apple.Automator",
957
+ "com.apple.shortcuts"
958
+ ]);
959
+ TRADING_BUNDLE_IDS = new Set([
960
+ "com.webull.desktop.v1",
961
+ "com.webull.trade.mac.v1",
962
+ "com.tastytrade.desktop",
963
+ "com.tradingview.tradingviewapp.desktop",
964
+ "com.fidelity.activetrader",
965
+ "com.fmr.activetrader",
966
+ "com.install4j.5889-6375-8446-2021",
967
+ "com.binance.BinanceDesktop",
968
+ "com.electron.exodus",
969
+ "org.pythonmac.unspecified.Electrum",
970
+ "com.ledger.live",
971
+ "io.trezor.TrezorSuite"
972
+ ]);
973
+ POLICY_DENIED_BUNDLE_IDS = new Set([
974
+ "com.apple.TV",
975
+ "com.apple.Music",
976
+ "com.apple.iBooksX",
977
+ "com.apple.podcasts",
978
+ "com.spotify.client",
979
+ "com.amazon.music",
980
+ "com.tidal.desktop",
981
+ "com.deezer.deezer-desktop",
982
+ "com.pandora.desktop",
983
+ "com.electron.pocket-casts",
984
+ "au.com.shiftyjelly.PocketCasts",
985
+ "tv.plex.desktop",
986
+ "tv.plex.htpc",
987
+ "tv.plex.plexamp",
988
+ "com.amazon.aiv.AIVApp",
989
+ "net.kovidgoyal.calibre",
990
+ "com.amazon.Kindle",
991
+ "com.amazon.Lassen",
992
+ "com.kobo.desktop.Kobo"
993
+ ]);
994
+ POLICY_DENIED_NAME_SUBSTRINGS = [
995
+ "netflix",
996
+ "disney+",
997
+ "hulu",
998
+ "prime video",
999
+ "apple tv",
1000
+ "peacock",
1001
+ "paramount+",
1002
+ "tubi",
1003
+ "crunchyroll",
1004
+ "vudu",
1005
+ "kindle",
1006
+ "apple books",
1007
+ "kobo",
1008
+ "play books",
1009
+ "calibre",
1010
+ "libby",
1011
+ "readium",
1012
+ "audible",
1013
+ "libro.fm",
1014
+ "speechify",
1015
+ "spotify",
1016
+ "apple music",
1017
+ "amazon music",
1018
+ "youtube music",
1019
+ "tidal",
1020
+ "deezer",
1021
+ "pandora",
1022
+ "pocket casts",
1023
+ "naver",
1024
+ "reddit",
1025
+ "sony music",
1026
+ "vegas pro",
1027
+ "pitchfork",
1028
+ "economist",
1029
+ "nytimes"
1030
+ ];
1031
+ BROWSER_NAME_SUBSTRINGS = [
1032
+ "safari",
1033
+ "chrome",
1034
+ "firefox",
1035
+ "microsoft edge",
1036
+ "brave",
1037
+ "opera",
1038
+ "vivaldi",
1039
+ "chromium",
1040
+ "arc browser",
1041
+ "tor browser",
1042
+ "duckduckgo",
1043
+ "yandex",
1044
+ "orion browser",
1045
+ "comet",
1046
+ "sigmaos",
1047
+ "dia browser"
1048
+ ];
1049
+ TERMINAL_NAME_SUBSTRINGS = [
1050
+ "terminal",
1051
+ "iterm",
1052
+ "wezterm",
1053
+ "alacritty",
1054
+ "kitty",
1055
+ "ghostty",
1056
+ "tabby",
1057
+ "termius",
1058
+ "script editor",
1059
+ "automator",
1060
+ "powershell",
1061
+ "cmd.exe",
1062
+ "command prompt",
1063
+ "git bash",
1064
+ "conemu",
1065
+ "cmder",
1066
+ "visual studio code",
1067
+ "visual studio",
1068
+ "vscode",
1069
+ "vs code",
1070
+ "vscodium",
1071
+ "cursor",
1072
+ "windsurf",
1073
+ "intellij",
1074
+ "pycharm",
1075
+ "webstorm",
1076
+ "clion",
1077
+ "goland",
1078
+ "rubymine",
1079
+ "phpstorm",
1080
+ "datagrip",
1081
+ "rider",
1082
+ "appcode",
1083
+ "rustrover",
1084
+ "fleet",
1085
+ "android studio",
1086
+ "sublime text",
1087
+ "macvim",
1088
+ "neovim",
1089
+ "emacs",
1090
+ "xcode",
1091
+ "eclipse",
1092
+ "netbeans"
1093
+ ];
1094
+ TRADING_NAME_SUBSTRINGS = [
1095
+ "bloomberg",
1096
+ "ameritrade",
1097
+ "thinkorswim",
1098
+ "schwab",
1099
+ "fidelity",
1100
+ "e*trade",
1101
+ "interactive brokers",
1102
+ "trader workstation",
1103
+ "tradestation",
1104
+ "webull",
1105
+ "robinhood",
1106
+ "tastytrade",
1107
+ "ninjatrader",
1108
+ "tradingview",
1109
+ "moomoo",
1110
+ "tradezero",
1111
+ "prorealtime",
1112
+ "plus500",
1113
+ "saxotrader",
1114
+ "oanda",
1115
+ "metatrader",
1116
+ "forex.com",
1117
+ "avaoptions",
1118
+ "ctrader",
1119
+ "jforex",
1120
+ "iq option",
1121
+ "olymp trade",
1122
+ "binomo",
1123
+ "pocket option",
1124
+ "raceoption",
1125
+ "expertoption",
1126
+ "quotex",
1127
+ "naga",
1128
+ "morgan stanley",
1129
+ "ubs neo",
1130
+ "eikon",
1131
+ "coinbase",
1132
+ "kraken",
1133
+ "binance",
1134
+ "okx",
1135
+ "bybit",
1136
+ "phemex",
1137
+ "stormgain",
1138
+ "crypto.com",
1139
+ "electrum",
1140
+ "ledger live",
1141
+ "trezor",
1142
+ "guarda",
1143
+ "atomic wallet",
1144
+ "bitpay",
1145
+ "bisq",
1146
+ "koinly",
1147
+ "cointracker",
1148
+ "blockfi",
1149
+ "stripe cli",
1150
+ "decentraland",
1151
+ "axie infinity",
1152
+ "gods unchained"
1153
+ ];
1154
+ });
1155
+
1156
+ // packages/@ant/computer-use-mcp/src/keyBlocklist.ts
1157
+ function partitionKeys(seq) {
1158
+ const parts = seq.toLowerCase().split("+").map((p) => p.trim()).filter(Boolean);
1159
+ const mods = [];
1160
+ const keys = [];
1161
+ for (const p of parts) {
1162
+ const canonical = CANONICAL_MODIFIER[p];
1163
+ if (canonical !== undefined) {
1164
+ mods.push(canonical);
1165
+ } else {
1166
+ keys.push(p);
1167
+ }
1168
+ }
1169
+ const uniqueMods = [...new Set(mods)];
1170
+ uniqueMods.sort((a, b) => MODIFIER_ORDER.indexOf(a) - MODIFIER_ORDER.indexOf(b));
1171
+ return { mods: uniqueMods, keys };
1172
+ }
1173
+ function isSystemKeyCombo(seq, platform) {
1174
+ const blocklist = platform === "darwin" ? BLOCKED_DARWIN : BLOCKED_WIN32;
1175
+ const { mods, keys } = partitionKeys(seq);
1176
+ const prefix = mods.length > 0 ? mods.join("+") + "+" : "";
1177
+ if (keys.length === 0) {
1178
+ return blocklist.has(mods.join("+"));
1179
+ }
1180
+ for (const key of keys) {
1181
+ if (blocklist.has(prefix + key)) {
1182
+ return true;
1183
+ }
1184
+ }
1185
+ return false;
1186
+ }
1187
+ var CANONICAL_MODIFIER, MODIFIER_ORDER, BLOCKED_DARWIN, BLOCKED_WIN32;
1188
+ var init_keyBlocklist = __esm(() => {
1189
+ CANONICAL_MODIFIER = {
1190
+ meta: "meta",
1191
+ super: "meta",
1192
+ command: "meta",
1193
+ cmd: "meta",
1194
+ windows: "meta",
1195
+ win: "meta",
1196
+ ctrl: "ctrl",
1197
+ control: "ctrl",
1198
+ lctrl: "ctrl",
1199
+ lcontrol: "ctrl",
1200
+ rctrl: "ctrl",
1201
+ rcontrol: "ctrl",
1202
+ shift: "shift",
1203
+ lshift: "shift",
1204
+ rshift: "shift",
1205
+ alt: "alt",
1206
+ option: "alt"
1207
+ };
1208
+ MODIFIER_ORDER = ["ctrl", "alt", "shift", "meta"];
1209
+ BLOCKED_DARWIN = new Set([
1210
+ "meta+q",
1211
+ "shift+meta+q",
1212
+ "alt+meta+escape",
1213
+ "meta+tab",
1214
+ "meta+space",
1215
+ "ctrl+meta+q"
1216
+ ]);
1217
+ BLOCKED_WIN32 = new Set([
1218
+ "ctrl+alt+delete",
1219
+ "alt+f4",
1220
+ "alt+tab",
1221
+ "meta+l",
1222
+ "meta+d"
1223
+ ]);
1224
+ });
1225
+
1226
+ // packages/@ant/computer-use-mcp/src/pixelCompare.ts
1227
+ function computeCropRect(imgW, imgH, xPercent, yPercent, gridSize) {
1228
+ if (!imgW || !imgH)
1229
+ return null;
1230
+ const clampedX = Math.max(0, Math.min(100, xPercent));
1231
+ const clampedY = Math.max(0, Math.min(100, yPercent));
1232
+ const centerX = Math.round(clampedX / 100 * imgW);
1233
+ const centerY = Math.round(clampedY / 100 * imgH);
1234
+ const halfGrid = Math.floor(gridSize / 2);
1235
+ const cropX = Math.max(0, centerX - halfGrid);
1236
+ const cropY = Math.max(0, centerY - halfGrid);
1237
+ const cropW = Math.min(gridSize, imgW - cropX);
1238
+ const cropH = Math.min(gridSize, imgH - cropY);
1239
+ if (cropW <= 0 || cropH <= 0)
1240
+ return null;
1241
+ return { x: cropX, y: cropY, width: cropW, height: cropH };
1242
+ }
1243
+ function comparePixelAtLocation(crop, lastScreenshot, freshScreenshot, xPercent, yPercent, gridSize = DEFAULT_GRID_SIZE) {
1244
+ const rect = computeCropRect(freshScreenshot.width, freshScreenshot.height, xPercent, yPercent, gridSize);
1245
+ if (!rect)
1246
+ return false;
1247
+ const patch1 = crop(lastScreenshot.base64, rect);
1248
+ const patch2 = crop(freshScreenshot.base64, rect);
1249
+ if (!patch1 || !patch2)
1250
+ return false;
1251
+ return patch1.equals(patch2);
1252
+ }
1253
+ async function validateClickTarget(crop, lastScreenshot, xPercent, yPercent, takeFreshScreenshot, logger, gridSize = DEFAULT_GRID_SIZE) {
1254
+ if (!lastScreenshot) {
1255
+ return { valid: true, skipped: true };
1256
+ }
1257
+ try {
1258
+ const fresh = await takeFreshScreenshot();
1259
+ if (!fresh) {
1260
+ return { valid: true, skipped: true };
1261
+ }
1262
+ const pixelsMatch = comparePixelAtLocation(crop, lastScreenshot, fresh, xPercent, yPercent, gridSize);
1263
+ if (pixelsMatch) {
1264
+ return { valid: true, skipped: false };
1265
+ }
1266
+ return {
1267
+ valid: false,
1268
+ skipped: false,
1269
+ warning: "Screen content at the target location changed since the last screenshot. Take a new screenshot before clicking."
1270
+ };
1271
+ } catch (err) {
1272
+ logger.debug("[pixelCompare] validation error, skipping", err);
1273
+ return { valid: true, skipped: true };
1274
+ }
1275
+ }
1276
+ var DEFAULT_GRID_SIZE = 9;
1277
+ var init_pixelCompare = () => {};
1278
+
1279
+ // packages/@ant/computer-use-mcp/src/sentinelApps.ts
1280
+ function getSentinelCategory(bundleId) {
1281
+ if (SHELL_ACCESS_BUNDLE_IDS.has(bundleId))
1282
+ return "shell";
1283
+ if (FILESYSTEM_ACCESS_BUNDLE_IDS.has(bundleId))
1284
+ return "filesystem";
1285
+ if (SYSTEM_SETTINGS_BUNDLE_IDS.has(bundleId))
1286
+ return "system_settings";
1287
+ return null;
1288
+ }
1289
+ var SHELL_ACCESS_BUNDLE_IDS, FILESYSTEM_ACCESS_BUNDLE_IDS, SYSTEM_SETTINGS_BUNDLE_IDS, SENTINEL_BUNDLE_IDS;
1290
+ var init_sentinelApps = __esm(() => {
1291
+ SHELL_ACCESS_BUNDLE_IDS = new Set([
1292
+ "com.apple.Terminal",
1293
+ "com.googlecode.iterm2",
1294
+ "com.microsoft.VSCode",
1295
+ "dev.warp.Warp-Stable",
1296
+ "com.github.wez.wezterm",
1297
+ "io.alacritty",
1298
+ "net.kovidgoyal.kitty",
1299
+ "com.jetbrains.intellij",
1300
+ "com.jetbrains.pycharm"
1301
+ ]);
1302
+ FILESYSTEM_ACCESS_BUNDLE_IDS = new Set(["com.apple.finder"]);
1303
+ SYSTEM_SETTINGS_BUNDLE_IDS = new Set(["com.apple.systempreferences"]);
1304
+ SENTINEL_BUNDLE_IDS = new Set([
1305
+ ...SHELL_ACCESS_BUNDLE_IDS,
1306
+ ...FILESYSTEM_ACCESS_BUNDLE_IDS,
1307
+ ...SYSTEM_SETTINGS_BUNDLE_IDS
1308
+ ]);
1309
+ });
1310
+
1311
+ // packages/@ant/computer-use-mcp/src/toolCalls.ts
1312
+ import { randomUUID } from "crypto";
1313
+ function errorResult(text, errorKind) {
1314
+ return {
1315
+ content: [{ type: "text", text }],
1316
+ isError: true,
1317
+ telemetry: errorKind ? { error_kind: errorKind } : undefined
1318
+ };
1319
+ }
1320
+ function okText(text) {
1321
+ return { content: [{ type: "text", text }] };
1322
+ }
1323
+ function okJson(obj, telemetry) {
1324
+ return {
1325
+ content: [{ type: "text", text: JSON.stringify(obj) }],
1326
+ telemetry
1327
+ };
1328
+ }
1329
+ function asRecord(args) {
1330
+ if (typeof args === "object" && args !== null) {
1331
+ return args;
1332
+ }
1333
+ return {};
1334
+ }
1335
+ function requireString(args, key) {
1336
+ const v = args[key];
1337
+ if (typeof v !== "string") {
1338
+ return new Error(`"${key}" must be a string.`);
1339
+ }
1340
+ return v;
1341
+ }
1342
+ function extractCoordinate(args, paramName = "coordinate") {
1343
+ const coord = args[paramName];
1344
+ if (coord === undefined) {
1345
+ return new Error(`${paramName} is required`);
1346
+ }
1347
+ if (!Array.isArray(coord) || coord.length !== 2) {
1348
+ return new Error(`${paramName} must be an array of length 2`);
1349
+ }
1350
+ const [x, y] = coord;
1351
+ if (typeof x !== "number" || typeof y !== "number" || x < 0 || y < 0) {
1352
+ return new Error(`${paramName} must be a tuple of non-negative numbers`);
1353
+ }
1354
+ return [x, y];
1355
+ }
1356
+ function scaleCoord(rawX, rawY, mode, display, lastScreenshot, logger) {
1357
+ if (mode === "normalized_0_100") {
1358
+ return {
1359
+ x: Math.round(rawX / 100 * display.width) + display.originX,
1360
+ y: Math.round(rawY / 100 * display.height) + display.originY
1361
+ };
1362
+ }
1363
+ if (lastScreenshot) {
1364
+ return {
1365
+ x: Math.round(rawX * (lastScreenshot.displayWidth / lastScreenshot.width)) + lastScreenshot.originX,
1366
+ y: Math.round(rawY * (lastScreenshot.displayHeight / lastScreenshot.height)) + lastScreenshot.originY
1367
+ };
1368
+ }
1369
+ logger.warn("[computer-use] pixels-mode coordinate received with no prior screenshot; " + "falling back to /scaleFactor. Click may be off if downsample is active.");
1370
+ return {
1371
+ x: Math.round(rawX / display.scaleFactor) + display.originX,
1372
+ y: Math.round(rawY / display.scaleFactor) + display.originY
1373
+ };
1374
+ }
1375
+ function coordToPercentageForPixelCompare(rawX, rawY, mode, lastScreenshot) {
1376
+ if (mode === "normalized_0_100") {
1377
+ return { xPct: rawX, yPct: rawY };
1378
+ }
1379
+ if (!lastScreenshot) {
1380
+ return { xPct: 0, yPct: 0 };
1381
+ }
1382
+ return {
1383
+ xPct: rawX / lastScreenshot.width * 100,
1384
+ yPct: rawY / lastScreenshot.height * 100
1385
+ };
1386
+ }
1387
+ function tierSatisfies(grantTier, actionKind) {
1388
+ const tier = grantTier ?? "full";
1389
+ if (actionKind === "mouse_position")
1390
+ return true;
1391
+ if (actionKind === "keyboard" || actionKind === "mouse_full") {
1392
+ return tier === "full";
1393
+ }
1394
+ return tier === "click" || tier === "full";
1395
+ }
1396
+ async function syncClipboardStash(adapter, overrides, frontmostIsClickTier) {
1397
+ const current = overrides.getClipboardStash?.();
1398
+ if (!frontmostIsClickTier) {
1399
+ if (current === undefined)
1400
+ return;
1401
+ try {
1402
+ await adapter.executor.writeClipboard(current);
1403
+ overrides.onClipboardStashChanged?.(undefined);
1404
+ } catch {}
1405
+ return;
1406
+ }
1407
+ if (current === undefined) {
1408
+ try {
1409
+ const read = await adapter.executor.readClipboard();
1410
+ overrides.onClipboardStashChanged?.(read);
1411
+ } catch {
1412
+ overrides.onClipboardStashChanged?.("");
1413
+ }
1414
+ }
1415
+ try {
1416
+ await adapter.executor.writeClipboard("");
1417
+ } catch {}
1418
+ }
1419
+ async function runInputActionGates(adapter, overrides, subGates, actionKind) {
1420
+ if (subGates.hideBeforeAction) {
1421
+ const hidden = await adapter.executor.prepareForAction(overrides.allowedApps.map((a) => a.bundleId), overrides.selectedDisplayId);
1422
+ if (hidden.length > 0) {
1423
+ overrides.onAppsHidden?.(hidden);
1424
+ }
1425
+ }
1426
+ if (adapter.executor.capabilities.screenshotFiltering === "none") {
1427
+ return null;
1428
+ }
1429
+ const frontmost = await adapter.executor.getFrontmostApp();
1430
+ const tierByBundleId = new Map(overrides.allowedApps.map((a) => [a.bundleId, a.tier]));
1431
+ const frontmostTier = frontmost ? tierByBundleId.get(frontmost.bundleId) : undefined;
1432
+ if (subGates.clipboardGuard) {
1433
+ await syncClipboardStash(adapter, overrides, frontmostTier === "click");
1434
+ }
1435
+ if (!frontmost) {
1436
+ return null;
1437
+ }
1438
+ const { hostBundleId } = adapter.executor.capabilities;
1439
+ if (frontmostTier !== undefined) {
1440
+ if (tierSatisfies(frontmostTier, actionKind))
1441
+ return null;
1442
+ if (frontmostTier === "read") {
1443
+ const isBrowser = getDeniedCategoryForApp(frontmost.bundleId, frontmost.displayName) === "browser";
1444
+ return errorResult(`"${frontmost.displayName}" is granted at tier "read" \u2014 ` + `visible in screenshots only, no clicks or typing.` + (isBrowser ? " Use the Claude-in-Chrome MCP for browser interaction (tools " + "named `mcp__Claude_in_Chrome__*`; load via ToolSearch if " + "deferred)." : " No interaction is permitted; ask the user to take any " + "actions in this app themselves.") + TIER_ANTI_SUBVERSION, "tier_insufficient");
1445
+ }
1446
+ if (actionKind === "keyboard") {
1447
+ return errorResult(`"${frontmost.displayName}" is granted at tier "click" \u2014 ` + `typing, key presses, and paste require tier "full". The keys ` + `would go to this app's text fields or integrated terminal. To ` + `type into a different app, click it first to bring it forward. ` + `For shell commands, use the Bash tool.` + TIER_ANTI_SUBVERSION, "tier_insufficient");
1448
+ }
1449
+ return errorResult(`"${frontmost.displayName}" is granted at tier "click" \u2014 ` + `right-click, middle-click, and clicks with modifier keys require ` + `tier "full". Right-click opens a context menu with Paste/Cut, and ` + `modifier chords fire as keystrokes before the click. Plain ` + `left_click is allowed here.` + TIER_ANTI_SUBVERSION, "tier_insufficient");
1450
+ }
1451
+ if (frontmost.bundleId === FINDER_BUNDLE_ID)
1452
+ return null;
1453
+ if (frontmost.bundleId === hostBundleId) {
1454
+ if (actionKind !== "keyboard") {
1455
+ return null;
1456
+ }
1457
+ return errorResult("Claude's own window still has keyboard focus. This should not happen " + "after the pre-action defocus. Click on the target application first.", "state_conflict");
1458
+ }
1459
+ return errorResult(`"${frontmost.displayName}" is not in the allowed applications and is ` + `currently in front. Take a new screenshot \u2014 it may have appeared ` + `since your last one.`, "app_not_granted");
1460
+ }
1461
+ async function runHitTestGate(adapter, overrides, subGates, x, y, actionKind) {
1462
+ if (adapter.executor.capabilities.screenshotFiltering === "none") {
1463
+ return null;
1464
+ }
1465
+ const target = await adapter.executor.appUnderPoint(x, y);
1466
+ if (!target)
1467
+ return null;
1468
+ if (target.bundleId === FINDER_BUNDLE_ID)
1469
+ return null;
1470
+ const tierByBundleId = new Map(overrides.allowedApps.map((a) => [a.bundleId, a.tier]));
1471
+ if (!tierByBundleId.has(target.bundleId)) {
1472
+ return errorResult(`Click at these coordinates would land on "${target.displayName}", ` + `which is not in the allowed applications. Take a fresh screenshot ` + `to see the current window layout.`, "app_not_granted");
1473
+ }
1474
+ const targetTier = tierByBundleId.get(target.bundleId);
1475
+ if (subGates.clipboardGuard && targetTier === "click") {
1476
+ await syncClipboardStash(adapter, overrides, true);
1477
+ }
1478
+ if (tierSatisfies(targetTier, actionKind))
1479
+ return null;
1480
+ if (actionKind === "mouse_full" && targetTier === "click") {
1481
+ return errorResult(`Click at these coordinates would land on "${target.displayName}", ` + `which is granted at tier "click" \u2014 right-click, middle-click, and ` + `clicks with modifier keys require tier "full" (they can Paste via ` + `the context menu or fire modifier-chord keystrokes). Plain ` + `left_click is allowed here.` + TIER_ANTI_SUBVERSION, "tier_insufficient");
1482
+ }
1483
+ const isBrowser = getDeniedCategoryForApp(target.bundleId, target.displayName) === "browser";
1484
+ return errorResult(`Click at these coordinates would land on "${target.displayName}", ` + `which is granted at tier "read" (screenshots only, no interaction). ` + (isBrowser ? "Use the Claude-in-Chrome MCP for browser interaction." : "Ask the user to take any actions in this app themselves.") + TIER_ANTI_SUBVERSION, "tier_insufficient");
1485
+ }
1486
+ function decodedByteLength(base64) {
1487
+ const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
1488
+ return Math.floor(base64.length * 3 / 4) - padding;
1489
+ }
1490
+ async function takeScreenshotWithRetry(executor, allowedBundleIds, logger, displayId) {
1491
+ let shot = await executor.screenshot({ allowedBundleIds, displayId });
1492
+ if (decodedByteLength(shot.base64) < MIN_SCREENSHOT_BYTES) {
1493
+ logger.warn(`[computer-use] screenshot implausibly small (${decodedByteLength(shot.base64)} bytes decoded), retrying once`);
1494
+ shot = await executor.screenshot({ allowedBundleIds, displayId });
1495
+ }
1496
+ return shot;
1497
+ }
1498
+ function segmentGraphemes(text) {
1499
+ try {
1500
+ const Segmenter = Intl.Segmenter;
1501
+ if (typeof Segmenter === "function") {
1502
+ const seg = new Segmenter(undefined, { granularity: "grapheme" });
1503
+ return Array.from(seg.segment(text), (s) => s.segment);
1504
+ }
1505
+ } catch {}
1506
+ return Array.from(text);
1507
+ }
1508
+ function sleep(ms) {
1509
+ return new Promise((r) => setTimeout(r, ms));
1510
+ }
1511
+ function parseKeyChord(text) {
1512
+ return text.split("+").map((s) => s.trim()).filter(Boolean);
1513
+ }
1514
+ function resetMouseButtonHeld() {
1515
+ mouseButtonHeld = false;
1516
+ mouseMoved = false;
1517
+ }
1518
+ async function releaseHeldMouse(adapter) {
1519
+ if (!mouseButtonHeld)
1520
+ return;
1521
+ await adapter.executor.mouseUp();
1522
+ mouseButtonHeld = false;
1523
+ mouseMoved = false;
1524
+ }
1525
+ function defersLockAcquire(toolName) {
1526
+ return toolName === "request_access" || toolName === "list_granted_applications";
1527
+ }
1528
+ function looksLikeBundleId(s) {
1529
+ return REVERSE_DNS_RE.test(s) && !s.includes(" ");
1530
+ }
1531
+ function resolveRequestedApps(requestedNames, installed, alreadyGrantedBundleIds) {
1532
+ const byLowerDisplayName = new Map;
1533
+ const byBundleId = new Map;
1534
+ for (const app of installed) {
1535
+ byBundleId.set(app.bundleId, app);
1536
+ byLowerDisplayName.set(app.displayName.toLowerCase(), app);
1537
+ }
1538
+ return requestedNames.map((requested) => {
1539
+ let resolved;
1540
+ if (looksLikeBundleId(requested)) {
1541
+ resolved = byBundleId.get(requested);
1542
+ }
1543
+ if (!resolved) {
1544
+ resolved = byLowerDisplayName.get(requested.toLowerCase());
1545
+ }
1546
+ if (!resolved) {
1547
+ const clean = requested.toLowerCase().replace(/\.exe$/, "").trim();
1548
+ for (const [name, app] of byLowerDisplayName) {
1549
+ if (name.includes(clean) || clean.includes(name)) {
1550
+ resolved = app;
1551
+ break;
1552
+ }
1553
+ }
1554
+ }
1555
+ const bundleId = resolved?.bundleId;
1556
+ const bundleIdCandidate = bundleId ?? (looksLikeBundleId(requested) ? requested : undefined);
1557
+ return {
1558
+ requestedName: requested,
1559
+ resolved,
1560
+ isSentinel: bundleId ? SENTINEL_BUNDLE_IDS.has(bundleId) : false,
1561
+ alreadyGranted: bundleId ? alreadyGrantedBundleIds.has(bundleId) : false,
1562
+ proposedTier: getDefaultTierForApp(bundleIdCandidate, resolved?.displayName ?? requested)
1563
+ };
1564
+ });
1565
+ }
1566
+ async function handleRequestAccess(adapter, args, overrides, tccState) {
1567
+ if (!overrides.onPermissionRequest) {
1568
+ return errorResult("This session was not wired with a permission handler. Computer control is not available here.", "feature_unavailable");
1569
+ }
1570
+ if (overrides.getTeachModeActive?.()) {
1571
+ return errorResult("Cannot request additional permissions during teach mode \u2014 the permission dialog would be hidden. End teach mode (finish the tour or let the turn complete), then call request_access, then start a new tour.", "teach_mode_conflict");
1572
+ }
1573
+ const reason = requireString(args, "reason");
1574
+ if (reason instanceof Error)
1575
+ return errorResult(reason.message, "bad_args");
1576
+ if (tccState) {
1577
+ const req = {
1578
+ requestId: randomUUID(),
1579
+ reason,
1580
+ apps: [],
1581
+ requestedFlags: {},
1582
+ screenshotFiltering: adapter.executor.capabilities.screenshotFiltering,
1583
+ tccState
1584
+ };
1585
+ await overrides.onPermissionRequest(req);
1586
+ const recheck = await adapter.ensureOsPermissions();
1587
+ if (recheck.granted) {
1588
+ return errorResult("macOS Accessibility and Screen Recording are now both granted. " + "Call request_access again immediately \u2014 the next call will show " + "the app selection list.");
1589
+ }
1590
+ const missing = [];
1591
+ if (!recheck.accessibility)
1592
+ missing.push("Accessibility");
1593
+ if (!recheck.screenRecording)
1594
+ missing.push("Screen Recording");
1595
+ return errorResult(`macOS ${missing.join(" and ")} permission(s) not yet granted. ` + `The permission panel has been shown. Once the user grants the ` + `missing permission(s), call request_access again.`, "tcc_not_granted");
1596
+ }
1597
+ const rawApps = args.apps;
1598
+ if (!Array.isArray(rawApps) || !rawApps.every((a) => typeof a === "string")) {
1599
+ return errorResult('"apps" must be an array of strings.', "bad_args");
1600
+ }
1601
+ const apps = rawApps;
1602
+ const requestedFlags = {};
1603
+ if (typeof args.clipboardRead === "boolean") {
1604
+ requestedFlags.clipboardRead = args.clipboardRead;
1605
+ }
1606
+ if (typeof args.clipboardWrite === "boolean") {
1607
+ requestedFlags.clipboardWrite = args.clipboardWrite;
1608
+ }
1609
+ if (typeof args.systemKeyCombos === "boolean") {
1610
+ requestedFlags.systemKeyCombos = args.systemKeyCombos;
1611
+ }
1612
+ const {
1613
+ needDialog,
1614
+ skipDialogGrants,
1615
+ willHide,
1616
+ tieredApps,
1617
+ userDenied,
1618
+ policyDenied
1619
+ } = await buildAccessRequest(adapter, apps, overrides.allowedApps, new Set(overrides.userDeniedBundleIds), overrides.selectedDisplayId);
1620
+ let dialogGranted = [];
1621
+ let dialogDenied = [];
1622
+ let dialogFlags = overrides.grantFlags;
1623
+ if (needDialog.length > 0 || Object.keys(requestedFlags).length > 0) {
1624
+ const req = {
1625
+ requestId: randomUUID(),
1626
+ reason,
1627
+ apps: needDialog,
1628
+ requestedFlags,
1629
+ screenshotFiltering: adapter.executor.capabilities.screenshotFiltering,
1630
+ ...willHide.length > 0 && {
1631
+ willHide,
1632
+ autoUnhideEnabled: adapter.getAutoUnhideEnabled()
1633
+ }
1634
+ };
1635
+ const response = await overrides.onPermissionRequest(req);
1636
+ dialogGranted = response.granted;
1637
+ dialogDenied = response.denied;
1638
+ dialogFlags = response.flags;
1639
+ }
1640
+ const allGranted = [...skipDialogGrants, ...dialogGranted];
1641
+ const grantedBundleIds = new Set(allGranted.map((g) => g.bundleId));
1642
+ const grantedTieredApps = tieredApps.filter((t) => grantedBundleIds.has(t.bundleId));
1643
+ let windowLocations = [];
1644
+ try {
1645
+ windowLocations = await buildWindowLocations(adapter, allGranted);
1646
+ } catch (e) {
1647
+ adapter.logger.warn(`[computer-use] buildWindowLocations failed: ${String(e)}`);
1648
+ }
1649
+ return okJson({
1650
+ granted: allGranted,
1651
+ denied: dialogDenied,
1652
+ ...policyDenied.length > 0 && {
1653
+ policyDenied: {
1654
+ apps: policyDenied,
1655
+ guidance: buildPolicyDeniedGuidance(policyDenied)
1656
+ }
1657
+ },
1658
+ ...userDenied.length > 0 && {
1659
+ userDenied: {
1660
+ apps: userDenied,
1661
+ guidance: buildUserDeniedGuidance(userDenied)
1662
+ }
1663
+ },
1664
+ ...grantedTieredApps.length > 0 && {
1665
+ tierGuidance: buildTierGuidanceMessage(grantedTieredApps)
1666
+ },
1667
+ screenshotFiltering: adapter.executor.capabilities.screenshotFiltering,
1668
+ ...windowLocations.length > 0 ? { windowLocations } : {}
1669
+ }, {
1670
+ granted_count: dialogGranted.length,
1671
+ denied_count: dialogDenied.length,
1672
+ ...tierAssignmentTelemetry(grantedTieredApps)
1673
+ });
1674
+ }
1675
+ async function buildWindowLocations(adapter, granted) {
1676
+ if (granted.length === 0)
1677
+ return [];
1678
+ const displays = await adapter.executor.listDisplays();
1679
+ if (displays.length <= 1)
1680
+ return [];
1681
+ const grantedBundleIds = granted.map((g) => g.bundleId);
1682
+ const windowLocs = await adapter.executor.findWindowDisplays(grantedBundleIds);
1683
+ const displayById = new Map(displays.map((d) => [d.displayId, d]));
1684
+ const idsByBundle = new Map(windowLocs.map((w) => [w.bundleId, w.displayIds]));
1685
+ const out = [];
1686
+ for (const g of granted) {
1687
+ const displayIds = idsByBundle.get(g.bundleId);
1688
+ if (!displayIds || displayIds.length === 0)
1689
+ continue;
1690
+ out.push({
1691
+ bundleId: g.bundleId,
1692
+ displayName: g.displayName,
1693
+ displays: displayIds.map((id) => {
1694
+ const d = displayById.get(id);
1695
+ return { id, label: d?.label, isPrimary: d?.isPrimary };
1696
+ })
1697
+ });
1698
+ }
1699
+ return out;
1700
+ }
1701
+ async function buildAccessRequest(adapter, apps, allowedApps, userDeniedBundleIds, selectedDisplayId) {
1702
+ const alreadyGranted = new Set(allowedApps.map((g) => g.bundleId));
1703
+ const installed = await adapter.executor.listInstalledApps();
1704
+ const resolved = resolveRequestedApps(apps, installed, alreadyGranted);
1705
+ const policyDenied = [];
1706
+ const afterPolicy = [];
1707
+ for (const r of resolved) {
1708
+ const displayName = r.resolved?.displayName ?? r.requestedName;
1709
+ if (isPolicyDenied(r.resolved?.bundleId, displayName)) {
1710
+ policyDenied.push({ requestedName: r.requestedName, displayName });
1711
+ } else {
1712
+ afterPolicy.push(r);
1713
+ }
1714
+ }
1715
+ const userDenied = [];
1716
+ const surviving = [];
1717
+ for (const r of afterPolicy) {
1718
+ if (r.resolved && userDeniedBundleIds.has(r.resolved.bundleId)) {
1719
+ userDenied.push({
1720
+ requestedName: r.requestedName,
1721
+ displayName: r.resolved.displayName
1722
+ });
1723
+ } else {
1724
+ surviving.push(r);
1725
+ }
1726
+ }
1727
+ const tieredApps = [];
1728
+ for (const r of surviving) {
1729
+ if (r.proposedTier === "full" || !r.resolved)
1730
+ continue;
1731
+ tieredApps.push({
1732
+ bundleId: r.resolved.bundleId,
1733
+ displayName: r.resolved.displayName,
1734
+ tier: r.proposedTier
1735
+ });
1736
+ }
1737
+ const skipDialog = surviving.filter((r) => r.alreadyGranted);
1738
+ const needDialog = surviving.filter((r) => !r.alreadyGranted);
1739
+ for (const r of needDialog) {
1740
+ if (!r.resolved)
1741
+ continue;
1742
+ try {
1743
+ r.resolved.iconDataUrl = await adapter.executor.getAppIcon(r.resolved.path);
1744
+ } catch {}
1745
+ }
1746
+ const now = Date.now();
1747
+ const skipDialogGrants = skipDialog.filter((r) => r.resolved).map((r) => {
1748
+ const existing = allowedApps.find((g) => g.bundleId === r.resolved.bundleId);
1749
+ return existing ?? {
1750
+ bundleId: r.resolved.bundleId,
1751
+ displayName: r.resolved.displayName,
1752
+ grantedAt: now,
1753
+ tier: r.proposedTier
1754
+ };
1755
+ });
1756
+ const exemptForPreview = [
1757
+ ...allowedApps.map((a) => a.bundleId),
1758
+ ...surviving.filter((r) => r.resolved).map((r) => r.resolved.bundleId)
1759
+ ];
1760
+ const willHide = await adapter.executor.previewHideSet(exemptForPreview, selectedDisplayId);
1761
+ return {
1762
+ needDialog,
1763
+ skipDialogGrants,
1764
+ willHide,
1765
+ tieredApps,
1766
+ userDenied,
1767
+ policyDenied
1768
+ };
1769
+ }
1770
+ function buildTierGuidanceMessage(tiered) {
1771
+ const readBrowsers = tiered.filter((t) => t.tier === "read" && getDeniedCategoryForApp(t.bundleId, t.displayName) === "browser");
1772
+ const readOther = tiered.filter((t) => t.tier === "read" && getDeniedCategoryForApp(t.bundleId, t.displayName) !== "browser");
1773
+ const clickTier = tiered.filter((t) => t.tier === "click");
1774
+ const parts = [];
1775
+ if (readBrowsers.length > 0) {
1776
+ const names = readBrowsers.map((b) => `"${b.displayName}"`).join(", ");
1777
+ parts.push(`${names} ${readBrowsers.length === 1 ? "is a browser" : "are browsers"} \u2014 ` + `granted at tier "read" (visible in screenshots only; no clicks or ` + `typing). You can read what's on screen but cannot navigate, click, ` + `or type into ${readBrowsers.length === 1 ? "it" : "them"}. For browser ` + `interaction, use the Claude-in-Chrome MCP (tools named ` + `\`mcp__Claude_in_Chrome__*\`; load via ToolSearch if deferred).`);
1778
+ }
1779
+ if (readOther.length > 0) {
1780
+ const names = readOther.map((t) => `"${t.displayName}"`).join(", ");
1781
+ parts.push(`${names} ${readOther.length === 1 ? "is" : "are"} granted at tier ` + `"read" (visible in screenshots only; no clicks or typing). You can ` + `read what's on screen but cannot interact. Ask the user to take any ` + `actions in ${readOther.length === 1 ? "this app" : "these apps"} ` + `themselves.`);
1782
+ }
1783
+ if (clickTier.length > 0) {
1784
+ const names = clickTier.map((t) => `"${t.displayName}"`).join(", ");
1785
+ parts.push(`${names} ${clickTier.length === 1 ? "has" : "have"} terminal or IDE ` + `capabilities \u2014 granted at tier "click" (visible + plain left-click ` + `only; NO typing, key presses, right-click, modifier-clicks, or ` + `drag-drop). You can click buttons and scroll output, but ` + `${clickTier.length === 1 ? "its" : "their"} integrated terminal and ` + `editor are off-limits to keyboard input. Right-click (context-menu ` + `Paste) and dragging text onto ${clickTier.length === 1 ? "it" : "them"} ` + `require tier "full". For shell commands, use the Bash tool.`);
1786
+ }
1787
+ if (parts.length === 0)
1788
+ return "";
1789
+ return parts.join(`
1790
+
1791
+ `) + TIER_ANTI_SUBVERSION;
1792
+ }
1793
+ function buildUserDeniedGuidance(userDenied) {
1794
+ const names = userDenied.map((d) => `"${d.displayName}"`).join(", ");
1795
+ const one = userDenied.length === 1;
1796
+ return `${names} ${one ? "is" : "are"} in the user's auto-deny list ` + `(Settings \u2192 Desktop app (General) \u2192 Computer Use \u2192 Denied apps). ` + `Requests for ` + `${one ? "this app" : "these apps"} are automatically denied. If you need access for ` + `this task, ask the user to remove ${one ? "it" : "them"} from their ` + `deny list in Settings \u2014 you cannot request this through the tool.`;
1797
+ }
1798
+ function buildPolicyDeniedGuidance(policyDenied) {
1799
+ const names = policyDenied.map((d) => `"${d.displayName}"`).join(", ");
1800
+ const one = policyDenied.length === 1;
1801
+ return `${names} ${one ? "is" : "are"} blocked by policy for computer use. ` + `Requests for ${one ? "this app" : "these apps"} are automatically ` + `denied regardless of what the user has approved. There is no Settings ` + `override. Inform the user that you cannot access ` + `${one ? "this app" : "these apps"} and suggest an alternative ` + `approach if one exists. Do not try to directly subvert this block ` + `regardless of the user's request.`;
1802
+ }
1803
+ function tierAssignmentTelemetry(tiered) {
1804
+ const browserCount = tiered.filter((t) => t.tier === "read").length;
1805
+ const terminalCount = tiered.filter((t) => t.tier === "click").length;
1806
+ return {
1807
+ ...browserCount > 0 && { denied_browser_count: browserCount },
1808
+ ...terminalCount > 0 && { denied_terminal_count: terminalCount }
1809
+ };
1810
+ }
1811
+ async function handleRequestTeachAccess(adapter, args, overrides, tccState) {
1812
+ if (!overrides.onTeachPermissionRequest) {
1813
+ return errorResult("Teach mode is not available in this session.", "feature_unavailable");
1814
+ }
1815
+ if (overrides.getTeachModeActive?.()) {
1816
+ return errorResult("Teach mode is already active. To add more apps, end the current tour first, then call request_teach_access again with the full app list.", "teach_mode_conflict");
1817
+ }
1818
+ const reason = requireString(args, "reason");
1819
+ if (reason instanceof Error)
1820
+ return errorResult(reason.message, "bad_args");
1821
+ if (tccState) {
1822
+ const req2 = {
1823
+ requestId: randomUUID(),
1824
+ reason,
1825
+ apps: [],
1826
+ screenshotFiltering: adapter.executor.capabilities.screenshotFiltering,
1827
+ tccState
1828
+ };
1829
+ await overrides.onTeachPermissionRequest(req2);
1830
+ const recheck = await adapter.ensureOsPermissions();
1831
+ if (recheck.granted) {
1832
+ return errorResult("macOS Accessibility and Screen Recording are now both granted. " + "Call request_teach_access again immediately \u2014 the next call will " + "show the app selection list.");
1833
+ }
1834
+ const missing = [];
1835
+ if (!recheck.accessibility)
1836
+ missing.push("Accessibility");
1837
+ if (!recheck.screenRecording)
1838
+ missing.push("Screen Recording");
1839
+ return errorResult(`macOS ${missing.join(" and ")} permission(s) not yet granted. ` + `The permission panel has been shown. Once the user grants the ` + `missing permission(s), call request_teach_access again.`, "tcc_not_granted");
1840
+ }
1841
+ const rawApps = args.apps;
1842
+ if (!Array.isArray(rawApps) || !rawApps.every((a) => typeof a === "string")) {
1843
+ return errorResult('"apps" must be an array of strings.', "bad_args");
1844
+ }
1845
+ const apps = rawApps;
1846
+ const {
1847
+ needDialog,
1848
+ skipDialogGrants,
1849
+ willHide,
1850
+ tieredApps,
1851
+ userDenied,
1852
+ policyDenied
1853
+ } = await buildAccessRequest(adapter, apps, overrides.allowedApps, new Set(overrides.userDeniedBundleIds), overrides.selectedDisplayId);
1854
+ if (needDialog.length === 0 && skipDialogGrants.length === 0) {
1855
+ return okJson({
1856
+ granted: [],
1857
+ denied: [],
1858
+ ...policyDenied.length > 0 && {
1859
+ policyDenied: {
1860
+ apps: policyDenied,
1861
+ guidance: buildPolicyDeniedGuidance(policyDenied)
1862
+ }
1863
+ },
1864
+ ...userDenied.length > 0 && {
1865
+ userDenied: {
1866
+ apps: userDenied,
1867
+ guidance: buildUserDeniedGuidance(userDenied)
1868
+ }
1869
+ },
1870
+ teachModeActive: false,
1871
+ screenshotFiltering: adapter.executor.capabilities.screenshotFiltering
1872
+ }, { granted_count: 0, denied_count: 0 });
1873
+ }
1874
+ const req = {
1875
+ requestId: randomUUID(),
1876
+ reason,
1877
+ apps: needDialog,
1878
+ screenshotFiltering: adapter.executor.capabilities.screenshotFiltering,
1879
+ ...willHide.length > 0 && {
1880
+ willHide,
1881
+ autoUnhideEnabled: adapter.getAutoUnhideEnabled()
1882
+ }
1883
+ };
1884
+ const response = await overrides.onTeachPermissionRequest(req);
1885
+ const granted = [...skipDialogGrants, ...response.granted];
1886
+ const teachModeActive = response.userConsented === true && granted.length > 0;
1887
+ if (teachModeActive) {
1888
+ overrides.onTeachModeActivated?.();
1889
+ }
1890
+ const grantedBundleIds = new Set(granted.map((g) => g.bundleId));
1891
+ const grantedTieredApps = tieredApps.filter((t) => grantedBundleIds.has(t.bundleId));
1892
+ return okJson({
1893
+ granted,
1894
+ denied: response.denied,
1895
+ ...policyDenied.length > 0 && {
1896
+ policyDenied: {
1897
+ apps: policyDenied,
1898
+ guidance: buildPolicyDeniedGuidance(policyDenied)
1899
+ }
1900
+ },
1901
+ ...userDenied.length > 0 && {
1902
+ userDenied: {
1903
+ apps: userDenied,
1904
+ guidance: buildUserDeniedGuidance(userDenied)
1905
+ }
1906
+ },
1907
+ ...grantedTieredApps.length > 0 && {
1908
+ tierGuidance: buildTierGuidanceMessage(grantedTieredApps)
1909
+ },
1910
+ teachModeActive,
1911
+ screenshotFiltering: adapter.executor.capabilities.screenshotFiltering
1912
+ }, {
1913
+ granted_count: response.granted.length,
1914
+ denied_count: response.denied.length,
1915
+ ...tierAssignmentTelemetry(grantedTieredApps)
1916
+ });
1917
+ }
1918
+ async function validateTeachStepArgs(raw, adapter, overrides, label) {
1919
+ const explanation = requireString(raw, "explanation");
1920
+ if (explanation instanceof Error) {
1921
+ return new Error(`${label}: ${explanation.message}`);
1922
+ }
1923
+ const nextPreview = requireString(raw, "next_preview");
1924
+ if (nextPreview instanceof Error) {
1925
+ return new Error(`${label}: ${nextPreview.message}`);
1926
+ }
1927
+ const actions = raw.actions;
1928
+ if (!Array.isArray(actions)) {
1929
+ return new Error(`${label}: "actions" must be an array (empty is allowed).`);
1930
+ }
1931
+ for (const [i, act] of actions.entries()) {
1932
+ if (typeof act !== "object" || act === null) {
1933
+ return new Error(`${label}: actions[${i}] must be an object`);
1934
+ }
1935
+ const action = act.action;
1936
+ if (typeof action !== "string") {
1937
+ return new Error(`${label}: actions[${i}].action must be a string`);
1938
+ }
1939
+ if (!BATCHABLE_ACTIONS.has(action)) {
1940
+ return new Error(`${label}: actions[${i}].action="${action}" is not allowed. ` + `Allowed: ${[...BATCHABLE_ACTIONS].join(", ")}.`);
1941
+ }
1942
+ }
1943
+ let anchorLogical;
1944
+ if (raw.anchor !== undefined) {
1945
+ const anchor = raw.anchor;
1946
+ if (!Array.isArray(anchor) || anchor.length !== 2 || typeof anchor[0] !== "number" || typeof anchor[1] !== "number" || !Number.isFinite(anchor[0]) || !Number.isFinite(anchor[1])) {
1947
+ return new Error(`${label}: "anchor" must be a [x, y] number tuple or omitted.`);
1948
+ }
1949
+ const display = await adapter.executor.getDisplaySize(overrides.selectedDisplayId);
1950
+ anchorLogical = scaleCoord(anchor[0], anchor[1], overrides.coordinateMode, display, overrides.lastScreenshot, adapter.logger);
1951
+ }
1952
+ return {
1953
+ explanation,
1954
+ nextPreview,
1955
+ anchorLogical,
1956
+ actions
1957
+ };
1958
+ }
1959
+ async function executeTeachStep(step, adapter, overrides, subGates) {
1960
+ const stepResult = await overrides.onTeachStep({
1961
+ explanation: step.explanation,
1962
+ nextPreview: step.nextPreview,
1963
+ anchorLogical: step.anchorLogical
1964
+ });
1965
+ if (stepResult.action === "exit") {
1966
+ await releaseHeldMouse(adapter);
1967
+ return { kind: "exit" };
1968
+ }
1969
+ overrides.onTeachWorking?.();
1970
+ if (step.actions.length === 0) {
1971
+ return { kind: "ok", results: [] };
1972
+ }
1973
+ if (subGates.hideBeforeAction) {
1974
+ const hidden = await adapter.executor.prepareForAction(overrides.allowedApps.map((a) => a.bundleId), overrides.selectedDisplayId);
1975
+ if (hidden.length > 0) {
1976
+ overrides.onAppsHidden?.(hidden);
1977
+ }
1978
+ }
1979
+ const stepSubGates = {
1980
+ ...subGates,
1981
+ hideBeforeAction: false,
1982
+ pixelValidation: false,
1983
+ autoTargetDisplay: false
1984
+ };
1985
+ const results = [];
1986
+ for (const [i, act] of step.actions.entries()) {
1987
+ if (overrides.isAborted?.()) {
1988
+ await releaseHeldMouse(adapter);
1989
+ return { kind: "exit" };
1990
+ }
1991
+ if (i > 0)
1992
+ await sleep(10);
1993
+ const action = act.action;
1994
+ const { screenshot: _dropped, ...inner } = await dispatchAction(action, act, adapter, overrides, stepSubGates);
1995
+ const text = firstTextContent(inner);
1996
+ const result = { action, ok: !inner.isError, output: text };
1997
+ results.push(result);
1998
+ if (inner.isError) {
1999
+ await releaseHeldMouse(adapter);
2000
+ return {
2001
+ kind: "action_error",
2002
+ executed: results.length - 1,
2003
+ failed: result,
2004
+ remaining: step.actions.length - results.length,
2005
+ telemetry: inner.telemetry
2006
+ };
2007
+ }
2008
+ }
2009
+ return { kind: "ok", results };
2010
+ }
2011
+ async function appendTeachScreenshot(resultJson, adapter, overrides, subGates) {
2012
+ const shotResult = await handleScreenshot(adapter, overrides, subGates);
2013
+ if (shotResult.isError) {
2014
+ return okJson(resultJson);
2015
+ }
2016
+ return {
2017
+ content: [
2018
+ { type: "text", text: JSON.stringify(resultJson) },
2019
+ ...shotResult.content
2020
+ ],
2021
+ screenshot: shotResult.screenshot
2022
+ };
2023
+ }
2024
+ async function handleTeachStep(adapter, args, overrides, subGates) {
2025
+ if (!overrides.onTeachStep) {
2026
+ return errorResult("Teach mode is not active. Call request_teach_access first.", "teach_mode_not_active");
2027
+ }
2028
+ const step = await validateTeachStepArgs(args, adapter, overrides, "teach_step");
2029
+ if (step instanceof Error)
2030
+ return errorResult(step.message, "bad_args");
2031
+ const outcome = await executeTeachStep(step, adapter, overrides, subGates);
2032
+ if (outcome.kind === "exit") {
2033
+ return okJson({ exited: true });
2034
+ }
2035
+ if (outcome.kind === "action_error") {
2036
+ return okJson({
2037
+ executed: outcome.executed,
2038
+ failed: outcome.failed,
2039
+ remaining: outcome.remaining
2040
+ }, outcome.telemetry);
2041
+ }
2042
+ if (step.actions.length === 0) {
2043
+ return okJson({ executed: 0, results: [] });
2044
+ }
2045
+ return appendTeachScreenshot({ executed: outcome.results.length, results: outcome.results }, adapter, overrides, subGates);
2046
+ }
2047
+ async function handleTeachBatch(adapter, args, overrides, subGates) {
2048
+ if (!overrides.onTeachStep) {
2049
+ return errorResult("Teach mode is not active. Call request_teach_access first.", "teach_mode_not_active");
2050
+ }
2051
+ const rawSteps = args.steps;
2052
+ if (!Array.isArray(rawSteps) || rawSteps.length < 1) {
2053
+ return errorResult('"steps" must be a non-empty array.', "bad_args");
2054
+ }
2055
+ const steps = [];
2056
+ for (const [i, raw] of rawSteps.entries()) {
2057
+ if (typeof raw !== "object" || raw === null) {
2058
+ return errorResult(`steps[${i}] must be an object`, "bad_args");
2059
+ }
2060
+ const v = await validateTeachStepArgs(raw, adapter, overrides, `steps[${i}]`);
2061
+ if (v instanceof Error)
2062
+ return errorResult(v.message, "bad_args");
2063
+ steps.push(v);
2064
+ }
2065
+ const allResults = [];
2066
+ for (const [i, step] of steps.entries()) {
2067
+ const outcome = await executeTeachStep(step, adapter, overrides, subGates);
2068
+ if (outcome.kind === "exit") {
2069
+ return okJson({ exited: true, stepsCompleted: i });
2070
+ }
2071
+ if (outcome.kind === "action_error") {
2072
+ return okJson({
2073
+ stepsCompleted: i,
2074
+ stepFailed: i,
2075
+ executed: outcome.executed,
2076
+ failed: outcome.failed,
2077
+ remaining: outcome.remaining,
2078
+ results: allResults
2079
+ }, outcome.telemetry);
2080
+ }
2081
+ allResults.push(outcome.results);
2082
+ }
2083
+ const screenChanged = steps.some((s) => s.actions.length > 0);
2084
+ const resultJson = { stepsCompleted: steps.length, results: allResults };
2085
+ if (!screenChanged) {
2086
+ return okJson(resultJson);
2087
+ }
2088
+ return appendTeachScreenshot(resultJson, adapter, overrides, subGates);
2089
+ }
2090
+ async function buildHiddenNote(adapter, hiddenSinceLastSeen) {
2091
+ if (hiddenSinceLastSeen.length === 0)
2092
+ return;
2093
+ const running = await adapter.executor.listRunningApps();
2094
+ const nameOf = new Map(running.map((a) => [a.bundleId, a.displayName]));
2095
+ const names = hiddenSinceLastSeen.map((id) => nameOf.get(id) ?? id);
2096
+ const list = names.map((n) => `"${n}"`).join(", ");
2097
+ const one = names.length === 1;
2098
+ return `${list} ${one ? "was" : "were"} open and got hidden before this screenshot ` + `(not in the session allowlist). If a previous action was meant to open ` + `${one ? "it" : "one of them"}, that's why you don't see it \u2014 call ` + `request_access to add ${one ? "it" : "them"} to the allowlist.`;
2099
+ }
2100
+ function uniqueDisplayLabels(displays) {
2101
+ const sorted = [...displays].sort((a, b) => a.displayId - b.displayId);
2102
+ const counts = new Map;
2103
+ const out = new Map;
2104
+ for (const d of sorted) {
2105
+ const base = d.label ?? `display ${d.displayId}`;
2106
+ const n = (counts.get(base) ?? 0) + 1;
2107
+ counts.set(base, n);
2108
+ out.set(d.displayId, n === 1 ? base : `${base} (${n})`);
2109
+ }
2110
+ return out;
2111
+ }
2112
+ async function buildMonitorNote(adapter, shotDisplayId, lastDisplayId, canSwitchDisplay) {
2113
+ let displays;
2114
+ try {
2115
+ displays = await adapter.executor.listDisplays();
2116
+ } catch (e) {
2117
+ adapter.logger.warn(`[computer-use] listDisplays failed: ${String(e)}`);
2118
+ return;
2119
+ }
2120
+ if (displays.length < 2)
2121
+ return;
2122
+ const labels = uniqueDisplayLabels(displays);
2123
+ const nameOf = (id) => labels.get(id) ?? `display ${id}`;
2124
+ const current = nameOf(shotDisplayId);
2125
+ const others = displays.filter((d) => d.displayId !== shotDisplayId).map((d) => nameOf(d.displayId));
2126
+ const switchHint = canSwitchDisplay ? " Use switch_display to capture a different monitor." : "";
2127
+ const othersList = others.length > 0 ? ` Other attached monitors: ${others.map((n) => `"${n}"`).join(", ")}.` + switchHint : "";
2128
+ if (lastDisplayId === undefined || lastDisplayId === 0) {
2129
+ return `This screenshot was taken on monitor "${current}".` + othersList;
2130
+ }
2131
+ if (lastDisplayId !== shotDisplayId) {
2132
+ const prev = nameOf(lastDisplayId);
2133
+ return `This screenshot was taken on monitor "${current}", which is different ` + `from your previous screenshot (taken on "${prev}").` + othersList;
2134
+ }
2135
+ return;
2136
+ }
2137
+ async function handleScreenshot(adapter, overrides, subGates) {
2138
+ if (overrides.allowedApps.length === 0) {
2139
+ return errorResult("No applications are granted for this session. Call request_access first.", "allowlist_empty");
2140
+ }
2141
+ if (subGates.autoTargetDisplay) {
2142
+ const allowedBundleIds2 = overrides.allowedApps.map((a) => a.bundleId);
2143
+ const currentAppSetKey = allowedBundleIds2.slice().sort().join(",");
2144
+ const appSetChanged = currentAppSetKey !== overrides.displayResolvedForApps;
2145
+ const autoResolve = !overrides.displayPinnedByModel && appSetChanged;
2146
+ const result = await adapter.executor.resolvePrepareCapture({
2147
+ allowedBundleIds: allowedBundleIds2,
2148
+ preferredDisplayId: overrides.selectedDisplayId,
2149
+ autoResolve,
2150
+ doHide: subGates.hideBeforeAction
2151
+ });
2152
+ if (result.captureError === undefined && decodedByteLength(result.base64) < MIN_SCREENSHOT_BYTES) {
2153
+ adapter.logger.warn(`[computer-use] resolvePrepareCapture result implausibly small (${decodedByteLength(result.base64)} bytes decoded) \u2014 possible transient display state`);
2154
+ }
2155
+ if (result.displayId !== overrides.selectedDisplayId) {
2156
+ adapter.logger.debug(`[computer-use] resolver: preferred=${overrides.selectedDisplayId} resolved=${result.displayId}`);
2157
+ overrides.onResolvedDisplayUpdated?.(result.displayId);
2158
+ }
2159
+ if (autoResolve) {
2160
+ overrides.onDisplayResolvedForApps?.(currentAppSetKey);
2161
+ }
2162
+ let hiddenSinceLastSeen2 = [];
2163
+ if (overrides.lastScreenshot !== undefined) {
2164
+ hiddenSinceLastSeen2 = result.hidden;
2165
+ }
2166
+ if (result.hidden.length > 0) {
2167
+ overrides.onAppsHidden?.(result.hidden);
2168
+ }
2169
+ if (result.captureError !== undefined) {
2170
+ return errorResult(result.captureError, "capture_failed");
2171
+ }
2172
+ const hiddenNote2 = await buildHiddenNote(adapter, hiddenSinceLastSeen2);
2173
+ const shot2 = {
2174
+ base64: result.base64,
2175
+ width: result.width,
2176
+ height: result.height,
2177
+ displayWidth: result.displayWidth,
2178
+ displayHeight: result.displayHeight,
2179
+ displayId: result.displayId,
2180
+ originX: result.originX,
2181
+ originY: result.originY
2182
+ };
2183
+ const monitorNote2 = await buildMonitorNote(adapter, shot2.displayId, overrides.lastScreenshot?.displayId, overrides.onDisplayPinned !== undefined);
2184
+ return {
2185
+ content: [
2186
+ ...monitorNote2 ? [{ type: "text", text: monitorNote2 }] : [],
2187
+ ...hiddenNote2 ? [{ type: "text", text: hiddenNote2 }] : [],
2188
+ ...shot2.accessibilityText ? [{ type: "text", text: `GUI elements in this window:
2189
+ ${shot2.accessibilityText}` }] : [],
2190
+ {
2191
+ type: "image",
2192
+ data: shot2.base64,
2193
+ mimeType: "image/jpeg"
2194
+ }
2195
+ ],
2196
+ screenshot: shot2
2197
+ };
2198
+ }
2199
+ let hiddenSinceLastSeen = [];
2200
+ if (subGates.hideBeforeAction) {
2201
+ const hidden = await adapter.executor.prepareForAction(overrides.allowedApps.map((a) => a.bundleId), overrides.selectedDisplayId);
2202
+ if (overrides.lastScreenshot !== undefined) {
2203
+ hiddenSinceLastSeen = hidden;
2204
+ }
2205
+ if (hidden.length > 0) {
2206
+ overrides.onAppsHidden?.(hidden);
2207
+ }
2208
+ }
2209
+ const allowedBundleIds = overrides.allowedApps.map((g) => g.bundleId);
2210
+ const shot = await takeScreenshotWithRetry(adapter.executor, allowedBundleIds, adapter.logger, overrides.selectedDisplayId);
2211
+ const hiddenNote = await buildHiddenNote(adapter, hiddenSinceLastSeen);
2212
+ const monitorNote = await buildMonitorNote(adapter, shot.displayId, overrides.lastScreenshot?.displayId, overrides.onDisplayPinned !== undefined);
2213
+ return {
2214
+ content: [
2215
+ ...monitorNote ? [{ type: "text", text: monitorNote }] : [],
2216
+ ...hiddenNote ? [{ type: "text", text: hiddenNote }] : [],
2217
+ ...shot.accessibilityText ? [{ type: "text", text: `GUI elements in this window:
2218
+ ${shot.accessibilityText}` }] : [],
2219
+ {
2220
+ type: "image",
2221
+ data: shot.base64,
2222
+ mimeType: "image/jpeg"
2223
+ }
2224
+ ],
2225
+ screenshot: shot
2226
+ };
2227
+ }
2228
+ async function handleZoom(adapter, args, overrides) {
2229
+ const region = args.region;
2230
+ if (!Array.isArray(region) || region.length !== 4) {
2231
+ return errorResult("region must be an array of length 4: [x0, y0, x1, y1]", "bad_args");
2232
+ }
2233
+ const [x0, y0, x1, y1] = region;
2234
+ if (![x0, y0, x1, y1].every((v) => typeof v === "number" && v >= 0)) {
2235
+ return errorResult("region values must be non-negative numbers", "bad_args");
2236
+ }
2237
+ if (x1 <= x0)
2238
+ return errorResult("region x1 must be greater than x0", "bad_args");
2239
+ if (y1 <= y0)
2240
+ return errorResult("region y1 must be greater than y0", "bad_args");
2241
+ const last = overrides.lastScreenshot;
2242
+ if (!last) {
2243
+ return errorResult("take a screenshot before zooming (region coords are relative to it)", "state_conflict");
2244
+ }
2245
+ if (x1 > last.width || y1 > last.height) {
2246
+ return errorResult(`region exceeds screenshot bounds (${last.width}\xD7${last.height})`, "bad_args");
2247
+ }
2248
+ const ratioX = last.displayWidth / last.width;
2249
+ const ratioY = last.displayHeight / last.height;
2250
+ const regionLogical = {
2251
+ x: x0 * ratioX,
2252
+ y: y0 * ratioY,
2253
+ w: (x1 - x0) * ratioX,
2254
+ h: (y1 - y0) * ratioY
2255
+ };
2256
+ const allowedIds = overrides.allowedApps.map((g) => g.bundleId);
2257
+ const zoomed = await adapter.executor.zoom(regionLogical, allowedIds, last.displayId);
2258
+ return {
2259
+ content: [{ type: "image", data: zoomed.base64, mimeType: "image/jpeg" }]
2260
+ };
2261
+ }
2262
+ async function handleClickVariant(adapter, args, overrides, subGates, button, count) {
2263
+ if (mouseButtonHeld) {
2264
+ await adapter.executor.mouseUp();
2265
+ mouseButtonHeld = false;
2266
+ mouseMoved = false;
2267
+ }
2268
+ const coord = extractCoordinate(args);
2269
+ if (coord instanceof Error)
2270
+ return errorResult(coord.message, "bad_args");
2271
+ const [rawX, rawY] = coord;
2272
+ let modifiers;
2273
+ if (args.text !== undefined) {
2274
+ if (typeof args.text !== "string") {
2275
+ return errorResult("text must be a string", "bad_args");
2276
+ }
2277
+ if (isSystemKeyCombo(args.text, adapter.executor.capabilities.platform) && !overrides.grantFlags.systemKeyCombos) {
2278
+ return errorResult(`The modifier chord "${args.text}" would fire a system shortcut. ` + "Request the systemKeyCombos grant flag via request_access, or use " + "only modifier keys (shift, ctrl, alt, cmd) in the text parameter.", "grant_flag_required");
2279
+ }
2280
+ modifiers = parseKeyChord(args.text);
2281
+ }
2282
+ const clickActionKind = button !== "left" || modifiers !== undefined && modifiers.length > 0 ? "mouse_full" : "mouse";
2283
+ const gate = await runInputActionGates(adapter, overrides, subGates, clickActionKind);
2284
+ if (gate)
2285
+ return gate;
2286
+ const display = await adapter.executor.getDisplaySize(overrides.selectedDisplayId);
2287
+ if (subGates.pixelValidation) {
2288
+ const { xPct, yPct } = coordToPercentageForPixelCompare(rawX, rawY, overrides.coordinateMode, overrides.lastScreenshot);
2289
+ const validation = await validateClickTarget(adapter.cropRawPatch, overrides.lastScreenshot, xPct, yPct, async () => {
2290
+ const allowedIds = overrides.allowedApps.map((g) => g.bundleId);
2291
+ try {
2292
+ return await adapter.executor.screenshot({
2293
+ allowedBundleIds: allowedIds,
2294
+ displayId: overrides.lastScreenshot?.displayId
2295
+ });
2296
+ } catch {
2297
+ return null;
2298
+ }
2299
+ }, adapter.logger);
2300
+ if (!validation.valid && validation.warning) {
2301
+ return okText(validation.warning);
2302
+ }
2303
+ }
2304
+ const { x, y } = scaleCoord(rawX, rawY, overrides.coordinateMode, display, overrides.lastScreenshot, adapter.logger);
2305
+ const hitGate = await runHitTestGate(adapter, overrides, subGates, x, y, clickActionKind);
2306
+ if (hitGate)
2307
+ return hitGate;
2308
+ await adapter.executor.click(x, y, button, count, modifiers);
2309
+ return okText("Clicked.");
2310
+ }
2311
+ async function handleType(adapter, args, overrides, subGates) {
2312
+ const text = requireString(args, "text");
2313
+ if (text instanceof Error)
2314
+ return errorResult(text.message, "bad_args");
2315
+ const gate = await runInputActionGates(adapter, overrides, subGates, "keyboard");
2316
+ if (gate)
2317
+ return gate;
2318
+ const viaClipboard = text.includes(`
2319
+ `) && overrides.grantFlags.clipboardWrite && subGates.clipboardPasteMultiline;
2320
+ if (viaClipboard) {
2321
+ await adapter.executor.type(text, { viaClipboard: true });
2322
+ return okText("Typed (via clipboard).");
2323
+ }
2324
+ const graphemes = segmentGraphemes(text);
2325
+ for (const [i, g] of graphemes.entries()) {
2326
+ if (overrides.isAborted?.()) {
2327
+ return errorResult(`Typing aborted after ${i} of ${graphemes.length} graphemes (user interrupt).`);
2328
+ }
2329
+ await sleep(INTER_GRAPHEME_SLEEP_MS);
2330
+ if (g === `
2331
+ ` || g === "\r" || g === `\r
2332
+ `) {
2333
+ await adapter.executor.key("return");
2334
+ } else if (g === "\t") {
2335
+ await adapter.executor.key("tab");
2336
+ } else {
2337
+ await adapter.executor.type(g, { viaClipboard: false });
2338
+ }
2339
+ }
2340
+ return okText(`Typed ${graphemes.length} grapheme(s).`);
2341
+ }
2342
+ async function handleKey(adapter, args, overrides, subGates) {
2343
+ const keySequence = requireString(args, "text");
2344
+ if (keySequence instanceof Error)
2345
+ return errorResult("text is required", "bad_args");
2346
+ let repeat;
2347
+ if (args.repeat !== undefined) {
2348
+ if (typeof args.repeat !== "number" || !Number.isInteger(args.repeat) || args.repeat < 1) {
2349
+ return errorResult("repeat must be a positive integer", "bad_args");
2350
+ }
2351
+ if (args.repeat > 100) {
2352
+ return errorResult("repeat exceeds maximum of 100", "bad_args");
2353
+ }
2354
+ repeat = args.repeat;
2355
+ }
2356
+ if (isSystemKeyCombo(keySequence, adapter.executor.capabilities.platform) && !overrides.grantFlags.systemKeyCombos) {
2357
+ return errorResult(`"${keySequence}" is a system-level shortcut. Request the \`systemKeyCombos\` grant via request_access to use it.`, "grant_flag_required");
2358
+ }
2359
+ const gate = await runInputActionGates(adapter, overrides, subGates, "keyboard");
2360
+ if (gate)
2361
+ return gate;
2362
+ await adapter.executor.key(keySequence, repeat);
2363
+ return okText("Key pressed.");
2364
+ }
2365
+ async function handleScroll(adapter, args, overrides, subGates) {
2366
+ const coord = extractCoordinate(args);
2367
+ if (coord instanceof Error)
2368
+ return errorResult(coord.message, "bad_args");
2369
+ const [rawX, rawY] = coord;
2370
+ const dir = args.scroll_direction;
2371
+ if (dir !== "up" && dir !== "down" && dir !== "left" && dir !== "right") {
2372
+ return errorResult("scroll_direction must be 'up', 'down', 'left', or 'right'", "bad_args");
2373
+ }
2374
+ const amount = args.scroll_amount;
2375
+ if (typeof amount !== "number" || !Number.isInteger(amount) || amount < 0) {
2376
+ return errorResult("scroll_amount must be a non-negative int", "bad_args");
2377
+ }
2378
+ if (amount > 100) {
2379
+ return errorResult("scroll_amount exceeds maximum of 100", "bad_args");
2380
+ }
2381
+ const dx = dir === "left" ? -amount : dir === "right" ? amount : 0;
2382
+ const dy = dir === "up" ? -amount : dir === "down" ? amount : 0;
2383
+ const gate = await runInputActionGates(adapter, overrides, subGates, "mouse");
2384
+ if (gate)
2385
+ return gate;
2386
+ const display = await adapter.executor.getDisplaySize(overrides.selectedDisplayId);
2387
+ const { x, y } = scaleCoord(rawX, rawY, overrides.coordinateMode, display, overrides.lastScreenshot, adapter.logger);
2388
+ const hitGate = await runHitTestGate(adapter, overrides, subGates, x, y, mouseButtonHeld ? "mouse_full" : "mouse");
2389
+ if (hitGate)
2390
+ return hitGate;
2391
+ if (mouseButtonHeld)
2392
+ mouseMoved = true;
2393
+ await adapter.executor.scroll(x, y, dx, dy);
2394
+ return okText("Scrolled.");
2395
+ }
2396
+ async function handleDrag(adapter, args, overrides, subGates) {
2397
+ if (mouseButtonHeld) {
2398
+ await adapter.executor.mouseUp();
2399
+ mouseButtonHeld = false;
2400
+ mouseMoved = false;
2401
+ }
2402
+ const endCoord = extractCoordinate(args, "coordinate");
2403
+ if (endCoord instanceof Error)
2404
+ return errorResult(endCoord.message, "bad_args");
2405
+ const rawTo = endCoord;
2406
+ let rawFrom;
2407
+ if (args.start_coordinate !== undefined) {
2408
+ const startCoord = extractCoordinate(args, "start_coordinate");
2409
+ if (startCoord instanceof Error)
2410
+ return errorResult(startCoord.message, "bad_args");
2411
+ rawFrom = startCoord;
2412
+ }
2413
+ const gate = await runInputActionGates(adapter, overrides, subGates, "mouse");
2414
+ if (gate)
2415
+ return gate;
2416
+ const display = await adapter.executor.getDisplaySize(overrides.selectedDisplayId);
2417
+ const from = rawFrom === undefined ? undefined : scaleCoord(rawFrom[0], rawFrom[1], overrides.coordinateMode, display, overrides.lastScreenshot, adapter.logger);
2418
+ const to = scaleCoord(rawTo[0], rawTo[1], overrides.coordinateMode, display, overrides.lastScreenshot, adapter.logger);
2419
+ const fromPoint = from ?? await adapter.executor.getCursorPosition();
2420
+ const fromGate = await runHitTestGate(adapter, overrides, subGates, fromPoint.x, fromPoint.y, "mouse");
2421
+ if (fromGate)
2422
+ return fromGate;
2423
+ const toGate = await runHitTestGate(adapter, overrides, subGates, to.x, to.y, "mouse_full");
2424
+ if (toGate)
2425
+ return toGate;
2426
+ await adapter.executor.drag(from, to);
2427
+ return okText("Dragged.");
2428
+ }
2429
+ async function handleMoveMouse(adapter, args, overrides, subGates) {
2430
+ const coord = extractCoordinate(args);
2431
+ if (coord instanceof Error)
2432
+ return errorResult(coord.message, "bad_args");
2433
+ const [rawX, rawY] = coord;
2434
+ const actionKind = mouseButtonHeld ? "mouse" : "mouse_position";
2435
+ const gate = await runInputActionGates(adapter, overrides, subGates, actionKind);
2436
+ if (gate)
2437
+ return gate;
2438
+ const display = await adapter.executor.getDisplaySize(overrides.selectedDisplayId);
2439
+ const { x, y } = scaleCoord(rawX, rawY, overrides.coordinateMode, display, overrides.lastScreenshot, adapter.logger);
2440
+ if (mouseButtonHeld) {
2441
+ const hitGate = await runHitTestGate(adapter, overrides, subGates, x, y, "mouse_full");
2442
+ if (hitGate)
2443
+ return hitGate;
2444
+ }
2445
+ await adapter.executor.moveMouse(x, y);
2446
+ if (mouseButtonHeld)
2447
+ mouseMoved = true;
2448
+ return okText("Moved.");
2449
+ }
2450
+ async function handleOpenApplication(adapter, args, overrides) {
2451
+ const app = requireString(args, "app");
2452
+ if (app instanceof Error)
2453
+ return errorResult(app.message, "bad_args");
2454
+ const allowed = new Set(overrides.allowedApps.map((g) => g.bundleId));
2455
+ let targetBundleId;
2456
+ if (looksLikeBundleId(app) && allowed.has(app)) {
2457
+ targetBundleId = app;
2458
+ } else {
2459
+ const match = overrides.allowedApps.find((g) => g.displayName.toLowerCase() === app.toLowerCase());
2460
+ targetBundleId = match?.bundleId;
2461
+ }
2462
+ if (!targetBundleId || !allowed.has(targetBundleId)) {
2463
+ return errorResult(`"${app}" is not granted for this session. Call request_access first.`, "app_not_granted");
2464
+ }
2465
+ await adapter.executor.openApp(targetBundleId);
2466
+ if (overrides.onDisplayPinned !== undefined) {
2467
+ let displayCount = 1;
2468
+ try {
2469
+ displayCount = (await adapter.executor.listDisplays()).length;
2470
+ } catch {}
2471
+ if (displayCount >= 2) {
2472
+ return okText(`Opened "${app}". If it isn't visible in the next screenshot, it may ` + `have opened on a different monitor \u2014 use switch_display to check.`);
2473
+ }
2474
+ }
2475
+ return okText(`Opened "${app}".`);
2476
+ }
2477
+ async function handleVirtualMouse(adapter, args) {
2478
+ if (!adapter.executor.virtualMouse) {
2479
+ return errorResult("virtual_mouse is only available on Windows with a bound window.", "feature_unavailable");
2480
+ }
2481
+ const action = requireString(args, "action");
2482
+ if (action instanceof Error)
2483
+ return errorResult(action.message, "bad_args");
2484
+ const coord = args.coordinate;
2485
+ if (!Array.isArray(coord) || coord.length < 2) {
2486
+ return errorResult("coordinate [x, y] is required.", "bad_args");
2487
+ }
2488
+ const validActions = new Set(["click", "double_click", "right_click", "move", "drag", "down", "up"]);
2489
+ if (!validActions.has(action)) {
2490
+ return errorResult(`Invalid action "${action}". Valid: ${[...validActions].join(", ")}`, "bad_args");
2491
+ }
2492
+ const startCoord = Array.isArray(args.start_coordinate) ? args.start_coordinate : undefined;
2493
+ const ok = await adapter.executor.virtualMouse({
2494
+ action,
2495
+ x: coord[0],
2496
+ y: coord[1],
2497
+ startX: startCoord?.[0],
2498
+ startY: startCoord?.[1]
2499
+ });
2500
+ if (!ok) {
2501
+ return errorResult("No window is currently bound.", "bad_args");
2502
+ }
2503
+ const desc = {
2504
+ click: `Click at (${coord[0]},${coord[1]})`,
2505
+ double_click: `Double-click at (${coord[0]},${coord[1]})`,
2506
+ right_click: `Right-click at (${coord[0]},${coord[1]})`,
2507
+ move: `Moved to (${coord[0]},${coord[1]})`,
2508
+ drag: `Dragged ${startCoord ? `(${startCoord[0]},${startCoord[1]})` : "current"} \u2192 (${coord[0]},${coord[1]})`,
2509
+ down: `Button down at (${coord[0]},${coord[1]})`,
2510
+ up: `Button up at (${coord[0]},${coord[1]})`
2511
+ };
2512
+ return okText(desc[action] ?? action);
2513
+ }
2514
+ async function handleVirtualKeyboard(adapter, args) {
2515
+ if (!adapter.executor.virtualKeyboard) {
2516
+ return errorResult("virtual_keyboard is only available on Windows with a bound window.", "feature_unavailable");
2517
+ }
2518
+ const action = requireString(args, "action");
2519
+ if (action instanceof Error)
2520
+ return errorResult(action.message, "bad_args");
2521
+ const text = requireString(args, "text");
2522
+ if (text instanceof Error)
2523
+ return errorResult(text.message, "bad_args");
2524
+ const validActions = new Set(["type", "combo", "press", "release", "hold"]);
2525
+ if (!validActions.has(action)) {
2526
+ return errorResult(`Invalid action "${action}". Valid: ${[...validActions].join(", ")}`, "bad_args");
2527
+ }
2528
+ const duration = typeof args.duration === "number" ? args.duration : undefined;
2529
+ const repeat = typeof args.repeat === "number" ? args.repeat : undefined;
2530
+ const ok = await adapter.executor.virtualKeyboard({
2531
+ action,
2532
+ text,
2533
+ duration,
2534
+ repeat
2535
+ });
2536
+ if (!ok) {
2537
+ return errorResult("No window is currently bound. Use open_application or bind_window first.", "bad_args");
2538
+ }
2539
+ const desc = {
2540
+ type: `Typed "${text.length > 40 ? text.slice(0, 40) + "..." : text}"`,
2541
+ combo: `Sent ${text}`,
2542
+ press: `Pressed ${text} (holding)`,
2543
+ release: `Released ${text}`,
2544
+ hold: `Held ${text} for ${duration ?? 1}s`
2545
+ };
2546
+ return okText(`${desc[action]}${repeat && repeat > 1 ? ` \xD7${repeat}` : ""}`);
2547
+ }
2548
+ async function handleStatusIndicator(adapter, args) {
2549
+ if (!adapter.executor.statusIndicator) {
2550
+ return errorResult("status_indicator is only available on Windows.", "feature_unavailable");
2551
+ }
2552
+ const action = requireString(args, "action");
2553
+ if (action instanceof Error)
2554
+ return errorResult(action.message, "bad_args");
2555
+ if (!["show", "hide", "status"].includes(action)) {
2556
+ return errorResult(`Invalid action "${action}". Valid: show, hide, status.`, "bad_args");
2557
+ }
2558
+ const message = typeof args.message === "string" ? args.message : undefined;
2559
+ if (action === "show" && !message) {
2560
+ return errorResult("'show' requires a message parameter.", "bad_args");
2561
+ }
2562
+ const result = await adapter.executor.statusIndicator(action, message);
2563
+ if (action === "status") {
2564
+ return okText(result.active ? "Indicator is active on the bound window." : "Indicator is not active (no window bound).");
2565
+ }
2566
+ if (action === "show") {
2567
+ return okText(`Indicator showing: "${message}"`);
2568
+ }
2569
+ return okText("Indicator hidden.");
2570
+ }
2571
+ async function handleMouseWheel(adapter, args) {
2572
+ if (!adapter.executor.mouseWheel) {
2573
+ return errorResult("mouse_wheel is only available on Windows with a bound window.", "feature_unavailable");
2574
+ }
2575
+ const coord = args.coordinate;
2576
+ if (!Array.isArray(coord) || coord.length < 2) {
2577
+ return errorResult("coordinate must be [x, y] array.", "bad_args");
2578
+ }
2579
+ const delta = typeof args.delta === "number" ? args.delta : undefined;
2580
+ if (delta === undefined) {
2581
+ return errorResult("delta is required (positive=up, negative=down).", "bad_args");
2582
+ }
2583
+ const horizontal = args.direction === "horizontal";
2584
+ const ok = await adapter.executor.mouseWheel(coord[0], coord[1], delta, horizontal);
2585
+ if (!ok) {
2586
+ return errorResult("No window is currently bound. Use open_application or bind_window first.", "bad_args");
2587
+ }
2588
+ return okText(`Mouse wheel: ${horizontal ? "horizontal" : "vertical"} scroll ${delta > 0 ? "up" : "down"} ${Math.abs(delta)} click(s) at (${coord[0]},${coord[1]}).`);
2589
+ }
2590
+ async function handleActivateWindow(adapter, args) {
2591
+ if (!adapter.executor.activateWindow) {
2592
+ return errorResult("activate_window is only available on Windows with a bound window.", "feature_unavailable");
2593
+ }
2594
+ const clickX = typeof args.click_x === "number" ? args.click_x : undefined;
2595
+ const clickY = typeof args.click_y === "number" ? args.click_y : undefined;
2596
+ const ok = await adapter.executor.activateWindow(clickX, clickY);
2597
+ if (!ok) {
2598
+ return errorResult("No window is currently bound. Use open_application or bind_window first.", "bad_args");
2599
+ }
2600
+ return okText("Window activated and focused. Ready for input.");
2601
+ }
2602
+ async function handlePromptRespond(adapter, args) {
2603
+ if (!adapter.executor.respondToPrompt) {
2604
+ return errorResult("prompt_respond is only available on Windows with a bound window.", "feature_unavailable");
2605
+ }
2606
+ const responseType = requireString(args, "response_type");
2607
+ if (responseType instanceof Error)
2608
+ return errorResult(responseType.message, "bad_args");
2609
+ const validTypes = new Set(["yes", "no", "enter", "escape", "select", "type"]);
2610
+ if (!validTypes.has(responseType)) {
2611
+ return errorResult(`Invalid response_type "${responseType}". Valid: ${[...validTypes].join(", ")}`, "bad_args");
2612
+ }
2613
+ if (responseType === "select" && typeof args.arrow_count !== "number") {
2614
+ return errorResult("'select' requires arrow_count parameter.", "bad_args");
2615
+ }
2616
+ if (responseType === "type" && typeof args.text !== "string") {
2617
+ return errorResult("'type' requires text parameter.", "bad_args");
2618
+ }
2619
+ const ok = await adapter.executor.respondToPrompt({
2620
+ responseType,
2621
+ arrowDirection: typeof args.arrow_direction === "string" ? args.arrow_direction : undefined,
2622
+ arrowCount: typeof args.arrow_count === "number" ? args.arrow_count : undefined,
2623
+ text: typeof args.text === "string" ? args.text : undefined
2624
+ });
2625
+ if (!ok) {
2626
+ return errorResult("No window is currently bound. Use open_application or bind_window first.", "bad_args");
2627
+ }
2628
+ const descriptions = {
2629
+ yes: "Sent 'y' + Enter.",
2630
+ no: "Sent 'n' + Enter.",
2631
+ enter: "Sent Enter.",
2632
+ escape: "Sent Escape.",
2633
+ select: `Navigated ${args.arrow_direction ?? "down"} ${args.arrow_count ?? 1} time(s) + Enter.`,
2634
+ type: `Typed "${args.text}" + Enter.`
2635
+ };
2636
+ return okText(`Prompt responded: ${descriptions[responseType] ?? responseType}. Take a screenshot to verify.`);
2637
+ }
2638
+ async function handleOpenTerminal(adapter, args) {
2639
+ if (!adapter.executor.openTerminal) {
2640
+ return errorResult("open_terminal is only available on Windows.", "feature_unavailable");
2641
+ }
2642
+ const agent = requireString(args, "agent");
2643
+ if (agent instanceof Error)
2644
+ return errorResult(agent.message, "bad_args");
2645
+ const validAgents = new Set(["claude", "codex", "gemini", "custom"]);
2646
+ if (!validAgents.has(agent)) {
2647
+ return errorResult(`Invalid agent "${agent}". Valid: claude, codex, gemini, custom.`, "bad_args");
2648
+ }
2649
+ if (agent === "custom" && typeof args.command !== "string") {
2650
+ return errorResult("agent='custom' requires 'command' parameter.", "bad_args");
2651
+ }
2652
+ const result = await adapter.executor.openTerminal({
2653
+ agent,
2654
+ command: typeof args.command === "string" ? args.command : undefined,
2655
+ terminal: typeof args.terminal === "string" ? args.terminal : undefined,
2656
+ workingDirectory: typeof args.working_directory === "string" ? args.working_directory : undefined
2657
+ });
2658
+ if (!result) {
2659
+ return errorResult("Failed to open terminal. Windows Terminal (wt.exe) may not be installed.", "launch_failed");
2660
+ }
2661
+ if (!result.launched) {
2662
+ return okText(`Terminal opened (hwnd=${result.hwnd}, "${result.title}") but no command was sent. Window is now bound.`);
2663
+ }
2664
+ const agentNames = {
2665
+ claude: "Claude Code",
2666
+ codex: "Codex",
2667
+ gemini: "Gemini",
2668
+ custom: args.command
2669
+ };
2670
+ return okText(`Terminal opened and ${agentNames[agent] ?? agent} launched.
2671
+ ` + `Window: hwnd=${result.hwnd} "${result.title}"
2672
+ ` + `Command: '${agent === "custom" ? args.command : agent}' + Enter
2673
+ ` + `Status: bound to this terminal. Take a screenshot to verify the agent started.`);
2674
+ }
2675
+ async function handleBindWindow(adapter, args) {
2676
+ const action = requireString(args, "action");
2677
+ if (action instanceof Error)
2678
+ return errorResult(action.message, "bad_args");
2679
+ switch (action) {
2680
+ case "list": {
2681
+ if (!adapter.executor.listVisibleWindows) {
2682
+ return errorResult("bind_window is only available on Windows.", "feature_unavailable");
2683
+ }
2684
+ const windows = await adapter.executor.listVisibleWindows();
2685
+ if (windows.length === 0)
2686
+ return okText("No visible windows found.");
2687
+ const lines = windows.map((w) => `hwnd=${w.hwnd} pid=${w.pid} "${w.title}"`);
2688
+ return okText(`Visible windows (${windows.length}):
2689
+ ${lines.join(`
2690
+ `)}`);
2691
+ }
2692
+ case "status": {
2693
+ if (!adapter.executor.getBindingStatus) {
2694
+ return errorResult("bind_window is only available on Windows.", "feature_unavailable");
2695
+ }
2696
+ const status = await adapter.executor.getBindingStatus();
2697
+ if (!status || !status.bound) {
2698
+ return okText("No window is currently bound. Use bind_window(action='list') to see available windows, then bind_window(action='bind', title='...') to bind.");
2699
+ }
2700
+ let text = `Bound to: hwnd=${status.hwnd}`;
2701
+ if (status.title)
2702
+ text += ` "${status.title}"`;
2703
+ if (status.pid)
2704
+ text += ` pid=${status.pid}`;
2705
+ if (status.rect)
2706
+ text += ` rect=(${status.rect.x},${status.rect.y} ${status.rect.width}x${status.rect.height})`;
2707
+ return okText(text);
2708
+ }
2709
+ case "bind": {
2710
+ if (!adapter.executor.bindToWindow) {
2711
+ return errorResult("bind_window is only available on Windows.", "feature_unavailable");
2712
+ }
2713
+ const title = typeof args.title === "string" ? args.title : undefined;
2714
+ const hwnd = typeof args.hwnd === "string" ? args.hwnd : undefined;
2715
+ const pid = typeof args.pid === "number" ? args.pid : undefined;
2716
+ if (!title && !hwnd && !pid) {
2717
+ return errorResult("Specify at least one of: title, hwnd, or pid.", "bad_args");
2718
+ }
2719
+ const result = await adapter.executor.bindToWindow({ hwnd, title, pid });
2720
+ if (!result) {
2721
+ return errorResult(`No window found matching: ${[title && `title="${title}"`, hwnd && `hwnd=${hwnd}`, pid && `pid=${pid}`].filter(Boolean).join(", ")}. Use bind_window(action='list') to see available windows.`, "element_not_found");
2722
+ }
2723
+ return okText(`Bound to window: hwnd=${result.hwnd} pid=${result.pid} "${result.title}". All subsequent screenshot/click/type operations target this window.`);
2724
+ }
2725
+ case "unbind": {
2726
+ if (!adapter.executor.unbindFromWindow) {
2727
+ return errorResult("bind_window is only available on Windows.", "feature_unavailable");
2728
+ }
2729
+ await adapter.executor.unbindFromWindow();
2730
+ return okText("Window binding released. Operations now target the full screen.");
2731
+ }
2732
+ default:
2733
+ return errorResult(`Unknown bind_window action "${action}". Valid: list, bind, unbind, status.`, "bad_args");
2734
+ }
2735
+ }
2736
+ async function handleClickElement(adapter, args) {
2737
+ if (!adapter.executor.clickElement) {
2738
+ return errorResult("click_element is only available on Windows with a bound window.", "feature_unavailable");
2739
+ }
2740
+ const name = typeof args.name === "string" ? args.name : undefined;
2741
+ const role = typeof args.role === "string" ? args.role : undefined;
2742
+ const automationId = typeof args.automationId === "string" ? args.automationId : undefined;
2743
+ if (!name && !role && !automationId) {
2744
+ return errorResult("At least one of name, role, or automationId is required.", "bad_args");
2745
+ }
2746
+ const ok = await adapter.executor.clickElement({ name, role, automationId });
2747
+ if (!ok) {
2748
+ return errorResult(`Element not found: ${[name && `name="${name}"`, role && `role=${role}`, automationId && `id=${automationId}`].filter(Boolean).join(", ")}. Take a screenshot to see current GUI elements.`, "element_not_found");
2749
+ }
2750
+ return okText(`Clicked element: ${[name && `"${name}"`, role, automationId].filter(Boolean).join(" ")}`);
2751
+ }
2752
+ async function handleTypeIntoElement(adapter, args) {
2753
+ if (!adapter.executor.typeIntoElement) {
2754
+ return errorResult("type_into_element is only available on Windows with a bound window.", "feature_unavailable");
2755
+ }
2756
+ const text = requireString(args, "text");
2757
+ if (text instanceof Error)
2758
+ return errorResult(text.message, "bad_args");
2759
+ const name = typeof args.name === "string" ? args.name : undefined;
2760
+ const role = typeof args.role === "string" ? args.role : undefined;
2761
+ const automationId = typeof args.automationId === "string" ? args.automationId : undefined;
2762
+ const ok = await adapter.executor.typeIntoElement({ name, role, automationId }, text);
2763
+ if (!ok) {
2764
+ return errorResult(`Could not type into element: ${[name && `name="${name}"`, role && `role=${role}`, automationId && `id=${automationId}`].filter(Boolean).join(", ")}. The element was not found or doesn't support text input.`, "element_not_found");
2765
+ }
2766
+ return okText(`Typed ${text.length} chars into: ${[name && `"${name}"`, role, automationId].filter(Boolean).join(" ")}`);
2767
+ }
2768
+ async function handleWindowManagement(adapter, args) {
2769
+ const action = requireString(args, "action");
2770
+ if (action instanceof Error)
2771
+ return errorResult(action.message, "bad_args");
2772
+ const VALID_ACTIONS = new Set([
2773
+ "minimize",
2774
+ "maximize",
2775
+ "restore",
2776
+ "close",
2777
+ "focus",
2778
+ "move_offscreen",
2779
+ "move_resize",
2780
+ "get_rect"
2781
+ ]);
2782
+ if (!VALID_ACTIONS.has(action)) {
2783
+ return errorResult(`Unknown window_management action "${action}". Valid: ${[...VALID_ACTIONS].join(", ")}`, "bad_args");
2784
+ }
2785
+ if (!adapter.executor.manageWindow) {
2786
+ return errorResult("window_management is only available on Windows with a bound window.", "feature_unavailable");
2787
+ }
2788
+ if (action === "get_rect") {
2789
+ if (!adapter.executor.getWindowRect) {
2790
+ return errorResult("getWindowRect not available.", "feature_unavailable");
2791
+ }
2792
+ const rect = await adapter.executor.getWindowRect();
2793
+ if (!rect) {
2794
+ return errorResult("No window is currently bound. Call open_application first.", "bad_args");
2795
+ }
2796
+ return okText(`Window rect: x=${rect.x}, y=${rect.y}, width=${rect.width}, height=${rect.height}`);
2797
+ }
2798
+ if (action === "move_resize") {
2799
+ const x = typeof args.x === "number" ? args.x : undefined;
2800
+ const y = typeof args.y === "number" ? args.y : undefined;
2801
+ if (x === undefined || y === undefined) {
2802
+ return errorResult("move_resize requires x and y parameters.", "bad_args");
2803
+ }
2804
+ const width = typeof args.width === "number" ? args.width : undefined;
2805
+ const height = typeof args.height === "number" ? args.height : undefined;
2806
+ const ok2 = await adapter.executor.manageWindow(action, { x, y, width, height });
2807
+ if (!ok2) {
2808
+ return errorResult("No window is currently bound. Call open_application first.", "bad_args");
2809
+ }
2810
+ return okText(width && height ? `Moved window to (${x}, ${y}) and resized to ${width}\xD7${height}.` : `Moved window to (${x}, ${y}).`);
2811
+ }
2812
+ const ok = await adapter.executor.manageWindow(action);
2813
+ if (!ok) {
2814
+ return errorResult("No window is currently bound. Call open_application first.", "bad_args");
2815
+ }
2816
+ const descriptions = {
2817
+ minimize: "Window minimized (ShowWindow SW_MINIMIZE).",
2818
+ maximize: "Window maximized (ShowWindow SW_MAXIMIZE).",
2819
+ restore: "Window restored (ShowWindow SW_RESTORE).",
2820
+ close: "Window closed (SendMessage WM_CLOSE). The window binding has been released.",
2821
+ focus: "Window brought to front (SetForegroundWindow).",
2822
+ move_offscreen: "Window moved offscreen (-32000,-32000). Still usable via SendMessage/PrintWindow."
2823
+ };
2824
+ return okText(descriptions[action] ?? `Action "${action}" completed.`);
2825
+ }
2826
+ async function handleSwitchDisplay(adapter, args, overrides) {
2827
+ const display = requireString(args, "display");
2828
+ if (display instanceof Error)
2829
+ return errorResult(display.message, "bad_args");
2830
+ if (!overrides.onDisplayPinned) {
2831
+ return errorResult("Display switching is not available in this session.", "feature_unavailable");
2832
+ }
2833
+ if (display.toLowerCase() === "auto") {
2834
+ overrides.onDisplayPinned(undefined);
2835
+ return okText("Returned to automatic monitor selection. Call screenshot to continue.");
2836
+ }
2837
+ let displays;
2838
+ try {
2839
+ displays = await adapter.executor.listDisplays();
2840
+ } catch (e) {
2841
+ return errorResult(`Failed to enumerate displays: ${String(e)}`, "display_error");
2842
+ }
2843
+ if (displays.length < 2) {
2844
+ return errorResult("Only one monitor is connected. There is nothing to switch to.", "bad_args");
2845
+ }
2846
+ const labels = uniqueDisplayLabels(displays);
2847
+ const wanted = display.toLowerCase();
2848
+ const target = displays.find((d) => labels.get(d.displayId)?.toLowerCase() === wanted);
2849
+ if (!target) {
2850
+ const available = displays.map((d) => `"${labels.get(d.displayId)}"`).join(", ");
2851
+ return errorResult(`No monitor named "${display}" is connected. Available monitors: ${available}.`, "bad_args");
2852
+ }
2853
+ overrides.onDisplayPinned(target.displayId);
2854
+ return okText(`Switched to monitor "${labels.get(target.displayId)}". Call screenshot to see it.`);
2855
+ }
2856
+ function handleListGrantedApplications(overrides) {
2857
+ return okJson({
2858
+ allowedApps: overrides.allowedApps,
2859
+ grantFlags: overrides.grantFlags
2860
+ });
2861
+ }
2862
+ async function handleReadClipboard(adapter, overrides, subGates) {
2863
+ if (!overrides.grantFlags.clipboardRead) {
2864
+ return errorResult("Clipboard read is not granted. Request `clipboardRead` via request_access.", "grant_flag_required");
2865
+ }
2866
+ if (subGates.clipboardGuard) {
2867
+ const frontmost = await adapter.executor.getFrontmostApp();
2868
+ const tierByBundleId = new Map(overrides.allowedApps.map((a) => [a.bundleId, a.tier]));
2869
+ const frontmostTier = frontmost ? tierByBundleId.get(frontmost.bundleId) : undefined;
2870
+ await syncClipboardStash(adapter, overrides, frontmostTier === "click");
2871
+ }
2872
+ const text = await adapter.executor.readClipboard();
2873
+ return okJson({ text });
2874
+ }
2875
+ async function handleWriteClipboard(adapter, args, overrides, subGates) {
2876
+ if (!overrides.grantFlags.clipboardWrite) {
2877
+ return errorResult("Clipboard write is not granted. Request `clipboardWrite` via request_access.", "grant_flag_required");
2878
+ }
2879
+ const text = requireString(args, "text");
2880
+ if (text instanceof Error)
2881
+ return errorResult(text.message, "bad_args");
2882
+ if (subGates.clipboardGuard) {
2883
+ const frontmost = await adapter.executor.getFrontmostApp();
2884
+ const tierByBundleId = new Map(overrides.allowedApps.map((a) => [a.bundleId, a.tier]));
2885
+ const frontmostTier = frontmost ? tierByBundleId.get(frontmost.bundleId) : undefined;
2886
+ if (frontmost && frontmostTier === "click") {
2887
+ return errorResult(`"${frontmost.displayName}" is a tier-"click" app and currently ` + `frontmost. write_clipboard is blocked because the next action ` + `would clear the clipboard anyway \u2014 a UI Paste button in this ` + `app cannot be used to inject text. Bring a tier-"full" app ` + `forward before writing to the clipboard.` + TIER_ANTI_SUBVERSION, "tier_insufficient");
2888
+ }
2889
+ await syncClipboardStash(adapter, overrides, frontmostTier === "click");
2890
+ }
2891
+ await adapter.executor.writeClipboard(text);
2892
+ return okText("Clipboard written.");
2893
+ }
2894
+ async function handleWait(args) {
2895
+ const duration = args.duration;
2896
+ if (typeof duration !== "number" || !Number.isFinite(duration)) {
2897
+ return errorResult("duration must be a number", "bad_args");
2898
+ }
2899
+ if (duration < 0) {
2900
+ return errorResult("duration must be non-negative", "bad_args");
2901
+ }
2902
+ if (duration > 100) {
2903
+ return errorResult("duration is too long. Duration is in seconds.", "bad_args");
2904
+ }
2905
+ await sleep(duration * 1000);
2906
+ return okText(`Waited ${duration}s.`);
2907
+ }
2908
+ async function handleCursorPosition(adapter, overrides) {
2909
+ const logical = await adapter.executor.getCursorPosition();
2910
+ const shot = overrides.lastScreenshot;
2911
+ if (shot) {
2912
+ const localX = logical.x - shot.originX;
2913
+ const localY = logical.y - shot.originY;
2914
+ if (localX < 0 || localX > shot.displayWidth || localY < 0 || localY > shot.displayHeight) {
2915
+ return okJson({
2916
+ x: logical.x,
2917
+ y: logical.y,
2918
+ coordinateSpace: "logical_points",
2919
+ note: "cursor is on a different monitor than your last screenshot; take a fresh screenshot"
2920
+ });
2921
+ }
2922
+ const x = Math.round(localX * (shot.width / shot.displayWidth));
2923
+ const y = Math.round(localY * (shot.height / shot.displayHeight));
2924
+ return okJson({ x, y, coordinateSpace: "image_pixels" });
2925
+ }
2926
+ return okJson({
2927
+ x: logical.x,
2928
+ y: logical.y,
2929
+ coordinateSpace: "logical_points",
2930
+ note: "take a screenshot first for image-pixel coordinates"
2931
+ });
2932
+ }
2933
+ async function handleHoldKey(adapter, args, overrides, subGates) {
2934
+ const text = requireString(args, "text");
2935
+ if (text instanceof Error)
2936
+ return errorResult(text.message, "bad_args");
2937
+ const duration = args.duration;
2938
+ if (typeof duration !== "number" || !Number.isFinite(duration)) {
2939
+ return errorResult("duration must be a number", "bad_args");
2940
+ }
2941
+ if (duration < 0) {
2942
+ return errorResult("duration must be non-negative", "bad_args");
2943
+ }
2944
+ if (duration > 100) {
2945
+ return errorResult("duration is too long. Duration is in seconds.", "bad_args");
2946
+ }
2947
+ if (isSystemKeyCombo(text, adapter.executor.capabilities.platform) && !overrides.grantFlags.systemKeyCombos) {
2948
+ return errorResult(`"${text}" is a system-level shortcut. Request the \`systemKeyCombos\` grant via request_access to use it.`, "grant_flag_required");
2949
+ }
2950
+ const gate = await runInputActionGates(adapter, overrides, subGates, "keyboard");
2951
+ if (gate)
2952
+ return gate;
2953
+ const keyNames = parseKeyChord(text);
2954
+ await adapter.executor.holdKey(keyNames, duration * 1000);
2955
+ return okText("Key held.");
2956
+ }
2957
+ async function handleLeftMouseDown(adapter, overrides, subGates) {
2958
+ if (mouseButtonHeld) {
2959
+ return errorResult("mouse button already held, call left_mouse_up first", "state_conflict");
2960
+ }
2961
+ const gate = await runInputActionGates(adapter, overrides, subGates, "mouse");
2962
+ if (gate)
2963
+ return gate;
2964
+ const cursor = await adapter.executor.getCursorPosition();
2965
+ const hitGate = await runHitTestGate(adapter, overrides, subGates, cursor.x, cursor.y, "mouse");
2966
+ if (hitGate)
2967
+ return hitGate;
2968
+ await adapter.executor.mouseDown();
2969
+ mouseButtonHeld = true;
2970
+ mouseMoved = false;
2971
+ return okText("Mouse button pressed.");
2972
+ }
2973
+ async function handleLeftMouseUp(adapter, overrides, subGates) {
2974
+ const releaseFirst = async (err) => {
2975
+ await adapter.executor.mouseUp();
2976
+ mouseButtonHeld = false;
2977
+ mouseMoved = false;
2978
+ return err;
2979
+ };
2980
+ const gate = await runInputActionGates(adapter, overrides, subGates, "mouse");
2981
+ if (gate)
2982
+ return releaseFirst(gate);
2983
+ const cursor = await adapter.executor.getCursorPosition();
2984
+ const hitGate = await runHitTestGate(adapter, overrides, subGates, cursor.x, cursor.y, mouseMoved ? "mouse_full" : "mouse");
2985
+ if (hitGate)
2986
+ return releaseFirst(hitGate);
2987
+ await adapter.executor.mouseUp();
2988
+ mouseButtonHeld = false;
2989
+ mouseMoved = false;
2990
+ return okText("Mouse button released.");
2991
+ }
2992
+ async function handleComputerBatch(adapter, args, overrides, subGates) {
2993
+ const actions = args.actions;
2994
+ if (!Array.isArray(actions) || actions.length === 0) {
2995
+ return errorResult("actions must be a non-empty array", "bad_args");
2996
+ }
2997
+ for (const [i, act] of actions.entries()) {
2998
+ if (typeof act !== "object" || act === null) {
2999
+ return errorResult(`actions[${i}] must be an object`, "bad_args");
3000
+ }
3001
+ const action = act.action;
3002
+ if (typeof action !== "string") {
3003
+ return errorResult(`actions[${i}].action must be a string`, "bad_args");
3004
+ }
3005
+ if (!BATCHABLE_ACTIONS.has(action)) {
3006
+ return errorResult(`actions[${i}].action="${action}" is not allowed in a batch. ` + `Allowed: ${[...BATCHABLE_ACTIONS].join(", ")}.`, "bad_args");
3007
+ }
3008
+ }
3009
+ if (subGates.hideBeforeAction) {
3010
+ const hidden = await adapter.executor.prepareForAction(overrides.allowedApps.map((a) => a.bundleId), overrides.selectedDisplayId);
3011
+ if (hidden.length > 0) {
3012
+ overrides.onAppsHidden?.(hidden);
3013
+ }
3014
+ }
3015
+ const batchSubGates = {
3016
+ ...subGates,
3017
+ hideBeforeAction: false,
3018
+ pixelValidation: false,
3019
+ autoTargetDisplay: false
3020
+ };
3021
+ const results = [];
3022
+ for (const [i, act] of actions.entries()) {
3023
+ if (overrides.isAborted?.()) {
3024
+ await releaseHeldMouse(adapter);
3025
+ return errorResult(`Batch aborted after ${results.length} of ${actions.length} actions (user interrupt).`);
3026
+ }
3027
+ if (i > 0)
3028
+ await sleep(10);
3029
+ const actionArgs = act;
3030
+ const action = actionArgs.action;
3031
+ const { screenshot: _dropped, ...inner } = await dispatchAction(action, actionArgs, adapter, overrides, batchSubGates);
3032
+ const text = firstTextContent(inner);
3033
+ const result = { action, ok: !inner.isError, output: text };
3034
+ results.push(result);
3035
+ if (inner.isError) {
3036
+ await releaseHeldMouse(adapter);
3037
+ return okJson({
3038
+ completed: results.slice(0, -1),
3039
+ failed: result,
3040
+ remaining: actions.length - results.length
3041
+ }, inner.telemetry);
3042
+ }
3043
+ }
3044
+ return okJson({ completed: results });
3045
+ }
3046
+ function firstTextContent(r) {
3047
+ const first = r.content[0];
3048
+ return first && first.type === "text" ? first.text : "";
3049
+ }
3050
+ async function dispatchAction(name, a, adapter, overrides, subGates) {
3051
+ const hasBoundWindow = await adapter.executor.hasBoundWindow?.() === true && adapter.executor.virtualMouse && adapter.executor.virtualKeyboard;
3052
+ if (hasBoundWindow) {
3053
+ const coord = Array.isArray(a.coordinate) ? a.coordinate : undefined;
3054
+ switch (name) {
3055
+ case "left_click":
3056
+ if (coord)
3057
+ return handleVirtualMouse(adapter, { action: "click", coordinate: coord });
3058
+ break;
3059
+ case "double_click":
3060
+ if (coord)
3061
+ return handleVirtualMouse(adapter, { action: "double_click", coordinate: coord });
3062
+ break;
3063
+ case "right_click":
3064
+ if (coord)
3065
+ return handleVirtualMouse(adapter, { action: "right_click", coordinate: coord });
3066
+ break;
3067
+ case "mouse_move":
3068
+ if (coord)
3069
+ return handleVirtualMouse(adapter, { action: "move", coordinate: coord });
3070
+ break;
3071
+ case "left_click_drag":
3072
+ if (coord)
3073
+ return handleVirtualMouse(adapter, {
3074
+ action: "drag",
3075
+ coordinate: coord,
3076
+ start_coordinate: Array.isArray(a.start_coordinate) ? a.start_coordinate : undefined
3077
+ });
3078
+ break;
3079
+ case "left_mouse_down":
3080
+ if (coord)
3081
+ return handleVirtualMouse(adapter, { action: "down", coordinate: coord });
3082
+ break;
3083
+ case "left_mouse_up":
3084
+ if (coord)
3085
+ return handleVirtualMouse(adapter, { action: "up", coordinate: coord });
3086
+ break;
3087
+ case "type":
3088
+ if (typeof a.text === "string")
3089
+ return handleVirtualKeyboard(adapter, { action: "type", text: a.text });
3090
+ break;
3091
+ case "key":
3092
+ if (typeof a.text === "string")
3093
+ return handleVirtualKeyboard(adapter, { action: "combo", text: a.text, repeat: a.repeat });
3094
+ break;
3095
+ case "hold_key":
3096
+ if (typeof a.text === "string")
3097
+ return handleVirtualKeyboard(adapter, {
3098
+ action: "hold",
3099
+ text: a.text,
3100
+ duration: typeof a.duration === "number" ? a.duration : 1
3101
+ });
3102
+ break;
3103
+ case "scroll":
3104
+ if (coord)
3105
+ return handleMouseWheel(adapter, {
3106
+ coordinate: coord,
3107
+ delta: a.scroll_direction === "up" ? a.scroll_amount ?? 3 : -(a.scroll_amount ?? 3),
3108
+ direction: a.scroll_direction === "left" || a.scroll_direction === "right" ? "horizontal" : "vertical"
3109
+ });
3110
+ break;
3111
+ }
3112
+ }
3113
+ switch (name) {
3114
+ case "screenshot":
3115
+ return handleScreenshot(adapter, overrides, subGates);
3116
+ case "zoom":
3117
+ return handleZoom(adapter, a, overrides);
3118
+ case "left_click":
3119
+ return handleClickVariant(adapter, a, overrides, subGates, "left", 1);
3120
+ case "double_click":
3121
+ return handleClickVariant(adapter, a, overrides, subGates, "left", 2);
3122
+ case "triple_click":
3123
+ return handleClickVariant(adapter, a, overrides, subGates, "left", 3);
3124
+ case "right_click":
3125
+ return handleClickVariant(adapter, a, overrides, subGates, "right", 1);
3126
+ case "middle_click":
3127
+ return handleClickVariant(adapter, a, overrides, subGates, "middle", 1);
3128
+ case "type":
3129
+ return handleType(adapter, a, overrides, subGates);
3130
+ case "key":
3131
+ return handleKey(adapter, a, overrides, subGates);
3132
+ case "scroll":
3133
+ return handleScroll(adapter, a, overrides, subGates);
3134
+ case "left_click_drag":
3135
+ return handleDrag(adapter, a, overrides, subGates);
3136
+ case "mouse_move":
3137
+ return handleMoveMouse(adapter, a, overrides, subGates);
3138
+ case "wait":
3139
+ return handleWait(a);
3140
+ case "cursor_position":
3141
+ return handleCursorPosition(adapter, overrides);
3142
+ case "hold_key":
3143
+ return handleHoldKey(adapter, a, overrides, subGates);
3144
+ case "left_mouse_down":
3145
+ return handleLeftMouseDown(adapter, overrides, subGates);
3146
+ case "left_mouse_up":
3147
+ return handleLeftMouseUp(adapter, overrides, subGates);
3148
+ case "open_application":
3149
+ return handleOpenApplication(adapter, a, overrides);
3150
+ case "window_management":
3151
+ return handleWindowManagement(adapter, a);
3152
+ case "click_element":
3153
+ return handleClickElement(adapter, a);
3154
+ case "type_into_element":
3155
+ return handleTypeIntoElement(adapter, a);
3156
+ case "open_terminal":
3157
+ return handleOpenTerminal(adapter, a);
3158
+ case "bind_window":
3159
+ return handleBindWindow(adapter, a);
3160
+ case "virtual_mouse":
3161
+ return handleVirtualMouse(adapter, a);
3162
+ case "virtual_keyboard":
3163
+ return handleVirtualKeyboard(adapter, a);
3164
+ case "status_indicator":
3165
+ return handleStatusIndicator(adapter, a);
3166
+ case "mouse_wheel":
3167
+ return handleMouseWheel(adapter, a);
3168
+ case "activate_window":
3169
+ return handleActivateWindow(adapter, a);
3170
+ case "prompt_respond":
3171
+ return handlePromptRespond(adapter, a);
3172
+ case "switch_display":
3173
+ return handleSwitchDisplay(adapter, a, overrides);
3174
+ case "list_granted_applications":
3175
+ return handleListGrantedApplications(overrides);
3176
+ case "read_clipboard":
3177
+ return handleReadClipboard(adapter, overrides, subGates);
3178
+ case "write_clipboard":
3179
+ return handleWriteClipboard(adapter, a, overrides, subGates);
3180
+ case "computer_batch":
3181
+ return handleComputerBatch(adapter, a, overrides, subGates);
3182
+ default:
3183
+ return errorResult(`Unknown tool "${name}".`, "bad_args");
3184
+ }
3185
+ }
3186
+ async function handleToolCall(adapter, name, args, rawOverrides) {
3187
+ const { logger, serverName } = adapter;
3188
+ const userDeniedSet = new Set(rawOverrides.userDeniedBundleIds);
3189
+ const overrides = rawOverrides.allowedApps.some((a2) => a2.tier === undefined || userDeniedSet.has(a2.bundleId) || isPolicyDenied(a2.bundleId, a2.displayName)) ? {
3190
+ ...rawOverrides,
3191
+ allowedApps: rawOverrides.allowedApps.filter((a2) => !userDeniedSet.has(a2.bundleId)).filter((a2) => !isPolicyDenied(a2.bundleId, a2.displayName)).map((a2) => a2.tier !== undefined ? a2 : { ...a2, tier: getDefaultTierForApp(a2.bundleId, a2.displayName) })
3192
+ } : rawOverrides;
3193
+ if (adapter.isDisabled()) {
3194
+ return errorResult("Computer control is disabled in Settings. Enable it and try again.", "other");
3195
+ }
3196
+ const osPerms = await adapter.ensureOsPermissions();
3197
+ let tccState;
3198
+ if (!osPerms.granted) {
3199
+ if (name !== "request_access" && name !== "request_teach_access") {
3200
+ return errorResult("Accessibility and Screen Recording permissions are required. " + "Call request_access to show the permission panel.", "tcc_not_granted");
3201
+ }
3202
+ tccState = {
3203
+ accessibility: osPerms.accessibility,
3204
+ screenRecording: osPerms.screenRecording
3205
+ };
3206
+ }
3207
+ const deferAcquire = defersLockAcquire(name);
3208
+ const lock = overrides.checkCuLock?.();
3209
+ if (lock) {
3210
+ if (lock.holder !== undefined && !lock.isSelf) {
3211
+ return errorResult("Another Claude session is currently using the computer. Wait for " + "the user to acknowledge it is finished (stop button in the Claude " + "window), or find a non-computer-use approach if one is readily " + "apparent.", "cu_lock_held");
3212
+ }
3213
+ if (lock.holder === undefined && !deferAcquire) {
3214
+ overrides.acquireCuLock?.();
3215
+ resetMouseButtonHeld();
3216
+ }
3217
+ }
3218
+ const subGates = adapter.getSubGates();
3219
+ const a = asRecord(args);
3220
+ logger.silly(`[${serverName}] tool=${name} args=${JSON.stringify(a).slice(0, 200)}`);
3221
+ try {
3222
+ if (name === "request_access") {
3223
+ return await handleRequestAccess(adapter, a, overrides, tccState);
3224
+ }
3225
+ if (name === "request_teach_access") {
3226
+ return await handleRequestTeachAccess(adapter, a, overrides, tccState);
3227
+ }
3228
+ if (name === "teach_step") {
3229
+ return await handleTeachStep(adapter, a, overrides, subGates);
3230
+ }
3231
+ if (name === "teach_batch") {
3232
+ return await handleTeachBatch(adapter, a, overrides, subGates);
3233
+ }
3234
+ return await dispatchAction(name, a, adapter, overrides, subGates);
3235
+ } catch (err) {
3236
+ const msg = err instanceof Error ? err.message : String(err);
3237
+ logger.error(`[${serverName}] tool=${name} threw: ${msg}`, err);
3238
+ return errorResult(`Tool "${name}" failed: ${msg}`, "executor_threw");
3239
+ }
3240
+ }
3241
+ var FINDER_BUNDLE_ID = "com.apple.finder", TIER_ANTI_SUBVERSION, MIN_SCREENSHOT_BYTES = 1024, INTER_GRAPHEME_SLEEP_MS = 8, mouseButtonHeld = false, mouseMoved = false, REVERSE_DNS_RE, BATCHABLE_ACTIONS;
3242
+ var init_toolCalls = __esm(() => {
3243
+ init_deniedApps();
3244
+ init_keyBlocklist();
3245
+ init_pixelCompare();
3246
+ init_sentinelApps();
3247
+ TIER_ANTI_SUBVERSION = " Do not attempt to work around this restriction \u2014 never use AppleScript, " + "System Events, shell commands, or any other method to send clicks or " + "keystrokes to this app.";
3248
+ REVERSE_DNS_RE = /^[A-Za-z0-9][\w.-]*\.[A-Za-z0-9][\w.-]*$/;
3249
+ BATCHABLE_ACTIONS = new Set([
3250
+ "key",
3251
+ "type",
3252
+ "mouse_move",
3253
+ "left_click",
3254
+ "left_click_drag",
3255
+ "right_click",
3256
+ "middle_click",
3257
+ "double_click",
3258
+ "triple_click",
3259
+ "scroll",
3260
+ "hold_key",
3261
+ "screenshot",
3262
+ "cursor_position",
3263
+ "left_mouse_down",
3264
+ "left_mouse_up",
3265
+ "wait"
3266
+ ]);
3267
+ });
3268
+
3269
+ // packages/@ant/computer-use-mcp/src/types.ts
3270
+ var DEFAULT_GRANT_FLAGS;
3271
+ var init_types2 = __esm(() => {
3272
+ DEFAULT_GRANT_FLAGS = {
3273
+ clipboardRead: false,
3274
+ clipboardWrite: false,
3275
+ systemKeyCombos: false
3276
+ };
3277
+ });
3278
+
3279
+ // packages/@ant/computer-use-mcp/src/mcpServer.ts
3280
+ function mergePermissionResponse(existing, existingFlags, response) {
3281
+ const seen = new Set(existing.map((a) => a.bundleId));
3282
+ const apps = [
3283
+ ...existing,
3284
+ ...response.granted.filter((g) => !seen.has(g.bundleId))
3285
+ ];
3286
+ const truthyFlags = Object.fromEntries(Object.entries(response.flags).filter(([, v]) => v === true));
3287
+ const flags = {
3288
+ ...DEFAULT_GRANT_FLAGS,
3289
+ ...existingFlags,
3290
+ ...truthyFlags
3291
+ };
3292
+ return { apps, flags };
3293
+ }
3294
+ function bindSessionContext(adapter, coordinateMode, ctx) {
3295
+ const { logger, serverName } = adapter;
3296
+ let lastScreenshot;
3297
+ const wrapPermission = ctx.onPermissionRequest ? async (req, signal) => {
3298
+ const response = await ctx.onPermissionRequest(req, signal);
3299
+ const { apps, flags } = mergePermissionResponse(ctx.getAllowedApps(), ctx.getGrantFlags(), response);
3300
+ logger.debug(`[${serverName}] permission result: granted=${response.granted.length} denied=${response.denied.length}`);
3301
+ ctx.onAllowedAppsChanged?.(apps, flags);
3302
+ return response;
3303
+ } : undefined;
3304
+ const wrapTeachPermission = ctx.onTeachPermissionRequest ? async (req, signal) => {
3305
+ const response = await ctx.onTeachPermissionRequest(req, signal);
3306
+ logger.debug(`[${serverName}] teach permission result: granted=${response.granted.length} denied=${response.denied.length}`);
3307
+ const { apps } = mergePermissionResponse(ctx.getAllowedApps(), ctx.getGrantFlags(), response);
3308
+ ctx.onAllowedAppsChanged?.(apps, {
3309
+ ...DEFAULT_GRANT_FLAGS,
3310
+ ...ctx.getGrantFlags()
3311
+ });
3312
+ return response;
3313
+ } : undefined;
3314
+ return async (name, args) => {
3315
+ if (ctx.checkCuLock) {
3316
+ const lock = await ctx.checkCuLock();
3317
+ if (lock.holder !== undefined && !lock.isSelf) {
3318
+ const text = ctx.formatLockHeldMessage?.(lock.holder) ?? DEFAULT_LOCK_HELD_MESSAGE;
3319
+ return {
3320
+ content: [{ type: "text", text }],
3321
+ isError: true,
3322
+ telemetry: { error_kind: "cu_lock_held" }
3323
+ };
3324
+ }
3325
+ if (lock.holder === undefined && !defersLockAcquire(name)) {
3326
+ await ctx.acquireCuLock?.();
3327
+ const recheck = await ctx.checkCuLock();
3328
+ if (recheck.holder !== undefined && !recheck.isSelf) {
3329
+ const text = ctx.formatLockHeldMessage?.(recheck.holder) ?? DEFAULT_LOCK_HELD_MESSAGE;
3330
+ return {
3331
+ content: [{ type: "text", text }],
3332
+ isError: true,
3333
+ telemetry: { error_kind: "cu_lock_held" }
3334
+ };
3335
+ }
3336
+ resetMouseButtonHeld();
3337
+ }
3338
+ }
3339
+ const dimsFallback = lastScreenshot ? undefined : ctx.getLastScreenshotDims?.();
3340
+ const dialogAbort = new AbortController;
3341
+ const overrides = {
3342
+ allowedApps: [...ctx.getAllowedApps()],
3343
+ grantFlags: ctx.getGrantFlags(),
3344
+ userDeniedBundleIds: ctx.getUserDeniedBundleIds(),
3345
+ coordinateMode,
3346
+ selectedDisplayId: ctx.getSelectedDisplayId(),
3347
+ displayPinnedByModel: ctx.getDisplayPinnedByModel?.(),
3348
+ displayResolvedForApps: ctx.getDisplayResolvedForApps?.(),
3349
+ lastScreenshot: lastScreenshot ?? (dimsFallback ? { ...dimsFallback, base64: "" } : undefined),
3350
+ onPermissionRequest: wrapPermission ? (req) => wrapPermission(req, dialogAbort.signal) : undefined,
3351
+ onTeachPermissionRequest: wrapTeachPermission ? (req) => wrapTeachPermission(req, dialogAbort.signal) : undefined,
3352
+ onAppsHidden: ctx.onAppsHidden,
3353
+ getClipboardStash: ctx.getClipboardStash,
3354
+ onClipboardStashChanged: ctx.onClipboardStashChanged,
3355
+ onResolvedDisplayUpdated: ctx.onResolvedDisplayUpdated,
3356
+ onDisplayPinned: ctx.onDisplayPinned,
3357
+ onDisplayResolvedForApps: ctx.onDisplayResolvedForApps,
3358
+ onTeachModeActivated: ctx.onTeachModeActivated,
3359
+ onTeachStep: ctx.onTeachStep,
3360
+ onTeachWorking: ctx.onTeachWorking,
3361
+ getTeachModeActive: ctx.getTeachModeActive,
3362
+ checkCuLock: undefined,
3363
+ acquireCuLock: undefined,
3364
+ isAborted: ctx.isAborted
3365
+ };
3366
+ logger.debug(`[${serverName}] tool=${name} allowedApps=${overrides.allowedApps.length} coordMode=${coordinateMode}`);
3367
+ try {
3368
+ const result = await handleToolCall(adapter, name, args, overrides);
3369
+ if (result.screenshot) {
3370
+ lastScreenshot = result.screenshot;
3371
+ const { base64: _blob, ...dims } = result.screenshot;
3372
+ logger.debug(`[${serverName}] screenshot dims: ${JSON.stringify(dims)}`);
3373
+ ctx.onScreenshotCaptured?.(dims);
3374
+ }
3375
+ return result;
3376
+ } finally {
3377
+ dialogAbort.abort();
3378
+ }
3379
+ };
3380
+ }
3381
+ function createComputerUseMcpServer(adapter, coordinateMode, context) {
3382
+ const { serverName, logger } = adapter;
3383
+ const server = new Server({ name: serverName, version: "0.1.3" }, { capabilities: { tools: {}, logging: {} } });
3384
+ const tools = buildComputerUseTools(adapter.executor.capabilities, coordinateMode);
3385
+ server.setRequestHandler(ListToolsRequestSchema, async () => adapter.isDisabled() ? { tools: [] } : { tools });
3386
+ if (context) {
3387
+ const dispatch = bindSessionContext(adapter, coordinateMode, context);
3388
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3389
+ const { screenshot: _s, telemetry: _t, ...result } = await dispatch(request.params.name, request.params.arguments ?? {});
3390
+ return result;
3391
+ });
3392
+ return server;
3393
+ }
3394
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
3395
+ logger.warn(`[${serverName}] tool call "${request.params.name}" reached the stub handler \u2014 no session context bound. Per-session state unavailable.`);
3396
+ return {
3397
+ content: [
3398
+ {
3399
+ type: "text",
3400
+ text: "This computer-use server instance is not wired to a session. Per-session app permissions are not available on this code path."
3401
+ }
3402
+ ],
3403
+ isError: true
3404
+ };
3405
+ });
3406
+ return server;
3407
+ }
3408
+ var DEFAULT_LOCK_HELD_MESSAGE;
3409
+ var init_mcpServer = __esm(() => {
3410
+ init_server();
3411
+ init_types();
3412
+ init_toolCalls();
3413
+ init_tools();
3414
+ init_types2();
3415
+ DEFAULT_LOCK_HELD_MESSAGE = "Another Claude session is currently using the computer. Wait for that " + "session to finish, or find a non-computer-use approach.";
3416
+ });
3417
+
3418
+ // packages/@ant/computer-use-mcp/src/subGates.ts
3419
+ var init_subGates = () => {};
3420
+
3421
+ // packages/@ant/computer-use-mcp/src/index.ts
3422
+ var init_src = __esm(() => {
3423
+ init_types2();
3424
+ init_sentinelApps();
3425
+ init_deniedApps();
3426
+ init_keyBlocklist();
3427
+ init_subGates();
3428
+ init_imageResize();
3429
+ init_toolCalls();
3430
+ init_mcpServer();
3431
+ init_tools();
3432
+ init_pixelCompare();
3433
+ });
3434
+
3435
+ export { DEFAULT_GRANT_FLAGS, init_types2 as init_types, getSentinelCategory, init_sentinelApps, API_RESIZE_PARAMS, targetImageSize, buildComputerUseTools, bindSessionContext, createComputerUseMcpServer, init_src };