volute 0.44.0 → 0.45.2
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/{activity-events-OMCSM7XW.js → activity-events-BUR2RYTJ.js} +2 -2
- package/dist/{ai-service-7PHSRDMO.js → ai-service-UODCCE4O.js} +3 -3
- package/dist/{archive-6R4TZMYI.js → archive-WS2L2VIQ.js} +2 -2
- package/dist/{auth-FRZJVQCS.js → auth-FLAEXXZK.js} +3 -3
- package/dist/{avatar-image-BNWEXSA2.js → avatar-image-6KY6UU4D.js} +3 -3
- package/dist/backup-TST5C2YN.js +381 -0
- package/dist/{chat-I4EDDIQC.js → chat-76MRWWQX.js} +2 -2
- package/dist/{chunk-5AHYQHNT.js → chunk-4JOQZPCE.js} +3 -2
- package/dist/{chunk-2BONPXAF.js → chunk-6EMWJZBK.js} +1 -1
- package/dist/{chunk-ZMIMSIIT.js → chunk-7C44R625.js} +1 -1
- package/dist/{chunk-I2Y2YHIO.js → chunk-7ZUB63PS.js} +4 -4
- package/dist/{chunk-LAXUUY7O.js → chunk-A7WQZKOU.js} +2 -2
- package/dist/{chunk-H7IYFRAL.js → chunk-ALKYQULU.js} +10 -5
- package/dist/{chunk-KP3KWNG6.js → chunk-CDPBTTZO.js} +2 -2
- package/dist/{chunk-SQL7M4HJ.js → chunk-DRJ24GXK.js} +2 -2
- package/dist/{chunk-HVU45COX.js → chunk-EJVPTVTI.js} +1 -1
- package/dist/{chunk-PNV24SEP.js → chunk-F7H6ATM4.js} +14 -2
- package/dist/{chunk-7FT24JBQ.js → chunk-FR6S2KNN.js} +10 -10
- package/dist/chunk-FXORA5JG.js +327 -0
- package/dist/{chunk-3ERIL673.js → chunk-H2X54EHC.js} +1 -1
- package/dist/{chunk-J47TIYHA.js → chunk-IHKGWTGT.js} +1 -1
- package/dist/{chunk-3GYVW2X3.js → chunk-JZ62SYWR.js} +1 -1
- package/dist/{chunk-EQZD4YU3.js → chunk-NYC5U6K7.js} +9 -9
- package/dist/{chunk-FZMEVCWC.js → chunk-OP4JG2BS.js} +9 -6
- package/dist/{chunk-CU6OFXMM.js → chunk-PFZBNKUH.js} +9 -0
- package/dist/{chunk-QMJJWTNL.js → chunk-QCN24XEN.js} +1 -1
- package/dist/{chunk-7KWANSLX.js → chunk-QNQMSWZE.js} +3 -3
- package/dist/{chunk-UMI4UIJG.js → chunk-R77O2WMK.js} +1 -1
- package/dist/{chunk-IEWZ7VD7.js → chunk-RRNXJOKB.js} +2 -2
- package/dist/{chunk-FHWUQZXE.js → chunk-RXEEYDIB.js} +1 -1
- package/dist/{chunk-CYI534DJ.js → chunk-T6HYVHPG.js} +2 -2
- package/dist/{chunk-Q2XBKQ2D.js → chunk-TQJ6ZYVY.js} +2 -2
- package/dist/{chunk-NF75HPNR.js → chunk-UYLGEDVD.js} +40 -15
- package/dist/{chunk-OMETFX5H.js → chunk-YT7PEESJ.js} +261 -102
- package/dist/{chunk-5GT7URXJ.js → chunk-ZDZISKCL.js} +1 -1
- package/dist/cli.js +21 -15
- package/dist/{cloud-sync-6WJ7WFYD.js → cloud-sync-3OJOPZRT.js} +16 -16
- package/dist/{conversations-WAJYZKOC.js → conversations-JZTD6KLR.js} +3 -3
- package/dist/{create-YZIV5OJC.js → create-IOV4GCRX.js} +1 -1
- package/dist/{daemon-restart-OUJVINXV.js → daemon-restart-TIHKVVVA.js} +6 -6
- package/dist/daemon.js +562 -321
- package/dist/{db-JFLCJCUG.js → db-MF2JNRUW.js} +1 -1
- package/dist/delivery-manager-VDVKVA46.js +32 -0
- package/dist/{delivery-router-GODSIS62.js → delivery-router-N4A7ZC5T.js} +2 -2
- package/dist/{down-XCAZXWLB.js → down-U2CZ23M4.js} +4 -4
- package/dist/echo-text-6JJOPUD4.js +32 -0
- package/dist/{exec-4GWHAHS3.js → exec-G3ZRST4Z.js} +2 -2
- package/dist/{export-ID7YUSLZ.js → export-GGIVO76O.js} +2 -2
- package/dist/{extensions-3QNDGW5E.js → extensions-JONTW2HF.js} +16 -16
- package/dist/{files-BQ2WB5KC.js → files-4LN3EN7Q.js} +2 -2
- package/dist/{import-SKID37QX.js → import-42YNQBF4.js} +5 -5
- package/dist/{isolation-5MB3J73F.js → isolation-YMGZZ4E5.js} +2 -2
- package/dist/{join-RXPXGV4L.js → join-ZJV7W6MO.js} +4 -0
- package/dist/{login-LM4NF4ZB.js → login-M6OJUPQ2.js} +1 -1
- package/dist/{logout-CTJVIZGA.js → logout-WQBWO77G.js} +1 -1
- package/dist/message-delivery-3C65ZI6L.js +34 -0
- package/dist/{mind-MI7Z6KM2.js → mind-DWB6XYCH.js} +7 -7
- package/dist/{mind-activity-tracker-BGHJE7XA.js → mind-activity-tracker-POBLU3LC.js} +3 -3
- package/dist/mind-service-3F4I46CI.js +36 -0
- package/dist/{package-5B4XDTJH.js → package-A7KXT67Q.js} +1 -1
- package/dist/{registry-NUJAGLQJ.js → registry-OUZBZ3Q4.js} +5 -1
- package/dist/{sandbox-IOPWWILM.js → sandbox-ZJ7QA6Z6.js} +3 -3
- package/dist/scheduler-P6DXLLXI.js +30 -0
- package/dist/{seed-UUPVQWFB.js → seed-HCP5NYKH.js} +1 -1
- package/dist/{seed-cmd-7XPKDQUC.js → seed-cmd-ILOGNIFB.js} +2 -2
- package/dist/{seed-create-IZ4M5ESO.js → seed-create-OURS2LS4.js} +3 -3
- package/dist/{seed-sprout-POJXHJWV.js → seed-sprout-ELDFDAN6.js} +7 -7
- package/dist/{send-O6W53VBM.js → send-AAIOPJAV.js} +2 -2
- package/dist/{service-AQVPUANO.js → service-UOCLXDWR.js} +3 -3
- package/dist/{service-install-4QNUDKLM.js → service-install-4HHFDDWY.js} +4 -4
- package/dist/{setup-5GCO3CUB.js → setup-DQM5VPY4.js} +6 -6
- package/dist/{setup-MLRKNP7Y.js → setup-Y2EJI3GG.js} +2 -2
- package/dist/skills/imagegen/scripts/imagegen.ts +100 -40
- package/dist/skills/memory/SKILL.md +2 -1
- package/dist/skills/orientation/SKILL.md +1 -1
- package/dist/skills/plan-coordinator/SKILL.md +2 -2
- package/dist/skills/volute-admin/SKILL.md +9 -6
- package/dist/skills/volute-mind/SKILL.md +20 -17
- package/dist/skills/volute-mind/references/extensions.md +5 -3
- package/dist/skills/volute-mind/references/integrations.md +2 -2
- package/dist/skills/volute-mind/references/routing.md +19 -23
- package/dist/skills/volute-mind/references/variants.md +10 -8
- package/dist/{skills-775C7QFF.js → skills-BKINFL7W.js} +4 -4
- package/dist/sleep-manager-HCUH4PM4.js +34 -0
- package/dist/{spirit-IK5OYWMV.js → spirit-DBTIW7P4.js} +7 -7
- package/dist/{sprout-ZY5QGOEL.js → sprout-W3KC7UGK.js} +1 -1
- package/dist/{src-XFY3XDD6.js → src-OJHARHTF.js} +28 -17
- package/dist/{status-E5DQNCAO.js → status-SWRVGXBI.js} +4 -4
- package/dist/system-chat-XOALE2RD.js +36 -0
- package/dist/{tailscale-QAWVKQKU.js → tailscale-3XOKOW7T.js} +1 -1
- package/dist/{turn-tracker-RWZMY7M6.js → turn-tracker-2W6Q2NSR.js} +6 -4
- package/dist/{up-FLCDR2UB.js → up-FTK7CTO3.js} +5 -5
- package/dist/{update-7TYVH5FM.js → update-SWAYZRWJ.js} +4 -4
- package/dist/{update-check-VSCSJ7KX.js → update-check-PQ2MZ47K.js} +2 -2
- package/dist/{upgrade-37DAGF6H.js → upgrade-NWAZ7MLD.js} +1 -1
- package/dist/{version-notify-B67N35A3.js → version-notify-3XMAIQTE.js} +17 -17
- package/dist/{volute-config-TS62GS6A.js → volute-config-A52FHWKM.js} +5 -1
- package/dist/web-assets/assets/{index-dJdNzAPn.css → index-B1JBQv2m.css} +1 -1
- package/dist/web-assets/assets/index-Bc2m8gRC.js +86 -0
- package/dist/web-assets/index.html +2 -2
- package/package.json +1 -1
- package/packages/extensions/plan/skills/plan/SKILL.md +1 -1
- package/templates/_base/.init/.config/prompts.json +1 -1
- package/templates/_base/.init/.local/hooks/startup-context.ts +0 -8
- package/templates/_base/.init/MEMORY.md +2 -1
- package/templates/_base/home/VOLUTE.md +6 -9
- package/templates/_base/src/lib/file-handler.ts +3 -3
- package/templates/_base/src/lib/router.ts +21 -25
- package/templates/_base/src/lib/startup.ts +3 -1
- package/templates/_base/src/lib/types.ts +2 -2
- package/templates/claude/.init/CLAUDE.md +1 -1
- package/templates/claude/src/agent.ts +97 -12
- package/templates/claude/src/lib/message-channel.ts +23 -0
- package/templates/claude/src/lib/session-reaper.ts +37 -0
- package/templates/claude/src/lib/stream-consumer.ts +7 -4
- package/templates/claude/src/server.ts +1 -0
- package/templates/codex/.init/AGENTS.md +4 -2
- package/templates/codex/src/agent.ts +31 -13
- package/templates/pi/.init/MINDS.md +4 -2
- package/templates/pi/src/agent.ts +18 -7
- package/templates/pi/src/lib/event-handler.ts +6 -2
- package/dist/delivery-manager-TEVOHX5W.js +0 -32
- package/dist/echo-text-T7ZA5EYD.js +0 -32
- package/dist/message-delivery-2EA5LLMD.js +0 -34
- package/dist/mind-service-S3SY7HAM.js +0 -36
- package/dist/scheduler-CXWQ6Z4E.js +0 -30
- package/dist/sleep-manager-HINI6Y46.js +0 -34
- package/dist/system-chat-4DQZOEZI.js +0 -34
- package/dist/web-assets/assets/index-Domoz5Cg.js +0 -79
- package/templates/_base/.init/.config/hooks/pre-prompt/session-activity.ts +0 -40
|
@@ -3,9 +3,9 @@ import {
|
|
|
3
3
|
broadcast,
|
|
4
4
|
publish,
|
|
5
5
|
subscribe
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-7C44R625.js";
|
|
7
7
|
import "./chunk-T2TP6ZC6.js";
|
|
8
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-ALKYQULU.js";
|
|
9
9
|
import "./chunk-ZV7MFISX.js";
|
|
10
10
|
import "./chunk-K3NQKI34.js";
|
|
11
11
|
export {
|
|
@@ -25,10 +25,10 @@ import {
|
|
|
25
25
|
setProviderRefreshHook,
|
|
26
26
|
setUtilityModel,
|
|
27
27
|
unqualifyModelId
|
|
28
|
-
} from "./chunk-
|
|
29
|
-
import "./chunk-
|
|
28
|
+
} from "./chunk-IHKGWTGT.js";
|
|
29
|
+
import "./chunk-F7H6ATM4.js";
|
|
30
30
|
import "./chunk-T2TP6ZC6.js";
|
|
31
|
-
import "./chunk-
|
|
31
|
+
import "./chunk-ALKYQULU.js";
|
|
32
32
|
import "./chunk-ZV7MFISX.js";
|
|
33
33
|
import "./chunk-K3NQKI34.js";
|
|
34
34
|
export {
|
|
@@ -5,8 +5,8 @@ import {
|
|
|
5
5
|
extractArchive,
|
|
6
6
|
isHomeOnlyArchive,
|
|
7
7
|
readManifest
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-QCN24XEN.js";
|
|
9
|
+
import "./chunk-ALKYQULU.js";
|
|
10
10
|
import "./chunk-ZV7MFISX.js";
|
|
11
11
|
import "./chunk-K3NQKI34.js";
|
|
12
12
|
export {
|
|
@@ -17,10 +17,10 @@ import {
|
|
|
17
17
|
syncMindProfile,
|
|
18
18
|
updateUserProfile,
|
|
19
19
|
verifyUser
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-T6HYVHPG.js";
|
|
21
|
+
import "./chunk-7C44R625.js";
|
|
22
22
|
import "./chunk-T2TP6ZC6.js";
|
|
23
|
-
import "./chunk-
|
|
23
|
+
import "./chunk-ALKYQULU.js";
|
|
24
24
|
import "./chunk-ZV7MFISX.js";
|
|
25
25
|
import "./chunk-K3NQKI34.js";
|
|
26
26
|
export {
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
AVATAR_DIM,
|
|
4
4
|
migrateAvatarSizes,
|
|
5
5
|
normalizeAvatar
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-DRJ24GXK.js";
|
|
7
|
+
import "./chunk-PFZBNKUH.js";
|
|
8
8
|
import "./chunk-T2TP6ZC6.js";
|
|
9
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-ALKYQULU.js";
|
|
10
10
|
import "./chunk-ZV7MFISX.js";
|
|
11
11
|
import "./chunk-K3NQKI34.js";
|
|
12
12
|
export {
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
stopDaemon
|
|
4
|
+
} from "./chunk-RRNXJOKB.js";
|
|
5
|
+
import {
|
|
6
|
+
promptLine,
|
|
7
|
+
promptPassword
|
|
8
|
+
} from "./chunk-VHWGEJ4V.js";
|
|
9
|
+
import {
|
|
10
|
+
daemonFetch
|
|
11
|
+
} from "./chunk-RBNMDAKB.js";
|
|
12
|
+
import {
|
|
13
|
+
getClient,
|
|
14
|
+
urlOf
|
|
15
|
+
} from "./chunk-LOPXTW6H.js";
|
|
16
|
+
import {
|
|
17
|
+
command,
|
|
18
|
+
subcommands
|
|
19
|
+
} from "./chunk-TXSA4Q3V.js";
|
|
20
|
+
import "./chunk-O7IGP7ZW.js";
|
|
21
|
+
import {
|
|
22
|
+
RESTIC_INSTALL_HINT,
|
|
23
|
+
resticVersion,
|
|
24
|
+
restoreStagedDb
|
|
25
|
+
} from "./chunk-FXORA5JG.js";
|
|
26
|
+
import {
|
|
27
|
+
getServiceMode,
|
|
28
|
+
modeLabel,
|
|
29
|
+
stopService
|
|
30
|
+
} from "./chunk-TQJ6ZYVY.js";
|
|
31
|
+
import {
|
|
32
|
+
chownMindDir,
|
|
33
|
+
exec,
|
|
34
|
+
execInherit,
|
|
35
|
+
wrapForIsolation
|
|
36
|
+
} from "./chunk-H2X54EHC.js";
|
|
37
|
+
import {
|
|
38
|
+
_resetConfigCache,
|
|
39
|
+
readGlobalConfig
|
|
40
|
+
} from "./chunk-F7H6ATM4.js";
|
|
41
|
+
import "./chunk-T2TP6ZC6.js";
|
|
42
|
+
import {
|
|
43
|
+
voluteHome,
|
|
44
|
+
voluteSystemDir
|
|
45
|
+
} from "./chunk-ALKYQULU.js";
|
|
46
|
+
import "./chunk-ZV7MFISX.js";
|
|
47
|
+
import "./chunk-K3NQKI34.js";
|
|
48
|
+
|
|
49
|
+
// src/commands/backup.ts
|
|
50
|
+
import { existsSync, readdirSync, rmSync } from "fs";
|
|
51
|
+
import { resolve } from "path";
|
|
52
|
+
function printPassphrase(password) {
|
|
53
|
+
console.log("\n\u250C\u2500 BACKUP PASSPHRASE \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
54
|
+
console.log(` ${password}`);
|
|
55
|
+
console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
|
|
56
|
+
console.log("Store this somewhere OFF this machine (password manager, paper).");
|
|
57
|
+
console.log("Without it your backups are unreadable \u2014 this is the exact");
|
|
58
|
+
console.log("scenario (lost machine) that backups exist for.\n");
|
|
59
|
+
console.log(`It is also stored in ${resolve(voluteSystemDir(), "secrets.json")}`);
|
|
60
|
+
}
|
|
61
|
+
async function apiError(res, fallback) {
|
|
62
|
+
const data = await res.json().catch(() => ({}));
|
|
63
|
+
console.error(data.error ?? `${fallback}: HTTP ${res.status}`);
|
|
64
|
+
process.exit(1);
|
|
65
|
+
}
|
|
66
|
+
var initCmd = command({
|
|
67
|
+
name: "volute backup init",
|
|
68
|
+
description: "Configure the backup repository and initialize it",
|
|
69
|
+
flags: {
|
|
70
|
+
repo: { type: "string", description: "Restic repository (path, s3:..., b2:..., sftp:...)" },
|
|
71
|
+
password: { type: "string", description: "Repository passphrase (generated if omitted)" }
|
|
72
|
+
},
|
|
73
|
+
examples: [
|
|
74
|
+
"volute backup init --repo /mnt/backups/volute",
|
|
75
|
+
"volute backup init --repo s3:s3.amazonaws.com/my-bucket/volute"
|
|
76
|
+
],
|
|
77
|
+
run: async ({ flags }) => {
|
|
78
|
+
let repo = flags.repo;
|
|
79
|
+
if (!repo) {
|
|
80
|
+
repo = (await promptLine("Repository (path or s3:/b2:/sftp: URL): ")).trim();
|
|
81
|
+
if (!repo) {
|
|
82
|
+
console.error("A repository is required.");
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const client = getClient();
|
|
87
|
+
const putRes = await daemonFetch(urlOf(client.api.backup.config.$url()), {
|
|
88
|
+
method: "PUT",
|
|
89
|
+
headers: { "Content-Type": "application/json" },
|
|
90
|
+
body: JSON.stringify({ repository: repo, password: flags.password ?? "" })
|
|
91
|
+
});
|
|
92
|
+
if (!putRes.ok) await apiError(putRes, "Failed to save backup config");
|
|
93
|
+
const initRes = await daemonFetch(urlOf(client.api.backup.init.$url()), { method: "POST" });
|
|
94
|
+
if (!initRes.ok) await apiError(initRes, "Failed to initialize repository");
|
|
95
|
+
const { password } = await initRes.json();
|
|
96
|
+
console.log(`Backup repository initialized: ${repo}`);
|
|
97
|
+
if (password) printPassphrase(password);
|
|
98
|
+
console.log("\nEnable scheduled backups with: volute backup schedule --enable");
|
|
99
|
+
console.log("Or run one now with: volute backup create");
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
var createCmd = command({
|
|
103
|
+
name: "volute backup create",
|
|
104
|
+
description: "Run a backup now",
|
|
105
|
+
flags: {},
|
|
106
|
+
run: async () => {
|
|
107
|
+
const client = getClient();
|
|
108
|
+
console.log("Running backup (this may take a while on first run)...");
|
|
109
|
+
const res = await daemonFetch(urlOf(client.api.backup.run.$url()), { method: "POST" });
|
|
110
|
+
if (!res.ok) await apiError(res, "Backup failed");
|
|
111
|
+
const summary = await res.json();
|
|
112
|
+
const addedMB = (summary.dataAdded / 1024 / 1024).toFixed(1);
|
|
113
|
+
console.log(`Snapshot ${summary.snapshotId.slice(0, 8)} created.`);
|
|
114
|
+
console.log(
|
|
115
|
+
` Files: ${summary.totalFilesProcessed} processed, ${summary.filesNew} new, ${summary.filesChanged} changed`
|
|
116
|
+
);
|
|
117
|
+
console.log(` Data added: ${addedMB} MB in ${(summary.durationMs / 1e3).toFixed(1)}s`);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
var listCmd = command({
|
|
121
|
+
name: "volute backup list",
|
|
122
|
+
description: "List backup snapshots",
|
|
123
|
+
flags: {},
|
|
124
|
+
run: async () => {
|
|
125
|
+
const client = getClient();
|
|
126
|
+
const res = await daemonFetch(urlOf(client.api.backup.snapshots.$url()));
|
|
127
|
+
if (!res.ok) await apiError(res, "Failed to list snapshots");
|
|
128
|
+
const snapshots = await res.json();
|
|
129
|
+
if (snapshots.length === 0) {
|
|
130
|
+
console.log("No snapshots yet. Run: volute backup create");
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
console.log("ID TIME HOST");
|
|
134
|
+
for (const s of snapshots) {
|
|
135
|
+
console.log(`${s.short_id} ${new Date(s.time).toLocaleString().padEnd(24)} ${s.hostname}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
var scheduleCmd = command({
|
|
140
|
+
name: "volute backup schedule",
|
|
141
|
+
description: "Enable, disable, or set the backup schedule",
|
|
142
|
+
flags: {
|
|
143
|
+
enable: { type: "boolean", description: "Enable scheduled backups" },
|
|
144
|
+
disable: { type: "boolean", description: "Disable scheduled backups" },
|
|
145
|
+
cron: { type: "string", description: 'Cron expression (default "0 3 * * *")' }
|
|
146
|
+
},
|
|
147
|
+
examples: ["volute backup schedule --enable", 'volute backup schedule --cron "30 4 * * *"'],
|
|
148
|
+
run: async ({ flags }) => {
|
|
149
|
+
const body = {};
|
|
150
|
+
if (flags.enable) body.enabled = true;
|
|
151
|
+
if (flags.disable) body.enabled = false;
|
|
152
|
+
if (flags.cron) body.schedule = flags.cron;
|
|
153
|
+
if (Object.keys(body).length === 0) {
|
|
154
|
+
console.error("Nothing to change. Use --enable, --disable, or --cron.");
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
const client = getClient();
|
|
158
|
+
const res = await daemonFetch(urlOf(client.api.backup.config.$url()), {
|
|
159
|
+
method: "PUT",
|
|
160
|
+
headers: { "Content-Type": "application/json" },
|
|
161
|
+
body: JSON.stringify(body)
|
|
162
|
+
});
|
|
163
|
+
if (!res.ok) await apiError(res, "Failed to update schedule");
|
|
164
|
+
const config = await res.json();
|
|
165
|
+
console.log(
|
|
166
|
+
`Scheduled backups ${config.enabled ? "enabled" : "disabled"} (cron: ${config.schedule})`
|
|
167
|
+
);
|
|
168
|
+
if (config.enabled && (!config.repository || !config.hasPassword)) {
|
|
169
|
+
console.log("Note: backups will NOT run until a repository is set up: volute backup init");
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
var statusCmd = command({
|
|
174
|
+
name: "volute backup status",
|
|
175
|
+
description: "Show backup configuration and last run",
|
|
176
|
+
flags: {},
|
|
177
|
+
run: async () => {
|
|
178
|
+
const client = getClient();
|
|
179
|
+
const res = await daemonFetch(urlOf(client.api.backup.status.$url()));
|
|
180
|
+
if (!res.ok) await apiError(res, "Failed to get backup status");
|
|
181
|
+
const status = await res.json();
|
|
182
|
+
console.log(`Restic: ${status.resticVersion ?? "not installed"}`);
|
|
183
|
+
if (status.installHint) console.log(` ${status.installHint}`);
|
|
184
|
+
console.log(`Repository: ${status.config.repository ?? "not configured"}`);
|
|
185
|
+
console.log(`Passphrase: ${status.config.hasPassword ? "set" : "not set"}`);
|
|
186
|
+
console.log(
|
|
187
|
+
`Schedule: ${status.config.enabled ? `enabled (${status.config.schedule})` : "disabled"}`
|
|
188
|
+
);
|
|
189
|
+
if (status.state.lastRun) {
|
|
190
|
+
console.log(`Last successful backup: ${new Date(status.state.lastRun).toLocaleString()}`);
|
|
191
|
+
if (status.state.lastSnapshotId) {
|
|
192
|
+
console.log(` Snapshot: ${status.state.lastSnapshotId.slice(0, 8)}`);
|
|
193
|
+
}
|
|
194
|
+
if (status.state.pruneError) {
|
|
195
|
+
console.log(` Retention prune failed: ${status.state.pruneError}`);
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
console.log("Last successful backup: never");
|
|
199
|
+
}
|
|
200
|
+
if (status.state.lastError) {
|
|
201
|
+
const at = status.state.lastAttempt ? ` at ${new Date(status.state.lastAttempt).toLocaleString()}` : "";
|
|
202
|
+
console.log(`Last attempt failed${at}: ${status.state.lastError}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
var restoreCmd = command({
|
|
207
|
+
name: "volute backup restore",
|
|
208
|
+
description: "Restore the whole system from a backup (stops the daemon)",
|
|
209
|
+
flags: {
|
|
210
|
+
repo: { type: "string", description: "Restic repository (defaults to configured one)" },
|
|
211
|
+
snapshot: { type: "string", description: "Snapshot ID (default: latest)" },
|
|
212
|
+
target: { type: "string", description: "Restore to this directory instead of in place" },
|
|
213
|
+
yes: { type: "boolean", description: "Skip confirmation" }
|
|
214
|
+
},
|
|
215
|
+
examples: [
|
|
216
|
+
"volute backup restore",
|
|
217
|
+
"volute backup restore --repo s3:s3.amazonaws.com/my-bucket/volute",
|
|
218
|
+
"volute backup restore --snapshot 1a2b3c4d --target /tmp/inspect"
|
|
219
|
+
],
|
|
220
|
+
run: async ({ flags }) => {
|
|
221
|
+
if (!await resticVersion()) {
|
|
222
|
+
console.error(`restic is not installed. ${RESTIC_INSTALL_HINT}`);
|
|
223
|
+
process.exit(1);
|
|
224
|
+
}
|
|
225
|
+
const backupConfig = readGlobalConfig().backup ?? {};
|
|
226
|
+
const repo = flags.repo ?? backupConfig.repository;
|
|
227
|
+
if (!repo) {
|
|
228
|
+
console.error("No repository configured. Pass --repo <repository>.");
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
let password = backupConfig.password ?? process.env.RESTIC_PASSWORD;
|
|
232
|
+
if (!password) {
|
|
233
|
+
password = await promptPassword("Repository passphrase: ");
|
|
234
|
+
if (!password) {
|
|
235
|
+
console.error("A passphrase is required.");
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
const env = {
|
|
240
|
+
...process.env,
|
|
241
|
+
...backupConfig.env,
|
|
242
|
+
RESTIC_REPOSITORY: repo,
|
|
243
|
+
RESTIC_PASSWORD: password
|
|
244
|
+
};
|
|
245
|
+
const snapshot = flags.snapshot ?? "latest";
|
|
246
|
+
if (flags.target) {
|
|
247
|
+
console.log(`Restoring snapshot ${snapshot} to ${flags.target}...`);
|
|
248
|
+
await execInherit("restic", ["restore", snapshot, "--target", flags.target], { env });
|
|
249
|
+
console.log("Done. (Inspection restore: no databases moved, no daemon touched.)");
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const home = voluteHome();
|
|
253
|
+
try {
|
|
254
|
+
const out = await exec("restic", ["snapshots", snapshot, "--json"], { env });
|
|
255
|
+
const snaps = JSON.parse(out || "[]");
|
|
256
|
+
const paths = snaps[0]?.paths ?? [];
|
|
257
|
+
if (paths.length > 0 && !paths.includes(home)) {
|
|
258
|
+
console.error(`This snapshot was taken with a different volute home:`);
|
|
259
|
+
for (const p of paths) console.error(` ${p}`);
|
|
260
|
+
console.error(`This machine's volute home is ${home}, so an in-place restore would`);
|
|
261
|
+
console.error("write to the old paths and restore nothing here. Either set VOLUTE_HOME");
|
|
262
|
+
console.error("to match, or inspect with --target and move files manually.");
|
|
263
|
+
process.exit(1);
|
|
264
|
+
}
|
|
265
|
+
} catch (err) {
|
|
266
|
+
console.error(
|
|
267
|
+
`Could not read snapshot ${snapshot}: ${err instanceof Error ? err.message : err}`
|
|
268
|
+
);
|
|
269
|
+
process.exit(1);
|
|
270
|
+
}
|
|
271
|
+
if (!flags.yes) {
|
|
272
|
+
console.log(`This restores snapshot ${snapshot} from ${repo} IN PLACE:`);
|
|
273
|
+
console.log(" - the daemon will be stopped");
|
|
274
|
+
console.log(" - current system state and mind files will be overwritten");
|
|
275
|
+
console.log(
|
|
276
|
+
" - minds wake with fresh sessions (transcripts are excluded unless includeSessions was on)"
|
|
277
|
+
);
|
|
278
|
+
const answer = (await promptLine("Continue? [y/N] ")).trim().toLowerCase();
|
|
279
|
+
if (answer !== "y" && answer !== "yes") {
|
|
280
|
+
console.log("Aborted.");
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
const mode = getServiceMode();
|
|
285
|
+
if (mode !== "manual") {
|
|
286
|
+
console.log(`Stopping volute (${modeLabel(mode)})...`);
|
|
287
|
+
try {
|
|
288
|
+
await stopService(mode);
|
|
289
|
+
} catch (err) {
|
|
290
|
+
console.error(`Failed to stop service: ${err instanceof Error ? err.message : err}`);
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
|
293
|
+
} else {
|
|
294
|
+
const result = await stopDaemon();
|
|
295
|
+
if (!result.stopped && result.reason !== "not-running") {
|
|
296
|
+
console.error("Could not stop the daemon \u2014 aborting so live databases aren't replaced.");
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
try {
|
|
301
|
+
console.log(`Restoring snapshot ${snapshot} from ${repo}...`);
|
|
302
|
+
await execInherit("restic", ["restore", snapshot, "--target", "/"], { env });
|
|
303
|
+
const systemDir = voluteSystemDir();
|
|
304
|
+
const staging = resolve(systemDir, "backup-staging");
|
|
305
|
+
const mainLive = resolve(systemDir, "volute.db");
|
|
306
|
+
if (!restoreStagedDb(resolve(staging, "volute.db"), mainLive)) {
|
|
307
|
+
console.error(`
|
|
308
|
+
FATAL: staged database not found at ${staging}/volute.db.`);
|
|
309
|
+
console.error("The snapshot does not contain a system database; whatever volute.db");
|
|
310
|
+
console.error("was on disk before this restore is still in place, and it does NOT");
|
|
311
|
+
console.error("match the restored files. Do not trust this system until you restore");
|
|
312
|
+
console.error("a snapshot that includes backup-staging/volute.db.");
|
|
313
|
+
process.exit(1);
|
|
314
|
+
}
|
|
315
|
+
console.log(`Restored database: ${mainLive}`);
|
|
316
|
+
const stagedExt = resolve(staging, "extension-data");
|
|
317
|
+
if (existsSync(stagedExt)) {
|
|
318
|
+
for (const id of readdirSync(stagedExt)) {
|
|
319
|
+
const live = resolve(systemDir, "extension-data", id, "data.db");
|
|
320
|
+
if (restoreStagedDb(resolve(stagedExt, id, "data.db"), live)) {
|
|
321
|
+
console.log(`Restored database: ${live}`);
|
|
322
|
+
} else {
|
|
323
|
+
console.error(` Warning: no staged copy for extension DB ${id} \u2014 skipped.`);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
rmSync(staging, { recursive: true, force: true });
|
|
328
|
+
} catch (err) {
|
|
329
|
+
console.error(`
|
|
330
|
+
Restore failed: ${err instanceof Error ? err.message : err}`);
|
|
331
|
+
console.error("The system is in a PARTIALLY RESTORED state (the daemon is stopped and");
|
|
332
|
+
console.error("some files may already be overwritten). Do not start the daemon.");
|
|
333
|
+
console.error("Fix the underlying problem and re-run: volute backup restore");
|
|
334
|
+
process.exit(1);
|
|
335
|
+
}
|
|
336
|
+
_resetConfigCache();
|
|
337
|
+
if (readGlobalConfig().setup?.isolation === "user") {
|
|
338
|
+
process.env.VOLUTE_ISOLATION = "user";
|
|
339
|
+
}
|
|
340
|
+
const { readAllMinds, mindDir } = await import("./registry-OUZBZ3Q4.js");
|
|
341
|
+
const seen = /* @__PURE__ */ new Set();
|
|
342
|
+
for (const mind of await readAllMinds()) {
|
|
343
|
+
const dir = mind.dir ?? mindDir(mind.name);
|
|
344
|
+
if (seen.has(dir) || !existsSync(resolve(dir, "package.json"))) continue;
|
|
345
|
+
seen.add(dir);
|
|
346
|
+
console.log(`Installing dependencies for ${mind.name}...`);
|
|
347
|
+
try {
|
|
348
|
+
await chownMindDir(dir, mind.name);
|
|
349
|
+
const [cmd2, args] = await wrapForIsolation(
|
|
350
|
+
"npm",
|
|
351
|
+
["install", "--no-audit", "--no-fund"],
|
|
352
|
+
mind.name
|
|
353
|
+
);
|
|
354
|
+
await exec(cmd2, args, { cwd: dir });
|
|
355
|
+
} catch (err) {
|
|
356
|
+
console.error(
|
|
357
|
+
` npm install failed for ${mind.name}: ${err instanceof Error ? err.message : err}`
|
|
358
|
+
);
|
|
359
|
+
console.error(` Run it manually: cd ${dir} && npm install`);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
console.log("\nRestore complete. Start the daemon with: volute up");
|
|
363
|
+
console.log("Minds' memory and history are restored from the snapshot.");
|
|
364
|
+
}
|
|
365
|
+
});
|
|
366
|
+
var cmd = subcommands({
|
|
367
|
+
name: "volute backup",
|
|
368
|
+
description: "Back up and restore the whole volute system (restic-based)",
|
|
369
|
+
commands: {
|
|
370
|
+
init: { description: "Configure and initialize the backup repository", run: initCmd.execute },
|
|
371
|
+
create: { description: "Run a backup now", run: createCmd.execute },
|
|
372
|
+
list: { description: "List snapshots", run: listCmd.execute },
|
|
373
|
+
schedule: { description: "Enable/disable/set the backup schedule", run: scheduleCmd.execute },
|
|
374
|
+
status: { description: "Show backup configuration and last run", run: statusCmd.execute },
|
|
375
|
+
restore: { description: "Restore the system from a backup", run: restoreCmd.execute }
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
var run = cmd.execute;
|
|
379
|
+
export {
|
|
380
|
+
run
|
|
381
|
+
};
|
|
@@ -12,7 +12,7 @@ var cmd = subcommands({
|
|
|
12
12
|
commands: {
|
|
13
13
|
send: {
|
|
14
14
|
description: "Send a message",
|
|
15
|
-
run: (args) => import("./send-
|
|
15
|
+
run: (args) => import("./send-AAIOPJAV.js").then((m) => m.run(args))
|
|
16
16
|
},
|
|
17
17
|
list: {
|
|
18
18
|
description: "List conversations",
|
|
@@ -32,7 +32,7 @@ var cmd = subcommands({
|
|
|
32
32
|
},
|
|
33
33
|
files: {
|
|
34
34
|
description: "List pending incoming files",
|
|
35
|
-
run: (args) => import("./files-
|
|
35
|
+
run: (args) => import("./files-4LN3EN7Q.js").then((m) => m.run(args))
|
|
36
36
|
},
|
|
37
37
|
accept: {
|
|
38
38
|
description: "Accept a pending file",
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-T2TP6ZC6.js";
|
|
5
5
|
import {
|
|
6
6
|
mindDir
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ALKYQULU.js";
|
|
8
8
|
|
|
9
9
|
// packages/daemon/src/lib/delivery/delivery-router.ts
|
|
10
10
|
import { readFileSync, statSync } from "fs";
|
|
@@ -186,7 +186,8 @@ function resolveDeliveryMode(config, sessionName, rule) {
|
|
|
186
186
|
delivery = {
|
|
187
187
|
mode: "batch",
|
|
188
188
|
debounce: sessionConfig.delivery.debounce ?? DEFAULT_BATCH_DEBOUNCE,
|
|
189
|
-
maxWait: sessionConfig.delivery.maxWait ?? DEFAULT_BATCH_MAX_WAIT
|
|
189
|
+
maxWait: sessionConfig.delivery.maxWait ?? DEFAULT_BATCH_MAX_WAIT,
|
|
190
|
+
triggers: sessionConfig.delivery.triggers
|
|
190
191
|
};
|
|
191
192
|
}
|
|
192
193
|
return {
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
exec,
|
|
4
4
|
gitExec
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-H2X54EHC.js";
|
|
6
6
|
import {
|
|
7
7
|
readGlobalConfig,
|
|
8
8
|
writeGlobalConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-F7H6ATM4.js";
|
|
10
10
|
import {
|
|
11
11
|
logger_default
|
|
12
12
|
} from "./chunk-T2TP6ZC6.js";
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
mindDir,
|
|
16
16
|
readRegistry,
|
|
17
17
|
voluteHome
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ALKYQULU.js";
|
|
19
19
|
import {
|
|
20
20
|
sharedSkills
|
|
21
21
|
} from "./chunk-ZV7MFISX.js";
|
|
@@ -46,7 +46,7 @@ async function initDefaultSkills() {
|
|
|
46
46
|
const config = readGlobalConfig();
|
|
47
47
|
let extensionSkills = [];
|
|
48
48
|
try {
|
|
49
|
-
const { getExtensionStandardSkills } = await import("./extensions-
|
|
49
|
+
const { getExtensionStandardSkills } = await import("./extensions-JONTW2HF.js");
|
|
50
50
|
extensionSkills = getExtensionStandardSkills();
|
|
51
51
|
} catch (err) {
|
|
52
52
|
logger_default.warn("failed to load extension standard skills during init", logger_default.errorData(err));
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
setBridgeConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-RXEEYDIB.js";
|
|
5
5
|
import {
|
|
6
6
|
readEnv,
|
|
7
7
|
sharedEnvPath,
|
|
8
8
|
writeEnv
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ZDZISKCL.js";
|
|
10
10
|
|
|
11
11
|
// packages/daemon/src/lib/template/import-utils.ts
|
|
12
12
|
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
|
|
7
7
|
// packages/daemon/src/lib/db.ts
|
|
8
8
|
import { chmodSync, existsSync } from "fs";
|
|
9
|
-
import { dirname
|
|
9
|
+
import { dirname, resolve as resolve2 } from "path";
|
|
10
10
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
11
11
|
import { sql } from "drizzle-orm";
|
|
12
12
|
import { drizzle } from "drizzle-orm/libsql";
|
|
@@ -15,13 +15,16 @@ import { migrate } from "drizzle-orm/libsql/migrator";
|
|
|
15
15
|
// packages/daemon/src/lib/mind/registry.ts
|
|
16
16
|
import { mkdirSync } from "fs";
|
|
17
17
|
import { homedir } from "os";
|
|
18
|
-
import {
|
|
18
|
+
import { resolve } from "path";
|
|
19
19
|
import { fileURLToPath } from "url";
|
|
20
20
|
import { and, eq, inArray, isNull } from "drizzle-orm";
|
|
21
|
+
var SPIRIT_NAME = "volute";
|
|
22
|
+
function isSpiritName(name) {
|
|
23
|
+
return name === SPIRIT_NAME;
|
|
24
|
+
}
|
|
21
25
|
function voluteHome() {
|
|
22
26
|
if (process.env.VOLUTE_HOME) return process.env.VOLUTE_HOME;
|
|
23
|
-
|
|
24
|
-
if (dir.endsWith("/src/lib")) {
|
|
27
|
+
if (fileURLToPath(import.meta.url).endsWith(".ts")) {
|
|
25
28
|
throw new Error(
|
|
26
29
|
'VOLUTE_HOME must be set when running from source. For tests, run via "npm test" or add "--import ./test/setup.ts".'
|
|
27
30
|
);
|
|
@@ -200,7 +203,7 @@ function daemonLoopback() {
|
|
|
200
203
|
}
|
|
201
204
|
|
|
202
205
|
// packages/daemon/src/lib/db.ts
|
|
203
|
-
var __dirname =
|
|
206
|
+
var __dirname = dirname(fileURLToPath2(import.meta.url));
|
|
204
207
|
var migrationsFolder = existsSync(resolve2(__dirname, "../drizzle")) ? resolve2(__dirname, "../drizzle") : existsSync(resolve2(__dirname, "../../drizzle")) ? resolve2(__dirname, "../../drizzle") : resolve2(__dirname, "../../../../drizzle");
|
|
205
208
|
var db = null;
|
|
206
209
|
var dbPromise = null;
|
|
@@ -246,6 +249,8 @@ async function getDb() {
|
|
|
246
249
|
|
|
247
250
|
export {
|
|
248
251
|
getDb,
|
|
252
|
+
SPIRIT_NAME,
|
|
253
|
+
isSpiritName,
|
|
249
254
|
voluteHome,
|
|
250
255
|
voluteUserHome,
|
|
251
256
|
voluteSystemDir,
|
|
@@ -3,10 +3,10 @@ import {
|
|
|
3
3
|
LAUNCHD_PLIST_LABEL,
|
|
4
4
|
LAUNCHD_PLIST_PATH,
|
|
5
5
|
USER_SYSTEMD_UNIT
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-TQJ6ZYVY.js";
|
|
7
7
|
import {
|
|
8
8
|
resolveVoluteBin
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-H2X54EHC.js";
|
|
10
10
|
|
|
11
11
|
// packages/daemon/src/lib/config/service-install.ts
|
|
12
12
|
import { execFile } from "child_process";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
readVoluteConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PFZBNKUH.js";
|
|
5
5
|
import {
|
|
6
6
|
logger_default
|
|
7
7
|
} from "./chunk-T2TP6ZC6.js";
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
mindDir,
|
|
10
10
|
readAllMinds,
|
|
11
11
|
voluteHome
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-ALKYQULU.js";
|
|
13
13
|
|
|
14
14
|
// packages/daemon/src/lib/util/avatar-image.ts
|
|
15
15
|
import { readdir, readFile, writeFile } from "fs/promises";
|