openmausbot 0.1.63 → 0.1.66
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.
- package/dist/assets/index-BftlaHAF.css +1 -0
- package/dist/assets/index-DuR3H-Hf.js +278 -0
- package/dist/assets/{index-C-SoIGdn.js → index-kW5L1QeO.js} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/browser-proxy.js +121 -0
- package/dist-server/container-mcp.js +4 -1
- package/dist-server/index.js +17996 -15876
- package/dist-server/openmausbot.js +752 -245
- package/dist-server/pair-cli.js +752 -245
- package/dist-server/prepare-cloudflared.js +10 -2
- package/dist-server/proxy-paths.js +1 -0
- package/dist-server/server/attachments.js +140 -16
- package/dist-server/server/browser-engine-release.js +10 -8
- package/dist-server/server/browser-engine.js +226 -26
- package/dist-server/server/browser-live.js +567 -0
- package/dist-server/server/browser-proxy.js +129 -0
- package/dist-server/server/browser-runtime.js +370 -0
- package/dist-server/server/claude-accounts.js +103 -0
- package/dist-server/server/config.js +31 -20
- package/dist-server/server/custom-domain.js +196 -0
- package/dist-server/server/drivers/claude.js +77 -19
- package/dist-server/server/drivers/codex-device-auth.js +234 -0
- package/dist-server/server/drivers/codex.js +10 -0
- package/dist-server/server/harness/bus.js +9 -4
- package/dist-server/server/harness/registry.js +15 -0
- package/dist-server/server/index.js +446 -91
- package/dist-server/server/provider-auth-sessions.js +118 -0
- package/dist-server/server/proxy-paths.js +1 -0
- package/dist-server/server/sse-fanout.js +53 -0
- package/dist-server/src/lib/composer-attachments.js +23 -6
- package/dist-server/vps-container-mcp.js +4 -1
- package/package.json +1 -1
- package/dist/assets/index-BuntoOSX.js +0 -264
- package/dist/assets/index-oPMv6a_k.css +0 -1
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// server/browser-proxy.ts
|
|
2
|
+
import { pathToFileURL } from "node:url";
|
|
3
|
+
var MAX_INPUT_BYTES = 1048576;
|
|
4
|
+
var MAX_OUTPUT_BYTES = 16777216;
|
|
5
|
+
var MAX_PENDING = 16;
|
|
6
|
+
function failure(id, method, message, code = -32603) {
|
|
7
|
+
return method === "tools/call" ? { jsonrpc: "2.0", id, result: { content: [{ type: "text", text: message }], isError: true } } : { jsonrpc: "2.0", id, error: { code, message } };
|
|
8
|
+
}
|
|
9
|
+
async function boundedJson(response) {
|
|
10
|
+
if (!response.body) throw new Error("Browser server returned an empty response.");
|
|
11
|
+
const reader = response.body.getReader();
|
|
12
|
+
const chunks = [];
|
|
13
|
+
let size = 0;
|
|
14
|
+
try {
|
|
15
|
+
for (; ; ) {
|
|
16
|
+
const { value, done } = await reader.read();
|
|
17
|
+
if (done) break;
|
|
18
|
+
size += value.byteLength;
|
|
19
|
+
if (size > MAX_OUTPUT_BYTES) throw new Error("Browser response exceeded the size limit.");
|
|
20
|
+
chunks.push(Buffer.from(value));
|
|
21
|
+
}
|
|
22
|
+
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
23
|
+
} finally {
|
|
24
|
+
await reader.cancel().catch(() => {
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async function browserProxyRequest(frame, connection) {
|
|
29
|
+
if (!frame || typeof frame !== "object" || Array.isArray(frame)) return failure(null, null, "Invalid request.", -32600);
|
|
30
|
+
const message = frame;
|
|
31
|
+
const id = message.id ?? null;
|
|
32
|
+
if (message.jsonrpc !== "2.0" || typeof message.method !== "string" || id !== null && typeof id !== "number" && typeof id !== "string") return failure(null, null, "Invalid request.", -32600);
|
|
33
|
+
if (!Object.hasOwn(message, "id")) return void 0;
|
|
34
|
+
if (message.method === "initialize") return {
|
|
35
|
+
jsonrpc: "2.0",
|
|
36
|
+
id,
|
|
37
|
+
result: { protocolVersion: "2024-11-05", capabilities: { tools: {} }, serverInfo: { name: "openmausbot-browser", version: "1" } }
|
|
38
|
+
};
|
|
39
|
+
if (message.method === "ping") return { jsonrpc: "2.0", id, result: {} };
|
|
40
|
+
if (message.method !== "tools/list" && message.method !== "tools/call") return failure(id, message.method, "Method not found.", -32601);
|
|
41
|
+
try {
|
|
42
|
+
const url = new URL(connection.url);
|
|
43
|
+
if (!connection.token || url.protocol !== "http:" || !["127.0.0.1", "localhost", "[::1]"].includes(url.hostname) || url.username || url.password || url.pathname !== "/" || url.search || url.hash) {
|
|
44
|
+
throw new Error("Browser connection is not configured. Start a new bot turn from OpenMausBot.");
|
|
45
|
+
}
|
|
46
|
+
const body = JSON.stringify({ method: message.method, params: message.params ?? {} });
|
|
47
|
+
if (Buffer.byteLength(body) > MAX_INPUT_BYTES) throw new Error("Browser request exceeded the size limit.");
|
|
48
|
+
const response = await fetch(new URL("/api/internal/browser/mcp", url), {
|
|
49
|
+
method: "POST",
|
|
50
|
+
redirect: "error",
|
|
51
|
+
headers: { "content-type": "application/json", authorization: `Bearer ${connection.token}` },
|
|
52
|
+
body,
|
|
53
|
+
signal: AbortSignal.timeout(13e4)
|
|
54
|
+
});
|
|
55
|
+
const payload = await boundedJson(response);
|
|
56
|
+
if (!response.ok || !payload || typeof payload !== "object" || !Object.hasOwn(payload, "result")) {
|
|
57
|
+
throw new Error(typeof payload?.error === "string" ? payload.error.slice(0, 2e3) : "Browser server is unavailable. Start a new bot turn or try again.");
|
|
58
|
+
}
|
|
59
|
+
return { jsonrpc: "2.0", id, result: payload.result };
|
|
60
|
+
} catch (error) {
|
|
61
|
+
return failure(id, message.method, error instanceof Error && !/fetch failed|abort|timeout/i.test(error.message) ? error.message : "Browser connection was interrupted. Do not repeat the action until its state is checked.");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function run() {
|
|
65
|
+
const connection = { url: process.env.OMB_HARNESS_URL ?? "", token: process.env.OMB_BROWSER_TOKEN ?? "" };
|
|
66
|
+
let input = Buffer.alloc(0);
|
|
67
|
+
let pending = 0;
|
|
68
|
+
const output = (message) => {
|
|
69
|
+
if (message === void 0) return;
|
|
70
|
+
const line = `${JSON.stringify(message)}
|
|
71
|
+
`;
|
|
72
|
+
if (Buffer.byteLength(line) > MAX_OUTPUT_BYTES || process.stdout.writableLength > MAX_OUTPUT_BYTES * 2) {
|
|
73
|
+
process.stdin.destroy();
|
|
74
|
+
process.exitCode = 1;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
process.stdout.write(line);
|
|
78
|
+
};
|
|
79
|
+
process.stdout.on("error", () => {
|
|
80
|
+
process.stdin.destroy();
|
|
81
|
+
process.exitCode = 1;
|
|
82
|
+
});
|
|
83
|
+
process.stdin.on("data", (chunk) => {
|
|
84
|
+
input = Buffer.concat([input, chunk]);
|
|
85
|
+
let newline;
|
|
86
|
+
while ((newline = input.indexOf(10)) !== -1) {
|
|
87
|
+
if (newline > MAX_INPUT_BYTES) {
|
|
88
|
+
process.stdin.destroy();
|
|
89
|
+
process.exitCode = 1;
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const line = input.subarray(0, newline).toString("utf8");
|
|
93
|
+
input = input.subarray(newline + 1);
|
|
94
|
+
if (!line.trim()) continue;
|
|
95
|
+
let frame;
|
|
96
|
+
try {
|
|
97
|
+
frame = JSON.parse(line);
|
|
98
|
+
} catch {
|
|
99
|
+
output(failure(null, null, "Parse error.", -32700));
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
if (pending >= MAX_PENDING) {
|
|
103
|
+
const request = frame;
|
|
104
|
+
if (request && Object.hasOwn(request, "id")) output(failure(request.id ?? null, request.method, "Too many pending browser requests."));
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
pending++;
|
|
108
|
+
void browserProxyRequest(frame, connection).then(output).finally(() => {
|
|
109
|
+
pending--;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
if (input.length > MAX_INPUT_BYTES) {
|
|
113
|
+
process.stdin.destroy();
|
|
114
|
+
process.exitCode = 1;
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) run();
|
|
119
|
+
export {
|
|
120
|
+
browserProxyRequest
|
|
121
|
+
};
|
|
@@ -14803,6 +14803,8 @@ var defaultModelSelectionSchema = external_exports.object({
|
|
|
14803
14803
|
effort: external_exports.enum(EFFORT_LEVELS).optional()
|
|
14804
14804
|
});
|
|
14805
14805
|
var appConfigSchema = external_exports.object({
|
|
14806
|
+
/** Verified by the dedicated domain endpoint, never a generic config patch. */
|
|
14807
|
+
customDomain: external_exports.string().optional(),
|
|
14806
14808
|
defaultModelSelection: defaultModelSelectionSchema.optional(),
|
|
14807
14809
|
/** CLI-only launch preferences. Never enable remote access implicitly. */
|
|
14808
14810
|
cliStartup: external_exports.object({
|
|
@@ -14846,7 +14848,7 @@ var appConfigSchema = external_exports.object({
|
|
|
14846
14848
|
var storedAppConfigSchema = appConfigSchema.extend({
|
|
14847
14849
|
browserProfiles: storedBrowserProfilesSchema.optional()
|
|
14848
14850
|
});
|
|
14849
|
-
var appConfigPatchSchema = appConfigSchema.omit({ instances: true, mcpServers: true, cliStartup: true });
|
|
14851
|
+
var appConfigPatchSchema = appConfigSchema.omit({ instances: true, mcpServers: true, cliStartup: true, customDomain: true });
|
|
14850
14852
|
var jsonObjectSchema = external_exports.record(external_exports.string(), external_exports.json());
|
|
14851
14853
|
var DATA_DIR = process.env.OMB_DATA_DIR ?? join2(homedir2(), ".openmausbot");
|
|
14852
14854
|
var LEGACY_DATA_DIR = join2(homedir2(), ".opengrokbot");
|
|
@@ -14863,6 +14865,7 @@ function resolveProxy(relative) {
|
|
|
14863
14865
|
return existsSync2(source) ? source : join3(SERVER_ROOT, `${relative}.js`);
|
|
14864
14866
|
}
|
|
14865
14867
|
var SPAWNED_PROXIES = {
|
|
14868
|
+
browser: resolveProxy("browser-proxy"),
|
|
14866
14869
|
computer: resolveProxy("computer-proxy"),
|
|
14867
14870
|
permission: resolveProxy("permission-proxy"),
|
|
14868
14871
|
containerMcp: resolveProxy("container-mcp"),
|