openmausbot 0.1.96 → 0.1.98

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 (185) hide show
  1. package/dist/assets/ActivityPanel-H6D3SD39.js +1 -0
  2. package/dist/assets/BotSettingsDialog-Dqz_AiBZ.js +7 -0
  3. package/dist/assets/CloudBackendPicker-iezpJFpF.js +1 -0
  4. package/dist/assets/ComputerPanel-DZPj-IWu.js +1 -0
  5. package/dist/assets/DesktopViewer-utONms1p.js +5 -0
  6. package/dist/assets/InspectorPanel-OVaBVrzC.js +5 -0
  7. package/dist/assets/KeyboardShortcutsModal-gk9mvHj_.js +1 -0
  8. package/dist/assets/LocalVmWorkspace-DLIvd2kC.js +1 -0
  9. package/dist/assets/MacLocalControl-bJv8yiPB.js +1 -0
  10. package/dist/assets/NewBotDialog-1qGOAdUM.js +2 -0
  11. package/dist/assets/RemoteAgentSettingsPanel-DqKr0HkO.js +1 -0
  12. package/dist/assets/RoutinesPage-BM2D4qGi.js +1 -0
  13. package/dist/assets/RoutinesSection-Dny9ra-c.js +1 -0
  14. package/dist/assets/SettingsModal-gC6XJJmt.js +11 -0
  15. package/dist/assets/TeamMapPage-B6fuu4r_.js +8 -0
  16. package/dist/assets/TriggersPanel-j0qTP2CO.js +1 -0
  17. package/dist/assets/VisibilitySection-DT0FqPvu.js +12 -0
  18. package/dist/assets/WebhooksPanel--YQyCjKO.js +3 -0
  19. package/dist/assets/{abnfDiagram-O67JEVCF-Dkbd2hcj.js → abnfDiagram-O67JEVCF-BsjcFX0-.js} +1 -1
  20. package/dist/assets/activity-BxOkayvD.js +1 -0
  21. package/dist/assets/{arc-Duj5Coy2.js → arc-CJNA94c6.js} +1 -1
  22. package/dist/assets/architectureDiagram-NJMV4G6O-dz2ud7lP.js +36 -0
  23. package/dist/assets/{blockDiagram-BEXU5L5S-CWDlTpXe.js → blockDiagram-BEXU5L5S-ChBEALoR.js} +1 -1
  24. package/dist/assets/brain-CFZ7PEXc.js +1 -0
  25. package/dist/assets/{c4Diagram-YGBWAQC7-B0t15PDc.js → c4Diagram-YGBWAQC7-KZNRKDQe.js} +1 -1
  26. package/dist/assets/channel-WhFyujhZ.js +1 -0
  27. package/dist/assets/{chunk-2Q5K7J3B-BJSCL-HV.js → chunk-2Q5K7J3B-BLLwmCET.js} +1 -1
  28. package/dist/assets/{chunk-3FUC2YCW-D3_ILccd.js → chunk-3FUC2YCW-CQxyreBZ.js} +2 -2
  29. package/dist/assets/{chunk-5VM5RSS4-D3dmwT_S.js → chunk-5VM5RSS4-D6sFMW0u.js} +1 -1
  30. package/dist/assets/{chunk-GTNCS2PH-Br73HFPD.js → chunk-GTNCS2PH-BaZ1YgLF.js} +1 -1
  31. package/dist/assets/{chunk-GWA4HPMP-uSsjxubC.js → chunk-GWA4HPMP-CcalphmC.js} +1 -1
  32. package/dist/assets/{chunk-JWPE2WC7-C40VWFyr.js → chunk-JWPE2WC7-CSk8R3ve.js} +1 -1
  33. package/dist/assets/{chunk-NETBCI7D-D6WNNYwU.js → chunk-NETBCI7D-CTmLjA57.js} +1 -1
  34. package/dist/assets/{chunk-WEXAMYUT-DOEhq64P.js → chunk-WEXAMYUT-CM9Z77Ne.js} +1 -1
  35. package/dist/assets/{chunk-XXDRQBXY-BqJEi6Pi.js → chunk-XXDRQBXY-B1fxpMS2.js} +1 -1
  36. package/dist/assets/{classDiagram-v2-NBCMYWYE-ByU_GnxT.js → classDiagram-v2-NBCMYWYE-DCCyoLpj.js} +1 -1
  37. package/dist/assets/computer-control-NLov352p.js +1 -0
  38. package/dist/assets/cose-bilkent-JH36ORCC-KyImBKvE.js +1 -0
  39. package/dist/assets/{cynefin-OW5HDTMX-CZWO7aYj.js → cynefin-OW5HDTMX-fsZc6MGa.js} +1 -1
  40. package/dist/assets/{cynefinDiagram-VND7K2PF-C70-w0la.js → cynefinDiagram-VND7K2PF-CGmHsShB.js} +1 -1
  41. package/dist/assets/{dagre-6A5THRUB-CnhjhExB.js → dagre-6A5THRUB-Dah1h-CH.js} +1 -1
  42. package/dist/assets/{diagram-22UHCM2B-bnjWCNb4.js → diagram-22UHCM2B-BIu71OyV.js} +1 -1
  43. package/dist/assets/{diagram-3UASUU5V-A4uTWoFV.js → diagram-3UASUU5V-gxhUB_Mu.js} +1 -1
  44. package/dist/assets/{diagram-ATOU4E4O-Zi6m3NUl.js → diagram-ATOU4E4O-CBhusUBn.js} +1 -1
  45. package/dist/assets/{diagram-CDSNMT55-DtCcmd5k.js → diagram-CDSNMT55-BdPrc86x.js} +1 -1
  46. package/dist/assets/{diagram-MLGK6HIB-DofuETS3.js → diagram-MLGK6HIB-Clp110R_.js} +1 -1
  47. package/dist/assets/{diagram-MPIPVDR6-Dw2T9PuU.js → diagram-MPIPVDR6-DJKfbugw.js} +1 -1
  48. package/dist/assets/{ebnfDiagram-ZINNZB2B-DbrwPiem.js → ebnfDiagram-ZINNZB2B-DnsltoBu.js} +1 -1
  49. package/dist/assets/{elk-276RUBZZ-BvCt1dCb.js → elk-276RUBZZ-jWdq6gqH.js} +1 -1
  50. package/dist/assets/{erDiagram-OPXOYQCR-Y-QKqPnU.js → erDiagram-OPXOYQCR-DArPVf8u.js} +1 -1
  51. package/dist/assets/{flowDiagram-KWPJA3E3-CDkL1B5w.js → flowDiagram-KWPJA3E3-D2HZ-2f7.js} +1 -1
  52. package/dist/assets/ganttDiagram-FUAMR5RP--o0KIxEo.js +292 -0
  53. package/dist/assets/{gitGraphDiagram-X574FWY7-nL9iFTCv.js → gitGraphDiagram-X574FWY7-CsoXr2D7.js} +1 -1
  54. package/dist/assets/image-plus-BbVjGHin.js +1 -0
  55. package/dist/assets/index-BrPW5HDO.css +1 -0
  56. package/dist/assets/index-C3NqfdVU.js +585 -0
  57. package/dist/assets/{index-DreDnjOu.js → index-CJTp9JEp.js} +1 -1
  58. package/dist/assets/{infoDiagram-VRGFBTTK-C7aHjzsf.js → infoDiagram-VRGFBTTK-g-6lNp7r.js} +1 -1
  59. package/dist/assets/{ishikawaDiagram-OU5B5YK6-KUZsNBTh.js → ishikawaDiagram-OU5B5YK6-B1d6qVTV.js} +1 -1
  60. package/dist/assets/{journeyDiagram-ZHPQQLJL-CGUuodFl.js → journeyDiagram-ZHPQQLJL-BTPuiU6T.js} +1 -1
  61. package/dist/assets/{kanban-definition-PNTS6WVX-Cy6r868Z.js → kanban-definition-PNTS6WVX-bDDuRJvP.js} +1 -1
  62. package/dist/assets/{linear-Bl669148.js → linear-BVVKbEMy.js} +1 -1
  63. package/dist/assets/{mermaid.core-86Xqz5Mr.js → mermaid.core-JJdoKyKB.js} +5 -5
  64. package/dist/assets/{mindmap-definition-NLK3R4M7-G4DzHLrd.js → mindmap-definition-NLK3R4M7-B4aE3T0q.js} +1 -1
  65. package/dist/assets/module-DCUsy2BQ.js +3 -0
  66. package/dist/assets/page-visible-BBo_Zm8g.js +1 -0
  67. package/dist/assets/{pegDiagram-GJSIUBJH-K4eruzY0.js → pegDiagram-GJSIUBJH-DFKQWpR7.js} +1 -1
  68. package/dist/assets/{pieDiagram-5QR66LMP-DYdR9PPq.js → pieDiagram-5QR66LMP-Iv7OKVJi.js} +1 -1
  69. package/dist/assets/{quadrantDiagram-O4NWA36T-BCAh0nEy.js → quadrantDiagram-O4NWA36T-U2YnfwBk.js} +1 -1
  70. package/dist/assets/{railroadDiagram-XR7U4H2S-p0dGRc4g.js → railroadDiagram-XR7U4H2S-CuPy6RqM.js} +1 -1
  71. package/dist/assets/remote-desktop-panel-BNEj7tUx.js +1 -0
  72. package/dist/assets/{requirementDiagram-PLB6GJNP-tLeBG0aL.js → requirementDiagram-PLB6GJNP-bMI5AK7T.js} +1 -1
  73. package/dist/assets/{sankeyDiagram-IPEJSGJF-QRuN16rV.js → sankeyDiagram-IPEJSGJF-BKcFE2WQ.js} +1 -1
  74. package/dist/assets/{sequenceDiagram-PO4LG4MO-ueT1nVoa.js → sequenceDiagram-PO4LG4MO-Bn9q88kl.js} +1 -1
  75. package/dist/assets/{sizeCapture-INFHLROL-wRS2zWg2.js → sizeCapture-INFHLROL-Cvmdq9HD.js} +1 -1
  76. package/dist/assets/{stateDiagram-v2-GCMORJYK-CYzA_hE1.js → stateDiagram-v2-GCMORJYK-JJQYw3eQ.js} +1 -1
  77. package/dist/assets/{swimlanes-2SLR337P-kDnv6LMc.js → swimlanes-2SLR337P-BkSCBEwp.js} +1 -1
  78. package/dist/assets/swimlanesDiagram-TC7HE7FX-CmTirbVT.js +8 -0
  79. package/dist/assets/table-file.worker-KkMx-SNx.js +10 -0
  80. package/dist/assets/{timeline-definition-EJHVYXUP-D1y2UbbH.js → timeline-definition-EJHVYXUP-DsaM4GHr.js} +1 -1
  81. package/dist/assets/{usecaseDiagram-POWQR4AR-IqB4v9HX.js → usecaseDiagram-POWQR4AR-3FOwLq7B.js} +1 -1
  82. package/dist/assets/user-DcZBnAuv.js +1 -0
  83. package/dist/assets/{vennDiagram-UO4OBE2U-BEi7KYVF.js → vennDiagram-UO4OBE2U-DyNjJsKt.js} +1 -1
  84. package/dist/assets/{wardleyDiagram-VNRHLVJA-Dkybo-Yf.js → wardleyDiagram-VNRHLVJA-Y4ZMcnBC.js} +1 -1
  85. package/dist/assets/{xychartDiagram-PMCCYNJV-BAPFJLpg.js → xychartDiagram-PMCCYNJV-BXZpg955.js} +1 -1
  86. package/dist/index.html +2 -2
  87. package/dist-server/cloud-home-start.js +20 -9
  88. package/dist-server/container-mcp.js +8 -0
  89. package/dist-server/desktop-entry.mjs +54 -0
  90. package/dist-server/drivers/agents-proxy.js +26 -9
  91. package/dist-server/index.js +3734 -2360
  92. package/dist-server/openmausbot.js +1664 -1553
  93. package/dist-server/pair-cli.js +1664 -1553
  94. package/dist-server/permission-proxy.js +2 -4
  95. package/dist-server/server/atomic.js +70 -2
  96. package/dist-server/server/auto-approve.js +1 -1
  97. package/dist-server/server/auto-vm-claims.js +13 -1
  98. package/dist-server/server/automatic-recovery.js +1 -2
  99. package/dist-server/server/boat.js +68 -84
  100. package/dist-server/server/bot-overview.js +1 -1
  101. package/dist-server/server/browser-engine.js +38 -1
  102. package/dist-server/server/browser-live.js +112 -25
  103. package/dist-server/server/browser-runtime.js +31 -1
  104. package/dist-server/server/checkpoints.js +275 -44
  105. package/dist-server/server/cli-setup.js +3 -3
  106. package/dist-server/server/cloud-computer-tools.js +11 -4
  107. package/dist-server/server/cloud-home-start.js +4 -4
  108. package/dist-server/server/cloud-home.js +3 -9
  109. package/dist-server/server/cloud-owner.js +1 -1
  110. package/dist-server/server/computer-engine-removal.js +70 -0
  111. package/dist-server/server/computer-selection.js +18 -0
  112. package/dist-server/server/config.js +29 -12
  113. package/dist-server/server/connector-card-text.js +15 -0
  114. package/dist-server/server/connector-scope-hint.js +83 -0
  115. package/dist-server/server/default-model-selection.js +23 -14
  116. package/dist-server/server/delegations.js +11 -5
  117. package/dist-server/server/delta-context.js +6 -1
  118. package/dist-server/server/drivers/acp/core.js +11 -1
  119. package/dist-server/server/drivers/acp/grok.js +47 -5
  120. package/dist-server/server/drivers/acp/opencode-go.js +16 -21
  121. package/dist-server/server/drivers/agents-call.js +1 -1
  122. package/dist-server/server/drivers/agents-catalog.js +27 -7
  123. package/dist-server/server/drivers/agents-proxy.js +1 -0
  124. package/dist-server/server/drivers/builtIn.js +0 -2
  125. package/dist-server/server/drivers/chat-mcp-tools.js +5 -3
  126. package/dist-server/server/drivers/claude-login-auth.js +1 -1
  127. package/dist-server/server/drivers/claude.js +84 -41
  128. package/dist-server/server/drivers/codex-device-auth.js +27 -319
  129. package/dist-server/server/drivers/codex.js +2 -2
  130. package/dist-server/server/drivers/device-auth.js +342 -0
  131. package/dist-server/server/drivers/openai-chat.js +110 -10
  132. package/dist-server/server/drivers/pi.js +184 -49
  133. package/dist-server/server/fleet-agent.js +18 -5
  134. package/dist-server/server/harness/http.js +5 -2
  135. package/dist-server/server/harness/registry.js +19 -0
  136. package/dist-server/server/harness-capabilities.js +7 -4
  137. package/dist-server/server/hosted-models.js +3 -1
  138. package/dist-server/server/index.js +823 -333
  139. package/dist-server/server/key-rejections.js +57 -0
  140. package/dist-server/server/live-call.js +11 -6
  141. package/dist-server/server/managed-policy.js +1 -1
  142. package/dist-server/server/message-file.js +7 -4
  143. package/dist-server/server/model-catalog/presets.js +8 -0
  144. package/dist-server/server/peer-roster.js +10 -2
  145. package/dist-server/server/permission-proxy.js +4 -0
  146. package/dist-server/server/provider-key-check.js +5 -1
  147. package/dist-server/server/request-auth.js +1 -1
  148. package/dist-server/server/room-turn-end.js +15 -0
  149. package/dist-server/server/room-turn-timeout.js +28 -0
  150. package/dist-server/server/routes/live.js +3 -3
  151. package/dist-server/server/routes/thread-models.js +36 -0
  152. package/dist-server/server/routine-requests.js +1 -1
  153. package/dist-server/server/routines.js +3 -3
  154. package/dist-server/server/screen-frame-gate.js +1 -3
  155. package/dist-server/server/skills.js +3 -2
  156. package/dist-server/server/store.js +273 -61
  157. package/dist-server/server/surface.js +29 -49
  158. package/dist-server/server/system-prompt.js +10 -10
  159. package/dist-server/server/team-backup.js +19 -4
  160. package/dist-server/server/thread-model.js +25 -0
  161. package/dist-server/server/turn-continuation.js +168 -0
  162. package/dist-server/server/webhook-ingress.js +8 -3
  163. package/dist-server/server/webhooks.js +40 -5
  164. package/dist-server/server/workspace.js +1 -1
  165. package/dist-server/shared/ask-question.js +0 -70
  166. package/dist-server/shared/cloud-computer.js +4 -6
  167. package/dist-server/shared/credential-request.js +1 -1
  168. package/dist-server/shared/device-sign-in.js +57 -0
  169. package/dist-server/shared/failed-turn.js +1 -4
  170. package/dist-server/shared/place-view.js +409 -0
  171. package/dist-server/shared/team-backup.js +2 -0
  172. package/dist-server/shared/thread-model.js +13 -0
  173. package/dist-server/shared/tool-scope-support.js +1 -2
  174. package/dist-server/vps-container-mcp.js +8 -0
  175. package/dist-server/workspace-backup.worker.js +41 -22
  176. package/package.json +1 -1
  177. package/dist/assets/DesktopViewer-DsnA23KM.js +0 -5
  178. package/dist/assets/architectureDiagram-NJMV4G6O-uYUsDawP.js +0 -36
  179. package/dist/assets/channel-BZxwC-Gw.js +0 -1
  180. package/dist/assets/cose-bilkent-JH36ORCC-D-Uglxqq.js +0 -1
  181. package/dist/assets/ganttDiagram-FUAMR5RP-CKV5D2F6.js +0 -292
  182. package/dist/assets/index-Du7o6Dsf.js +0 -610
  183. package/dist/assets/index-KxG4bWSr.css +0 -1
  184. package/dist/assets/swimlanesDiagram-TC7HE7FX-C7voMDle.js +0 -8
  185. package/dist-server/server/drivers/boatagent.js +0 -443
