openmausbot 0.1.55

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 (499) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +14 -0
  3. package/cli.js +2 -0
  4. package/dist/app-icon.svg +29 -0
  5. package/dist/assets/abap-BdImnpbu.js +1 -0
  6. package/dist/assets/actionscript-3-B3316cI-.js +1 -0
  7. package/dist/assets/ada-bCR0ucgS.js +1 -0
  8. package/dist/assets/ahk-CsyLZFj1.js +1 -0
  9. package/dist/assets/ahk2-8Zs4aa1G.js +1 -0
  10. package/dist/assets/andromeeda-C4gqWexZ.js +1 -0
  11. package/dist/assets/angular-html-DA-rfuFy.js +1 -0
  12. package/dist/assets/angular-ts-BrjP3tb8.js +1 -0
  13. package/dist/assets/apache-Pmp26Uib.js +1 -0
  14. package/dist/assets/apex-DhZFqWV2.js +1 -0
  15. package/dist/assets/apl-CORt7UWP.js +1 -0
  16. package/dist/assets/applescript-Co6uUVPk.js +1 -0
  17. package/dist/assets/ara-BRHolxvo.js +1 -0
  18. package/dist/assets/asciidoc-CSVQ5wI8.js +1 -0
  19. package/dist/assets/asm-D_Q5rh1f.js +1 -0
  20. package/dist/assets/astro-HNnZUWAn.js +1 -0
  21. package/dist/assets/aurora-x-D-2ljcwZ.js +1 -0
  22. package/dist/assets/awk-DMzUqQB5.js +1 -0
  23. package/dist/assets/ayu-dark-DYE7WIF3.js +1 -0
  24. package/dist/assets/ayu-light-BA47KaF1.js +1 -0
  25. package/dist/assets/ayu-mirage-32ctXXKs.js +1 -0
  26. package/dist/assets/ballerina-BFfxhgS-.js +1 -0
  27. package/dist/assets/bat-CickPsom.js +1 -0
  28. package/dist/assets/beancount-k_qm7-4y.js +1 -0
  29. package/dist/assets/berry-uYugtg8r.js +1 -0
  30. package/dist/assets/bibtex-CHM0blh-.js +1 -0
  31. package/dist/assets/bicep-Bmn6On1c.js +1 -0
  32. package/dist/assets/bird2-Bx8U0n9b.js +1 -0
  33. package/dist/assets/blade-2xfisSek.js +1 -0
  34. package/dist/assets/bsl-DlhNcFeZ.js +1 -0
  35. package/dist/assets/c-BIGW1oBm.js +1 -0
  36. package/dist/assets/c3-Dp5svz6Z.js +1 -0
  37. package/dist/assets/cadence-Bv_4Rxtq.js +1 -0
  38. package/dist/assets/cairo-KRGpt6FW.js +1 -0
  39. package/dist/assets/catppuccin-frappe-CZL1YF0i.js +1 -0
  40. package/dist/assets/catppuccin-latte-DH-8KZSZ.js +1 -0
  41. package/dist/assets/catppuccin-macchiato-B7yYVSCf.js +1 -0
  42. package/dist/assets/catppuccin-mocha-Ct7hS0mc.js +1 -0
  43. package/dist/assets/chapel-DTp_pixX.js +1 -0
  44. package/dist/assets/clarity-Dn5IMItf.js +1 -0
  45. package/dist/assets/clojure-P80f7IUj.js +1 -0
  46. package/dist/assets/cmake-D1j8_8rp.js +1 -0
  47. package/dist/assets/cobol-nBiQ_Alo.js +1 -0
  48. package/dist/assets/codeowners-Bp6g37R7.js +1 -0
  49. package/dist/assets/codeql-DsOJ9woJ.js +1 -0
  50. package/dist/assets/coffee-Ch7k5sss.js +1 -0
  51. package/dist/assets/common-lisp-Cg-RD9OK.js +1 -0
  52. package/dist/assets/coq-C7JzOVbR.js +1 -0
  53. package/dist/assets/cpp-BMRokrvK.js +1 -0
  54. package/dist/assets/crystal-DGywbUpC.js +1 -0
  55. package/dist/assets/csharp-DSvCPggb.js +1 -0
  56. package/dist/assets/css-CLj8gQPS.js +1 -0
  57. package/dist/assets/csv-fuZLfV_i.js +1 -0
  58. package/dist/assets/cue-D82EKSYY.js +1 -0
  59. package/dist/assets/cypher-COkxafJQ.js +1 -0
  60. package/dist/assets/d-85-TOEBH.js +1 -0
  61. package/dist/assets/dark-plus-C3mMm8J8.js +1 -0
  62. package/dist/assets/dart-bE4Kk8sk.js +1 -0
  63. package/dist/assets/dax-CEL-wOlO.js +1 -0
  64. package/dist/assets/desktop-BmXAJ9_W.js +1 -0
  65. package/dist/assets/diff-D97Zzqfu.js +1 -0
  66. package/dist/assets/docker-BcOcwvcX.js +1 -0
  67. package/dist/assets/dotenv-Da5cRb03.js +1 -0
  68. package/dist/assets/dracula-BzJJZx-M.js +1 -0
  69. package/dist/assets/dracula-soft-BXkSAIEj.js +1 -0
  70. package/dist/assets/dream-maker-BtqSS_iP.js +1 -0
  71. package/dist/assets/edge-FbVlp4U3.js +1 -0
  72. package/dist/assets/elixir-CkH2-t6x.js +1 -0
  73. package/dist/assets/elm-DbKCFpqz.js +1 -0
  74. package/dist/assets/emacs-lisp-C_m_b--Z.js +1 -0
  75. package/dist/assets/erb-DXfck5VN.js +1 -0
  76. package/dist/assets/erlang-DsQrWhSR.js +1 -0
  77. package/dist/assets/everforest-dark-BgDCqdQA.js +1 -0
  78. package/dist/assets/everforest-light-C8M2exoo.js +1 -0
  79. package/dist/assets/fennel-BYunw83y.js +1 -0
  80. package/dist/assets/fish-BvzEVeQv.js +1 -0
  81. package/dist/assets/fluent-C4IJs8-o.js +1 -0
  82. package/dist/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
  83. package/dist/assets/fortran-free-form-BxgE0vQu.js +1 -0
  84. package/dist/assets/fsharp-CXgrBDvD.js +1 -0
  85. package/dist/assets/gdresource-TyuKm33G.js +1 -0
  86. package/dist/assets/gdscript-DqcFQ5yU.js +1 -0
  87. package/dist/assets/gdshader-DkwncUOv.js +1 -0
  88. package/dist/assets/genie-D0YGMca9.js +1 -0
  89. package/dist/assets/gherkin-DyxjwDmM.js +1 -0
  90. package/dist/assets/git-commit-F4YmCXRG.js +1 -0
  91. package/dist/assets/git-rebase-r7XF79zn.js +1 -0
  92. package/dist/assets/github-dark-DHJKELXO.js +1 -0
  93. package/dist/assets/github-dark-default-Cuk6v7N8.js +1 -0
  94. package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
  95. package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
  96. package/dist/assets/github-light-DAi9KRSo.js +1 -0
  97. package/dist/assets/github-light-default-D7oLnXFd.js +1 -0
  98. package/dist/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
  99. package/dist/assets/gleam-BspZqrRM.js +1 -0
  100. package/dist/assets/glimmer-js-ByusRIyA.js +1 -0
  101. package/dist/assets/glimmer-ts-BfAWNZQY.js +1 -0
  102. package/dist/assets/glsl-DplSGwfg.js +1 -0
  103. package/dist/assets/gn-n2N0HUVH.js +1 -0
  104. package/dist/assets/gnuplot-DdkO51Og.js +1 -0
  105. package/dist/assets/go-C27-OAKa.js +1 -0
  106. package/dist/assets/graphql-ChdNCCLP.js +1 -0
  107. package/dist/assets/groovy-gcz8RCvz.js +1 -0
  108. package/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
  109. package/dist/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
  110. package/dist/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
  111. package/dist/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
  112. package/dist/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
  113. package/dist/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
  114. package/dist/assets/hack-BWmVpMyf.js +1 -0
  115. package/dist/assets/haml-D5jkg6IW.js +1 -0
  116. package/dist/assets/handlebars-BpdQsYii.js +1 -0
  117. package/dist/assets/haskell-Df6bDoY_.js +1 -0
  118. package/dist/assets/haxe-CfZj7gIn.js +1 -0
  119. package/dist/assets/hcl-BWvSN4gD.js +1 -0
  120. package/dist/assets/hjson-D5-asLiD.js +1 -0
  121. package/dist/assets/hlsl-D3lLCCz7.js +1 -0
  122. package/dist/assets/horizon-BUw7H-hv.js +1 -0
  123. package/dist/assets/horizon-bright-CUuTKBJd.js +1 -0
  124. package/dist/assets/houston-DnULxvSX.js +1 -0
  125. package/dist/assets/html-derivative-DlHx6ybY.js +1 -0
  126. package/dist/assets/html-pp8916En.js +1 -0
  127. package/dist/assets/http-jrhK8wxY.js +1 -0
  128. package/dist/assets/hurl-irOxFIW8.js +1 -0
  129. package/dist/assets/hxml-2-FPmUDs.js +1 -0
  130. package/dist/assets/hy-DFXneXwc.js +1 -0
  131. package/dist/assets/imba-DGztddWO.js +1 -0
  132. package/dist/assets/index-B9rLIY81.js +263 -0
  133. package/dist/assets/index-CJBrtDbC.css +1 -0
  134. package/dist/assets/index-D-u0LYsV.js +153 -0
  135. package/dist/assets/ini-BEwlwnbL.js +1 -0
  136. package/dist/assets/java-CylS5w8V.js +1 -0
  137. package/dist/assets/javascript-wDzz0qaB.js +1 -0
  138. package/dist/assets/jinja-f2NsQr07.js +1 -0
  139. package/dist/assets/jison-wvAkD_A8.js +1 -0
  140. package/dist/assets/json-Cp-IABpG.js +1 -0
  141. package/dist/assets/json5-C9tS-k6U.js +1 -0
  142. package/dist/assets/jsonc-Des-eS-w.js +1 -0
  143. package/dist/assets/jsonl-DcaNXYhu.js +1 -0
  144. package/dist/assets/jsonnet-DFQXde-d.js +1 -0
  145. package/dist/assets/jssm-C2t-YnRu.js +1 -0
  146. package/dist/assets/jsx-g9-lgVsj.js +1 -0
  147. package/dist/assets/julia-5Bft2YPA.js +1 -0
  148. package/dist/assets/just-Cwhn7H3k.js +1 -0
  149. package/dist/assets/kanagawa-dragon-BuwD2xS4.js +1 -0
  150. package/dist/assets/kanagawa-lotus-C3DzagqV.js +1 -0
  151. package/dist/assets/kanagawa-wave-DFGoQZhC.js +1 -0
  152. package/dist/assets/kdl-DV7GczEv.js +1 -0
  153. package/dist/assets/kotlin-BdnUsdx6.js +1 -0
  154. package/dist/assets/kusto-wEQ09or8.js +1 -0
  155. package/dist/assets/laserwave-DUszq2jm.js +1 -0
  156. package/dist/assets/latex-D5pSuvFb.js +1 -0
  157. package/dist/assets/lean-BZvkOJ9d.js +1 -0
  158. package/dist/assets/less-B1dDrJ26.js +1 -0
  159. package/dist/assets/light-plus-B7mTdjB0.js +1 -0
  160. package/dist/assets/liquid-C0sCDyMI.js +1 -0
  161. package/dist/assets/llvm-BZoOZj88.js +1 -0
  162. package/dist/assets/log-2UxHyX5q.js +1 -0
  163. package/dist/assets/logo-BtOb2qkB.js +1 -0
  164. package/dist/assets/lua-BaeVxFsk.js +1 -0
  165. package/dist/assets/luau-BnpPk5vE.js +1 -0
  166. package/dist/assets/make-CHLpvVh8.js +1 -0
  167. package/dist/assets/markdown-Cvjx9yec.js +1 -0
  168. package/dist/assets/marko-DjSrsDqO.js +1 -0
  169. package/dist/assets/material-theme-D5KoaKCx.js +1 -0
  170. package/dist/assets/material-theme-darker-BfHTSMKl.js +1 -0
  171. package/dist/assets/material-theme-lighter-B0m2ddpp.js +1 -0
  172. package/dist/assets/material-theme-ocean-CyktbL80.js +1 -0
  173. package/dist/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
  174. package/dist/assets/matlab-D7o27uSR.js +1 -0
  175. package/dist/assets/mdc-D1_yUvq7.js +1 -0
  176. package/dist/assets/mdx-Cmh6b_Ma.js +1 -0
  177. package/dist/assets/mermaid-CQcHuHx7.js +1 -0
  178. package/dist/assets/min-dark-CafNBF8u.js +1 -0
  179. package/dist/assets/min-light-CTRr51gU.js +1 -0
  180. package/dist/assets/mipsasm-CKIfxQSi.js +1 -0
  181. package/dist/assets/mojo-DJz3ZmWd.js +1 -0
  182. package/dist/assets/monokai-BRVnQi9A.js +1 -0
  183. package/dist/assets/moonbit-CHtswR0a.js +1 -0
  184. package/dist/assets/move-el3G9tDJ.js +1 -0
  185. package/dist/assets/narrat-DRg8JJMk.js +1 -0
  186. package/dist/assets/nextflow-C-mBbutL.js +1 -0
  187. package/dist/assets/nextflow-groovy-vE_lwT2v.js +1 -0
  188. package/dist/assets/nginx-BpAMiNFr.js +1 -0
  189. package/dist/assets/night-owl-C39BiMTA.js +1 -0
  190. package/dist/assets/night-owl-light-CMTm3GFP.js +1 -0
  191. package/dist/assets/nim-BIad80T-.js +1 -0
  192. package/dist/assets/nix-CwoSXNpI.js +1 -0
  193. package/dist/assets/nord-Ddv68eIx.js +1 -0
  194. package/dist/assets/nsis-BlV79W_Q.js +1 -0
  195. package/dist/assets/nushell-D3jzshHO.js +1 -0
  196. package/dist/assets/objective-c-DXmwc3jG.js +1 -0
  197. package/dist/assets/objective-cpp-CLxacb5B.js +1 -0
  198. package/dist/assets/ocaml-C0hk2d4L.js +1 -0
  199. package/dist/assets/odin-BBf5iR-q.js +1 -0
  200. package/dist/assets/one-dark-pro-DVMEJ2y_.js +1 -0
  201. package/dist/assets/one-light-C3Wv6jpd.js +1 -0
  202. package/dist/assets/openscad-C4EeE6gA.js +1 -0
  203. package/dist/assets/org-DM6o9KBp.js +1 -0
  204. package/dist/assets/pascal-D93ZcfNL.js +1 -0
  205. package/dist/assets/perl-B9cMNwum.js +1 -0
  206. package/dist/assets/php-Csjmro_R.js +1 -0
  207. package/dist/assets/pkl-u5AG7uiY.js +1 -0
  208. package/dist/assets/plastic-3e1v2bzS.js +1 -0
  209. package/dist/assets/plsql-ChMvpjG-.js +1 -0
  210. package/dist/assets/po-BTJTHyun.js +1 -0
  211. package/dist/assets/poimandres-CS3Unz2-.js +1 -0
  212. package/dist/assets/polar-C0HS_06l.js +1 -0
  213. package/dist/assets/postcss-CXtECtnM.js +1 -0
  214. package/dist/assets/powerquery-CEu0bR-o.js +1 -0
  215. package/dist/assets/powershell-BmBUJMz7.js +1 -0
  216. package/dist/assets/prisma-Vru482bI.js +1 -0
  217. package/dist/assets/prolog-CbFg5uaA.js +1 -0
  218. package/dist/assets/proto-C7zT0LnQ.js +1 -0
  219. package/dist/assets/pug-DKIMFp6K.js +1 -0
  220. package/dist/assets/puppet-BMWR74SV.js +1 -0
  221. package/dist/assets/purescript-CklMAg4u.js +1 -0
  222. package/dist/assets/python-B6aJPvgy.js +1 -0
  223. package/dist/assets/qml-3beO22l8.js +1 -0
  224. package/dist/assets/qmldir-C8lEn-DE.js +1 -0
  225. package/dist/assets/qss-IeuSbFQv.js +1 -0
  226. package/dist/assets/r-Cf5RLm7j.js +1 -0
  227. package/dist/assets/racket-BqYA7rlc.js +1 -0
  228. package/dist/assets/raku-DXvB9xmW.js +1 -0
  229. package/dist/assets/razor-BjBPvh-w.js +1 -0
  230. package/dist/assets/rbs-CpoqiR4B.js +1 -0
  231. package/dist/assets/red-hvxz__6c.js +1 -0
  232. package/dist/assets/reg-C-SQnVFl.js +1 -0
  233. package/dist/assets/regexp-CDVJQ6XC.js +1 -0
  234. package/dist/assets/rel-C3B-1QV4.js +1 -0
  235. package/dist/assets/riscv-BM1_JUlF.js +1 -0
  236. package/dist/assets/ron-D8l8udqQ.js +1 -0
  237. package/dist/assets/rose-pine-5qJOZa0Y.js +1 -0
  238. package/dist/assets/rose-pine-dawn-zx0QlTCp.js +1 -0
  239. package/dist/assets/rose-pine-moon-C9pEdX9L.js +1 -0
  240. package/dist/assets/rosmsg-BJDFO7_C.js +1 -0
  241. package/dist/assets/rst-bs7f0vWN.js +1 -0
  242. package/dist/assets/ruby-C0TQ7zu5.js +1 -0
  243. package/dist/assets/rust-B1yitclQ.js +1 -0
  244. package/dist/assets/sas-DEy46yEz.js +1 -0
  245. package/dist/assets/sass-Cj5Yp3dK.js +1 -0
  246. package/dist/assets/scala-CqE71os6.js +1 -0
  247. package/dist/assets/scheme-C98Dy4si.js +1 -0
  248. package/dist/assets/scss-D5BDwBP9.js +1 -0
  249. package/dist/assets/sdbl-DVxCFoDh.js +1 -0
  250. package/dist/assets/shaderlab-Dg9Lc6iA.js +1 -0
  251. package/dist/assets/shellscript-Yzrsuije.js +1 -0
  252. package/dist/assets/shellsession-BADoaaVG.js +1 -0
  253. package/dist/assets/slack-dark-BthQWCQV.js +1 -0
  254. package/dist/assets/slack-ochin-DqwNpetd.js +1 -0
  255. package/dist/assets/smalltalk-BOQMe2GC.js +1 -0
  256. package/dist/assets/smithy-cds9vsN8.js +1 -0
  257. package/dist/assets/snazzy-light-Bw305WKR.js +1 -0
  258. package/dist/assets/solarized-dark-CpvCGNkr.js +1 -0
  259. package/dist/assets/solarized-light-Dlz6yCKv.js +1 -0
  260. package/dist/assets/solidity-DijEV5ha.js +1 -0
  261. package/dist/assets/soy-8wufbnw4.js +1 -0
  262. package/dist/assets/sparql-rVzFXLq3.js +1 -0
  263. package/dist/assets/splunk-BtCnVYZw.js +1 -0
  264. package/dist/assets/sql-CRqJ_cUM.js +1 -0
  265. package/dist/assets/ssh-config-_ykCGR6B.js +1 -0
  266. package/dist/assets/stata-DI20mbqo.js +1 -0
  267. package/dist/assets/stylus-BEDo0Tqx.js +1 -0
  268. package/dist/assets/surrealql-Cjom0U5J.js +1 -0
  269. package/dist/assets/svelte-Cy7k_4gC.js +1 -0
  270. package/dist/assets/swift-C2oV4EkX.js +1 -0
  271. package/dist/assets/synthwave-84-CbfX1IO0.js +1 -0
  272. package/dist/assets/system-verilog-0hqHdDBg.js +1 -0
  273. package/dist/assets/systemd-4A_iFExJ.js +1 -0
  274. package/dist/assets/talonscript-CkByrt1z.js +1 -0
  275. package/dist/assets/tasl-QIJgUcNo.js +1 -0
  276. package/dist/assets/tcl-dwOrl1Do.js +1 -0
  277. package/dist/assets/templ-DhtptRzy.js +1 -0
  278. package/dist/assets/terraform-BETggiCN.js +1 -0
  279. package/dist/assets/tex-D96PA37w.js +1 -0
  280. package/dist/assets/tokyo-night-hegEt444.js +1 -0
  281. package/dist/assets/toml-vGWfd6FD.js +1 -0
  282. package/dist/assets/ts-tags-D351s5mN.js +1 -0
  283. package/dist/assets/tsv-B_m7g4N7.js +1 -0
  284. package/dist/assets/tsx-COt5Ahok.js +1 -0
  285. package/dist/assets/turtle-BsS91CYL.js +1 -0
  286. package/dist/assets/twig-27uCiNez.js +1 -0
  287. package/dist/assets/typescript-BPQ3VLAy.js +1 -0
  288. package/dist/assets/typespec-CAFt9gP4.js +1 -0
  289. package/dist/assets/typst-BUadGCkm.js +1 -0
  290. package/dist/assets/v-BGw2Nkan.js +1 -0
  291. package/dist/assets/vala-CsfeWuGM.js +1 -0
  292. package/dist/assets/vb-Cu-pLBUe.js +1 -0
  293. package/dist/assets/verilog-nZwndyjY.js +1 -0
  294. package/dist/assets/vesper-DRje8inN.js +1 -0
  295. package/dist/assets/vhdl-CeAyd5Ju.js +1 -0
  296. package/dist/assets/viml-CJc9bBzg.js +1 -0
  297. package/dist/assets/vitesse-black-Bkuqu6BP.js +1 -0
  298. package/dist/assets/vitesse-dark-D0r3Knsf.js +1 -0
  299. package/dist/assets/vitesse-light-CVO1_9PV.js +1 -0
  300. package/dist/assets/vue-BqiEGhQt.js +1 -0
  301. package/dist/assets/vue-html-AaS7Mt5G.js +1 -0
  302. package/dist/assets/vue-vine-BoDAl6tE.js +1 -0
  303. package/dist/assets/vyper-CDx5xZoG.js +1 -0
  304. package/dist/assets/wasm-CG6Dc4jp.js +1 -0
  305. package/dist/assets/wasm-MzD3tlZU.js +1 -0
  306. package/dist/assets/wenyan-BV7otONQ.js +1 -0
  307. package/dist/assets/wgsl-Dx-B1_4e.js +1 -0
  308. package/dist/assets/wikitext-BhOHFoWU.js +1 -0
  309. package/dist/assets/wit-5i3qLPDT.js +1 -0
  310. package/dist/assets/wolfram-lXgVvXCa.js +1 -0
  311. package/dist/assets/xml-sdJ4AIDG.js +1 -0
  312. package/dist/assets/xsl-CtQFsRM5.js +1 -0
  313. package/dist/assets/yaml-Buea-lGh.js +1 -0
  314. package/dist/assets/zenscript-DVFEvuxE.js +1 -0
  315. package/dist/assets/zig-VOosw3JB.js +1 -0
  316. package/dist/index.html +14 -0
  317. package/dist-server/companion/src/listener.js +187 -0
  318. package/dist-server/computer-proxy.js +1185 -0
  319. package/dist-server/connector-proxy.js +186 -0
  320. package/dist-server/container-mcp.js +15186 -0
  321. package/dist-server/drivers/agents-proxy.js +887 -0
  322. package/dist-server/drivers/browser-proxy.js +15037 -0
  323. package/dist-server/drivers/dweb-proxy.js +175 -0
  324. package/dist-server/drivers/phone-proxy.js +339 -0
  325. package/dist-server/drivers/pi-mcp-extension.ts +638 -0
  326. package/dist-server/index.js +64869 -0
  327. package/dist-server/local-computer.js +198 -0
  328. package/dist-server/mcp-server.js +1233 -0
  329. package/dist-server/openmausbot.js +3671 -0
  330. package/dist-server/pair-cli.js +3671 -0
  331. package/dist-server/permission-proxy.js +126 -0
  332. package/dist-server/prepare-cloudflared.js +253 -0
  333. package/dist-server/proxy-paths.js +29 -0
  334. package/dist-server/server/atomic.js +40 -0
  335. package/dist-server/server/attachments.js +471 -0
  336. package/dist-server/server/auto-approve.js +162 -0
  337. package/dist-server/server/auto-review.js +79 -0
  338. package/dist-server/server/avatar-image.js +144 -0
  339. package/dist-server/server/bot-cwd.js +29 -0
  340. package/dist-server/server/bot-directory.js +127 -0
  341. package/dist-server/server/bot-package.js +268 -0
  342. package/dist-server/server/bot-profile.js +76 -0
  343. package/dist-server/server/box-create-idempotency.js +463 -0
  344. package/dist-server/server/box.js +944 -0
  345. package/dist-server/server/brand.js +65 -0
  346. package/dist-server/server/browser-connection.js +187 -0
  347. package/dist-server/server/browser-lifecycle-cleanup.js +359 -0
  348. package/dist-server/server/calendar-calls.js +314 -0
  349. package/dist-server/server/channel-queue.js +70 -0
  350. package/dist-server/server/checkpoints.js +405 -0
  351. package/dist-server/server/chief-of-staff.js +49 -0
  352. package/dist-server/server/claude-update.js +70 -0
  353. package/dist-server/server/cli.js +524 -0
  354. package/dist-server/server/cloud-backend.js +30 -0
  355. package/dist-server/server/comms-visibility.js +109 -0
  356. package/dist-server/server/composio.js +945 -0
  357. package/dist-server/server/computer-control.js +149 -0
  358. package/dist-server/server/computer-observation.js +133 -0
  359. package/dist-server/server/computer-proxy.js +1061 -0
  360. package/dist-server/server/config.js +760 -0
  361. package/dist-server/server/connector-proxy.js +228 -0
  362. package/dist-server/server/container-computer.js +840 -0
  363. package/dist-server/server/container-mcp.js +27 -0
  364. package/dist-server/server/contracts.js +24 -0
  365. package/dist-server/server/control-client.js +100 -0
  366. package/dist-server/server/data-dir-lease.js +3 -0
  367. package/dist-server/server/decision-log.js +106 -0
  368. package/dist-server/server/delegations.js +628 -0
  369. package/dist-server/server/drivers/acp/core.js +904 -0
  370. package/dist-server/server/drivers/acp/cursor.js +365 -0
  371. package/dist-server/server/drivers/acp/custom.js +51 -0
  372. package/dist-server/server/drivers/acp/droid.js +225 -0
  373. package/dist-server/server/drivers/acp/gemini.js +95 -0
  374. package/dist-server/server/drivers/acp/grok.js +249 -0
  375. package/dist-server/server/drivers/acp/hermes.js +429 -0
  376. package/dist-server/server/drivers/acp/kimi.js +559 -0
  377. package/dist-server/server/drivers/acp/opencode-go.js +370 -0
  378. package/dist-server/server/drivers/acp/qwen.js +98 -0
  379. package/dist-server/server/drivers/agents-proxy.js +941 -0
  380. package/dist-server/server/drivers/antigravity-acp.js +507 -0
  381. package/dist-server/server/drivers/antigravity-release.js +65 -0
  382. package/dist-server/server/drivers/antigravity-runtime.js +395 -0
  383. package/dist-server/server/drivers/antigravity.js +144 -0
  384. package/dist-server/server/drivers/boxagent.js +245 -0
  385. package/dist-server/server/drivers/browser-proxy.js +520 -0
  386. package/dist-server/server/drivers/builtIn.js +36 -0
  387. package/dist-server/server/drivers/claude.js +1337 -0
  388. package/dist-server/server/drivers/codex-catalog.js +409 -0
  389. package/dist-server/server/drivers/codex.js +1116 -0
  390. package/dist-server/server/drivers/dweb-proxy.js +193 -0
  391. package/dist-server/server/drivers/grok.js +48 -0
  392. package/dist-server/server/drivers/grokagent.js +4 -0
  393. package/dist-server/server/drivers/local-inject.js +388 -0
  394. package/dist-server/server/drivers/minimax.js +108 -0
  395. package/dist-server/server/drivers/native.js +21 -0
  396. package/dist-server/server/drivers/openai-chat.js +240 -0
  397. package/dist-server/server/drivers/openai-compat.js +143 -0
  398. package/dist-server/server/drivers/phone-proxy.js +372 -0
  399. package/dist-server/server/drivers/pi.js +855 -0
  400. package/dist-server/server/drivers/retry.js +96 -0
  401. package/dist-server/server/enterprise.js +93 -0
  402. package/dist-server/server/env-path.js +329 -0
  403. package/dist-server/server/environment.js +105 -0
  404. package/dist-server/server/generated-image.js +39 -0
  405. package/dist-server/server/graceful-shutdown.js +24 -0
  406. package/dist-server/server/group-goal-run.js +124 -0
  407. package/dist-server/server/harness/bus.js +86 -0
  408. package/dist-server/server/harness/registry.js +217 -0
  409. package/dist-server/server/index.js +11634 -0
  410. package/dist-server/server/installed-playbooks.js +34 -0
  411. package/dist-server/server/local-computer.js +278 -0
  412. package/dist-server/server/local-routing.js +9 -0
  413. package/dist-server/server/local-vm-idle.js +44 -0
  414. package/dist-server/server/local-vm-inventory.js +34 -0
  415. package/dist-server/server/local-vm-lease.js +58 -0
  416. package/dist-server/server/mcp-bridge.js +251 -0
  417. package/dist-server/server/mcp-probe.js +153 -0
  418. package/dist-server/server/mcp-registry.js +130 -0
  419. package/dist-server/server/member-turn.js +6 -0
  420. package/dist-server/server/message-db.js +358 -0
  421. package/dist-server/server/message-file.js +439 -0
  422. package/dist-server/server/names.js +26 -0
  423. package/dist-server/server/notify.js +69 -0
  424. package/dist-server/server/openmaus-status-capsule.js +329 -0
  425. package/dist-server/server/openmausbot.js +6 -0
  426. package/dist-server/server/package-export.js +157 -0
  427. package/dist-server/server/pair-cli.js +7 -0
  428. package/dist-server/server/peer-approval-key.js +5 -0
  429. package/dist-server/server/peer-approval.js +182 -0
  430. package/dist-server/server/peer-provenance.js +44 -0
  431. package/dist-server/server/peer-roster.js +139 -0
  432. package/dist-server/server/permission-proxy.js +157 -0
  433. package/dist-server/server/phone-secret.js +358 -0
  434. package/dist-server/server/private-screen-capture.js +17 -0
  435. package/dist-server/server/procs.js +123 -0
  436. package/dist-server/server/project-scout.js +304 -0
  437. package/dist-server/server/proxy-paths.js +47 -0
  438. package/dist-server/server/redact.js +102 -0
  439. package/dist-server/server/remote-computer.js +170 -0
  440. package/dist-server/server/repeat-detector.js +48 -0
  441. package/dist-server/server/replies.js +38 -0
  442. package/dist-server/server/request-auth.js +327 -0
  443. package/dist-server/server/room-cwd.js +15 -0
  444. package/dist-server/server/room-post-budget.js +112 -0
  445. package/dist-server/server/room-turn-timeout.js +115 -0
  446. package/dist-server/server/routine-requests.js +871 -0
  447. package/dist-server/server/routines.js +1111 -0
  448. package/dist-server/server/schema.js +11 -0
  449. package/dist-server/server/screen-frame-gate.js +80 -0
  450. package/dist-server/server/section-context.js +85 -0
  451. package/dist-server/server/send-idempotency.js +53 -0
  452. package/dist-server/server/sessions.js +319 -0
  453. package/dist-server/server/skill-fetch.js +148 -0
  454. package/dist-server/server/skill-learn.js +61 -0
  455. package/dist-server/server/skill-library.js +116 -0
  456. package/dist-server/server/skills.js +1223 -0
  457. package/dist-server/server/steer-queue.js +114 -0
  458. package/dist-server/server/store.js +1217 -0
  459. package/dist-server/server/surface.js +107 -0
  460. package/dist-server/server/tailscale.js +103 -0
  461. package/dist-server/server/team-backup.js +183 -0
  462. package/dist-server/server/team-library.js +205 -0
  463. package/dist-server/server/team-manifest.js +224 -0
  464. package/dist-server/server/thread-events.js +226 -0
  465. package/dist-server/server/tts/elevenlabs.js +92 -0
  466. package/dist-server/server/tts/index.js +79 -0
  467. package/dist-server/server/tts/speech-text.js +195 -0
  468. package/dist-server/server/tts/system-voices.js +74 -0
  469. package/dist-server/server/tunnel.js +202 -0
  470. package/dist-server/server/turn-context.js +40 -0
  471. package/dist-server/server/turn-dispatch-guard.js +152 -0
  472. package/dist-server/server/turn-images.js +138 -0
  473. package/dist-server/server/turn-watchdog.js +65 -0
  474. package/dist-server/server/vps-computer.js +1099 -0
  475. package/dist-server/server/vps-container-mcp.js +31 -0
  476. package/dist-server/server/webhook-ingress.js +173 -0
  477. package/dist-server/server/webhooks.js +491 -0
  478. package/dist-server/server/workspace.js +178 -0
  479. package/dist-server/shared/approval-mode.js +39 -0
  480. package/dist-server/shared/bot-avatar.js +33 -0
  481. package/dist-server/shared/bot-profile.js +7 -0
  482. package/dist-server/shared/connector-availability.js +12 -0
  483. package/dist-server/shared/credential-request.js +82 -0
  484. package/dist-server/shared/group-goal-run.js +1 -0
  485. package/dist-server/shared/import-name.js +11 -0
  486. package/dist-server/shared/mascot-bodies.js +107 -0
  487. package/dist-server/shared/routine-request.js +10 -0
  488. package/dist-server/shared/routine-run.js +1 -0
  489. package/dist-server/shared/skill-request.js +16 -0
  490. package/dist-server/shared/team-backup.js +148 -0
  491. package/dist-server/src/lib/composer-attachments.js +676 -0
  492. package/dist-server/tunnel-guardian.js +390 -0
  493. package/dist-server/vps-container-mcp.js +15209 -0
  494. package/package.json +32 -0
  495. package/skills/create-verification-skill/SKILL.md +65 -0
  496. package/skills/create-verification-skill/manifest.json +13 -0
  497. package/skills/phone-harness/SKILL.md +26 -0
  498. package/skills/phone-harness/agents/openai.yaml +13 -0
  499. package/skills/phone-harness/manifest.json +17 -0
