openmausbot 0.1.56 → 0.1.58
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-B433sv8K.css +1 -0
- package/dist/assets/{index-Dq2j4Ikr.js → index-CE7W1AIk.js} +1 -1
- package/dist/assets/index-r-WPT-Pu.js +264 -0
- package/dist/index.html +2 -2
- package/dist-server/companion/src/routes.js +6 -1
- package/dist-server/connector-proxy.js +31 -12
- package/dist-server/container-mcp.js +49 -31
- package/dist-server/drivers/agents-proxy.js +56 -2
- package/dist-server/index.js +2126 -487
- package/dist-server/openmausbot.js +15219 -305
- package/dist-server/pair-cli.js +15219 -305
- package/dist-server/server/auto-approve.js +24 -0
- package/dist-server/server/bot-folder.js +102 -0
- package/dist-server/server/bot-overview.js +206 -0
- package/dist-server/server/bot-package.js +5 -0
- package/dist-server/server/bot-profile.js +7 -0
- package/dist-server/server/browser-engine-release.js +44 -0
- package/dist-server/server/browser-engine.js +185 -0
- package/dist-server/server/cli.js +55 -1
- package/dist-server/server/connector-proxy.js +37 -16
- package/dist-server/server/container-computer.js +9 -2
- package/dist-server/server/drivers/agents-proxy.js +63 -2
- package/dist-server/server/drivers/antigravity-acp.js +119 -20
- package/dist-server/server/drivers/antigravity-runtime.js +47 -3
- package/dist-server/server/drivers/antigravity.js +23 -2
- package/dist-server/server/drivers/claude.js +7 -1
- package/dist-server/server/index.js +634 -107
- package/dist-server/server/mcp-bridge.js +73 -44
- package/dist-server/server/package-export.js +1 -0
- package/dist-server/server/profile-requests.js +332 -0
- package/dist-server/server/profile-revision.js +15 -0
- package/dist-server/server/profile-versions.js +154 -0
- package/dist-server/server/routine-requests.js +34 -1
- package/dist-server/server/routines.js +70 -2
- package/dist-server/server/setup-mode.js +63 -0
- package/dist-server/server/skill-fetch.js +67 -11
- package/dist-server/server/skills.js +1 -1
- package/dist-server/server/store.js +87 -7
- package/dist-server/server/system-prompt.js +49 -0
- package/dist-server/server/team-backup.js +2 -2
- package/dist-server/server/team-manifest.js +7 -0
- package/dist-server/shared/bot-profile.js +5 -1
- package/dist-server/shared/line-diff.js +42 -0
- package/dist-server/shared/profile-request.js +9 -0
- package/dist-server/shared/team-backup.js +4 -0
- package/dist-server/vps-container-mcp.js +49 -31
- package/package.json +1 -1
- package/dist/assets/index-CJBrtDbC.css +0 -1
- package/dist/assets/index-D0xt96rv.js +0 -263
package/dist/index.html
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<link rel="icon" type="image/svg+xml" href="/app-icon.svg" />
|
|
7
7
|
<title>OpenMausBot</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-r-WPT-Pu.js"></script>
|
|
9
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B433sv8K.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
|
12
12
|
<div id="root"></div>
|
|
@@ -84,8 +84,13 @@ const ALLOWED = [
|
|
|
84
84
|
{ method: "POST", path: /^\/api\/bots\/[\w-]+\/tasks\/[\w-]+$/ },
|
|
85
85
|
{ method: "PATCH", path: /^\/api\/bots\/[\w-]+\/tasks\/[\w-]+$/ },
|
|
86
86
|
{ method: "DELETE", path: /^\/api\/bots\/[\w-]+\/tasks\/[\w-]+$/ },
|
|
87
|
+
// Read-only summary: who the bot is, what it does and won't do, and its
|
|
88
|
+
// recent activity. No settings, no transcript — read on open and on
|
|
89
|
+
// pull-to-refresh.
|
|
90
|
+
{ method: "GET", path: /^\/api\/bots\/[\w-]+\/overview$/ },
|
|
87
91
|
// Paired-safe profile subset. The harness route itself rejects fields
|
|
88
|
-
// outside identity,
|
|
92
|
+
// outside identity, standing instructions (soul, byte-capped), avatar,
|
|
93
|
+
// notifications, and voice preferences.
|
|
89
94
|
{ method: "PATCH", path: /^\/api\/bots\/[\w-]+\/profile$/ },
|
|
90
95
|
// Full model selection, but no other bot settings. The harness validates
|
|
91
96
|
// the live catalog and refuses changes while the bot is working.
|
|
@@ -96,20 +96,38 @@ function connectorAdds(args) {
|
|
|
96
96
|
if (!args || typeof args !== "object" || Array.isArray(args)) return [];
|
|
97
97
|
const toolkits = args.toolkits;
|
|
98
98
|
if (!Array.isArray(toolkits)) return [];
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
const seen = /* @__PURE__ */ new Set();
|
|
100
|
+
const requests = [];
|
|
101
|
+
for (const item of toolkits) {
|
|
102
|
+
if (typeof item === "string") {
|
|
103
|
+
const slug2 = item.trim().toLowerCase();
|
|
104
|
+
const key2 = JSON.stringify([slug2, ""]);
|
|
105
|
+
if (!seen.has(key2)) {
|
|
106
|
+
seen.add(key2);
|
|
107
|
+
requests.push({ slug: slug2 });
|
|
108
|
+
}
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) continue;
|
|
102
112
|
const row = item;
|
|
103
|
-
const slug = typeof row.toolkit === "string" ? row.toolkit : row.name;
|
|
104
113
|
const action = String(row.action ?? "add").toLowerCase();
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
if (!["add", "connect", "initiate"].includes(action)) continue;
|
|
115
|
+
const slug = typeof row.toolkit === "string" ? row.toolkit : row.name;
|
|
116
|
+
if (typeof slug !== "string") continue;
|
|
117
|
+
const normalized = slug.trim().toLowerCase();
|
|
118
|
+
const alias = (typeof row.alias === "string" ? row.alias : typeof row.account === "string" ? row.account : "").trim();
|
|
119
|
+
const key = JSON.stringify([normalized, alias.toLowerCase()]);
|
|
120
|
+
if (seen.has(key)) continue;
|
|
121
|
+
seen.add(key);
|
|
122
|
+
requests.push({ slug: normalized, ...alias ? { alias } : {} });
|
|
123
|
+
}
|
|
124
|
+
return requests;
|
|
107
125
|
}
|
|
108
|
-
async function showConnectorCards(
|
|
126
|
+
async function showConnectorCards(items) {
|
|
109
127
|
const response = await fetch(`${HARNESS}/api/internal/connectors/request`, {
|
|
110
128
|
method: "POST",
|
|
111
129
|
headers: { "content-type": "application/json", authorization: `Bearer ${TOKEN}` },
|
|
112
|
-
body: JSON.stringify({ botId: BOT_ID, threadId: THREAD_ID,
|
|
130
|
+
body: JSON.stringify({ botId: BOT_ID, threadId: THREAD_ID, items, resumeKey: randomUUID() }),
|
|
113
131
|
signal: AbortSignal.timeout(3e4)
|
|
114
132
|
});
|
|
115
133
|
if (!response.ok) {
|
|
@@ -141,12 +159,13 @@ async function handle(message) {
|
|
|
141
159
|
if (method === "tools/call") {
|
|
142
160
|
const params = message.params ?? {};
|
|
143
161
|
const name = String(params.name ?? "");
|
|
144
|
-
const
|
|
145
|
-
if (
|
|
146
|
-
await showConnectorCards(
|
|
162
|
+
const requests = /MANAGE_CONNECTIONS$/i.test(name) ? connectorAdds(params.arguments) : [];
|
|
163
|
+
if (requests.length) {
|
|
164
|
+
await showConnectorCards(requests);
|
|
165
|
+
const labels = requests.map((r) => r.alias ? `${r.slug} (${r.alias})` : r.slug).join(", ");
|
|
147
166
|
send(textResult(
|
|
148
167
|
id,
|
|
149
|
-
`OpenMausBot showed the user a secure connection card for ${
|
|
168
|
+
`OpenMausBot showed the user a secure connection card for ${labels}. End this turn now. The app will continue the task automatically after the connection finishes.`
|
|
150
169
|
));
|
|
151
170
|
return;
|
|
152
171
|
}
|
|
@@ -15082,6 +15082,28 @@ function createGateInterceptor(options) {
|
|
|
15082
15082
|
});
|
|
15083
15083
|
};
|
|
15084
15084
|
}
|
|
15085
|
+
function createMcpBridgeInterceptor(options) {
|
|
15086
|
+
const afterPing = options.gate ? createGateInterceptor({
|
|
15087
|
+
isHeld: options.gate.isHeld,
|
|
15088
|
+
forward: options.forward,
|
|
15089
|
+
refuse: options.answer,
|
|
15090
|
+
refusalText: options.gate.refusalText
|
|
15091
|
+
}) : options.forward;
|
|
15092
|
+
return (line) => {
|
|
15093
|
+
let frame = null;
|
|
15094
|
+
try {
|
|
15095
|
+
frame = JSON.parse(line);
|
|
15096
|
+
} catch {
|
|
15097
|
+
}
|
|
15098
|
+
if (frame && frame.method === "ping") {
|
|
15099
|
+
if (frame.id !== void 0) {
|
|
15100
|
+
options.answer(JSON.stringify({ jsonrpc: "2.0", id: frame.id, result: {} }));
|
|
15101
|
+
}
|
|
15102
|
+
return;
|
|
15103
|
+
}
|
|
15104
|
+
afterPing(line);
|
|
15105
|
+
};
|
|
15106
|
+
}
|
|
15085
15107
|
function runMcpBridge(options) {
|
|
15086
15108
|
const child = spawn(options.command, options.args, {
|
|
15087
15109
|
shell: false,
|
|
@@ -15091,37 +15113,33 @@ function runMcpBridge(options) {
|
|
|
15091
15113
|
child.stdin.on("error", () => {
|
|
15092
15114
|
});
|
|
15093
15115
|
child.stderr.pipe(process.stderr);
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
15102
|
-
|
|
15103
|
-
|
|
15104
|
-
|
|
15105
|
-
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
|
|
15109
|
-
|
|
15110
|
-
|
|
15111
|
-
|
|
15112
|
-
child.
|
|
15113
|
-
|
|
15114
|
-
|
|
15115
|
-
|
|
15116
|
-
|
|
15117
|
-
|
|
15118
|
-
process.stdin.
|
|
15119
|
-
|
|
15120
|
-
|
|
15121
|
-
process.stdin.unpipe(child.stdin);
|
|
15122
|
-
process.stdin.pause();
|
|
15123
|
-
};
|
|
15124
|
-
}
|
|
15116
|
+
const client = options.gate ? createControlClient({ url: options.gate.url, token: options.gate.token }) : null;
|
|
15117
|
+
const answer = (line) => process.stdout.write(line + "\n");
|
|
15118
|
+
const forward = (line) => child.stdin.write(line + "\n");
|
|
15119
|
+
const inbound = createLineSplitter(
|
|
15120
|
+
createMcpBridgeInterceptor({
|
|
15121
|
+
answer,
|
|
15122
|
+
forward,
|
|
15123
|
+
...options.gate ? {
|
|
15124
|
+
gate: {
|
|
15125
|
+
isHeld: async () => (await client.state(true)).held
|
|
15126
|
+
}
|
|
15127
|
+
} : {}
|
|
15128
|
+
})
|
|
15129
|
+
);
|
|
15130
|
+
const onStdin = (chunk) => inbound.push(chunk);
|
|
15131
|
+
process.stdin.on("data", onStdin);
|
|
15132
|
+
process.stdin.on("end", () => {
|
|
15133
|
+
inbound.flush();
|
|
15134
|
+
child.stdin.end();
|
|
15135
|
+
});
|
|
15136
|
+
const outbound = createLineSplitter((line) => process.stdout.write(line + "\n"));
|
|
15137
|
+
child.stdout.on("data", (chunk) => outbound.push(chunk));
|
|
15138
|
+
child.stdout.on("end", () => outbound.flush());
|
|
15139
|
+
const detach = () => {
|
|
15140
|
+
process.stdin.off("data", onStdin);
|
|
15141
|
+
process.stdin.pause();
|
|
15142
|
+
};
|
|
15125
15143
|
let watchdog = null;
|
|
15126
15144
|
if (options.liveness) {
|
|
15127
15145
|
const liveness = options.liveness;
|
|
@@ -192,6 +192,10 @@ var ROUTINE_FIELDS_SCHEMA = {
|
|
|
192
192
|
clear_timeout: {
|
|
193
193
|
type: "boolean",
|
|
194
194
|
description: "Only for updates: set true to remove an existing safety limit. Do not combine with timeout_minutes."
|
|
195
|
+
},
|
|
196
|
+
continuity: {
|
|
197
|
+
type: "boolean",
|
|
198
|
+
description: "Opt in to using the latest completed run's bounded report as historical context. Defaults to false; set false in an update to start fresh again. Shown on the confirmation card."
|
|
195
199
|
}
|
|
196
200
|
};
|
|
197
201
|
var TOOLS = [
|
|
@@ -371,6 +375,31 @@ var TOOLS = [
|
|
|
371
375
|
required: ["routine_id", "action"]
|
|
372
376
|
}
|
|
373
377
|
},
|
|
378
|
+
{
|
|
379
|
+
name: "propose_profile",
|
|
380
|
+
description: "Propose changes to your own name, title, description, standing instructions (SOUL.md), or working folder (cwd). This only creates a confirmation card; nothing changes until the user approves it. After calling it, end the turn and do not claim the change is applied. Keep SOUL.md short \u2014 who you are and the rules you never break; put step-by-step procedure into a skill instead. A Chief of Staff may pass for_bot_id (from list_bots) to propose a change for another bot in its section.",
|
|
381
|
+
inputSchema: {
|
|
382
|
+
type: "object",
|
|
383
|
+
additionalProperties: false,
|
|
384
|
+
properties: {
|
|
385
|
+
name: { type: "string", maxLength: 100, description: "New display name." },
|
|
386
|
+
title: { type: "string", maxLength: 200, description: "New role or title." },
|
|
387
|
+
description: { type: "string", maxLength: 4e3, description: "New one-line blurb shown in rosters." },
|
|
388
|
+
soul: { type: "string", description: "Full replacement text for SOUL.md, at most 24000 bytes." },
|
|
389
|
+
cwd: {
|
|
390
|
+
type: "string",
|
|
391
|
+
maxLength: 1024,
|
|
392
|
+
description: "Absolute path of the folder your tools read and write in (for example /Users/me/Projects/site). It must already exist. An empty string means your private workspace."
|
|
393
|
+
},
|
|
394
|
+
reason: { type: "string", minLength: 1, maxLength: 500, description: "One sentence the user will see explaining why." },
|
|
395
|
+
for_bot_id: {
|
|
396
|
+
type: "string",
|
|
397
|
+
description: "Chief of Staff only: the id of another bot in your section whose profile this changes. Omit to change your own."
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
required: ["reason"]
|
|
401
|
+
}
|
|
402
|
+
},
|
|
374
403
|
{
|
|
375
404
|
name: "skills_list",
|
|
376
405
|
description: "List this bot's imported skills (enabled and disabled) and any staged skill writes waiting for the user to confirm. Use this before skill_manage to avoid duplicate names. Listing does not enable anything.",
|
|
@@ -445,16 +474,17 @@ function routineFields(args) {
|
|
|
445
474
|
if (typeof args.run_on === "string") fields.runOn = args.run_on;
|
|
446
475
|
if (args.clear_timeout === true) fields.timeoutMinutes = null;
|
|
447
476
|
else if (typeof args.timeout_minutes === "number") fields.timeoutMinutes = args.timeout_minutes;
|
|
477
|
+
if (typeof args.continuity === "boolean") fields.continuity = args.continuity;
|
|
448
478
|
return { fields };
|
|
449
479
|
}
|
|
450
|
-
function confirmationResult(r, fallback) {
|
|
480
|
+
function confirmationResult(r, fallback, noun = "routine") {
|
|
451
481
|
const summary = typeof r.summary === "string" && r.summary.trim() ? `
|
|
452
482
|
|
|
453
483
|
${r.summary.trim()}` : "";
|
|
454
484
|
return {
|
|
455
485
|
text: `A confirmation card is now visible to the user for ${fallback}.${summary}
|
|
456
486
|
|
|
457
|
-
This change has not been applied yet. End this turn and wait for the user to confirm or deny the card; do not claim the
|
|
487
|
+
This change has not been applied yet. End this turn and wait for the user to confirm or deny the card; do not claim the ${noun} was created or changed before confirmation.`
|
|
458
488
|
};
|
|
459
489
|
}
|
|
460
490
|
function recallSpeaker(hit) {
|
|
@@ -723,6 +753,30 @@ ${JSON.stringify(routines, null, 2)}`
|
|
|
723
753
|
});
|
|
724
754
|
return confirmationResult(r, `${action.replace("_", " ")} on routine ${routineId}`);
|
|
725
755
|
}
|
|
756
|
+
if (name === "propose_profile") {
|
|
757
|
+
const changes = {};
|
|
758
|
+
if (typeof args.name === "string") changes.name = args.name.trim();
|
|
759
|
+
if (typeof args.title === "string") changes.title = args.title.trim();
|
|
760
|
+
if (typeof args.description === "string") changes.description = args.description.trim();
|
|
761
|
+
if (typeof args.soul === "string") changes.soul = args.soul;
|
|
762
|
+
if (typeof args.cwd === "string") changes.cwd = args.cwd.trim();
|
|
763
|
+
if (!Object.keys(changes).length) {
|
|
764
|
+
return { text: "propose_profile needs at least one of name, title, description, soul, or cwd.", isError: true };
|
|
765
|
+
}
|
|
766
|
+
const forBotId = String(args.for_bot_id ?? "").trim();
|
|
767
|
+
const r = await api("/api/internal/profile-requests", {
|
|
768
|
+
method: "POST",
|
|
769
|
+
body: JSON.stringify({
|
|
770
|
+
fromBotId: BOT_ID,
|
|
771
|
+
fromThreadId: THREAD_ID,
|
|
772
|
+
changes,
|
|
773
|
+
reason: args.reason,
|
|
774
|
+
// JSON.stringify drops the key entirely when no target was named
|
|
775
|
+
forBotId: forBotId || void 0
|
|
776
|
+
})
|
|
777
|
+
});
|
|
778
|
+
return confirmationResult(r, "the profile change", "profile");
|
|
779
|
+
}
|
|
726
780
|
if (name === "session_search") {
|
|
727
781
|
const q = String(args.query ?? "").trim();
|
|
728
782
|
if (!q) return { text: 'session_search needs a query, for example {"query":"site audit broken links"}.', isError: true };
|