volute 0.19.0 → 0.21.0
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/README.md +68 -68
- package/dist/activity-events-3WHHCOBB.js +15 -0
- package/dist/{archive-ZCFOSTKB.js → archive-4ZQYK5MN.js} +4 -2
- package/dist/auth-HM2RSPY7.js +37 -0
- package/dist/{channel-PUQKGSQM.js → channel-BOOMFULW.js} +2 -2
- package/dist/{chunk-OTWLI7F4.js → chunk-5462YKWP.js} +12 -9
- package/dist/{chunk-2TJGRJ4O.js → chunk-7LPTHFIL.js} +64 -59
- package/dist/chunk-A4S7H6G6.js +56 -0
- package/dist/chunk-AKPFNL7L.js +148 -0
- package/dist/{chunk-EBGCNDMM.js → chunk-B2CPS4QU.js} +128 -114
- package/dist/{chunk-FCDU5BFX.js → chunk-HFCBO2GL.js} +2 -2
- package/dist/chunk-HGCDWKSP.js +97 -0
- package/dist/{chunk-DYZGP3EW.js → chunk-IPJXU366.js} +1 -1
- package/dist/{chunk-VE4D3GOP.js → chunk-J5A3DF2U.js} +2 -2
- package/dist/{chunk-WC6ZHVRL.js → chunk-KFI7TQJ6.js} +2 -2
- package/dist/{chunk-AW7P4EVV.js → chunk-KTJGZ7M7.js} +55 -7
- package/dist/{chunk-4KPUF5JD.js → chunk-L3LHXZD7.js} +18 -5
- package/dist/{chunk-OGXOMR65.js → chunk-NWPT4ASZ.js} +1 -1
- package/dist/{chunk-FGV2H4TX.js → chunk-OGZYB5GL.js} +312 -268
- package/dist/{chunk-SCUDS4US.js → chunk-ON3FF5JA.js} +1 -1
- package/dist/{chunk-EMQSAY3B.js → chunk-PC6R6UUW.js} +6 -5
- package/dist/{chunk-VDWCHYTS.js → chunk-PHU4DEAJ.js} +1 -1
- package/dist/{chunk-7NO7EV5Z.js → chunk-Q7AITQ44.js} +2 -2
- package/dist/{chunk-32VR2EOH.js → chunk-QUJUKM4U.js} +2 -2
- package/dist/{chunk-VQWDC6UK.js → chunk-SGPEZ32F.js} +46 -1
- package/dist/{chunk-RHEGSQFJ.js → chunk-WSLPZF72.js} +1 -1
- package/dist/cli.js +59 -111
- package/dist/{connector-JBVNZ7VK.js → connector-PYT5UOTZ.js} +6 -6
- package/dist/connectors/discord.js +2 -2
- package/dist/connectors/slack.js +2 -2
- package/dist/connectors/telegram.js +2 -2
- package/dist/{create-HP4OVVHF.js → create-WIDA3M4C.js} +1 -1
- package/dist/{daemon-client-ITWUCNFO.js → daemon-client-ZHCDL4RS.js} +2 -2
- package/dist/{daemon-restart-JMZM3QY4.js → daemon-restart-BH67ZOTE.js} +8 -8
- package/dist/daemon.js +2872 -1301
- package/dist/{delete-BSU7K3RY.js → delete-LOIANQGD.js} +1 -1
- package/dist/down-LIOQ5JDH.js +14 -0
- package/dist/{env-A3LMO777.js → env-4PHIHTF4.js} +2 -2
- package/dist/{export-GCDNQCF3.js → export-XD6PJBQP.js} +19 -8
- package/dist/file-X4L5TTOL.js +204 -0
- package/dist/{history-WNK3DFUM.js → history-HTEKRNID.js} +2 -2
- package/dist/{import-M63VIUJ5.js → import-E433B4KG.js} +3 -3
- package/dist/{log-PPPZDVEF.js → log-SRO5Q6AD.js} +2 -2
- package/dist/{login-HNH3EUQV.js → login-UO6AOVEA.js} +4 -4
- package/dist/{logout-I5CB5UZS.js → logout-UKD5LA37.js} +2 -2
- package/dist/{logs-SF2IMJN4.js → logs-HNTNNBDW.js} +2 -2
- package/dist/{merge-33C237A4.js → merge-B6SYTGI7.js} +2 -2
- package/dist/{mind-PQ5NCPSU.js → mind-BIDOF65R.js} +27 -11
- package/dist/mind-activity-tracker-PGC3DBJ7.js +18 -0
- package/dist/{mind-manager-RVCFROAY.js → mind-manager-3V2NXX4I.js} +5 -6
- package/dist/{package-MYE2ZJLV.js → package-HQR52XSG.js} +1 -1
- package/dist/{pages-AXCOSY3P.js → pages-KQBR5TAZ.js} +6 -6
- package/dist/{publish-YB377JB7.js → publish-OJ4QMXVZ.js} +12 -9
- package/dist/{pull-XAEWQJ47.js → pull-GRQAXM2E.js} +2 -2
- package/dist/{register-VSPCMHKX.js → register-U2UO6TC4.js} +5 -5
- package/dist/registry-D2BSQ2X5.js +42 -0
- package/dist/{restart-IQKMCK5M.js → restart-CIDAKGG2.js} +3 -6
- package/dist/{schedule-LMX7GAQZ.js → schedule-NLR3LZLY.js} +27 -7
- package/dist/{seed-J43YDKXG.js → seed-3H2MRREW.js} +2 -2
- package/dist/{send-KVIZIGCE.js → send-RP2TA7SG.js} +132 -36
- package/dist/{service-LUR7WDO7.js → service-TVNEORO7.js} +31 -13
- package/dist/{setup-OH3PJUJO.js → setup-OZDYCKDI.js} +25 -34
- package/dist/{shared-KO35ZM44.js → shared-DCQ2UXOM.js} +4 -4
- package/dist/{skill-BCVNI6TV.js → skill-Q2Y6PQ3L.js} +2 -2
- package/dist/skills/orientation/SKILL.md +2 -2
- package/dist/skills/volute-mind/SKILL.md +38 -8
- package/dist/{sprout-VBEX63LX.js → sprout-6Z6C42YM.js} +34 -30
- package/dist/{start-I5JYB65M.js → start-JR6CUUWF.js} +3 -6
- package/dist/{status-D7E5HHBV.js → status-5XDGYHKP.js} +2 -2
- package/dist/{status-JCJAOXTW.js → status-LV34BG6G.js} +6 -5
- package/dist/{status-4ESFLGH4.js → status-Z7NAFMBI.js} +5 -5
- package/dist/{stop-NBVKEFQQ.js → stop-VKPGK25U.js} +2 -5
- package/dist/template-hash-BIMA4ILT.js +8 -0
- package/dist/{up-WG65SWJU.js → up-7BGDMFRT.js} +5 -5
- package/dist/{update-FJIHDJKM.js → update-4WT7VWHW.js} +5 -5
- package/dist/{update-check-MWE5AH4U.js → update-check-F5Z3ALXX.js} +2 -2
- package/dist/{upgrade-AIT24B5I.js → upgrade-ZEC2GGFO.js} +1 -1
- package/dist/{variant-63ZWO2W7.js → variant-A4I7PHXS.js} +16 -24
- package/dist/version-notify-TFS2U5CF.js +173 -0
- package/dist/web-assets/assets/index-BR3gtK3E.css +1 -0
- package/dist/web-assets/assets/index-CWmrZRQd.js +64 -0
- package/dist/web-assets/index.html +2 -2
- package/drizzle/0012_activity.sql +11 -0
- package/drizzle/meta/0012_snapshot.json +7 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +1 -1
- package/templates/_base/home/.config/routes.json +2 -2
- package/templates/_base/home/VOLUTE.md +1 -1
- package/templates/_base/src/lib/daemon-client.ts +22 -0
- package/templates/_base/src/lib/transparency.ts +1 -1
- package/templates/claude/.init/.config/routes.json +7 -1
- package/templates/pi/.init/.config/routes.json +7 -1
- package/templates/pi/src/agent.ts +11 -5
- package/templates/pi/src/lib/session-context-extension.ts +6 -4
- package/templates/pi/src/server.ts +2 -0
- package/dist/chunk-UJ6GHNR7.js +0 -675
- package/dist/chunk-Z524RFCJ.js +0 -36
- package/dist/db-5ZVC6MQF.js +0 -10
- package/dist/delivery-manager-ISTJMZDW.js +0 -16
- package/dist/down-ZY35KMHR.js +0 -14
- package/dist/schema-5BW7DFZI.js +0 -24
- package/dist/variants-JAGWGBXG.js +0 -26
- package/dist/web-assets/assets/index-BAbuRsVF.css +0 -1
- package/dist/web-assets/assets/index-CiQhSKi_.js +0 -63
|
@@ -8,11 +8,11 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
readSystemsConfig,
|
|
10
10
|
writeSystemsConfig
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-HFCBO2GL.js";
|
|
12
12
|
import {
|
|
13
13
|
parseArgs
|
|
14
14
|
} from "./chunk-D424ZQGI.js";
|
|
15
|
-
import "./chunk-
|
|
15
|
+
import "./chunk-B2CPS4QU.js";
|
|
16
16
|
import "./chunk-K3NQKI34.js";
|
|
17
17
|
|
|
18
18
|
// src/commands/pages/register.ts
|
|
@@ -23,13 +23,13 @@ async function run(args) {
|
|
|
23
23
|
});
|
|
24
24
|
const existing = readSystemsConfig();
|
|
25
25
|
if (existing) {
|
|
26
|
-
console.error(`Already registered as "${existing.system}". Run "volute logout" first.`);
|
|
26
|
+
console.error(`Already registered as "${existing.system}". Run "volute auth logout" first.`);
|
|
27
27
|
process.exit(1);
|
|
28
28
|
}
|
|
29
29
|
let name = flags.name;
|
|
30
30
|
if (!name) {
|
|
31
31
|
if (!process.stdin.isTTY) {
|
|
32
|
-
console.error("Usage: volute
|
|
32
|
+
console.error("Usage: volute auth register --name <system-name>");
|
|
33
33
|
process.exit(1);
|
|
34
34
|
}
|
|
35
35
|
name = await promptLine("Choose a system name: ");
|
|
@@ -55,7 +55,7 @@ async function run(args) {
|
|
|
55
55
|
} catch (err) {
|
|
56
56
|
console.error(`Failed to save credentials: ${err.message}`);
|
|
57
57
|
console.error(`Your API key is: ${apiKey}`);
|
|
58
|
-
console.error(`Save it and run: volute
|
|
58
|
+
console.error(`Save it and run: volute auth login --key ${apiKey}`);
|
|
59
59
|
process.exit(1);
|
|
60
60
|
}
|
|
61
61
|
console.log(`Registered as "${system}". Credentials saved.`);
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
addMind,
|
|
4
|
+
daemonLoopback,
|
|
5
|
+
ensureVoluteHome,
|
|
6
|
+
findMind,
|
|
7
|
+
getRegistryCache,
|
|
8
|
+
initRegistryCache,
|
|
9
|
+
mindDir,
|
|
10
|
+
nextPort,
|
|
11
|
+
readRegistry,
|
|
12
|
+
removeMind,
|
|
13
|
+
resolveMind,
|
|
14
|
+
setMindRunning,
|
|
15
|
+
setMindStage,
|
|
16
|
+
setMindTemplateHash,
|
|
17
|
+
stateDir,
|
|
18
|
+
validateMindName,
|
|
19
|
+
voluteHome,
|
|
20
|
+
writeRegistry
|
|
21
|
+
} from "./chunk-B2CPS4QU.js";
|
|
22
|
+
import "./chunk-K3NQKI34.js";
|
|
23
|
+
export {
|
|
24
|
+
addMind,
|
|
25
|
+
daemonLoopback,
|
|
26
|
+
ensureVoluteHome,
|
|
27
|
+
findMind,
|
|
28
|
+
getRegistryCache,
|
|
29
|
+
initRegistryCache,
|
|
30
|
+
mindDir,
|
|
31
|
+
nextPort,
|
|
32
|
+
readRegistry,
|
|
33
|
+
removeMind,
|
|
34
|
+
resolveMind,
|
|
35
|
+
setMindRunning,
|
|
36
|
+
setMindStage,
|
|
37
|
+
setMindTemplateHash,
|
|
38
|
+
stateDir,
|
|
39
|
+
validateMindName,
|
|
40
|
+
voluteHome,
|
|
41
|
+
writeRegistry
|
|
42
|
+
};
|
|
@@ -8,16 +8,13 @@ import {
|
|
|
8
8
|
} from "./chunk-NAOW2CLO.js";
|
|
9
9
|
import {
|
|
10
10
|
daemonFetch
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import
|
|
13
|
-
resolveMind
|
|
14
|
-
} from "./chunk-EBGCNDMM.js";
|
|
11
|
+
} from "./chunk-KFI7TQJ6.js";
|
|
12
|
+
import "./chunk-B2CPS4QU.js";
|
|
15
13
|
import "./chunk-K3NQKI34.js";
|
|
16
14
|
|
|
17
15
|
// src/commands/restart.ts
|
|
18
16
|
async function run(args) {
|
|
19
17
|
const name = resolveMindName({ mind: args[0] });
|
|
20
|
-
const { entry } = resolveMind(name);
|
|
21
18
|
const client = getClient();
|
|
22
19
|
const res = await daemonFetch(
|
|
23
20
|
urlOf(client.api.minds[":name"].restart.$url({ param: { name } })),
|
|
@@ -28,7 +25,7 @@ async function run(args) {
|
|
|
28
25
|
console.error(data.error || "Failed to restart mind");
|
|
29
26
|
process.exit(1);
|
|
30
27
|
}
|
|
31
|
-
console.log(`${name} restarted on port ${
|
|
28
|
+
console.log(`${name} restarted on port ${data.port}`);
|
|
32
29
|
}
|
|
33
30
|
export {
|
|
34
31
|
run
|
|
@@ -11,11 +11,12 @@ import {
|
|
|
11
11
|
} from "./chunk-D424ZQGI.js";
|
|
12
12
|
import {
|
|
13
13
|
daemonFetch
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-KFI7TQJ6.js";
|
|
15
|
+
import "./chunk-B2CPS4QU.js";
|
|
16
16
|
import "./chunk-K3NQKI34.js";
|
|
17
17
|
|
|
18
18
|
// src/commands/schedule.ts
|
|
19
|
+
import { CronExpressionParser } from "cron-parser";
|
|
19
20
|
async function run(args) {
|
|
20
21
|
const subcommand = args[0];
|
|
21
22
|
switch (subcommand) {
|
|
@@ -42,6 +43,7 @@ function printUsage() {
|
|
|
42
43
|
console.log(`Usage:
|
|
43
44
|
volute schedule list [--mind <name>]
|
|
44
45
|
volute schedule add [--mind <name>] --cron "..." --message "..." [--id name]
|
|
46
|
+
volute schedule add [--mind <name>] --cron "..." --script "..." [--id name]
|
|
45
47
|
volute schedule remove [--mind <name>] --id <id>`);
|
|
46
48
|
}
|
|
47
49
|
async function listSchedules(args) {
|
|
@@ -65,10 +67,11 @@ async function listSchedules(args) {
|
|
|
65
67
|
}
|
|
66
68
|
const idW = Math.max(2, ...schedules.map((s) => s.id.length));
|
|
67
69
|
const cronW = Math.max(4, ...schedules.map((s) => s.cron.length));
|
|
68
|
-
|
|
70
|
+
const actionLabel = (s) => s.script ? `[script] ${s.script}` : s.message ?? "";
|
|
71
|
+
console.log(`${"ID".padEnd(idW)} ${"CRON".padEnd(cronW)} ENABLED ACTION`);
|
|
69
72
|
for (const s of schedules) {
|
|
70
73
|
console.log(
|
|
71
|
-
`${s.id.padEnd(idW)} ${s.cron.padEnd(cronW)} ${String(s.enabled).padEnd(7)} ${s
|
|
74
|
+
`${s.id.padEnd(idW)} ${s.cron.padEnd(cronW)} ${String(s.enabled).padEnd(7)} ${actionLabel(s)}`
|
|
72
75
|
);
|
|
73
76
|
}
|
|
74
77
|
}
|
|
@@ -77,14 +80,31 @@ async function addSchedule(args) {
|
|
|
77
80
|
mind: { type: "string" },
|
|
78
81
|
cron: { type: "string" },
|
|
79
82
|
message: { type: "string" },
|
|
83
|
+
script: { type: "string" },
|
|
80
84
|
id: { type: "string" }
|
|
81
85
|
});
|
|
82
86
|
const mind = resolveMindName(flags);
|
|
83
|
-
if (!flags.cron
|
|
84
|
-
console.error("--cron
|
|
87
|
+
if (!flags.cron) {
|
|
88
|
+
console.error("--cron is required");
|
|
85
89
|
process.exit(1);
|
|
86
90
|
}
|
|
87
|
-
|
|
91
|
+
if (!flags.message && !flags.script) {
|
|
92
|
+
console.error("--message or --script is required");
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
if (flags.message && flags.script) {
|
|
96
|
+
console.error("--message and --script are mutually exclusive");
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
CronExpressionParser.parse(flags.cron);
|
|
101
|
+
} catch {
|
|
102
|
+
console.error(`Invalid cron expression: ${flags.cron}`);
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
const body = { cron: flags.cron };
|
|
106
|
+
if (flags.message) body.message = flags.message;
|
|
107
|
+
if (flags.script) body.script = flags.script;
|
|
88
108
|
if (flags.id) body.id = flags.id;
|
|
89
109
|
const client = getClient();
|
|
90
110
|
const res = await daemonFetch(
|
|
@@ -15,13 +15,13 @@ async function run(args) {
|
|
|
15
15
|
const name = positional[0];
|
|
16
16
|
if (!name) {
|
|
17
17
|
console.error(
|
|
18
|
-
"Usage: volute seed <name> [--template <name>] [--model <model>] [--description <text>] [--skills <list|none>]"
|
|
18
|
+
"Usage: volute mind seed <name> [--template <name>] [--model <model>] [--description <text>] [--skills <list|none>]"
|
|
19
19
|
);
|
|
20
20
|
process.exit(1);
|
|
21
21
|
}
|
|
22
22
|
const template = flags.template ?? "claude";
|
|
23
23
|
const skills = flags.skills === "none" ? [] : flags.skills ? flags.skills.split(",") : void 0;
|
|
24
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
24
|
+
const { daemonFetch } = await import("./daemon-client-ZHCDL4RS.js");
|
|
25
25
|
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
26
26
|
const client = getClient();
|
|
27
27
|
const createRes = await daemonFetch(urlOf(client.api.minds.$url()), {
|
|
@@ -6,19 +6,15 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
resolveMindName
|
|
8
8
|
} from "./chunk-NAOW2CLO.js";
|
|
9
|
-
import {
|
|
10
|
-
getChannelDriver
|
|
11
|
-
} from "./chunk-UJ6GHNR7.js";
|
|
12
9
|
import {
|
|
13
10
|
parseArgs
|
|
14
11
|
} from "./chunk-D424ZQGI.js";
|
|
15
|
-
import "./chunk-RHEGSQFJ.js";
|
|
16
12
|
import {
|
|
17
13
|
daemonFetch
|
|
18
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-KFI7TQJ6.js";
|
|
19
15
|
import {
|
|
20
16
|
findMind
|
|
21
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-B2CPS4QU.js";
|
|
22
18
|
import "./chunk-K3NQKI34.js";
|
|
23
19
|
|
|
24
20
|
// src/commands/send.ts
|
|
@@ -94,16 +90,88 @@ function loadImage(imagePath) {
|
|
|
94
90
|
const data = readFileSync(imagePath).toString("base64");
|
|
95
91
|
return { media_type: mediaType, data };
|
|
96
92
|
}
|
|
93
|
+
async function waitForResponse(mindName, conversationId, timeoutMs) {
|
|
94
|
+
const client = getClient();
|
|
95
|
+
const eventPath = urlOf(
|
|
96
|
+
client.api.minds[":name"].conversations[":id"].events.$url({
|
|
97
|
+
param: { name: mindName, id: conversationId }
|
|
98
|
+
})
|
|
99
|
+
);
|
|
100
|
+
const controller = new AbortController();
|
|
101
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
102
|
+
let response;
|
|
103
|
+
try {
|
|
104
|
+
response = await daemonFetch(eventPath, {
|
|
105
|
+
signal: controller.signal
|
|
106
|
+
});
|
|
107
|
+
} catch {
|
|
108
|
+
clearTimeout(timeout);
|
|
109
|
+
console.error("Could not connect to event stream. Is the mind running?");
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
if (!response.body) {
|
|
113
|
+
clearTimeout(timeout);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
const reader = response.body.getReader();
|
|
117
|
+
const decoder = new TextDecoder();
|
|
118
|
+
let buffer = "";
|
|
119
|
+
try {
|
|
120
|
+
while (true) {
|
|
121
|
+
const { done, value } = await reader.read();
|
|
122
|
+
if (done) break;
|
|
123
|
+
buffer += decoder.decode(value, { stream: true });
|
|
124
|
+
const chunks = buffer.split("\n\n");
|
|
125
|
+
buffer = chunks.pop();
|
|
126
|
+
for (const chunk of chunks) {
|
|
127
|
+
for (const line of chunk.split("\n")) {
|
|
128
|
+
if (!line.startsWith("data: ")) continue;
|
|
129
|
+
const data = line.slice(6).trim();
|
|
130
|
+
if (!data) continue;
|
|
131
|
+
let event;
|
|
132
|
+
try {
|
|
133
|
+
event = JSON.parse(data);
|
|
134
|
+
} catch {
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (event.type === "message" && event.senderName === mindName && event.content) {
|
|
138
|
+
const text = event.content.filter((b) => b.type === "text" && !!b.text).map((b) => b.text).join("");
|
|
139
|
+
if (text) {
|
|
140
|
+
process.stdout.write(`${text}
|
|
141
|
+
`);
|
|
142
|
+
}
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} catch (err) {
|
|
149
|
+
if (err.name === "AbortError") {
|
|
150
|
+
console.error(`(timed out after ${timeoutMs / 1e3}s)`);
|
|
151
|
+
} else {
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
154
|
+
} finally {
|
|
155
|
+
clearTimeout(timeout);
|
|
156
|
+
reader.cancel().catch(() => {
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
97
160
|
async function run(args) {
|
|
98
161
|
const { positional, flags } = parseArgs(args, {
|
|
99
162
|
mind: { type: "string" },
|
|
100
|
-
image: { type: "string" }
|
|
163
|
+
image: { type: "string" },
|
|
164
|
+
wait: { type: "boolean" },
|
|
165
|
+
timeout: { type: "number" },
|
|
166
|
+
sender: { type: "string" }
|
|
101
167
|
});
|
|
102
168
|
const target = positional[0];
|
|
103
169
|
const message = positional[1] ?? await readStdin();
|
|
104
170
|
const images = flags.image ? [loadImage(flags.image)] : void 0;
|
|
105
171
|
if (!target || !message && !images) {
|
|
106
|
-
console.error(
|
|
172
|
+
console.error(
|
|
173
|
+
'Usage: volute send <target> "<message>" [--mind <name>] [--image <path>] [--wait]'
|
|
174
|
+
);
|
|
107
175
|
console.error(' echo "message" | volute send <target> [--mind <name>]');
|
|
108
176
|
console.error("");
|
|
109
177
|
console.error("Examples:");
|
|
@@ -112,6 +180,7 @@ async function run(args) {
|
|
|
112
180
|
console.error(' volute send discord:server/channel "hello"');
|
|
113
181
|
console.error(' volute send @mind "check this out" --image photo.png');
|
|
114
182
|
console.error(" volute send @mind --image photo.png");
|
|
183
|
+
console.error(' volute send @mind "hello" --wait');
|
|
115
184
|
process.exit(1);
|
|
116
185
|
}
|
|
117
186
|
if (target === "system" || target === "@system") {
|
|
@@ -130,44 +199,55 @@ To reply to a person, use their username from the message prefix (e.g. volute se
|
|
|
130
199
|
isDM: true
|
|
131
200
|
};
|
|
132
201
|
}
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
console.error(`No driver for platform: ${parsed.platform}`);
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
202
|
+
const client = getClient();
|
|
203
|
+
let waitMindName;
|
|
138
204
|
let channelUri = parsed.uri;
|
|
139
205
|
if (parsed.isDM && parsed.platform === "volute") {
|
|
140
206
|
const targetName = parsed.identifier.slice(1);
|
|
141
207
|
const mindSelf = process.env.VOLUTE_MIND;
|
|
142
|
-
const sender = mindSelf || userInfo().username;
|
|
143
|
-
|
|
144
|
-
console.error("Volute driver does not support creating conversations");
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
208
|
+
const sender = flags.sender || mindSelf || userInfo().username;
|
|
209
|
+
waitMindName = findMind(targetName) ? targetName : void 0;
|
|
147
210
|
const targetIsMind = !!findMind(targetName);
|
|
148
211
|
const contextMind = mindSelf && !targetIsMind ? mindSelf : targetName;
|
|
149
212
|
const participants = mindSelf && !targetIsMind ? [targetName] : [sender];
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
213
|
+
const createRes = await daemonFetch(
|
|
214
|
+
urlOf(client.api.minds[":name"].channels.create.$url({ param: { name: contextMind } })),
|
|
215
|
+
{
|
|
216
|
+
method: "POST",
|
|
217
|
+
headers: { "Content-Type": "application/json" },
|
|
218
|
+
body: JSON.stringify({ platform: "volute", participants, sender })
|
|
219
|
+
}
|
|
220
|
+
);
|
|
221
|
+
if (!createRes.ok) {
|
|
222
|
+
const data = await createRes.json().catch(() => ({ error: "Unknown error" }));
|
|
223
|
+
console.error(data.error);
|
|
158
224
|
process.exit(1);
|
|
159
225
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
226
|
+
const { slug } = await createRes.json();
|
|
227
|
+
channelUri = slug;
|
|
228
|
+
const sendRes = await daemonFetch(
|
|
229
|
+
urlOf(client.api.minds[":name"].channels.send.$url({ param: { name: contextMind } })),
|
|
230
|
+
{
|
|
231
|
+
method: "POST",
|
|
232
|
+
headers: { "Content-Type": "application/json" },
|
|
233
|
+
body: JSON.stringify({
|
|
234
|
+
platform: "volute",
|
|
235
|
+
uri: channelUri,
|
|
236
|
+
message: message ?? "",
|
|
237
|
+
images,
|
|
238
|
+
sender
|
|
239
|
+
})
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
if (!sendRes.ok) {
|
|
243
|
+
const data = await sendRes.json().catch(() => ({ error: "Unknown error" }));
|
|
244
|
+
console.error(data.error);
|
|
165
245
|
process.exit(1);
|
|
166
246
|
}
|
|
247
|
+
if (!flags.wait) console.log("Message sent.");
|
|
167
248
|
if (mindSelf) {
|
|
168
249
|
try {
|
|
169
|
-
const
|
|
170
|
-
await daemonFetch(
|
|
250
|
+
const histRes = await daemonFetch(
|
|
171
251
|
urlOf(client.api.minds[":name"].history.$url({ param: { name: mindSelf } })),
|
|
172
252
|
{
|
|
173
253
|
method: "POST",
|
|
@@ -175,13 +255,15 @@ To reply to a person, use their username from the message prefix (e.g. volute se
|
|
|
175
255
|
body: JSON.stringify({ channel: parsed.uri, content: message ?? "" })
|
|
176
256
|
}
|
|
177
257
|
);
|
|
258
|
+
if (!histRes.ok) {
|
|
259
|
+
console.error(`Failed to persist to history: HTTP ${histRes.status}`);
|
|
260
|
+
}
|
|
178
261
|
} catch (err) {
|
|
179
262
|
console.error(`Failed to persist to history: ${err instanceof Error ? err.message : err}`);
|
|
180
263
|
}
|
|
181
264
|
}
|
|
182
265
|
} else {
|
|
183
266
|
const mindName = resolveMindName(flags);
|
|
184
|
-
const client = getClient();
|
|
185
267
|
const res = await daemonFetch(
|
|
186
268
|
urlOf(client.api.minds[":name"].channels.send.$url({ param: { name: mindName } })),
|
|
187
269
|
{
|
|
@@ -200,10 +282,10 @@ To reply to a person, use their username from the message prefix (e.g. volute se
|
|
|
200
282
|
console.error(body.error);
|
|
201
283
|
process.exit(1);
|
|
202
284
|
}
|
|
203
|
-
console.log("Message sent.");
|
|
285
|
+
if (!flags.wait) console.log("Message sent.");
|
|
204
286
|
if (process.env.VOLUTE_MIND) {
|
|
205
287
|
try {
|
|
206
|
-
await daemonFetch(
|
|
288
|
+
const histRes = await daemonFetch(
|
|
207
289
|
urlOf(client.api.minds[":name"].history.$url({ param: { name: mindName } })),
|
|
208
290
|
{
|
|
209
291
|
method: "POST",
|
|
@@ -211,11 +293,25 @@ To reply to a person, use their username from the message prefix (e.g. volute se
|
|
|
211
293
|
body: JSON.stringify({ channel: channelUri, content: message ?? "" })
|
|
212
294
|
}
|
|
213
295
|
);
|
|
296
|
+
if (!histRes.ok) {
|
|
297
|
+
console.error(`Failed to persist to history: HTTP ${histRes.status}`);
|
|
298
|
+
}
|
|
214
299
|
} catch (err) {
|
|
215
300
|
console.error(`Failed to persist to history: ${err instanceof Error ? err.message : err}`);
|
|
216
301
|
}
|
|
217
302
|
}
|
|
218
303
|
}
|
|
304
|
+
if (flags.wait && waitMindName) {
|
|
305
|
+
const conversationId = channelUri.startsWith("volute:") ? channelUri.slice(7) : void 0;
|
|
306
|
+
if (!conversationId) {
|
|
307
|
+
console.error("--wait requires a volute conversation (DM to a mind)");
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
310
|
+
await waitForResponse(waitMindName, conversationId, flags.timeout ?? 12e4);
|
|
311
|
+
} else if (flags.wait && !waitMindName) {
|
|
312
|
+
console.error("--wait is only supported when sending to a mind");
|
|
313
|
+
process.exit(1);
|
|
314
|
+
}
|
|
219
315
|
}
|
|
220
316
|
export {
|
|
221
317
|
run
|
|
@@ -4,15 +4,15 @@ import {
|
|
|
4
4
|
LAUNCHD_PLIST_PATH,
|
|
5
5
|
SYSTEM_SERVICE_PATH,
|
|
6
6
|
USER_SYSTEMD_UNIT
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-QUJUKM4U.js";
|
|
8
8
|
import {
|
|
9
9
|
parseArgs
|
|
10
10
|
} from "./chunk-D424ZQGI.js";
|
|
11
11
|
import {
|
|
12
12
|
resolveVoluteBin
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-IPJXU366.js";
|
|
14
|
+
import "./chunk-NWPT4ASZ.js";
|
|
15
|
+
import "./chunk-B2CPS4QU.js";
|
|
16
16
|
import "./chunk-K3NQKI34.js";
|
|
17
17
|
|
|
18
18
|
// src/commands/service.ts
|
|
@@ -87,16 +87,20 @@ async function install(port, host) {
|
|
|
87
87
|
console.log("Service installed and loaded. Volute daemon will start on login.");
|
|
88
88
|
} else if (platform === "linux") {
|
|
89
89
|
if (existsSync(SYSTEM_SERVICE_PATH)) {
|
|
90
|
-
console.error(
|
|
90
|
+
console.error(
|
|
91
|
+
"A system-level Volute service is already installed (via `volute service install --system`)."
|
|
92
|
+
);
|
|
91
93
|
console.error("Use `systemctl status volute` to check its status.");
|
|
92
|
-
console.error("To remove it first: sudo volute
|
|
94
|
+
console.error("To remove it first: sudo volute service uninstall --system");
|
|
93
95
|
process.exit(1);
|
|
94
96
|
}
|
|
95
97
|
if (process.getuid?.() === 0) {
|
|
96
98
|
console.error(
|
|
97
99
|
"Error: `volute service install` uses systemd user services, which don't work as root."
|
|
98
100
|
);
|
|
99
|
-
console.error(
|
|
101
|
+
console.error(
|
|
102
|
+
"Use `volute service install --system` instead to install a system-level service."
|
|
103
|
+
);
|
|
100
104
|
process.exit(1);
|
|
101
105
|
}
|
|
102
106
|
const path = USER_SYSTEMD_UNIT;
|
|
@@ -199,24 +203,38 @@ async function status() {
|
|
|
199
203
|
async function run(args) {
|
|
200
204
|
const { positional, flags } = parseArgs(args, {
|
|
201
205
|
port: { type: "number" },
|
|
202
|
-
host: { type: "string" }
|
|
206
|
+
host: { type: "string" },
|
|
207
|
+
system: { type: "boolean" },
|
|
208
|
+
force: { type: "boolean" }
|
|
203
209
|
});
|
|
204
210
|
const subcommand = positional[0];
|
|
205
211
|
switch (subcommand) {
|
|
206
212
|
case "install":
|
|
207
|
-
|
|
213
|
+
if (flags.system) {
|
|
214
|
+
const setup = await import("./setup-OZDYCKDI.js");
|
|
215
|
+
setup.install(flags.port, flags.host);
|
|
216
|
+
} else {
|
|
217
|
+
await install(flags.port, flags.host);
|
|
218
|
+
}
|
|
208
219
|
break;
|
|
209
220
|
case "uninstall":
|
|
210
|
-
|
|
221
|
+
if (flags.system) {
|
|
222
|
+
const setup = await import("./setup-OZDYCKDI.js");
|
|
223
|
+
setup.uninstall(!!flags.force);
|
|
224
|
+
} else {
|
|
225
|
+
await uninstall();
|
|
226
|
+
}
|
|
211
227
|
break;
|
|
212
228
|
case "status":
|
|
213
229
|
await status();
|
|
214
230
|
break;
|
|
215
231
|
default:
|
|
216
232
|
console.log(`Usage:
|
|
217
|
-
volute service install [--port N] [--host H]
|
|
218
|
-
volute service
|
|
219
|
-
volute service
|
|
233
|
+
volute service install [--port N] [--host H] Install as user-level service
|
|
234
|
+
volute service install --system [--port N] [--host H] Install system service with user isolation
|
|
235
|
+
volute service uninstall Remove user-level service
|
|
236
|
+
volute service uninstall --system [--force] Remove system service (--force removes data + users)
|
|
237
|
+
volute service status Check service status`);
|
|
220
238
|
if (subcommand) {
|
|
221
239
|
console.error(`
|
|
222
240
|
Unknown subcommand: ${subcommand}`);
|
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
SYSTEM_SERVICE_PATH
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import {
|
|
6
|
-
parseArgs
|
|
7
|
-
} from "./chunk-D424ZQGI.js";
|
|
4
|
+
} from "./chunk-QUJUKM4U.js";
|
|
8
5
|
import {
|
|
9
6
|
resolveVoluteBin
|
|
10
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-IPJXU366.js";
|
|
11
8
|
import {
|
|
12
9
|
ensureVoluteGroup
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-NWPT4ASZ.js";
|
|
11
|
+
import "./chunk-B2CPS4QU.js";
|
|
15
12
|
import "./chunk-K3NQKI34.js";
|
|
16
13
|
|
|
17
14
|
// src/commands/setup.ts
|
|
@@ -80,11 +77,11 @@ function generateUnit(voluteBin, port, host) {
|
|
|
80
77
|
function install(port, host) {
|
|
81
78
|
if (host) validateHost(host);
|
|
82
79
|
if (process.getuid?.() !== 0) {
|
|
83
|
-
console.error("Error: volute
|
|
80
|
+
console.error("Error: volute service install --system must be run as root (use sudo).");
|
|
84
81
|
process.exit(1);
|
|
85
82
|
}
|
|
86
83
|
if (process.platform !== "linux") {
|
|
87
|
-
console.error("Error: volute
|
|
84
|
+
console.error("Error: volute service install --system is only supported on Linux.");
|
|
88
85
|
console.error("On macOS, use `volute service install` for user-level service management.");
|
|
89
86
|
process.exit(1);
|
|
90
87
|
}
|
|
@@ -95,6 +92,22 @@ function install(port, host) {
|
|
|
95
92
|
console.log(`Created ${MINDS_DIR}`);
|
|
96
93
|
ensureVoluteGroup({ force: true });
|
|
97
94
|
console.log("Ensured volute group exists");
|
|
95
|
+
try {
|
|
96
|
+
execFileSync("git", ["config", "--system", "user.name"]);
|
|
97
|
+
console.log("System git identity already configured, skipping");
|
|
98
|
+
} catch {
|
|
99
|
+
try {
|
|
100
|
+
execFileSync("git", ["config", "--system", "user.name", "Volute"]);
|
|
101
|
+
execFileSync("git", ["config", "--system", "user.email", "volute@localhost"]);
|
|
102
|
+
console.log("Configured system git identity");
|
|
103
|
+
} catch (err) {
|
|
104
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
105
|
+
console.warn(`Warning: failed to set system git config: ${msg}`);
|
|
106
|
+
console.warn("Git commits by the daemon may fail. You can set this manually with:");
|
|
107
|
+
console.warn(' git config --system user.name "Volute"');
|
|
108
|
+
console.warn(' git config --system user.email "volute@localhost"');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
98
111
|
execFileSync("chmod", ["755", DATA_DIR]);
|
|
99
112
|
execFileSync("chmod", ["755", MINDS_DIR]);
|
|
100
113
|
console.log("Set permissions on directories");
|
|
@@ -148,7 +161,7 @@ Volute daemon is running. Data directory: ${DATA_DIR}`);
|
|
|
148
161
|
}
|
|
149
162
|
function uninstall(force) {
|
|
150
163
|
if (process.getuid?.() !== 0) {
|
|
151
|
-
console.error("Error: volute
|
|
164
|
+
console.error("Error: volute service uninstall --system must be run as root (use sudo).");
|
|
152
165
|
process.exit(1);
|
|
153
166
|
}
|
|
154
167
|
if (!existsSync(SYSTEM_SERVICE_PATH)) {
|
|
@@ -211,29 +224,7 @@ function uninstall(force) {
|
|
|
211
224
|
console.log("Use --force to also remove data and system users.");
|
|
212
225
|
}
|
|
213
226
|
}
|
|
214
|
-
async function run(args) {
|
|
215
|
-
const { positional, flags } = parseArgs(args, {
|
|
216
|
-
port: { type: "number" },
|
|
217
|
-
host: { type: "string" },
|
|
218
|
-
force: { type: "boolean" }
|
|
219
|
-
});
|
|
220
|
-
const subcommand = positional[0];
|
|
221
|
-
switch (subcommand) {
|
|
222
|
-
case "uninstall":
|
|
223
|
-
uninstall(!!flags.force);
|
|
224
|
-
break;
|
|
225
|
-
case void 0:
|
|
226
|
-
install(flags.port, flags.host);
|
|
227
|
-
break;
|
|
228
|
-
default:
|
|
229
|
-
console.log(`Usage:
|
|
230
|
-
volute setup [--port N] [--host H] Install system-level service with user isolation
|
|
231
|
-
volute setup uninstall [--force] Remove service (--force removes data + users)`);
|
|
232
|
-
console.error(`
|
|
233
|
-
Unknown subcommand: ${subcommand}`);
|
|
234
|
-
process.exit(1);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
227
|
export {
|
|
238
|
-
|
|
228
|
+
install,
|
|
229
|
+
uninstall
|
|
239
230
|
};
|
|
@@ -6,16 +6,16 @@ async function run(args) {
|
|
|
6
6
|
const subcommand = args[0];
|
|
7
7
|
switch (subcommand) {
|
|
8
8
|
case "merge":
|
|
9
|
-
await import("./merge-
|
|
9
|
+
await import("./merge-B6SYTGI7.js").then((m) => m.run(args.slice(1)));
|
|
10
10
|
break;
|
|
11
11
|
case "pull":
|
|
12
|
-
await import("./pull-
|
|
12
|
+
await import("./pull-GRQAXM2E.js").then((m) => m.run(args.slice(1)));
|
|
13
13
|
break;
|
|
14
14
|
case "log":
|
|
15
|
-
await import("./log-
|
|
15
|
+
await import("./log-SRO5Q6AD.js").then((m) => m.run(args.slice(1)));
|
|
16
16
|
break;
|
|
17
17
|
case "status":
|
|
18
|
-
await import("./status-
|
|
18
|
+
await import("./status-5XDGYHKP.js").then((m) => m.run(args.slice(1)));
|
|
19
19
|
break;
|
|
20
20
|
case "--help":
|
|
21
21
|
case "-h":
|
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
} from "./chunk-D424ZQGI.js";
|
|
12
12
|
import {
|
|
13
13
|
daemonFetch
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-KFI7TQJ6.js";
|
|
15
|
+
import "./chunk-B2CPS4QU.js";
|
|
16
16
|
import "./chunk-K3NQKI34.js";
|
|
17
17
|
|
|
18
18
|
// src/commands/skill.ts
|