@@ -0,0 +1,365 @@
1
+ import { execCli } from "../../procs.js";
2
+ import { createAcpDriver } from "./core.js";
3
+ /** Translate an argv `--model` slug into the id this ACP session will accept.
4
+ *
5
+ * Cursor keeps two model namespaces and they do not match. `cursor-agent
6
+ * models` and the `--model` flag speak flat slugs (`auto`, `gpt-5.3-codex`).
7
+ * The ACP session advertises parameterised ids instead
8
+ * (`default[]`, `gpt-5.3-codex[reasoning=medium,fast=false]`), and
9
+ * `session/set_model` accepts *only* those. Sending the argv slug earns
10
+ * `-32602 Invalid params` for every model, not merely unknown ones — which
11
+ * read as "this account cannot use that model" and sent people to check their
12
+ * subscription over a pure id-format mismatch.
13
+ *
14
+ * Matching walks from most to least specific, and `auto` is special-cased
15
+ * because Cursor calls that entry `default[]` while naming it "Auto".
16
+ *
17
+ * Returns null when nothing matches, including when the agent advertised no
18
+ * models at all. The caller then falls back to sending the slug unchanged,
19
+ * which is what older CLIs that ignore the model list still expect.
20
+ */
21
+ export function resolveCursorAcpModelId(available, wanted) {
22
+ const want = wanted.trim().toLowerCase();
23
+ if (!want)
24
+ return null;
25
+ const ids = available.filter((m) => typeof m?.modelId === "string" && m.modelId);
26
+ if (!ids.length)
27
+ return null;
28
+ const base = (id) => id.split("[")[0].trim().toLowerCase();
29
+ const exact = ids.find((m) => m.modelId.toLowerCase() === want);
30
+ if (exact)
31
+ return exact.modelId;
32
+ const byBase = ids.find((m) => base(m.modelId) === want);
33
+ if (byBase)
34
+ return byBase.modelId;
35
+ const byName = ids.find((m) => (m.name ?? "").trim().toLowerCase() === want);
36
+ if (byName)
37
+ return byName.modelId;
38
+ if (want === "auto" || want === "default") {
39
+ const dflt = ids.find((m) => base(m.modelId) === "default");
40
+ if (dflt)
41
+ return dflt.modelId;
42
+ }
43
+ return null;
44
+ }
45
+ export const STATIC_CURSOR_MODELS = {
46
+ default: "auto",
47
+ options: [
48
+ { id: "auto", label: "Auto" },
49
+ { id: "composer-2.5", label: "Composer 2.5" },
50
+ { id: "composer-2.5-fast", label: "Composer 2.5 Fast" },
51
+ { id: "gpt-5.3-codex", label: "Codex 5.3" },
52
+ { id: "claude-sonnet-5-thinking-high", label: "Claude Sonnet 5 1M Thinking" },
53
+ ],
54
+ };
55
+ const SLUG = /^[a-z0-9][a-z0-9._:+-]*$/i;
56
+ const EXEC_TIMEOUT_MS = 8_000;
57
+ const nonBlank = (value) => Boolean(value?.trim());
58
+ function firstJsonValue(text) {
59
+ const trimmed = text.trim();
60
+ if (!trimmed)
61
+ return null;
62
+ try {
63
+ return JSON.parse(trimmed);
64
+ }
65
+ catch {
66
+ // CLIs sometimes print a banner before the payload. Take the first
67
+ // {...} or [...] span that parses, rather than requiring a clean stdout.
68
+ }
69
+ const start = trimmed.search(/[{[]/);
70
+ if (start < 0)
71
+ return null;
72
+ for (let end = trimmed.length; end > start + 1; end--) {
73
+ const slice = trimmed.slice(start, end).trim();
74
+ if (!slice.endsWith("}") && !slice.endsWith("]"))
75
+ continue;
76
+ try {
77
+ return JSON.parse(slice);
78
+ }
79
+ catch {
80
+ // keep shrinking
81
+ }
82
+ }
83
+ return null;
84
+ }
85
+ function asRecord(value) {
86
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
87
+ }
88
+ function labelFor(id, explicit) {
89
+ if (explicit?.trim())
90
+ return explicit.trim();
91
+ return id
92
+ .split(/[-_./]+/g)
93
+ .filter(Boolean)
94
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
95
+ .join(" ");
96
+ }
97
+ function pushModel(options, seen, id, label, custom = false) {
98
+ if (!SLUG.test(id) || seen.has(id))
99
+ return;
100
+ seen.add(id);
101
+ options.push({ id, label: labelFor(id, label), ...(custom ? { custom: true } : {}) });
102
+ }
103
+ /** Turn `cursor-agent models` JSON (or a close cousin) into a picker catalog.
104
+ * Unknown shapes return null so the caller can try text / keep the fallback. */
105
+ export function decodeCursorModelCatalog(payload) {
106
+ const records = Array.isArray(payload)
107
+ ? payload
108
+ : Array.isArray(asRecord(payload)?.models)
109
+ ? asRecord(payload).models
110
+ : Array.isArray(asRecord(payload)?.data)
111
+ ? asRecord(payload).data
112
+ : Array.isArray(asRecord(payload)?.modelIds)
113
+ ? asRecord(payload).modelIds
114
+ : [];
115
+ if (!records.length)
116
+ return null;
117
+ const options = [];
118
+ const seen = new Set();
119
+ for (const row of records) {
120
+ if (typeof row === "string") {
121
+ pushModel(options, seen, row);
122
+ continue;
123
+ }
124
+ const rec = asRecord(row);
125
+ if (!rec)
126
+ continue;
127
+ const id = rec.id ?? rec.modelId ?? rec.slug ?? rec.name;
128
+ if (typeof id !== "string")
129
+ continue;
130
+ const label = (typeof rec.label === "string" && rec.label) ||
131
+ (typeof rec.displayName === "string" && rec.displayName) ||
132
+ (typeof rec.name === "string" && rec.name !== id ? rec.name : undefined);
133
+ pushModel(options, seen, id, label || undefined);
134
+ }
135
+ if (!options.length)
136
+ return null;
137
+ const defaultId = (typeof asRecord(payload)?.default === "string" && seen.has(asRecord(payload).default)
138
+ ? asRecord(payload).default
139
+ : undefined) ??
140
+ (seen.has(STATIC_CURSOR_MODELS.default) ? STATIC_CURSOR_MODELS.default : options[0].id);
141
+ // Keep the static cloud set at the front (stable picker rail) and append
142
+ // live ids the static list does not already name.
143
+ const merged = STATIC_CURSOR_MODELS.options.map((option) => ({ ...option }));
144
+ const mergedSeen = new Set(merged.map((option) => option.id));
145
+ for (const option of options) {
146
+ if (mergedSeen.has(option.id))
147
+ continue;
148
+ mergedSeen.add(option.id);
149
+ merged.push(option);
150
+ }
151
+ return { default: defaultId, options: merged };
152
+ }
153
+ function stripModelMarkers(label) {
154
+ let cleaned = label.trim();
155
+ let isDefault = false;
156
+ let isCurrent = false;
157
+ const defaultMatch = cleaned.match(/\s*\(default\)\s*$/i);
158
+ if (defaultMatch) {
159
+ isDefault = true;
160
+ cleaned = cleaned.slice(0, defaultMatch.index).trim();
161
+ }
162
+ const currentMatch = cleaned.match(/\s*\(current\)\s*$/i);
163
+ if (currentMatch) {
164
+ isCurrent = true;
165
+ cleaned = cleaned.slice(0, currentMatch.index).trim();
166
+ }
167
+ return { label: cleaned, isDefault, isCurrent };
168
+ }
169
+ /** Parse plain `cursor-agent models` text: one slug per line, optional `id - label`
170
+ * columns, and `(default)` / `(current)` markers on the label. */
171
+ export function decodeCursorModelText(text) {
172
+ const options = [];
173
+ const seen = new Set();
174
+ let markedDefault;
175
+ let markedCurrent;
176
+ for (const raw of text.split(/\r?\n/)) {
177
+ const line = raw.trim();
178
+ if (!line || line.startsWith("#") || /^available\s+models?\b/i.test(line) || /^models?\b/i.test(line))
179
+ continue;
180
+ const stripped = line.replace(/^[\s*•\-]+\s*/, "");
181
+ const parts = stripped.split(/\s+[—–|:]\s+|\s+-\s+|\s{2,}/);
182
+ const id = (parts[0] ?? "").trim();
183
+ const rawLabel = parts.slice(1).join(" ").trim();
184
+ const { label, isDefault, isCurrent } = stripModelMarkers(rawLabel);
185
+ pushModel(options, seen, id, label || undefined);
186
+ if (isDefault)
187
+ markedDefault = id;
188
+ if (isCurrent)
189
+ markedCurrent = id;
190
+ }
191
+ if (!options.length)
192
+ return null;
193
+ const merged = STATIC_CURSOR_MODELS.options.map((option) => ({ ...option }));
194
+ const mergedSeen = new Set(merged.map((option) => option.id));
195
+ for (const option of options) {
196
+ if (mergedSeen.has(option.id))
197
+ continue;
198
+ mergedSeen.add(option.id);
199
+ merged.push(option);
200
+ }
201
+ const defaultId = (markedDefault && seen.has(markedDefault) ? markedDefault : undefined) ??
202
+ (markedCurrent && seen.has(markedCurrent) ? markedCurrent : undefined) ??
203
+ (seen.has(STATIC_CURSOR_MODELS.default) ? STATIC_CURSOR_MODELS.default : options[0].id);
204
+ return { default: defaultId, options: merged };
205
+ }
206
+ function truthyAuthFlag(value) {
207
+ if (value === true)
208
+ return true;
209
+ if (value === false)
210
+ return false;
211
+ if (typeof value === "string") {
212
+ const normalized = value.trim().toLowerCase();
213
+ if (["true", "authenticated", "logged_in", "logged-in", "yes"].includes(normalized))
214
+ return true;
215
+ if (["false", "unauthenticated", "logged_out", "logged-out", "no"].includes(normalized))
216
+ return false;
217
+ }
218
+ return null;
219
+ }
220
+ /** Read `cursor-agent status --format json`.
221
+ * Returns null when the payload does not actually answer the question. */
222
+ export function decodeCursorAuthStatus(payload) {
223
+ const rec = asRecord(payload);
224
+ if (!rec)
225
+ return null;
226
+ const auth = asRecord(rec.auth);
227
+ const candidates = [
228
+ rec.isAuthenticated,
229
+ rec.authenticated,
230
+ rec.loggedIn,
231
+ rec.logged_in,
232
+ auth?.isAuthenticated,
233
+ auth?.authenticated,
234
+ rec.status,
235
+ auth?.status,
236
+ ];
237
+ for (const candidate of candidates) {
238
+ const flag = truthyAuthFlag(candidate);
239
+ if (flag !== null)
240
+ return flag;
241
+ }
242
+ return null;
243
+ }
244
+ /** Parse the documented human-readable `cursor-agent status` fallback. */
245
+ export function decodeCursorAuthText(text) {
246
+ const normalized = text.trim().toLowerCase();
247
+ if (!normalized)
248
+ return null;
249
+ if (/not (?:logged|signed) in|not authenticated|unauthenticated|logged out/.test(normalized))
250
+ return false;
251
+ if (/login successful|logged in|signed in|authenticated/.test(normalized))
252
+ return true;
253
+ return null;
254
+ }
255
+ function execText(run, cli, args, env) {
256
+ return new Promise((resolve) => {
257
+ run(cli, args, { timeout: EXEC_TIMEOUT_MS, env: env }, (err, stdout) => {
258
+ if (err)
259
+ return resolve(null);
260
+ resolve(String(stdout ?? ""));
261
+ });
262
+ });
263
+ }
264
+ export async function probeCursorAuth(cli, env, run = execCli) {
265
+ if (nonBlank(env.CURSOR_API_KEY) || nonBlank(env.CURSOR_AUTH_TOKEN))
266
+ return true;
267
+ for (const args of [["status", "--format", "json"], ["status"]]) {
268
+ const stdout = await execText(run, cli, [...args], env);
269
+ if (stdout == null)
270
+ continue;
271
+ const decoded = decodeCursorAuthStatus(firstJsonValue(stdout)) ?? decodeCursorAuthText(stdout);
272
+ if (decoded !== null)
273
+ return decoded;
274
+ }
275
+ return false;
276
+ }
277
+ export async function fetchCursorModels(cli, env, run = execCli) {
278
+ // Live CLI prints plain text (`slug - Label`); `--format json` is not supported yet.
279
+ for (const args of [["models"], ["--list-models"]]) {
280
+ const stdout = await execText(run, cli, [...args], env);
281
+ if (stdout == null)
282
+ continue;
283
+ const fromText = decodeCursorModelText(stdout);
284
+ if (fromText)
285
+ return fromText;
286
+ const fromJson = decodeCursorModelCatalog(firstJsonValue(stdout));
287
+ if (fromJson)
288
+ return fromJson;
289
+ }
290
+ return STATIC_CURSOR_MODELS;
291
+ }
292
+ export function classifyCursorError(error) {
293
+ const message = error instanceof Error ? error.message : String(error ?? "");
294
+ const code = error && typeof error === "object" ? error.code : undefined;
295
+ const blob = `${code ?? ""} ${message}`.toLowerCase();
296
+ if (code === -32000 ||
297
+ /unauthoriz|unauthenticated|not signed in|not logged in|invalid api key|invalid_credentials|authentication required/.test(blob)) {
298
+ return "invalid_credentials";
299
+ }
300
+ if (/inactive subscription|subscription.*(expired|inactive)|upgrade your (plan|subscription)/.test(blob)) {
301
+ return "inactive_subscription";
302
+ }
303
+ return undefined;
304
+ }
305
+ const support = (run) => ({
306
+ driverKind: "cursorAgent",
307
+ displayName: "Cursor",
308
+ models: STATIC_CURSOR_MODELS,
309
+ // Cursor and other coding agents can both install a generic `agent` shim.
310
+ // Cursor's compatibility alias is unambiguous and ships with the same CLI.
311
+ defaultCli: "cursor-agent",
312
+ nativeSource: "cursor.acp",
313
+ loginNote: "Cursor CLI is not signed in — run `cursor-agent login` in a terminal, or set CURSOR_API_KEY",
314
+ install: {
315
+ command: {
316
+ darwin: "curl https://cursor.com/install -fsS | bash",
317
+ linux: "curl https://cursor.com/install -fsS | bash",
318
+ win32: "irm 'https://cursor.com/install?win32=true' | iex",
319
+ },
320
+ docsUrl: "https://cursor.com/docs/cli/installation",
321
+ signInCommand: "cursor-agent login",
322
+ },
323
+ // Global flags must precede `acp` (cursor.com/docs/cli/reference/parameters).
324
+ // `--force` is the documented auto-approve switch (`--yolo` is an alias);
325
+ // `--model` is the reliable pin — ACP session/set_model is best-effort below.
326
+ spawnArgs: (config, turn) => [
327
+ ...(config.fullAuto ? ["--force"] : turn.approvalMode === "auto" ? ["--auto-review"] : []),
328
+ ...(turn.model ? ["--model", turn.model] : []),
329
+ "acp",
330
+ ],
331
+ credentialEnv: ["CURSOR_API_KEY", "CURSOR_AUTH_TOKEN"],
332
+ resolveModels: (environment, config) => fetchCursorModels(config.cli || "cursor-agent", environment, run),
333
+ // Prefer the advertised ACP method. An already-signed-in CLI should accept
334
+ // cursor_login without a browser; a missing method rides the ambient login
335
+ // (CURSOR_API_KEY / `cursor-agent login`) instead of failing the turn.
336
+ pickAuthMethod: (methods) => (methods.some((m) => m.id === "cursor_login") ? "cursor_login" : null),
337
+ authFailure: "continue",
338
+ isAuthenticated: (env, config) => probeCursorAuth(config.cli || "cursor-agent", env, run),
339
+ classifyError: classifyCursorError,
340
+ async configureSession({ request, sessionId, turn, sessionModels }) {
341
+ if (!turn.model)
342
+ return;
343
+ // Prefer the id this session actually advertised; fall back to the argv
344
+ // slug so a CLI that advertises nothing behaves exactly as before.
345
+ const modelId = resolveCursorAcpModelId(sessionModels ?? [], turn.model) ?? turn.model;
346
+ try {
347
+ await request("session/set_model", { sessionId, modelId });
348
+ }
349
+ catch (e) {
350
+ const err = e;
351
+ // -32601 method missing, -32602 id not in this session's namespace. In
352
+ // both cases spawnArgs already pinned `--model`, so the turn runs the
353
+ // right model anyway; failing it here would refuse a working request.
354
+ if (err.code === -32601 || err.code === -32602)
355
+ return;
356
+ throw new Error(`Cursor rejected model "${turn.model}" (sent as "${modelId}") via session/set_model: ${err.message}. ` +
357
+ `Check that \`cursor-agent\` is current and that this account can use that model.`);
358
+ }
359
+ },
360
+ buildPromptText: (turn) => (turn.system ? `${turn.system}\n\n${turn.text}` : turn.text),
361
+ });
362
+ export function createCursorAgentDriver(run = execCli) {
363
+ return createAcpDriver(support(run));
364
+ }
365
+ export const CursorAgentDriver = createCursorAgentDriver();
@@ -0,0 +1,51 @@
1
+ // Bring-your-own engine: any agent CLI that speaks ACP over stdio plugs in
2
+ // as an instance of this driver — no code, one config entry:
3
+ //
4
+ // { "instances": { "my-agent": {
5
+ // "driver": "customAcp",
6
+ // "displayName": "My Agent",
7
+ // "config": { "cli": "my-agent acp" } } } }
8
+ //
9
+ // The `cli` string carries the whole command (wrapper strings resolve via
10
+ // splitCliString, so "npx -y some-agent acp" works too). There is no auth
11
+ // story on purpose: the user's CLI is expected to be signed in from a
12
+ // terminal already, exactly like the qwen harness. Model choice stays
13
+ // inside the agent — we advertise a single passthrough id and never pass
14
+ // a model on argv, because -m conventions differ per CLI.
15
+ import { createAcpDriver } from "./core.js";
16
+ const CONFIGURE_HINT = 'a custom ACP engine needs its command — add "config": { "cli": "<your-agent> acp" } to this instance in config.json, or use Settings → Engines → Set CLI…';
17
+ const support = {
18
+ driverKind: "customAcp",
19
+ displayName: "Custom (ACP)",
20
+ access: "custom",
21
+ // One passthrough id: the agent runs whatever it is configured for.
22
+ // Advertising a made-up catalog would promise switching we cannot do.
23
+ models: { default: "agent-default", options: [{ id: "agent-default", label: "Agent default" }] },
24
+ defaultCli: "",
25
+ nativeSource: "custom.acp",
26
+ loginNote: CONFIGURE_HINT,
27
+ // Mode-entering args ride the cli string itself ("fx acp"), so nothing
28
+ // extra here.
29
+ spawnArgs: () => [],
30
+ pickAuthMethod: () => null,
31
+ authFailure: "continue",
32
+ isAuthenticated: () => true,
33
+ };
34
+ const base = createAcpDriver(support);
35
+ export const CustomAcpDriver = {
36
+ ...base,
37
+ // decodeAcpConfig never throws (a missing cli falls back to defaultCli,
38
+ // which is empty here). Turn every blank-command path into the same
39
+ // teaching shadow row instead of a bare spawn ENOENT at first send.
40
+ decodeConfig(raw) {
41
+ const decoded = base.decodeConfig(raw);
42
+ if (!decoded.cli.trim())
43
+ throw new Error(CONFIGURE_HINT);
44
+ return decoded;
45
+ },
46
+ async create(input) {
47
+ if (!input.config.cli.trim())
48
+ throw new Error(CONFIGURE_HINT);
49
+ return base.create(input);
50
+ },
51
+ };
@@ -0,0 +1,225 @@
1
+ // Factory Droid harness support — the `droid` CLI over ACP stdio
2
+ // (`droid exec -o acp`), on the Factory login (~/.factory/auth.v2.file) or a
3
+ // FACTORY_API_KEY. The generic protocol runtime lives in acp/core.ts; this
4
+ // file is only the per-harness quirks. Verified against droid 0.196.0:
5
+ // initialize reports protocolVersion 1, loadSession:true (session/load resume
6
+ // works), promptCapabilities image+embeddedContext, and authMethods
7
+ // device-pairing + factory-api-key.
8
+ //
9
+ // UNLIKE every other ACP harness here, droid ignores argv for session
10
+ // settings. `droid exec --help` says so under "Stream JSON-RPC Mode": "CLI
11
+ // flags do not configure JSON-RPC sessions: -m/--model, --auto,
12
+ // -r/--reasoning-effort, and --disable-builtin-skills are still validated,
13
+ // but session settings come from JSON-RPC requests." So a `-m` that only
14
+ // reaches argv is accepted and then ignored, and the session runs whatever
15
+ // ~/.factory/settings.json selected. Model and autonomy are session config
16
+ // options set over the wire (session/set_model, session/set_mode), which is
17
+ // why both live in configureSession() below and NOT in spawnArgs.
18
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
19
+ import { homedir } from "node:os";
20
+ import { join } from "node:path";
21
+ import { decodeInjectId, hostApiKey, localHost, mergeLocalInject } from "../local-inject.js";
22
+ import { createAcpDriver } from "./core.js";
23
+ // FACTORY_HOME_OVERRIDE replaces the HOME the CLI resolves, NOT the data root:
24
+ // droid builds every path as <home>/.factory/… (verified against 0.196.0 —
25
+ // `FACTORY_HOME_OVERRIDE=/tmp/x droid exec -o acp` created /tmp/x/.factory/).
26
+ // Kimi's KIMI_CODE_HOME is a data root; this one is not, so the `.factory`
27
+ // segment stays on both branches.
28
+ //
29
+ // Which credential file exists depends on the `secure_auth_storage` feature
30
+ // flag droid fetches for the account: with secure storage on it writes
31
+ // auth.v2.loginkeychain (macOS) or auth.v2.keyring (keytar), and only falls
32
+ // back to auth.v2.file when that write fails. droid's own check tries all of
33
+ // them, so checking one name alone reports a fresh signed-in login as logged
34
+ // out. Names read from the 0.196.0 binary.
35
+ const AUTH_FILES = ["auth.v2.file", "auth.v2.loginkeychain", "auth.v2.keyring"];
36
+ function authFilePaths(env) {
37
+ const home = env.FACTORY_HOME_OVERRIDE || env.HOME || homedir();
38
+ return AUTH_FILES.map((name) => join(home, ".factory", name));
39
+ }
40
+ const INJECT_ID_PREFIX = "custom:openmausbot-";
41
+ export function droidInjectId(host, model) {
42
+ const safe = `${host}-${model}`.replace(/[^a-zA-Z0-9._+-]+/g, "-").replace(/-+/g, "-");
43
+ return `${INJECT_ID_PREFIX}${safe}`;
44
+ }
45
+ function factoryHome(env) {
46
+ return env.FACTORY_HOME_OVERRIDE || env.HOME || env.USERPROFILE || homedir();
47
+ }
48
+ /** Upsert a BYOK custom model so session/set_model can reach the local host. */
49
+ export function ensureDroidInjectModel(modelId, env = process.env) {
50
+ const inject = decodeInjectId(modelId);
51
+ if (!inject)
52
+ return modelId;
53
+ const host = localHost(inject.host);
54
+ if (!host)
55
+ return modelId;
56
+ const id = droidInjectId(inject.host, inject.model);
57
+ const dir = join(factoryHome(env), ".factory");
58
+ mkdirSync(dir, { recursive: true });
59
+ const path = join(dir, "settings.json");
60
+ let settings = {};
61
+ try {
62
+ settings = JSON.parse(readFileSync(path, "utf8"));
63
+ }
64
+ catch (error) {
65
+ if (existsSync(path))
66
+ throw error;
67
+ }
68
+ const custom = Array.isArray(settings.customModels) ? [...settings.customModels] : [];
69
+ const match = custom.find((row) => row.id === id || (row.model === inject.model && row.baseUrl === host.baseUrl));
70
+ if (match) {
71
+ if (!match.id) {
72
+ match.id = id;
73
+ settings.customModels = custom;
74
+ writeFileSync(path, `${JSON.stringify(settings, null, 2)}\n`);
75
+ }
76
+ return match.id;
77
+ }
78
+ custom.push({
79
+ id,
80
+ model: inject.model,
81
+ displayName: `${inject.model} (${host.label})`,
82
+ baseUrl: host.baseUrl,
83
+ apiKey: hostApiKey(host, env),
84
+ provider: "generic-chat-completion-api",
85
+ });
86
+ settings.customModels = custom;
87
+ writeFileSync(path, `${JSON.stringify(settings, null, 2)}\n`);
88
+ return id;
89
+ }
90
+ /** ACP `session/new` throws "Authentication required" unless a Factory
91
+ * login or FACTORY_API_KEY is present — even for a BYOK custom model.
92
+ * Droid 0.198 only checks that the env var is set, then uses the
93
+ * custom row's own key for the local host. Do not invent a key for
94
+ * subscription models, and do not overwrite a real Factory key. */
95
+ export function applyDroidLocalAuthEnv(env, modelId) {
96
+ if (!decodeInjectId(modelId))
97
+ return;
98
+ if (env.FACTORY_API_KEY?.trim())
99
+ return;
100
+ // session/new already succeeds on a Factory login file. A placeholder
101
+ // FACTORY_API_KEY can take precedence over that login, so leave env
102
+ // alone when one of the auth files is present.
103
+ if (authFilePaths(env).some(existsSync))
104
+ return;
105
+ env.FACTORY_API_KEY = "openmausbot-local";
106
+ }
107
+ function readSettings(env) {
108
+ return JSON.parse(readFileSync(join(factoryHome(env), ".factory", "settings.json"), "utf8"));
109
+ }
110
+ async function resolveModels(env) {
111
+ let catalog = MODELS;
112
+ try {
113
+ const settings = readSettings(env);
114
+ const custom = (settings.customModels ?? []).flatMap((m) => {
115
+ // Live inject rows come from mergeLocalInject as host::model. Skip the
116
+ // BYOK copies we wrote so the picker does not list the same model twice.
117
+ if (m.id?.startsWith(INJECT_ID_PREFIX))
118
+ return [];
119
+ const id = m.id || (m.model ? `custom:${m.model}` : "");
120
+ if (!id)
121
+ return [];
122
+ return [{ id, label: m.displayName || m.model || id, custom: true }];
123
+ });
124
+ const merged = [...custom, ...MODELS.options.filter((o) => !custom.some((c) => c.id === o.id))];
125
+ // Favourites first, in the user's own order; everything else keeps its
126
+ // existing order (Array.prototype.sort is stable).
127
+ const rank = new Map((settings.modelFavorites ?? []).map((id, i) => [id, i]));
128
+ const options = merged.sort((a, b) => (rank.get(a.id) ?? Infinity) - (rank.get(b.id) ?? Infinity));
129
+ const configured = settings.sessionDefaultSettings?.model;
130
+ const fallback = options[0]?.id ?? MODELS.default;
131
+ catalog = {
132
+ default: configured && options.some((o) => o.id === configured) ? configured : fallback,
133
+ options,
134
+ };
135
+ }
136
+ catch {
137
+ // no settings file yet, or unreadable: ship the built-ins
138
+ }
139
+ return mergeLocalInject(catalog, env);
140
+ }
141
+ // droid answers a rejected setting with a bare JSON-RPC message ("Model not
142
+ // recognized", "Method not found") that reaches the error card verbatim,
143
+ // naming neither the engine nor the setting that failed. Say what we asked for.
144
+ async function applySetting(request, method, params, what) {
145
+ try {
146
+ await request(method, params);
147
+ }
148
+ catch (e) {
149
+ throw new Error(`Droid rejected ${what} via ${method}: ${e.message}. ` +
150
+ `Check that \`droid\` is current (0.196.0+ supports it) and that this account can use that value.`);
151
+ }
152
+ }
153
+ // Autonomy maps onto droid's session modes (session/new advertises
154
+ // normal | spec | auto-low | auto-medium | auto-high). Always set it
155
+ // explicitly: ~/.factory/settings.json can pin a mode, and inheriting it
156
+ // would either make every session yolo or make fullAuto silently ask.
157
+ const MODE_DEFAULT = "normal"; // auto-approves reads only; everything else asks
158
+ const MODE_FULL_AUTO = "auto-high";
159
+ // A curated slice of `droid exec -m <bogus>`'s built-in catalog (0.196.0 lists
160
+ // 43). Custom models from ~/.factory/settings.json are per-machine and carry a
161
+ // `custom:` prefix, so they can't be enumerated statically; a bot can still be
162
+ // switched onto one through the model picker (PATCH /api/bots/:id).
163
+ const MODELS = {
164
+ default: "claude-opus-5",
165
+ options: [
166
+ { id: "auto", label: "Auto (Factory picks)" },
167
+ { id: "claude-opus-5", label: "Claude Opus 5" },
168
+ { id: "claude-sonnet-5", label: "Claude Sonnet 5" },
169
+ { id: "claude-haiku-4-5-20251001", label: "Claude Haiku 4.5" },
170
+ { id: "gpt-5.6-sol", label: "GPT-5.6 Sol" },
171
+ { id: "gpt-5.6-terra", label: "GPT-5.6 Terra" },
172
+ { id: "gemini-3.1-pro-preview", label: "Gemini 3.1 Pro" },
173
+ { id: "glm-5.2", label: "GLM 5.2" },
174
+ { id: "kimi-k3", label: "Kimi K3" },
175
+ { id: "grok-4.6", label: "Grok 4.6" },
176
+ ],
177
+ };
178
+ const support = {
179
+ driverKind: "droidAgent",
180
+ displayName: "Droid",
181
+ models: MODELS,
182
+ defaultCli: "droid",
183
+ nativeSource: "droid.acp",
184
+ loginNote: "Droid CLI is not signed in — run `droid` once and log in, or set FACTORY_API_KEY",
185
+ install: {
186
+ command: {
187
+ darwin: "curl -fsSL https://app.factory.ai/cli | sh",
188
+ linux: "curl -fsSL https://app.factory.ai/cli | sh",
189
+ win32: "irm https://app.factory.ai/cli/windows | iex",
190
+ },
191
+ docsUrl: "https://docs.factory.ai/droid-cli/quickstart",
192
+ signInCommand: "droid",
193
+ },
194
+ // No model/mode flags here on purpose: see the header note. `-o acp` is the
195
+ // ACP entry point; everything else is negotiated over the protocol.
196
+ spawnArgs: () => ["exec", "-o", "acp"],
197
+ credentialEnv: ["FACTORY_API_KEY"],
198
+ // The advertised methods are device-pairing (a browser flow that cannot be
199
+ // driven over ACP) and factory-api-key (read from the child env, no
200
+ // authenticate call needed). Ride the ambient login instead, like Kimi.
201
+ pickAuthMethod: () => null,
202
+ authFailure: "continue",
203
+ // The signed-in CLI is the primary source; FACTORY_API_KEY is the fallback
204
+ // droid itself advertises, and it is checked last so an ambient key can
205
+ // never be what makes an otherwise logged-out instance look ready.
206
+ isAuthenticated: (env) => authFilePaths(env).some(existsSync) || Boolean(env.FACTORY_API_KEY),
207
+ resolveModels,
208
+ resolveTurnModel: (model, env) => (model ? ensureDroidInjectModel(model, env) : model),
209
+ applyTurnEnv: (env, { requestedModel }) => {
210
+ applyDroidLocalAuthEnv(env, requestedModel);
211
+ },
212
+ async configureSession({ request, sessionId, config, turn }) {
213
+ const modeId = config.fullAuto ? MODE_FULL_AUTO : MODE_DEFAULT;
214
+ await applySetting(request, "session/set_mode", { sessionId, modeId }, `autonomy mode "${modeId}"`);
215
+ // Pin the model for the same reason as the mode: with no set_model the
216
+ // session runs whatever ~/.factory/settings.json selected, which can be a
217
+ // `custom:` provider pointing at its own endpoint and key.
218
+ const modelId = turn.model ?? MODELS.default;
219
+ await applySetting(request, "session/set_model", { sessionId, modelId }, `model "${modelId}"`);
220
+ },
221
+ // House convention for ACP harnesses (grok, gemini, kimi all do this): the
222
+ // persona rides in the prompt text rather than a CLI system-prompt flag.
223
+ buildPromptText: (turn) => (turn.system ? `${turn.system}\n\n${turn.text}` : turn.text),
224
+ };
225
+ export const DroidAgentDriver = createAcpDriver(support);