openmausbot 0.1.87 → 0.1.89
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 -1
- package/dist/assets/{abnfDiagram-O67JEVCF-BTiuL79F.js → abnfDiagram-O67JEVCF-BwaMaZEm.js} +1 -1
- package/dist/assets/{arc-C88Blc2v.js → arc-Be-8GKxd.js} +1 -1
- package/dist/assets/{architectureDiagram-NJMV4G6O-BZsJIZrb.js → architectureDiagram-NJMV4G6O-Dp_U2Kv1.js} +1 -1
- package/dist/assets/{blockDiagram-BEXU5L5S-CVeMe9Ah.js → blockDiagram-BEXU5L5S-DQjUjYUk.js} +1 -1
- package/dist/assets/{c4Diagram-YGBWAQC7-Cedk3Bhx.js → c4Diagram-YGBWAQC7-Bd3aE4Kc.js} +1 -1
- package/dist/assets/channel-DqY_gMLg.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-D-VRqzTB.js → chunk-2Q5K7J3B-BijjTBeJ.js} +1 -1
- package/dist/assets/{chunk-3FUC2YCW-BChov01Y.js → chunk-3FUC2YCW-CMGdwvzW.js} +2 -2
- package/dist/assets/{chunk-5VM5RSS4-C-TfwvHy.js → chunk-5VM5RSS4-0G09BfsZ.js} +1 -1
- package/dist/assets/{chunk-GTNCS2PH-Db7CGj5Y.js → chunk-GTNCS2PH-FOp3vSHe.js} +1 -1
- package/dist/assets/{chunk-GWA4HPMP-CNvIfqKT.js → chunk-GWA4HPMP-Dv-20VIn.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-C_bEp5tq.js → chunk-JWPE2WC7-CRgrdFcz.js} +1 -1
- package/dist/assets/{chunk-NETBCI7D-Coi4BOls.js → chunk-NETBCI7D-3hP4f7QB.js} +1 -1
- package/dist/assets/{chunk-WEXAMYUT-CzylEuL3.js → chunk-WEXAMYUT-CG98IjlG.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-m7p7ztaD.js → chunk-XXDRQBXY-BrSTC9xG.js} +1 -1
- package/dist/assets/{classDiagram-v2-NBCMYWYE-BMy6o9x2.js → classDiagram-v2-NBCMYWYE-rpQQQDFX.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-BDQ__0_J.js → cose-bilkent-JH36ORCC-G6RSafHA.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-Djv4ghUb.js → cynefin-OW5HDTMX-CXjv-IM2.js} +1 -1
- package/dist/assets/{cynefinDiagram-VND7K2PF-BULrlGYH.js → cynefinDiagram-VND7K2PF-Dw07MR9f.js} +1 -1
- package/dist/assets/{dagre-6A5THRUB-D-jrT_hU.js → dagre-6A5THRUB-BwPnlTg2.js} +1 -1
- package/dist/assets/{diagram-22UHCM2B-p2UhQmfL.js → diagram-22UHCM2B-Cm6xcMiz.js} +1 -1
- package/dist/assets/{diagram-3UASUU5V-DHvGWZ7q.js → diagram-3UASUU5V-CDpogPbE.js} +1 -1
- package/dist/assets/{diagram-ATOU4E4O-ChhKDot-.js → diagram-ATOU4E4O-BV8z3Pnc.js} +1 -1
- package/dist/assets/{diagram-CDSNMT55-B-T7A43R.js → diagram-CDSNMT55-CKCQhOOC.js} +1 -1
- package/dist/assets/{diagram-MLGK6HIB-CJm8ENNY.js → diagram-MLGK6HIB-FGvJg69C.js} +1 -1
- package/dist/assets/{diagram-MPIPVDR6-510tlza8.js → diagram-MPIPVDR6-CwATvgnS.js} +1 -1
- package/dist/assets/{ebnfDiagram-ZINNZB2B-PkvRPHel.js → ebnfDiagram-ZINNZB2B-CH_c3SSC.js} +1 -1
- package/dist/assets/{elk-276RUBZZ-BVBVPoX3.js → elk-276RUBZZ-3guZi71R.js} +1 -1
- package/dist/assets/{erDiagram-OPXOYQCR-BgYMVm7L.js → erDiagram-OPXOYQCR-BMHphR2n.js} +1 -1
- package/dist/assets/{flowDiagram-KWPJA3E3-BGqsnc_3.js → flowDiagram-KWPJA3E3-Vm5DkW5x.js} +1 -1
- package/dist/assets/{ganttDiagram-FUAMR5RP-D_-UeReH.js → ganttDiagram-FUAMR5RP-DO-1ct07.js} +1 -1
- package/dist/assets/{gitGraphDiagram-X574FWY7-D0uooONx.js → gitGraphDiagram-X574FWY7-nxeksEIN.js} +1 -1
- package/dist/assets/index-BIMdIbaw.css +1 -0
- package/dist/assets/index-BVPdbq2r.js +583 -0
- package/dist/assets/{index-zRsJERGJ.js → index-Oxk9x45i.js} +1 -1
- package/dist/assets/{infoDiagram-VRGFBTTK-B9e1z77f.js → infoDiagram-VRGFBTTK-Dkcvr0p7.js} +1 -1
- package/dist/assets/{ishikawaDiagram-OU5B5YK6-BB4vNwvD.js → ishikawaDiagram-OU5B5YK6-BwVibkoO.js} +1 -1
- package/dist/assets/{journeyDiagram-ZHPQQLJL-DpkosOTB.js → journeyDiagram-ZHPQQLJL-ByiBZqgG.js} +1 -1
- package/dist/assets/{kanban-definition-PNTS6WVX-DbDP4kUu.js → kanban-definition-PNTS6WVX-qqjgXBF3.js} +1 -1
- package/dist/assets/{linear-DBJGPmjT.js → linear-CtJnKe6A.js} +1 -1
- package/dist/assets/{mermaid.core-DWPRi-ue.js → mermaid.core-BEiDklrY.js} +5 -5
- package/dist/assets/{mindmap-definition-NLK3R4M7-nszBbJmx.js → mindmap-definition-NLK3R4M7-DfIYHia9.js} +1 -1
- package/dist/assets/{pegDiagram-GJSIUBJH-CWykJWu_.js → pegDiagram-GJSIUBJH-CYyRqa1a.js} +1 -1
- package/dist/assets/{pieDiagram-5QR66LMP-g3Da-Vnv.js → pieDiagram-5QR66LMP-hOToy_zH.js} +1 -1
- package/dist/assets/{quadrantDiagram-O4NWA36T-Wzrlpzgh.js → quadrantDiagram-O4NWA36T-DKAsNN9I.js} +1 -1
- package/dist/assets/{railroadDiagram-XR7U4H2S-moHTFMC0.js → railroadDiagram-XR7U4H2S-BSA-d8JU.js} +1 -1
- package/dist/assets/{requirementDiagram-PLB6GJNP-CwfXdFH8.js → requirementDiagram-PLB6GJNP-CSmlvb-p.js} +1 -1
- package/dist/assets/{sankeyDiagram-IPEJSGJF-3ZROYvnq.js → sankeyDiagram-IPEJSGJF-CD5F6fnG.js} +1 -1
- package/dist/assets/{sequenceDiagram-PO4LG4MO-E1TBebP8.js → sequenceDiagram-PO4LG4MO-JUq5sx6d.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-DHKEU5pu.js → sizeCapture-INFHLROL-BjIS-Stk.js} +1 -1
- package/dist/assets/{stateDiagram-v2-GCMORJYK-BguEj09D.js → stateDiagram-v2-GCMORJYK-DklkUxOg.js} +1 -1
- package/dist/assets/{swimlanes-2SLR337P-C7IDYnhd.js → swimlanes-2SLR337P-CsjIU6be.js} +1 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-Bk14M0_B.js +8 -0
- package/dist/assets/{timeline-definition-EJHVYXUP-DCW-F5PW.js → timeline-definition-EJHVYXUP-BkFqK7AB.js} +1 -1
- package/dist/assets/{usecaseDiagram-POWQR4AR-xBMFtWYV.js → usecaseDiagram-POWQR4AR-70gJB1EU.js} +1 -1
- package/dist/assets/{vennDiagram-UO4OBE2U-B5nIkuH8.js → vennDiagram-UO4OBE2U-83Tm62dN.js} +1 -1
- package/dist/assets/{wardleyDiagram-VNRHLVJA-DYFAhdbr.js → wardleyDiagram-VNRHLVJA-tTmseoX9.js} +1 -1
- package/dist/assets/{xychartDiagram-PMCCYNJV-DeXwX6Cz.js → xychartDiagram-PMCCYNJV-R1LBA55a.js} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/companion/src/routes.js +8 -1
- package/dist-server/connector-proxy.js +105 -1
- package/dist-server/container-mcp.js +11 -1
- package/dist-server/drivers/agents-proxy.js +277 -22
- package/dist-server/index.js +23722 -20272
- package/dist-server/local-computer-proxy.js +2 -0
- package/dist-server/mcp-gate.js +2 -0
- package/dist-server/mcp-server.js +5 -3
- package/dist-server/message-search.worker.js +52 -0
- package/dist-server/openmausbot.js +755 -404
- package/dist-server/pair-cli.js +755 -404
- package/dist-server/server/admission.js +81 -0
- package/dist-server/server/aside-queue.js +294 -0
- package/dist-server/server/attachments.js +43 -1
- package/dist-server/server/automatic-recovery.js +15 -0
- package/dist-server/server/bot-attachment.js +107 -0
- package/dist-server/server/bot-overview.js +19 -0
- package/dist-server/server/composio.js +297 -1
- package/dist-server/server/config.js +34 -3
- package/dist-server/server/connector-advertisement.js +165 -0
- package/dist-server/server/connector-proxy.js +14 -2
- package/dist-server/server/connector-verdict.js +31 -4
- package/dist-server/server/container-computer.js +70 -0
- package/dist-server/server/contracts.js +32 -0
- package/dist-server/server/drivers/acp/core.js +148 -23
- package/dist-server/server/drivers/acp/cursor.js +3 -7
- package/dist-server/server/drivers/acp/droid.js +4 -7
- package/dist-server/server/drivers/acp/gemini.js +4 -4
- package/dist-server/server/drivers/acp/grok.js +4 -9
- package/dist-server/server/drivers/acp/hermes.js +3 -5
- package/dist-server/server/drivers/acp/opencode-go.js +2 -5
- package/dist-server/server/drivers/acp/qwen.js +12 -15
- package/dist-server/server/drivers/agents-call.js +137 -10
- package/dist-server/server/drivers/agents-catalog.js +100 -6
- package/dist-server/server/drivers/boxagent.js +3 -17
- package/dist-server/server/drivers/claude.js +31 -17
- package/dist-server/server/drivers/codex-catalog.js +14 -6
- package/dist-server/server/drivers/codex-identity.js +2 -1
- package/dist-server/server/drivers/codex-release.js +48 -0
- package/dist-server/server/drivers/codex.js +7 -25
- package/dist-server/server/drivers/openai-chat.js +31 -3
- package/dist-server/server/drivers/pi.js +237 -30
- package/dist-server/server/drivers/prompt-split.js +32 -9
- package/dist-server/server/drivers/session-idle.js +29 -0
- package/dist-server/server/env-path.js +15 -0
- package/dist-server/server/guarded-requests.js +2 -2
- package/dist-server/server/harness-capabilities.js +61 -0
- package/dist-server/server/index.js +1173 -262
- package/dist-server/server/message-db.js +22 -42
- package/dist-server/server/message-file.js +9 -1
- package/dist-server/server/message-search-query.js +43 -0
- package/dist-server/server/message-search-worker.js +80 -0
- package/dist-server/server/message-search.worker.js +21 -0
- package/dist-server/server/model-requests.js +248 -0
- package/dist-server/server/options-card.js +21 -0
- package/dist-server/server/org-library.js +15 -1
- package/dist-server/server/peer-delivery.js +60 -0
- package/dist-server/server/peer-roster.js +57 -0
- package/dist-server/server/presets.js +32 -32
- package/dist-server/server/profile-requests.js +66 -39
- package/dist-server/server/profile-revision.js +9 -1
- package/dist-server/server/profile-versions.js +6 -3
- package/dist-server/server/routine-requests.js +29 -7
- package/dist-server/server/skill-fetch.js +72 -14
- package/dist-server/server/skills.js +1 -0
- package/dist-server/server/store.js +32 -2
- package/dist-server/server/system-prompt.js +37 -2
- package/dist-server/server/team-setup-requests.js +124 -23
- package/dist-server/server/thread-events.js +3 -1
- package/dist-server/server/tightening-requests.js +405 -0
- package/dist-server/server/tts/chatterbox.js +27 -5
- package/dist-server/server/usage-ledger.js +7 -1
- package/dist-server/server/webhooks.js +21 -3
- package/dist-server/server/workspace-backup.js +40 -3
- package/dist-server/server/workspace-backup.worker.js +10 -0
- package/dist-server/shared/ask-question.js +19 -0
- package/dist-server/shared/credential-request.js +5 -1
- package/dist-server/shared/line-diff.js +23 -0
- package/dist-server/shared/model-request.js +1 -0
- package/dist-server/shared/options-card.js +51 -0
- package/dist-server/shared/profile-request.js +5 -4
- package/dist-server/shared/tightening-request.js +87 -0
- package/dist-server/src/lib/composer-attachments.js +42 -3
- package/dist-server/vps-container-mcp.js +11 -1
- package/dist-server/workspace-backup.worker.js +19482 -0
- package/package.json +1 -1
- package/dist/assets/channel-taCNRlUU.js +0 -1
- package/dist/assets/index-BwdMAQ6p.css +0 -1
- package/dist/assets/index-ByJennr7.js +0 -581
- package/dist/assets/swimlanesDiagram-TC7HE7FX-BpEdoB2e.js +0 -8
|
@@ -50,6 +50,47 @@ function isCredentialTargetId(value) {
|
|
|
50
50
|
return typeof value === "string" && Object.prototype.hasOwnProperty.call(CREDENTIAL_TARGETS, value);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
// shared/options-card.ts
|
|
54
|
+
var WATCHER_OPTIONS_CARD_BOT_ID = "f08dd8e3-f942-4eb4-8783-df32b26b88a4";
|
|
55
|
+
var OPTIONS_CARD_LIMITS = {
|
|
56
|
+
title: 120,
|
|
57
|
+
subtitle: 1e3,
|
|
58
|
+
option: 120,
|
|
59
|
+
minOptions: 2,
|
|
60
|
+
maxOptions: 6
|
|
61
|
+
};
|
|
62
|
+
function record(value) {
|
|
63
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
64
|
+
}
|
|
65
|
+
function boundedText(value, field, maximum) {
|
|
66
|
+
if (typeof value !== "string") return { error: `${field} must be a string.` };
|
|
67
|
+
const text = value.trim();
|
|
68
|
+
if (!text) return { error: `${field} must not be blank.` };
|
|
69
|
+
if (text.length > maximum) return { error: `${field} must be at most ${maximum} characters.` };
|
|
70
|
+
return text;
|
|
71
|
+
}
|
|
72
|
+
function parseOptionsCardInput(value) {
|
|
73
|
+
if (!record(value)) return { ok: false, error: "create_options_card needs an object." };
|
|
74
|
+
const title = boundedText(value.title, "title", OPTIONS_CARD_LIMITS.title);
|
|
75
|
+
if (typeof title !== "string") return { ok: false, error: title.error };
|
|
76
|
+
const subtitle = boundedText(value.subtitle, "subtitle", OPTIONS_CARD_LIMITS.subtitle);
|
|
77
|
+
if (typeof subtitle !== "string") return { ok: false, error: subtitle.error };
|
|
78
|
+
if (!Array.isArray(value.options)) return { ok: false, error: "options must be an array of strings." };
|
|
79
|
+
if (value.options.length < OPTIONS_CARD_LIMITS.minOptions || value.options.length > OPTIONS_CARD_LIMITS.maxOptions) {
|
|
80
|
+
return { ok: false, error: `options must contain ${OPTIONS_CARD_LIMITS.minOptions}-${OPTIONS_CARD_LIMITS.maxOptions} items.` };
|
|
81
|
+
}
|
|
82
|
+
const options = [];
|
|
83
|
+
const seen = /* @__PURE__ */ new Set();
|
|
84
|
+
for (let index = 0; index < value.options.length; index += 1) {
|
|
85
|
+
const option = boundedText(value.options[index], `options[${index}]`, OPTIONS_CARD_LIMITS.option);
|
|
86
|
+
if (typeof option !== "string") return { ok: false, error: option.error };
|
|
87
|
+
if (seen.has(option)) return { ok: false, error: `options must be unique; "${option}" is repeated.` };
|
|
88
|
+
seen.add(option);
|
|
89
|
+
options.push(option);
|
|
90
|
+
}
|
|
91
|
+
return { ok: true, value: { title, subtitle, options } };
|
|
92
|
+
}
|
|
93
|
+
|
|
53
94
|
// server/agent-tool-policy.ts
|
|
54
95
|
var READ_ONLY_AGENT_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
55
96
|
"list_bots",
|
|
@@ -206,6 +247,26 @@ var ROUTINE_FIELDS_SCHEMA = {
|
|
|
206
247
|
};
|
|
207
248
|
var PROPOSAL_OUTCOME = " Read the result: granted Full Access may apply the change immediately. If applied, continue the requested work without another confirmation. Only a pending result requires ending the turn and waiting for the in-app decision. Never claim success from the permission mode alone; report failed or cancelled results honestly. This does not elevate another bot's execution permissions.";
|
|
208
249
|
var toolDefinitions = (externalRuntime) => [
|
|
250
|
+
{
|
|
251
|
+
name: "create_options_card",
|
|
252
|
+
description: "Show the person a native card with 2-6 choices in this Watcher conversation. The card is passive: a click returns the selected words as a reply and never authorizes or performs an external action. Use it for Watcher's review and draft-selection steps, then wait for the person's response.",
|
|
253
|
+
inputSchema: {
|
|
254
|
+
type: "object",
|
|
255
|
+
additionalProperties: false,
|
|
256
|
+
properties: {
|
|
257
|
+
title: { type: "string", minLength: 1, maxLength: OPTIONS_CARD_LIMITS.title },
|
|
258
|
+
subtitle: { type: "string", minLength: 1, maxLength: OPTIONS_CARD_LIMITS.subtitle },
|
|
259
|
+
options: {
|
|
260
|
+
type: "array",
|
|
261
|
+
minItems: OPTIONS_CARD_LIMITS.minOptions,
|
|
262
|
+
maxItems: OPTIONS_CARD_LIMITS.maxOptions,
|
|
263
|
+
uniqueItems: true,
|
|
264
|
+
items: { type: "string", minLength: 1, maxLength: OPTIONS_CARD_LIMITS.option }
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
required: ["title", "subtitle", "options"]
|
|
268
|
+
}
|
|
269
|
+
},
|
|
209
270
|
{
|
|
210
271
|
name: "tool_result_read",
|
|
211
272
|
description: "Read a missing portion of an oversized agents-tool result using the saved id and next offset from its notice. Returns at most 16,000 characters, only from this bot in this conversation. Use only when the preview is insufficient; do not load every page by default. Results expire after one hour, on app restart, or under cache pressure. This never reruns the original action.",
|
|
@@ -356,15 +417,42 @@ var toolDefinitions = (externalRuntime) => [
|
|
|
356
417
|
required: ["title", "message"]
|
|
357
418
|
}
|
|
358
419
|
},
|
|
420
|
+
{
|
|
421
|
+
name: "vm_exec",
|
|
422
|
+
description: "Run a shell command inside your own Local VM (as the desktop user, starting in /home/cua/workspace) and get its exit code, stdout and stderr back as text. Use this for all command-line work in the VM: pip install --user, running a script, generating or converting a file, checking that a file exists. Do not type commands into a terminal window and read screenshots: that is slow and unreliable. GUI programs you start appear on the VM desktop. For a long job raise timeout_seconds (default 60, at most 300). Only available while you have a Local VM desktop.",
|
|
423
|
+
inputSchema: {
|
|
424
|
+
type: "object",
|
|
425
|
+
additionalProperties: false,
|
|
426
|
+
properties: {
|
|
427
|
+
command: { type: "string", description: "The shell command to run, for example: python3 make_report.py && ls -l report.pdf" },
|
|
428
|
+
timeout_seconds: { type: "integer", minimum: 1, maximum: 300, description: "How long it may run before it is stopped. Default 60." }
|
|
429
|
+
},
|
|
430
|
+
required: ["command"]
|
|
431
|
+
}
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
name: "attach_file",
|
|
435
|
+
description: "Attach a finished file to the chat so the user can preview and download it: an image, video, audio clip, PDF, spreadsheet, slide deck or other document you made. Pass its path: a path inside your computer's /home/cua/workspace (for example /home/cua/workspace/report.pdf), or a file in your working folder. Do this instead of pasting a VM path as a link; a path inside a VM cannot be opened from chat. Supported: images (png, jpg, gif, webp), video (mp4, webm, mov), audio (mp3, m4a, aac, wav, ogg, opus, flac), pdf, Word/Excel/PowerPoint and OpenDocument files, and csv, tsv, txt, md, json, rtf. Up to 25 MB (images 10 MB). Finish writing the file first, then call this directly: it reports an error if the file is missing, so you do not need to list or open the folder to check.",
|
|
436
|
+
inputSchema: {
|
|
437
|
+
type: "object",
|
|
438
|
+
additionalProperties: false,
|
|
439
|
+
properties: {
|
|
440
|
+
path: { type: "string", description: "The file's path, for example /home/cua/workspace/report.pdf." },
|
|
441
|
+
name: { type: "string", description: "Optional file name to show the user. Defaults to the file's own name." }
|
|
442
|
+
},
|
|
443
|
+
required: ["path"]
|
|
444
|
+
}
|
|
445
|
+
},
|
|
359
446
|
{
|
|
360
447
|
name: "post_to_room",
|
|
361
|
-
description: "Put one message into a shared room you belong to, for example when the user asks you to tell the team something. Get group_id from list_rooms. This posts and returns: no room member's turn starts, nobody replies, and nothing comes back except confirmation \u2014 so never use it to ask a question or hand out work (use ask_bot or delegate_bot for those). Post once, say it in full, and tell the user what you posted. If a post is refused, do not retry it: say what you wanted to post in your reply instead.",
|
|
448
|
+
description: "Put one message into a shared room you belong to, for example when the user asks you to tell the team something. Get group_id from list_rooms. This posts and returns: no room member's turn starts, nobody replies, and nothing comes back except confirmation \u2014 so never use it to ask a question or hand out work (use ask_bot or delegate_bot for those). Post once, say it in full, and tell the user what you posted. Set attach_voice_note true to attach this turn's voice note. If a post is refused, do not retry it: say what you wanted to post in your reply instead.",
|
|
362
449
|
inputSchema: {
|
|
363
450
|
type: "object",
|
|
364
451
|
additionalProperties: false,
|
|
365
452
|
properties: {
|
|
366
453
|
group_id: { type: "string", description: "The room's id, copied exactly from list_rooms." },
|
|
367
|
-
message: { type: "string", description: "The complete message to post, written for the room to read as it stands." }
|
|
454
|
+
message: { type: "string", description: "The complete message to post, written for the room to read as it stands." },
|
|
455
|
+
attach_voice_note: { type: "boolean", description: "True to attach this turn's send_voice_note recording; the message is its caption. Call send_voice_note first." }
|
|
368
456
|
},
|
|
369
457
|
required: ["group_id", "message"]
|
|
370
458
|
}
|
|
@@ -383,7 +471,12 @@ var toolDefinitions = (externalRuntime) => [
|
|
|
383
471
|
model: { type: "string" },
|
|
384
472
|
effort: { type: "string" },
|
|
385
473
|
variant: { type: "string" }
|
|
386
|
-
}, required: ["instanceId", "model"] }
|
|
474
|
+
}, required: ["instanceId", "model"] },
|
|
475
|
+
cwd: {
|
|
476
|
+
type: "string",
|
|
477
|
+
maxLength: 1024,
|
|
478
|
+
description: "Absolute path of the folder this specialist's tools read and write in (for example /Users/me/Projects/site). It must already exist. Leave it out for the specialist's private workspace."
|
|
479
|
+
}
|
|
387
480
|
},
|
|
388
481
|
required: ["name", "role", "instructions"]
|
|
389
482
|
}
|
|
@@ -415,11 +508,13 @@ var toolDefinitions = (externalRuntime) => [
|
|
|
415
508
|
chiefOfStaff: { type: "boolean", description: "Appoint or remove this team's Chief. At most one Chief per team: explicitly demote the current Chief in the same plan when replacing them. Does not grant access to other teams or change execution permissions." },
|
|
416
509
|
description: { type: "string", maxLength: 4e3 },
|
|
417
510
|
soul: { type: "string", description: "Standing instructions; required with name/title/modelSelection for every new bot." },
|
|
511
|
+
cwd: { type: "string", maxLength: 1024, description: "Create only: absolute path of the folder the new bot's tools read and write in. It must already exist. Leave it out for a private workspace." },
|
|
418
512
|
section: { type: "string", maxLength: 60, description: "Exact authorized existing team, or a team explicitly named in newTeams. Empty string means General." },
|
|
419
513
|
modelSelection: { type: "object", additionalProperties: false, properties: {
|
|
420
514
|
instanceId: { type: "string" },
|
|
421
515
|
model: { type: "string" },
|
|
422
|
-
effort: { type: "string" }
|
|
516
|
+
effort: { type: "string" },
|
|
517
|
+
variant: { type: "string" }
|
|
423
518
|
}, required: ["instanceId", "model"] }
|
|
424
519
|
} }
|
|
425
520
|
},
|
|
@@ -645,7 +740,7 @@ var toolDefinitions = (externalRuntime) => [
|
|
|
645
740
|
},
|
|
646
741
|
{
|
|
647
742
|
name: "propose_profile",
|
|
648
|
-
description: "Submit user-requested changes to your own name, title, description, standing instructions (SOUL.md),
|
|
743
|
+
description: "Submit user-requested changes to your own name, title, description, standing instructions (SOUL.md), working folder (cwd), or your alert and voice toggles (notifications, speakReplies). 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) for a requested change to another bot in its section." + PROPOSAL_OUTCOME,
|
|
649
744
|
inputSchema: {
|
|
650
745
|
type: "object",
|
|
651
746
|
additionalProperties: false,
|
|
@@ -659,6 +754,14 @@ var toolDefinitions = (externalRuntime) => [
|
|
|
659
754
|
maxLength: 1024,
|
|
660
755
|
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."
|
|
661
756
|
},
|
|
757
|
+
notifications: {
|
|
758
|
+
type: "boolean",
|
|
759
|
+
description: "Completion and attention notifications for this bot on the host and paired clients."
|
|
760
|
+
},
|
|
761
|
+
speakReplies: {
|
|
762
|
+
type: "boolean",
|
|
763
|
+
description: "Speak this bot's replies aloud as they settle, without being asked."
|
|
764
|
+
},
|
|
662
765
|
reason: { type: "string", minLength: 1, maxLength: 500, description: "One sentence the user will see explaining why." },
|
|
663
766
|
for_bot_id: {
|
|
664
767
|
type: "string",
|
|
@@ -668,6 +771,34 @@ var toolDefinitions = (externalRuntime) => [
|
|
|
668
771
|
required: ["reason"]
|
|
669
772
|
}
|
|
670
773
|
},
|
|
774
|
+
{
|
|
775
|
+
name: "propose_model",
|
|
776
|
+
description: "Submit a user-requested switch of this bot's default engine and model. Use the exact instance and model ids the person named, or for a Chief the ids from the team-setup catalog. The card warns about capabilities the switch gains or loses; existing threads keep their current models." + PROPOSAL_OUTCOME,
|
|
777
|
+
inputSchema: {
|
|
778
|
+
type: "object",
|
|
779
|
+
additionalProperties: false,
|
|
780
|
+
properties: {
|
|
781
|
+
model_selection: {
|
|
782
|
+
type: "object",
|
|
783
|
+
additionalProperties: false,
|
|
784
|
+
properties: {
|
|
785
|
+
instanceId: { type: "string", minLength: 1, description: "Engine instance id, for example codex or claude." },
|
|
786
|
+
model: { type: "string", minLength: 1, description: "Exact model id on that instance." },
|
|
787
|
+
effort: { type: "string", description: "Optional effort level the instance offers; omit for the engine default." },
|
|
788
|
+
variant: { type: "string", description: "Optional explicit model variant; choose this or effort, not both." }
|
|
789
|
+
},
|
|
790
|
+
required: ["instanceId", "model"],
|
|
791
|
+
description: "The new default selection."
|
|
792
|
+
},
|
|
793
|
+
reason: { type: "string", minLength: 1, maxLength: 500, description: "One sentence the user will see explaining why." },
|
|
794
|
+
for_bot_id: {
|
|
795
|
+
type: "string",
|
|
796
|
+
description: "Chief of Staff only: the id of another bot in your section whose default model this changes. Omit to change your own."
|
|
797
|
+
}
|
|
798
|
+
},
|
|
799
|
+
required: ["model_selection", "reason"]
|
|
800
|
+
}
|
|
801
|
+
},
|
|
671
802
|
{
|
|
672
803
|
name: "skills_list",
|
|
673
804
|
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.",
|
|
@@ -715,12 +846,14 @@ var VOICE_TOOL_NAMES = /* @__PURE__ */ new Set(["send_voice_note"]);
|
|
|
715
846
|
var ROOM_ONLY_TOOLS = /* @__PURE__ */ new Set(["list_room_targets", "coordinate_bots"]);
|
|
716
847
|
var ROOM_REPLACED_TOOLS = /* @__PURE__ */ new Set(["ask_bot", "delegate_bot", "check_delegation", "wait_delegation", "start_thread", "send_to_thread", "wait_thread"]);
|
|
717
848
|
var EXTERNAL_TOOL_NAMES = /* @__PURE__ */ new Set(["list_bots", "ask_bot", "delegate_bot", "check_delegation", "wait_delegation"]);
|
|
849
|
+
var WATCHER_TOOL_NAMES = /* @__PURE__ */ new Set(["create_options_card"]);
|
|
718
850
|
function availableTools(profile) {
|
|
719
851
|
const TOOLS = toolDefinitions(profile.externalRuntime);
|
|
720
|
-
const
|
|
852
|
+
const BOT_SCOPED_TOOLS = profile.botId === WATCHER_OPTIONS_CARD_BOT_ID ? TOOLS : TOOLS.filter((tool) => !WATCHER_TOOL_NAMES.has(tool.name));
|
|
853
|
+
const AUTHORING_TOOLS = profile.skillAuthoring ? BOT_SCOPED_TOOLS : BOT_SCOPED_TOOLS.filter((tool) => !SKILL_TOOL_NAMES.has(tool.name));
|
|
721
854
|
const SHAREABLE_TOOLS = profile.sharedComputers ? AUTHORING_TOOLS : AUTHORING_TOOLS.filter((tool) => !SHARED_COMPUTER_TOOL_NAMES.has(tool.name));
|
|
722
855
|
const VOICE_READY_TOOLS = profile.voiceNotes ? SHAREABLE_TOOLS : SHAREABLE_TOOLS.filter((tool) => !VOICE_TOOL_NAMES.has(tool.name));
|
|
723
|
-
return profile.externalRuntime ?
|
|
856
|
+
return profile.externalRuntime ? BOT_SCOPED_TOOLS.filter((tool) => EXTERNAL_TOOL_NAMES.has(tool.name)) : profile.coordinating ? VOICE_READY_TOOLS.filter((tool) => !ROOM_REPLACED_TOOLS.has(tool.name) || tool.name === "start_thread" && profile.ownThreadCreation).map((tool) => tool.name === "start_thread" ? {
|
|
724
857
|
...tool,
|
|
725
858
|
description: "Open a separate job on yourself with its own history and run, without switching the person's selected conversation. Use only when the user requests independent jobs (for example one review per pull request). Give a short specific title and complete instructions; you can open at most five per turn. This is not a teammate handoff: use coordinate_bots for teammates and their automatic replies. Self-opened jobs cannot recursively open more jobs. If refused, do not retry; explain what remains.",
|
|
726
859
|
inputSchema: { ...tool.inputSchema, properties: {
|
|
@@ -1632,7 +1765,7 @@ __export(external_exports, {
|
|
|
1632
1765
|
promise: () => promise,
|
|
1633
1766
|
property: () => _property,
|
|
1634
1767
|
readonly: () => readonly,
|
|
1635
|
-
record: () =>
|
|
1768
|
+
record: () => record2,
|
|
1636
1769
|
refine: () => refine,
|
|
1637
1770
|
regex: () => _regex,
|
|
1638
1771
|
regexes: () => regexes_exports,
|
|
@@ -13970,7 +14103,7 @@ __export(schemas_exports2, {
|
|
|
13970
14103
|
preprocess: () => preprocess,
|
|
13971
14104
|
promise: () => promise,
|
|
13972
14105
|
readonly: () => readonly,
|
|
13973
|
-
record: () =>
|
|
14106
|
+
record: () => record2,
|
|
13974
14107
|
refine: () => refine,
|
|
13975
14108
|
set: () => set,
|
|
13976
14109
|
strictObject: () => strictObject,
|
|
@@ -14939,7 +15072,7 @@ var ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
|
|
|
14939
15072
|
inst.keyType = def.keyType;
|
|
14940
15073
|
inst.valueType = def.valueType;
|
|
14941
15074
|
});
|
|
14942
|
-
function
|
|
15075
|
+
function record2(keyType, valueType, params) {
|
|
14943
15076
|
if (!valueType || !valueType._zod) {
|
|
14944
15077
|
return new ZodRecord({
|
|
14945
15078
|
type: "record",
|
|
@@ -15406,7 +15539,7 @@ var stringbool = (...args) => _stringbool({
|
|
|
15406
15539
|
}, ...args);
|
|
15407
15540
|
function json(params) {
|
|
15408
15541
|
const jsonSchema = lazy(() => {
|
|
15409
|
-
return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema),
|
|
15542
|
+
return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema), record2(string2(), jsonSchema)]);
|
|
15410
15543
|
});
|
|
15411
15544
|
return jsonSchema;
|
|
15412
15545
|
}
|
|
@@ -15975,6 +16108,15 @@ function peerName(value) {
|
|
|
15975
16108
|
return clip(value.replace(/[[\]]/g, " "), ROSTER_NAME_MAX);
|
|
15976
16109
|
}
|
|
15977
16110
|
|
|
16111
|
+
// server/peer-delivery.ts
|
|
16112
|
+
var named = (receipt) => peerName(receipt.botName ?? "") || peerName(receipt.botId) || "teammate";
|
|
16113
|
+
function renderPeerDeliveryReceipts(receipts) {
|
|
16114
|
+
if (!receipts.length) return "";
|
|
16115
|
+
const line = (receipt) => `${named(receipt)}: ${receipt.outcome} \u2014 ${receipt.detail}`;
|
|
16116
|
+
if (receipts.length === 1) return `Delivery to ${line(receipts[0])}`;
|
|
16117
|
+
return ["Delivery receipts:", ...receipts.map((receipt) => `- ${line(receipt)}`)].join("\n");
|
|
16118
|
+
}
|
|
16119
|
+
|
|
15978
16120
|
// server/drivers/agents-client.ts
|
|
15979
16121
|
function createHarnessClient(baseUrl, token) {
|
|
15980
16122
|
async function api(path, init) {
|
|
@@ -16348,6 +16490,23 @@ function recallSpeaker(hit) {
|
|
|
16348
16490
|
if (typeof hit.from === "string" && hit.from) return hit.from;
|
|
16349
16491
|
return hit.role === "user" ? "user" : "you";
|
|
16350
16492
|
}
|
|
16493
|
+
var isPeerDeliveryOutcome = (value) => value === "queued" || value === "injected" || value === "failed";
|
|
16494
|
+
function deliveryNote(r) {
|
|
16495
|
+
const receipt = r.receipt;
|
|
16496
|
+
if (!receipt || typeof receipt !== "object") return "";
|
|
16497
|
+
const { botId, botName, outcome, detail, taskId, requestId } = receipt;
|
|
16498
|
+
if (typeof botId !== "string" || !botId || typeof detail !== "string" || !detail) return "";
|
|
16499
|
+
if (!isPeerDeliveryOutcome(outcome)) return "";
|
|
16500
|
+
const parsed = {
|
|
16501
|
+
botId,
|
|
16502
|
+
...typeof botName === "string" && botName ? { botName } : {},
|
|
16503
|
+
outcome,
|
|
16504
|
+
detail,
|
|
16505
|
+
...typeof taskId === "string" && taskId ? { taskId } : {},
|
|
16506
|
+
...typeof requestId === "string" && requestId ? { requestId } : {}
|
|
16507
|
+
};
|
|
16508
|
+
return renderPeerDeliveryReceipts([parsed]);
|
|
16509
|
+
}
|
|
16351
16510
|
function recallWhen(at, dateOnly) {
|
|
16352
16511
|
if (typeof at !== "number" || !Number.isFinite(at)) return "";
|
|
16353
16512
|
const said = new Date(at);
|
|
@@ -16360,6 +16519,43 @@ async function callTool(name, args, context) {
|
|
|
16360
16519
|
const { botId: BOT_ID, threadId: THREAD_ID, depth: DEPTH, externalRuntime: EXTERNAL_RUNTIME, coordinating: COORDINATING, turn } = context;
|
|
16361
16520
|
const { delegationTaskIdsThisTurn } = turn;
|
|
16362
16521
|
const { api, apiResponse } = context.client;
|
|
16522
|
+
if (name === "vm_exec") {
|
|
16523
|
+
const { ok: ok2, body } = await apiResponse("/api/internal/vm-exec", {
|
|
16524
|
+
method: "POST",
|
|
16525
|
+
body: JSON.stringify({ command: args.command, ...typeof args.timeout_seconds === "number" ? { timeout_seconds: args.timeout_seconds } : {} })
|
|
16526
|
+
});
|
|
16527
|
+
if (!ok2) return { text: String(body.error ?? "Could not run that command."), isError: true };
|
|
16528
|
+
const exitCode = Number(body.exitCode ?? 0);
|
|
16529
|
+
const stdout = String(body.stdout ?? "");
|
|
16530
|
+
const stderr = String(body.stderr ?? "");
|
|
16531
|
+
const lines = [body.timedOut ? "The command was stopped: it ran past its time limit." : `exit code ${exitCode}`];
|
|
16532
|
+
if (stdout) lines.push("--- stdout ---", stdout.replace(/\s+$/, ""));
|
|
16533
|
+
if (stderr) lines.push("--- stderr ---", stderr.replace(/\s+$/, ""));
|
|
16534
|
+
if (!stdout && !stderr && !body.timedOut) lines.push("(no output)");
|
|
16535
|
+
return { text: lines.join("\n"), ...exitCode !== 0 || body.timedOut ? { isError: true } : {} };
|
|
16536
|
+
}
|
|
16537
|
+
if (name === "attach_file") {
|
|
16538
|
+
const { ok: ok2, body } = await apiResponse("/api/internal/attach-file", {
|
|
16539
|
+
method: "POST",
|
|
16540
|
+
body: JSON.stringify({ path: args.path, ...typeof args.name === "string" ? { name: args.name } : {} })
|
|
16541
|
+
});
|
|
16542
|
+
if (!ok2) return { text: String(body.error ?? "Could not attach that file."), isError: true };
|
|
16543
|
+
return { text: `Attached ${String(body.name ?? "the file")} (${Number(body.bytes ?? 0)} bytes). It now appears in the chat with a preview.` };
|
|
16544
|
+
}
|
|
16545
|
+
if (name === "create_options_card") {
|
|
16546
|
+
if (BOT_ID !== WATCHER_OPTIONS_CARD_BOT_ID) {
|
|
16547
|
+
return { text: "create_options_card is not enabled for this bot.", isError: true };
|
|
16548
|
+
}
|
|
16549
|
+
const parsed = parseOptionsCardInput(args);
|
|
16550
|
+
if (!parsed.ok) return { text: parsed.error, isError: true };
|
|
16551
|
+
const result = await api("/api/internal/options-card", {
|
|
16552
|
+
method: "POST",
|
|
16553
|
+
body: JSON.stringify(parsed.value)
|
|
16554
|
+
});
|
|
16555
|
+
return {
|
|
16556
|
+
text: `Rendered the native options card in this Watcher thread (message ${String(result.messageId ?? "created")}). Wait for the person's click or custom response; the card itself authorizes no external action.`
|
|
16557
|
+
};
|
|
16558
|
+
}
|
|
16363
16559
|
if (SHARED_COMPUTER_TOOL_NAMES.has(name) && !context.sharedComputers) {
|
|
16364
16560
|
return { text: "Computer sharing is turned off in this workspace. There are no shared computers to use.", isError: true };
|
|
16365
16561
|
}
|
|
@@ -16456,6 +16652,7 @@ Use post_to_room with one of these ids. A post adds one message to the room; it
|
|
|
16456
16652
|
if (name === "post_to_room") {
|
|
16457
16653
|
const groupId = String(args.group_id ?? "").trim();
|
|
16458
16654
|
const message = String(args.message ?? "").trim();
|
|
16655
|
+
const attachVoiceNote = args.attach_voice_note === true;
|
|
16459
16656
|
if (!groupId || !message) {
|
|
16460
16657
|
return { text: "post_to_room needs group_id (from list_rooms) and message.", isError: true };
|
|
16461
16658
|
}
|
|
@@ -16467,12 +16664,12 @@ Use post_to_room with one of these ids. A post adds one message to the room; it
|
|
|
16467
16664
|
}
|
|
16468
16665
|
const r = await api("/api/internal/post-to-room", {
|
|
16469
16666
|
method: "POST",
|
|
16470
|
-
body: JSON.stringify({ fromBotId: BOT_ID, fromThreadId: THREAD_ID, groupId, message })
|
|
16667
|
+
body: JSON.stringify({ fromBotId: BOT_ID, fromThreadId: THREAD_ID, groupId, message, attachVoiceNote })
|
|
16471
16668
|
});
|
|
16472
16669
|
if (r.error) return { text: String(r.error), isError: true };
|
|
16473
16670
|
turn.roomPostsThisTurn += 1;
|
|
16474
16671
|
return {
|
|
16475
|
-
text: `Posted in ${r.roomName ?? "the room"}. Nobody's turn was started, so expect no reply \u2014 tell the user it is posted.`
|
|
16672
|
+
text: `Posted in ${r.roomName ?? "the room"}${r.attachedVoiceNote ? " with the voice note attached" : ""}. Nobody's turn was started, so expect no reply \u2014 tell the user it is posted.`
|
|
16476
16673
|
};
|
|
16477
16674
|
}
|
|
16478
16675
|
if (name === "ask_bot") {
|
|
@@ -16483,6 +16680,7 @@ Use post_to_room with one of these ids. A post adds one message to the room; it
|
|
|
16483
16680
|
method: "POST",
|
|
16484
16681
|
body: JSON.stringify({ fromBotId: BOT_ID, fromThreadId: THREAD_ID, toBotId, message, depth: DEPTH })
|
|
16485
16682
|
});
|
|
16683
|
+
const note = deliveryNote(r);
|
|
16486
16684
|
if (r.timeout) {
|
|
16487
16685
|
const taskId = String(r.taskId ?? "").trim();
|
|
16488
16686
|
if (taskId && !EXTERNAL_RUNTIME) delegationTaskIdsThisTurn.add(taskId);
|
|
@@ -16490,22 +16688,42 @@ Use post_to_room with one of these ids. A post adds one message to the room; it
|
|
|
16490
16688
|
const amount = waitedSeconds < 60 ? waitedSeconds : Math.round(waitedSeconds / 60);
|
|
16491
16689
|
const unit = waitedSeconds < 60 ? "second" : "minute";
|
|
16492
16690
|
return {
|
|
16493
|
-
text: `${r.toBotName ?? "That bot"} is still working after ${amount} ${unit}${amount === 1 ? "" : "s"} \u2014 the ask was converted to a delegation so the reply is not lost. Task id: ${taskId}. ${EXTERNAL_RUNTIME ? EXTERNAL_STATUS_GUIDANCE : "Finish your turn now; the result will be delivered to this conversation automatically. Use check_delegation in a later turn only if the user asks for status."}`
|
|
16691
|
+
text: `${r.toBotName ?? "That bot"} is still working after ${amount} ${unit}${amount === 1 ? "" : "s"} \u2014 the ask was converted to a delegation so the reply is not lost. Task id: ${taskId}. ${EXTERNAL_RUNTIME ? EXTERNAL_STATUS_GUIDANCE : "Finish your turn now; the result will be delivered to this conversation automatically. Use check_delegation in a later turn only if the user asks for status."}${note ? `
|
|
16692
|
+
|
|
16693
|
+
${note}` : ""}`
|
|
16494
16694
|
};
|
|
16495
16695
|
}
|
|
16496
16696
|
if (r.busy) {
|
|
16697
|
+
if (r.aside === "injected") {
|
|
16698
|
+
return {
|
|
16699
|
+
text: `${r.toBotName ?? "That bot"} is mid-turn; your message was handed to them as an aside \u2014 peer context folded into their current work, not a request that interrupts or replies. Finish your turn and treat their eventual output as possibly informed by it.`
|
|
16700
|
+
};
|
|
16701
|
+
}
|
|
16702
|
+
if (r.aside === "queued") {
|
|
16703
|
+
return {
|
|
16704
|
+
text: `${r.toBotName ?? "That bot"} is mid-turn; your aside is queued and will reach them as context when the turn settles. No reply is expected \u2014 finish your turn.`
|
|
16705
|
+
};
|
|
16706
|
+
}
|
|
16497
16707
|
const taskId = String(r.taskId ?? "").trim();
|
|
16498
16708
|
if (taskId) {
|
|
16499
16709
|
if (!EXTERNAL_RUNTIME) delegationTaskIdsThisTurn.add(taskId);
|
|
16500
16710
|
return {
|
|
16501
|
-
text: `${r.toBotName ?? "That bot"} is busy right now, so your message was queued as a delegation instead \u2014 ${EXTERNAL_RUNTIME ? "it waits for the peer and any required approval" : "it runs after your current turn ends"}. Task id: ${taskId}. ${EXTERNAL_RUNTIME ? EXTERNAL_STATUS_GUIDANCE : "Finish your turn now; the result will be delivered to this conversation automatically. Use check_delegation in a later turn only if the user asks for status."}`
|
|
16711
|
+
text: `${r.toBotName ?? "That bot"} is busy right now, so your message was queued as a delegation instead \u2014 ${EXTERNAL_RUNTIME ? "it waits for the peer and any required approval" : "it runs after your current turn ends"}. Task id: ${taskId}. ${EXTERNAL_RUNTIME ? EXTERNAL_STATUS_GUIDANCE : "Finish your turn now; the result will be delivered to this conversation automatically. Use check_delegation in a later turn only if the user asks for status."}${note ? `
|
|
16712
|
+
|
|
16713
|
+
${note}` : ""}`
|
|
16502
16714
|
};
|
|
16503
16715
|
}
|
|
16504
|
-
return { text: `That bot is busy right now \u2014 try again after it finishes
|
|
16716
|
+
return { text: `That bot is busy right now \u2014 try again after it finishes.${note ? `
|
|
16717
|
+
|
|
16718
|
+
${note}` : ""}` };
|
|
16505
16719
|
}
|
|
16506
|
-
if (r.error) return { text: `Couldn't reach that bot: ${r.error}
|
|
16720
|
+
if (r.error) return { text: `Couldn't reach that bot: ${r.error}${note ? `
|
|
16721
|
+
|
|
16722
|
+
${note}` : ""}`, isError: true };
|
|
16507
16723
|
return { text: `${r.botName ?? "Bot"} replied:
|
|
16508
|
-
${r.text ?? "(no reply)"}`
|
|
16724
|
+
${r.text ?? "(no reply)"}${note ? `
|
|
16725
|
+
|
|
16726
|
+
${note}` : ""}` };
|
|
16509
16727
|
}
|
|
16510
16728
|
if (name === "delegate_bot") {
|
|
16511
16729
|
const toBotId = String(args.bot_id ?? "").trim();
|
|
@@ -16521,12 +16739,17 @@ ${r.text ?? "(no reply)"}` };
|
|
|
16521
16739
|
};
|
|
16522
16740
|
if (reason) body.reason = reason;
|
|
16523
16741
|
const r = await api(`/api/internal/delegate-bot`, { method: "POST", body: JSON.stringify(body) });
|
|
16524
|
-
|
|
16742
|
+
const delivery = deliveryNote(r);
|
|
16743
|
+
if (r.error) return { text: `Couldn't queue the delegation: ${r.error}${delivery ? `
|
|
16744
|
+
|
|
16745
|
+
${delivery}` : ""}`, isError: true };
|
|
16525
16746
|
const note = typeof r.message === "string" ? r.message : "Delegation queued.";
|
|
16526
16747
|
const taskId = typeof r.taskId === "string" ? r.taskId.trim() : "";
|
|
16527
16748
|
if (taskId && !EXTERNAL_RUNTIME) delegationTaskIdsThisTurn.add(taskId);
|
|
16528
16749
|
const suffix = taskId ? ` Task id: ${taskId}. ${EXTERNAL_RUNTIME ? EXTERNAL_STATUS_GUIDANCE : "Acknowledge the assignment and finish your turn; the result will be delivered to this conversation automatically. Do not check or wait for it in this turn."}` : "";
|
|
16529
|
-
return { text: `${note}${suffix}`
|
|
16750
|
+
return { text: `${note}${suffix}${delivery ? `
|
|
16751
|
+
|
|
16752
|
+
${delivery}` : ""}` };
|
|
16530
16753
|
}
|
|
16531
16754
|
if (name === "check_delegation" || name === "wait_delegation") {
|
|
16532
16755
|
const taskId = String(args.task_id ?? "").trim();
|
|
@@ -16680,7 +16903,8 @@ ${lines.join("\n")}` };
|
|
|
16680
16903
|
name: botName,
|
|
16681
16904
|
role,
|
|
16682
16905
|
instructions,
|
|
16683
|
-
...args.modelSelection !== void 0 ? { modelSelection: args.modelSelection } : {}
|
|
16906
|
+
...args.modelSelection !== void 0 ? { modelSelection: args.modelSelection } : {},
|
|
16907
|
+
...typeof args.cwd === "string" ? { cwd: args.cwd.trim() } : {}
|
|
16684
16908
|
})
|
|
16685
16909
|
});
|
|
16686
16910
|
turn.createdThisTurn += 1;
|
|
@@ -16846,14 +17070,19 @@ ${JSON.stringify(routines, null, 2)}`
|
|
|
16846
17070
|
return confirmationResult(r, `${action.replace("_", " ")} on routine ${routineId}`);
|
|
16847
17071
|
}
|
|
16848
17072
|
if (name === "propose_profile") {
|
|
17073
|
+
if (args.notifications !== void 0 && typeof args.notifications !== "boolean" || args.speakReplies !== void 0 && typeof args.speakReplies !== "boolean") {
|
|
17074
|
+
return { text: "propose_profile notifications and speakReplies must be true or false.", isError: true };
|
|
17075
|
+
}
|
|
16849
17076
|
const changes = {};
|
|
16850
17077
|
if (typeof args.name === "string") changes.name = args.name.trim();
|
|
16851
17078
|
if (typeof args.title === "string") changes.title = args.title.trim();
|
|
16852
17079
|
if (typeof args.description === "string") changes.description = args.description.trim();
|
|
16853
17080
|
if (typeof args.soul === "string") changes.soul = args.soul;
|
|
16854
17081
|
if (typeof args.cwd === "string") changes.cwd = args.cwd.trim();
|
|
17082
|
+
if (typeof args.notifications === "boolean") changes.notifications = args.notifications;
|
|
17083
|
+
if (typeof args.speakReplies === "boolean") changes.speakReplies = args.speakReplies;
|
|
16855
17084
|
if (!Object.keys(changes).length) {
|
|
16856
|
-
return { text: "propose_profile needs at least one of name, title, description, soul, or
|
|
17085
|
+
return { text: "propose_profile needs at least one of name, title, description, soul, cwd, notifications, or speakReplies.", isError: true };
|
|
16857
17086
|
}
|
|
16858
17087
|
const forBotId = String(args.for_bot_id ?? "").trim();
|
|
16859
17088
|
const r = await api("/api/internal/profile-requests", {
|
|
@@ -16869,6 +17098,32 @@ ${JSON.stringify(routines, null, 2)}`
|
|
|
16869
17098
|
});
|
|
16870
17099
|
return confirmationResult(r, "the profile change", "profile");
|
|
16871
17100
|
}
|
|
17101
|
+
if (name === "propose_model") {
|
|
17102
|
+
const raw = args.model_selection;
|
|
17103
|
+
const fields = typeof raw === "object" && raw !== null && !Array.isArray(raw) ? raw : null;
|
|
17104
|
+
if (!fields || typeof fields.instanceId !== "string" || !fields.instanceId.trim() || typeof fields.model !== "string" || !fields.model.trim()) {
|
|
17105
|
+
return { text: "propose_model needs model_selection with instanceId and model.", isError: true };
|
|
17106
|
+
}
|
|
17107
|
+
if (fields.effort !== void 0 && (typeof fields.effort !== "string" || !fields.effort.trim()) || fields.variant !== void 0 && (typeof fields.variant !== "string" || !fields.variant.trim())) {
|
|
17108
|
+
return { text: "propose_model effort and variant must be non-empty strings when supplied.", isError: true };
|
|
17109
|
+
}
|
|
17110
|
+
const selection = { instanceId: fields.instanceId.trim(), model: fields.model.trim() };
|
|
17111
|
+
if (typeof fields.effort === "string" && fields.effort.trim()) selection.effort = fields.effort.trim();
|
|
17112
|
+
if (typeof fields.variant === "string" && fields.variant.trim()) selection.variant = fields.variant.trim();
|
|
17113
|
+
const forBotId = String(args.for_bot_id ?? "").trim();
|
|
17114
|
+
const r = await api("/api/internal/model-requests", {
|
|
17115
|
+
method: "POST",
|
|
17116
|
+
body: JSON.stringify({
|
|
17117
|
+
fromBotId: BOT_ID,
|
|
17118
|
+
fromThreadId: THREAD_ID,
|
|
17119
|
+
modelSelection: selection,
|
|
17120
|
+
reason: args.reason,
|
|
17121
|
+
// JSON.stringify drops the key entirely when no target was named
|
|
17122
|
+
forBotId: forBotId || void 0
|
|
17123
|
+
})
|
|
17124
|
+
});
|
|
17125
|
+
return confirmationResult(r, "the default model change", "model");
|
|
17126
|
+
}
|
|
16872
17127
|
if (name === "memory_update") {
|
|
16873
17128
|
if (!["append", "replace", "remove", "supersede"].includes(String(args.action)) || args.action !== "remove" && (typeof args.text !== "string" || !args.text.trim()) || args.action !== "append" && (typeof args.old_text !== "string" || !args.old_text.trim())) {
|
|
16874
17129
|
return { text: "Use memory_update action=append with text, replace or supersede with text and old_text, or remove with old_text.", isError: true };
|