openmausbot 0.1.91 → 0.1.93
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/DesktopViewer-CKNR3SEW.js +5 -0
- package/dist/assets/{abnfDiagram-O67JEVCF-yP-w8pRq.js → abnfDiagram-O67JEVCF-Ckrm1I1X.js} +1 -1
- package/dist/assets/{arc-DsivfZEh.js → arc-BBdBuCgB.js} +1 -1
- package/dist/assets/{architectureDiagram-NJMV4G6O-CILw7lzT.js → architectureDiagram-NJMV4G6O-CDdA3Hjs.js} +1 -1
- package/dist/assets/{blockDiagram-BEXU5L5S-DEQUV3HF.js → blockDiagram-BEXU5L5S-AUrsx1YR.js} +1 -1
- package/dist/assets/{c4Diagram-YGBWAQC7-lSXCZoKA.js → c4Diagram-YGBWAQC7-BEqQ0Unh.js} +1 -1
- package/dist/assets/channel-BU94VpxE.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-QCD5bgWP.js → chunk-2Q5K7J3B-CEEuvd4C.js} +1 -1
- package/dist/assets/{chunk-3FUC2YCW-C5-iZJuL.js → chunk-3FUC2YCW-DyANCiHl.js} +2 -2
- package/dist/assets/{chunk-5VM5RSS4-cxsawMpY.js → chunk-5VM5RSS4-Dx_Slpw9.js} +1 -1
- package/dist/assets/{chunk-GTNCS2PH-DV8tV8H7.js → chunk-GTNCS2PH-Dl7h7iiD.js} +1 -1
- package/dist/assets/{chunk-GWA4HPMP-CJFZyfbW.js → chunk-GWA4HPMP-BLx07SPb.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-BigbMXco.js → chunk-JWPE2WC7-BMxDj3n7.js} +1 -1
- package/dist/assets/{chunk-NETBCI7D-oVxTfpDy.js → chunk-NETBCI7D-CN66PT4H.js} +1 -1
- package/dist/assets/{chunk-WEXAMYUT-CH4BiroW.js → chunk-WEXAMYUT-6HwhsDKw.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-KEDa6gax.js → chunk-XXDRQBXY-gWnLt7SN.js} +1 -1
- package/dist/assets/{classDiagram-v2-NBCMYWYE-BiPjfqVv.js → classDiagram-v2-NBCMYWYE-CMS5l2ea.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-Caxew3OY.js → cose-bilkent-JH36ORCC-CV7sQwIG.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-B_Pui369.js → cynefin-OW5HDTMX-CSyl-7vl.js} +1 -1
- package/dist/assets/{cynefinDiagram-VND7K2PF-X64ydIhP.js → cynefinDiagram-VND7K2PF-BCLKL6az.js} +1 -1
- package/dist/assets/{dagre-6A5THRUB-TqYCI1E1.js → dagre-6A5THRUB-DiaZs6S1.js} +1 -1
- package/dist/assets/{diagram-22UHCM2B-TeOt3rAQ.js → diagram-22UHCM2B-BeTtmt3I.js} +1 -1
- package/dist/assets/{diagram-3UASUU5V-D70BLhDA.js → diagram-3UASUU5V-CsdBG-QQ.js} +1 -1
- package/dist/assets/{diagram-ATOU4E4O-BbQDLwUC.js → diagram-ATOU4E4O-BczvdbR1.js} +1 -1
- package/dist/assets/{diagram-CDSNMT55-ChNJZ1u-.js → diagram-CDSNMT55-DHTTTMhi.js} +1 -1
- package/dist/assets/{diagram-MLGK6HIB-DMBl2APa.js → diagram-MLGK6HIB-RTjHyd8z.js} +1 -1
- package/dist/assets/{diagram-MPIPVDR6-CEqDchOp.js → diagram-MPIPVDR6-BDenHEH_.js} +1 -1
- package/dist/assets/{ebnfDiagram-ZINNZB2B-BVDKRp_-.js → ebnfDiagram-ZINNZB2B-BSiRSbtL.js} +1 -1
- package/dist/assets/{elk-276RUBZZ-CRkofO9B.js → elk-276RUBZZ-BCAElss-.js} +1 -1
- package/dist/assets/{erDiagram-OPXOYQCR-DruOMh5e.js → erDiagram-OPXOYQCR-C4_1ZPJe.js} +1 -1
- package/dist/assets/{flowDiagram-KWPJA3E3-8GMQeB7t.js → flowDiagram-KWPJA3E3-Bcb4Z75S.js} +1 -1
- package/dist/assets/{ganttDiagram-FUAMR5RP-ORE9jcsM.js → ganttDiagram-FUAMR5RP-BiPOzxzb.js} +1 -1
- package/dist/assets/{gitGraphDiagram-X574FWY7-BmsedsWh.js → gitGraphDiagram-X574FWY7-B1wtF3ZS.js} +1 -1
- package/dist/assets/index-Biji-bfL.css +1 -0
- package/dist/assets/{index-DKNEM8Q6.js → index-BkYwilkG.js} +1 -1
- package/dist/assets/index-DZlhoES0.js +597 -0
- package/dist/assets/{infoDiagram-VRGFBTTK-E_p7AooJ.js → infoDiagram-VRGFBTTK-A19No71U.js} +1 -1
- package/dist/assets/{ishikawaDiagram-OU5B5YK6-Y-B2mKda.js → ishikawaDiagram-OU5B5YK6-BQsqJ_cV.js} +1 -1
- package/dist/assets/{journeyDiagram-ZHPQQLJL-eA8RELcK.js → journeyDiagram-ZHPQQLJL-DAO0pVan.js} +1 -1
- package/dist/assets/{kanban-definition-PNTS6WVX-DqIL2e8e.js → kanban-definition-PNTS6WVX-NepmKEe2.js} +1 -1
- package/dist/assets/{linear-yC_29R6e.js → linear-bq1PTDTW.js} +1 -1
- package/dist/assets/{mermaid.core-VhEMkSND.js → mermaid.core-s4LTbQle.js} +5 -5
- package/dist/assets/{mindmap-definition-NLK3R4M7-oJ7kyQZy.js → mindmap-definition-NLK3R4M7-LtdbgHFH.js} +1 -1
- package/dist/assets/{pegDiagram-GJSIUBJH-BmfYcY0O.js → pegDiagram-GJSIUBJH-tdbaCxiK.js} +1 -1
- package/dist/assets/{pieDiagram-5QR66LMP-DKvgP7w9.js → pieDiagram-5QR66LMP-DvkbpW8l.js} +1 -1
- package/dist/assets/{quadrantDiagram-O4NWA36T-BEKL3W0L.js → quadrantDiagram-O4NWA36T-Do4KaH-E.js} +1 -1
- package/dist/assets/{railroadDiagram-XR7U4H2S-BEsiqR5s.js → railroadDiagram-XR7U4H2S-BQWULOAs.js} +1 -1
- package/dist/assets/{requirementDiagram-PLB6GJNP-DWBcWvAP.js → requirementDiagram-PLB6GJNP-w9kei1FU.js} +1 -1
- package/dist/assets/{sankeyDiagram-IPEJSGJF-rpZ2_O4s.js → sankeyDiagram-IPEJSGJF-D2gRy0e8.js} +1 -1
- package/dist/assets/{sequenceDiagram-PO4LG4MO-B99HQdJR.js → sequenceDiagram-PO4LG4MO-a2sO5_Eo.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-BjN0qT5T.js → sizeCapture-INFHLROL-CiPJmFEB.js} +1 -1
- package/dist/assets/{stateDiagram-v2-GCMORJYK-BbsVgGsC.js → stateDiagram-v2-GCMORJYK-DAkUUlL7.js} +1 -1
- package/dist/assets/{swimlanes-2SLR337P-DG3gKkeR.js → swimlanes-2SLR337P-DANf2R8Y.js} +1 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-CdHxG8aM.js +8 -0
- package/dist/assets/{timeline-definition-EJHVYXUP-BTHOdtF_.js → timeline-definition-EJHVYXUP-BKpQmzrT.js} +1 -1
- package/dist/assets/{usecaseDiagram-POWQR4AR-acLSLFwc.js → usecaseDiagram-POWQR4AR-BtI7qLN-.js} +1 -1
- package/dist/assets/{vennDiagram-UO4OBE2U-C5JzNX9G.js → vennDiagram-UO4OBE2U-gXJXrAG_.js} +1 -1
- package/dist/assets/{wardleyDiagram-VNRHLVJA-DL1-PrR_.js → wardleyDiagram-VNRHLVJA-GU8Po5-n.js} +1 -1
- package/dist/assets/{xychartDiagram-PMCCYNJV-Bvr1477p.js → xychartDiagram-PMCCYNJV-BF4J30g6.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/novnc-NOTICE.txt +118 -0
- package/dist-server/cloud-home-start.js +112 -14
- package/dist-server/companion/src/routes.js +24 -1
- package/dist-server/container-mcp.js +201 -16
- package/dist-server/drivers/agents-proxy.js +7 -4
- package/dist-server/enterprise/server/index.js +5 -1
- package/dist-server/index.js +10698 -4737
- package/dist-server/local-computer-proxy.js +133 -8
- package/dist-server/mcp-gate.js +16 -6
- package/dist-server/model-catalog/models-dev.snapshot.json +7299 -0
- package/dist-server/openmausbot.js +4656 -1258
- package/dist-server/pair-cli.js +4656 -1258
- package/dist-server/server/boat.js +5 -5
- package/dist-server/server/browser-engine.js +10 -1
- package/dist-server/server/browser-live.js +46 -2
- package/dist-server/server/browser-runtime.js +74 -8
- package/dist-server/server/browser-tool-shape.js +6 -4
- package/dist-server/server/chief-of-staff.js +1 -1
- package/dist-server/server/cloud-home-start.js +118 -26
- package/dist-server/server/cloud-home.js +39 -3
- package/dist-server/server/cloud-lending.js +74 -10
- package/dist-server/server/cloud-owner.js +196 -0
- package/dist-server/server/cloud-secrets-boot.js +6 -0
- package/dist-server/server/cloud-secrets.js +65 -0
- package/dist-server/server/computer-control.js +6 -0
- package/dist-server/server/config.js +187 -14
- package/dist-server/server/container-computer.js +46 -34
- package/dist-server/server/desktop-viewer-targets.js +26 -0
- package/dist-server/server/digest.js +12 -2
- package/dist-server/server/drivers/acp/core.js +339 -33
- package/dist-server/server/drivers/acp/cursor.js +13 -1
- package/dist-server/server/drivers/acp/opencode-go.js +614 -85
- package/dist-server/server/drivers/acp/quiet-status.js +257 -0
- package/dist-server/server/drivers/acp/qwen.js +18 -0
- package/dist-server/server/drivers/agents-catalog.js +6 -6
- package/dist-server/server/drivers/antigravity-acp.js +69 -11
- package/dist-server/server/drivers/antigravity-temp.js +360 -0
- package/dist-server/server/drivers/antigravity.js +21 -0
- package/dist-server/server/drivers/builtIn.js +2 -0
- package/dist-server/server/drivers/cerebras.js +108 -0
- package/dist-server/server/drivers/chat-mcp-tools.js +20 -3
- package/dist-server/server/drivers/chatgpt-plan-auth.js +481 -0
- package/dist-server/server/drivers/claude.js +329 -37
- package/dist-server/server/drivers/codex.js +228 -18
- package/dist-server/server/drivers/grok.js +2 -2
- package/dist-server/server/drivers/mistral.js +4 -3
- package/dist-server/server/drivers/openai-chat-protocol.js +4 -3
- package/dist-server/server/drivers/openai-chat.js +66 -4
- package/dist-server/server/drivers/openai-compat.js +73 -23
- package/dist-server/server/drivers/prompt-split.js +2 -0
- package/dist-server/server/engine-install.js +46 -12
- package/dist-server/server/env-path.js +21 -5
- package/dist-server/server/harness/registry.js +2 -2
- package/dist-server/server/index.js +1545 -238
- package/dist-server/server/lending-memory.js +479 -0
- package/dist-server/server/local-vm-idle.js +24 -6
- package/dist-server/server/local-vm-stop-reason.js +26 -0
- package/dist-server/server/managed-desktop.js +3 -0
- package/dist-server/server/mcp-bridge.js +5 -3
- package/dist-server/server/mcp-http.js +6 -3
- package/dist-server/server/mcp-oauth-discovery.js +133 -0
- package/dist-server/server/mcp-oauth-store.js +70 -0
- package/dist-server/server/mcp-oauth.js +550 -0
- package/dist-server/server/mcp-probe.js +14 -1
- package/dist-server/server/mcp-registry.js +43 -0
- package/dist-server/server/memory-upkeep.js +94 -84
- package/dist-server/server/model-catalog/catalog.js +374 -0
- package/dist-server/server/model-catalog/presets.js +176 -0
- package/dist-server/server/model-catalog/trim.js +219 -0
- package/dist-server/server/provider-key-check.js +5 -2
- package/dist-server/server/recent-work.js +1 -1
- package/dist-server/server/request-auth.js +23 -0
- package/dist-server/server/routes/antigravity-leftovers.js +45 -0
- package/dist-server/server/routes/bot-memory.js +31 -6
- package/dist-server/server/routes/desktop-viewer.js +238 -0
- package/dist-server/server/routine-requests.js +1 -1
- package/dist-server/server/routines.js +6 -3
- package/dist-server/server/sessions.js +56 -9
- package/dist-server/server/skills.js +25 -10
- package/dist-server/server/store.js +116 -122
- package/dist-server/server/thread-events.js +2 -0
- package/dist-server/server/thread-starters.js +33 -0
- package/dist-server/server/thread-title.js +46 -0
- package/dist-server/server/tts/fish.js +4 -5
- package/dist-server/server/tts/index.js +5 -3
- package/dist-server/server/vps-computer.js +80 -13
- package/dist-server/server/webhooks.js +18 -1
- package/dist-server/server/workspace-backup-policy.js +3 -0
- package/dist-server/server/workspace-backup.js +25 -0
- package/dist-server/server/workspace.js +66 -16
- package/dist-server/shared/approval-mode.js +1 -1
- package/dist-server/shared/redact.js +1 -0
- package/dist-server/shared/tool-name.js +22 -0
- package/dist-server/shared/workspace-backup-client.js +1 -0
- package/dist-server/src/lib/citations.js +177 -0
- package/dist-server/src/lib/composer-attachments.js +7 -1
- package/dist-server/vps-container-mcp.js +202 -16
- package/dist-server/workspace-backup.worker.js +87 -9
- package/enterprise/server/index.js +5 -1
- package/package.json +1 -1
- package/dist/assets/channel-DrfGMu7X.js +0 -1
- package/dist/assets/index-BlnCEcU6.js +0 -588
- package/dist/assets/index-DVxjOvID.css +0 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-BCZhxl7e.js +0 -8
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// Selection matching is adapted from T3 Code's assistantTextSelection.ts
|
|
2
|
+
// (Copyright 2026 T3 Tools Inc., MIT License; see third_party/t3-code/LICENSE).
|
|
3
|
+
export const CITATION_MAX_QUOTE_LENGTH = 12_000;
|
|
4
|
+
export const CITATION_MAX_COMMENT_LENGTH = 4_000;
|
|
5
|
+
const CITATION_CONTEXT_LENGTH = 64;
|
|
6
|
+
const CITATION_MARKER = "<!--omb-citation-v1:";
|
|
7
|
+
const CITATION_MARKER_RE = /<!--omb-citation-v1:([A-Za-z0-9_-]{1,100000})-->/g;
|
|
8
|
+
function boundedString(value, max, allowEmpty = false) {
|
|
9
|
+
return typeof value === "string" && value.length <= max && (allowEmpty || value.length > 0);
|
|
10
|
+
}
|
|
11
|
+
export function isCitationAttachment(value) {
|
|
12
|
+
if (!value || typeof value !== "object")
|
|
13
|
+
return false;
|
|
14
|
+
const citation = value;
|
|
15
|
+
const source = citation.source;
|
|
16
|
+
return citation.kind === "citation" &&
|
|
17
|
+
citation.version === 1 &&
|
|
18
|
+
boundedString(citation.id, 200) &&
|
|
19
|
+
boundedString(citation.quote, CITATION_MAX_QUOTE_LENGTH) &&
|
|
20
|
+
(citation.comment === undefined || boundedString(citation.comment, CITATION_MAX_COMMENT_LENGTH, true)) &&
|
|
21
|
+
typeof citation.size === "number" && Number.isFinite(citation.size) && citation.size >= 0 &&
|
|
22
|
+
Boolean(source) &&
|
|
23
|
+
(source.ownerType === "bot" || source.ownerType === "group") &&
|
|
24
|
+
boundedString(source.ownerId, 200) &&
|
|
25
|
+
boundedString(source.threadId, 200) &&
|
|
26
|
+
boundedString(source.messageId, 200) &&
|
|
27
|
+
Number.isSafeInteger(source.start) && Number(source.start) >= 0 &&
|
|
28
|
+
Number.isSafeInteger(source.end) && Number(source.end) >= Number(source.start) &&
|
|
29
|
+
boundedString(source.prefix, CITATION_CONTEXT_LENGTH, true) &&
|
|
30
|
+
boundedString(source.suffix, CITATION_CONTEXT_LENGTH, true);
|
|
31
|
+
}
|
|
32
|
+
function newId() {
|
|
33
|
+
return globalThis.crypto?.randomUUID?.() ?? `c${Math.random().toString(36).slice(2)}`;
|
|
34
|
+
}
|
|
35
|
+
function byteLength(text) {
|
|
36
|
+
return new TextEncoder().encode(text).length;
|
|
37
|
+
}
|
|
38
|
+
export function citationAttachment(source, selector, comment = "") {
|
|
39
|
+
const trimmedComment = comment.trim();
|
|
40
|
+
if (!selector.text.trim() || selector.text.length > CITATION_MAX_QUOTE_LENGTH) {
|
|
41
|
+
throw new Error("Citation quote is empty or too long");
|
|
42
|
+
}
|
|
43
|
+
if (trimmedComment.length > CITATION_MAX_COMMENT_LENGTH)
|
|
44
|
+
throw new Error("Citation comment is too long");
|
|
45
|
+
return {
|
|
46
|
+
kind: "citation",
|
|
47
|
+
version: 1,
|
|
48
|
+
id: newId(),
|
|
49
|
+
quote: selector.text,
|
|
50
|
+
...(trimmedComment ? { comment: trimmedComment } : {}),
|
|
51
|
+
source: { ...source, start: selector.start, end: selector.end, prefix: selector.prefix, suffix: selector.suffix },
|
|
52
|
+
size: byteLength(selector.text) + byteLength(trimmedComment),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function withCitationComment(citation, comment) {
|
|
56
|
+
const trimmed = comment.trim();
|
|
57
|
+
if (trimmed.length > CITATION_MAX_COMMENT_LENGTH)
|
|
58
|
+
throw new Error("Citation comment is too long");
|
|
59
|
+
const { comment: _old, ...rest } = citation;
|
|
60
|
+
return { ...rest, ...(trimmed ? { comment: trimmed } : {}), size: byteLength(citation.quote) + byteLength(trimmed) };
|
|
61
|
+
}
|
|
62
|
+
function base64UrlEncode(value) {
|
|
63
|
+
const bytes = new TextEncoder().encode(JSON.stringify(value));
|
|
64
|
+
let binary = "";
|
|
65
|
+
for (const byte of bytes)
|
|
66
|
+
binary += String.fromCharCode(byte);
|
|
67
|
+
return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
|
|
68
|
+
}
|
|
69
|
+
function base64UrlDecode(value) {
|
|
70
|
+
const padded = value.replaceAll("-", "+").replaceAll("_", "/").padEnd(Math.ceil(value.length / 4) * 4, "=");
|
|
71
|
+
const binary = atob(padded);
|
|
72
|
+
return JSON.parse(new TextDecoder().decode(Uint8Array.from(binary, (character) => character.charCodeAt(0))));
|
|
73
|
+
}
|
|
74
|
+
/** Readable in clients without citation UI and unambiguous to model providers. */
|
|
75
|
+
export function citationFallback(citation) {
|
|
76
|
+
const quote = citation.quote.split("\n").map((line) => `> ${line}`).join("\n");
|
|
77
|
+
return `> Quoted message:\n${quote}${citation.comment ? `\n\nComment:\n${citation.comment}` : ""}`;
|
|
78
|
+
}
|
|
79
|
+
export function serializeCitation(citation) {
|
|
80
|
+
return `${CITATION_MARKER}${base64UrlEncode(citation)}-->\n${citationFallback(citation)}`;
|
|
81
|
+
}
|
|
82
|
+
export function splitTranscriptCitations(text) {
|
|
83
|
+
const citations = [];
|
|
84
|
+
let display = "";
|
|
85
|
+
let cursor = 0;
|
|
86
|
+
for (const match of text.matchAll(CITATION_MARKER_RE)) {
|
|
87
|
+
if (match.index < cursor)
|
|
88
|
+
continue;
|
|
89
|
+
let citation;
|
|
90
|
+
try {
|
|
91
|
+
const decoded = base64UrlDecode(match[1]);
|
|
92
|
+
if (!isCitationAttachment(decoded))
|
|
93
|
+
continue;
|
|
94
|
+
citation = decoded;
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const block = `${match[0]}\n${citationFallback(citation)}`;
|
|
100
|
+
if (!text.startsWith(block, match.index))
|
|
101
|
+
continue;
|
|
102
|
+
display += text.slice(cursor, match.index);
|
|
103
|
+
cursor = match.index + block.length;
|
|
104
|
+
citations.push(citation);
|
|
105
|
+
}
|
|
106
|
+
return { display: `${display}${text.slice(cursor)}`.trim(), citations };
|
|
107
|
+
}
|
|
108
|
+
export function citationPreviewText(text) {
|
|
109
|
+
const cited = splitTranscriptCitations(text);
|
|
110
|
+
if (!cited.citations.length)
|
|
111
|
+
return text;
|
|
112
|
+
return [
|
|
113
|
+
cited.display,
|
|
114
|
+
...cited.citations.map((citation) => citation.comment
|
|
115
|
+
? `${citation.quote} — ${citation.comment}`
|
|
116
|
+
: citation.quote),
|
|
117
|
+
].filter(Boolean).join(" ");
|
|
118
|
+
}
|
|
119
|
+
function normalizeWhitespace(text) {
|
|
120
|
+
return text.replace(/\s+/g, " ");
|
|
121
|
+
}
|
|
122
|
+
function splitsSurrogatePair(text, offset) {
|
|
123
|
+
const before = text.charCodeAt(offset - 1);
|
|
124
|
+
const after = text.charCodeAt(offset);
|
|
125
|
+
return before >= 0xd800 && before <= 0xdbff && after >= 0xdc00 && after <= 0xdfff;
|
|
126
|
+
}
|
|
127
|
+
export function createCitationTextSelector(text, rawStart, rawEnd) {
|
|
128
|
+
const quote = text.slice(rawStart, rawEnd);
|
|
129
|
+
if (!quote.trim())
|
|
130
|
+
return null;
|
|
131
|
+
const normalized = normalizeWhitespace(text);
|
|
132
|
+
let start = normalizeWhitespace(text.slice(0, rawStart)).length;
|
|
133
|
+
if (rawStart > 0 && /\s/.test(text[rawStart - 1]) && /\s/.test(text[rawStart]))
|
|
134
|
+
start -= 1;
|
|
135
|
+
const end = normalizeWhitespace(text.slice(0, rawEnd)).length;
|
|
136
|
+
let prefixStart = Math.max(0, start - CITATION_CONTEXT_LENGTH);
|
|
137
|
+
let suffixEnd = Math.min(normalized.length, end + CITATION_CONTEXT_LENGTH);
|
|
138
|
+
if (splitsSurrogatePair(normalized, prefixStart))
|
|
139
|
+
prefixStart += 1;
|
|
140
|
+
if (splitsSurrogatePair(normalized, suffixEnd))
|
|
141
|
+
suffixEnd -= 1;
|
|
142
|
+
return {
|
|
143
|
+
text: quote,
|
|
144
|
+
start,
|
|
145
|
+
end,
|
|
146
|
+
prefix: normalized.slice(prefixStart, start),
|
|
147
|
+
suffix: normalized.slice(end, suffixEnd),
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
export function findCitationText(text, selector) {
|
|
151
|
+
const normalized = normalizeWhitespace(text);
|
|
152
|
+
const quote = normalizeWhitespace(selector.text);
|
|
153
|
+
if (!quote.trim())
|
|
154
|
+
return null;
|
|
155
|
+
const prefix = normalizeWhitespace(selector.prefix);
|
|
156
|
+
const suffix = normalizeWhitespace(selector.suffix);
|
|
157
|
+
const matchesContext = (start, end) => normalized.slice(Math.max(0, start - prefix.length), start) === prefix &&
|
|
158
|
+
normalized.slice(end, end + suffix.length) === suffix;
|
|
159
|
+
let match = Number.isSafeInteger(selector.start) && Number.isSafeInteger(selector.end) &&
|
|
160
|
+
selector.start >= 0 && selector.end - selector.start === quote.length &&
|
|
161
|
+
normalized.slice(selector.start, selector.end) === quote && matchesContext(selector.start, selector.end)
|
|
162
|
+
? { start: selector.start, end: selector.end }
|
|
163
|
+
: null;
|
|
164
|
+
let onlyQuote = null;
|
|
165
|
+
let quoteCount = 0;
|
|
166
|
+
for (let start = normalized.indexOf(quote); start !== -1; start = normalized.indexOf(quote, start + 1)) {
|
|
167
|
+
const end = start + quote.length;
|
|
168
|
+
quoteCount += 1;
|
|
169
|
+
onlyQuote = { start, end };
|
|
170
|
+
if (!matchesContext(start, end))
|
|
171
|
+
continue;
|
|
172
|
+
if (match && match.start !== start)
|
|
173
|
+
return null;
|
|
174
|
+
match = { start, end };
|
|
175
|
+
}
|
|
176
|
+
return match ?? (quoteCount === 1 ? onlyQuote : null);
|
|
177
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { isCitationAttachment, serializeCitation } from "./citations.js";
|
|
1
2
|
export function isAttachment(value) {
|
|
2
3
|
if (!value || typeof value !== "object")
|
|
3
4
|
return false;
|
|
4
5
|
const attachment = value;
|
|
6
|
+
if (attachment.kind === "citation")
|
|
7
|
+
return isCitationAttachment(value);
|
|
5
8
|
if (typeof attachment.id !== "string" || !validSize(attachment.size))
|
|
6
9
|
return false;
|
|
7
10
|
if (attachment.kind === "paste") {
|
|
@@ -362,7 +365,10 @@ export function formatSize(bytes) {
|
|
|
362
365
|
export function composeMessage(text, attachments) {
|
|
363
366
|
const parts = [text.trim()];
|
|
364
367
|
attachments.forEach((a, i) => {
|
|
365
|
-
if (a.kind === "
|
|
368
|
+
if (a.kind === "citation") {
|
|
369
|
+
parts.push(serializeCitation(a));
|
|
370
|
+
}
|
|
371
|
+
else if (a.kind === "paste") {
|
|
366
372
|
parts.push(`<pasted-text index="${i + 1}">\n${a.text}\n</pasted-text>`);
|
|
367
373
|
}
|
|
368
374
|
else if (a.kind === "image") {
|
|
@@ -90,6 +90,9 @@ function nvmBinDirs() {
|
|
|
90
90
|
return [];
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
|
+
function sealedFixture() {
|
|
94
|
+
return process.env.OMB_TEST_SEALED_PATH === "1";
|
|
95
|
+
}
|
|
93
96
|
function knownDirs() {
|
|
94
97
|
const home = homedir();
|
|
95
98
|
return [
|
|
@@ -105,10 +108,13 @@ function knownDirs() {
|
|
|
105
108
|
// opencode installer
|
|
106
109
|
join(home, ".claude", "local"),
|
|
107
110
|
// claude "local install"
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
111
|
+
// Machine-wide rather than under the (possibly temporary) home.
|
|
112
|
+
...sealedFixture() ? [] : [
|
|
113
|
+
"/opt/homebrew/bin",
|
|
114
|
+
// brew, Apple silicon
|
|
115
|
+
"/usr/local/bin"
|
|
116
|
+
// brew Intel / classic installs
|
|
117
|
+
],
|
|
112
118
|
join(home, ".volta", "bin"),
|
|
113
119
|
join(home, ".bun", "bin"),
|
|
114
120
|
join(home, ".asdf", "shims"),
|
|
@@ -130,6 +136,8 @@ function windowsKnownDirs() {
|
|
|
130
136
|
// x.ai installer
|
|
131
137
|
join(localAppData, "agy", "bin"),
|
|
132
138
|
// Antigravity installer
|
|
139
|
+
// Cursor installer: cursor-agent.* and its `agent` copies (MOCA-272)
|
|
140
|
+
join(localAppData, "cursor-agent"),
|
|
133
141
|
join(home, ".local", "bin"),
|
|
134
142
|
// claude native installer
|
|
135
143
|
join(home, ".claude", "local"),
|
|
@@ -137,7 +145,9 @@ function windowsKnownDirs() {
|
|
|
137
145
|
// Factory droid installer (%USERPROFILE%\bin)
|
|
138
146
|
join(home, ".bun", "bin"),
|
|
139
147
|
join(home, ".deno", "bin"),
|
|
140
|
-
join(home, "go", "bin")
|
|
148
|
+
join(home, "go", "bin"),
|
|
149
|
+
join(process.env.ProgramFiles ?? "C:\\Program Files", "Docker", "Docker", "resources", "bin")
|
|
150
|
+
// Docker Desktop installer
|
|
141
151
|
];
|
|
142
152
|
}
|
|
143
153
|
var cached = null;
|
|
@@ -160,7 +170,7 @@ function augmentedPath() {
|
|
|
160
170
|
...(process.platform === "win32" ? windowsKnownDirs() : knownDirs()).filter((d) => existsSync(d))
|
|
161
171
|
]);
|
|
162
172
|
}
|
|
163
|
-
if (!probed && !process.env.VITEST && process.platform !== "win32") {
|
|
173
|
+
if (!probed && !process.env.VITEST && !sealedFixture() && process.platform !== "win32") {
|
|
164
174
|
probed = true;
|
|
165
175
|
probeLoginShellPath();
|
|
166
176
|
}
|
|
@@ -184,6 +194,119 @@ function probeLoginShellPath() {
|
|
|
184
194
|
}
|
|
185
195
|
);
|
|
186
196
|
}
|
|
197
|
+
function splitCliString(cli) {
|
|
198
|
+
const out = [];
|
|
199
|
+
let cur = "";
|
|
200
|
+
let quote = null;
|
|
201
|
+
for (const ch of cli.trim()) {
|
|
202
|
+
if (quote) {
|
|
203
|
+
if (ch === quote) quote = null;
|
|
204
|
+
else cur += ch;
|
|
205
|
+
} else if (ch === '"' || ch === "'") {
|
|
206
|
+
quote = ch;
|
|
207
|
+
} else if (/\s/.test(ch)) {
|
|
208
|
+
if (cur) out.push(cur);
|
|
209
|
+
cur = "";
|
|
210
|
+
} else {
|
|
211
|
+
cur += ch;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (cur) out.push(cur);
|
|
215
|
+
return out;
|
|
216
|
+
}
|
|
217
|
+
function isFile(p2) {
|
|
218
|
+
try {
|
|
219
|
+
return statSync(p2, { throwIfNoEntry: false })?.isFile() ?? false;
|
|
220
|
+
} catch {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function whichWin(cli, env) {
|
|
225
|
+
const exts = ((env ?? process.env).PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").filter(Boolean);
|
|
226
|
+
const probe = (base) => {
|
|
227
|
+
const order = extname(base) ? [base, ...exts.map((e) => base + e)] : [...exts.map((e) => base + e), base];
|
|
228
|
+
return order.find(isFile) ?? null;
|
|
229
|
+
};
|
|
230
|
+
if (/[\\/]/.test(cli) || /^[a-zA-Z]:/.test(cli)) return probe(cli);
|
|
231
|
+
const path = env ? env.PATH ?? env.Path ?? "" : augmentedPath();
|
|
232
|
+
for (const dir of path.split(delimiter)) {
|
|
233
|
+
if (!dir) continue;
|
|
234
|
+
const hit = probe(join(dir, cli));
|
|
235
|
+
if (hit) return hit;
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
function nodeExe(near, env) {
|
|
240
|
+
const local = join(near, "node.exe");
|
|
241
|
+
if (isFile(local)) return local;
|
|
242
|
+
const onPath = whichWin("node.exe", env);
|
|
243
|
+
if (onPath && extname(onPath).toLowerCase() === ".exe") return onPath;
|
|
244
|
+
return process.versions.electron ? null : process.execPath;
|
|
245
|
+
}
|
|
246
|
+
function parseCmdShim(shim, env) {
|
|
247
|
+
let text;
|
|
248
|
+
try {
|
|
249
|
+
text = readFileSync(shim, "utf8");
|
|
250
|
+
} catch {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
const dir = dirname(shim);
|
|
254
|
+
const npmEntry = /^SET "NP[MX]_CLI_JS=%~dp0\\([^"]+)"/im.exec(text);
|
|
255
|
+
const targets = [...npmEntry ? [npmEntry] : [], ...text.matchAll(/"%~?dp0%?\\?([^"]+)"/g)].map((m2) => join(dir, m2[1])).filter((p2) => isFile(p2) && basename(p2).toLowerCase() !== "node.exe");
|
|
256
|
+
const script = targets.find((p2) => /\.[cm]?js$/i.test(p2));
|
|
257
|
+
if (script) {
|
|
258
|
+
const node = nodeExe(dir, env);
|
|
259
|
+
if (node) return { command: node, args: [script] };
|
|
260
|
+
}
|
|
261
|
+
const exe = targets.find((p2) => extname(p2).toLowerCase() === ".exe");
|
|
262
|
+
return exe ? { command: exe, args: [] } : null;
|
|
263
|
+
}
|
|
264
|
+
function parseNodeShebang(file2, env) {
|
|
265
|
+
let head = "";
|
|
266
|
+
let fd = null;
|
|
267
|
+
try {
|
|
268
|
+
fd = openSync(file2, "r");
|
|
269
|
+
const buf = Buffer.alloc(128);
|
|
270
|
+
const n = readSync(fd, buf, 0, buf.length, 0);
|
|
271
|
+
head = buf.subarray(0, n).toString("utf8").split("\n", 1)[0];
|
|
272
|
+
} catch {
|
|
273
|
+
return null;
|
|
274
|
+
} finally {
|
|
275
|
+
if (fd !== null) {
|
|
276
|
+
try {
|
|
277
|
+
closeSync(fd);
|
|
278
|
+
} catch {
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (!/^#!.*\bnode(\.exe)?\b/.test(head)) return null;
|
|
283
|
+
const node = nodeExe(dirname(file2), env);
|
|
284
|
+
return node ? { command: node, args: [file2] } : null;
|
|
285
|
+
}
|
|
286
|
+
function resolveWord(cli, args2, env) {
|
|
287
|
+
if (process.platform !== "win32") return { command: cli, args: args2 };
|
|
288
|
+
const file2 = whichWin(cli, env);
|
|
289
|
+
if (!file2) return { command: cli, args: args2 };
|
|
290
|
+
const ext = extname(file2).toLowerCase();
|
|
291
|
+
if (ext === ".cmd" || ext === ".bat") {
|
|
292
|
+
const direct = parseCmdShim(file2, env);
|
|
293
|
+
return direct ? { command: direct.command, args: [...direct.args, ...args2] } : { command: file2, args: args2 };
|
|
294
|
+
}
|
|
295
|
+
if (ext === ".exe" || ext === ".com") return { command: file2, args: args2 };
|
|
296
|
+
const viaNode = parseNodeShebang(file2, env);
|
|
297
|
+
return viaNode ? { command: viaNode.command, args: [...viaNode.args, ...args2] } : { command: file2, args: args2 };
|
|
298
|
+
}
|
|
299
|
+
function resolveCliSpawn(cli, args2, env) {
|
|
300
|
+
const trimmed = cli.trim();
|
|
301
|
+
if (trimmed.includes(" ") && existsSync(trimmed)) return resolveWord(trimmed, args2, env);
|
|
302
|
+
const split = splitCliString(cli);
|
|
303
|
+
if (split.length > 1 || split[0] !== trimmed) {
|
|
304
|
+
const [head, ...fixed] = split;
|
|
305
|
+
if (!head) return { command: cli, args: args2 };
|
|
306
|
+
return resolveWord(head, [...fixed, ...args2], env);
|
|
307
|
+
}
|
|
308
|
+
return resolveWord(cli, args2, env);
|
|
309
|
+
}
|
|
187
310
|
|
|
188
311
|
// server/mcp-tool-schema.ts
|
|
189
312
|
var ROOT_COMBINATORS = ["anyOf", "oneOf", "allOf", "not"];
|
|
@@ -407,9 +530,11 @@ function createMcpBridgeInterceptor(options) {
|
|
|
407
530
|
};
|
|
408
531
|
}
|
|
409
532
|
function runMcpBridge(options) {
|
|
410
|
-
const
|
|
533
|
+
const env = options.env ?? { ...process.env, PATH: augmentedPath() };
|
|
534
|
+
const { command, args: args2 } = resolveCliSpawn(options.command, options.args, env);
|
|
535
|
+
const child = spawn(command, args2, {
|
|
411
536
|
shell: false,
|
|
412
|
-
env
|
|
537
|
+
env,
|
|
413
538
|
stdio: ["pipe", "pipe", "pipe"]
|
|
414
539
|
});
|
|
415
540
|
child.stdin.on("error", () => {
|
|
@@ -16008,15 +16133,27 @@ var stdioEntrySchema = external_exports.object({
|
|
|
16008
16133
|
var stdioMutationSchema = stdioEntrySchema.extend({
|
|
16009
16134
|
env: external_exports.record(external_exports.string(), external_exports.union([external_exports.string().max(16384), external_exports.literal(true)])).optional()
|
|
16010
16135
|
});
|
|
16136
|
+
var CLIENT_ID = /^[\x20-\x7e]+$/;
|
|
16137
|
+
var SCOPE = /^[\x21\x23-\x5b\x5d-\x7e]+$/;
|
|
16138
|
+
var CLIENT_SECRET_MAX = 4096;
|
|
16139
|
+
var oauthClientSchema = external_exports.object({
|
|
16140
|
+
clientId: external_exports.string().trim().min(1, "Enter the client ID of the app registered with this server's sign-in provider.").max(512).regex(CLIENT_ID, "A client ID is printable text on one line."),
|
|
16141
|
+
clientSecret: external_exports.string().min(1).max(CLIENT_SECRET_MAX).regex(CLIENT_ID, "A client secret is printable text on one line.").optional(),
|
|
16142
|
+
scopes: external_exports.array(external_exports.string().max(256).regex(SCOPE, "Scopes are single words, like offline_access or api://my-app/mcp.read.")).max(32).optional()
|
|
16143
|
+
}).strict();
|
|
16011
16144
|
var remoteEntrySchema = external_exports.object({
|
|
16012
16145
|
/** Streamable HTTP unless the entry says the older SSE transport. */
|
|
16013
16146
|
type: external_exports.enum(["http", "sse"]).optional(),
|
|
16014
16147
|
url: external_exports.string().trim().min(1).max(2048),
|
|
16015
16148
|
headers: external_exports.record(external_exports.string(), external_exports.string().max(16384)).optional(),
|
|
16149
|
+
oauth: oauthClientSchema.optional(),
|
|
16016
16150
|
enabled: external_exports.boolean().optional()
|
|
16017
16151
|
}).strict();
|
|
16018
16152
|
var remoteMutationSchema = remoteEntrySchema.extend({
|
|
16019
|
-
headers: external_exports.record(external_exports.string(), external_exports.union([external_exports.string().max(16384), external_exports.literal(true)])).optional()
|
|
16153
|
+
headers: external_exports.record(external_exports.string(), external_exports.union([external_exports.string().max(16384), external_exports.literal(true)])).optional(),
|
|
16154
|
+
oauth: oauthClientSchema.extend({
|
|
16155
|
+
clientSecret: external_exports.union([external_exports.string().min(1).max(CLIENT_SECRET_MAX).regex(CLIENT_ID, "A client secret is printable text on one line."), external_exports.literal(true)]).optional()
|
|
16156
|
+
}).optional()
|
|
16020
16157
|
});
|
|
16021
16158
|
|
|
16022
16159
|
// server/cloud-overflow.ts
|
|
@@ -16082,7 +16219,11 @@ var sessionSchema = external_exports.object({
|
|
|
16082
16219
|
userId: external_exports.string().max(256).optional(),
|
|
16083
16220
|
email: external_exports.string().max(320).optional(),
|
|
16084
16221
|
/** Set only by the internal verified-portal issuance path, never by email or pairing input. */
|
|
16085
|
-
membershipAuthority: external_exports.literal("portal").optional()
|
|
16222
|
+
membershipAuthority: external_exports.literal("portal").optional(),
|
|
16223
|
+
/** A browser sign-in (PairingCode `browser`): accepted only as its browser's cookie, never as a bearer token. */
|
|
16224
|
+
cookieOnly: external_exports.literal(true).optional(),
|
|
16225
|
+
/** Whose OMB Cloud a browser sign-in signed in to (its PairingCode `owner`). */
|
|
16226
|
+
owner: external_exports.string().max(254).optional()
|
|
16086
16227
|
});
|
|
16087
16228
|
var fileSchema = external_exports.object({ version: external_exports.literal(1), sessions: external_exports.array(sessionSchema) });
|
|
16088
16229
|
|
|
@@ -16094,6 +16235,7 @@ var optionalText = external_exports.string().optional();
|
|
|
16094
16235
|
var SSH_ALIAS = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/;
|
|
16095
16236
|
var LEGACY_BROWSER_PROFILE_ID = /^[A-Za-z0-9_-]{1,40}$/;
|
|
16096
16237
|
var BROWSER_PROFILE_ID = /^[a-z0-9_-]{1,40}$/;
|
|
16238
|
+
var FISH_TTS_MODELS = ["s2.1-pro", "s2.1-pro-free"];
|
|
16097
16239
|
var MIN_ROOM_TURN_TIMEOUT_MINUTES = 1;
|
|
16098
16240
|
var MAX_ROOM_TURN_TIMEOUT_MINUTES = 1440;
|
|
16099
16241
|
var DEFAULT_ROOM_HANDOFF_LIFETIME_MINUTES = 30;
|
|
@@ -16104,6 +16246,8 @@ var MIN_THREAD_EVENT_LOG_BYTES = 256 * 1024;
|
|
|
16104
16246
|
var MAX_THREAD_EVENT_LOG_BYTES = 4 * 1024 * 1024 * 1024;
|
|
16105
16247
|
var MIN_LOCAL_VM_MAX_INSTANCES = 1;
|
|
16106
16248
|
var MAX_LOCAL_VM_MAX_INSTANCES = 8;
|
|
16249
|
+
var MIN_LOCAL_VM_IDLE_TIMEOUT_MINUTES = 5;
|
|
16250
|
+
var MAX_LOCAL_VM_IDLE_TIMEOUT_MINUTES = 1440;
|
|
16107
16251
|
function isValidSshAlias(value) {
|
|
16108
16252
|
return typeof value === "string" && SSH_ALIAS.test(value);
|
|
16109
16253
|
}
|
|
@@ -16141,7 +16285,8 @@ var roomConfigSchema = external_exports.object({
|
|
|
16141
16285
|
);
|
|
16142
16286
|
var localVmConfigSchema = external_exports.object({
|
|
16143
16287
|
mode: external_exports.enum(["shared", "per-bot", "pool"]).optional(),
|
|
16144
|
-
maxInstances: external_exports.number().int().min(MIN_LOCAL_VM_MAX_INSTANCES).max(MAX_LOCAL_VM_MAX_INSTANCES).optional()
|
|
16288
|
+
maxInstances: external_exports.number().int().min(MIN_LOCAL_VM_MAX_INSTANCES).max(MAX_LOCAL_VM_MAX_INSTANCES).optional(),
|
|
16289
|
+
idleTimeoutMinutes: external_exports.number().int().min(MIN_LOCAL_VM_IDLE_TIMEOUT_MINUTES).max(MAX_LOCAL_VM_IDLE_TIMEOUT_MINUTES).optional()
|
|
16145
16290
|
});
|
|
16146
16291
|
var browserProfileSchema = external_exports.object({
|
|
16147
16292
|
// "guest" is the throwaway session's reserved id, never a saved profile
|
|
@@ -16300,7 +16445,11 @@ var onboardingConfigSchema = external_exports.object({
|
|
|
16300
16445
|
/** Which welcome flow was completed; a newer flow may re-show itself. */
|
|
16301
16446
|
version: external_exports.number().int().min(0).max(1e3).optional(),
|
|
16302
16447
|
reelSeen: external_exports.boolean().optional(),
|
|
16303
|
-
hintsSeen: external_exports.array(external_exports.string().trim().min(1).max(60)).max(100).optional()
|
|
16448
|
+
hintsSeen: external_exports.array(external_exports.string().trim().min(1).max(60)).max(100).optional(),
|
|
16449
|
+
/** OMB Cloud home only: when a bot's turn first finished on this machine
|
|
16450
|
+
* (cloud-home.ts firstCloudTurnPatch). Written by the server, read by the
|
|
16451
|
+
* Cloud's setup checklist. */
|
|
16452
|
+
firstTurnAt: external_exports.string().trim().max(40).optional()
|
|
16304
16453
|
}).strict();
|
|
16305
16454
|
var instanceConfigSchema = external_exports.object({
|
|
16306
16455
|
driver: external_exports.string().min(1),
|
|
@@ -16312,6 +16461,7 @@ var instanceConfigSchema = external_exports.object({
|
|
|
16312
16461
|
]).optional(),
|
|
16313
16462
|
environment: external_exports.record(external_exports.string(), external_exports.string()).optional(),
|
|
16314
16463
|
enabled: external_exports.boolean().optional(),
|
|
16464
|
+
access: external_exports.enum(["subscription", "custom", "api"]).optional(),
|
|
16315
16465
|
config: external_exports.json().optional()
|
|
16316
16466
|
});
|
|
16317
16467
|
var instanceConfigMapSchema = external_exports.record(external_exports.string(), instanceConfigSchema);
|
|
@@ -16369,11 +16519,17 @@ var appConfigSchema = external_exports.object({
|
|
|
16369
16519
|
phone: external_exports.enum(["ios", "android"]).optional()
|
|
16370
16520
|
}).optional(),
|
|
16371
16521
|
mistral: external_exports.object({ key: optionalText }).optional(),
|
|
16522
|
+
cerebras: external_exports.object({ key: optionalText }).optional(),
|
|
16372
16523
|
xai: external_exports.object({ key: optionalText, url: optionalText }).optional(),
|
|
16373
16524
|
/** Anthropic API key for Claude Code billed per token, handed only to
|
|
16374
16525
|
* Claude instances; `url` only for a proxy or a test double. Never a
|
|
16375
16526
|
* personal-login OAuth token. */
|
|
16376
|
-
anthropic: external_exports.object({ key: optionalText, url: optionalText }).optional(),
|
|
16527
|
+
anthropic: external_exports.object({ key: optionalText, url: optionalText, everyClaudeBot: external_exports.boolean().optional() }).optional(),
|
|
16528
|
+
/** OpenAI's own API key, for the `openai` instance only. Codex keeps its
|
|
16529
|
+
* own ChatGPT or API login and never reads this. */
|
|
16530
|
+
openai: external_exports.object({ key: optionalText }).optional(),
|
|
16531
|
+
/** OpenRouter key, for the `openrouter` instance only. */
|
|
16532
|
+
openrouter: external_exports.object({ key: optionalText }).optional(),
|
|
16377
16533
|
/** Monthly spend limit for the whole workspace, against the cost engines
|
|
16378
16534
|
* report to the usage ledger. Enforced only with the `budgets` entitlement. */
|
|
16379
16535
|
budgets: external_exports.object({
|
|
@@ -16407,8 +16563,8 @@ var appConfigSchema = external_exports.object({
|
|
|
16407
16563
|
opencodeGo: external_exports.object({ apiKey: optionalText }).optional(),
|
|
16408
16564
|
/** Voice settings and the selected voice id. `provider` picks the
|
|
16409
16565
|
* engine: "elevenlabs" (default; needs `key`), "fish" (needs its own
|
|
16410
|
-
* `fishKey`), "system" (the Mac's
|
|
16411
|
-
* "xai" (Grok TTS, reusing `xai.key`), or
|
|
16566
|
+
* `fishKey`; `fishModel` picks its speech model), "system" (the Mac's
|
|
16567
|
+
* built-in voices, no key), "xai" (Grok TTS, reusing `xai.key`), or
|
|
16412
16568
|
* "chatterbox" (a local OpenAI-compatible Chatterbox server; `baseUrl`
|
|
16413
16569
|
* and `model` are settings, not secrets). Cloud keys stay separate so
|
|
16414
16570
|
* switching providers never overwrites or misuses the other key. */
|
|
@@ -16418,7 +16574,8 @@ var appConfigSchema = external_exports.object({
|
|
|
16418
16574
|
voice: optionalText,
|
|
16419
16575
|
provider: external_exports.enum(["elevenlabs", "fish", "system", "chatterbox", "xai"]).optional(),
|
|
16420
16576
|
baseUrl: external_exports.string().trim().max(2048).refine((value) => !value || /^https?:\/\//i.test(value), "the Chatterbox server address must start with http:// or https://").optional(),
|
|
16421
|
-
model: optionalText
|
|
16577
|
+
model: optionalText,
|
|
16578
|
+
fishModel: external_exports.enum(FISH_TTS_MODELS).optional()
|
|
16422
16579
|
}).optional(),
|
|
16423
16580
|
/** The decision model (server/decider): a fast classifier that picks
|
|
16424
16581
|
* things for bots, starting with who answers a room message. `key` is
|
|
@@ -16506,6 +16663,34 @@ var DATA_DIR = process.env.OMB_DATA_DIR ?? join3(homedir2(), ".openmausbot");
|
|
|
16506
16663
|
var LEGACY_DATA_DIR = join3(homedir2(), ".opengrokbot");
|
|
16507
16664
|
var EVENTS_DIR = join3(DATA_DIR, "events");
|
|
16508
16665
|
var NATIVE_DIR = join3(DATA_DIR, "native");
|
|
16666
|
+
var OPENAI_API_INSTANCE = "openai";
|
|
16667
|
+
var OPENROUTER_API_INSTANCE = "openrouter";
|
|
16668
|
+
var XAI_API_INSTANCE = "xaiApi";
|
|
16669
|
+
var CLAUDE_API_INSTANCE = "claudeApi";
|
|
16670
|
+
var API_KEY_FLEET = {
|
|
16671
|
+
[OPENAI_API_INSTANCE]: {
|
|
16672
|
+
driver: "openai-compat",
|
|
16673
|
+
displayName: "OpenAI",
|
|
16674
|
+
access: "api",
|
|
16675
|
+
icon: { kind: "preset", preset: "openai" },
|
|
16676
|
+
config: { url: "https://api.openai.com/v1", apiKeyEnv: "OMB_OPENAI_API_KEY", catalog: "openai" }
|
|
16677
|
+
},
|
|
16678
|
+
[CLAUDE_API_INSTANCE]: {
|
|
16679
|
+
driver: "claudeAgent",
|
|
16680
|
+
displayName: "Claude (API key)",
|
|
16681
|
+
access: "api",
|
|
16682
|
+
icon: { kind: "preset", preset: "anthropic" },
|
|
16683
|
+
config: { requireApiKey: true }
|
|
16684
|
+
},
|
|
16685
|
+
[XAI_API_INSTANCE]: { driver: "grok", displayName: "xAI", access: "api", icon: { kind: "preset", preset: "xai" } },
|
|
16686
|
+
[OPENROUTER_API_INSTANCE]: {
|
|
16687
|
+
driver: "openai-compat",
|
|
16688
|
+
displayName: "OpenRouter",
|
|
16689
|
+
access: "api",
|
|
16690
|
+
icon: { kind: "preset", preset: "openrouter" },
|
|
16691
|
+
config: { url: "https://openrouter.ai/api/v1", apiKeyEnv: "OMB_OPENROUTER_API_KEY" }
|
|
16692
|
+
}
|
|
16693
|
+
};
|
|
16509
16694
|
|
|
16510
16695
|
// server/container-computer.ts
|
|
16511
16696
|
var run = promisify(execFile2);
|
|
@@ -16637,6 +16822,7 @@ var CONTAINER_ID = /^[a-f0-9]{12,64}$/i;
|
|
|
16637
16822
|
var LOCK_ACQUIRE_TIMEOUT_MS = 5e3;
|
|
16638
16823
|
var SCREENSHOT_BUDGET_MS = 45e3;
|
|
16639
16824
|
var PREPARATION_LOCK_TIMEOUT_MS = SCREENSHOT_BUDGET_MS + LOCK_ACQUIRE_TIMEOUT_MS;
|
|
16825
|
+
var NATIVE_VIEWER_LIFETIME_MS = 8 * 60 * 6e4;
|
|
16640
16826
|
function vpsDockerArgs(alias2, args2) {
|
|
16641
16827
|
if (!isValidSshAlias(alias2)) {
|
|
16642
16828
|
throw new Error("invalid VPS SSH config alias");
|