@@ -0,0 +1,409 @@
1
+ // Where a bot works, said once: one plain line and at most one next action
2
+ // for every state a place can be in, from the facts the server and the app
3
+ // already hold. The server words a failed turn's row from it (English, the
4
+ // language phones read), and every control that shows or picks a place
5
+ // (the Computer panel's cards and Simple grid, the composer chip, the failed
6
+ // turn row, the bot's Access settings) renders the same state from it in the
7
+ // person's language. Nothing else decides what a place is called or what to
8
+ // do when it can't be used.
9
+ //
10
+ // The English below mirrors src/locales/en.json `place.view.*`,
11
+ // `place.action.*` and `place.askAdmin`/`place.backOnAuto` exactly (a test
12
+ // holds them together), the way shared/live-approval.ts mirrors its keys:
13
+ // the server has no i18n.
14
+ /** Every state a place can be in. cc-* is the cloud computer. */
15
+ export const PLACE_STATES = [
16
+ "auto", "auto-team",
17
+ "cc-cannot", "cc-tools-off", "cc-sign-in", "cc-new", "cc-starting", "cc-waking", "cc-on", "cc-asleep",
18
+ "cc-no-hours", "cc-at-once", "cc-unavailable", "cc-ended", "cc-no-start", "cc-clearing", "cc-provider",
19
+ "cc-on-my-cloud", "cc-needs-key", "vps",
20
+ "browser", "browser-off", "browser-cannot",
21
+ "local", "local-unavailable", "vm", "vm-cannot", "place-failed",
22
+ "off",
23
+ ];
24
+ /** The next actions a place offers. Each is one button in the app and, on a
25
+ * stored row, one sentence a phone can read. */
26
+ export const PLACE_ACTIONS = [
27
+ "choose-model", "open-tools", "sign-in", "start", "wake", "watch", "see-plan", "manage-computers",
28
+ "try-again", "open-my-cloud", "add-boat-key", "turn-on-browser", "open-team-map", "open-vm-settings",
29
+ "clear-pin", "change-routine", "open-computer-panel",
30
+ ];
31
+ /** The English catalog, mirrored by en.json. */
32
+ export const PLACE_EN = {
33
+ "place.view.auto.short": "Chooses for you",
34
+ "place.view.auto.lineMyCloud": "Uses the built-in browser. In a chat, it starts its cloud computer by itself when a task needs desktop apps.",
35
+ "place.view.auto.lineDesktop": "Uses the built-in browser, a private desktop on this computer, or this computer's screen, whichever the task needs.",
36
+ "place.view.auto.lineLinux": "Uses the built-in browser, or a running Local VM when a task needs a desktop.",
37
+ "place.view.autoTeam.short": "Shared",
38
+ "place.view.autoTeam.line": "Uses {computer}, the cloud computer this team shares.",
39
+ "place.view.ccCannot.short": "Not with this model",
40
+ "place.view.ccCannot.line": "{model} can't use a computer. Choose a model that can, such as Claude or ChatGPT.",
41
+ "place.view.ccToolsOff.short": "Not allowed",
42
+ "place.view.ccToolsOff.line": "What {bot} can use doesn't include a computer.",
43
+ "place.view.ccSignIn.short": "Sign in first",
44
+ "place.view.ccSignIn.line": "Sign in to {engine} first. {bot} uses it on the cloud computer too.",
45
+ "place.view.ccSignIn.lineMyCloud": "Sign in to {engine} on My Cloud first. {bot} uses it on the cloud computer too.",
46
+ "place.view.ccNew.short": "Ready",
47
+ "place.view.ccNew.line": "{bot} gets its own cloud computer the first time a task needs one. The first start takes about a minute.",
48
+ "place.view.ccStarting.short": "Starting…",
49
+ "place.view.ccStarting.line": "Starting {bot}'s cloud computer. The first start takes about a minute.",
50
+ "place.view.ccWaking.short": "Waking…",
51
+ "place.view.ccWaking.line": "Waking {bot}'s cloud computer. This takes a few seconds.",
52
+ "place.view.ccOn.short": "On",
53
+ "place.view.ccOn.line": "{bot}'s cloud computer is on.",
54
+ "place.view.ccAsleep.short": "Asleep",
55
+ "place.view.ccAsleep.line": "{bot}'s cloud computer is asleep. It wakes in a few seconds when {bot} needs it.",
56
+ "place.view.ccNoHours.short": "No hours left",
57
+ "place.view.ccNoHours.line": "This month's {hours} cloud computer hours are used up. They come back on 1 {month}.",
58
+ "place.view.ccNoHours.lineUnknown": "This month's cloud computer hours are used up.",
59
+ "place.view.ccAtOnce.short": "In use",
60
+ "place.view.ccAtOnce.lineOne": "Your {plan} plan includes 1 cloud computer, and {holders} has it.",
61
+ "place.view.ccAtOnce.lineMany": "Your {plan} plan includes {max} cloud computers, and {holders} have them.",
62
+ "place.view.ccAtOnce.lineUnknown": "All the cloud computers your plan includes are in use.",
63
+ "place.view.ccUnavailable.short": "Not available now",
64
+ "place.view.ccUnavailable.line": "Cloud computers can't start right now. It isn't anything you did.",
65
+ "place.view.ccEnded.short": "Plan ended",
66
+ "place.view.ccEnded.line": "Your OpenMausBot Cloud plan has ended, so cloud computers are off.",
67
+ "place.view.ccNoStart.short": "Didn't start",
68
+ "place.view.ccNoStart.line": "{bot}'s cloud computer didn't start.",
69
+ "place.view.ccClearing.short": "Clearing up",
70
+ "place.view.ccClearing.line": "{bot}'s previous cloud computer is still being removed.",
71
+ "place.view.ccProvider.short": "Couldn't start",
72
+ "place.view.ccProvider.line": "Your Boat account couldn't start {bot}'s cloud computer: {words}",
73
+ "place.view.ccOnMyCloud.short": "On My Cloud",
74
+ "place.view.ccOnMyCloud.line": "Cloud computers from your plan work for bots on My Cloud for now.",
75
+ "place.view.ccNeedsKey.short": "Needs a Boat key",
76
+ "place.view.ccNeedsKey.line": "A cloud computer here needs your own Boat key, a paid service.",
77
+ "place.view.vps.short": "Your server",
78
+ "place.view.vps.line": "Uses your own server, connected over SSH.",
79
+ "place.view.browser.short": "Web pages only",
80
+ "place.view.browser.line": "Works in the built-in browser only: web pages, no desktop apps.",
81
+ "place.view.browserOff.short": "Browser is off",
82
+ "place.view.browserOff.line": "The built-in browser is switched off.",
83
+ "place.view.browserCannot.short": "Not with this model",
84
+ "place.view.browserCannot.line": "{model} can't use the built-in browser.",
85
+ "place.view.local.short": "Your screen",
86
+ "place.view.local.line": "Uses your screen, mouse, and keyboard.",
87
+ "place.view.localUnavailable.short": "Not ready",
88
+ "place.view.localUnavailable.line": "{reason}",
89
+ "place.view.vm.short": "Private desktop",
90
+ "place.view.vm.line": "A private Linux desktop on this device, separate from your own screen.",
91
+ "place.view.vmCannot.short": "Not with this model",
92
+ "place.view.vmCannot.line": "{model} can't use a Local VM. Choose a model that can, such as Claude or ChatGPT.",
93
+ "place.view.placeFailed.short": "Didn't start",
94
+ "place.view.placeFailed.line": "{cause}",
95
+ "place.view.off.short": "No screen",
96
+ "place.view.off.line": "{bot} has no screen. It can still chat and do anything that doesn't need one.",
97
+ "place.action.chooseModel": "Choose a model",
98
+ "place.action.openTools": "Change what {bot} can use",
99
+ "place.action.signIn": "Sign in",
100
+ "place.action.start": "Start it now",
101
+ "place.action.wake": "Wake it now",
102
+ "place.action.watch": "Watch",
103
+ "place.action.seePlan": "See your plan",
104
+ "place.action.manageComputers": "Manage cloud computers",
105
+ "place.action.tryAgain": "Try again",
106
+ "place.action.openMyCloud": "Open My Cloud",
107
+ "place.action.addBoatKey": "Add Boat key",
108
+ "place.action.turnOnBrowser": "Turn on the browser",
109
+ "place.action.openTeamMap": "Open Team map",
110
+ "place.action.openVmSettings": "Local VM settings",
111
+ "place.action.clearPin": "Clear this conversation's place",
112
+ "place.action.usePlace": "Use {place}",
113
+ "place.action.changeRoutine": "Change where it runs",
114
+ "place.action.openComputerPanel": "Open Computer panel",
115
+ "place.askAdmin": "Ask an Admin to change it.",
116
+ "place.backOnAuto": "This conversation is back on Auto.",
117
+ };
118
+ /** A stored row's next action as one English sentence: what a phone, which
119
+ * shows only the row's words, reads instead of a button. English only, like
120
+ * the row it ends. */
121
+ export const PLACE_WORDS = {
122
+ "choose-model": "Choose another model in {bot}'s settings.",
123
+ "open-tools": "Change what {bot} can use in its settings.",
124
+ "sign-in": "Sign in to {engine} in Settings.",
125
+ start: "Start it from the Computer panel.",
126
+ wake: "Wake it from the Computer panel.",
127
+ watch: "Watch it from the Computer panel.",
128
+ "see-plan": "See your plan on the Plan page.",
129
+ "manage-computers": "Manage your cloud computers in Settings → Local VM.",
130
+ "try-again": "Try again.",
131
+ "open-my-cloud": "Open My Cloud from the menu at the top of the sidebar.",
132
+ "add-boat-key": "Add a Boat key in Settings → API keys.",
133
+ "turn-on-browser": "Turn on the built-in browser in the Computer panel.",
134
+ "open-team-map": "Open Team map to manage it.",
135
+ "open-vm-settings": "Check it in Settings → Local VM.",
136
+ "clear-pin": "Clear this conversation's place in the composer to continue.",
137
+ "change-routine": "Change where this routine runs.",
138
+ "open-computer-panel": "Check it in the Computer panel.",
139
+ };
140
+ function fill(template, params = {}) {
141
+ return template.replace(/\{(\w+)\}/g, (whole, name) => (Object.hasOwn(params, name) ? String(params[name]) : whole));
142
+ }
143
+ export const english = (key, params) => fill(PLACE_EN[key], params);
144
+ /** Each state's key segment, short and line keys, and own action. */
145
+ const STATE = {
146
+ auto: { key: "auto", action: null },
147
+ "auto-team": { key: "autoTeam", action: "open-team-map" },
148
+ "cc-cannot": { key: "ccCannot", action: "choose-model" },
149
+ "cc-tools-off": { key: "ccToolsOff", action: "open-tools" },
150
+ "cc-sign-in": { key: "ccSignIn", action: "sign-in" },
151
+ "cc-new": { key: "ccNew", action: "start" },
152
+ "cc-starting": { key: "ccStarting", action: "watch" },
153
+ "cc-waking": { key: "ccWaking", action: "watch" },
154
+ "cc-on": { key: "ccOn", action: "watch" },
155
+ "cc-asleep": { key: "ccAsleep", action: "wake" },
156
+ "cc-no-hours": { key: "ccNoHours", action: "see-plan" },
157
+ "cc-at-once": { key: "ccAtOnce", action: "manage-computers" },
158
+ "cc-unavailable": { key: "ccUnavailable", action: "try-again" },
159
+ "cc-ended": { key: "ccEnded", action: "see-plan" },
160
+ "cc-no-start": { key: "ccNoStart", action: "try-again" },
161
+ "cc-clearing": { key: "ccClearing", action: "try-again" },
162
+ "cc-provider": { key: "ccProvider", action: "try-again" },
163
+ "cc-on-my-cloud": { key: "ccOnMyCloud", action: "open-my-cloud" },
164
+ "cc-needs-key": { key: "ccNeedsKey", action: "add-boat-key" },
165
+ vps: { key: "vps", action: null },
166
+ browser: { key: "browser", action: null },
167
+ "browser-off": { key: "browserOff", action: "turn-on-browser" },
168
+ "browser-cannot": { key: "browserCannot", action: "choose-model" },
169
+ local: { key: "local", action: null },
170
+ "local-unavailable": { key: "localUnavailable", action: null },
171
+ vm: { key: "vm", action: "open-vm-settings" },
172
+ "vm-cannot": { key: "vmCannot", action: "choose-model" },
173
+ "place-failed": { key: "placeFailed", action: "open-computer-panel" },
174
+ off: { key: "off", action: null },
175
+ };
176
+ /** A passing cause: nothing to fix, so where the place came from decides the
177
+ * way on (sourceAction). Every other state's action removes its cause. */
178
+ const PASSING = new Set(["cc-unavailable", "cc-no-start", "cc-clearing", "cc-provider", "place-failed"]);
179
+ /** Actions that change a setting, a sign-in or the plan: a User can't take
180
+ * them, so the line ends "Ask an Admin to change it." instead. */
181
+ const ADMIN_ONLY = new Set([
182
+ "choose-model", "open-tools", "sign-in", "see-plan", "manage-computers", "open-my-cloud",
183
+ "add-boat-key", "turn-on-browser", "open-team-map", "open-vm-settings", "change-routine",
184
+ ]);
185
+ /** Starting or waking a computer early: a User's own message does it, so
186
+ * there is nothing to ask anyone for. */
187
+ const ADMIN_SHORTCUT = new Set(["start", "wake"]);
188
+ const ACTION_KEY = {
189
+ "choose-model": "place.action.chooseModel",
190
+ "open-tools": "place.action.openTools",
191
+ "sign-in": "place.action.signIn",
192
+ start: "place.action.start",
193
+ wake: "place.action.wake",
194
+ watch: "place.action.watch",
195
+ "see-plan": "place.action.seePlan",
196
+ "manage-computers": "place.action.manageComputers",
197
+ "try-again": "place.action.tryAgain",
198
+ "open-my-cloud": "place.action.openMyCloud",
199
+ "add-boat-key": "place.action.addBoatKey",
200
+ "turn-on-browser": "place.action.turnOnBrowser",
201
+ "open-team-map": "place.action.openTeamMap",
202
+ "open-vm-settings": "place.action.openVmSettings",
203
+ "clear-pin": "place.action.clearPin",
204
+ "change-routine": "place.action.changeRoutine",
205
+ "open-computer-panel": "place.action.openComputerPanel",
206
+ };
207
+ /** The state and its params, from the facts. Pure: the panel, the chip, the
208
+ * Access line and the server all ask this. */
209
+ export function placeState(facts) {
210
+ const bot = facts.bot;
211
+ const model = facts.engine.model || facts.engine.name;
212
+ if (facts.place === "off")
213
+ return { state: "off", params: { bot } };
214
+ if (facts.place === "auto") {
215
+ return facts.teamComputer
216
+ ? { state: "auto-team", params: { bot, computer: facts.teamComputer } }
217
+ : { state: "auto", params: { bot } };
218
+ }
219
+ if (facts.place === "browser") {
220
+ if (!facts.engine.browser)
221
+ return { state: "browser-cannot", params: { bot, model } };
222
+ return facts.browserOn ? { state: "browser", params: { bot } } : { state: "browser-off", params: { bot } };
223
+ }
224
+ if (facts.place === "local") {
225
+ return facts.local?.ready === false
226
+ ? { state: "local-unavailable", params: { bot, reason: facts.local.reason ?? "" } }
227
+ : { state: "local", params: { bot } };
228
+ }
229
+ if (facts.place === "vm") {
230
+ return facts.engine.computer ? { state: "vm", params: { bot } } : { state: "vm-cannot", params: { bot, model } };
231
+ }
232
+ // The cloud computer: on the person's own server (VPS) or on Boat, one
233
+ // rule for both (shared/cloud-computer.ts).
234
+ const vps = facts.backend === "vps";
235
+ if (!facts.engine.computer)
236
+ return { state: "cc-cannot", params: { bot, model } };
237
+ if (!facts.toolsAllowComputer)
238
+ return { state: "cc-tools-off", params: { bot } };
239
+ if (!facts.engine.signedIn)
240
+ return { state: "cc-sign-in", params: { bot, engine: facts.engine.name } };
241
+ if (vps)
242
+ return { state: "vps", params: { bot } };
243
+ if (facts.refusal)
244
+ return { state: facts.refusal.state, params: { bot, ...facts.refusal.params } };
245
+ if (facts.boat === "none") {
246
+ // My Cloud always has the plan's computers while the plan is active.
247
+ if (facts.server === "my-cloud")
248
+ return { state: "cc-unavailable", params: { bot } };
249
+ return { state: facts.plan ? "cc-on-my-cloud" : "cc-needs-key", params: { bot } };
250
+ }
251
+ switch (facts.computer) {
252
+ case "starting": return { state: "cc-starting", params: { bot } };
253
+ case "waking": return { state: "cc-waking", params: { bot } };
254
+ case "on": return { state: "cc-on", params: { bot } };
255
+ case "asleep": return { state: "cc-asleep", params: { bot } };
256
+ default: return { state: "cc-new", params: { bot } };
257
+ }
258
+ }
259
+ /** Where the person goes when a passing cause stops a place: try again in
260
+ * place, clear the pin that holds this conversation, change where the
261
+ * routine runs. A room member's turn has no retry of its own. */
262
+ function sourceAction(source, state) {
263
+ switch (source) {
264
+ case "works-on": return state === "place-failed" ? "open-computer-panel" : "try-again";
265
+ case "auto-pin": return "try-again";
266
+ case "pin": return "clear-pin";
267
+ case "routine": return "change-routine";
268
+ case "room": return null;
269
+ }
270
+ }
271
+ function lineKey(state, params, server) {
272
+ const segment = STATE[state].key;
273
+ if (state === "auto") {
274
+ return server === "my-cloud" ? "place.view.auto.lineMyCloud" : server === "linux" ? "place.view.auto.lineLinux" : "place.view.auto.lineDesktop";
275
+ }
276
+ if (state === "cc-sign-in" && server === "my-cloud")
277
+ return "place.view.ccSignIn.lineMyCloud";
278
+ // A refusal read from a code alone has no numbers or names to give.
279
+ if (state === "cc-no-hours" && (params.hours === undefined || !params.month))
280
+ return "place.view.ccNoHours.lineUnknown";
281
+ if (state === "cc-at-once") {
282
+ if (!params.holders?.length || !params.plan || params.max === undefined)
283
+ return "place.view.ccAtOnce.lineUnknown";
284
+ return params.max === 1 ? "place.view.ccAtOnce.lineOne" : "place.view.ccAtOnce.lineMany";
285
+ }
286
+ return `place.view.${segment}.line`;
287
+ }
288
+ /** Join names the way a sentence lists them, in the reader's language. */
289
+ export function listNames(names, locale = "en") {
290
+ try {
291
+ return new Intl.ListFormat(locale, { style: "long", type: "conjunction" }).format(names);
292
+ }
293
+ catch {
294
+ return names.join(", ");
295
+ }
296
+ }
297
+ function templateParams(params, locale) {
298
+ const out = {};
299
+ for (const [name, value] of Object.entries(params)) {
300
+ if (value === undefined)
301
+ continue;
302
+ out[name] = Array.isArray(value) ? listNames(value, locale) : value;
303
+ }
304
+ return out;
305
+ }
306
+ /** One state, worded: its short label, its one line and its one action. */
307
+ export function placeViewOf(state, params, context) {
308
+ const translate = context.translate ?? english;
309
+ const values = templateParams(params, context.locale ?? "en");
310
+ const segment = STATE[state].key;
311
+ let line = translate(lineKey(state, params, context.server), values);
312
+ let action = context.source && PASSING.has(state) ? sourceAction(context.source, state) : STATE[state].action;
313
+ // A failed row never offers what only the panel can do on the spot.
314
+ if (context.source && (action === "start" || action === "wake" || action === "watch"))
315
+ action = null;
316
+ if (context.source === "auto-pin")
317
+ line = `${line} ${translate("place.backOnAuto")}`;
318
+ // Simple mode leaves Local VM setup to Advanced.
319
+ if (action === "open-vm-settings" && context.mode === "simple")
320
+ action = null;
321
+ if (action && context.role === "user" && ADMIN_SHORTCUT.has(action))
322
+ action = null;
323
+ if (action && context.role === "user" && ADMIN_ONLY.has(action)) {
324
+ action = null;
325
+ line = `${line} ${translate("place.askAdmin")}`;
326
+ }
327
+ // Simple mode has no composer chip, so a pin's way back is the grid's
328
+ // choice, by the grid's own name for it.
329
+ const label = !action ? null
330
+ : action === "clear-pin" && context.mode === "simple" && context.worksOnLabel
331
+ ? translate("place.action.usePlace", { place: context.worksOnLabel })
332
+ : translate(ACTION_KEY[action], values);
333
+ return {
334
+ state,
335
+ params,
336
+ short: translate(`place.view.${segment}.short`, values),
337
+ line,
338
+ action: action && label ? { id: action, label } : null,
339
+ };
340
+ }
341
+ /** The view of a place from its facts. */
342
+ export function placeView(facts, options = {}) {
343
+ const { state, params } = placeState(facts);
344
+ return placeViewOf(state, params, { server: facts.server, role: facts.role, mode: facts.mode, ...options });
345
+ }
346
+ /** A stored failed-turn row, worded for this reader. */
347
+ export function placeRowView(row, context) {
348
+ return placeViewOf(row.state, row.params, { ...context, source: row.source });
349
+ }
350
+ /** What the server stores as the row's words: the line and its action as a
351
+ * sentence, in English, so a phone that reads only the words knows both. */
352
+ export function placeRowText(row, server) {
353
+ const view = placeViewOf(row.state, row.params, { server, role: "admin", source: row.source });
354
+ if (!view.action)
355
+ return view.line;
356
+ const words = row.source === "auto-pin" && view.action.id === "try-again"
357
+ ? "Send your message again."
358
+ : fill(PLACE_WORDS[view.action.id], templateParams(row.params, "en"));
359
+ return `${view.line} ${words}`;
360
+ }
361
+ // ── Reading a failed start ──────────────────────────────────────────────
362
+ const MONTH = "(January|February|March|April|May|June|July|August|September|October|November|December)";
363
+ const HOURS_USED = new RegExp(`Your (.+?) plan's (\\d+) cloud computer hours for \\w+ are used up\\. They reset on 1 ${MONTH}`);
364
+ const AT_ONCE = /Your (.+?) plan includes (\d+) cloud computers? at once/;
365
+ const PASSING_WORDS = [
366
+ /cloud computers are busy right now/i, /temporarily unavailable/i, /can't be checked right now/i, /could not be reached/i,
367
+ /returned an unexpected answer/i, /could not complete that request/i, /started too often/i, /woken too often/i,
368
+ /included with your Cloud plan aren't available/i, /are not available right now/i, /fetch failed/i, /ECONNREFUSED/,
369
+ /rate-limiting/i, /\b50[234]\b/,
370
+ ];
371
+ const NO_START_WORDS = [
372
+ /did not become ready/i, /desktop link could not be created/i, /could not be created or reached/i, /did not wake/i,
373
+ /no computer yet/i, /didn't start in time/i,
374
+ ];
375
+ const CLEARING_WORDS = [/is being deleted/i, /previous cloud computer deletion/i, /deletion was not confirmed/i, /deletion is still being reconciled/i];
376
+ /** Read a failed cloud computer start as a state. The Admin's own codes come
377
+ * first; until every refusal has one, its English is read (the words below
378
+ * are exactly the Admin's, server/cloud-services.ts). `included`: the plan's
379
+ * computers, not the person's own Boat key, whose provider's words are shown
380
+ * as they are. */
381
+ export function cloudRefusal(failure, included) {
382
+ const message = failure.message.trim();
383
+ const code = failure.code;
384
+ const hours = HOURS_USED.exec(message);
385
+ if (code === "hours_used" || hours) {
386
+ return { state: "cc-no-hours", params: hours ? { plan: hours[1], hours: Number(hours[2]), month: hours[3] } : {} };
387
+ }
388
+ const atOnce = AT_ONCE.exec(message);
389
+ if (code === "at_once" || atOnce) {
390
+ return { state: "cc-at-once", params: atOnce ? { plan: atOnce[1], max: Number(atOnce[2]) } : {} };
391
+ }
392
+ if (code === "subscription_inactive")
393
+ return { state: "cc-ended", params: {} };
394
+ if (code === "too_many_starts" || code === "rate_limited" || code === "usage_unavailable" || code === "service_unavailable"
395
+ || code === "upstream_unavailable" || code === "invalid_response" || code === "upstream_error") {
396
+ return { state: "cc-unavailable", params: {} };
397
+ }
398
+ // A start that failed and left its new computer still being removed
399
+ // didn't start; the next attempt meets the removal.
400
+ if (NO_START_WORDS.some((words) => words.test(message)))
401
+ return { state: "cc-no-start", params: {} };
402
+ if (CLEARING_WORDS.some((words) => words.test(message)))
403
+ return { state: "cc-clearing", params: {} };
404
+ if ((failure.status ?? 0) >= 500 || PASSING_WORDS.some((words) => words.test(message)))
405
+ return { state: "cc-unavailable", params: {} };
406
+ if (!included && message)
407
+ return { state: "cc-provider", params: { words: message.replace(/[\s.]+$/, "") + "." } };
408
+ return { state: "cc-no-start", params: {} };
409
+ }
@@ -29,6 +29,8 @@ const task = z.object({
29
29
  closedBy: z.object({ botId: key, name, at: timestamp }).optional(),
30
30
  /** Only true travels. Absence is unpinned, including backups from before pins. */
31
31
  pinned: z.literal(true).optional(),
32
+ /** A conversation's own turn ceiling. Absence keeps the group default. */
33
+ turnTimeoutMinutes: z.number().int().min(1).max(1_440).optional(),
32
34
  activeLeafId: key.nullable(),
33
35
  messages: z.array(message).max(100_000),
34
36
  });
