openmausbot 0.1.78 → 0.1.80

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 (56) hide show
  1. package/dist/assets/index-Cu8BkIfo.js +305 -0
  2. package/dist/assets/{index-BqDJqf2C.js → index-D6RZKWks.js} +1 -1
  3. package/dist/assets/index-tfpeJAIG.css +1 -0
  4. package/dist/index.html +2 -2
  5. package/dist-server/container-mcp.js +11 -5
  6. package/dist-server/drivers/agents-proxy.js +21 -6
  7. package/dist-server/enterprise/server/index.js +0 -1
  8. package/dist-server/index.js +15942 -6859
  9. package/dist-server/local-computer.js +0 -1
  10. package/dist-server/mcp-server.js +8 -1
  11. package/dist-server/openmausbot.js +9303 -786
  12. package/dist-server/pair-cli.js +9303 -786
  13. package/dist-server/proxy-paths.js +0 -1
  14. package/dist-server/server/box.js +98 -41
  15. package/dist-server/server/browser-engine.js +1 -1
  16. package/dist-server/server/browser-runtime.js +11 -3
  17. package/dist-server/server/browser-tool-shape.js +72 -0
  18. package/dist-server/server/claude-accounts.js +1 -0
  19. package/dist-server/server/cli-setup.js +1 -1
  20. package/dist-server/server/composio.js +18 -0
  21. package/dist-server/server/config.js +16 -4
  22. package/dist-server/server/container-computer.js +0 -12
  23. package/dist-server/server/drivers/acp/core.js +4 -19
  24. package/dist-server/server/drivers/agents-proxy.js +27 -2
  25. package/dist-server/server/drivers/boxagent.js +48 -4
  26. package/dist-server/server/drivers/chat-mcp-tools.js +368 -0
  27. package/dist-server/server/drivers/chat-tool-approval.js +42 -0
  28. package/dist-server/server/drivers/claude.js +86 -38
  29. package/dist-server/server/drivers/codex.js +225 -75
  30. package/dist-server/server/drivers/grok.js +4 -0
  31. package/dist-server/server/drivers/minimax.js +11 -3
  32. package/dist-server/server/drivers/openai-chat-protocol.js +92 -0
  33. package/dist-server/server/drivers/openai-chat.js +332 -88
  34. package/dist-server/server/drivers/openai-compat.js +4 -0
  35. package/dist-server/server/drivers/pi.js +1 -9
  36. package/dist-server/server/harness/registry.js +2 -2
  37. package/dist-server/server/index.js +267 -50
  38. package/dist-server/server/managed-desktop.js +205 -0
  39. package/dist-server/server/model-context-window.js +20 -0
  40. package/dist-server/server/proxy-paths.js +0 -1
  41. package/dist-server/server/redact.js +1 -0
  42. package/dist-server/server/room-handoffs.js +57 -9
  43. package/dist-server/server/store.js +13 -1
  44. package/dist-server/server/tts/chatterbox.js +83 -0
  45. package/dist-server/server/tts/index.js +45 -12
  46. package/dist-server/server/workspace.js +12 -2
  47. package/dist-server/shared/ask-question.js +28 -0
  48. package/dist-server/shared/computer-contention.js +17 -0
  49. package/dist-server/vps-container-mcp.js +11 -5
  50. package/enterprise/server/index.js +0 -1
  51. package/package.json +1 -1
  52. package/dist/assets/index-DjwAroIZ.js +0 -305
  53. package/dist/assets/index-Pbb6Ao0s.css +0 -1
  54. package/dist-server/computer-proxy.js +0 -1196
  55. package/dist-server/server/computer-proxy.js +0 -1070
  56. package/dist-server/server/remote-computer.js +0 -170
