openmausbot 0.1.85 → 0.1.87

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 (262) hide show
  1. package/README.md +2 -2
  2. package/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  3. package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  4. package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  5. package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  6. package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  7. package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  8. package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  9. package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  10. package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  11. package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  12. package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  13. package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  14. package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  15. package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  16. package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  17. package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  18. package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  19. package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  20. package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  21. package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  22. package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  23. package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  24. package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  25. package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  26. package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  27. package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  28. package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  29. package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  30. package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  31. package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  32. package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  33. package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  34. package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  35. package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  36. package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  37. package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  38. package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  39. package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  40. package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  41. package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  42. package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  43. package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  44. package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  45. package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  46. package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  47. package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  48. package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  49. package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  50. package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  51. package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  52. package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  53. package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  54. package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  55. package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  56. package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  57. package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  58. package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  59. package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  60. package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  61. package/dist/assets/abnfDiagram-O67JEVCF-BTiuL79F.js +1 -0
  62. package/dist/assets/arc-C88Blc2v.js +1 -0
  63. package/dist/assets/architectureDiagram-NJMV4G6O-BZsJIZrb.js +36 -0
  64. package/dist/assets/blockDiagram-BEXU5L5S-CVeMe9Ah.js +140 -0
  65. package/dist/assets/c4Diagram-YGBWAQC7-Cedk3Bhx.js +38 -0
  66. package/dist/assets/channel-taCNRlUU.js +1 -0
  67. package/dist/assets/chunk-2Q5K7J3B-D-VRqzTB.js +1 -0
  68. package/dist/assets/chunk-3FUC2YCW-BChov01Y.js +2 -0
  69. package/dist/assets/chunk-5VM5RSS4-C-TfwvHy.js +15 -0
  70. package/dist/assets/chunk-GTNCS2PH-Db7CGj5Y.js +88 -0
  71. package/dist/assets/chunk-GWA4HPMP-CNvIfqKT.js +1 -0
  72. package/dist/assets/chunk-JWPE2WC7-C_bEp5tq.js +1 -0
  73. package/dist/assets/chunk-NETBCI7D-Coi4BOls.js +1 -0
  74. package/dist/assets/chunk-WEXAMYUT-CzylEuL3.js +1 -0
  75. package/dist/assets/chunk-XXDRQBXY-m7p7ztaD.js +1 -0
  76. package/dist/assets/classDiagram-v2-NBCMYWYE-BMy6o9x2.js +217 -0
  77. package/dist/assets/cose-bilkent-JH36ORCC-BDQ__0_J.js +1 -0
  78. package/dist/assets/cynefin-OW5HDTMX-Djv4ghUb.js +166 -0
  79. package/dist/assets/cynefinDiagram-VND7K2PF-BULrlGYH.js +62 -0
  80. package/dist/assets/cytoscape.esm-BB4DxJjf.js +321 -0
  81. package/dist/assets/dagre-6A5THRUB-D-jrT_hU.js +4 -0
  82. package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
  83. package/dist/assets/diagram-22UHCM2B-p2UhQmfL.js +200 -0
  84. package/dist/assets/diagram-3UASUU5V-DHvGWZ7q.js +24 -0
  85. package/dist/assets/diagram-ATOU4E4O-ChhKDot-.js +3 -0
  86. package/dist/assets/diagram-CDSNMT55-B-T7A43R.js +30 -0
  87. package/dist/assets/diagram-MLGK6HIB-CJm8ENNY.js +24 -0
  88. package/dist/assets/diagram-MPIPVDR6-510tlza8.js +41 -0
  89. package/dist/assets/ebnfDiagram-ZINNZB2B-PkvRPHel.js +1 -0
  90. package/dist/assets/elk-276RUBZZ-BVBVPoX3.js +27 -0
  91. package/dist/assets/erDiagram-OPXOYQCR-BgYMVm7L.js +99 -0
  92. package/dist/assets/flowDiagram-KWPJA3E3-BGqsnc_3.js +213 -0
  93. package/dist/assets/ganttDiagram-FUAMR5RP-D_-UeReH.js +292 -0
  94. package/dist/assets/gitGraphDiagram-X574FWY7-D0uooONx.js +106 -0
  95. package/dist/assets/graph-D8UmR1vK.js +1 -0
  96. package/dist/assets/index-BwdMAQ6p.css +1 -0
  97. package/dist/assets/index-ByJennr7.js +581 -0
  98. package/dist/assets/{index-CTNNoqSJ.js → index-zRsJERGJ.js} +1 -1
  99. package/dist/assets/infoDiagram-VRGFBTTK-B9e1z77f.js +2 -0
  100. package/dist/assets/init-Gi6I4Gst.js +1 -0
  101. package/dist/assets/ishikawaDiagram-OU5B5YK6-BB4vNwvD.js +70 -0
  102. package/dist/assets/journeyDiagram-ZHPQQLJL-DpkosOTB.js +139 -0
  103. package/dist/assets/kanban-definition-PNTS6WVX-DbDP4kUu.js +89 -0
  104. package/dist/assets/linear-DBJGPmjT.js +1 -0
  105. package/dist/assets/mermaid.core-DWPRi-ue.js +311 -0
  106. package/dist/assets/mindmap-definition-NLK3R4M7-nszBbJmx.js +96 -0
  107. package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
  108. package/dist/assets/pegDiagram-GJSIUBJH-CWykJWu_.js +1 -0
  109. package/dist/assets/pieDiagram-5QR66LMP-g3Da-Vnv.js +39 -0
  110. package/dist/assets/quadrantDiagram-O4NWA36T-Wzrlpzgh.js +7 -0
  111. package/dist/assets/railroadDiagram-XR7U4H2S-moHTFMC0.js +1 -0
  112. package/dist/assets/requirementDiagram-PLB6GJNP-CwfXdFH8.js +84 -0
  113. package/dist/assets/sankeyDiagram-IPEJSGJF-3ZROYvnq.js +40 -0
  114. package/dist/assets/sequenceDiagram-PO4LG4MO-E1TBebP8.js +169 -0
  115. package/dist/assets/sizeCapture-INFHLROL-DHKEU5pu.js +1 -0
  116. package/dist/assets/stateDiagram-v2-GCMORJYK-BguEj09D.js +291 -0
  117. package/dist/assets/swimlanes-2SLR337P-C7IDYnhd.js +1 -0
  118. package/dist/assets/swimlanesDiagram-TC7HE7FX-BpEdoB2e.js +8 -0
  119. package/dist/assets/timeline-definition-EJHVYXUP-DCW-F5PW.js +120 -0
  120. package/dist/assets/usecaseDiagram-POWQR4AR-xBMFtWYV.js +370 -0
  121. package/dist/assets/vennDiagram-UO4OBE2U-B5nIkuH8.js +34 -0
  122. package/dist/assets/wardleyDiagram-VNRHLVJA-DYFAhdbr.js +78 -0
  123. package/dist/assets/xychartDiagram-PMCCYNJV-DeXwX6Cz.js +7 -0
  124. package/dist/index.html +2 -2
  125. package/dist-server/browser-proxy.js +2 -1
  126. package/dist-server/container-mcp.js +1047 -173
  127. package/dist-server/drivers/agents-proxy.js +16121 -1504
  128. package/dist-server/drivers/phone-proxy.js +33 -2
  129. package/dist-server/enterprise/LICENSE +32 -0
  130. package/dist-server/enterprise/server/index.js +5 -5
  131. package/dist-server/index.js +16134 -7446
  132. package/dist-server/local-computer-proxy.js +3 -3
  133. package/dist-server/local-computer.js +53 -17
  134. package/dist-server/mcp-server.js +3 -1
  135. package/dist-server/openmausbot.js +9353 -6124
  136. package/dist-server/pair-cli.js +9353 -6124
  137. package/dist-server/permission-proxy.js +29 -9
  138. package/dist-server/server/admin-activity.js +410 -0
  139. package/dist-server/server/attachments.js +55 -0
  140. package/dist-server/server/auto-approve.js +4 -3
  141. package/dist-server/server/auto-vm-claims.js +1 -0
  142. package/dist-server/server/bot-package.js +18 -292
  143. package/dist-server/server/bot-profile.js +5 -17
  144. package/dist-server/server/bot-visibility.js +462 -0
  145. package/dist-server/server/box-create-idempotency.js +3 -3
  146. package/dist-server/server/box.js +59 -56
  147. package/dist-server/server/browser-proxy.js +3 -2
  148. package/dist-server/server/browser-runtime.js +38 -2
  149. package/dist-server/server/channel-queue.js +2 -0
  150. package/dist-server/server/cli-prompts.js +24 -2
  151. package/dist-server/server/cli.js +81 -12
  152. package/dist-server/server/command-allowlist.js +154 -0
  153. package/dist-server/server/composio.js +49 -11
  154. package/dist-server/server/computer-wait.js +22 -9
  155. package/dist-server/server/config.js +133 -17
  156. package/dist-server/server/connector-verdict.js +141 -0
  157. package/dist-server/server/container-computer.js +1 -1
  158. package/dist-server/server/decision-log.js +209 -48
  159. package/dist-server/server/default-model-selection.js +29 -3
  160. package/dist-server/server/delegations.js +97 -44
  161. package/dist-server/server/drivers/acp/core.js +163 -33
  162. package/dist-server/server/drivers/acp/grok.js +4 -3
  163. package/dist-server/server/drivers/agents-call.js +1162 -0
  164. package/dist-server/server/drivers/agents-catalog.js +689 -0
  165. package/dist-server/server/drivers/agents-client.js +28 -0
  166. package/dist-server/server/drivers/agents-proxy.js +18 -1722
  167. package/dist-server/server/drivers/boxagent.js +174 -36
  168. package/dist-server/server/drivers/builtIn.js +2 -0
  169. package/dist-server/server/drivers/chat-box-tools.js +90 -0
  170. package/dist-server/server/drivers/chat-images.js +54 -0
  171. package/dist-server/server/drivers/chat-mcp-tools.js +55 -10
  172. package/dist-server/server/drivers/chat-tool-approval.js +70 -18
  173. package/dist-server/server/drivers/claude.js +28 -8
  174. package/dist-server/server/drivers/codex-instructions.js +48 -6
  175. package/dist-server/server/drivers/codex-mcp-names.js +44 -0
  176. package/dist-server/server/drivers/codex-tool-surface.js +20 -0
  177. package/dist-server/server/drivers/codex.js +121 -34
  178. package/dist-server/server/drivers/grok.js +2 -1
  179. package/dist-server/server/drivers/mistral.js +115 -0
  180. package/dist-server/server/drivers/openai-chat.js +155 -32
  181. package/dist-server/server/drivers/openai-compat.js +16 -8
  182. package/dist-server/server/drivers/permission-command.js +35 -0
  183. package/dist-server/server/drivers/phone-proxy.js +47 -2
  184. package/dist-server/server/drivers/pi.js +75 -4
  185. package/dist-server/server/drivers/prompt-split.js +87 -0
  186. package/dist-server/server/enterprise.js +97 -16
  187. package/dist-server/server/external-runtime.js +83 -0
  188. package/dist-server/server/fleet.js +1 -1
  189. package/dist-server/server/group-thread-usage.js +103 -0
  190. package/dist-server/server/guarded-requests.js +60 -0
  191. package/dist-server/server/harness/http.js +61 -0
  192. package/dist-server/server/harness/registry.js +1 -0
  193. package/dist-server/server/hosted-models.js +151 -0
  194. package/dist-server/server/hosted-slack.js +11 -0
  195. package/dist-server/server/index.js +3091 -658
  196. package/dist-server/server/local-computer.js +72 -23
  197. package/dist-server/server/managed-desktop.js +79 -14
  198. package/dist-server/server/managed-policy.js +153 -0
  199. package/dist-server/server/mcp-bridge.js +6 -6
  200. package/dist-server/server/message-db.js +28 -0
  201. package/dist-server/server/model-context-window.js +7 -0
  202. package/dist-server/server/model-prices.js +121 -0
  203. package/dist-server/server/new-bot-defaults.js +115 -0
  204. package/dist-server/server/notify.js +10 -1
  205. package/dist-server/server/org-library.js +1051 -0
  206. package/dist-server/server/package-export.js +627 -39
  207. package/dist-server/server/package-import.js +458 -0
  208. package/dist-server/server/package-parts.js +87 -0
  209. package/dist-server/server/peer-approval.js +16 -7
  210. package/dist-server/server/peer-roster.js +23 -2
  211. package/dist-server/server/presets.js +492 -0
  212. package/dist-server/server/provider-key-check.js +3 -2
  213. package/dist-server/server/published-teams.js +80 -0
  214. package/dist-server/server/recent-work.js +15 -0
  215. package/dist-server/server/request-auth.js +96 -0
  216. package/dist-server/server/room-handoffs.js +44 -14
  217. package/dist-server/server/routes/bot-presets.js +25 -0
  218. package/dist-server/server/routes/hosted-slack.js +20 -0
  219. package/dist-server/server/routes/table.js +14 -0
  220. package/dist-server/server/routine-requests.js +6 -3
  221. package/dist-server/server/routines.js +63 -1
  222. package/dist-server/server/section-context.js +10 -0
  223. package/dist-server/server/skills.js +34 -61
  224. package/dist-server/server/spend.js +111 -16
  225. package/dist-server/server/steer-queue.js +9 -3
  226. package/dist-server/server/store.js +550 -35
  227. package/dist-server/server/surface.js +10 -4
  228. package/dist-server/server/system-prompt.js +12 -4
  229. package/dist-server/server/team-backup.js +16 -3
  230. package/dist-server/server/team-computers.js +10 -0
  231. package/dist-server/server/team-library.js +6 -2
  232. package/dist-server/server/team-manifest.js +4 -3
  233. package/dist-server/server/team-setup-requests.js +16 -5
  234. package/dist-server/server/thread-events.js +17 -1
  235. package/dist-server/server/thread-starters.js +53 -0
  236. package/dist-server/server/turn-context.js +2 -0
  237. package/dist-server/server/turn-watchdog.js +12 -3
  238. package/dist-server/server/usage-ledger.js +43 -9
  239. package/dist-server/server/vps-computer.js +139 -51
  240. package/dist-server/server/vps-container-mcp.js +7 -0
  241. package/dist-server/server/vps-ssh.js +36 -7
  242. package/dist-server/server/workspace-backup-policy.js +21 -2
  243. package/dist-server/server/workspace-backup.js +7 -4
  244. package/dist-server/server/workspace.js +1 -1
  245. package/dist-server/shared/approval-mode.js +1 -1
  246. package/dist-server/shared/ask-question.js +188 -12
  247. package/dist-server/shared/bot-profile.js +15 -0
  248. package/dist-server/shared/command-allowlist.js +1 -0
  249. package/dist-server/shared/credential-request.js +1 -1
  250. package/dist-server/shared/mention-boundary.js +15 -0
  251. package/dist-server/shared/package-format.js +967 -0
  252. package/dist-server/shared/routines.js +7 -1
  253. package/dist-server/shared/skill-md.js +64 -0
  254. package/dist-server/shared/team-backup.js +9 -0
  255. package/dist-server/shared/wire.js +4 -0
  256. package/dist-server/src/lib/composer-attachments.js +16 -0
  257. package/dist-server/vps-container-mcp.js +1147 -179
  258. package/enterprise/README.md +33 -12
  259. package/enterprise/server/index.js +5 -5
  260. package/package.json +1 -1
  261. package/dist/assets/index-Ba9G44HI.js +0 -310
  262. package/dist/assets/index-CkRNp7wX.css +0 -1