@@ -0,0 +1,13 @@
1
+ /** The same engine, model, effort and variant. */
2
+ export function sameModelSelection(a, b) {
3
+ if (!a || !b)
4
+ return a === b;
5
+ return a.instanceId === b.instanceId && a.model === b.model && a.effort === b.effort && a.variant === b.variant;
6
+ }
7
+ /** A bot's threads that run on a model of their own, different from the
8
+ * bot's: the ones "Switch them too" moves onto the bot's model. Reads the
9
+ * wire shape, where only followsBotModel === false is a thread's own pick, so
10
+ * a server too old to send it counts none. */
11
+ export function threadsOnOwnModel(botModel, tasks) {
12
+ return tasks.filter((task) => task.followsBotModel === false && !sameModelSelection(task.modelSelection ?? botModel, botModel));
13
+ }
@@ -5,7 +5,6 @@ export const TOOL_SCOPE_SUPPORT = {
5
5
  "openai-compat": "native-and-mcp", mistral: "native-and-mcp", minimax: "native-and-mcp", cerebras: "native-and-mcp",
6
6
  claudeAgent: "mcp", codex: "mcp", geminiAgent: "mcp", kimiAgent: "mcp", droidAgent: "mcp",
7
7
  cursorAgent: "mcp", opencodeGo: "mcp", qwenAgent: "mcp", hermesAgent: "mcp", customAcp: "mcp", antigravityAgent: "mcp",
8
- boxAgent: "none",
9
8
  };