@@ -1,170 +0,0 @@
1
- // Shared provisioning and shell contract for the cloud computer's Cua Driver.
2
- // The box command API is the transport boundary: the daemon stays loopback-only
3
- // inside the VM and OpenMausBot never exposes another inbound port.
4
- export const REMOTE_CUA_VERSION = "0.20.0";
5
- export const REMOTE_CUA_EXECUTABLE = "/opt/ogb/cua-driver";
6
- export const REMOTE_CUA_SOCKET = "/opt/ogb/run/cua.sock";
7
- export const REMOTE_CUA_SESSION = "openmausbot";
8
- export const REMOTE_CDP_HELPER = "/opt/ogb/openmausbot-cdp.mjs";
9
- const REMOTE_CUA_WHEELS = {
10
- x86_64: {
11
- url: "https://files.pythonhosted.org/packages/fa/d7/a43008a328a40c85e7bc706fc20235b9abedc75e28b413817655153157ff/cua_driver-0.20.0-py3-none-manylinux_2_31_x86_64.whl",
12
- sha256: "f60c35696a37f37ac954935e478ae4754f220856d022036625c9400d72185961",
13
- },
14
- aarch64: {
15
- url: "https://files.pythonhosted.org/packages/94/9d/1c1838b69067e83266c3d2aae02d74eef353a43dc8644884ccf03fe7f933/cua_driver-0.20.0-py3-none-manylinux_2_31_aarch64.whl",
16
- sha256: "48833bc5e4c60e701fc9eefb57dbac36ec77ef3990f816fbbe85b4e954af2c77",
17
- },
18
- };
19
- const CDP_HELPER_SOURCE = String.raw `const [action, encoded = ""] = process.argv.slice(2);
20
- const input = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8") || "{}");
21
- const pages = await fetch("http://127.0.0.1:9222/json/list").then((r) => r.json());
22
- const page = pages.find((item) => item.type === "page" && item.webSocketDebuggerUrl);
23
- if (!page) throw new Error("no debuggable browser page");
24
- if (input.url && page.url !== input.url) throw new Error("page changed; take a new browser snapshot");
25
- const socket = new WebSocket(page.webSocketDebuggerUrl);
26
- await new Promise((resolve, reject) => {
27
- socket.addEventListener("open", resolve, { once: true });
28
- socket.addEventListener("error", () => reject(new Error("DevTools connection failed")), { once: true });
29
- });
30
- let nextId = 0;
31
- const pending = new Map();
32
- socket.addEventListener("message", (event) => {
33
- const message = JSON.parse(String(event.data));
34
- if (!message.id) return;
35
- const waiter = pending.get(message.id);
36
- if (!waiter) return;
37
- pending.delete(message.id);
38
- if (message.error) waiter.reject(new Error(message.error.message));
39
- else waiter.resolve(message.result ?? {});
40
- });
41
- const send = (method, params = {}) => new Promise((resolve, reject) => {
42
- const id = ++nextId;
43
- pending.set(id, { resolve, reject });
44
- socket.send(JSON.stringify({ id, method, params }));
45
- });
46
- const refId = (value) => {
47
- const match = /^b(\d+)$/.exec(String(value ?? ""));
48
- if (!match) throw new Error("invalid or stale browser ref; take a new snapshot");
49
- return Number(match[1]);
50
- };
51
- if (action === "snapshot") {
52
- await send("Accessibility.enable");
53
- const { nodes = [] } = await send("Accessibility.getFullAXTree", { depth: 14 });
54
- const useful = new Set(["button", "checkbox", "combobox", "heading", "link", "menuitem", "radio", "searchbox", "slider", "spinbutton", "switch", "tab", "textbox"]);
55
- const elements = [];
56
- for (const node of nodes) {
57
- const role = String(node.role?.value ?? "").toLowerCase();
58
- const name = String(node.name?.value ?? "").replace(/\s+/g, " ").trim().slice(0, 180);
59
- const backend = Number(node.backendDOMNodeId ?? 0);
60
- if (!backend || !useful.has(role) || (!name && role !== "textbox" && role !== "searchbox")) continue;
61
- const disabled = node.properties?.some((property) => property.name === "disabled" && property.value?.value === true) ?? false;
62
- elements.push({ ref: "b" + backend, role, name: name || "unnamed", disabled });
63
- if (elements.length >= 250) break;
64
- }
65
- process.stdout.write(JSON.stringify({ title: String(page.title ?? "").slice(0, 200), url: page.url, elements }));
66
- } else if (action === "click") {
67
- const backendNodeId = refId(input.ref);
68
- const { model } = await send("DOM.getBoxModel", { backendNodeId });
69
- const quad = model?.border ?? model?.content;
70
- if (!Array.isArray(quad) || quad.length < 8) throw new Error("element is not visible; take a new snapshot");
71
- const x = (quad[0] + quad[2] + quad[4] + quad[6]) / 4;
72
- const y = (quad[1] + quad[3] + quad[5] + quad[7]) / 4;
73
- await send("Input.dispatchMouseEvent", { type: "mousePressed", x, y, button: "left", clickCount: 1 });
74
- await send("Input.dispatchMouseEvent", { type: "mouseReleased", x, y, button: "left", clickCount: 1 });
75
- process.stdout.write(JSON.stringify({ ok: true, ref: input.ref }));
76
- } else if (action === "fill") {
77
- const backendNodeId = refId(input.ref);
78
- await send("DOM.focus", { backendNodeId });
79
- await send("Input.dispatchKeyEvent", { type: "keyDown", key: "a", code: "KeyA", modifiers: 2 });
80
- await send("Input.dispatchKeyEvent", { type: "keyUp", key: "a", code: "KeyA", modifiers: 2 });
81
- await send("Input.dispatchKeyEvent", { type: "keyDown", key: "Backspace", code: "Backspace" });
82
- await send("Input.dispatchKeyEvent", { type: "keyUp", key: "Backspace", code: "Backspace" });
83
- await send("Input.insertText", { text: String(input.text ?? "") });
84
- process.stdout.write(JSON.stringify({ ok: true, ref: input.ref }));
85
- } else {
86
- throw new Error("unknown browser action");
87
- }
88
- socket.close();`;
89
- const shellQuote = (value) => `'${value.replace(/'/g, "'\\''")}'`;
90
- export const MAX_REMOTE_COMMAND_LENGTH = 4_000;
91
- /** Run a user- or model-supplied command without inheriting provider or
92
- * account credentials from an older box image. Keep this shared by the bot
93
- * tool and the owner's Computer-panel console so the two boundaries cannot
94
- * drift apart. */
95
- export function isolatedRemoteCommand(command) {
96
- return [
97
- "exec env -i",
98
- 'HOME="$HOME"',
99
- 'USER="${USER:-$(id -un)}"',
100
- 'LOGNAME="${LOGNAME:-${USER:-$(id -un)}}"',
101
- 'PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"',
102
- 'DISPLAY="${DISPLAY:-:0}"',
103
- 'XAUTHORITY="${XAUTHORITY:-$HOME/.Xauthority}"',
104
- 'XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"',
105
- 'DBUS_SESSION_BUS_ADDRESS="${DBUS_SESSION_BUS_ADDRESS:-}"',
106
- "/bin/bash -c",
107
- shellQuote(command),
108
- ].join(" ");
109
- }
110
- /** Start the already-installed daemon after a box resume. This is cheap when
111
- * it is healthy and intentionally does not install anything on the hot path. */
112
- export function ensureRemoteCuaCommand() {
113
- return [
114
- `if [ -x ${REMOTE_CUA_EXECUTABLE} ]; then`,
115
- ` mkdir -p ${REMOTE_CUA_SOCKET.slice(0, REMOTE_CUA_SOCKET.lastIndexOf("/"))}`,
116
- ` if ! ${REMOTE_CUA_EXECUTABLE} status --socket ${REMOTE_CUA_SOCKET} >/dev/null 2>&1; then`,
117
- ` rm -f ${REMOTE_CUA_SOCKET}`,
118
- ' display=${DISPLAY:-$(find /tmp/.X11-unix -maxdepth 1 -name "X*" -printf ":%f\\n" 2>/dev/null | sed "s/:X/:/" | head -1)}',
119
- ' display=${display:-:0}',
120
- ` nohup env HOME="$HOME" DISPLAY="$display" CUA_DRIVER_INSTALL_CHANNEL=python_package CUA_DRIVER_RS_TELEMETRY_ENABLED=0 ${REMOTE_CUA_EXECUTABLE} serve --socket ${REMOTE_CUA_SOCKET} --permission-mode standard > /tmp/ogb-cua-driver.log 2>&1 &`,
121
- ` for i in 1 2 3 4 5 6 7 8 9 10; do ${REMOTE_CUA_EXECUTABLE} status --socket ${REMOTE_CUA_SOCKET} >/dev/null 2>&1 && break; sleep 0.2; done`,
122
- " fi",
123
- "fi",
124
- ].join("\n");
125
- }
126
- /** Idempotent setup. The exact wheel is verified before its bundled native
127
- * executable is installed; installation remains asynchronous so first-time
128
- * provisioning does not block the desktop for several minutes. */
129
- export function remoteComputerBootstrapCommand(botName) {
130
- const helper = Buffer.from(CDP_HELPER_SOURCE).toString("base64");
131
- const installer = [
132
- "set -eu",
133
- "trap 'rm -f /tmp/ogb-cua-installing' EXIT",
134
- "sudo mkdir -p /opt/ogb/run",
135
- 'sudo chown -R "$(id -u):$(id -g)" /opt/ogb',
136
- 'arch="$(uname -m)"',
137
- `case "$arch" in x86_64) url=${shellQuote(REMOTE_CUA_WHEELS.x86_64.url)}; sha=${REMOTE_CUA_WHEELS.x86_64.sha256} ;; aarch64|arm64) url=${shellQuote(REMOTE_CUA_WHEELS.aarch64.url)}; sha=${REMOTE_CUA_WHEELS.aarch64.sha256} ;; *) echo "unsupported architecture: $arch" >&2; exit 1 ;; esac`,
138
- 'wheel="/tmp/cua-driver-${sha}.whl"',
139
- 'curl -fsSL "$url" -o "$wheel"',
140
- 'echo "$sha $wheel" | sha256sum -c -',
141
- 'python3 - "$wheel" <<\'PY\'\nimport os, sys, zipfile\nwheel = sys.argv[1]\nwith zipfile.ZipFile(wheel) as archive:\n names = [name for name in archive.namelist() if name == "cua_driver/bin/cua-driver" or name.endswith("/cua_driver/bin/cua-driver")]\n if len(names) != 1:\n raise SystemExit("cua-driver executable missing from wheel")\n with archive.open(names[0]) as source, open("/opt/ogb/cua-driver", "wb") as target:\n target.write(source.read())\nos.chmod("/opt/ogb/cua-driver", 0o755)\nPY',
142
- `test "$(${REMOTE_CUA_EXECUTABLE} --version)" = "cua-driver ${REMOTE_CUA_VERSION}"`,
143
- `touch /opt/ogb/cua-${REMOTE_CUA_VERSION}-ready`,
144
- 'rm -f "$wheel"',
145
- ].join("\n");
146
- // The display name is untrusted. Encode the banner before composing the
147
- // nested tmux shell so substitutions/backticks can never become syntax.
148
- const banner = Buffer.from(` ▦ ${botName}'s computer — OpenMausBot`).toString("base64");
149
- const tmuxSessionCommand = [
150
- "echo",
151
- `printf %s ${shellQuote(banner)} | base64 -d`,
152
- "echo",
153
- "exec bash -i",
154
- ].join("; ");
155
- return [
156
- "if ! command -v xdotool >/dev/null || ! command -v convert >/dev/null || ! command -v curl >/dev/null || ! command -v python3 >/dev/null; then sudo apt-get update -qq || true; sudo apt-get install -y -qq ca-certificates curl python3 gnome-screenshot xclip wmctrl xdotool imagemagick scrot >/dev/null 2>&1 || true; fi",
157
- "sudo mkdir -p /opt/ogb/run",
158
- `printf %s ${shellQuote(helper)} | base64 -d | sudo tee ${REMOTE_CDP_HELPER} >/dev/null`,
159
- `sudo chmod 0755 ${REMOTE_CDP_HELPER}`,
160
- 'pkill -f "^/opt/ogb/venv/bin/python -m computer_server( |$)" >/dev/null 2>&1 || true',
161
- `[ -f /opt/ogb/cua-${REMOTE_CUA_VERSION}-ready ] || [ -f /tmp/ogb-cua-installing ] || { touch /tmp/ogb-cua-installing; nohup bash -c ${shellQuote(installer)} > /tmp/ogb-cua-install.log 2>&1 & }`,
162
- ensureRemoteCuaCommand(),
163
- `tmux has-session -t work 2>/dev/null || tmux new-session -d -s work ${shellQuote(tmuxSessionCommand)}`,
164
- "echo bootstrapped",
165
- ].join("\n");
166
- }
167
- export function semanticBrowserCommand(action, input) {
168
- const encoded = Buffer.from(JSON.stringify(input ?? {})).toString("base64url");
169
- return `node ${REMOTE_CDP_HELPER} ${action} ${shellQuote(encoded)}`;
170
- }