@chibitek/chibi 0.1.172 → 0.1.174

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.
Files changed (87) hide show
  1. package/dist/assets/{abnfDiagram-O67JEVCF-CGoW52MW.js → abnfDiagram-O67JEVCF-BVDndX1g.js} +1 -1
  2. package/dist/assets/{arc-DEkKLw4F.js → arc-WduS6wYB.js} +1 -1
  3. package/dist/assets/{architectureDiagram-NJMV4G6O-Cyi6MYs6.js → architectureDiagram-NJMV4G6O-CYK9LkCf.js} +1 -1
  4. package/dist/assets/{blockDiagram-BEXU5L5S-CddA0wa_.js → blockDiagram-BEXU5L5S-BMj-aPW9.js} +1 -1
  5. package/dist/assets/{c4Diagram-YGBWAQC7-Dg8q9n90.js → c4Diagram-YGBWAQC7-cXYIStgL.js} +1 -1
  6. package/dist/assets/channel-TratrwmM.js +1 -0
  7. package/dist/assets/{chunk-2Q5K7J3B-BSMub34c.js → chunk-2Q5K7J3B-CZ_nCppA.js} +1 -1
  8. package/dist/assets/{chunk-3FUC2YCW--Xc7Up5y.js → chunk-3FUC2YCW-C3wRAbtM.js} +2 -2
  9. package/dist/assets/{chunk-5VM5RSS4-B9Ae4f30.js → chunk-5VM5RSS4-CMvgOXJP.js} +1 -1
  10. package/dist/assets/{chunk-GTNCS2PH-Dh1To9G3.js → chunk-GTNCS2PH-9wBuLQzU.js} +1 -1
  11. package/dist/assets/{chunk-GWA4HPMP-C_5eiV2n.js → chunk-GWA4HPMP-BpJMmfAi.js} +1 -1
  12. package/dist/assets/{chunk-JWPE2WC7-5wQuPsks.js → chunk-JWPE2WC7-BnM06ABv.js} +1 -1
  13. package/dist/assets/{chunk-NETBCI7D-BGXS05ur.js → chunk-NETBCI7D-CjjiiXiT.js} +1 -1
  14. package/dist/assets/{chunk-WEXAMYUT-ClIMhmD5.js → chunk-WEXAMYUT-D3heHHZs.js} +1 -1
  15. package/dist/assets/{chunk-XXDRQBXY-CcKs11-L.js → chunk-XXDRQBXY-n_P41ZlM.js} +1 -1
  16. package/dist/assets/{classDiagram-v2-NBCMYWYE-BCiLckGU.js → classDiagram-v2-NBCMYWYE-Dz60Ek-6.js} +1 -1
  17. package/dist/assets/{cose-bilkent-JH36ORCC-JyAqT-ND.js → cose-bilkent-JH36ORCC-BCt6vBi9.js} +1 -1
  18. package/dist/assets/{cynefin-OW5HDTMX-BznovZj0.js → cynefin-OW5HDTMX-U0uq4EAQ.js} +1 -1
  19. package/dist/assets/{cynefinDiagram-VND7K2PF-BDRrTIEB.js → cynefinDiagram-VND7K2PF-CaQX0eUJ.js} +1 -1
  20. package/dist/assets/{dagre-6A5THRUB-BbWguhLj.js → dagre-6A5THRUB-DlCMESYH.js} +1 -1
  21. package/dist/assets/{diagram-22UHCM2B-BMk1KTBr.js → diagram-22UHCM2B-Cl1xmlTD.js} +1 -1
  22. package/dist/assets/{diagram-3UASUU5V-ChnEP2in.js → diagram-3UASUU5V-Cus3CPg7.js} +1 -1
  23. package/dist/assets/{diagram-ATOU4E4O-C78imnTV.js → diagram-ATOU4E4O-i06rMvae.js} +1 -1
  24. package/dist/assets/{diagram-CDSNMT55-Dekx02f_.js → diagram-CDSNMT55-CUM5_heN.js} +1 -1
  25. package/dist/assets/{diagram-MLGK6HIB-D2__fPwe.js → diagram-MLGK6HIB-B5NKRruo.js} +1 -1
  26. package/dist/assets/{diagram-MPIPVDR6-C9l7MZm7.js → diagram-MPIPVDR6-CAumAcGl.js} +1 -1
  27. package/dist/assets/{ebnfDiagram-ZINNZB2B-D4x0h3XT.js → ebnfDiagram-ZINNZB2B-B19d7d8l.js} +1 -1
  28. package/dist/assets/{elk-276RUBZZ-twChz5io.js → elk-276RUBZZ-NJEpfRWi.js} +1 -1
  29. package/dist/assets/{erDiagram-OPXOYQCR-BXEKWWMq.js → erDiagram-OPXOYQCR-BExk6CHc.js} +1 -1
  30. package/dist/assets/{flowDiagram-KWPJA3E3-Ct-XrJMr.js → flowDiagram-KWPJA3E3-ClExQ_p0.js} +1 -1
  31. package/dist/assets/{ganttDiagram-FUAMR5RP-Bn92lxCs.js → ganttDiagram-FUAMR5RP-1MeM9sSl.js} +1 -1
  32. package/dist/assets/{gitGraphDiagram-X574FWY7-Dvfjo7cn.js → gitGraphDiagram-X574FWY7-Tw9Dudpa.js} +1 -1
  33. package/dist/assets/{index-DvneZE6Z.js → index-KYHldywn.js} +140 -140
  34. package/dist/assets/{index-CarzpTfN.js → index-qsorLr2x.js} +1 -1
  35. package/dist/assets/{infoDiagram-VRGFBTTK-MJ14OyNX.js → infoDiagram-VRGFBTTK-ChU2tjvl.js} +1 -1
  36. package/dist/assets/{ishikawaDiagram-OU5B5YK6-nf9xhTNX.js → ishikawaDiagram-OU5B5YK6-BeTbrX2Q.js} +1 -1
  37. package/dist/assets/{journeyDiagram-ZHPQQLJL-DqfK6X2e.js → journeyDiagram-ZHPQQLJL-B7ijaWBD.js} +1 -1
  38. package/dist/assets/{kanban-definition-PNTS6WVX-CjUR1QYT.js → kanban-definition-PNTS6WVX-JBmK2F1r.js} +1 -1
  39. package/dist/assets/{linear-dPqGsZwL.js → linear-B7FXe3Ue.js} +1 -1
  40. package/dist/assets/{mermaid.core-zL0DLPAI.js → mermaid.core-BPlfZpqv.js} +5 -5
  41. package/dist/assets/{mindmap-definition-NLK3R4M7-C1-Jqg3_.js → mindmap-definition-NLK3R4M7-CmT3S5QR.js} +1 -1
  42. package/dist/assets/{pegDiagram-GJSIUBJH-CFlvuAHC.js → pegDiagram-GJSIUBJH-CFFHIcdQ.js} +1 -1
  43. package/dist/assets/{pieDiagram-5QR66LMP-BvyT0IgF.js → pieDiagram-5QR66LMP-yTiPmXRV.js} +1 -1
  44. package/dist/assets/{quadrantDiagram-O4NWA36T-bg7JeR2c.js → quadrantDiagram-O4NWA36T-Cw8u7esm.js} +1 -1
  45. package/dist/assets/{railroadDiagram-XR7U4H2S-dF2Nqim8.js → railroadDiagram-XR7U4H2S-BfKggsOW.js} +1 -1
  46. package/dist/assets/{requirementDiagram-PLB6GJNP-CwVu_Or6.js → requirementDiagram-PLB6GJNP-Cf3n79jF.js} +1 -1
  47. package/dist/assets/{sankeyDiagram-IPEJSGJF-wBC3-mRy.js → sankeyDiagram-IPEJSGJF-B2NkSZig.js} +1 -1
  48. package/dist/assets/{sequenceDiagram-PO4LG4MO-Bs9lHMf-.js → sequenceDiagram-PO4LG4MO-BfFYiYK3.js} +1 -1
  49. package/dist/assets/{sizeCapture-INFHLROL-d6YiGOIQ.js → sizeCapture-INFHLROL-CZ_2nC3f.js} +1 -1
  50. package/dist/assets/{stateDiagram-v2-GCMORJYK--f6dscuE.js → stateDiagram-v2-GCMORJYK-B9jwzMXf.js} +1 -1
  51. package/dist/assets/{swimlanes-2SLR337P-CQpzBoAc.js → swimlanes-2SLR337P-Bxhafu77.js} +1 -1
  52. package/dist/assets/swimlanesDiagram-TC7HE7FX-DWNGCaH3.js +8 -0
  53. package/dist/assets/{timeline-definition-EJHVYXUP-DpoyUyqt.js → timeline-definition-EJHVYXUP-Dle5SJls.js} +1 -1
  54. package/dist/assets/{usecaseDiagram-POWQR4AR-Dg7mR3GW.js → usecaseDiagram-POWQR4AR-CgRTu9EO.js} +1 -1
  55. package/dist/assets/{vennDiagram-UO4OBE2U-CoEfTL7k.js → vennDiagram-UO4OBE2U-D7m_1z6B.js} +1 -1
  56. package/dist/assets/{wardleyDiagram-VNRHLVJA-24tIY01C.js → wardleyDiagram-VNRHLVJA-7-TzmX4L.js} +1 -1
  57. package/dist/assets/{xychartDiagram-PMCCYNJV-CsoqIRqn.js → xychartDiagram-PMCCYNJV-BVXXdviS.js} +1 -1
  58. package/dist/index.html +1 -1
  59. package/dist-server/index.js +2797 -1875
  60. package/dist-server/openmausbot.js +64 -2
  61. package/dist-server/pair-cli.js +64 -2
  62. package/dist-server/server/builtin-chibi.js +1 -1
  63. package/dist-server/server/dictation.js +8 -0
  64. package/dist-server/server/drivers/claude.js +4 -4
  65. package/dist-server/server/engine-tiers-view.js +49 -0
  66. package/dist-server/server/engine-tiers.js +37 -55
  67. package/dist-server/server/harness-import/engine-policy.js +6 -1
  68. package/dist-server/server/index.js +12 -13
  69. package/dist-server/server/oauth-account-core.js +153 -0
  70. package/dist-server/server/oauth-account-tools.js +7 -348
  71. package/dist-server/server/oauth-calendar-tools.js +551 -0
  72. package/dist-server/server/personal-bot.js +0 -26
  73. package/dist-server/server/remote-desktop.js +139 -7
  74. package/dist-server/server/routes/engine-tiers.js +12 -1
  75. package/dist-server/server/subscription-bots.js +2 -21
  76. package/dist-server/server/turn-resources.js +28 -0
  77. package/dist-server/server/workspace-backup-archive.js +138 -0
  78. package/dist-server/server/workspace-backup-http.js +50 -8
  79. package/dist-server/server/workspace-backup-private.js +83 -0
  80. package/dist-server/server/workspace-backup-secrets.js +90 -0
  81. package/dist-server/server/workspace-backup.js +171 -235
  82. package/dist-server/server/workspace-restore-paths.js +186 -0
  83. package/dist-server/shared/oauth-providers.js +2 -1
  84. package/dist-server/shared/provider-accounts.js +29 -0
  85. package/package.json +1 -1
  86. package/dist/assets/channel-Dda8O6gd.js +0 -1
  87. package/dist/assets/swimlanesDiagram-TC7HE7FX-C1ko4o6t.js +0 -8
