openmausbot 0.1.85 → 0.1.86
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/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/assets/abnfDiagram-O67JEVCF-DpUZNnFD.js +1 -0
- package/dist/assets/arc-DW7mrI4p.js +1 -0
- package/dist/assets/architectureDiagram-NJMV4G6O-CyeZ5WLZ.js +36 -0
- package/dist/assets/blockDiagram-BEXU5L5S-CBVaNjO7.js +140 -0
- package/dist/assets/c4Diagram-YGBWAQC7-sf8d41uT.js +38 -0
- package/dist/assets/channel-BXFkgus9.js +1 -0
- package/dist/assets/chunk-2Q5K7J3B-BOGvy7Y_.js +1 -0
- package/dist/assets/chunk-3FUC2YCW-BiF9zyiz.js +2 -0
- package/dist/assets/chunk-5VM5RSS4-EFuZ1SBZ.js +15 -0
- package/dist/assets/chunk-GTNCS2PH-pJLNSAT7.js +88 -0
- package/dist/assets/chunk-GWA4HPMP-Cb-3_3IT.js +1 -0
- package/dist/assets/chunk-JWPE2WC7-DAf5aogn.js +1 -0
- package/dist/assets/chunk-NETBCI7D-DR3kiwZz.js +1 -0
- package/dist/assets/chunk-WEXAMYUT-BmU8PeyM.js +1 -0
- package/dist/assets/chunk-XXDRQBXY-Buh8g8OT.js +1 -0
- package/dist/assets/classDiagram-v2-NBCMYWYE-BurfmMWM.js +217 -0
- package/dist/assets/cose-bilkent-JH36ORCC-KkGZUEkU.js +1 -0
- package/dist/assets/cynefin-OW5HDTMX-C3PpV96d.js +166 -0
- package/dist/assets/cynefinDiagram-VND7K2PF-Dt8JwJaI.js +62 -0
- package/dist/assets/cytoscape.esm-BB4DxJjf.js +321 -0
- package/dist/assets/dagre-6A5THRUB-DkjN8266.js +4 -0
- package/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/dist/assets/diagram-22UHCM2B-DUAJS0JV.js +200 -0
- package/dist/assets/diagram-3UASUU5V-Dw4KhF1a.js +24 -0
- package/dist/assets/diagram-ATOU4E4O-Dd1gmQqf.js +3 -0
- package/dist/assets/diagram-CDSNMT55-CjwGs0Yw.js +30 -0
- package/dist/assets/diagram-MLGK6HIB-BL-69Zrq.js +24 -0
- package/dist/assets/diagram-MPIPVDR6-5Zi2N7wo.js +41 -0
- package/dist/assets/ebnfDiagram-ZINNZB2B-D9NekWUX.js +1 -0
- package/dist/assets/elk-276RUBZZ-CkaSQjxw.js +27 -0
- package/dist/assets/erDiagram-OPXOYQCR-CdAVBV8-.js +99 -0
- package/dist/assets/flowDiagram-KWPJA3E3-Bm_lWWH7.js +213 -0
- package/dist/assets/ganttDiagram-FUAMR5RP-FZ8ejYWJ.js +292 -0
- package/dist/assets/gitGraphDiagram-X574FWY7-Dlv9rizZ.js +106 -0
- package/dist/assets/graph-D8UmR1vK.js +1 -0
- package/dist/assets/index-BGgqlWPJ.css +1 -0
- package/dist/assets/index-BtHo8ZKl.js +577 -0
- package/dist/assets/{index-CTNNoqSJ.js → index-h9FFNwTu.js} +1 -1
- package/dist/assets/infoDiagram-VRGFBTTK-BdQ_gW5B.js +2 -0
- package/dist/assets/init-Gi6I4Gst.js +1 -0
- package/dist/assets/ishikawaDiagram-OU5B5YK6-EwssEp2X.js +70 -0
- package/dist/assets/journeyDiagram-ZHPQQLJL-BX1G1vOd.js +139 -0
- package/dist/assets/kanban-definition-PNTS6WVX-BB4kAsyC.js +89 -0
- package/dist/assets/linear-3su2TG93.js +1 -0
- package/dist/assets/mermaid.core-CDD1E0s9.js +311 -0
- package/dist/assets/mindmap-definition-NLK3R4M7-Ba50MsNK.js +96 -0
- package/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/dist/assets/pegDiagram-GJSIUBJH-DZLkkZlM.js +1 -0
- package/dist/assets/pieDiagram-5QR66LMP-DaTz77Uq.js +39 -0
- package/dist/assets/quadrantDiagram-O4NWA36T-CpaiidpR.js +7 -0
- package/dist/assets/railroadDiagram-XR7U4H2S-mN4JrMeI.js +1 -0
- package/dist/assets/requirementDiagram-PLB6GJNP-BSNDRpg7.js +84 -0
- package/dist/assets/sankeyDiagram-IPEJSGJF-FngzGNug.js +40 -0
- package/dist/assets/sequenceDiagram-PO4LG4MO-CM4pCC3L.js +169 -0
- package/dist/assets/sizeCapture-INFHLROL-CRICHXkw.js +1 -0
- package/dist/assets/stateDiagram-v2-GCMORJYK-oyTWpxH2.js +291 -0
- package/dist/assets/swimlanes-2SLR337P-D9h9mPBq.js +1 -0
- package/dist/assets/swimlanesDiagram-TC7HE7FX-BWrvB2ak.js +8 -0
- package/dist/assets/timeline-definition-EJHVYXUP-BJUlN9bW.js +120 -0
- package/dist/assets/usecaseDiagram-POWQR4AR-3uBNkbAb.js +370 -0
- package/dist/assets/vennDiagram-UO4OBE2U-D2odalzT.js +34 -0
- package/dist/assets/wardleyDiagram-VNRHLVJA-DHgFaB9S.js +78 -0
- package/dist/assets/xychartDiagram-PMCCYNJV-w5GYM2h0.js +7 -0
- package/dist/index.html +2 -2
- package/dist-server/container-mcp.js +19 -10
- package/dist-server/drivers/agents-proxy.js +16159 -1596
- package/dist-server/enterprise/LICENSE +32 -0
- package/dist-server/enterprise/server/index.js +5 -5
- package/dist-server/index.js +4779 -1667
- package/dist-server/mcp-server.js +3 -1
- package/dist-server/openmausbot.js +4679 -4266
- package/dist-server/pair-cli.js +4679 -4266
- package/dist-server/server/admin-activity.js +410 -0
- package/dist-server/server/bot-visibility.js +462 -0
- package/dist-server/server/box.js +2 -1
- package/dist-server/server/browser-runtime.js +1 -1
- package/dist-server/server/channel-queue.js +2 -0
- package/dist-server/server/cli-prompts.js +24 -2
- package/dist-server/server/cli.js +79 -10
- package/dist-server/server/composio.js +49 -11
- package/dist-server/server/config.js +79 -13
- package/dist-server/server/decision-log.js +209 -48
- package/dist-server/server/default-model-selection.js +20 -3
- package/dist-server/server/delegations.js +11 -9
- package/dist-server/server/drivers/acp/core.js +110 -22
- package/dist-server/server/drivers/acp/grok.js +4 -3
- package/dist-server/server/drivers/agents-call.js +1123 -0
- package/dist-server/server/drivers/agents-catalog.js +659 -0
- package/dist-server/server/drivers/agents-client.js +28 -0
- package/dist-server/server/drivers/agents-proxy.js +18 -1722
- package/dist-server/server/drivers/chat-mcp-tools.js +17 -2
- package/dist-server/server/drivers/claude.js +21 -6
- package/dist-server/server/drivers/codex-mcp-names.js +44 -0
- package/dist-server/server/drivers/codex.js +26 -4
- package/dist-server/server/drivers/grok.js +2 -1
- package/dist-server/server/drivers/openai-compat.js +15 -8
- package/dist-server/server/enterprise.js +97 -16
- package/dist-server/server/external-runtime.js +83 -0
- package/dist-server/server/guarded-requests.js +60 -0
- package/dist-server/server/harness/http.js +61 -0
- package/dist-server/server/hosted-models.js +151 -0
- package/dist-server/server/hosted-slack.js +11 -0
- package/dist-server/server/index.js +1718 -348
- package/dist-server/server/managed-desktop.js +79 -14
- package/dist-server/server/managed-policy.js +153 -0
- package/dist-server/server/message-db.js +28 -0
- package/dist-server/server/model-context-window.js +7 -0
- package/dist-server/server/model-prices.js +121 -0
- package/dist-server/server/notify.js +10 -1
- package/dist-server/server/peer-roster.js +13 -2
- package/dist-server/server/recent-work.js +15 -0
- package/dist-server/server/request-auth.js +96 -0
- package/dist-server/server/room-handoffs.js +25 -11
- package/dist-server/server/routes/hosted-slack.js +20 -0
- package/dist-server/server/routes/table.js +14 -0
- package/dist-server/server/routines.js +22 -0
- package/dist-server/server/spend.js +111 -16
- package/dist-server/server/steer-queue.js +6 -1
- package/dist-server/server/store.js +292 -21
- package/dist-server/server/team-backup.js +10 -1
- package/dist-server/server/thread-starters.js +53 -0
- package/dist-server/server/usage-ledger.js +31 -8
- package/dist-server/server/workspace-backup-policy.js +9 -2
- package/dist-server/server/workspace-backup.js +7 -4
- package/dist-server/shared/mention-boundary.js +15 -0
- package/dist-server/shared/routines.js +7 -1
- package/dist-server/shared/team-backup.js +2 -0
- package/dist-server/src/lib/composer-attachments.js +16 -0
- package/dist-server/vps-container-mcp.js +19 -10
- package/enterprise/README.md +33 -12
- package/enterprise/server/index.js +5 -5
- package/package.json +1 -1
- package/dist/assets/index-Ba9G44HI.js +0 -310
- package/dist/assets/index-CkRNp7wX.css +0 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
const jsonHooks = new WeakMap();
|
|
2
|
+
const parsedBodies = new WeakMap();
|
|
3
|
+
/** Pass every JSON body sent on this response through `hook` first (it may
|
|
4
|
+
* return a narrowed copy). Set once a request is authenticated: index.ts
|
|
5
|
+
* narrows what a member is sent and notes what an admin change answered.
|
|
6
|
+
* Hooks added later run after earlier ones. */
|
|
7
|
+
export function onJsonBody(res, hook) {
|
|
8
|
+
const previous = jsonHooks.get(res);
|
|
9
|
+
jsonHooks.set(res, previous ? (body) => hook(previous(body)) : hook);
|
|
10
|
+
}
|
|
11
|
+
/** The JSON body readBody parsed for this request, if it read one. */
|
|
12
|
+
export function parsedBodyOf(req) {
|
|
13
|
+
return parsedBodies.get(req);
|
|
14
|
+
}
|
|
15
|
+
export function json(res, status, body) {
|
|
16
|
+
const hook = jsonHooks.get(res);
|
|
17
|
+
const data = JSON.stringify(hook ? hook(body) : body);
|
|
18
|
+
res.writeHead(status, { "content-type": "application/json" });
|
|
19
|
+
res.end(data);
|
|
20
|
+
}
|
|
21
|
+
export function readBody(req, limit = 1_000_000) {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
let data = "";
|
|
24
|
+
let bytes = 0;
|
|
25
|
+
let done = false;
|
|
26
|
+
const fail = (status, msg) => {
|
|
27
|
+
if (done)
|
|
28
|
+
return;
|
|
29
|
+
done = true;
|
|
30
|
+
const err = Object.assign(new Error(msg), { status });
|
|
31
|
+
reject(err);
|
|
32
|
+
};
|
|
33
|
+
req.on("data", (c) => {
|
|
34
|
+
if (done)
|
|
35
|
+
return;
|
|
36
|
+
bytes += typeof c === "string" ? Buffer.byteLength(c) : c.length;
|
|
37
|
+
if (bytes > limit) {
|
|
38
|
+
// Keep draining the socket, but stop retaining attacker-controlled
|
|
39
|
+
// bytes. Destroying the request here prevents the caller from
|
|
40
|
+
// receiving the useful 413 response.
|
|
41
|
+
return fail(413, "body too large");
|
|
42
|
+
}
|
|
43
|
+
data += c;
|
|
44
|
+
});
|
|
45
|
+
req.on("end", () => {
|
|
46
|
+
if (done)
|
|
47
|
+
return;
|
|
48
|
+
let body;
|
|
49
|
+
try {
|
|
50
|
+
body = data ? JSON.parse(data) : {};
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return fail(400, "invalid JSON body");
|
|
54
|
+
}
|
|
55
|
+
done = true;
|
|
56
|
+
parsedBodies.set(req, body);
|
|
57
|
+
resolve(body);
|
|
58
|
+
});
|
|
59
|
+
req.on("error", (e) => fail(400, e instanceof Error ? e.message : String(e)));
|
|
60
|
+
});
|
|
61
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { writeFileAtomic } from "./atomic.js";
|
|
5
|
+
import { hostedWorkspaceConfiguration } from "./enterprise.js";
|
|
6
|
+
export const HOSTED_MODEL_POLICY_HEADER = "X-Omb-Hosted-Model-Policy";
|
|
7
|
+
export const HOSTED_MODEL_SETUP_ERROR = "No company models are assigned to this workspace. Ask your administrator to enable model access in Admin.";
|
|
8
|
+
export const HOSTED_MODEL_SELECTION_ERROR = "This model is not assigned to this workspace. Choose one of its company models.";
|
|
9
|
+
export const HOSTED_PROVIDER_SETTINGS_ERROR = "Company models and provider accounts are managed in Admin.";
|
|
10
|
+
const nativeModels = z.array(z.string().regex(/^[A-Za-z0-9][A-Za-z0-9._-]{0,159}$/)).max(100);
|
|
11
|
+
const catalogSchema = z.object({
|
|
12
|
+
anthropic: nativeModels,
|
|
13
|
+
openai: nativeModels,
|
|
14
|
+
openrouter: z.array(z.string().max(160).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*\/[A-Za-z0-9][A-Za-z0-9._:/+-]*$/)).max(100),
|
|
15
|
+
}).strict();
|
|
16
|
+
const providerFor = { claude: "anthropic", codex: "openai", opencode: "openrouter" };
|
|
17
|
+
/** Operator-only policy. An ordinary desktop has neither input and keeps its
|
|
18
|
+
* personal providers. Partial policy configuration must never enable them. */
|
|
19
|
+
export function hostedModelPolicy(dataDirectory, env = process.env) {
|
|
20
|
+
if (env.OMB_HOSTED_MODELS === undefined && env.OMB_HOSTED_MODEL_TOKEN === undefined)
|
|
21
|
+
return null;
|
|
22
|
+
const hosted = hostedWorkspaceConfiguration(env);
|
|
23
|
+
if (!hosted?.portalMembership || env.OMB_DESKTOP_PARENT === "1" || !/^omb_workspace_[A-Za-z0-9_-]{43}$/.test(env.OMB_HOSTED_MODEL_TOKEN ?? "")) {
|
|
24
|
+
throw new Error("Hosted model access requires complete portal-managed workspace configuration.");
|
|
25
|
+
}
|
|
26
|
+
let catalog;
|
|
27
|
+
try {
|
|
28
|
+
if (!env.OMB_HOSTED_MODELS || env.OMB_HOSTED_MODELS.length > 65536)
|
|
29
|
+
throw new Error();
|
|
30
|
+
catalog = catalogSchema.parse(JSON.parse(env.OMB_HOSTED_MODELS));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
throw new Error("Invalid hosted model catalog.");
|
|
34
|
+
}
|
|
35
|
+
for (const key of ["anthropic", "openai", "openrouter"])
|
|
36
|
+
catalog[key] = [...new Set(catalog[key])];
|
|
37
|
+
const token = env.OMB_HOSTED_MODEL_TOKEN;
|
|
38
|
+
const base = `${hosted.admin.origin}/api/gateway/${hosted.workspace}`;
|
|
39
|
+
const assigned = (id) => Object.hasOwn(providerFor, id) ? catalog[providerFor[id]] : [];
|
|
40
|
+
const allows = (selection) => assigned(selection.instanceId).includes(selection.model);
|
|
41
|
+
const normalized = (selection) => {
|
|
42
|
+
if (selection.instanceId === "codex" && selection.model.startsWith("omb-managed-openai::")) {
|
|
43
|
+
return { ...selection, model: selection.model.slice("omb-managed-openai::".length) };
|
|
44
|
+
}
|
|
45
|
+
if (["opencode", "opencodeGo"].includes(selection.instanceId) && selection.model.startsWith("omb-managed-openrouter/")) {
|
|
46
|
+
return { instanceId: "opencode", model: selection.model.slice("omb-managed-openrouter/".length) };
|
|
47
|
+
}
|
|
48
|
+
// This stable ID now uses the replay-based OpenAI-compatible driver,
|
|
49
|
+
// which supports neither OpenCode variants nor native effort levels.
|
|
50
|
+
if (selection.instanceId === "opencode")
|
|
51
|
+
return { instanceId: "opencode", model: selection.model };
|
|
52
|
+
return selection;
|
|
53
|
+
};
|
|
54
|
+
const select = (previous) => {
|
|
55
|
+
const current = previous ? normalized(previous) : undefined;
|
|
56
|
+
if (current && allows(current))
|
|
57
|
+
return { ...current };
|
|
58
|
+
const id = current && assigned(current.instanceId).length ? current.instanceId
|
|
59
|
+
: Object.keys(providerFor).find(id => assigned(id).length);
|
|
60
|
+
return id ? { instanceId: id, model: assigned(id)[0] } : { instanceId: "", model: "" };
|
|
61
|
+
};
|
|
62
|
+
const home = (name) => {
|
|
63
|
+
let directory = dataDirectory;
|
|
64
|
+
for (const part of ["providers", "hosted", name]) {
|
|
65
|
+
directory = join(directory, part);
|
|
66
|
+
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
67
|
+
const stat = lstatSync(directory);
|
|
68
|
+
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
69
|
+
throw new Error("Hosted provider storage must be an owned directory.");
|
|
70
|
+
}
|
|
71
|
+
return directory;
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
allows, select,
|
|
75
|
+
resetTask(previous, next) {
|
|
76
|
+
return previous.instanceId !== next.instanceId || previous.model !== next.model
|
|
77
|
+
? { resumeCursors: {}, lastInstanceId: undefined, rewound: true, lastContextModel: undefined, appliedCompactionId: undefined }
|
|
78
|
+
: {};
|
|
79
|
+
},
|
|
80
|
+
error: () => Object.values(catalog).some(models => models.length) ? HOSTED_MODEL_SELECTION_ERROR : HOSTED_MODEL_SETUP_ERROR,
|
|
81
|
+
configs() {
|
|
82
|
+
const configs = {};
|
|
83
|
+
// Saved instance commands are tenant-editable personal configuration.
|
|
84
|
+
// Only the operator may replace the bundled executables (also how an
|
|
85
|
+
// isolated verification fixture supplies its synthetic native engines).
|
|
86
|
+
const cli = (name) => env[`OMB_HOSTED_${name}_CLI`]?.trim() || name.toLowerCase();
|
|
87
|
+
if (catalog.anthropic.length)
|
|
88
|
+
configs.claude = {
|
|
89
|
+
driver: "claudeAgent", displayName: "Company · Claude",
|
|
90
|
+
config: { cli: cli("CLAUDE"), managed: true, managedModels: catalog.anthropic, configDir: home("claude") },
|
|
91
|
+
environment: { ANTHROPIC_API_KEY: token, ANTHROPIC_AUTH_TOKEN: token, ANTHROPIC_BASE_URL: `${base}/anthropic`,
|
|
92
|
+
ANTHROPIC_MODEL: catalog.anthropic[0], ANTHROPIC_DEFAULT_HAIKU_MODEL: catalog.anthropic[0],
|
|
93
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: catalog.anthropic[0], ANTHROPIC_DEFAULT_OPUS_MODEL: catalog.anthropic[0],
|
|
94
|
+
ANTHROPIC_SMALL_FAST_MODEL: catalog.anthropic[0] },
|
|
95
|
+
};
|
|
96
|
+
if (catalog.openai.length)
|
|
97
|
+
configs.codex = {
|
|
98
|
+
driver: "codex", displayName: "Company · Codex",
|
|
99
|
+
config: { cli: cli("CODEX"), managed: { url: `${base}/openai/v1`, models: catalog.openai } },
|
|
100
|
+
environment: { OPENMAUSBOT_COMPANY_API_KEY: token, CODEX_HOME: home("codex") },
|
|
101
|
+
};
|
|
102
|
+
if (catalog.openrouter.length)
|
|
103
|
+
configs.opencode = {
|
|
104
|
+
driver: "openai-compat", displayName: "Company · OpenRouter",
|
|
105
|
+
config: { url: `${base}/openrouter/v1`, apiKeyEnv: "OPENMAUSBOT_COMPANY_API_KEY", provider: "", model: catalog.openrouter[0], managedModels: catalog.openrouter },
|
|
106
|
+
environment: { OPENMAUSBOT_COMPANY_API_KEY: token },
|
|
107
|
+
};
|
|
108
|
+
return configs;
|
|
109
|
+
},
|
|
110
|
+
decorate(instance) {
|
|
111
|
+
const models = assigned(instance.instanceId);
|
|
112
|
+
return {
|
|
113
|
+
...instance,
|
|
114
|
+
models: { default: models[0], options: models.map(id => ({ id, label: id })) },
|
|
115
|
+
refreshModels: async () => { },
|
|
116
|
+
installRuntime: undefined, startAuthentication: undefined, getAuthentication: undefined,
|
|
117
|
+
completeAuthentication: undefined, cancelAuthentication: undefined, signOut: undefined,
|
|
118
|
+
snapshot: async () => ({ ...await instance.snapshot(), authenticated: true, billing: "metered" }),
|
|
119
|
+
adapter: { ...instance.adapter, sendTurn: async (input) => {
|
|
120
|
+
if (!input.model || !models.includes(input.model))
|
|
121
|
+
throw new Error(HOSTED_MODEL_SELECTION_ERROR);
|
|
122
|
+
return instance.adapter.sendTurn(input);
|
|
123
|
+
} },
|
|
124
|
+
};
|
|
125
|
+
},
|
|
126
|
+
/** A one-time route migration drops only native continuation handles. The
|
|
127
|
+
* canonical conversations and branches remain, and rewind replays them. */
|
|
128
|
+
reconcile(store) {
|
|
129
|
+
const marker = join(dataDirectory, "hosted-model-policy.json");
|
|
130
|
+
const identity = JSON.stringify({ version: 1, admin: hosted.admin.origin, workspace: hosted.workspace });
|
|
131
|
+
const changedRoute = !existsSync(marker) || readFileSync(marker, "utf8") !== identity;
|
|
132
|
+
for (const bot of store.bots) {
|
|
133
|
+
const previousDefault = bot.modelSelection;
|
|
134
|
+
const nextDefault = select(previousDefault);
|
|
135
|
+
for (const task of store.tasks(bot.id)) {
|
|
136
|
+
const current = task.modelSelection ?? previousDefault;
|
|
137
|
+
const next = select(current);
|
|
138
|
+
const changed = JSON.stringify(next) !== JSON.stringify(current);
|
|
139
|
+
if (changed || changedRoute)
|
|
140
|
+
store.patchTask(bot.id, task.threadId, {
|
|
141
|
+
modelSelection: next, resumeCursors: {}, lastInstanceId: undefined, rewound: true,
|
|
142
|
+
lastContextModel: undefined, appliedCompactionId: undefined,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (JSON.stringify(previousDefault) !== JSON.stringify(nextDefault))
|
|
146
|
+
store.patchBot(bot.id, { modelSelection: nextDefault });
|
|
147
|
+
}
|
|
148
|
+
writeFileAtomic(marker, identity, { mode: 0o600 });
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { hostedWorkspaceConfiguration } from "./enterprise.js";
|
|
2
|
+
/** The hosted Admin owns Slack installation and authorization. This link
|
|
3
|
+
* carries identifiers only; opening it never grants access to that service. */
|
|
4
|
+
export function hostedSlackManagement(botId, runtimeReady, env = process.env) {
|
|
5
|
+
const hosted = hostedWorkspaceConfiguration(env);
|
|
6
|
+
if (!runtimeReady || !hosted?.portalMembership)
|
|
7
|
+
return { available: false };
|
|
8
|
+
const management = new URL("/slack", hosted.admin);
|
|
9
|
+
management.search = new URLSearchParams({ workspace: hosted.workspace, bot: botId }).toString();
|
|
10
|
+
return { available: true, managementUrl: management.href };
|
|
11
|
+
}
|