openmausbot 0.1.97 → 0.1.99

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 (434) hide show
  1. package/dist/assets/ActivityPanel-CgUgtumZ.js +1 -0
  2. package/dist/assets/BotSettingsDialog-lJj6oiir.js +7 -0
  3. package/dist/assets/CloudBackendPicker-C5-_arUz.js +1 -0
  4. package/dist/assets/ComputerPanel-euJ2CSlH.js +1 -0
  5. package/dist/assets/DesktopViewer-XCln1Pn_.js +5 -0
  6. package/dist/assets/InspectorPanel-DKYyQZlo.js +5 -0
  7. package/dist/assets/KeyboardShortcutsModal-DkkZWZRI.js +1 -0
  8. package/dist/assets/LocalVmWorkspace-Cwt3_XSx.js +1 -0
  9. package/dist/assets/MacLocalControl-B28RbdCS.js +1 -0
  10. package/dist/assets/NewBotDialog-dMWDs5xm.js +2 -0
  11. package/dist/assets/RemoteAgentSettingsPanel-B5KWXnqH.js +1 -0
  12. package/dist/assets/RoutinesPage-DOosRYDK.js +1 -0
  13. package/dist/assets/RoutinesSection-uOfOTfkB.js +1 -0
  14. package/dist/assets/SettingsModal-BTGkFbj1.js +11 -0
  15. package/dist/assets/TeamMapPage-DqNdJn96.js +8 -0
  16. package/dist/assets/TriggersPanel-c6xkG9mi.js +1 -0
  17. package/dist/assets/VisibilitySection-DD4ffIR5.js +12 -0
  18. package/dist/assets/WebhooksPanel-Cz17K-_O.js +3 -0
  19. package/dist/assets/{abnfDiagram-O67JEVCF-k1UCNXb7.js → abnfDiagram-O67JEVCF-CX6tDpkg.js} +1 -1
  20. package/dist/assets/activity-BAVWO0Zj.js +1 -0
  21. package/dist/assets/{arc-BUWGa9UU.js → arc-h45-9NFk.js} +1 -1
  22. package/dist/assets/architectureDiagram-NJMV4G6O-CgLFXbg6.js +36 -0
  23. package/dist/assets/{blockDiagram-BEXU5L5S-Ag9nLW4H.js → blockDiagram-BEXU5L5S-DGDFFc9M.js} +1 -1
  24. package/dist/assets/brain-CeCdoTb2.js +1 -0
  25. package/dist/assets/{c4Diagram-YGBWAQC7-Bh0sjgUa.js → c4Diagram-YGBWAQC7-B9aklAUj.js} +1 -1
  26. package/dist/assets/channel-TsOXCiPg.js +1 -0
  27. package/dist/assets/{chunk-2Q5K7J3B-BFBcIIqu.js → chunk-2Q5K7J3B-BC0KmWsM.js} +1 -1
  28. package/dist/assets/{chunk-3FUC2YCW-Dvfpex-f.js → chunk-3FUC2YCW-BbDFHsJ1.js} +2 -2
  29. package/dist/assets/{chunk-5VM5RSS4-CMjP2YZW.js → chunk-5VM5RSS4-DtGbsjOM.js} +1 -1
  30. package/dist/assets/{chunk-GTNCS2PH-BryoeTc7.js → chunk-GTNCS2PH-VMghMcEl.js} +1 -1
  31. package/dist/assets/{chunk-GWA4HPMP-BhfvcchO.js → chunk-GWA4HPMP-BP_JyGWQ.js} +1 -1
  32. package/dist/assets/{chunk-JWPE2WC7-bcCVp8rp.js → chunk-JWPE2WC7-CYFyzgAU.js} +1 -1
  33. package/dist/assets/{chunk-NETBCI7D-yKIjIlkQ.js → chunk-NETBCI7D-DBNa_kqm.js} +1 -1
  34. package/dist/assets/{chunk-WEXAMYUT-D3Zqbmup.js → chunk-WEXAMYUT-BKEeM7CJ.js} +1 -1
  35. package/dist/assets/{chunk-XXDRQBXY-CjVoIMG6.js → chunk-XXDRQBXY-C__m3ZXl.js} +1 -1
  36. package/dist/assets/{classDiagram-v2-NBCMYWYE-mUCWdVyH.js → classDiagram-v2-NBCMYWYE-CBUrTSAX.js} +1 -1
  37. package/dist/assets/computer-control-NLov352p.js +1 -0
  38. package/dist/assets/core-6lvx-ypA.js +12 -0
  39. package/dist/assets/cose-bilkent-JH36ORCC-GRfL-1Vb.js +1 -0
  40. package/dist/assets/cpp-DddhVWhK.js +1 -0
  41. package/dist/assets/{cynefin-OW5HDTMX-BpRrxoO4.js → cynefin-OW5HDTMX-LopwGUjm.js} +1 -1
  42. package/dist/assets/{cynefinDiagram-VND7K2PF-D3VBWCPK.js → cynefinDiagram-VND7K2PF-DSB8ZRNS.js} +1 -1
  43. package/dist/assets/{dagre-6A5THRUB-DxEIACOO.js → dagre-6A5THRUB-DL3Kgdfk.js} +1 -1
  44. package/dist/assets/{diagram-22UHCM2B-BANgZEOS.js → diagram-22UHCM2B-DIxN34BM.js} +1 -1
  45. package/dist/assets/{diagram-3UASUU5V-Cnq7nJir.js → diagram-3UASUU5V-CJnSvXaI.js} +1 -1
  46. package/dist/assets/{diagram-ATOU4E4O-4TBDIWnz.js → diagram-ATOU4E4O-C-XF-lO8.js} +1 -1
  47. package/dist/assets/{diagram-CDSNMT55-CD_B39D4.js → diagram-CDSNMT55-Df2yZPi_.js} +1 -1
  48. package/dist/assets/{diagram-MLGK6HIB-CzvnFhEC.js → diagram-MLGK6HIB-BBs9oZFs.js} +1 -1
  49. package/dist/assets/{diagram-MPIPVDR6-C4w2SNml.js → diagram-MPIPVDR6-CEbK11mM.js} +1 -1
  50. package/dist/assets/{ebnfDiagram-ZINNZB2B-gkUEBm2s.js → ebnfDiagram-ZINNZB2B-BNq6Yv3C.js} +1 -1
  51. package/dist/assets/{elk-276RUBZZ-B_56X6mw.js → elk-276RUBZZ-CFbQ2bGm.js} +1 -1
  52. package/dist/assets/engine-javascript-D5Xfc425.js +141 -0
  53. package/dist/assets/{erDiagram-OPXOYQCR-C_oByoDS.js → erDiagram-OPXOYQCR-Bz8vmjN4.js} +1 -1
  54. package/dist/assets/{flowDiagram-KWPJA3E3-CR9xXJkC.js → flowDiagram-KWPJA3E3-cQUfEYrx.js} +1 -1
  55. package/dist/assets/ganttDiagram-FUAMR5RP-BY8n9tbI.js +292 -0
  56. package/dist/assets/{gitGraphDiagram-X574FWY7-VJ6-Tp_p.js → gitGraphDiagram-X574FWY7-KduSOMDN.js} +1 -1
  57. package/dist/assets/image-plus-DNIWU160.js +1 -0
  58. package/dist/assets/index-C8xb62XS.js +585 -0
  59. package/dist/assets/index-DbN_Hfjs.css +1 -0
  60. package/dist/assets/{infoDiagram-VRGFBTTK-2Lu9te4D.js → infoDiagram-VRGFBTTK-xBKgUkpL.js} +1 -1
  61. package/dist/assets/{ishikawaDiagram-OU5B5YK6-DR49XY-e.js → ishikawaDiagram-OU5B5YK6-_ei09tAJ.js} +1 -1
  62. package/dist/assets/{journeyDiagram-ZHPQQLJL-ZoR0M305.js → journeyDiagram-ZHPQQLJL-Fp49MkSp.js} +1 -1
  63. package/dist/assets/{kanban-definition-PNTS6WVX-DLKHxrO-.js → kanban-definition-PNTS6WVX-CY9lLm7V.js} +1 -1
  64. package/dist/assets/{linear-BASsfWly.js → linear-D2ai4eM2.js} +1 -1
  65. package/dist/assets/{mermaid.core-BVidiPkk.js → mermaid.core-DP6qPqu1.js} +5 -5
  66. package/dist/assets/{mindmap-definition-NLK3R4M7-g_Qx0U5C.js → mindmap-definition-NLK3R4M7-g1ynEw_d.js} +1 -1
  67. package/dist/assets/module-DCUsy2BQ.js +3 -0
  68. package/dist/assets/page-visible-BZn8304W.js +1 -0
  69. package/dist/assets/{pegDiagram-GJSIUBJH-DI9Cjs8w.js → pegDiagram-GJSIUBJH-Bt4ObsZj.js} +1 -1
  70. package/dist/assets/{pieDiagram-5QR66LMP-sRI0Uhr5.js → pieDiagram-5QR66LMP-CeLld8bY.js} +1 -1
  71. package/dist/assets/{quadrantDiagram-O4NWA36T-CamKTby3.js → quadrantDiagram-O4NWA36T-D4WWZw3x.js} +1 -1
  72. package/dist/assets/{railroadDiagram-XR7U4H2S-DOLlkbf3.js → railroadDiagram-XR7U4H2S-D95P5NqU.js} +1 -1
  73. package/dist/assets/remote-desktop-panel-DOIMmT4T.js +1 -0
  74. package/dist/assets/{requirementDiagram-PLB6GJNP-DrRQ5r97.js → requirementDiagram-PLB6GJNP-D12p3RhR.js} +1 -1
  75. package/dist/assets/ruby-Ct1eTYOr.js +1 -0
  76. package/dist/assets/{sankeyDiagram-IPEJSGJF-DGS_lXcX.js → sankeyDiagram-IPEJSGJF-Co26Dwcs.js} +1 -1
  77. package/dist/assets/{sequenceDiagram-PO4LG4MO-CkjWqwtf.js → sequenceDiagram-PO4LG4MO-y5YxaDKt.js} +1 -1
  78. package/dist/assets/{sizeCapture-INFHLROL-CepRgful.js → sizeCapture-INFHLROL-D49hZ8U5.js} +1 -1
  79. package/dist/assets/{stateDiagram-v2-GCMORJYK-hykr-9RS.js → stateDiagram-v2-GCMORJYK-C0sylr-r.js} +1 -1
  80. package/dist/assets/{swimlanes-2SLR337P-CKOHEZbI.js → swimlanes-2SLR337P-DmRWsDIs.js} +1 -1
  81. package/dist/assets/swimlanesDiagram-TC7HE7FX-DzhbBHtd.js +8 -0
  82. package/dist/assets/table-file.worker-KkMx-SNx.js +10 -0
  83. package/dist/assets/{timeline-definition-EJHVYXUP-CB8pJ6AC.js → timeline-definition-EJHVYXUP-DVmHYs3w.js} +1 -1
  84. package/dist/assets/{usecaseDiagram-POWQR4AR-DrclJHdl.js → usecaseDiagram-POWQR4AR-BQ1q0VV6.js} +1 -1
  85. package/dist/assets/user-B9lohN4n.js +1 -0
  86. package/dist/assets/{vennDiagram-UO4OBE2U-zS23qjv8.js → vennDiagram-UO4OBE2U-C_cnfST0.js} +1 -1
  87. package/dist/assets/{wardleyDiagram-VNRHLVJA-52jgeKxz.js → wardleyDiagram-VNRHLVJA-Bb3BSu12.js} +1 -1
  88. package/dist/assets/{xychartDiagram-PMCCYNJV-DSdl9rQ8.js → xychartDiagram-PMCCYNJV-CcwEuuEi.js} +1 -1
  89. package/dist/index.html +2 -2
  90. package/dist-server/cloud-home-start.js +19 -8
  91. package/dist-server/container-mcp.js +8 -0
  92. package/dist-server/desktop-entry.mjs +54 -0
  93. package/dist-server/drivers/agents-proxy.js +30 -12
  94. package/dist-server/index.js +2745 -1487
  95. package/dist-server/openmausbot.js +1004 -642
  96. package/dist-server/pair-cli.js +1004 -642
  97. package/dist-server/permission-proxy.js +2 -0
  98. package/dist-server/server/activity.js +2 -0
  99. package/dist-server/server/atomic.js +70 -2
  100. package/dist-server/server/checkpoints.js +55 -39
  101. package/dist-server/server/cloud-home-start.js +3 -3
  102. package/dist-server/server/config.js +22 -1
  103. package/dist-server/server/connector-card-text.js +15 -0
  104. package/dist-server/server/default-model-selection.js +7 -4
  105. package/dist-server/server/direct-apply.js +20 -0
  106. package/dist-server/server/drivers/acp/core.js +10 -0
  107. package/dist-server/server/drivers/acp/grok.js +47 -5
  108. package/dist-server/server/drivers/agents-call.js +1 -1
  109. package/dist-server/server/drivers/agents-catalog.js +34 -11
  110. package/dist-server/server/drivers/agents-proxy.js +1 -0
  111. package/dist-server/server/drivers/chat-mcp-tools.js +5 -3
  112. package/dist-server/server/drivers/claude-login-auth.js +1 -1
  113. package/dist-server/server/drivers/claude.js +35 -11
  114. package/dist-server/server/drivers/codex-device-auth.js +27 -319
  115. package/dist-server/server/drivers/codex.js +147 -24
  116. package/dist-server/server/drivers/device-auth.js +343 -0
  117. package/dist-server/server/drivers/openai-chat.js +17 -8
  118. package/dist-server/server/fleet-agent.js +18 -5
  119. package/dist-server/server/harness/http.js +5 -2
  120. package/dist-server/server/harness/registry.js +82 -45
  121. package/dist-server/server/harness-capabilities.js +7 -4
  122. package/dist-server/server/hosted-models.js +3 -1
  123. package/dist-server/server/index.js +471 -77
  124. package/dist-server/server/key-rejections.js +57 -0
  125. package/dist-server/server/mcp-oauth.js +125 -47
  126. package/dist-server/server/message-file.js +102 -7
  127. package/dist-server/server/model-requests.js +55 -4
  128. package/dist-server/server/permission-proxy.js +4 -0
  129. package/dist-server/server/profile-requests.js +80 -4
  130. package/dist-server/server/provider-key-check.js +5 -1
  131. package/dist-server/server/request-auth.js +2 -1
  132. package/dist-server/server/room-turn-timeout.js +28 -0
  133. package/dist-server/server/routes/thread-models.js +36 -0
  134. package/dist-server/server/routes/undo.js +17 -0
  135. package/dist-server/server/routine-requests.js +210 -6
  136. package/dist-server/server/routines.js +2 -2
  137. package/dist-server/server/setup-mode.js +1 -1
  138. package/dist-server/server/skill-learn.js +2 -2
  139. package/dist-server/server/skills.js +33 -2
  140. package/dist-server/server/store.js +148 -60
  141. package/dist-server/server/system-prompt.js +1 -1
  142. package/dist-server/server/team-backup.js +19 -4
  143. package/dist-server/server/thread-model.js +25 -0
  144. package/dist-server/server/turn-continuation.js +17 -16
  145. package/dist-server/server/webhook-ingress.js +8 -3
  146. package/dist-server/server/webhooks.js +40 -5
  147. package/dist-server/server/workspace-backup.js +6 -1
  148. package/dist-server/shared/device-sign-in.js +57 -0
  149. package/dist-server/shared/team-backup.js +2 -0
  150. package/dist-server/shared/thread-model.js +13 -0
  151. package/dist-server/vps-container-mcp.js +8 -0
  152. package/dist-server/workspace-backup.worker.js +42 -23
  153. package/package.json +1 -1
  154. package/skills/create-verification-skill/SKILL.md +9 -8
  155. package/skills/create-verification-skill/manifest.json +1 -1
  156. package/dist/assets/DesktopViewer-CPidMCtt.js +0 -5
  157. package/dist/assets/abap-BdImnpbu.js +0 -1
  158. package/dist/assets/actionscript-3-B3316cI-.js +0 -1
  159. package/dist/assets/ada-bCR0ucgS.js +0 -1
  160. package/dist/assets/ahk-CsyLZFj1.js +0 -1
  161. package/dist/assets/ahk2-8Zs4aa1G.js +0 -1
  162. package/dist/assets/andromeeda-C4gqWexZ.js +0 -1
  163. package/dist/assets/angular-html-DA-rfuFy.js +0 -1
  164. package/dist/assets/angular-ts-BrjP3tb8.js +0 -1
  165. package/dist/assets/apache-Pmp26Uib.js +0 -1
  166. package/dist/assets/apex-DhZFqWV2.js +0 -1
  167. package/dist/assets/apl-CORt7UWP.js +0 -1
  168. package/dist/assets/applescript-Co6uUVPk.js +0 -1
  169. package/dist/assets/ara-BRHolxvo.js +0 -1
  170. package/dist/assets/architectureDiagram-NJMV4G6O-DiPor3UT.js +0 -36
  171. package/dist/assets/asciidoc-CSVQ5wI8.js +0 -1
  172. package/dist/assets/asm-D_Q5rh1f.js +0 -1
  173. package/dist/assets/astro-HNnZUWAn.js +0 -1
  174. package/dist/assets/aurora-x-D-2ljcwZ.js +0 -1
  175. package/dist/assets/awk-DMzUqQB5.js +0 -1
  176. package/dist/assets/ayu-dark-DYE7WIF3.js +0 -1
  177. package/dist/assets/ayu-light-BA47KaF1.js +0 -1
  178. package/dist/assets/ayu-mirage-32ctXXKs.js +0 -1
  179. package/dist/assets/ballerina-BFfxhgS-.js +0 -1
  180. package/dist/assets/bat-CickPsom.js +0 -1
  181. package/dist/assets/beancount-k_qm7-4y.js +0 -1
  182. package/dist/assets/berry-uYugtg8r.js +0 -1
  183. package/dist/assets/bibtex-CHM0blh-.js +0 -1
  184. package/dist/assets/bicep-Bmn6On1c.js +0 -1
  185. package/dist/assets/bird2-Bx8U0n9b.js +0 -1
  186. package/dist/assets/blade-2xfisSek.js +0 -1
  187. package/dist/assets/bsl-DlhNcFeZ.js +0 -1
  188. package/dist/assets/c3-Dp5svz6Z.js +0 -1
  189. package/dist/assets/cadence-Bv_4Rxtq.js +0 -1
  190. package/dist/assets/cairo-KRGpt6FW.js +0 -1
  191. package/dist/assets/catppuccin-frappe-CZL1YF0i.js +0 -1
  192. package/dist/assets/catppuccin-latte-DH-8KZSZ.js +0 -1
  193. package/dist/assets/catppuccin-macchiato-B7yYVSCf.js +0 -1
  194. package/dist/assets/catppuccin-mocha-Ct7hS0mc.js +0 -1
  195. package/dist/assets/channel-DR8eD6QW.js +0 -1
  196. package/dist/assets/chapel-DTp_pixX.js +0 -1
  197. package/dist/assets/clarity-Dn5IMItf.js +0 -1
  198. package/dist/assets/clojure-P80f7IUj.js +0 -1
  199. package/dist/assets/cmake-D1j8_8rp.js +0 -1
  200. package/dist/assets/cobol-nBiQ_Alo.js +0 -1
  201. package/dist/assets/codeowners-Bp6g37R7.js +0 -1
  202. package/dist/assets/codeql-DsOJ9woJ.js +0 -1
  203. package/dist/assets/coffee-Ch7k5sss.js +0 -1
  204. package/dist/assets/common-lisp-Cg-RD9OK.js +0 -1
  205. package/dist/assets/coq-C7JzOVbR.js +0 -1
  206. package/dist/assets/cose-bilkent-JH36ORCC-BBmR1bbX.js +0 -1
  207. package/dist/assets/cpp-BMRokrvK.js +0 -1
  208. package/dist/assets/crystal-DGywbUpC.js +0 -1
  209. package/dist/assets/csv-fuZLfV_i.js +0 -1
  210. package/dist/assets/cue-D82EKSYY.js +0 -1
  211. package/dist/assets/cypher-COkxafJQ.js +0 -1
  212. package/dist/assets/d-85-TOEBH.js +0 -1
  213. package/dist/assets/dark-plus-C3mMm8J8.js +0 -1
  214. package/dist/assets/dax-CEL-wOlO.js +0 -1
  215. package/dist/assets/desktop-BmXAJ9_W.js +0 -1
  216. package/dist/assets/dotenv-Da5cRb03.js +0 -1
  217. package/dist/assets/dracula-BzJJZx-M.js +0 -1
  218. package/dist/assets/dracula-soft-BXkSAIEj.js +0 -1
  219. package/dist/assets/dream-maker-BtqSS_iP.js +0 -1
  220. package/dist/assets/edge-FbVlp4U3.js +0 -1
  221. package/dist/assets/elixir-CkH2-t6x.js +0 -1
  222. package/dist/assets/elm-DbKCFpqz.js +0 -1
  223. package/dist/assets/emacs-lisp-C_m_b--Z.js +0 -1
  224. package/dist/assets/erb-DXfck5VN.js +0 -1
  225. package/dist/assets/erlang-DsQrWhSR.js +0 -1
  226. package/dist/assets/everforest-dark-BgDCqdQA.js +0 -1
  227. package/dist/assets/everforest-light-C8M2exoo.js +0 -1
  228. package/dist/assets/fennel-BYunw83y.js +0 -1
  229. package/dist/assets/fluent-C4IJs8-o.js +0 -1
  230. package/dist/assets/fortran-fixed-form-CkoXwp7k.js +0 -1
  231. package/dist/assets/fortran-free-form-BxgE0vQu.js +0 -1
  232. package/dist/assets/fsharp-CXgrBDvD.js +0 -1
  233. package/dist/assets/ganttDiagram-FUAMR5RP-gtYBTu0B.js +0 -292
  234. package/dist/assets/gdresource-TyuKm33G.js +0 -1
  235. package/dist/assets/gdscript-DqcFQ5yU.js +0 -1
  236. package/dist/assets/gdshader-DkwncUOv.js +0 -1
  237. package/dist/assets/genie-D0YGMca9.js +0 -1
  238. package/dist/assets/gherkin-DyxjwDmM.js +0 -1
  239. package/dist/assets/git-commit-F4YmCXRG.js +0 -1
  240. package/dist/assets/git-rebase-r7XF79zn.js +0 -1
  241. package/dist/assets/github-dark-DHJKELXO.js +0 -1
  242. package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +0 -1
  243. package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -1
  244. package/dist/assets/github-light-DAi9KRSo.js +0 -1
  245. package/dist/assets/github-light-high-contrast-BfjtVDDH.js +0 -1
  246. package/dist/assets/gleam-BspZqrRM.js +0 -1
  247. package/dist/assets/glimmer-js-ByusRIyA.js +0 -1
  248. package/dist/assets/glimmer-ts-BfAWNZQY.js +0 -1
  249. package/dist/assets/glsl-DplSGwfg.js +0 -1
  250. package/dist/assets/gn-n2N0HUVH.js +0 -1
  251. package/dist/assets/gnuplot-DdkO51Og.js +0 -1
  252. package/dist/assets/groovy-gcz8RCvz.js +0 -1
  253. package/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +0 -1
  254. package/dist/assets/gruvbox-dark-medium-GsRaNv29.js +0 -1
  255. package/dist/assets/gruvbox-dark-soft-CVdnzihN.js +0 -1
  256. package/dist/assets/gruvbox-light-hard-CH1njM8p.js +0 -1
  257. package/dist/assets/gruvbox-light-medium-DRw_LuNl.js +0 -1
  258. package/dist/assets/gruvbox-light-soft-hJgmCMqR.js +0 -1
  259. package/dist/assets/hack-BWmVpMyf.js +0 -1
  260. package/dist/assets/haml-D5jkg6IW.js +0 -1
  261. package/dist/assets/handlebars-BpdQsYii.js +0 -1
  262. package/dist/assets/haskell-Df6bDoY_.js +0 -1
  263. package/dist/assets/haxe-CfZj7gIn.js +0 -1
  264. package/dist/assets/hcl-BWvSN4gD.js +0 -1
  265. package/dist/assets/hjson-D5-asLiD.js +0 -1
  266. package/dist/assets/hlsl-D3lLCCz7.js +0 -1
  267. package/dist/assets/horizon-BUw7H-hv.js +0 -1
  268. package/dist/assets/horizon-bright-CUuTKBJd.js +0 -1
  269. package/dist/assets/houston-DnULxvSX.js +0 -1
  270. package/dist/assets/html-derivative-DlHx6ybY.js +0 -1
  271. package/dist/assets/http-jrhK8wxY.js +0 -1
  272. package/dist/assets/hurl-irOxFIW8.js +0 -1
  273. package/dist/assets/hxml-2-FPmUDs.js +0 -1
  274. package/dist/assets/hy-DFXneXwc.js +0 -1
  275. package/dist/assets/imba-DGztddWO.js +0 -1
  276. package/dist/assets/index-Cp4S4NOL.js +0 -153
  277. package/dist/assets/index-CpaIXRLp.js +0 -614
  278. package/dist/assets/index-Z81SMsgR.css +0 -1
  279. package/dist/assets/ini-BEwlwnbL.js +0 -1
  280. package/dist/assets/jinja-f2NsQr07.js +0 -1
  281. package/dist/assets/jison-wvAkD_A8.js +0 -1
  282. package/dist/assets/jsonl-DcaNXYhu.js +0 -1
  283. package/dist/assets/jsonnet-DFQXde-d.js +0 -1
  284. package/dist/assets/jssm-C2t-YnRu.js +0 -1
  285. package/dist/assets/julia-5Bft2YPA.js +0 -1
  286. package/dist/assets/just-Cwhn7H3k.js +0 -1
  287. package/dist/assets/kanagawa-dragon-BuwD2xS4.js +0 -1
  288. package/dist/assets/kanagawa-lotus-C3DzagqV.js +0 -1
  289. package/dist/assets/kanagawa-wave-DFGoQZhC.js +0 -1
  290. package/dist/assets/kdl-DV7GczEv.js +0 -1
  291. package/dist/assets/kusto-wEQ09or8.js +0 -1
  292. package/dist/assets/laserwave-DUszq2jm.js +0 -1
  293. package/dist/assets/latex-D5pSuvFb.js +0 -1
  294. package/dist/assets/lean-BZvkOJ9d.js +0 -1
  295. package/dist/assets/light-plus-B7mTdjB0.js +0 -1
  296. package/dist/assets/liquid-C0sCDyMI.js +0 -1
  297. package/dist/assets/llvm-BZoOZj88.js +0 -1
  298. package/dist/assets/log-2UxHyX5q.js +0 -1
  299. package/dist/assets/logo-BtOb2qkB.js +0 -1
  300. package/dist/assets/luau-BnpPk5vE.js +0 -1
  301. package/dist/assets/marko-DjSrsDqO.js +0 -1
  302. package/dist/assets/material-theme-D5KoaKCx.js +0 -1
  303. package/dist/assets/material-theme-darker-BfHTSMKl.js +0 -1
  304. package/dist/assets/material-theme-lighter-B0m2ddpp.js +0 -1
  305. package/dist/assets/material-theme-ocean-CyktbL80.js +0 -1
  306. package/dist/assets/material-theme-palenight-Csfq5Kiy.js +0 -1
  307. package/dist/assets/matlab-D7o27uSR.js +0 -1
  308. package/dist/assets/mdc-D1_yUvq7.js +0 -1
  309. package/dist/assets/mermaid-CQcHuHx7.js +0 -1
  310. package/dist/assets/min-dark-CafNBF8u.js +0 -1
  311. package/dist/assets/min-light-CTRr51gU.js +0 -1
  312. package/dist/assets/mipsasm-CKIfxQSi.js +0 -1
  313. package/dist/assets/mojo-DJz3ZmWd.js +0 -1
  314. package/dist/assets/monokai-BRVnQi9A.js +0 -1
  315. package/dist/assets/moonbit-CHtswR0a.js +0 -1
  316. package/dist/assets/move-el3G9tDJ.js +0 -1
  317. package/dist/assets/narrat-DRg8JJMk.js +0 -1
  318. package/dist/assets/nextflow-C-mBbutL.js +0 -1
  319. package/dist/assets/nextflow-groovy-vE_lwT2v.js +0 -1
  320. package/dist/assets/nginx-BpAMiNFr.js +0 -1
  321. package/dist/assets/night-owl-C39BiMTA.js +0 -1
  322. package/dist/assets/night-owl-light-CMTm3GFP.js +0 -1
  323. package/dist/assets/nim-BIad80T-.js +0 -1
  324. package/dist/assets/nix-CwoSXNpI.js +0 -1
  325. package/dist/assets/nord-Ddv68eIx.js +0 -1
  326. package/dist/assets/nsis-BlV79W_Q.js +0 -1
  327. package/dist/assets/nushell-D3jzshHO.js +0 -1
  328. package/dist/assets/objective-c-DXmwc3jG.js +0 -1
  329. package/dist/assets/objective-cpp-CLxacb5B.js +0 -1
  330. package/dist/assets/ocaml-C0hk2d4L.js +0 -1
  331. package/dist/assets/odin-BBf5iR-q.js +0 -1
  332. package/dist/assets/one-dark-pro-DVMEJ2y_.js +0 -1
  333. package/dist/assets/one-light-C3Wv6jpd.js +0 -1
  334. package/dist/assets/openscad-C4EeE6gA.js +0 -1
  335. package/dist/assets/org-DM6o9KBp.js +0 -1
  336. package/dist/assets/pascal-D93ZcfNL.js +0 -1
  337. package/dist/assets/perl-B9cMNwum.js +0 -1
  338. package/dist/assets/pkl-u5AG7uiY.js +0 -1
  339. package/dist/assets/plastic-3e1v2bzS.js +0 -1
  340. package/dist/assets/plsql-ChMvpjG-.js +0 -1
  341. package/dist/assets/po-BTJTHyun.js +0 -1
  342. package/dist/assets/poimandres-CS3Unz2-.js +0 -1
  343. package/dist/assets/polar-C0HS_06l.js +0 -1
  344. package/dist/assets/postcss-CXtECtnM.js +0 -1
  345. package/dist/assets/powerquery-CEu0bR-o.js +0 -1
  346. package/dist/assets/prisma-Vru482bI.js +0 -1
  347. package/dist/assets/prolog-CbFg5uaA.js +0 -1
  348. package/dist/assets/pug-DKIMFp6K.js +0 -1
  349. package/dist/assets/puppet-BMWR74SV.js +0 -1
  350. package/dist/assets/purescript-CklMAg4u.js +0 -1
  351. package/dist/assets/qml-3beO22l8.js +0 -1
  352. package/dist/assets/qmldir-C8lEn-DE.js +0 -1
  353. package/dist/assets/qss-IeuSbFQv.js +0 -1
  354. package/dist/assets/racket-BqYA7rlc.js +0 -1
  355. package/dist/assets/raku-DXvB9xmW.js +0 -1
  356. package/dist/assets/razor-BjBPvh-w.js +0 -1
  357. package/dist/assets/rbs-CpoqiR4B.js +0 -1
  358. package/dist/assets/red-hvxz__6c.js +0 -1
  359. package/dist/assets/reg-C-SQnVFl.js +0 -1
  360. package/dist/assets/regexp-CDVJQ6XC.js +0 -1
  361. package/dist/assets/rel-C3B-1QV4.js +0 -1
  362. package/dist/assets/riscv-BM1_JUlF.js +0 -1
  363. package/dist/assets/ron-D8l8udqQ.js +0 -1
  364. package/dist/assets/rose-pine-5qJOZa0Y.js +0 -1
  365. package/dist/assets/rose-pine-dawn-zx0QlTCp.js +0 -1
  366. package/dist/assets/rose-pine-moon-C9pEdX9L.js +0 -1
  367. package/dist/assets/rosmsg-BJDFO7_C.js +0 -1
  368. package/dist/assets/rst-bs7f0vWN.js +0 -1
  369. package/dist/assets/ruby-C0TQ7zu5.js +0 -1
  370. package/dist/assets/sas-DEy46yEz.js +0 -1
  371. package/dist/assets/scala-CqE71os6.js +0 -1
  372. package/dist/assets/scheme-C98Dy4si.js +0 -1
  373. package/dist/assets/sdbl-DVxCFoDh.js +0 -1
  374. package/dist/assets/shaderlab-Dg9Lc6iA.js +0 -1
  375. package/dist/assets/shellsession-BADoaaVG.js +0 -1
  376. package/dist/assets/slack-dark-BthQWCQV.js +0 -1
  377. package/dist/assets/slack-ochin-DqwNpetd.js +0 -1
  378. package/dist/assets/smalltalk-BOQMe2GC.js +0 -1
  379. package/dist/assets/smithy-cds9vsN8.js +0 -1
  380. package/dist/assets/snazzy-light-Bw305WKR.js +0 -1
  381. package/dist/assets/solarized-dark-CpvCGNkr.js +0 -1
  382. package/dist/assets/solarized-light-Dlz6yCKv.js +0 -1
  383. package/dist/assets/solidity-DijEV5ha.js +0 -1
  384. package/dist/assets/soy-8wufbnw4.js +0 -1
  385. package/dist/assets/sparql-rVzFXLq3.js +0 -1
  386. package/dist/assets/splunk-BtCnVYZw.js +0 -1
  387. package/dist/assets/ssh-config-_ykCGR6B.js +0 -1
  388. package/dist/assets/stata-DI20mbqo.js +0 -1
  389. package/dist/assets/stylus-BEDo0Tqx.js +0 -1
  390. package/dist/assets/surrealql-Cjom0U5J.js +0 -1
  391. package/dist/assets/svelte-Cy7k_4gC.js +0 -1
  392. package/dist/assets/swimlanesDiagram-TC7HE7FX-D-8vqZ4-.js +0 -8
  393. package/dist/assets/synthwave-84-CbfX1IO0.js +0 -1
  394. package/dist/assets/system-verilog-0hqHdDBg.js +0 -1
  395. package/dist/assets/systemd-4A_iFExJ.js +0 -1
  396. package/dist/assets/talonscript-CkByrt1z.js +0 -1
  397. package/dist/assets/tasl-QIJgUcNo.js +0 -1
  398. package/dist/assets/tcl-dwOrl1Do.js +0 -1
  399. package/dist/assets/templ-DhtptRzy.js +0 -1
  400. package/dist/assets/terraform-BETggiCN.js +0 -1
  401. package/dist/assets/tex-D96PA37w.js +0 -1
  402. package/dist/assets/tokyo-night-hegEt444.js +0 -1
  403. package/dist/assets/ts-tags-D351s5mN.js +0 -1
  404. package/dist/assets/tsv-B_m7g4N7.js +0 -1
  405. package/dist/assets/turtle-BsS91CYL.js +0 -1
  406. package/dist/assets/twig-27uCiNez.js +0 -1
  407. package/dist/assets/typespec-CAFt9gP4.js +0 -1
  408. package/dist/assets/typst-BUadGCkm.js +0 -1
  409. package/dist/assets/v-BGw2Nkan.js +0 -1
  410. package/dist/assets/vala-CsfeWuGM.js +0 -1
  411. package/dist/assets/vb-Cu-pLBUe.js +0 -1
  412. package/dist/assets/verilog-nZwndyjY.js +0 -1
  413. package/dist/assets/vesper-DRje8inN.js +0 -1
  414. package/dist/assets/vhdl-CeAyd5Ju.js +0 -1
  415. package/dist/assets/viml-CJc9bBzg.js +0 -1
  416. package/dist/assets/vitesse-black-Bkuqu6BP.js +0 -1
  417. package/dist/assets/vitesse-dark-D0r3Knsf.js +0 -1
  418. package/dist/assets/vitesse-light-CVO1_9PV.js +0 -1
  419. package/dist/assets/vue-BqiEGhQt.js +0 -1
  420. package/dist/assets/vue-html-AaS7Mt5G.js +0 -1
  421. package/dist/assets/vue-vine-BoDAl6tE.js +0 -1
  422. package/dist/assets/vyper-CDx5xZoG.js +0 -1
  423. package/dist/assets/wasm-CG6Dc4jp.js +0 -1
  424. package/dist/assets/wenyan-BV7otONQ.js +0 -1
  425. package/dist/assets/wgsl-Dx-B1_4e.js +0 -1
  426. package/dist/assets/wikitext-BhOHFoWU.js +0 -1
  427. package/dist/assets/wit-5i3qLPDT.js +0 -1
  428. package/dist/assets/wolfram-lXgVvXCa.js +0 -1
  429. package/dist/assets/xsl-CtQFsRM5.js +0 -1
  430. package/dist/assets/zenscript-DVFEvuxE.js +0 -1
  431. package/dist/assets/zig-VOosw3JB.js +0 -1
  432. /package/dist/assets/{shellscript-Yzrsuije.js → bash-Yzrsuije.js} +0 -0
  433. /package/dist/assets/{docker-BcOcwvcX.js → dockerfile-BcOcwvcX.js} +0 -0
  434. /package/dist/assets/{make-CHLpvVh8.js → makefile-CHLpvVh8.js} +0 -0
