openmausbot 0.1.86 → 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.
- package/README.md +2 -2
- package/dist/assets/{abnfDiagram-O67JEVCF-DpUZNnFD.js → abnfDiagram-O67JEVCF-BTiuL79F.js} +1 -1
- package/dist/assets/{arc-DW7mrI4p.js → arc-C88Blc2v.js} +1 -1
- package/dist/assets/{architectureDiagram-NJMV4G6O-CyeZ5WLZ.js → architectureDiagram-NJMV4G6O-BZsJIZrb.js} +1 -1
- package/dist/assets/{blockDiagram-BEXU5L5S-CBVaNjO7.js → blockDiagram-BEXU5L5S-CVeMe9Ah.js} +1 -1
- package/dist/assets/{c4Diagram-YGBWAQC7-sf8d41uT.js → c4Diagram-YGBWAQC7-Cedk3Bhx.js} +1 -1
- package/dist/assets/channel-taCNRlUU.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-BOGvy7Y_.js → chunk-2Q5K7J3B-D-VRqzTB.js} +1 -1
- package/dist/assets/{chunk-3FUC2YCW-BiF9zyiz.js → chunk-3FUC2YCW-BChov01Y.js} +2 -2
- package/dist/assets/{chunk-5VM5RSS4-EFuZ1SBZ.js → chunk-5VM5RSS4-C-TfwvHy.js} +1 -1
- package/dist/assets/{chunk-GTNCS2PH-pJLNSAT7.js → chunk-GTNCS2PH-Db7CGj5Y.js} +1 -1
- package/dist/assets/{chunk-GWA4HPMP-Cb-3_3IT.js → chunk-GWA4HPMP-CNvIfqKT.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DAf5aogn.js → chunk-JWPE2WC7-C_bEp5tq.js} +1 -1
- package/dist/assets/{chunk-NETBCI7D-DR3kiwZz.js → chunk-NETBCI7D-Coi4BOls.js} +1 -1
- package/dist/assets/{chunk-WEXAMYUT-BmU8PeyM.js → chunk-WEXAMYUT-CzylEuL3.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-Buh8g8OT.js → chunk-XXDRQBXY-m7p7ztaD.js} +1 -1
- package/dist/assets/{classDiagram-v2-NBCMYWYE-BurfmMWM.js → classDiagram-v2-NBCMYWYE-BMy6o9x2.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-KkGZUEkU.js → cose-bilkent-JH36ORCC-BDQ__0_J.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-C3PpV96d.js → cynefin-OW5HDTMX-Djv4ghUb.js} +1 -1
- package/dist/assets/{cynefinDiagram-VND7K2PF-Dt8JwJaI.js → cynefinDiagram-VND7K2PF-BULrlGYH.js} +1 -1
- package/dist/assets/{dagre-6A5THRUB-DkjN8266.js → dagre-6A5THRUB-D-jrT_hU.js} +1 -1
- package/dist/assets/{diagram-22UHCM2B-DUAJS0JV.js → diagram-22UHCM2B-p2UhQmfL.js} +1 -1
- package/dist/assets/{diagram-3UASUU5V-Dw4KhF1a.js → diagram-3UASUU5V-DHvGWZ7q.js} +1 -1
- package/dist/assets/{diagram-ATOU4E4O-Dd1gmQqf.js → diagram-ATOU4E4O-ChhKDot-.js} +1 -1
- package/dist/assets/{diagram-CDSNMT55-CjwGs0Yw.js → diagram-CDSNMT55-B-T7A43R.js} +1 -1
- package/dist/assets/{diagram-MLGK6HIB-BL-69Zrq.js → diagram-MLGK6HIB-CJm8ENNY.js} +1 -1
- package/dist/assets/{diagram-MPIPVDR6-5Zi2N7wo.js → diagram-MPIPVDR6-510tlza8.js} +1 -1
- package/dist/assets/{ebnfDiagram-ZINNZB2B-D9NekWUX.js → ebnfDiagram-ZINNZB2B-PkvRPHel.js} +1 -1
- package/dist/assets/{elk-276RUBZZ-CkaSQjxw.js → elk-276RUBZZ-BVBVPoX3.js} +1 -1
- package/dist/assets/{erDiagram-OPXOYQCR-CdAVBV8-.js → erDiagram-OPXOYQCR-BgYMVm7L.js} +1 -1
- package/dist/assets/{flowDiagram-KWPJA3E3-Bm_lWWH7.js → flowDiagram-KWPJA3E3-BGqsnc_3.js} +1 -1
- package/dist/assets/{ganttDiagram-FUAMR5RP-FZ8ejYWJ.js → ganttDiagram-FUAMR5RP-D_-UeReH.js} +1 -1
- package/dist/assets/{gitGraphDiagram-X574FWY7-Dlv9rizZ.js → gitGraphDiagram-X574FWY7-D0uooONx.js} +1 -1
- package/dist/assets/index-BwdMAQ6p.css +1 -0
- package/dist/assets/index-ByJennr7.js +581 -0
- package/dist/assets/{index-h9FFNwTu.js → index-zRsJERGJ.js} +1 -1
- package/dist/assets/{infoDiagram-VRGFBTTK-BdQ_gW5B.js → infoDiagram-VRGFBTTK-B9e1z77f.js} +1 -1
- package/dist/assets/{ishikawaDiagram-OU5B5YK6-EwssEp2X.js → ishikawaDiagram-OU5B5YK6-BB4vNwvD.js} +1 -1
- package/dist/assets/{journeyDiagram-ZHPQQLJL-BX1G1vOd.js → journeyDiagram-ZHPQQLJL-DpkosOTB.js} +1 -1
- package/dist/assets/{kanban-definition-PNTS6WVX-BB4kAsyC.js → kanban-definition-PNTS6WVX-DbDP4kUu.js} +1 -1
- package/dist/assets/{linear-3su2TG93.js → linear-DBJGPmjT.js} +1 -1
- package/dist/assets/{mermaid.core-CDD1E0s9.js → mermaid.core-DWPRi-ue.js} +5 -5
- package/dist/assets/{mindmap-definition-NLK3R4M7-Ba50MsNK.js → mindmap-definition-NLK3R4M7-nszBbJmx.js} +1 -1
- package/dist/assets/{pegDiagram-GJSIUBJH-DZLkkZlM.js → pegDiagram-GJSIUBJH-CWykJWu_.js} +1 -1
- package/dist/assets/{pieDiagram-5QR66LMP-DaTz77Uq.js → pieDiagram-5QR66LMP-g3Da-Vnv.js} +1 -1
- package/dist/assets/{quadrantDiagram-O4NWA36T-CpaiidpR.js → quadrantDiagram-O4NWA36T-Wzrlpzgh.js} +1 -1
- package/dist/assets/{railroadDiagram-XR7U4H2S-mN4JrMeI.js → railroadDiagram-XR7U4H2S-moHTFMC0.js} +1 -1
- package/dist/assets/{requirementDiagram-PLB6GJNP-BSNDRpg7.js → requirementDiagram-PLB6GJNP-CwfXdFH8.js} +1 -1
- package/dist/assets/{sankeyDiagram-IPEJSGJF-FngzGNug.js → sankeyDiagram-IPEJSGJF-3ZROYvnq.js} +1 -1
- package/dist/assets/{sequenceDiagram-PO4LG4MO-CM4pCC3L.js → sequenceDiagram-PO4LG4MO-E1TBebP8.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-CRICHXkw.js → sizeCapture-INFHLROL-DHKEU5pu.js} +1 -1
- package/dist/assets/{stateDiagram-v2-GCMORJYK-oyTWpxH2.js → stateDiagram-v2-GCMORJYK-BguEj09D.js} +1 -1
- package/dist/assets/{swimlanes-2SLR337P-D9h9mPBq.js → swimlanes-2SLR337P-C7IDYnhd.js} +1 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-BpEdoB2e.js +8 -0
- package/dist/assets/{timeline-definition-EJHVYXUP-BJUlN9bW.js → timeline-definition-EJHVYXUP-DCW-F5PW.js} +1 -1
- package/dist/assets/{usecaseDiagram-POWQR4AR-3uBNkbAb.js → usecaseDiagram-POWQR4AR-xBMFtWYV.js} +1 -1
- package/dist/assets/{vennDiagram-UO4OBE2U-D2odalzT.js → vennDiagram-UO4OBE2U-B5nIkuH8.js} +1 -1
- package/dist/assets/{wardleyDiagram-VNRHLVJA-DHgFaB9S.js → wardleyDiagram-VNRHLVJA-DYFAhdbr.js} +1 -1
- package/dist/assets/{xychartDiagram-PMCCYNJV-w5GYM2h0.js → xychartDiagram-PMCCYNJV-DeXwX6Cz.js} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/browser-proxy.js +2 -1
- package/dist-server/container-mcp.js +1029 -164
- package/dist-server/drivers/agents-proxy.js +64 -10
- package/dist-server/drivers/phone-proxy.js +33 -2
- package/dist-server/index.js +14577 -9001
- package/dist-server/local-computer-proxy.js +3 -3
- package/dist-server/local-computer.js +53 -17
- package/dist-server/openmausbot.js +3981 -1165
- package/dist-server/pair-cli.js +3981 -1165
- package/dist-server/permission-proxy.js +29 -9
- package/dist-server/server/attachments.js +55 -0
- package/dist-server/server/auto-approve.js +4 -3
- package/dist-server/server/auto-vm-claims.js +1 -0
- package/dist-server/server/bot-package.js +18 -292
- package/dist-server/server/bot-profile.js +5 -17
- package/dist-server/server/box-create-idempotency.js +3 -3
- package/dist-server/server/box.js +57 -55
- package/dist-server/server/browser-proxy.js +3 -2
- package/dist-server/server/browser-runtime.js +37 -1
- package/dist-server/server/cli.js +2 -2
- package/dist-server/server/command-allowlist.js +154 -0
- package/dist-server/server/computer-wait.js +22 -9
- package/dist-server/server/config.js +59 -9
- package/dist-server/server/connector-verdict.js +141 -0
- package/dist-server/server/container-computer.js +1 -1
- package/dist-server/server/default-model-selection.js +9 -0
- package/dist-server/server/delegations.js +85 -34
- package/dist-server/server/drivers/acp/core.js +57 -15
- package/dist-server/server/drivers/agents-call.js +42 -3
- package/dist-server/server/drivers/agents-catalog.js +34 -4
- package/dist-server/server/drivers/boxagent.js +174 -36
- package/dist-server/server/drivers/builtIn.js +2 -0
- package/dist-server/server/drivers/chat-box-tools.js +90 -0
- package/dist-server/server/drivers/chat-images.js +54 -0
- package/dist-server/server/drivers/chat-mcp-tools.js +38 -8
- package/dist-server/server/drivers/chat-tool-approval.js +70 -18
- package/dist-server/server/drivers/claude.js +7 -2
- package/dist-server/server/drivers/codex-instructions.js +48 -6
- package/dist-server/server/drivers/codex-tool-surface.js +20 -0
- package/dist-server/server/drivers/codex.js +95 -30
- package/dist-server/server/drivers/mistral.js +115 -0
- package/dist-server/server/drivers/openai-chat.js +155 -32
- package/dist-server/server/drivers/openai-compat.js +1 -0
- package/dist-server/server/drivers/permission-command.js +35 -0
- package/dist-server/server/drivers/phone-proxy.js +47 -2
- package/dist-server/server/drivers/pi.js +75 -4
- package/dist-server/server/drivers/prompt-split.js +87 -0
- package/dist-server/server/fleet.js +1 -1
- package/dist-server/server/group-thread-usage.js +103 -0
- package/dist-server/server/harness/registry.js +1 -0
- package/dist-server/server/hosted-models.js +1 -1
- package/dist-server/server/index.js +1385 -322
- package/dist-server/server/local-computer.js +72 -23
- package/dist-server/server/managed-desktop.js +1 -1
- package/dist-server/server/mcp-bridge.js +6 -6
- package/dist-server/server/new-bot-defaults.js +115 -0
- package/dist-server/server/org-library.js +1051 -0
- package/dist-server/server/package-export.js +627 -39
- package/dist-server/server/package-import.js +458 -0
- package/dist-server/server/package-parts.js +87 -0
- package/dist-server/server/peer-approval.js +16 -7
- package/dist-server/server/peer-roster.js +10 -0
- package/dist-server/server/presets.js +492 -0
- package/dist-server/server/provider-key-check.js +3 -2
- package/dist-server/server/published-teams.js +80 -0
- package/dist-server/server/room-handoffs.js +19 -3
- package/dist-server/server/routes/bot-presets.js +25 -0
- package/dist-server/server/routine-requests.js +6 -3
- package/dist-server/server/routines.js +41 -1
- package/dist-server/server/section-context.js +10 -0
- package/dist-server/server/skills.js +34 -61
- package/dist-server/server/steer-queue.js +3 -2
- package/dist-server/server/store.js +259 -15
- package/dist-server/server/surface.js +10 -4
- package/dist-server/server/system-prompt.js +12 -4
- package/dist-server/server/team-backup.js +6 -2
- package/dist-server/server/team-computers.js +10 -0
- package/dist-server/server/team-library.js +6 -2
- package/dist-server/server/team-manifest.js +4 -3
- package/dist-server/server/team-setup-requests.js +16 -5
- package/dist-server/server/thread-events.js +17 -1
- package/dist-server/server/turn-context.js +2 -0
- package/dist-server/server/turn-watchdog.js +12 -3
- package/dist-server/server/usage-ledger.js +12 -1
- package/dist-server/server/vps-computer.js +139 -51
- package/dist-server/server/vps-container-mcp.js +7 -0
- package/dist-server/server/vps-ssh.js +36 -7
- package/dist-server/server/workspace-backup-policy.js +12 -0
- package/dist-server/server/workspace-backup.js +2 -2
- package/dist-server/server/workspace.js +1 -1
- package/dist-server/shared/approval-mode.js +1 -1
- package/dist-server/shared/ask-question.js +188 -12
- package/dist-server/shared/bot-profile.js +15 -0
- package/dist-server/shared/command-allowlist.js +1 -0
- package/dist-server/shared/credential-request.js +1 -1
- package/dist-server/shared/package-format.js +967 -0
- package/dist-server/shared/skill-md.js +64 -0
- package/dist-server/shared/team-backup.js +7 -0
- package/dist-server/shared/wire.js +4 -0
- package/dist-server/vps-container-mcp.js +1129 -170
- package/enterprise/README.md +1 -1
- package/package.json +1 -1
- package/dist/assets/channel-BXFkgus9.js +0 -1
- package/dist/assets/index-BGgqlWPJ.css +0 -1
- package/dist/assets/index-BtHo8ZKl.js +0 -577
- package/dist/assets/swimlanesDiagram-TC7HE7FX-BWrvB2ak.js +0 -8
|
@@ -70,19 +70,21 @@ function sameDriverFileIdentity(expected, actual) {
|
|
|
70
70
|
}
|
|
71
71
|
function decodeLegacyDescriptor(value, platform) {
|
|
72
72
|
const supportedPlatform = legacyPlatform(platform);
|
|
73
|
-
if (!supportedPlatform || !value ||
|
|
73
|
+
if (!supportedPlatform || !value ||
|
|
74
|
+
!(value.mode === "embedded" || (supportedPlatform === "darwin" && value.mode === "standalone")) ||
|
|
75
|
+
(Object.hasOwn(value, "status") && value.status !== "ready") ||
|
|
76
|
+
typeof value.socketPath !== "string" || !value.socketPath ||
|
|
77
|
+
typeof value.mcpCommand !== "string" || !value.mcpCommand.trim()) {
|
|
74
78
|
return null;
|
|
75
79
|
}
|
|
76
|
-
if (
|
|
80
|
+
if (!Array.isArray(value.mcpArgs) || value.mcpArgs[0] !== "mcp")
|
|
77
81
|
return null;
|
|
78
|
-
if (value.mcpEnv !==
|
|
79
|
-
(!value.mcpEnv || typeof value.mcpEnv !== "object" || Array.isArray(value.mcpEnv))) {
|
|
82
|
+
if (!value.mcpEnv || typeof value.mcpEnv !== "object" || Array.isArray(value.mcpEnv))
|
|
80
83
|
return null;
|
|
81
|
-
|
|
82
|
-
const args = value.mcpArgs ?? ["mcp"];
|
|
84
|
+
const args = value.mcpArgs;
|
|
83
85
|
if (!args.every((arg) => typeof arg === "string"))
|
|
84
86
|
return null;
|
|
85
|
-
const env = value.mcpEnv
|
|
87
|
+
const env = value.mcpEnv;
|
|
86
88
|
if (!Object.values(env).every((entry) => typeof entry === "string"))
|
|
87
89
|
return null;
|
|
88
90
|
return {
|
|
@@ -288,31 +290,78 @@ function validateLegacyDescriptorRuntime(descriptorFile, platform, { uid = proce
|
|
|
288
290
|
return false;
|
|
289
291
|
}
|
|
290
292
|
}
|
|
293
|
+
/** An older fallback cannot override a present but unavailable, malformed, or
|
|
294
|
+
* unreadable descriptor at a more specific location. */
|
|
295
|
+
function firstPresentCuaDescriptor(candidates) {
|
|
296
|
+
for (const file of new Set(candidates)) {
|
|
297
|
+
try {
|
|
298
|
+
lstatSync(file);
|
|
299
|
+
return file;
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
if (error.code !== "ENOENT")
|
|
303
|
+
return file;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return null;
|
|
307
|
+
}
|
|
291
308
|
export function readCuaConnection({ platform = process.platform, userData = process.env.OMB_USER_DATA, home = homedir(), validateLinuxRuntime = validateLinuxDescriptorRuntime, validateLegacyRuntime = validateLegacyDescriptorRuntime, } = {}) {
|
|
292
309
|
const candidates = userData ? [join(userData, "cua-connection.json")] : [];
|
|
293
|
-
if (platform === "darwin") {
|
|
294
|
-
// Legacy/dev fallback
|
|
310
|
+
if (platform === "darwin" && !userData) {
|
|
311
|
+
// Legacy/dev fallback only when Electron did not provide its exact path.
|
|
295
312
|
for (const directory of ["OpenMausBot", "openmausbot", "OpenGrokBot", "opengrokbot"]) {
|
|
296
313
|
candidates.push(join(home, "Library", "Application Support", directory, "cua-connection.json"));
|
|
297
314
|
}
|
|
298
315
|
}
|
|
299
|
-
|
|
300
|
-
|
|
316
|
+
const file = firstPresentCuaDescriptor(candidates);
|
|
317
|
+
if (!file)
|
|
318
|
+
return null;
|
|
319
|
+
try {
|
|
320
|
+
const raw = JSON.parse(readFileSync(file, "utf8"));
|
|
321
|
+
if (platform === "linux") {
|
|
322
|
+
const decoded = decodeLinuxDescriptor(raw);
|
|
323
|
+
if (decoded && validateLinuxRuntime(file, raw))
|
|
324
|
+
return decoded;
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
const decoded = decodeLegacyDescriptor(raw, platform);
|
|
328
|
+
if (decoded && validateLegacyRuntime(file, platform))
|
|
329
|
+
return decoded;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
// Missing, invalid, tampered, or stale descriptors are unavailable.
|
|
334
|
+
}
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
/** An unavailable descriptor is diagnostic only. It never becomes a connection
|
|
338
|
+
* and only a private, well-formed macOS/Windows descriptor may supply text. */
|
|
339
|
+
export function readCuaUnavailableReason({ platform = process.platform, userData = process.env.OMB_USER_DATA, home = homedir(), } = {}) {
|
|
340
|
+
if (!legacyPlatform(platform))
|
|
341
|
+
return null;
|
|
342
|
+
const candidates = userData ? [join(userData, "cua-connection.json")] : [];
|
|
343
|
+
if (platform === "darwin" && !userData) {
|
|
344
|
+
for (const directory of ["OpenMausBot", "openmausbot", "OpenGrokBot", "opengrokbot"]) {
|
|
345
|
+
candidates.push(join(home, "Library", "Application Support", directory, "cua-connection.json"));
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const file = firstPresentCuaDescriptor(candidates);
|
|
349
|
+
if (!file)
|
|
350
|
+
return null;
|
|
351
|
+
try {
|
|
352
|
+
if (validateLegacyDescriptorRuntime(file, platform)) {
|
|
301
353
|
const raw = JSON.parse(readFileSync(file, "utf8"));
|
|
302
|
-
if (
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const decoded = decodeLegacyDescriptor(raw, platform);
|
|
309
|
-
if (decoded && validateLegacyRuntime(file, platform))
|
|
310
|
-
return decoded;
|
|
354
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw) &&
|
|
355
|
+
Object.keys(raw).length === 2 &&
|
|
356
|
+
raw.mode === "unavailable") {
|
|
357
|
+
const reason = raw.reason;
|
|
358
|
+
if (typeof reason === "string" && reason.trim() && reason.length <= 2_000)
|
|
359
|
+
return reason.trim();
|
|
311
360
|
}
|
|
312
361
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
// No usable diagnostic; the caller still refuses computer control.
|
|
316
365
|
}
|
|
317
366
|
return null;
|
|
318
367
|
}
|
|
@@ -20,7 +20,7 @@ const identitySchema = z.object({ portalOrigin: z.string().max(2048), organizati
|
|
|
20
20
|
const PROVIDER_IDS = ["anthropic", "openai", "openrouter"];
|
|
21
21
|
const signature = (value) => createHash("sha256").update(JSON.stringify(value)).digest("hex");
|
|
22
22
|
const expiredMessage = "Company access has ended. Reconnect your organization or explicitly choose a personal model; personal billing will not be used automatically.";
|
|
23
|
-
export const LICENSE_EXPIRED_MESSAGE = "Your
|
|
23
|
+
export const LICENSE_EXPIRED_MESSAGE = "Your organization's OpenMaus Admin license has expired. Contact your admin.";
|
|
24
24
|
/** Validate only messages received over Electron's private utility-parent port.
|
|
25
25
|
* Never expose this input to renderer HTTP or merge it into saved AppConfig.
|
|
26
26
|
*/
|
|
@@ -36,14 +36,14 @@ import { createToolListNormalizer } from "./mcp-tool-schema.js";
|
|
|
36
36
|
// stdin/stdout/stderr resets the window.
|
|
37
37
|
export const BRIDGE_INACTIVITY_MS = 45_000;
|
|
38
38
|
const PROBE_TIMEOUT_MS = 10_000;
|
|
39
|
-
/** Run the liveness command; alive means "exited 0 within the timeout".
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
export function runLivenessProbe(probe, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
39
|
+
/** Run the liveness command; alive means "exited 0 within the timeout". A
|
|
40
|
+
* separate bounded command checks the transport without waiting for an
|
|
41
|
+
* answer on the possibly wedged MCP stream. */
|
|
42
|
+
export function runLivenessProbe(probe, timeoutMs = PROBE_TIMEOUT_MS, env) {
|
|
43
43
|
return new Promise((resolve) => {
|
|
44
44
|
const child = spawn(probe.command, probe.args, {
|
|
45
45
|
shell: false,
|
|
46
|
-
env: { ...process.env, PATH: augmentedPath() },
|
|
46
|
+
env: env ?? { ...process.env, PATH: augmentedPath() },
|
|
47
47
|
stdio: ["ignore", "ignore", "ignore"],
|
|
48
48
|
});
|
|
49
49
|
const timer = setTimeout(() => {
|
|
@@ -265,7 +265,7 @@ export function runMcpBridge(options) {
|
|
|
265
265
|
const liveness = options.liveness;
|
|
266
266
|
watchdog = createInactivityWatchdog({
|
|
267
267
|
inactivityMs: BRIDGE_INACTIVITY_MS,
|
|
268
|
-
probe: () => runLivenessProbe(liveness),
|
|
268
|
+
probe: () => runLivenessProbe(liveness, PROBE_TIMEOUT_MS, options.env),
|
|
269
269
|
onDead: () => {
|
|
270
270
|
process.stderr.write(`${options.label} transport went silent and stopped answering liveness probes; ending the bridge\n`);
|
|
271
271
|
process.exitCode = 1;
|
|
@@ -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
|
+
}
|