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
|
@@ -24,7 +24,15 @@ function monthKey(at) {
|
|
|
24
24
|
export function usageFileFor(dataDir, at) {
|
|
25
25
|
return join(dataDir, DIR, `${monthKey(at)}.jsonl`);
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
27
|
+
/** Identifies one row: a thread runs one turn at a time, so a bot cannot
|
|
28
|
+
* settle two turns on the same thread in the same millisecond. Lets the
|
|
29
|
+
* spend cap tell a booked row it already counted from memory apart from the
|
|
30
|
+
* same row read back from the file. */
|
|
31
|
+
export function usageRowKey(row) {
|
|
32
|
+
return `${row.at}|${row.threadId}|${row.botId}`;
|
|
33
|
+
}
|
|
34
|
+
/** Append one settled turn. Fire-and-forget (see the module comment): the
|
|
35
|
+
* returned promise never rejects, and says whether the row reached disk. */
|
|
28
36
|
export function appendUsage(dataDir, row) {
|
|
29
37
|
const record = {
|
|
30
38
|
...row,
|
|
@@ -34,10 +42,14 @@ export function appendUsage(dataDir, row) {
|
|
|
34
42
|
...(typeof row.cachedInput === "number" ? { cachedInput: clean(row.cachedInput) } : {}),
|
|
35
43
|
costUsd: finiteOrNull(row.costUsd),
|
|
36
44
|
};
|
|
45
|
+
// A cost is labelled with where it came from; an unpriced row carries no label.
|
|
46
|
+
if (record.costUsd === null)
|
|
47
|
+
delete record.costSource;
|
|
48
|
+
else
|
|
49
|
+
record.costSource = row.costSource === "estimated" ? "estimated" : "reported";
|
|
37
50
|
const previous = writeQueues.get(dataDir) ?? Promise.resolve();
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
.catch(() => {
|
|
51
|
+
const attempt = previous.then(() => write(dataDir, record));
|
|
52
|
+
const queued = attempt.then(() => undefined, () => {
|
|
41
53
|
/* bookkeeping must never take down the turn */
|
|
42
54
|
});
|
|
43
55
|
writeQueues.set(dataDir, queued);
|
|
@@ -45,6 +57,7 @@ export function appendUsage(dataDir, row) {
|
|
|
45
57
|
if (writeQueues.get(dataDir) === queued)
|
|
46
58
|
writeQueues.delete(dataDir);
|
|
47
59
|
});
|
|
60
|
+
return attempt.then(() => true, () => false);
|
|
48
61
|
}
|
|
49
62
|
async function write(dataDir, record) {
|
|
50
63
|
await mkdir(join(dataDir, DIR), { recursive: true, mode: 0o700 });
|
|
@@ -165,7 +178,13 @@ function groupOf(row, groupBy) {
|
|
|
165
178
|
}
|
|
166
179
|
}
|
|
167
180
|
function emptyGroup(key, label) {
|
|
168
|
-
return { key, label, turns: 0, input: 0, output: 0, cachedInput: 0, costUsd: null, unpriced: 0, billableUsd: null };
|
|
181
|
+
return { key, label, turns: 0, input: 0, output: 0, cachedInput: 0, costUsd: null, estimatedUsd: null, unpriced: 0, billableUsd: null };
|
|
182
|
+
}
|
|
183
|
+
/** Where a row's cost came from, for rows old and new; null when it has none. */
|
|
184
|
+
export function costSourceOf(row) {
|
|
185
|
+
if (finiteOrNull(row.costUsd) === null)
|
|
186
|
+
return null;
|
|
187
|
+
return row.costSource === "estimated" ? "estimated" : "reported";
|
|
169
188
|
}
|
|
170
189
|
function add(group, row, prices) {
|
|
171
190
|
group.turns += 1;
|
|
@@ -175,8 +194,11 @@ function add(group, row, prices) {
|
|
|
175
194
|
const cost = finiteOrNull(row.costUsd);
|
|
176
195
|
if (cost === null)
|
|
177
196
|
group.unpriced += 1;
|
|
178
|
-
else
|
|
197
|
+
else {
|
|
179
198
|
group.costUsd = (group.costUsd ?? 0) + cost;
|
|
199
|
+
if (costSourceOf(row) === "estimated")
|
|
200
|
+
group.estimatedUsd = (group.estimatedUsd ?? 0) + cost;
|
|
201
|
+
}
|
|
180
202
|
const billable = prices ? billableFor(row, prices) : null;
|
|
181
203
|
if (billable !== null)
|
|
182
204
|
group.billableUsd = (group.billableUsd ?? 0) + billable;
|
|
@@ -207,7 +229,7 @@ export function summarizeUsage(rows, groupBy, prices = null) {
|
|
|
207
229
|
}
|
|
208
230
|
return { groups: ordered, total };
|
|
209
231
|
}
|
|
210
|
-
function csvCell(value) {
|
|
232
|
+
export function csvCell(value) {
|
|
211
233
|
if (value === null)
|
|
212
234
|
return "";
|
|
213
235
|
const text = String(value);
|
|
@@ -218,7 +240,7 @@ function csvCell(value) {
|
|
|
218
240
|
}
|
|
219
241
|
/** One line per turn, spreadsheet-ready; a billable column when a price list is given. */
|
|
220
242
|
export function usageCsv(rows, prices = null) {
|
|
221
|
-
const header = ["time", "bot", "model", "engine", "triggered_by", "input_tokens", "output_tokens", "cached_input_tokens", "cost_usd", ...(prices ? ["billable_usd"] : []), "thread"];
|
|
243
|
+
const header = ["time", "bot", "model", "engine", "triggered_by", "input_tokens", "output_tokens", "cached_input_tokens", "cost_usd", "cost_source", ...(prices ? ["billable_usd"] : []), "thread"];
|
|
222
244
|
const lines = [header.join(",")];
|
|
223
245
|
for (const row of rows) {
|
|
224
246
|
lines.push([
|
|
@@ -231,6 +253,7 @@ export function usageCsv(rows, prices = null) {
|
|
|
231
253
|
clean(row.output),
|
|
232
254
|
clean(row.cachedInput),
|
|
233
255
|
finiteOrNull(row.costUsd),
|
|
256
|
+
costSourceOf(row),
|
|
234
257
|
...(prices ? [billableFor(row, prices)] : []),
|
|
235
258
|
row.threadId,
|
|
236
259
|
].map(csvCell).join(","));
|
|
@@ -22,7 +22,14 @@ export function restoredWorkspaceConfig(portable, destination) {
|
|
|
22
22
|
}
|
|
23
23
|
/** Exact app-owned authentication paths, not a scan of user document text. */
|
|
24
24
|
export function excludedWorkspaceAuthPath(path) {
|
|
25
|
-
return /^(?:(?:providers|caddy|chrome-profile|\.agent-browser)(?:\/|$)|workspace-credentials\.json$|browser-engine-key$)/.test(path) ||
|
|
26
|
-
/^(?:config\.json|webhooks\.json|workspace-credentials\.json|browser-engine-key|sessions\.json|tunnel-account\.json)\.\d+(?:\.[0-9a-f-]+)?\.tmp$/.test(path) ||
|
|
25
|
+
return /^(?:(?:providers|caddy|chrome-profile|\.agent-browser)(?:\/|$)|workspace-credentials\.json$|external-runtimes\.json$|browser-engine-key$)/.test(path) ||
|
|
26
|
+
/^(?:config\.json|webhooks\.json|workspace-credentials\.json|external-runtimes\.json|browser-engine-key|sessions\.json|tunnel-account\.json)\.\d+(?:\.[0-9a-f-]+)?\.tmp$/.test(path) ||
|
|
27
27
|
/^(?:vm-home|vm-homes\/[^/]+)\/\.browser-profiles(?:\/|$)/.test(path);
|
|
28
28
|
}
|
|
29
|
+
/** Per-turn engine hook bearers (`hook-tokens/<digest>.token`, written by the
|
|
30
|
+
* Claude driver). They are dead once their turn settles, so they are never
|
|
31
|
+
* exported. Unlike the saved auth paths above they are not refused on import:
|
|
32
|
+
* v0.1.85 did export them, and such a backup must still restore, without them. */
|
|
33
|
+
export function ephemeralWorkspaceTokenPath(path) {
|
|
34
|
+
return /^hook-tokens(?:\/|$)/.test(path);
|
|
35
|
+
}
|
|
@@ -11,7 +11,7 @@ import { fromMarkdown } from "mdast-util-from-markdown";
|
|
|
11
11
|
import { writeFileAtomic } from "./atomic.js";
|
|
12
12
|
import { escapeAttribute, splitTranscriptAttachments } from "../src/lib/composer-attachments.js";
|
|
13
13
|
import { WORKSPACE_BACKUP_CLIENT_KEYS } from "../shared/workspace-backup-client.js";
|
|
14
|
-
import { excludedWorkspaceAuthPath, portableWorkspaceConfig, restoredWorkspaceConfig } from "./workspace-backup-policy.js";
|
|
14
|
+
import { ephemeralWorkspaceTokenPath, excludedWorkspaceAuthPath, portableWorkspaceConfig, restoredWorkspaceConfig } from "./workspace-backup-policy.js";
|
|
15
15
|
export const MAX_WORKSPACE_BACKUP_BYTES = 10 * 1024 ** 3;
|
|
16
16
|
export const MAX_WORKSPACE_BACKUP_FILES = 100_000;
|
|
17
17
|
export const MAX_WORKSPACE_BACKUP_UPLOAD_BYTES = MAX_WORKSPACE_BACKUP_BYTES + 256 * 1024 ** 2;
|
|
@@ -311,7 +311,7 @@ export async function createWorkspaceBackup(dataDir, options) {
|
|
|
311
311
|
if (!prefix && excluded(name))
|
|
312
312
|
continue;
|
|
313
313
|
const path = prefix ? `${prefix}/${name}` : name;
|
|
314
|
-
if (excludedWorkspaceAuthPath(path))
|
|
314
|
+
if (excludedWorkspaceAuthPath(path) || ephemeralWorkspaceTokenPath(path))
|
|
315
315
|
continue;
|
|
316
316
|
// Do not silently skip noncanonical source spellings: reject them so
|
|
317
317
|
// a case-sensitive host cannot export auth paths active on Windows/Mac.
|
|
@@ -781,9 +781,12 @@ function prepareRestore(dataDir, id, manifest) {
|
|
|
781
781
|
folder(prepared);
|
|
782
782
|
// Keep the authenticated original staging tree intact for reinspection and
|
|
783
783
|
// recovery. Only this installation copy has paths/scheduling adapted.
|
|
784
|
-
|
|
784
|
+
// An archive from a release that exported per-turn hook tokens still
|
|
785
|
+
// restores; the dead tokens themselves are never installed.
|
|
786
|
+
const installed = manifest.entries.filter((entry) => !ephemeralWorkspaceTokenPath(entry.path));
|
|
787
|
+
for (const entry of installed.filter((entry) => entry.type === "directory"))
|
|
785
788
|
folder(join(prepared, entry.path));
|
|
786
|
-
for (const entry of
|
|
789
|
+
for (const entry of installed) {
|
|
787
790
|
const destination = join(prepared, entry.path);
|
|
788
791
|
if (entry.type === "file")
|
|
789
792
|
copyRegular(join(job, "staged", "data", entry.path), destination);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Keep mention recognition identical in the renderer and server routing.
|
|
2
|
+
// Deliberately allow only opening punctuation/Markdown markers here: `/@bot`
|
|
3
|
+
// remains a URL path, while `(@bot)`, `【@bot】`, and `**@bot**` are tags.
|
|
4
|
+
const OPENING_MENTION_BOUNDARY = /[(*_~[{<'"\u2018\u201c\u3008\u300a\u300c\u300e\u3010\uff08]/u;
|
|
5
|
+
/** Return whether an at-sign starts a standalone mention at this offset. */
|
|
6
|
+
export function isMentionBoundary(text, at) {
|
|
7
|
+
if (at === 0)
|
|
8
|
+
return true;
|
|
9
|
+
const before = text[at - 1];
|
|
10
|
+
return /\s/u.test(before) || OPENING_MENTION_BOUNDARY.test(before);
|
|
11
|
+
}
|
|
12
|
+
/** A matched name must not be the prefix of a longer Unicode word. */
|
|
13
|
+
export function isMentionNameContinuation(value) {
|
|
14
|
+
return value !== undefined && /^[\p{L}\p{N}\p{M}_]/u.test(value);
|
|
15
|
+
}
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/** The statuses both failure indicators count: a run that went wrong and has
|
|
2
|
+
* not been acknowledged. One home so the sidebar dot, the errors pill, the
|
|
3
|
+
* logs filter and the bulk-seen sweep cannot drift apart. */
|
|
4
|
+
export const ROUTINE_PROBLEM_STATUSES = ["failed", "missed"];
|
|
5
|
+
export function isRoutineProblemRun(run) {
|
|
6
|
+
return ROUTINE_PROBLEM_STATUSES.includes(run.status);
|
|
7
|
+
}
|
|
@@ -25,6 +25,8 @@ const task = z.object({
|
|
|
25
25
|
titleFromFirstMessage: z.literal(true).optional(),
|
|
26
26
|
openedBy: z.object({ botId: key, name, at: timestamp, kind: z.enum(["pair", "work"]).optional() }).optional(),
|
|
27
27
|
closedBy: z.object({ botId: key, name, at: timestamp }).optional(),
|
|
28
|
+
/** Only true travels. Absence is unpinned, including backups from before pins. */
|
|
29
|
+
pinned: z.literal(true).optional(),
|
|
28
30
|
activeLeafId: key.nullable(),
|
|
29
31
|
messages: z.array(message).max(100_000),
|
|
30
32
|
});
|
|
@@ -691,3 +691,19 @@ export async function intakeFiles(_files, _opts) {
|
|
|
691
691
|
notice: pathless && failed ? `${pathless} (${failed})` : (pathless ?? failed),
|
|
692
692
|
};
|
|
693
693
|
}
|
|
694
|
+
/**
|
|
695
|
+
* Whether the composer may pull keyboard focus back into its textarea after an
|
|
696
|
+
* attachment lands. The draft was the writer's place when focus is still there,
|
|
697
|
+
* has fallen to the page (a disabled element drops it), or sits on a control
|
|
698
|
+
* inside the composer such as the paperclip button after the file dialog. A
|
|
699
|
+
* focused control elsewhere — a dialog, the thread list — is left alone.
|
|
700
|
+
*/
|
|
701
|
+
export function composerShouldRefocus(active, input) {
|
|
702
|
+
if (!active || active === input)
|
|
703
|
+
return true;
|
|
704
|
+
const root = input.ownerDocument;
|
|
705
|
+
if (active === root.body || active === root.documentElement)
|
|
706
|
+
return true;
|
|
707
|
+
const composer = input.closest("[data-tour=composer]");
|
|
708
|
+
return Boolean(composer?.contains(active));
|
|
709
|
+
}
|
|
@@ -15372,6 +15372,20 @@ var defaultModelSelectionSchema = external_exports.object({
|
|
|
15372
15372
|
(selection) => selection.variant === void 0 || selection.effort === void 0,
|
|
15373
15373
|
"choose either a model variant or an effort level"
|
|
15374
15374
|
);
|
|
15375
|
+
var threadsConfigSchema = external_exports.object({
|
|
15376
|
+
maxConcurrentPerBot: external_exports.number().int().min(1).max(MAX_CONCURRENT_BOT_THREADS),
|
|
15377
|
+
/** Cap each per-thread events/ and native/ NDJSON log at this many
|
|
15378
|
+
* bytes; absent (the default) keeps today's unbounded growth (#1280). */
|
|
15379
|
+
eventLogMaxBytes: external_exports.number().int().min(MIN_THREAD_EVENT_LOG_BYTES).max(MAX_THREAD_EVENT_LOG_BYTES).optional(),
|
|
15380
|
+
/** Days a closed or archived thread's event logs survive (#1280).
|
|
15381
|
+
* Absent keeps them forever. */
|
|
15382
|
+
eventLogRetentionDays: external_exports.number().int().min(1).max(3650).optional()
|
|
15383
|
+
}).strict();
|
|
15384
|
+
var threadsPatchSchema = threadsConfigSchema.extend({
|
|
15385
|
+
maxConcurrentPerBot: threadsConfigSchema.shape.maxConcurrentPerBot.optional(),
|
|
15386
|
+
eventLogMaxBytes: threadsConfigSchema.shape.eventLogMaxBytes.nullable(),
|
|
15387
|
+
eventLogRetentionDays: threadsConfigSchema.shape.eventLogRetentionDays.nullable()
|
|
15388
|
+
});
|
|
15375
15389
|
var appConfigSchema = external_exports.object({
|
|
15376
15390
|
/** Verified by the dedicated domain endpoint, never a generic config patch. */
|
|
15377
15391
|
customDomain: external_exports.string().optional(),
|
|
@@ -15464,15 +15478,10 @@ var appConfigSchema = external_exports.object({
|
|
|
15464
15478
|
compactAt: external_exports.number().positive().max(1e7).optional(),
|
|
15465
15479
|
autoCompact: external_exports.boolean().optional()
|
|
15466
15480
|
}).optional(),
|
|
15467
|
-
threads:
|
|
15468
|
-
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
eventLogMaxBytes: external_exports.number().int().min(MIN_THREAD_EVENT_LOG_BYTES).max(MAX_THREAD_EVENT_LOG_BYTES).optional(),
|
|
15472
|
-
/** Days a closed or archived thread's event logs survive (#1280).
|
|
15473
|
-
* Absent keeps them forever. */
|
|
15474
|
-
eventLogRetentionDays: external_exports.number().int().min(1).max(3650).optional()
|
|
15475
|
-
}).strict().optional(),
|
|
15481
|
+
threads: threadsConfigSchema.optional(),
|
|
15482
|
+
/** The authorization decision log (server/decision-log.ts): days of month
|
|
15483
|
+
* files kept, at least; OMB_DECISION_RETENTION_DAYS wins when set. */
|
|
15484
|
+
decisions: external_exports.object({ retentionDays: external_exports.number().int().min(1).max(3650).optional() }).strict().optional(),
|
|
15476
15485
|
localVm: localVmConfigSchema.optional(),
|
|
15477
15486
|
features: featureConfigSchema.optional(),
|
|
15478
15487
|
onboarding: onboardingConfigSchema.optional(),
|
|
@@ -15489,7 +15498,7 @@ var appConfigSchema = external_exports.object({
|
|
|
15489
15498
|
var storedAppConfigSchema = appConfigSchema.extend({
|
|
15490
15499
|
browserProfiles: storedBrowserProfilesSchema.optional()
|
|
15491
15500
|
});
|
|
15492
|
-
var appConfigPatchSchema = appConfigSchema.omit({ instances: true, mcpServers: true, cliStartup: true, customDomain: true });
|
|
15501
|
+
var appConfigPatchSchema = appConfigSchema.omit({ instances: true, mcpServers: true, cliStartup: true, customDomain: true }).extend({ threads: threadsPatchSchema.optional() });
|
|
15493
15502
|
var jsonObjectSchema = external_exports.record(external_exports.string(), external_exports.json());
|
|
15494
15503
|
var DATA_DIR = process.env.OMB_DATA_DIR ?? join2(homedir2(), ".openmausbot");
|
|
15495
15504
|
var LEGACY_DATA_DIR = join2(homedir2(), ".opengrokbot");
|
package/enterprise/README.md
CHANGED
|
@@ -5,24 +5,42 @@ folder has its own [LICENSE](./LICENSE); everything outside it is Apache 2.0.
|
|
|
5
5
|
|
|
6
6
|
**Delete this folder and you have the open-source edition.** Core only
|
|
7
7
|
reaches the layer through one hook point, `server/enterprise.ts`, which
|
|
8
|
-
loads `enterprise/server/index.ts`
|
|
9
|
-
open-source edition. No core file imports anything
|
|
8
|
+
loads `enterprise/server/index.ts` (or the bundled `index.js`) if it exists
|
|
9
|
+
and otherwise reports the open-source edition. No core file imports anything
|
|
10
|
+
from here.
|
|
11
|
+
|
|
12
|
+
Where core looks, in order: `OMB_ENTERPRISE_DIR` when it is set (and then
|
|
13
|
+
only there); otherwise beside the server root (a checkout's `enterprise/`,
|
|
14
|
+
the npm package's `<package>/enterprise/`), then inside it
|
|
15
|
+
(`dist-server/enterprise/`, which is all the Docker image and the packaged
|
|
16
|
+
desktop carry; `scripts/bundle-server.mjs` writes the bundled layer and this
|
|
17
|
+
LICENSE there).
|
|
10
18
|
|
|
11
19
|
## How a deployment turns enterprise
|
|
12
20
|
|
|
13
21
|
Set `OMB_LICENSE_KEY` on the server. The key is `omb1.<claims>.<signature>`:
|
|
14
22
|
the claims are visible JSON (who it is for, which entitlements, when it
|
|
15
23
|
expires), signed with an Ed25519 key whose public half is baked into
|
|
16
|
-
`server/license.ts`. Verification is offline, and one build serves
|
|
17
|
-
customer, because the key decides the feature set rather than the code.
|
|
24
|
+
`enterprise/server/license.ts`. Verification is offline, and one build serves
|
|
25
|
+
every customer, because the key decides the feature set rather than the code.
|
|
18
26
|
|
|
19
27
|
`GET /api/edition` reports the outcome:
|
|
20
28
|
|
|
21
29
|
```json
|
|
22
|
-
{ "edition": "enterprise", "customer": "Acme", "features": ["
|
|
23
|
-
{ "edition": "
|
|
30
|
+
{ "edition": "enterprise", "customer": "Acme", "features": ["budgets", "whitelabel"], "expiresAt": "2027-09-02", "expiresInDays": 12 }
|
|
31
|
+
{ "edition": "enterprise", "customer": "Acme", "features": ["budgets", "whitelabel"], "expiresAt": "2027-09-02", "expiresInDays": -2, "graceEndsAt": "2027-09-09", "notice": "OMB_LICENSE_KEY expired on 2027-09-02; enterprise features keep working until 2027-09-09 while it is renewed" }
|
|
32
|
+
{ "edition": "oss", "features": [], "notice": "enterprise layer disabled: OMB_LICENSE_KEY expired on 2027-09-02; renew it to keep enterprise features" }
|
|
24
33
|
```
|
|
25
34
|
|
|
35
|
+
`expiresInDays` is present whenever the key has an expiry; a non-admin
|
|
36
|
+
session's `/api/edition` leaves out `expiresInDays`, `graceEndsAt` and the
|
|
37
|
+
notice. From 30 days
|
|
38
|
+
before it, the server logs a warning at startup and admins see a banner in
|
|
39
|
+
Settings. After the expiry date the features keep working for a 7-day grace
|
|
40
|
+
period, with the notice above and a banner saying until when; then they stop,
|
|
41
|
+
without a restart. The key format and its signature check do not change: the
|
|
42
|
+
layer simply accepts a key that expired less than the grace period ago.
|
|
43
|
+
|
|
26
44
|
A missing, altered, or expired key does not stop an ordinary standalone
|
|
27
45
|
server: it runs the open-source edition and the notice says what to fix.
|
|
28
46
|
A workspace explicitly configured for hosted sign-in fails closed for remote
|
|
@@ -31,12 +49,15 @@ must not silently fall back to standalone email or pairing credentials.
|
|
|
31
49
|
|
|
32
50
|
## Entitlement ids
|
|
33
51
|
|
|
34
|
-
| id | grants |
|
|
35
|
-
|
|
36
|
-
| `whitelabel` | product name, tagline, accent colour, logo, favicon and support link from `brand.json` (below) |
|
|
37
|
-
| `sso` |
|
|
38
|
-
| `admin` | Settings → Workspaces and the optional hosted workspace sign-in adapter |
|
|
39
|
-
| `budgets` | per
|
|
52
|
+
| id | grants | status |
|
|
53
|
+
|---|---|---|
|
|
54
|
+
| `whitelabel` | product name, tagline, accent colour, logo, favicon and support link from `brand.json` (below) | shipped |
|
|
55
|
+
| `sso` | sign-in through a company identity provider | planned: nothing checks it yet |
|
|
56
|
+
| `admin` | Settings → Workspaces and the optional hosted workspace sign-in adapter | shipped |
|
|
57
|
+
| `budgets` | one monthly spend limit for the whole workspace, refusing new turns at the cap, with a warning percentage and admin notices (not per bot or per section) | shipped |
|
|
58
|
+
| `billing` | sell prices per model: a billable column in Usage → History and its CSV, and per-model prices that replace list prices in cost estimates | shipped |
|
|
59
|
+
|
|
60
|
+
[FEATURES](./FEATURES) is the authoritative list.
|
|
40
61
|
|
|
41
62
|
Core gates a feature with `entitled("id")` from `server/enterprise.ts`.
|
|
42
63
|
Unknown ids are carried in the key but grant nothing, so keys can be issued
|
|
@@ -14579,9 +14579,6 @@ function verifyLicenseKey(key, options = {}) {
|
|
|
14579
14579
|
// enterprise/server/workspace-access.ts
|
|
14580
14580
|
import { createHash, randomBytes, timingSafeEqual } from "node:crypto";
|
|
14581
14581
|
|
|
14582
|
-
// server/enterprise.ts
|
|
14583
|
-
import { join as join2 } from "node:path";
|
|
14584
|
-
|
|
14585
14582
|
// server/proxy-paths.ts
|
|
14586
14583
|
import { existsSync } from "node:fs";
|
|
14587
14584
|
import { dirname, join } from "node:path";
|
|
@@ -14615,7 +14612,7 @@ var layerSchema = external_exports.object({
|
|
|
14615
14612
|
features: external_exports.array(external_exports.string().min(1)),
|
|
14616
14613
|
expiresAt: external_exports.string().nullable()
|
|
14617
14614
|
});
|
|
14618
|
-
var
|
|
14615
|
+
var DAY_MS = 24 * 60 * 6e4;
|
|
14619
14616
|
function hostedWorkspaceConfiguration(env = process.env) {
|
|
14620
14617
|
try {
|
|
14621
14618
|
const origin = (raw) => {
|
|
@@ -14934,9 +14931,12 @@ function createWorkspaceAccess(options) {
|
|
|
14934
14931
|
}
|
|
14935
14932
|
|
|
14936
14933
|
// enterprise/server/index.ts
|
|
14934
|
+
var MAX_GRACE_DAYS = 14;
|
|
14935
|
+
var DAY_MS2 = 24 * 60 * 6e4;
|
|
14937
14936
|
function register(options) {
|
|
14938
14937
|
if (!options.licenseKey) return null;
|
|
14939
|
-
const
|
|
14938
|
+
const graceDays = Math.min(MAX_GRACE_DAYS, Math.max(0, Number.isFinite(options.graceDays) ? options.graceDays : 0));
|
|
14939
|
+
const claims = verifyLicenseKey(options.licenseKey, { now: new Date((options.now ?? Date.now()) - graceDays * DAY_MS2) });
|
|
14940
14940
|
return { customer: claims.customer, features: claims.features, expiresAt: claims.expires };
|
|
14941
14941
|
}
|
|
14942
14942
|
export {
|