@@ -157,6 +157,7 @@ var allowQuestion = allowsTool(selection.scope, { kind: "mcp", server: "ogb", na
157
157
  var socketPath = process.argv[2] ?? "";
158
158
  var waiting = /* @__PURE__ */ new Map();
159
159
  var conn = connect(socketPath);
160
+ conn.setEncoding("utf8");
160
161
  var dead = () => {
161
162
  for (const resolve of waiting.values()) {
162
163
  resolve({ behavior: "deny", message: "OpenMausBot: permission broker unavailable \u2014 skip this action" });
@@ -295,6 +296,7 @@ async function handle(msg) {
295
296
  }
296
297
  }
297
298
  var inBuf = "";
299
+ process.stdin.setEncoding("utf8");
298
300
  process.stdin.on("data", (chunk) => {
299
301
  inBuf += chunk;
300
302
  let nl;
@@ -103,6 +103,8 @@ const OUTCOME_OF_DECISION = {
103
103
  "user-approved": "allowed",
104
104
  "review-would-approve": "allowed",
105
105
  "user-denied": "denied",
106
+ // A person reverted a change that had applied on its own.
107
+ "user-undone": "denied",
106
108
  "review-would-deny": "denied",
107
109
  "card-shown": "waiting",
108
110
  };
@@ -4,8 +4,15 @@
4
4
  // reader always sees either the complete old contents or the complete new
5
5
  // ones. Without this, an interrupted writeFileSync produces half-written JSON
6
6
  // that fails to parse on next boot and is silently treated as empty state.
7
+ //
8
+ // The fsync is the expensive part: on macOS it is F_FULLFSYNC, about 4 ms of
9
+ // blocked event loop per call. `durable: false` drops only the fsync, for
10
+ // files whose loss after a power cut costs nothing (a derived cache, a
11
+ // session-scoped token). The temp file and rename stay, so an app crash or
12
+ // kill -9 still never leaves a torn file; only a power loss or kernel panic
13
+ // can leave such a file empty.
7
14
  import { randomUUID } from "node:crypto";
8
- import { closeSync, fsyncSync, openSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
15
+ import { closeSync, constants, fstatSync, fsyncSync, lstatSync, openSync, readFileSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
9
16
  /** Windows refuses a rename onto an existing path while anything else holds a
10
17
  * handle to either file, and a virus scanner or the search indexer opening a
11
18
  * just-closed file for a few milliseconds is enough. It surfaces as EPERM or
@@ -51,7 +58,8 @@ export function writeFileAtomic(path, data, options = {}) {
51
58
  // config file visible between the write and a later chmod.
52
59
  fd = openSync(tmp, "w", options.mode);
53
60
  writeFileSync(fd, data);
54
- fsyncSync(fd);
61
+ if (options.durable !== false)
62
+ fsyncSync(fd);
55
63
  closeSync(fd);
56
64
  fd = null;
57
65
  renameWithRetry(tmp, path);
@@ -74,3 +82,63 @@ export function writeFileAtomic(path, data, options = {}) {
74
82
  throw e;
75
83
  }
76
84
  }
85
+ /** True only when `path` is already exactly `data`: a regular file (never a
86
+ * symlink, FIFO or directory), owned by this user, with permissions no
87
+ * broader than `mode`. Any doubt or error answers false, so the caller falls
88
+ * back to a full write — this check must never be the reason a save fails.
89
+ *
90
+ * It reads the file on disk rather than remembering the last write: a
91
+ * workspace restore or a hand edit can change the file underneath, and the
92
+ * next save has to put its own bytes back exactly as before. */
93
+ function holdsExactly(path, data, mode) {
94
+ let fd = null;
95
+ try {
96
+ if (process.platform === "win32") {
97
+ // No O_NOFOLLOW on Windows; a reparse point is replaced, not read.
98
+ if (!lstatSync(path).isFile())
99
+ return false;
100
+ fd = openSync(path, "r");
101
+ }
102
+ else {
103
+ // Inspect and read the same inode the open landed on, so a swap
104
+ // between a stat and the read cannot be mistaken for a match.
105
+ // O_NONBLOCK keeps a FIFO planted at the path from hanging the open.
106
+ fd = openSync(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
107
+ }
108
+ const stat = fstatSync(fd);
109
+ if (!stat.isFile() || stat.size !== Buffer.byteLength(data))
110
+ return false;
111
+ const uid = process.getuid?.();
112
+ if (uid !== undefined && stat.uid !== uid)
113
+ return false;
114
+ // Windows reports 0o666 for any writable file; its mode bits mean nothing.
115
+ if (mode !== undefined && process.platform !== "win32" && (stat.mode & 0o777 & ~mode) !== 0)
116
+ return false;
117
+ // Bytes, not strings: decoding and comparing a megabyte-sized registry as
118
+ // a JS string costs several times more than a memcmp of the raw bytes.
119
+ return readFileSync(fd).equals(Buffer.from(data));
120
+ }
121
+ catch {
122
+ return false;
123
+ }
124
+ finally {
125
+ if (fd !== null) {
126
+ try {
127
+ closeSync(fd);
128
+ }
129
+ catch {
130
+ /* best-effort cleanup */
131
+ }
132
+ }
133
+ }
134
+ }
135
+ /** writeFileAtomic for saves that often repeat what the file already holds.
136
+ * A save that changes nothing costs one open and read instead of a temp
137
+ * file, a rename and an fsync; a save whose size differs pays only an
138
+ * open and fstat before the normal write. Returns whether it wrote. */
139
+ export function writeFileAtomicIfChanged(path, data, options = {}) {
140
+ if (holdsExactly(path, data, options.mode))
141
+ return false;
142
+ writeFileAtomic(path, data, options);
143
+ return true;
144
+ }
@@ -246,33 +246,25 @@ function gitFailure(command, err, stderr, signal) {
246
246
  }
247
247
  /** Run one git command against the shadow repo. cwd is the WORK TREE — the
248
248
  * "." pathspec in add resolves relative to it. Every call carries the
249
- * GIT_TIMEOUT_MS hard timeout. */
250
- function runGit(args, cwd, env, signal) {
249
+ * GIT_TIMEOUT_MS hard timeout. `input` is written to git's stdin.
250
+ * Each call is a process start, which costs tens of milliseconds on Windows,
251
+ * and the turn waits for its snapshot — so a snapshot keeps its calls few
252
+ * (see commitAll). */
253
+ function runGit(args, cwd, env, signal, input) {
251
254
  return new Promise((resolvePromise, rejectPromise) => {
252
255
  signal?.throwIfAborted();
253
- execFile("git", args, { cwd, env, signal, windowsHide: true, encoding: "utf8", timeout: GIT_TIMEOUT_MS, maxBuffer: 16 * 1024 * 1024 }, (err, stdout, stderr) => {
256
+ const child = execFile("git", args, { cwd, env, signal, windowsHide: true, encoding: "utf8", timeout: GIT_TIMEOUT_MS, maxBuffer: 16 * 1024 * 1024 }, (err, stdout, stderr) => {
254
257
  if (err)
255
258
  rejectPromise(gitFailure(args[0], err, stderr, signal));
256
259
  else
257
260
  resolvePromise(stdout);
258
261
  });
259
- });
260
- }
261
- /** `git diff --cached --quiet`: is there anything staged beyond HEAD? Used
262
- * instead of `status --porcelain` emptiness on purpose — a nested repo with
263
- * a dirty work tree shows up in status forever while staging nothing, which
264
- * would either commit empty churn every turn or fail the commit outright. */
265
- function hasStagedChanges(cwd, env, signal) {
266
- return new Promise((resolvePromise, rejectPromise) => {
267
- signal?.throwIfAborted();
268
- execFile("git", ["diff", "--cached", "--quiet", "--ignore-submodules=dirty"], { cwd, env, signal, windowsHide: true, encoding: "utf8", timeout: GIT_TIMEOUT_MS, maxBuffer: 16 * 1024 * 1024 }, (err, _stdout, stderr) => {
269
- if (err === null)
270
- resolvePromise(false);
271
- else if (err.code === 1)
272
- resolvePromise(true);
273
- else
274
- rejectPromise(gitFailure("diff", err, stderr, signal));
275
- });
262
+ if (input !== undefined) {
263
+ // A git that exits before reading reports through its exit status; a
264
+ // broken pipe here must not become an unhandled stream error.
265
+ child.stdin?.on("error", () => { });
266
+ child.stdin?.end(input);
267
+ }
276
268
  });
277
269
  }
278
270
  // One operation at a time per shadow repo: snapshots, diffs and pin releases
@@ -312,6 +304,20 @@ async function sweepLiveRefs(cwd, env, shadow, signal) {
312
304
  droppedPins.add(shadow);
313
305
  sweptShadows.add(shadow);
314
306
  }
307
+ /** One git call, however long the history: HEAD and at most its parent. */
308
+ async function readHead(cwd, env, signal) {
309
+ const out = await runGit(["log", "-2", "--format=%H %T %P", "HEAD"], cwd, env, signal);
310
+ const [head, parent] = out.split("\n").filter(Boolean).map((line) => line.trim().split(" "));
311
+ const [hash, tree, ...parents] = head ?? [];
312
+ if (!hash || !tree)
313
+ throw new Error(`git log: unexpected output ${JSON.stringify(out.slice(0, 200))}`);
314
+ let base = null;
315
+ if (parents.length === 0)
316
+ base = hash;
317
+ else if (parents.length === 1 && parent?.length === 2)
318
+ base = parents[0];
319
+ return { hash, tree, base };
320
+ }
315
321
  /** Create the shadow repo on first use; self-heal its config files on every
316
322
  * use (they are tiny, and rewriting them lets exclude-list updates reach
317
323
  * shadows that already exist). The base commit is an EMPTY marker so HEAD
@@ -349,14 +355,17 @@ async function ensureShadow(cwd, env, shadow, signal) {
349
355
  }
350
356
  }
351
357
  writeFileSync(join(shadow, ".git", "info", "exclude"), EXCLUDES + [...cachePatterns].join("\n") + "\n");
358
+ let head;
352
359
  try {
353
- await runGit(["rev-parse", "--verify", "HEAD"], cwd, env, signal);
360
+ head = await readHead(cwd, env, signal);
354
361
  }
355
362
  catch {
356
363
  // brand-new repo (or a crash between init and first commit)
357
364
  await runGit(["commit", "--no-verify", "--allow-empty", "-m", "checkpoint base"], cwd, env, signal);
365
+ head = await readHead(cwd, env, signal);
358
366
  }
359
367
  await sweepLiveRefs(cwd, env, shadow, signal);
368
+ return head;
360
369
  }
361
370
  /** Folder listings in flight at once (libuv's pool has four threads). */
362
371
  const LISTING_CONCURRENCY = 4;
@@ -469,9 +478,11 @@ async function stageWorkTree(cwd, env, signal) {
469
478
  }
470
479
  /** Capture fully before advancing HEAD: null when the add was partial, so a
471
480
  * partial capture never replaces the last usable checkpoint or authorizes
472
- * removal of its objects. */
473
- async function commitAll(cwd, env, label, signal) {
474
- const previous = (await runGit(["rev-parse", "HEAD"], cwd, env, signal)).trim();
481
+ * removal of its objects. With `pin`, the turn's pin lands on the returned
482
+ * commit in the same ref transaction that moves HEAD.
483
+ * A changed folder costs the shadow `write-tree`, `commit-tree` and one
484
+ * `update-ref` past staging; an unchanged one, `write-tree` alone. */
485
+ async function commitAll(cwd, env, head, label, pin, signal) {
475
486
  try {
476
487
  await stageWorkTree(cwd, env, signal);
477
488
  }
@@ -481,18 +492,25 @@ async function commitAll(cwd, env, label, signal) {
481
492
  throw e;
482
493
  return null;
483
494
  }
484
- const changed = await hasStagedChanges(cwd, env, signal);
485
- const base = (await runGit(["rev-list", "--max-parents=0", "HEAD"], cwd, env, signal)).trim();
486
- const count = (await runGit(["rev-list", "--count", "HEAD"], cwd, env, signal)).trim();
487
- if (!changed && Number(count) <= 2)
488
- return { hash: previous, advanced: false, compacted: false };
495
+ // Is anything staged beyond HEAD? The staged tree is HEAD's tree exactly
496
+ // when nothing is. Only what is staged counts, never work-tree status: a
497
+ // nested repo with a dirty work tree stages nothing (its gitlink is
498
+ // unchanged), so it neither commits empty churn every turn nor fails.
489
499
  const tree = (await runGit(["write-tree"], cwd, env, signal)).trim();
490
- const message = changed ? label : (await runGit(["show", "-s", "--format=%B", "HEAD"], cwd, env, signal)).trim();
491
- // Parent only the empty marker, never the previous snapshot: keeping the
492
- // previous commit as an ancestor would retain every old tree indefinitely.
493
- const hash = (await runGit(["commit-tree", tree, "-p", base, "-m", message], cwd, env, signal)).trim();
494
- await runGit(["update-ref", "HEAD", hash, previous], cwd, env, signal);
495
- return { hash, advanced: true, compacted: Number(count) > 2 };
500
+ const changed = tree !== head.tree;
501
+ let hash = head.hash;
502
+ if (changed || head.base === null) {
503
+ const base = head.base ?? (await runGit(["rev-list", "--max-parents=0", "HEAD"], cwd, env, signal)).trim();
504
+ const message = changed ? label : (await runGit(["show", "-s", "--format=%B", "HEAD"], cwd, env, signal)).trim();
505
+ // Parent only the empty marker, never the previous snapshot: keeping the
506
+ // previous commit as an ancestor would retain every old tree indefinitely.
507
+ hash = (await runGit(["commit-tree", tree, "-p", base, "-m", message], cwd, env, signal)).trim();
508
+ }
509
+ const advanced = hash !== head.hash;
510
+ const updates = [advanced ? `update HEAD ${hash} ${head.hash}\n` : "", pin ? `update ${liveRef(pin)} ${hash}\n` : ""].join("");
511
+ if (updates !== "")
512
+ await runGit(["update-ref", "--stdin"], cwd, env, signal, updates);
513
+ return { hash, advanced, compacted: advanced && head.base === null };
496
514
  }
497
515
  /** HEAD-advancing snapshots per shadow since this process last collected. */
498
516
  const commitsSinceGc = new Map();
@@ -582,12 +600,10 @@ export async function snapshot(botId, cwd, label, signal, opts) {
582
600
  releaseCollection(shadow);
583
601
  return await serialize(shadow, async () => {
584
602
  const env = gitEnv(shadow, worktree);
585
- await ensureShadow(worktree, env, shadow, signal);
586
- const result = await commitAll(worktree, env, label, signal);
603
+ const head = await ensureShadow(worktree, env, shadow, signal);
604
+ const result = await commitAll(worktree, env, head, label, opts?.pin, signal);
587
605
  if (!result)
588
606
  return null;
589
- if (opts?.pin)
590
- await runGit(["update-ref", liveRef(opts.pin), result.hash], worktree, env, signal);
591
607
  // Never awaited by the turn waiting on this snapshot, and held for that
592
608
  // turn's settled diff: diffWorkingTree queues it behind itself, so GC
593
609
  // never eats into the digest's capture window.
@@ -1,4 +1,4 @@
1
- // Entry point of the OMB Cloud Pro home image (deploy/fly/Dockerfile).
1
+ // Entry point of the OMB Cloud Pro home image (the Dockerfile's cloud-home target).
2
2
  //
3
3
  // Starts as root, hands a fresh Fly volume (mounted root-owned at /data) to
4
4
  // the unprivileged `maus` user, and stays a small root supervisor of two
@@ -77,7 +77,7 @@ export function cloudHomeChildEnvironments(config, env, home) {
77
77
  /** Why the root supervisor must not run or trust `files`, or null: each
78
78
  * must be root's and not writable by anyone else (nor any folder above it),
79
79
  * and none may live on the volume `home`, which `maus` owns. The image makes its code
80
- * root's (deploy/fly/Dockerfile); a file `maus` could rewrite would run as
80
+ * root's (the Dockerfile's cloud-home target); a file `maus` could rewrite would run as
81
81
  * root at the next start, or be handed the secrets. */
82
82
  export function codeTrustProblem(files, home, stat = statSync) {
83
83
  const volume = posix.join(home, "/");
@@ -155,7 +155,7 @@ export function startCloudHome(env = process.env) {
155
155
  if (ids) {
156
156
  const problem = codeTrustProblem([process.execPath, fileURLToPath(import.meta.url), join(here, "index.js"), edgeBin, edgeConfig], home);
157
157
  if (problem)
158
- throw new Error(`This image's code is not safe to run as root: ${problem}. Rebuild it from deploy/fly/Dockerfile.`);
158
+ throw new Error(`This image's code is not safe to run as root: ${problem}. Rebuild it with docker build --target cloud-home.`);
159
159
  }
160
160
  const { server, edge, secrets, dropped } = cloudHomeChildEnvironments(config, env, home);
161
161
  // Names only, never values: what the server does not get from here.
@@ -24,6 +24,13 @@ export const FISH_TTS_MODELS = ["s2.1-pro", "s2.1-pro-free"];
24
24
  export const DEFAULT_ROOM_TURN_TIMEOUT_MINUTES = 5;
25
25
  export const MIN_ROOM_TURN_TIMEOUT_MINUTES = 1;
26
26
  export const MAX_ROOM_TURN_TIMEOUT_MINUTES = 1_440;
27
+ /** Per-call ceiling for a bot's MCP tools (tools/call on the chat MCP
28
+ * transport). 10 minutes matches the historic constant in
29
+ * chat-mcp-tools.ts; a single tool call that runs longer is cut at this
30
+ * deadline because its execution outcome can no longer be trusted. */
31
+ export const DEFAULT_MCP_CALL_TIMEOUT_MINUTES = 10;
32
+ export const MIN_MCP_CALL_TIMEOUT_MINUTES = 1;
33
+ export const MAX_MCP_CALL_TIMEOUT_MINUTES = 60;
27
34
  export const DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES = 30;
28
35
  export const DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES = 10;
29
36
  export const DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES = 240;
@@ -105,6 +112,16 @@ const roomConfigSchema = z.object({
105
112
  (rooms.handoffLifetimeMinutes ?? DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES) &&
106
113
  (rooms.handoffLifetimeMinutes ?? DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES) <=
107
114
  (rooms.handoffHardCapMinutes ?? DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES), { message: "rooms handoff bounds must satisfy handoffMinRunwayMinutes <= handoffLifetimeMinutes <= handoffHardCapMinutes" });
115
+ const mcpConfigSchema = z.object({
116
+ /** Ceiling (minutes) for one bot MCP tool call. Missing values resolve to
117
+ * 10, preserving the historic chat-mcp-tools constant. */
118
+ callTimeoutMinutes: z
119
+ .number()
120
+ .int()
121
+ .min(MIN_MCP_CALL_TIMEOUT_MINUTES)
122
+ .max(MAX_MCP_CALL_TIMEOUT_MINUTES)
123
+ .optional(),
124
+ }).strict();
108
125
  /** Isolation for bot desktops. Migration note (issue #1654): switching
109
126
  * modes changes lease keys and vm-home directories, so desktops cold-start
110
127
  * under the new mode — a pool seat lives in vm-homes/pool-N — while the old
@@ -503,6 +520,7 @@ const appConfigSchema = z.object({
503
520
  * system language. Unknown tags degrade to English in the renderer. */
504
521
  language: optionalText,
505
522
  rooms: roomConfigSchema.optional(),
523
+ mcp: mcpConfigSchema.optional(),
506
524
  context: z.object({
507
525
  rebuildBytes: z.number().int().min(1_024).max(1_000_000).optional(),
508
526
  compactAt: z.number().positive().max(10_000_000).optional(),
@@ -635,6 +653,9 @@ export function browserEngineAttachCdpUrl(cfg) {
635
653
  export function roomTurnTimeoutMinutes(cfg) {
636
654
  return cfg.rooms?.turnTimeoutMinutes ?? DEFAULT_ROOM_TURN_TIMEOUT_MINUTES;
637
655
  }
656
+ export function mcpCallTimeoutMinutes(cfg) {
657
+ return cfg.mcp?.callTimeoutMinutes ?? DEFAULT_MCP_CALL_TIMEOUT_MINUTES;
658
+ }
638
659
  export const LIVE_IDLE_MINUTES_DEFAULT = 5;
639
660
  /** Non-secret Live settings. The key only shows up as `configured`. */
640
661
  export function liveSettingsFor(cfg) {
@@ -1204,7 +1225,7 @@ export function saveConfig(patch, options = {}) {
1204
1225
  const storedProfiles = storedBrowserProfilesSchema.safeParse(disk.browserProfiles);
1205
1226
  if (storedProfiles.success)
1206
1227
  disk.browserProfiles = storedProfiles.data;
1207
- for (const key of ["xai", "anthropic", "mistral", "cerebras", "openai", "openrouter", "openaiCompat", "composio", "box", "opencodeGo", "tts", "decider", "imageGen", "live", "profile", "rooms", "threads", "context", "memory", "localVm", "features", "budgets", "billing", "decisions", "onboarding", "browserEngine", "newBots"]) {
1228
+ for (const key of ["xai", "anthropic", "mistral", "cerebras", "openai", "openrouter", "openaiCompat", "composio", "box", "opencodeGo", "tts", "decider", "imageGen", "live", "profile", "rooms", "mcp", "threads", "context", "memory", "localVm", "features", "budgets", "billing", "decisions", "onboarding", "browserEngine", "newBots"]) {
1208
1229
  const section = checkedPatch[key];
1209
1230
  if (!section)
1210
1231
  continue;
@@ -0,0 +1,15 @@
1
+ // The plain line a connection card carries beside its `connector` payload.
2
+ //
3
+ // Desktop and current phones draw `kind: "connector"` as a card and never
4
+ // read this. It exists for clients that do not know the kind yet — phone
5
+ // builds from before the in-chat card shipped decode it as "unknown" and draw
6
+ // whatever `text` a message has, so without it they showed nothing at all
7
+ // while the bot sat waiting for a connection. Exports and backups read it too.
8
+ // It names the app and points at the card; it never carries a link, because
9
+ // the authorization URL is only ever handed to the person's own client.
10
+ /** "Connect GitHub to continue." — or, for a second account, the alias too. */
11
+ export function connectorCardText(label, alias) {
12
+ const app = label.replace(/\s+/g, " ").trim() || "this app";
13
+ const account = alias?.replace(/\s+/g, " ").trim();
14
+ return account ? `Connect ${app} as “${account}” to continue.` : `Connect ${app} to continue.`;
15
+ }
@@ -1,10 +1,13 @@
1
1
  const claudeFirst = (instances) => instances.find((instance) => instance.driverKind === "claudeAgent") ?? instances[0];
2
+ /** Installed and waiting on a sign-in. A custom endpoint brings its own
3
+ * credential, so its sign-in state does not count. */
4
+ export function signedOut(instance) {
5
+ return instance.snapshot.state === "available" && instance.access !== "custom" && instance.snapshot.authenticated === false;
6
+ }
2
7
  /** The ready rule: an engine can run a turn now when it is available, the
3
- * organisation allows it, and it is not signed out. A custom endpoint brings
4
- * its own credential, so its sign-in state does not count. */
8
+ * organisation allows it, and it is not signed out (signedOut). */
5
9
  export function readyToRun(instance, context = {}) {
6
- return instance.snapshot.state === "available" && context.refusal?.(instance) === undefined &&
7
- (instance.access === "custom" || instance.snapshot.authenticated !== false);
10
+ return instance.snapshot.state === "available" && context.refusal?.(instance) === undefined && !signedOut(instance);
8
11
  }
9
12
  /** The engine a new bot gets, and the one a bot moved off a removed engine
10
13
  * gets (computer-engine-removal.ts): one picker for both.
@@ -0,0 +1,20 @@
1
+ // Which of a bot's proposed changes apply without a person. One rule for
2
+ // routines, skills, profile and default model, on the desktop, a server and
3
+ // a Cloud home alike:
4
+ // - Full access applies everything it always has, with no new limits;
5
+ // - at any other level a bot's change to ITSELF applies directly (its own
6
+ // routines, skills, profile, model), and the person sees a one-line
7
+ // receipt with Undo. A change for another bot keeps its card.
8
+ // The one exception is a Cloud home's guest-driven turn, which keeps today's
9
+ // card for everything (`blocked`). Team setup and peer approvals are not
10
+ // changes to the bot itself and stay Full access only.
11
+ /** What Undo says, applying nothing, once the thing changed since. */
12
+ export const UNDO_STALE = "Changed since, so it can't be undone here.";
13
+ /** A bot applying its own routines directly keeps at most this many
14
+ * enabled; past it, a create or resume shows today's card instead. */
15
+ export const SELF_ROUTINE_CAP = 20;
16
+ export function directApply(args) {
17
+ if (args.fullAccess)
18
+ return "full-access";
19
+ return args.targetBotId === args.botId && !args.blocked ? "self" : null;
20
+ }
@@ -31,6 +31,7 @@ import { basename, dirname, isAbsolute, relative, resolve } from "node:path";
31
31
  import { createHash } from "node:crypto";
32
32
  import { PROVIDER_CREDENTIAL_ENV, stripControlPlaneEnv, WORKSPACE_CREDENTIAL_ENV } from "../../config.js";
33
33
  import { decodeInjectId } from "../local-inject.js";
34
+ import { DeviceAuthController } from "../device-auth.js";
34
35
  import { deletePromptSplitReceipt, promptHalves, readPromptSplitReceipt, splitSessionPrompt, writePromptSplitReceipt } from "../prompt-split.js";
35
36
  import { describeSpawnFailure, execCli, killCliTree, spawnCli } from "../../procs.js";
36
37
  import { classifyQuiet, describeQuiet, lastSeenPhrase, LogTail, quietKey, sampleProcessTree, } from "./quiet-status.js";
@@ -373,6 +374,9 @@ export function createAcpDriver(support) {
373
374
  };
374
375
  if (support.resolveModelsOnCreate !== false)
375
376
  await refreshModels();
377
+ const deviceSignIn = support.deviceSignIn
378
+ ? new DeviceAuthController(support.deviceSignIn, { cli: config.cli, environment: () => childEnv(), onAuthenticated: refreshModels })
379
+ : null;
376
380
  const listeners = new Set();
377
381
  const active = new Map();
378
382
  // One live agent process per thread, kept across turns — the Claude
@@ -1904,6 +1908,11 @@ export function createAcpDriver(support) {
1904
1908
  return models;
1905
1909
  },
1906
1910
  refreshModels: support.resolveModels ? refreshModels : undefined,
1911
+ ...(deviceSignIn ? {
1912
+ startAuthentication: () => deviceSignIn.start(),
1913
+ getAuthentication: (flowId) => deviceSignIn.get(flowId),
1914
+ cancelAuthentication: () => deviceSignIn.cancel(),
1915
+ } : {}),
1907
1916
  snapshot,
1908
1917
  adapter: {
1909
1918
  provider: DRIVER_KIND,
@@ -1950,6 +1959,7 @@ export function createAcpDriver(support) {
1950
1959
  },
1951
1960
  },
1952
1961
  dispose: async () => {
1962
+ await deviceSignIn?.dispose();
1953
1963
  for (const { stop } of active.values())
1954
1964
  stop();
1955
1965
  for (const threadId of Array.from(sessions.keys()))
@@ -20,6 +20,45 @@ export const STATIC_GROK_MODELS = {
20
20
  ],
21
21
  };
22
22
  const SLUG = /^[a-z0-9][a-z0-9._-]*$/i;
23
+ /** Grok's own home: `$GROK_HOME`, else `~/.grok`. Its grok.com sign-in,
24
+ * config and catalog all live here. */
25
+ export function grokHome(env = process.env) {
26
+ return env.GROK_HOME || harnessHome("grok", env);
27
+ }
28
+ /** The grok.com sign-in a turn runs on is stored. */
29
+ export function grokSignedIn(env) {
30
+ return existsSync(join(grokHome(env), "auth.json"));
31
+ }
32
+ function grokLoginFailure(output) {
33
+ if (/(unexpected argument|unrecognized (argument|option)|unknown option).*device-(auth|code)/i.test(output)) {
34
+ return "This server's Grok is too old to sign in with a code. Update Grok on the server, then try again.";
35
+ }
36
+ if (/device-code login is not available/i.test(output)) {
37
+ return "This Grok account can't sign in with a code. Use an xAI API key instead.";
38
+ }
39
+ if (/expired/i.test(output))
40
+ return "The Grok sign-in code expired. Start sign-in again for a new code.";
41
+ if (/denied|rejected/i.test(output))
42
+ return "Grok sign-in was declined in the browser. Start sign-in again to try once more.";
43
+ return "Grok sign-in did not finish. Check the server's connection, then try again.";
44
+ }
45
+ /** Grok Build's half of the in-app sign-in (device-auth.ts): `grok login
46
+ * --device-auth` on the grok.com subscription. Grok has no status command,
47
+ * so nothing is checked first, and a stored login that a failed turn just
48
+ * refused is signed in again; the sign-in is confirmed the way a turn checks
49
+ * it. Checked against grok 1.0.25 and 1.0.41: `login --help` and the
50
+ * device-code text in their binaries. */
51
+ export const GROK_DEVICE_SIGN_IN = {
52
+ provider: "grok",
53
+ product: "Grok",
54
+ account: "Grok",
55
+ homeEnv: "GROK_HOME",
56
+ homeDir: ".grok",
57
+ loginArgs: ["login", "--device-auth"],
58
+ install: "Install it with xAI's installer (https://x.ai/cli), then try again.",
59
+ failure: grokLoginFailure,
60
+ signedIn: grokSignedIn,
61
+ };
23
62
  function unquote(raw) {
24
63
  const value = raw.trim();
25
64
  if (value.length >= 2 && value.startsWith('"') && value.endsWith('"')) {
@@ -30,7 +69,7 @@ function unquote(raw) {
30
69
  /** Local slugs from ~/.grok/config.toml, plus the cloud defaults.
31
70
  * `grok -m <slug>` already accepts these; the picker just didn't list them. */
32
71
  export function readGrokModelCatalog(env = process.env) {
33
- const path = join(env.GROK_HOME || harnessHome("grok", env), "config.toml");
72
+ const path = join(grokHome(env), "config.toml");
34
73
  let text = "";
35
74
  try {
36
75
  text = readFileSync(path, "utf8");
@@ -112,7 +151,7 @@ export function ensureGrokInjectSlug(modelId, env = process.env) {
112
151
  const host = localHost(inject.host);
113
152
  if (!host)
114
153
  return modelId;
115
- const path = join(env.GROK_HOME || harnessHome("grok", env), "config.toml");
154
+ const path = join(grokHome(env), "config.toml");
116
155
  let text = "";
117
156
  try {
118
157
  text = readFileSync(path, "utf8");
@@ -215,7 +254,7 @@ export function grokInheritedProfile(cli, env, cwd) {
215
254
  let path = flag >= 0 ? (args[flag].includes("=") ? args[flag].slice(args[flag].indexOf("=") + 1) : args[flag + 1]) : undefined;
216
255
  if (flag >= 0 && (!path || path.startsWith("-")))
217
256
  return unsupported();
218
- const files = [join(env.GROK_HOME || harnessHome("grok", env), "config.toml")];
257
+ const files = [join(grokHome(env), "config.toml")];
219
258
  for (let directory = resolve(cwd);;) {
220
259
  const file = join(directory, ".grok", "config.toml");
221
260
  if (!files.includes(file))
@@ -331,7 +370,7 @@ const support = {
331
370
  effortLevels: ["low", "medium", "high"],
332
371
  defaultCli: "grok",
333
372
  nativeSource: "grok.acp",
334
- loginNote: "Grok CLI is not signed in — run `grok login` in a terminal",
373
+ loginNote: "Grok is not signed in to your grok.com account — choose Sign in to Grok in engine setup",
335
374
  // No Windows one-liner: the installer is a POSIX shell script, and offering
336
375
  // `curl … | bash` there would be advice that cannot run. Windows falls back
337
376
  // to docsUrl, which is honest rather than broken.
@@ -341,8 +380,11 @@ const support = {
341
380
  linux: "curl -fsSL https://x.ai/cli/install.sh | bash",
342
381
  },
343
382
  docsUrl: "https://x.ai/cli",
383
+ // The terminal route, for people who prefer it; the app's own sign-in
384
+ // is the device code below, which needs no terminal.
344
385
  signInCommand: "grok login",
345
386
  },
387
+ deviceSignIn: GROK_DEVICE_SIGN_IN,
346
388
  // Write the [model.slug] block with the instance HOME/GROK_HOME, then pass
347
389
  // the slug on argv. spawnArgs must not call ensureGrokInjectSlug itself —
348
390
  // that helper defaults to process.env and would miss the instance override.
@@ -458,7 +500,7 @@ const support = {
458
500
  // an unauthenticated CLI is a user action, not something to paper over.
459
501
  pickAuthMethod: (methods) => (methods.some((m) => m.id === "cached_token") ? "cached_token" : null),
460
502
  authFailure: "fail",
461
- isAuthenticated: (env) => existsSync(join(harnessHome("grok", env), "auth.json")),
503
+ isAuthenticated: (env) => grokSignedIn(env),
462
504
  // `--append-system-prompt`/`--rules` are accepted by the CLI but do NOT
463
505
  // reach the agent-stdio system prompt (verified against 1.0.0), so the
464
506
  // persona is prepended codex-style.
@@ -1243,7 +1243,7 @@ export async function callTool(name, args, context) {
1243
1243
  return `- ${row.action} ${row.name}`;
1244
1244
  }).join("\n")
1245
1245
  : "(none)";
1246
- return { text: `Imported skills:\n${live}\n\nStaged (waiting for the user to confirm):\n${pending}` };
1246
+ return { text: `Imported skills:\n${live}\n\nStaged (waiting for the user's decision):\n${pending}` };
1247
1247
  }
1248
1248
  if (name === "skill_manage") {
1249
1249
  if (args.action !== "create" && args.action !== "update") {