volute 0.20.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 +7 -7
- package/dist/{activity-events-OMXKXD5N.js → activity-events-3WHHCOBB.js} +3 -4
- 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-IKMY5X76.js → chunk-5462YKWP.js} +12 -9
- package/dist/{chunk-PUVXOZ6T.js → chunk-7LPTHFIL.js} +63 -64
- package/dist/{chunk-UU7A7KLB.js → chunk-A4S7H6G6.js} +5 -7
- 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-GZ7DW4YL.js → chunk-HGCDWKSP.js} +2 -2
- package/dist/{chunk-DYZGP3EW.js → chunk-IPJXU366.js} +1 -1
- package/dist/{chunk-7UFKREVW.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-TIWH32HP.js → chunk-L3LHXZD7.js} +3 -3
- package/dist/{chunk-OGXOMR65.js → chunk-NWPT4ASZ.js} +1 -1
- package/dist/{chunk-FGSYHIS3.js → chunk-OGZYB5GL.js} +252 -296
- package/dist/{chunk-SCUDS4US.js → chunk-ON3FF5JA.js} +1 -1
- package/dist/{chunk-O6ASDHFO.js → chunk-PC6R6UUW.js} +4 -4
- 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-NSE7VJQA.js → chunk-SGPEZ32F.js} +29 -1
- package/dist/{chunk-RHEGSQFJ.js → chunk-WSLPZF72.js} +1 -1
- package/dist/cli.js +57 -119
- 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-KPSWNYTH.js → daemon-restart-BH67ZOTE.js} +6 -6
- package/dist/daemon.js +1538 -687
- 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-6QBUOQGC.js → export-XD6PJBQP.js} +19 -8
- package/dist/{file-C57SK5DK.js → file-X4L5TTOL.js} +2 -2
- package/dist/{history-WNK3DFUM.js → history-HTEKRNID.js} +2 -2
- package/dist/{import-XEC34Y4Z.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-Z7CKD6DG.js → mind-BIDOF65R.js} +27 -11
- package/dist/{mind-activity-tracker-624QLQLC.js → mind-activity-tracker-PGC3DBJ7.js} +4 -5
- package/dist/{mind-manager-3DMYKZPB.js → mind-manager-3V2NXX4I.js} +5 -6
- package/dist/{package-4NHAVUUI.js → package-HQR52XSG.js} +1 -1
- package/dist/{pages-4DGQT7ZA.js → pages-KQBR5TAZ.js} +6 -6
- package/dist/{publish-TAJUET4I.js → publish-OJ4QMXVZ.js} +6 -6
- 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-FFZG23IW.js → schedule-NLR3LZLY.js} +2 -2
- 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-52YRV7VP.js → setup-OZDYCKDI.js} +9 -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 +5 -5
- package/dist/{sprout-QN7Y4VVO.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-FU2PFVVF.js → status-LV34BG6G.js} +3 -3
- 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-FS7CKM6V.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/package.json +1 -1
- package/dist/chunk-5XNT2472.js +0 -36
- package/dist/chunk-UJ6GHNR7.js +0 -675
- package/dist/db-C2CJ46ZU.js +0 -10
- package/dist/delivery-manager-CSG7LXA4.js +0 -16
- package/dist/down-ZY35KMHR.js +0 -14
- package/dist/schema-GFH6RV3W.js +0 -26
- package/dist/variants-JAGWGBXG.js +0 -26
- package/dist/web-assets/assets/index-CUZTZzaW.js +0 -64
- package/dist/web-assets/assets/index-adVuCkqy.css +0 -1
|
@@ -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
|
}
|
|
@@ -164,7 +161,7 @@ Volute daemon is running. Data directory: ${DATA_DIR}`);
|
|
|
164
161
|
}
|
|
165
162
|
function uninstall(force) {
|
|
166
163
|
if (process.getuid?.() !== 0) {
|
|
167
|
-
console.error("Error: volute
|
|
164
|
+
console.error("Error: volute service uninstall --system must be run as root (use sudo).");
|
|
168
165
|
process.exit(1);
|
|
169
166
|
}
|
|
170
167
|
if (!existsSync(SYSTEM_SERVICE_PATH)) {
|
|
@@ -227,29 +224,7 @@ function uninstall(force) {
|
|
|
227
224
|
console.log("Use --force to also remove data and system users.");
|
|
228
225
|
}
|
|
229
226
|
}
|
|
230
|
-
async function run(args) {
|
|
231
|
-
const { positional, flags } = parseArgs(args, {
|
|
232
|
-
port: { type: "number" },
|
|
233
|
-
host: { type: "string" },
|
|
234
|
-
force: { type: "boolean" }
|
|
235
|
-
});
|
|
236
|
-
const subcommand = positional[0];
|
|
237
|
-
switch (subcommand) {
|
|
238
|
-
case "uninstall":
|
|
239
|
-
uninstall(!!flags.force);
|
|
240
|
-
break;
|
|
241
|
-
case void 0:
|
|
242
|
-
install(flags.port, flags.host);
|
|
243
|
-
break;
|
|
244
|
-
default:
|
|
245
|
-
console.log(`Usage:
|
|
246
|
-
volute setup [--port N] [--host H] Install system-level service with user isolation
|
|
247
|
-
volute setup uninstall [--force] Remove service (--force removes data + users)`);
|
|
248
|
-
console.error(`
|
|
249
|
-
Unknown subcommand: ${subcommand}`);
|
|
250
|
-
process.exit(1);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
227
|
export {
|
|
254
|
-
|
|
228
|
+
install,
|
|
229
|
+
uninstall
|
|
255
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
|
|
@@ -39,7 +39,7 @@ Once you have a sense of who you are:
|
|
|
39
39
|
|
|
40
40
|
1. Write `SOUL.md` — your identity, personality, and perspective. This becomes your system prompt.
|
|
41
41
|
2. Write `MEMORY.md` — any important context, preferences, or knowledge to start with.
|
|
42
|
-
3. Run `volute sprout` to complete the transformation.
|
|
42
|
+
3. Run `volute mind sprout` to complete the transformation.
|
|
43
43
|
|
|
44
44
|
After sprouting, you'll have full mind capabilities (connectors, schedules, variants, etc.).
|
|
45
45
|
|
|
@@ -48,7 +48,7 @@ After sprouting, you'll have full mind capabilities (connectors, schedules, vari
|
|
|
48
48
|
| Command | Purpose |
|
|
49
49
|
|---------|---------|
|
|
50
50
|
| `volute send @<name> "msg"` | Send a message to another user |
|
|
51
|
-
| `volute sprout` | Complete orientation and become a full mind |
|
|
51
|
+
| `volute mind sprout` | Complete orientation and become a full mind |
|
|
52
52
|
|
|
53
53
|
## Files
|
|
54
54
|
|
|
@@ -22,8 +22,8 @@ You manage yourself through the `volute` CLI. Your mind name is auto-detected vi
|
|
|
22
22
|
| `volute variant merge <name> [--summary "..." --memory "..."]` | Merge a variant back |
|
|
23
23
|
| `volute variant delete <name>` | Delete a variant without merging |
|
|
24
24
|
| `volute mind upgrade [--template <name>] [--continue]` | Upgrade your server code |
|
|
25
|
-
| `volute
|
|
26
|
-
| `volute
|
|
25
|
+
| `volute mind connect <type>` | Enable a connector (discord, slack, etc.) |
|
|
26
|
+
| `volute mind disconnect <type>` | Disable a connector |
|
|
27
27
|
| `volute channel read <platform>:<id> [--limit N]` | Read channel history |
|
|
28
28
|
| `volute send <platform>:<id> "msg"` | Send a message proactively (or pipe via stdin) |
|
|
29
29
|
| `volute channel list [<platform>]` | List conversations on a platform (or all platforms) |
|
|
@@ -286,9 +286,9 @@ Your pages are served at `https://{system}.volute.systems/~{your-name}/`. Create
|
|
|
286
286
|
|
|
287
287
|
Registration commands (usually run by the operator, not the mind):
|
|
288
288
|
```sh
|
|
289
|
-
volute register --name <system-name>
|
|
290
|
-
volute login --key <api-key>
|
|
291
|
-
volute logout
|
|
289
|
+
volute auth register --name <system-name>
|
|
290
|
+
volute auth login --key <api-key>
|
|
291
|
+
volute auth logout
|
|
292
292
|
```
|
|
293
293
|
|
|
294
294
|
## Git Introspection
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
STANDARD_SKILLS
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
uninstallSkill
|
|
7
|
-
} from "./chunk-IKMY5X76.js";
|
|
3
|
+
STANDARD_SKILLS
|
|
4
|
+
} from "./chunk-5462YKWP.js";
|
|
5
|
+
import "./chunk-SGPEZ32F.js";
|
|
8
6
|
import "./chunk-YUIHSKR6.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-DYZGP3EW.js";
|
|
12
|
-
import "./chunk-OGXOMR65.js";
|
|
7
|
+
import "./chunk-IPJXU366.js";
|
|
8
|
+
import "./chunk-NWPT4ASZ.js";
|
|
13
9
|
import {
|
|
14
10
|
findMind,
|
|
15
11
|
mindDir
|
|
16
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-B2CPS4QU.js";
|
|
17
13
|
import "./chunk-K3NQKI34.js";
|
|
18
14
|
|
|
19
15
|
// src/commands/sprout.ts
|
|
@@ -23,7 +19,7 @@ var ORIENTATION_MARKER = "You don't have a soul yet";
|
|
|
23
19
|
async function run(_args) {
|
|
24
20
|
const mindName = process.env.VOLUTE_MIND;
|
|
25
21
|
if (!mindName) {
|
|
26
|
-
console.error("volute sprout must be run by a mind (VOLUTE_MIND not set)");
|
|
22
|
+
console.error("volute mind sprout must be run by a mind (VOLUTE_MIND not set)");
|
|
27
23
|
process.exit(1);
|
|
28
24
|
}
|
|
29
25
|
const entry = findMind(mindName);
|
|
@@ -53,44 +49,52 @@ async function run(_args) {
|
|
|
53
49
|
console.error("Write your MEMORY.md before sprouting.");
|
|
54
50
|
process.exit(1);
|
|
55
51
|
}
|
|
52
|
+
const { daemonFetch } = await import("./daemon-client-ZHCDL4RS.js");
|
|
53
|
+
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
54
|
+
const client = getClient();
|
|
56
55
|
const failedSkills = [];
|
|
57
56
|
for (const skillId of STANDARD_SKILLS) {
|
|
58
|
-
const shared = await getSharedSkill(skillId);
|
|
59
|
-
if (!shared) {
|
|
60
|
-
console.error(`Shared skill not found: ${skillId} \u2014 run 'volute up' to sync built-in skills`);
|
|
61
|
-
failedSkills.push(skillId);
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
57
|
const skillDir = resolve(dir, "home", ".claude", "skills", skillId);
|
|
65
58
|
if (!existsSync(skillDir)) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
const installRes = await daemonFetch(
|
|
60
|
+
urlOf(client.api.minds[":name"].skills.install.$url({ param: { name: mindName } })),
|
|
61
|
+
{
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: { "Content-Type": "application/json" },
|
|
64
|
+
body: JSON.stringify({ skillId })
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
if (!installRes.ok) {
|
|
68
|
+
const data = await installRes.json().catch(() => ({ error: `HTTP ${installRes.status}` }));
|
|
69
|
+
console.error(`Failed to install skill ${skillId}: ${data.error}`);
|
|
70
70
|
failedSkills.push(skillId);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
const orientationDir = resolve(dir, "home", ".claude", "skills", "orientation");
|
|
75
75
|
if (existsSync(orientationDir)) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
const delRes = await daemonFetch(
|
|
77
|
+
urlOf(
|
|
78
|
+
client.api.minds[":name"].skills[":skill"].$url({
|
|
79
|
+
param: { name: mindName, skill: "orientation" }
|
|
80
|
+
})
|
|
81
|
+
),
|
|
82
|
+
{ method: "DELETE" }
|
|
83
|
+
);
|
|
84
|
+
if (!delRes.ok) {
|
|
85
|
+
const data = await delRes.json().catch(() => ({ error: `HTTP ${delRes.status}` }));
|
|
86
|
+
console.error(`Failed to uninstall orientation skill: ${data.error}`);
|
|
80
87
|
}
|
|
81
88
|
}
|
|
82
89
|
if (failedSkills.length > 0) {
|
|
83
90
|
console.error(`Warning: failed to install skills: ${failedSkills.join(", ")}`);
|
|
84
91
|
}
|
|
85
|
-
const { daemonFetch } = await import("./daemon-client-ITWUCNFO.js");
|
|
86
|
-
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
87
|
-
const client = getClient();
|
|
88
92
|
const sproutRes = await daemonFetch(
|
|
89
93
|
urlOf(client.api.minds[":name"].sprout.$url({ param: { name: mindName } })),
|
|
90
94
|
{ method: "POST" }
|
|
91
95
|
);
|
|
92
96
|
if (!sproutRes.ok) {
|
|
93
|
-
const data = await sproutRes.json();
|
|
97
|
+
const data = await sproutRes.json().catch(() => ({ error: `HTTP ${sproutRes.status}` }));
|
|
94
98
|
console.error(data.error ?? "Failed to update stage");
|
|
95
99
|
process.exit(1);
|
|
96
100
|
}
|
|
@@ -103,7 +107,7 @@ async function run(_args) {
|
|
|
103
107
|
}
|
|
104
108
|
);
|
|
105
109
|
if (!res.ok) {
|
|
106
|
-
const data = await res.json();
|
|
110
|
+
const data = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
107
111
|
console.error(data.error ?? "Failed to restart after sprouting");
|
|
108
112
|
process.exit(1);
|
|
109
113
|
}
|
|
@@ -5,10 +5,8 @@ import {
|
|
|
5
5
|
} from "./chunk-4RQBJWQX.js";
|
|
6
6
|
import {
|
|
7
7
|
daemonFetch
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import
|
|
10
|
-
resolveMind
|
|
11
|
-
} from "./chunk-EBGCNDMM.js";
|
|
8
|
+
} from "./chunk-KFI7TQJ6.js";
|
|
9
|
+
import "./chunk-B2CPS4QU.js";
|
|
12
10
|
import "./chunk-K3NQKI34.js";
|
|
13
11
|
|
|
14
12
|
// src/commands/start.ts
|
|
@@ -18,7 +16,6 @@ async function run(args) {
|
|
|
18
16
|
console.error("Usage: volute mind start <name>");
|
|
19
17
|
process.exit(1);
|
|
20
18
|
}
|
|
21
|
-
const { entry } = resolveMind(name);
|
|
22
19
|
const client = getClient();
|
|
23
20
|
const res = await daemonFetch(urlOf(client.api.minds[":name"].start.$url({ param: { name } })), {
|
|
24
21
|
method: "POST"
|
|
@@ -28,7 +25,7 @@ async function run(args) {
|
|
|
28
25
|
console.error(data.error || "Failed to start mind");
|
|
29
26
|
process.exit(1);
|
|
30
27
|
}
|
|
31
|
-
console.log(`${name} started on port ${
|
|
28
|
+
console.log(`${name} started on port ${data.port}`);
|
|
32
29
|
}
|
|
33
30
|
export {
|
|
34
31
|
run
|
|
@@ -7,8 +7,8 @@ import {
|
|
|
7
7
|
} from "./chunk-D424ZQGI.js";
|
|
8
8
|
import {
|
|
9
9
|
daemonFetch
|
|
10
|
-
} from "./chunk-
|
|
11
|
-
import "./chunk-
|
|
10
|
+
} from "./chunk-KFI7TQJ6.js";
|
|
11
|
+
import "./chunk-B2CPS4QU.js";
|
|
12
12
|
import "./chunk-K3NQKI34.js";
|
|
13
13
|
|
|
14
14
|
// src/commands/shared/status.ts
|