@@ -0,0 +1,121 @@
1
+ import { billableFor } from "./prices.js";
2
+ const AS_OF = "2026-09-23";
3
+ const OPENAI = "https://developers.openai.com/api/docs/pricing";
4
+ const ANTHROPIC = "https://platform.claude.com/docs/en/about-claude/pricing";
5
+ const XAI = "https://docs.x.ai/developers/models";
6
+ const GOOGLE = "https://ai.google.dev/gemini-api/docs/pricing";
7
+ const MINIMAX = "https://platform.minimax.io/docs/guides/pricing-paygo";
8
+ // OpenRouter's FAQ (https://openrouter.ai/docs/faq) says it passes provider
9
+ // prices through without markup, but its live list does discount some
10
+ // models, so these are read from that list rather than copied from the
11
+ // vendors. Its 5.5% fee on buying credits is not a per-token price.
12
+ const OPENROUTER = "https://openrouter.ai/api/v1/models";
13
+ const price = (source, input, cached, output, extra = {}) => ({
14
+ inputPerMillion: input,
15
+ cachedInputPerMillion: cached,
16
+ outputPerMillion: output,
17
+ asOf: AS_OF,
18
+ source,
19
+ ...extra,
20
+ });
21
+ /** Keyed by the model id as a bot's selection names it, lower-cased. */
22
+ export const LIST_PRICES = {
23
+ // OpenAI, Standard tier, short context (<272K input tokens).
24
+ "gpt-6-astra": price(OPENAI, 10, 1, 50),
25
+ // Labelled promotional pricing on the source page, with no end date given.
26
+ "gpt-5.6-sol": price(OPENAI, 4, 0.4, 20),
27
+ "gpt-5.6-terra": price(OPENAI, 2, 0.2, 12),
28
+ "gpt-5.6-luna": price(OPENAI, 0.2, 0.02, 1.2),
29
+ "gpt-5.5": price(OPENAI, 5, 0.5, 30),
30
+ "gpt-5.4": price(OPENAI, 2.5, 0.25, 15),
31
+ "gpt-5.4-mini": price(OPENAI, 0.75, 0.075, 4.5),
32
+ "gpt-5.3-codex": price(OPENAI, 1.75, 0.175, 14),
33
+ // gpt-5.3-codex-spark has no published API price: unpriced.
34
+ // Anthropic: base input, cache hit, output. No long-context tier.
35
+ "claude-fable-5-1": price(ANTHROPIC, 10, 0.25, 50),
36
+ "claude-fable-5": price(ANTHROPIC, 10, 1, 50),
37
+ "claude-opus-5": price(ANTHROPIC, 5, 0.5, 25),
38
+ "claude-sonnet-5": price(ANTHROPIC, 2, 0.2, 10),
39
+ "claude-haiku-4-5": price(ANTHROPIC, 1, 0.1, 5),
40
+ "claude-haiku-4-5-20251001": price(ANTHROPIC, 1, 0.1, 5),
41
+ // xAI, under 200k prompt tokens. grok-4, grok-4-fast and grok-3-mini are
42
+ // retired or unlisted: unpriced.
43
+ "grok-4.7": price(XAI, 2, 0.5, 6),
44
+ "grok-4.6": price(XAI, 2, 0.5, 6),
45
+ "grok-4.5": price(XAI, 2, 0.3, 6),
46
+ // Google Gemini API, paid tier, prompts up to 200k tokens.
47
+ "gemini-2.5-pro": price(GOOGLE, 1.25, 0.125, 10),
48
+ "gemini-2.5-flash": price(GOOGLE, 0.3, 0.03, 2.5),
49
+ "gemini-3.1-pro-preview": price(GOOGLE, 2, 0.2, 12),
50
+ "gemini-3.8-flash": price(GOOGLE, 0.75, 0.075, 3.75, {
51
+ changes: [{ from: "2027-01-01", inputPerMillion: 1.5, cachedInputPerMillion: 0.15, outputPerMillion: 7.5 }],
52
+ }),
53
+ // MiniMax, international pay-as-you-go, Standard. M3 up to 512k input
54
+ // tokens, at the price charged (the page shows it as 50% off, permanently).
55
+ "minimax-m3": price(MINIMAX, 0.3, 0.06, 1.2),
56
+ "minimax-m2.7": price(MINIMAX, 0.3, 0.06, 1.2),
57
+ "minimax-m2.7-highspeed": price(MINIMAX, 0.6, 0.06, 2.4),
58
+ // OpenRouter ids, as its live model list prices them.
59
+ "openai/gpt-6-astra": price(OPENROUTER, 10, 1, 50),
60
+ "openai/gpt-5.6-sol": price(OPENROUTER, 2, 0.2, 10),
61
+ "openai/gpt-5.6-terra": price(OPENROUTER, 2, 0.2, 12),
62
+ "openai/gpt-5.6-luna": price(OPENROUTER, 0.2, 0.02, 1.2),
63
+ "openai/gpt-5.5": price(OPENROUTER, 5, 0.5, 30),
64
+ "openai/gpt-5.4": price(OPENROUTER, 2.5, 0.25, 15),
65
+ "openai/gpt-5.4-mini": price(OPENROUTER, 0.75, 0.075, 4.5),
66
+ "openai/gpt-5.3-codex": price(OPENROUTER, 1.75, 0.175, 14),
67
+ "anthropic/claude-fable-5.1": price(OPENROUTER, 10, 0.25, 50),
68
+ "anthropic/claude-fable-5": price(OPENROUTER, 10, 1, 50),
69
+ "anthropic/claude-opus-5": price(OPENROUTER, 5, 0.5, 25),
70
+ "anthropic/claude-sonnet-5": price(OPENROUTER, 2, 0.2, 10),
71
+ "anthropic/claude-haiku-4.5": price(OPENROUTER, 1, 0.1, 5),
72
+ "x-ai/grok-4.7": price(OPENROUTER, 1.6, 0.4, 4.8),
73
+ "x-ai/grok-4.6": price(OPENROUTER, 2, 0.5, 6),
74
+ "x-ai/grok-4.5": price(OPENROUTER, 2, 0.3, 6),
75
+ "google/gemini-2.5-pro": price(OPENROUTER, 1.25, 0.125, 10),
76
+ "google/gemini-2.5-flash": price(OPENROUTER, 0.3, 0.03, 2.5),
77
+ "google/gemini-3.1-pro-preview": price(OPENROUTER, 2, 0.2, 12),
78
+ "google/gemini-3.8-flash": price(OPENROUTER, 0.75, 0.075, 3.75),
79
+ "minimax/minimax-m3": price(OPENROUTER, 0.3, 0.06, 1.2),
80
+ "minimax/minimax-m2.7": price(OPENROUTER, 0.3, 0.06, 1.2),
81
+ };
82
+ /** Catalog ids that name a listed model with a setting attached: the
83
+ * Antigravity picker offers Gemini 3.8 Flash at three thinking levels. */
84
+ const ALIASES = {
85
+ "gemini-3.8-flash-high": "gemini-3.8-flash",
86
+ "gemini-3.8-flash-medium": "gemini-3.8-flash",
87
+ "gemini-3.8-flash-low": "gemini-3.8-flash",
88
+ };
89
+ /** The list price for a model at a moment, or null when it is not listed. */
90
+ export function listPriceFor(model, at = new Date()) {
91
+ const key = model.trim().toLowerCase();
92
+ const entry = LIST_PRICES[ALIASES[key] ?? key];
93
+ if (!entry)
94
+ return null;
95
+ const day = at.toISOString().slice(0, 10);
96
+ const change = entry.changes?.filter((candidate) => candidate.from <= day).at(-1);
97
+ const current = change ?? entry;
98
+ return {
99
+ inputPerMillion: current.inputPerMillion,
100
+ outputPerMillion: current.outputPerMillion,
101
+ ...(current.cachedInputPerMillion !== undefined ? { cachedInputPerMillion: current.cachedInputPerMillion } : {}),
102
+ };
103
+ }
104
+ /** The price an estimate uses: the operator's own price for this exact
105
+ * model (Settings → Usage → prices, `driver/model` or model id), then the
106
+ * built-in list, then the operator's `default` row. */
107
+ export function estimatePriceFor(turn, operatorPrices, at = new Date()) {
108
+ return operatorPrices?.[`${turn.driverKind}/${turn.model}`] ?? operatorPrices?.[turn.model] ??
109
+ listPriceFor(turn.model, at) ?? operatorPrices?.default ?? null;
110
+ }
111
+ /** What the ledger books for a settled turn: the engine's own cost when it
112
+ * reported one, else an estimate, else null (unpriced). */
113
+ export function ledgerCost(turn, operatorPrices, at = new Date()) {
114
+ if (typeof turn.costUsd === "number" && Number.isFinite(turn.costUsd) && turn.costUsd >= 0) {
115
+ return { costUsd: turn.costUsd, costSource: "reported" };
116
+ }
117
+ const unit = estimatePriceFor(turn, operatorPrices, at);
118
+ if (!unit)
119
+ return { costUsd: null };
120
+ return { costUsd: billableFor(turn, { [turn.model]: unit }), costSource: "estimated" };
121
+ }
@@ -0,0 +1,115 @@
1
+ import { z } from "zod";
2
+ import { profilePatchSchema, fitsOnOneLine } from "./bot-profile.js";
3
+ import { EFFORT_LEVELS } from "../shared/wire.js";
4
+ import { isModelVariant } from "./contracts.js";
5
+ import { normalizeCronSchedule } from "../shared/routine-schedule.js";
6
+ const strings = (max, length) => z.array(z.string().max(length)).max(max);
7
+ const clock = z.string().regex(/^(?:[01]\d|2[0-3]):[0-5]\d$/);
8
+ const weekdays = z.array(z.number().int().min(0).max(6)).min(1).max(7);
9
+ const timestamp = z.number().int().nonnegative().max(8_640_000_000_000_000);
10
+ export const botDefaultModelSchema = z.object({
11
+ instanceId: z.string().trim().min(1).max(200),
12
+ model: z.string().trim().min(1).max(500),
13
+ effort: z.enum(EFFORT_LEVELS).optional(),
14
+ variant: z.string().refine(isModelVariant, "invalid model variant").optional(),
15
+ }).strict().refine(value => value.effort === undefined || value.variant === undefined, "choose either a model variant or an effort level");
16
+ // Preferences only. Consent flags, live grants, bot IDs and execution state
17
+ // cannot be stored here and therefore cannot be replayed as permission grants.
18
+ export const botDefaultsProfileSchema = profilePatchSchema.extend({
19
+ name: z.string().max(100).refine(fitsOnOneLine, "name must fit on one line").optional(),
20
+ section: z.string().trim().max(60).optional(),
21
+ color: z.enum(["green", "blue", "red", "orange", "purple", "cyan", "pink", "yellow", "teal", "coral"]).optional(),
22
+ mascotExpression: z.string().max(60).nullable().optional(),
23
+ modelSelection: botDefaultModelSchema.optional(),
24
+ computer: z.enum(["cloud", "vm", "local", "browser", "off"]).nullable().optional(),
25
+ cloudBackend: z.enum(["box", "vps"]).optional(),
26
+ autoStartVps: z.boolean().optional(),
27
+ cwd: z.string().max(4096).nullable().optional(),
28
+ approvalMode: z.enum(["ask", "auto", "full", "custom"]).optional(),
29
+ alwaysAllow: strings(200, 500).optional(),
30
+ chiefOfStaff: z.boolean().optional(),
31
+ managedSections: strings(100, 60).optional(),
32
+ approvePeerComms: z.boolean().optional(),
33
+ peers: strings(1000, 100).nullable().optional(),
34
+ composio: z.boolean().optional(),
35
+ browser: z.boolean().optional(),
36
+ browserProfile: z.string().max(100).nullable().optional(),
37
+ mcpServers: strings(100, 100).nullable().optional(),
38
+ parkDirectMessages: z.boolean().optional(),
39
+ }).strict();
40
+ const scheduleSchema = z.discriminatedUnion("type", [
41
+ z.object({ type: z.literal("once"), at: timestamp }).strict(),
42
+ z.object({ type: z.literal("daily"), time: clock, weekdays }).strict(),
43
+ z.object({
44
+ type: z.literal("interval"), everyMinutes: z.number().int().min(5).max(1440), anchorAt: timestamp,
45
+ weekdays: weekdays.nullable().optional(),
46
+ window: z.object({ start: clock, end: clock }).strict().nullable().optional(),
47
+ endsAt: timestamp.nullable().optional(),
48
+ }).strict(),
49
+ z.object({ type: z.literal("cron"), expression: z.string().max(256), timeZone: z.string().max(128) }).strict(),
50
+ ]).superRefine((value, ctx) => {
51
+ if (value.type === "cron") {
52
+ try {
53
+ normalizeCronSchedule(value);
54
+ }
55
+ catch (error) {
56
+ ctx.addIssue({ code: "custom", message: String(error) });
57
+ }
58
+ }
59
+ if (value.type === "interval" && value.window) {
60
+ const minutes = (time) => Number(time.slice(0, 2)) * 60 + Number(time.slice(3));
61
+ if (minutes(value.window.end) - minutes(value.window.start) < value.everyMinutes) {
62
+ ctx.addIssue({ code: "custom", message: "The interval must fit inside its time window" });
63
+ }
64
+ }
65
+ });
66
+ export const botRoutineTemplateSchema = z.object({
67
+ name: z.string().trim().min(1).max(80), prompt: z.string().trim().min(1).max(20_000),
68
+ schedule: scheduleSchema, enabled: z.boolean().optional(),
69
+ runOn: z.enum(["maus", "cloud"]).optional(),
70
+ durationMinutes: z.number().int().min(5).max(240).optional(),
71
+ timeoutMinutes: z.number().min(1).max(1440).nullable().optional(),
72
+ overlap: z.enum(["skip", "queue"]).optional(),
73
+ attachments: z.array(z.object({
74
+ id: z.string().min(1).max(200), kind: z.enum(["file", "image"]),
75
+ name: z.string().min(1).max(255), path: z.string().min(1).max(4096), size: z.number().nonnegative(),
76
+ }).strict()).max(50).optional(),
77
+ }).strict();
78
+ export const botSkillTemplateSchema = z.object({
79
+ name: z.string().regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/).max(64),
80
+ description: z.string().max(1024),
81
+ warnings: strings(100, 2000).default([]),
82
+ source: z.string().min(1).max(2000),
83
+ text: z.string().refine(value => Buffer.byteLength(value, "utf8") <= 262_144, "Skill exceeds 256 KiB"),
84
+ enabled: z.boolean(),
85
+ }).strict();
86
+ export const newBotDefaultsSchema = z.object({
87
+ profile: botDefaultsProfileSchema.default({}),
88
+ memory: z.record(z.string().regex(/^(?:MEMORY\.md|memory\/[a-zA-Z0-9_-]+\.md)$/), z.string().refine(value => Buffer.byteLength(value, "utf8") <= 262_144, "Memory file exceeds 256 KiB"))
89
+ .refine(value => Object.keys(value).length <= 100, "At most 100 memory files").default({}),
90
+ skills: z.array(botSkillTemplateSchema).max(100).default([]),
91
+ routines: z.array(botRoutineTemplateSchema).max(100).default([]),
92
+ }).strict().refine(value => Buffer.byteLength(JSON.stringify(value), "utf8") <= 900_000, "Bot defaults must fit within 900 KB");
93
+ /** Explicit values (including empty values) win. A resolved renderer draft
94
+ * opts out so deleted fields and template extras are not restored on POST. */
95
+ export function resolveBotCreationDefaults(saved, body) {
96
+ if (body.useDefaults !== undefined && typeof body.useDefaults !== "boolean") {
97
+ throw Object.assign(new Error("useDefaults must be true or false"), { status: 400 });
98
+ }
99
+ const template = newBotDefaultsSchema.parse(body.useDefaults === false ? {} : saved ?? {});
100
+ const checked = botDefaultsProfileSchema.safeParse(body.settings === undefined ? {} : body.settings);
101
+ if (!checked.success)
102
+ throw Object.assign(new Error(checked.error.message), { status: 400 });
103
+ const explicit = checked.data;
104
+ const profile = { ...template.profile, ...explicit };
105
+ for (const key of ["name", "title", "description", "modelSelection", "section"]) {
106
+ if (Object.hasOwn(body, key))
107
+ Object.assign(profile, { [key]: key === "section" && body[key] === null ? "" : body[key] });
108
+ }
109
+ const resolved = botDefaultsProfileSchema.safeParse(profile);
110
+ if (!resolved.success)
111
+ throw Object.assign(new Error(resolved.error.message), { status: 400 });
112
+ if (!resolved.data.name?.trim())
113
+ delete resolved.data.name;
114
+ return { ...template, profile: resolved.data };
115
+ }
@@ -33,6 +33,13 @@ export function blockedTarget(bot, room) {
33
33
  return { threadId: bot.threadId };
34
34
  return { threadId: room.threadId, group: { id: room.id, name: room.name } };
35
35
  }
36
+ /** A workspace spend notice (server/spend.ts decides when). It opens the
37
+ * thread whose turn crossed the line, so clicking it lands somewhere real,
38
+ * but it is the workspace's news, not that bot's: the bot's notification
39
+ * toggle does not silence it. */
40
+ export function buildSpendNotification(bot, threadId, text) {
41
+ return { kind: "spend", botId: bot.id, botName: bot.name, threadId, title: text.title, body: summarize(text.body, 200) };
42
+ }
36
43
  /** Build the frame for one event, or null when it should stay quiet.
37
44
  *
38
45
  * Kept pure and separate from the event fold so the policy — which is the
@@ -62,7 +69,9 @@ export function buildNotification(kind, bot, threadId, detail, extra) {
62
69
  ? `${who} couldn't start`
63
70
  : kind === "incident"
64
71
  ? `${who} hit a problem`
65
- : `${who} finished`;
72
+ : kind === "delegation-settled"
73
+ ? `${who} resumed with results`
74
+ : `${who} finished`;
66
75
  // A "finished" with nothing to say is not worth a notification — the
67
76
  // badge in the sidebar already carries that much.
68
77
  if (kind === "done" && !body)