10
9
  export function assertToolScopeSupported(engine, value) {
11
10
  const parsed = parseToolScope(value);
@@ -13,7 +12,7 @@ export function assertToolScopeSupported(engine, value) {
13
12
  throw new Error(parsed.error);
14
13
  const support = TOOL_SCOPE_SUPPORT[engine];
15
14
  if (parsed.scope !== undefined && support !== "native-and-mcp") {
16
- if (support === "none" || support === undefined) {
15
+ if (support === undefined) {
17
16
  if (parsed.scope.allow !== undefined || parsed.scope.deny?.length)
18
17
  throw new Error(`${engine}: tool selection is not supported by this engine. Choose a supported engine.`);
19
18
  }
@@ -16210,6 +16210,8 @@ var BROWSER_PROFILE_ID = /^[a-z0-9_-]{1,40}$/;
16210
16210
  var FISH_TTS_MODELS = ["s2.1-pro", "s2.1-pro-free"];
16211
16211
  var MIN_ROOM_TURN_TIMEOUT_MINUTES = 1;
16212
16212
  var MAX_ROOM_TURN_TIMEOUT_MINUTES = 1440;
16213
+ var MIN_MCP_CALL_TIMEOUT_MINUTES = 1;
16214
+ var MAX_MCP_CALL_TIMEOUT_MINUTES = 60;
16213
16215
  var DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES = 30;
16214
16216
  var DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES = 10;
16215
16217
  var DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES = 240;
@@ -16255,6 +16257,11 @@ var roomConfigSchema = external_exports.object({
16255
16257
  (rooms) => (rooms.handoffMinRunwayMinutes ?? DEFAULT_ROOM_HANDOFF_MIN_RUNWAY_MINUTES) <= (rooms.handoffLifetimeMinutes ?? DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES) && (rooms.handoffLifetimeMinutes ?? DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES) <= (rooms.handoffHardCapMinutes ?? DEFAULT_ROOM_HANDOFF_HARD_CAP_MINUTES),
16256
16258
  { message: "rooms handoff bounds must satisfy handoffMinRunwayMinutes <= handoffLifetimeMinutes <= handoffHardCapMinutes" }
16257
16259
  );
16260
+ var mcpConfigSchema = external_exports.object({
16261
+ /** Ceiling (minutes) for one bot MCP tool call. Missing values resolve to
16262
+ * 10, preserving the historic chat-mcp-tools constant. */
16263
+ callTimeoutMinutes: external_exports.number().int().min(MIN_MCP_CALL_TIMEOUT_MINUTES).max(MAX_MCP_CALL_TIMEOUT_MINUTES).optional()
16264
+ }).strict();
16258
16265
  var localVmConfigSchema = external_exports.object({
16259
16266
  mode: external_exports.enum(["shared", "per-bot", "pool"]).optional(),
16260
16267
  maxInstances: external_exports.number().int().min(MIN_LOCAL_VM_MAX_INSTANCES).max(MAX_LOCAL_VM_MAX_INSTANCES).optional(),
@@ -16593,6 +16600,7 @@ var appConfigSchema = external_exports.object({
16593
16600
  * system language. Unknown tags degrade to English in the renderer. */
16594
16601
  language: optionalText,
16595
16602
  rooms: roomConfigSchema.optional(),
16603
+ mcp: mcpConfigSchema.optional(),
16596
16604
  context: external_exports.object({
16597
16605
  rebuildBytes: external_exports.number().int().min(1024).max(1e6).optional(),
16598
16606
  compactAt: external_exports.number().positive().max(1e7).optional(),