@@ -0,0 +1,83 @@
1
+ // Company backups (electron/company-backups.mjs) leave the person's Private
2
+ // Bot out: its record, threads, messages, memory, folders and attachments.
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { join } from "node:path";
5
+ import { DatabaseSync } from "node:sqlite";
6
+ function record(value) {
7
+ return value !== null && typeof value === "object" && !Array.isArray(value);
8
+ }
9
+ /** The Private Bot's ids and thread ids in a data folder, from bots.json. */
10
+ export function privateBotIds(dataDir) {
11
+ const botIds = new Set();
12
+ const threadIds = new Set();
13
+ const path = join(dataDir, "bots.json");
14
+ if (!existsSync(path))
15
+ return { botIds, threadIds };
16
+ let value;
17
+ try {
18
+ value = JSON.parse(readFileSync(path, "utf8"));
19
+ }
20
+ catch {
21
+ return { botIds, threadIds };
22
+ }
23
+ if (!Array.isArray(value))
24
+ return { botIds, threadIds };
25
+ for (const bot of value) {
26
+ if (!record(bot) || bot.personal !== true || typeof bot.id !== "string")
27
+ continue;
28
+ botIds.add(bot.id);
29
+ if (typeof bot.threadId === "string")
30
+ threadIds.add(bot.threadId);
31
+ if (Array.isArray(bot.tasks))
32
+ for (const task of bot.tasks)
33
+ if (record(task) && typeof task.threadId === "string")
34
+ threadIds.add(task.threadId);
35
+ }
36
+ return { botIds, threadIds };
37
+ }
38
+ /** Whether a data-folder path belongs to the Private Bot: a folder or file
39
+ * named after its id or one of its threads, anywhere below the top level
40
+ * (workspaces/<id>, task-workspaces/<id>, events/<thread>.jsonl, ...). */
41
+ export function privateBotPath(path, ids) {
42
+ if (ids.size === 0)
43
+ return false;
44
+ const parts = path.split("/");
45
+ return parts.slice(1).some((part) => {
46
+ const stem = part.split(".")[0] ?? part;
47
+ return ids.has(part) || ids.has(stem);
48
+ });
49
+ }
50
+ /** Remove the Private Bot's rows from a copy of the message database, and
51
+ * return the attachment names its messages referenced. */
52
+ export function scrubPrivateMessages(dbPath, botIds, threadIds) {
53
+ const attachments = new Set();
54
+ if (!existsSync(dbPath) || (botIds.size === 0 && threadIds.size === 0))
55
+ return attachments;
56
+ const db = new DatabaseSync(dbPath);
57
+ try {
58
+ const threads = [...threadIds];
59
+ const bots = [...botIds];
60
+ const tables = new Set(db.prepare("SELECT name FROM sqlite_master WHERE type='table'").all().map((row) => String(row.name)));
61
+ const marks = (count) => Array.from({ length: count }, () => "?").join(", ");
62
+ if (threads.length && tables.has("messages")) {
63
+ for (const row of db.prepare(`SELECT json FROM messages WHERE thread_id IN (${marks(threads.length)})`).all(...threads)) {
64
+ for (const match of String(row.json).matchAll(/\/api\/attachments\/([A-Za-z0-9._-]{1,200})/g))
65
+ attachments.add(match[1]);
66
+ }
67
+ db.prepare(`DELETE FROM messages WHERE thread_id IN (${marks(threads.length)})`).run(...threads);
68
+ }
69
+ if (threads.length && tables.has("thread_state"))
70
+ db.prepare(`DELETE FROM thread_state WHERE thread_id IN (${marks(threads.length)})`).run(...threads);
71
+ if (tables.has("chat_followups") && (threads.length || bots.length)) {
72
+ db.prepare(`DELETE FROM chat_followups WHERE thread_id IN (${marks(threads.length || 1)}) OR owner_id IN (${marks(bots.length || 1)})`)
73
+ .run(...(threads.length ? threads : [""]), ...(bots.length ? bots : [""]));
74
+ }
75
+ if (bots.length && tables.has("memory_files"))
76
+ db.prepare(`DELETE FROM memory_files WHERE bot_id IN (${marks(bots.length)})`).run(...bots);
77
+ db.exec("VACUUM");
78
+ }
79
+ finally {
80
+ db.close();
81
+ }
82
+ return attachments;
83
+ }
@@ -0,0 +1,90 @@
1
+ // Secrets in an encrypted workspace backup. Two kinds travel:
2
+ // - data-folder files that hold credentials (provider login homes, instance
3
+ // keys, saved runtimes), as ordinary archive entries; and
4
+ // - the desktop's secure-store entries and native vault key, as one
5
+ // secrets.json beside the manifest, read from and handed back to the
6
+ // desktop app over its private port (electron/workspace-restore-secrets.mjs).
7
+ // Neither is ever written into an unencrypted backup.
8
+ import { randomUUID } from "node:crypto";
9
+ import { existsSync, readFileSync } from "node:fs";
10
+ import { join } from "node:path";
11
+ import { writeFileAtomic } from "./atomic.js";
12
+ import { WORKSPACE_SECRETS_REQUEST, WORKSPACE_SECRETS_RESULT } from "../electron/workspace-restore-secrets.mjs";
13
+ /** Top-level data-folder entries that only a secrets backup carries. */
14
+ export const SECRET_TOP_LEVEL = new Set(["providers", "workspace-credentials.json", "instance-keys.json", "external-runtimes.json"]);
15
+ /** The native vault's key file is sealed by this computer's keychain and is
16
+ * unreadable anywhere else; its raw record travels in secrets.json. */
17
+ export function secretWorkspacePath(path) {
18
+ return SECRET_TOP_LEVEL.has(path.split("/")[0]) && path !== "providers/native-vault/key.bin";
19
+ }
20
+ export function validSecretsBundle(value) {
21
+ if (!value || typeof value !== "object" || Array.isArray(value))
22
+ return false;
23
+ const bundle = value;
24
+ const key = bundle.vaultKey;
25
+ return Object.keys(bundle).every((name) => name === "credentials" || name === "vaultKey") &&
26
+ !!bundle.credentials && typeof bundle.credentials === "object" && !Array.isArray(bundle.credentials) &&
27
+ (key === null || (!!key && key.version === 1 && typeof key.ownerId === "string" && typeof key.key === "string" && /^[0-9a-f]{64}$/.test(key.key)));
28
+ }
29
+ let desktop = null;
30
+ /** The desktop's secure store, or null on a headless or development server. */
31
+ export function desktopWorkspaceSecrets() { return desktop; }
32
+ /** Wire the private port, then finish a restore this boot just applied: the
33
+ * desktop installs the waiting secrets and relaunches the app. The outcome
34
+ * goes on the restore receipt so Settings can say what needs signing in. */
35
+ export function installWorkspaceSecrets(port, dataDir, restore) {
36
+ if (!port) {
37
+ // A server without the desktop app cannot install the credential store.
38
+ if (restore.restored && restore.id && restore.summary?.secrets)
39
+ markRestoreSecrets(dataDir, restore, "failed");
40
+ return;
41
+ }
42
+ const waiting = new Map();
43
+ port.on("message", (event) => {
44
+ const message = event?.data;
45
+ if (message?.type !== WORKSPACE_SECRETS_RESULT || typeof message.requestId !== "string")
46
+ return;
47
+ waiting.get(message.requestId)?.(message);
48
+ });
49
+ const request = (body) => new Promise((resolve, reject) => {
50
+ const requestId = randomUUID();
51
+ const timer = setTimeout(() => { waiting.delete(requestId); reject(new Error("The desktop app did not answer. Try again.")); }, 30_000);
52
+ waiting.set(requestId, (message) => {
53
+ clearTimeout(timer);
54
+ waiting.delete(requestId);
55
+ if (message.ok === true)
56
+ resolve(message);
57
+ else
58
+ reject(new Error(typeof message.error === "string" ? message.error : "The desktop app could not use its secure credential store."));
59
+ });
60
+ port.postMessage({ type: WORKSPACE_SECRETS_REQUEST, requestId, ...body });
61
+ });
62
+ desktop = {
63
+ async export() {
64
+ const { secrets } = await request({ action: "export" });
65
+ if (!validSecretsBundle(secrets))
66
+ throw new Error("The desktop app returned unreadable secrets.");
67
+ return secrets;
68
+ },
69
+ async stage(id, secrets) { await request({ action: "stage", id, secrets }); },
70
+ async apply(id) { return (await request({ action: "apply", id })).applied === true; },
71
+ };
72
+ if (restore.restored && restore.id && restore.summary?.secrets) {
73
+ void desktop.apply(restore.id).then((applied) => markRestoreSecrets(dataDir, restore, applied ? "applied" : "failed"), (error) => {
74
+ console.error(`[workspace-restore] secrets were not installed: ${error instanceof Error ? error.message : String(error)}`);
75
+ markRestoreSecrets(dataDir, restore, "failed");
76
+ });
77
+ }
78
+ }
79
+ /** Record on the receipt (and this boot's copy of it) whether the saved
80
+ * credentials went in, so Settings can say what needs signing in again. */
81
+ export function markRestoreSecrets(dataDir, restore, outcome) {
82
+ restore.secrets = outcome;
83
+ const path = join(dataDir, ".backups", "last-restore.json");
84
+ if (!existsSync(path))
85
+ return;
86
+ const receipt = JSON.parse(readFileSync(path, "utf8"));
87
+ if (!receipt || typeof receipt !== "object" || receipt.id !== restore.id)
88
+ return;
89
+ writeFileAtomic(path, JSON.stringify({ ...receipt, secrets: outcome }), { mode: 0o600 });
90
+ }