volute 0.34.0 → 0.35.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 -6
- package/dist/accept-ZBDVVCEU.js +42 -0
- package/dist/{activity-events-BN7V6KCC.js → activity-events-ZW4SDL2C.js} +4 -4
- package/dist/{ai-service-PSILB5WD.js → ai-service-LURBEDDB.js} +5 -5
- package/dist/{api-client-XUXOB7LI.js → api-client-3A77HMH7.js} +1 -1
- package/dist/api.d.ts +1 -5618
- package/dist/{archive-C2VEMQOR.js → archive-ESU2FUN4.js} +3 -3
- package/dist/{auth-ZFZXJZDQ.js → auth-WX4TESEI.js} +5 -5
- package/dist/bridge-PXIO6PS2.js +206 -0
- package/dist/chat-QXAJF3FU.js +51 -0
- package/dist/{chunk-7F2SW2KD.js → chunk-2TGZJFAT.js} +3 -3
- package/dist/{chunk-6LXAAQ43.js → chunk-33ODGMFZ.js} +1 -1
- package/dist/{chunk-4JSR7YO7.js → chunk-5N7Y5WAM.js} +1 -1
- package/dist/{chunk-FYCALD4Q.js → chunk-5T5YMX6S.js} +1 -1
- package/dist/{chunk-B2BVAIZ4.js → chunk-5XJYUFZH.js} +21 -15
- package/dist/{chunk-M3K5AARV.js → chunk-A2ZLHBHG.js} +2 -2
- package/dist/{chunk-U5BTYSAL.js → chunk-AN2W47GW.js} +2 -2
- package/dist/{chunk-G53F3JA4.js → chunk-AOB6GVRM.js} +1 -1
- package/dist/{chunk-N7BLAHNE.js → chunk-BDYXIWA5.js} +5 -5
- package/dist/{chunk-YUIHSKR6.js → chunk-BKF4WQCY.js} +2 -2
- package/dist/{chunk-6OWJXUAR.js → chunk-BMZQYACC.js} +2 -2
- package/dist/{chunk-NAOW2CLO.js → chunk-BTY4WNFE.js} +1 -1
- package/dist/{chunk-MLOQKQNB.js → chunk-BV65KRHM.js} +2 -2
- package/dist/{chunk-XWXBJQBE.js → chunk-CORXD635.js} +4 -4
- package/dist/{chunk-PVY5W6QN.js → chunk-F7ZNLYKZ.js} +2 -2
- package/dist/{chunk-BFWHBQK4.js → chunk-FT5KETXZ.js} +3 -3
- package/dist/{chunk-N3DNFPVA.js → chunk-IJHIXLVN.js} +8 -8
- package/dist/{chunk-V6ZCNULL.js → chunk-J6CJQDWI.js} +37 -28
- package/dist/{chunk-4RQBJWQX.js → chunk-LOPXTW6H.js} +1 -1
- package/dist/{chunk-47ZPNLF4.js → chunk-MDJGMOSD.js} +8 -137
- package/dist/{chunk-BTWAGDV5.js → chunk-N446KRP7.js} +3 -3
- package/dist/{chunk-6WAWMWR5.js → chunk-N5LMGYXX.js} +2 -2
- package/dist/{chunk-G6BSYHPK.js → chunk-NJK5SDGR.js} +1 -1
- package/dist/{chunk-D424ZQGI.js → chunk-O7IGP7ZW.js} +11 -3
- package/dist/{chunk-2IOP6PHB.js → chunk-OTC67N2Z.js} +2 -2
- package/dist/{chunk-V45JXOWY.js → chunk-PWQ2ITYG.js} +4 -4
- package/dist/{chunk-KTLFDYPT.js → chunk-QCH6K235.js} +1 -1
- package/dist/chunk-QHG4OMZL.js +145 -0
- package/dist/{chunk-IS7WJ56Q.js → chunk-QWTR6AWZ.js} +3 -3
- package/dist/chunk-TXSA4Q3V.js +116 -0
- package/dist/{chunk-BDK73LK6.js → chunk-VHJRZM2S.js} +2 -2
- package/dist/{chunk-SSI47XP2.js → chunk-VHWGEJ4V.js} +1 -1
- package/dist/chunk-VY3RB2V7.js +164 -0
- package/dist/chunk-WJPROOU5.js +8314 -0
- package/dist/{chunk-E5C7OWZ2.js → chunk-WZRZFFCL.js} +8 -8
- package/dist/{chunk-BM474GX6.js → chunk-XRQSAMX2.js} +4 -4
- package/dist/{chunk-OYAKCAVY.js → chunk-ZSR72JB3.js} +1 -1
- package/dist/{chunk-PLDWHR4D.js → chunk-ZX7EAV5J.js} +17 -7
- package/dist/cli.js +90 -29
- package/dist/clock-HSEKS5AR.js +289 -0
- package/dist/{cloud-sync-TG3TIX5H.js → cloud-sync-6JL4C24T.js} +21 -22
- package/dist/config-UTS7QULS.js +76 -0
- package/dist/connectors/discord-bridge.js +3 -3
- package/dist/connectors/slack-bridge.js +3 -3
- package/dist/connectors/telegram-bridge.js +3 -3
- package/dist/{conversations-HL2JP5GI.js → conversations-2PW57WO2.js} +5 -5
- package/dist/create-5BPOOJAN.js +75 -0
- package/dist/create-UVCK2CS6.js +50 -0
- package/dist/daemon-client-RVIKXGFQ.js +12 -0
- package/dist/daemon-restart-HSZ3BCX5.js +65 -0
- package/dist/daemon.js +845 -1766
- package/dist/{db-PLEDCBHZ.js → db-BDMH4SZ2.js} +7 -3
- package/dist/{db-RYX3SS2W.js → db-BVBJ57TU.js} +2 -2
- package/dist/delete-L5PAVDGQ.js +42 -0
- package/dist/delivery-manager-H5ZVBMCQ.js +31 -0
- package/dist/{delivery-router-D5ELDMS2.js → delivery-router-HEJSJAHQ.js} +4 -4
- package/dist/down-74VXM45A.js +17 -0
- package/dist/env-E4XHO2BI.js +223 -0
- package/dist/{exec-DVLXKRIO.js → exec-PY7THYH4.js} +4 -4
- package/dist/export-OAS6QVBN.js +113 -0
- package/dist/{extension-PM42QCID.js → extension-D74CNM7G.js} +25 -33
- package/dist/{extensions-BBGVL5JC.js → extensions-XDDFY72A.js} +22 -11
- package/dist/files-CWTK6V3H.js +53 -0
- package/dist/import-5A3T7QV4.js +143 -0
- package/dist/{isolation-62MKDZN3.js → isolation-TK5RX2WM.js} +3 -3
- package/dist/join-DF5XSJAC.js +67 -0
- package/dist/list-PDMQM7ZV.js +53 -0
- package/dist/login-7TE6CIZF.js +60 -0
- package/dist/login-GOTAYLXP.js +51 -0
- package/dist/logout-6KIA74EV.js +29 -0
- package/dist/logout-T4XS6LRU.js +50 -0
- package/dist/message-delivery-GRC4W6P7.js +41 -0
- package/dist/mind-5IEYKV7I.js +97 -0
- package/dist/{mind-activity-tracker-2ACNHA7B.js → mind-activity-tracker-QBLIV7ZJ.js} +5 -5
- package/dist/{mind-history-WOYFLQAI.js → mind-history-IE2QH7U5.js} +82 -71
- package/dist/mind-list-GEWHWAL4.js +38 -0
- package/dist/mind-manager-HFLB5653.js +31 -0
- package/dist/mind-profile-DCBDVF5B.js +53 -0
- package/dist/mind-service-X2CAA6W6.js +37 -0
- package/dist/mind-sleep-ITCF6OQA.js +47 -0
- package/dist/mind-status-X4SX3YUG.js +65 -0
- package/dist/mind-wake-KXMKMGWX.js +42 -0
- package/dist/{package-V2WHWVG6.js → package-D2FSVFAX.js} +5 -5
- package/dist/read-67VRP2DO.js +91 -0
- package/dist/{read-stdin-PIRM6A2Y.js → read-stdin-3X5VYKNS.js} +1 -1
- package/dist/register-SB7NXCOE.js +51 -0
- package/dist/{registry-UYV5S6QT.js → registry-GBSNW3HG.js} +2 -2
- package/dist/reject-MUR2KWJ4.js +40 -0
- package/dist/restart-5EGG4JXU.js +42 -0
- package/dist/{sandbox-SI5HMBP3.js → sandbox-R37VIU36.js} +5 -5
- package/dist/scheduler-Y7O4CJXL.js +31 -0
- package/dist/{schema-ETMABTW4.js → schema-XVZ2CLKW.js} +1 -1
- package/dist/{seed-WNGI6PNW.js → seed-EQORWX77.js} +2 -2
- package/dist/seed-check-KJNTL72M.js +35 -0
- package/dist/seed-cmd-ZM2XGVU2.js +30 -0
- package/dist/seed-create-DRWGGHEI.js +113 -0
- package/dist/seed-sprout-JYXGXOP3.js +148 -0
- package/dist/send-JBJJQ7CA.js +409 -0
- package/dist/service-WNPCNHOX.js +121 -0
- package/dist/{setup-Z3DEVWV7.js → setup-BJ4YAY26.js} +153 -127
- package/dist/{setup-GGMKENLN.js → setup-RHJRFURI.js} +3 -3
- package/dist/skill-TAAKEYBV.js +389 -0
- package/dist/skills/volute-mind/SKILL.md +3 -7
- package/dist/skills/volute-mind/references/extensions.md +8 -11
- package/dist/{skills-Q6VZ2UGD.js → skills-EKMCQ46K.js} +7 -7
- package/dist/sleep-manager-7KFK3USC.js +35 -0
- package/dist/spirit-ZFRDXMG7.js +23 -0
- package/dist/split-AWVOYOPZ.js +64 -0
- package/dist/{sprout-E3HJIV2Z.js → sprout-HE4TITMK.js} +2 -2
- package/dist/start-3UXOPXQG.js +39 -0
- package/dist/status-ZK34WYIM.js +125 -0
- package/dist/stop-3XYIBGFM.js +41 -0
- package/dist/system-chat-IDPHYHY4.js +35 -0
- package/dist/systems-O43WGQY6.js +52 -0
- package/dist/{tailscale-ZEUK7GKZ.js → tailscale-ZIZ2HWJ5.js} +4 -4
- package/dist/{template-hash-EJRTKE36.js → template-hash-A7FNHTB7.js} +2 -2
- package/dist/up-77ICEDEW.js +19 -0
- package/dist/update-ANE5ZM7F.js +225 -0
- package/dist/{update-check-X3YG4WVP.js → update-check-UV55CBEP.js} +3 -3
- package/dist/upgrade-ZMDGC7M2.js +74 -0
- package/dist/variant-QWL2WSRI.js +62 -0
- package/dist/{version-notify-YCH4UVQ2.js → version-notify-FXSEMXWW.js} +28 -27
- package/dist/{volute-config-WBKYJGYQ.js → volute-config-D2XVS2YI.js} +1 -1
- package/dist/web-assets/assets/index-BhxWKvbB.css +1 -0
- package/dist/web-assets/assets/index-CHVKJ9II.js +75 -0
- package/dist/web-assets/index.html +2 -2
- package/dist/web-assets/sw.js +117 -0
- package/package.json +5 -5
- package/packages/extensions/pages/dist/ui/assets/index-DKZLNMED.js +2 -0
- package/packages/extensions/pages/dist/ui/index.html +1 -1
- package/packages/extensions/pages/skills/pages/SKILL.md +84 -9
- package/templates/_base/src/lib/auto-commit.ts +8 -8
- package/templates/_base/src/lib/volute-server.ts +6 -0
- package/templates/claude/src/agent.ts +8 -1
- package/dist/accept-TW6V4WI4.js +0 -42
- package/dist/bridge-O753D5F4.js +0 -207
- package/dist/chat-BHYX7DJ4.js +0 -68
- package/dist/chunk-47XDEWWV.js +0 -156
- package/dist/chunk-CVL5IGIR.js +0 -2084
- package/dist/chunk-PB65JZK2.js +0 -85
- package/dist/chunk-TAHX36HZ.js +0 -3679
- package/dist/clock-3X4DSC2N.js +0 -281
- package/dist/config-OROA5DUA.js +0 -72
- package/dist/create-3SEKKI6P.js +0 -71
- package/dist/create-UOSOQ2HN.js +0 -44
- package/dist/daemon-client-WOAQXXBM.js +0 -12
- package/dist/daemon-restart-5ABHNXJZ.js +0 -52
- package/dist/delete-KYOVWR23.js +0 -35
- package/dist/delivery-manager-2BR5NZKF.js +0 -32
- package/dist/down-QVFN4UPK.js +0 -15
- package/dist/env-R34DT7XL.js +0 -195
- package/dist/export-6ZXAXATG.js +0 -112
- package/dist/files-VQV2VZQO.js +0 -47
- package/dist/import-MK2I2T6F.js +0 -23
- package/dist/join-DGYHTJUH.js +0 -66
- package/dist/list-C644WTHV.js +0 -49
- package/dist/login-IIGEQPHL.js +0 -47
- package/dist/login-KZQLMAWE.js +0 -47
- package/dist/logout-AGTZVRGP.js +0 -40
- package/dist/logout-KD6GXIJJ.js +0 -21
- package/dist/message-delivery-V3R6NXJP.js +0 -42
- package/dist/mind-BI4EPBVZ.js +0 -108
- package/dist/mind-list-6VPM7GUQ.js +0 -30
- package/dist/mind-manager-MWW3BTS4.js +0 -32
- package/dist/mind-profile-WPG42U5Y.js +0 -47
- package/dist/mind-service-VIKZJK2M.js +0 -38
- package/dist/mind-sleep-XDISJY74.js +0 -42
- package/dist/mind-status-7FTZWPZF.js +0 -56
- package/dist/mind-wake-KIIKEI3A.js +0 -37
- package/dist/read-H5C26YO7.js +0 -85
- package/dist/register-J27WP33N.js +0 -47
- package/dist/reject-OEANJYIA.js +0 -40
- package/dist/restart-V5EGYBJG.js +0 -33
- package/dist/scheduler-AGG3L2FO.js +0 -32
- package/dist/seed-check-PXTH7YXS.js +0 -32
- package/dist/seed-cmd-VENFTGS3.js +0 -36
- package/dist/seed-create-663ALOKH.js +0 -112
- package/dist/seed-sprout-EH3AGKAI.js +0 -132
- package/dist/send-7FUUUZZH.js +0 -386
- package/dist/skill-DKNYJS4P.js +0 -362
- package/dist/skills/shared-files/SKILL.md +0 -44
- package/dist/skills/shared-files/scripts/merge.ts +0 -72
- package/dist/skills/shared-files/scripts/pull.ts +0 -52
- package/dist/sleep-manager-BJK2ROPX.js +0 -36
- package/dist/spirit-4JP4TY4C.js +0 -23
- package/dist/split-3YPMS2CL.js +0 -63
- package/dist/start-W3TPKX4D.js +0 -33
- package/dist/status-4OVFXFEJ.js +0 -115
- package/dist/stop-GTT6YWYO.js +0 -32
- package/dist/system-channel-DXD2JBOU.js +0 -36
- package/dist/system-chat-TYLOL7SX.js +0 -36
- package/dist/systems-AYLO727G.js +0 -61
- package/dist/up-PA7F2CXE.js +0 -18
- package/dist/update-HG4LCUSG.js +0 -215
- package/dist/upgrade-YGNIDICG.js +0 -67
- package/dist/variant-MZUMRTQO.js +0 -41
- package/dist/web-assets/assets/index-DiiwC-CZ.css +0 -1
- package/dist/web-assets/assets/index-d6y5b9Ij.js +0 -75
- package/packages/extensions/pages/dist/ui/assets/index-tLTROSk5.js +0 -2
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
readStdin
|
|
4
|
+
} from "./chunk-33ODGMFZ.js";
|
|
5
|
+
import {
|
|
6
|
+
isCompact
|
|
7
|
+
} from "./chunk-5T5YMX6S.js";
|
|
8
|
+
import {
|
|
9
|
+
command
|
|
10
|
+
} from "./chunk-TXSA4Q3V.js";
|
|
11
|
+
import "./chunk-O7IGP7ZW.js";
|
|
12
|
+
import {
|
|
13
|
+
daemonFetch
|
|
14
|
+
} from "./chunk-ZX7EAV5J.js";
|
|
15
|
+
import {
|
|
16
|
+
getClient,
|
|
17
|
+
urlOf
|
|
18
|
+
} from "./chunk-LOPXTW6H.js";
|
|
19
|
+
import {
|
|
20
|
+
formatFileSize
|
|
21
|
+
} from "./chunk-BV65KRHM.js";
|
|
22
|
+
import "./chunk-BDYXIWA5.js";
|
|
23
|
+
import "./chunk-5N7Y5WAM.js";
|
|
24
|
+
import "./chunk-7KJOFUNN.js";
|
|
25
|
+
|
|
26
|
+
// packages/cli/src/commands/send.ts
|
|
27
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
28
|
+
import { userInfo } from "os";
|
|
29
|
+
import { basename, extname } from "path";
|
|
30
|
+
|
|
31
|
+
// packages/cli/src/lib/parse-target.ts
|
|
32
|
+
function parseTarget(target) {
|
|
33
|
+
const colonIdx = target.indexOf(":");
|
|
34
|
+
if (colonIdx !== -1) {
|
|
35
|
+
const platform = target.slice(0, colonIdx);
|
|
36
|
+
const identifier = target.slice(colonIdx + 1);
|
|
37
|
+
return {
|
|
38
|
+
platform,
|
|
39
|
+
identifier,
|
|
40
|
+
uri: target,
|
|
41
|
+
isDM: identifier.startsWith("@")
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (target.startsWith("@")) {
|
|
45
|
+
return {
|
|
46
|
+
platform: "volute",
|
|
47
|
+
identifier: target,
|
|
48
|
+
uri: target,
|
|
49
|
+
isDM: true
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
platform: "volute",
|
|
54
|
+
identifier: target,
|
|
55
|
+
uri: target,
|
|
56
|
+
isDM: false
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// packages/cli/src/commands/send.ts
|
|
61
|
+
async function isMind(name) {
|
|
62
|
+
try {
|
|
63
|
+
const res = await daemonFetch(`/api/minds/${encodeURIComponent(name)}`);
|
|
64
|
+
return res.ok;
|
|
65
|
+
} catch {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
var IMAGE_MEDIA_TYPES = {
|
|
70
|
+
".png": "image/png",
|
|
71
|
+
".jpg": "image/jpeg",
|
|
72
|
+
".jpeg": "image/jpeg",
|
|
73
|
+
".gif": "image/gif",
|
|
74
|
+
".webp": "image/webp"
|
|
75
|
+
};
|
|
76
|
+
function loadImage(imagePath) {
|
|
77
|
+
if (!existsSync(imagePath)) {
|
|
78
|
+
console.error(`Image file not found: ${imagePath}`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
const ext = extname(imagePath).toLowerCase();
|
|
82
|
+
const mediaType = IMAGE_MEDIA_TYPES[ext];
|
|
83
|
+
if (!mediaType) {
|
|
84
|
+
console.error(`Unsupported image format: ${ext} (supported: png, jpg, jpeg, gif, webp)`);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
const data = readFileSync(imagePath).toString("base64");
|
|
88
|
+
return { media_type: mediaType, data };
|
|
89
|
+
}
|
|
90
|
+
async function waitForResponse(mindName, conversationId, timeoutMs) {
|
|
91
|
+
const client = getClient();
|
|
92
|
+
const eventPath = urlOf(
|
|
93
|
+
client.api.minds[":name"].conversations[":id"].events.$url({
|
|
94
|
+
param: { name: mindName, id: conversationId }
|
|
95
|
+
})
|
|
96
|
+
);
|
|
97
|
+
const controller = new AbortController();
|
|
98
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
99
|
+
let response;
|
|
100
|
+
try {
|
|
101
|
+
response = await daemonFetch(eventPath, {
|
|
102
|
+
signal: controller.signal
|
|
103
|
+
});
|
|
104
|
+
} catch {
|
|
105
|
+
clearTimeout(timeout);
|
|
106
|
+
console.error("Could not connect to event stream. Is the mind running?");
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
if (!response.body) {
|
|
110
|
+
clearTimeout(timeout);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const reader = response.body.getReader();
|
|
114
|
+
const decoder = new TextDecoder();
|
|
115
|
+
let buffer = "";
|
|
116
|
+
try {
|
|
117
|
+
while (true) {
|
|
118
|
+
const { done, value } = await reader.read();
|
|
119
|
+
if (done) break;
|
|
120
|
+
buffer += decoder.decode(value, { stream: true });
|
|
121
|
+
const chunks = buffer.split("\n\n");
|
|
122
|
+
buffer = chunks.pop();
|
|
123
|
+
for (const chunk of chunks) {
|
|
124
|
+
for (const line of chunk.split("\n")) {
|
|
125
|
+
if (!line.startsWith("data: ")) continue;
|
|
126
|
+
const data = line.slice(6).trim();
|
|
127
|
+
if (!data) continue;
|
|
128
|
+
let event;
|
|
129
|
+
try {
|
|
130
|
+
event = JSON.parse(data);
|
|
131
|
+
} catch {
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
if (event.type === "message" && event.senderName === mindName && event.content) {
|
|
135
|
+
const text = event.content.filter((b) => b.type === "text" && !!b.text).map((b) => b.text).join("");
|
|
136
|
+
if (text) {
|
|
137
|
+
process.stdout.write(`${text}
|
|
138
|
+
`);
|
|
139
|
+
}
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
} catch (err) {
|
|
146
|
+
if (err.name === "AbortError") {
|
|
147
|
+
console.error(`(timed out after ${timeoutMs / 1e3}s)`);
|
|
148
|
+
} else {
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
} finally {
|
|
152
|
+
clearTimeout(timeout);
|
|
153
|
+
reader.cancel().catch(() => {
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
var cmd = command({
|
|
158
|
+
name: "volute chat send",
|
|
159
|
+
description: "Send a message to a mind, channel, or platform",
|
|
160
|
+
args: [
|
|
161
|
+
{
|
|
162
|
+
name: "target",
|
|
163
|
+
required: true,
|
|
164
|
+
description: "Recipient (@name, #channel, or platform:channel)"
|
|
165
|
+
},
|
|
166
|
+
{ name: "message", description: "Message text (or pipe via stdin)" }
|
|
167
|
+
],
|
|
168
|
+
flags: {
|
|
169
|
+
image: { type: "string", description: "Path to image to embed" },
|
|
170
|
+
file: { type: "string", description: "Path to file to send" },
|
|
171
|
+
wait: { type: "boolean", description: "Wait for mind response" },
|
|
172
|
+
timeout: { type: "number", description: "Response timeout in ms (default 120000)" },
|
|
173
|
+
sender: { type: "string", description: "Send as a specific user" }
|
|
174
|
+
},
|
|
175
|
+
examples: [
|
|
176
|
+
'volute chat send @alice "hello"',
|
|
177
|
+
'volute chat send #general "announcement"',
|
|
178
|
+
"echo hi | volute chat send @alice"
|
|
179
|
+
],
|
|
180
|
+
async run({ args, flags }) {
|
|
181
|
+
const target = args.target;
|
|
182
|
+
const message = args.message ?? await readStdin();
|
|
183
|
+
const images = flags.image ? [loadImage(flags.image)] : void 0;
|
|
184
|
+
if (!message && !images && !flags.file) {
|
|
185
|
+
console.error(
|
|
186
|
+
'Usage: volute chat send <target> "<message>" [--image <path>] [--file <path>] [--wait]'
|
|
187
|
+
);
|
|
188
|
+
console.error(' echo "message" | volute chat send <target>');
|
|
189
|
+
console.error("");
|
|
190
|
+
console.error("Examples:");
|
|
191
|
+
console.error(' volute chat send @other-mind "hello"');
|
|
192
|
+
console.error(' volute chat send #animal-chat "hello everyone"');
|
|
193
|
+
console.error(' volute chat send @mind "check this out" --image photo.png');
|
|
194
|
+
console.error(" volute chat send @mind --image photo.png");
|
|
195
|
+
console.error(' volute chat send @mind "check this out" --file notes.txt');
|
|
196
|
+
console.error(' volute chat send @mind "hello" --wait');
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
if (target === "system" || target === "@system") {
|
|
200
|
+
console.error(
|
|
201
|
+
`Can't send to system \u2014 system messages are automated.
|
|
202
|
+
To reply to a person, use their username from the message prefix (e.g. volute chat send @username "msg").`
|
|
203
|
+
);
|
|
204
|
+
process.exit(1);
|
|
205
|
+
}
|
|
206
|
+
if (flags.file) {
|
|
207
|
+
const filePath = flags.file;
|
|
208
|
+
const parsed2 = parseTarget(target);
|
|
209
|
+
const targetName = parsed2.isDM && parsed2.platform === "volute" ? parsed2.identifier.slice(1) : parsed2.identifier;
|
|
210
|
+
const mindSelf = process.env.VOLUTE_MIND;
|
|
211
|
+
if (mindSelf) {
|
|
212
|
+
const res = await daemonFetch(`/api/minds/${encodeURIComponent(mindSelf)}/files/send`, {
|
|
213
|
+
method: "POST",
|
|
214
|
+
headers: { "Content-Type": "application/json" },
|
|
215
|
+
body: JSON.stringify({ targetMind: targetName, filePath })
|
|
216
|
+
});
|
|
217
|
+
if (!res.ok) {
|
|
218
|
+
const data2 = await res.json();
|
|
219
|
+
console.error(data2.error ?? `Failed to send file: ${res.status}`);
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
const data = await res.json();
|
|
223
|
+
console.log(`File staged for ${targetName} (id: ${data.id})`);
|
|
224
|
+
} else {
|
|
225
|
+
if (!existsSync(filePath)) {
|
|
226
|
+
console.error(`File not found: ${filePath}`);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
}
|
|
229
|
+
const stat = statSync(filePath);
|
|
230
|
+
const MAX_FILE_SIZE = 50 * 1024 * 1024;
|
|
231
|
+
if (stat.size > MAX_FILE_SIZE) {
|
|
232
|
+
console.error(
|
|
233
|
+
`File too large (${formatFileSize(stat.size)}, max ${formatFileSize(MAX_FILE_SIZE)})`
|
|
234
|
+
);
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
const content = readFileSync(filePath);
|
|
238
|
+
const filename = basename(filePath);
|
|
239
|
+
const senderName = flags.sender || userInfo().username;
|
|
240
|
+
const res = await daemonFetch(`/api/minds/${encodeURIComponent(targetName)}/files/stage`, {
|
|
241
|
+
method: "POST",
|
|
242
|
+
headers: { "Content-Type": "application/json" },
|
|
243
|
+
body: JSON.stringify({
|
|
244
|
+
sender: senderName,
|
|
245
|
+
filename,
|
|
246
|
+
data: content.toString("base64")
|
|
247
|
+
})
|
|
248
|
+
});
|
|
249
|
+
if (!res.ok) {
|
|
250
|
+
const data2 = await res.json();
|
|
251
|
+
console.error(data2.error ?? `Failed to stage file: ${res.status}`);
|
|
252
|
+
process.exit(1);
|
|
253
|
+
}
|
|
254
|
+
const data = await res.json();
|
|
255
|
+
console.log(`File staged for ${targetName} (id: ${data.id})`);
|
|
256
|
+
}
|
|
257
|
+
if (!message) return;
|
|
258
|
+
}
|
|
259
|
+
let parsed = parseTarget(target);
|
|
260
|
+
if (!parsed.isDM && parsed.platform === "volute" && await isMind(parsed.identifier)) {
|
|
261
|
+
parsed = {
|
|
262
|
+
platform: "volute",
|
|
263
|
+
identifier: `@${parsed.identifier}`,
|
|
264
|
+
uri: `@${parsed.identifier}`,
|
|
265
|
+
isDM: true
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
const client = getClient();
|
|
269
|
+
let waitMindName;
|
|
270
|
+
let waitConversationId;
|
|
271
|
+
if (parsed.isDM && parsed.platform === "volute") {
|
|
272
|
+
const targetName = parsed.identifier.slice(1);
|
|
273
|
+
const mindSelf = process.env.VOLUTE_MIND;
|
|
274
|
+
const sender = flags.sender || mindSelf || userInfo().username;
|
|
275
|
+
const targetIsMind = await isMind(targetName);
|
|
276
|
+
waitMindName = targetIsMind ? targetName : void 0;
|
|
277
|
+
const contextMind = mindSelf ?? targetName;
|
|
278
|
+
const participants = mindSelf ? [targetName] : [sender];
|
|
279
|
+
const createRes = await daemonFetch(
|
|
280
|
+
urlOf(client.api.minds[":name"].channels.create.$url({ param: { name: contextMind } })),
|
|
281
|
+
{
|
|
282
|
+
method: "POST",
|
|
283
|
+
headers: { "Content-Type": "application/json" },
|
|
284
|
+
body: JSON.stringify({ platform: "volute", participants, sender })
|
|
285
|
+
}
|
|
286
|
+
);
|
|
287
|
+
if (!createRes.ok) {
|
|
288
|
+
const data = await createRes.json().catch(() => ({ error: "Unknown error" }));
|
|
289
|
+
console.error(data.error);
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
const { conversationId: convId } = await createRes.json();
|
|
293
|
+
if (convId) waitConversationId = convId;
|
|
294
|
+
const sendRes = await daemonFetch("/api/v1/chat", {
|
|
295
|
+
method: "POST",
|
|
296
|
+
headers: { "Content-Type": "application/json" },
|
|
297
|
+
body: JSON.stringify({
|
|
298
|
+
message: message ?? "",
|
|
299
|
+
conversationId: convId,
|
|
300
|
+
images,
|
|
301
|
+
sender,
|
|
302
|
+
targetMind: contextMind
|
|
303
|
+
})
|
|
304
|
+
});
|
|
305
|
+
if (!sendRes.ok) {
|
|
306
|
+
const data = await sendRes.json().catch(() => ({ error: "Unknown error" }));
|
|
307
|
+
console.error(data.error);
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
310
|
+
if (!flags.wait) {
|
|
311
|
+
let outboundId;
|
|
312
|
+
try {
|
|
313
|
+
const resData = await sendRes.json();
|
|
314
|
+
outboundId = resData.outboundId;
|
|
315
|
+
} catch (err) {
|
|
316
|
+
console.error(
|
|
317
|
+
`Warning: could not read outboundId from response: ${err.message}`
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
if (isCompact()) {
|
|
321
|
+
if (outboundId != null) console.log(`[volute:outbound:${outboundId}]`);
|
|
322
|
+
} else {
|
|
323
|
+
console.log(
|
|
324
|
+
`Message sent.${outboundId != null ? `
|
|
325
|
+
[volute:outbound:${outboundId}]` : ""}`
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
} else if (!parsed.isDM && parsed.platform === "volute") {
|
|
330
|
+
if (!parsed.identifier.startsWith("#")) {
|
|
331
|
+
console.error(
|
|
332
|
+
`Mind "${parsed.identifier}" not found.
|
|
333
|
+
To send a DM: volute chat send @${parsed.identifier} "..."
|
|
334
|
+
To send to channel: volute chat send #${parsed.identifier} "..."`
|
|
335
|
+
);
|
|
336
|
+
process.exit(1);
|
|
337
|
+
}
|
|
338
|
+
const channelName = parsed.identifier.slice(1);
|
|
339
|
+
const mindSelf = process.env.VOLUTE_MIND;
|
|
340
|
+
const sender = flags.sender || mindSelf || userInfo().username;
|
|
341
|
+
const channelRes = await daemonFetch(`/api/v1/channels/${encodeURIComponent(channelName)}`);
|
|
342
|
+
if (!channelRes.ok) {
|
|
343
|
+
console.error(`Channel "${channelName}" not found. Create it first or check the name.`);
|
|
344
|
+
process.exit(1);
|
|
345
|
+
}
|
|
346
|
+
const channelData = await channelRes.json();
|
|
347
|
+
const mindParticipant = channelData.participants?.find((p) => p.userType === "mind");
|
|
348
|
+
const contextMind = mindSelf ?? mindParticipant?.username;
|
|
349
|
+
if (!contextMind) {
|
|
350
|
+
console.error("No mind is a member of this channel. A mind must join the channel first.");
|
|
351
|
+
process.exit(1);
|
|
352
|
+
}
|
|
353
|
+
const sendRes = await daemonFetch("/api/v1/chat", {
|
|
354
|
+
method: "POST",
|
|
355
|
+
headers: { "Content-Type": "application/json" },
|
|
356
|
+
body: JSON.stringify({
|
|
357
|
+
message: message ?? "",
|
|
358
|
+
conversationId: channelData.id,
|
|
359
|
+
images,
|
|
360
|
+
sender,
|
|
361
|
+
targetMind: contextMind
|
|
362
|
+
})
|
|
363
|
+
});
|
|
364
|
+
if (!sendRes.ok) {
|
|
365
|
+
const data = await sendRes.json().catch(() => ({ error: "Unknown error" }));
|
|
366
|
+
console.error(data.error);
|
|
367
|
+
process.exit(1);
|
|
368
|
+
}
|
|
369
|
+
let outboundId;
|
|
370
|
+
try {
|
|
371
|
+
const resData = await sendRes.json();
|
|
372
|
+
outboundId = resData.outboundId;
|
|
373
|
+
} catch (err) {
|
|
374
|
+
console.error(
|
|
375
|
+
`Warning: could not read outboundId from response: ${err.message}`
|
|
376
|
+
);
|
|
377
|
+
}
|
|
378
|
+
if (isCompact()) {
|
|
379
|
+
if (outboundId != null) console.log(`[volute:outbound:${outboundId}]`);
|
|
380
|
+
} else {
|
|
381
|
+
console.log(
|
|
382
|
+
`Message sent.${outboundId != null ? `
|
|
383
|
+
[volute:outbound:${outboundId}]` : ""}`
|
|
384
|
+
);
|
|
385
|
+
}
|
|
386
|
+
} else {
|
|
387
|
+
console.error(
|
|
388
|
+
`Direct sends to ${parsed.platform} channels are no longer supported.
|
|
389
|
+
Use bridge channel names instead (e.g. volute chat send @mind-name or #channel-name).
|
|
390
|
+
See: volute chat bridge --help`
|
|
391
|
+
);
|
|
392
|
+
process.exit(1);
|
|
393
|
+
}
|
|
394
|
+
if (flags.wait && waitMindName) {
|
|
395
|
+
if (!waitConversationId) {
|
|
396
|
+
console.error("--wait requires a volute conversation (DM to a mind)");
|
|
397
|
+
process.exit(1);
|
|
398
|
+
}
|
|
399
|
+
await waitForResponse(waitMindName, waitConversationId, flags.timeout ?? 12e4);
|
|
400
|
+
} else if (flags.wait && !waitMindName) {
|
|
401
|
+
console.error("--wait is only supported when sending to a mind");
|
|
402
|
+
process.exit(1);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
var run = cmd.execute;
|
|
407
|
+
export {
|
|
408
|
+
run
|
|
409
|
+
};
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
LAUNCHD_PLIST_LABEL,
|
|
4
|
+
LAUNCHD_PLIST_PATH,
|
|
5
|
+
SYSTEM_LAUNCHD_PLIST_PATH,
|
|
6
|
+
SYSTEM_SERVICE_PATH,
|
|
7
|
+
USER_SYSTEMD_UNIT
|
|
8
|
+
} from "./chunk-2TGZJFAT.js";
|
|
9
|
+
import {
|
|
10
|
+
subcommands
|
|
11
|
+
} from "./chunk-TXSA4Q3V.js";
|
|
12
|
+
import "./chunk-O7IGP7ZW.js";
|
|
13
|
+
import "./chunk-AN2W47GW.js";
|
|
14
|
+
import "./chunk-VHJRZM2S.js";
|
|
15
|
+
import "./chunk-BDYXIWA5.js";
|
|
16
|
+
import "./chunk-5N7Y5WAM.js";
|
|
17
|
+
import "./chunk-7KJOFUNN.js";
|
|
18
|
+
|
|
19
|
+
// packages/cli/src/commands/service.ts
|
|
20
|
+
import { execFile } from "child_process";
|
|
21
|
+
import { existsSync } from "fs";
|
|
22
|
+
import { promisify } from "util";
|
|
23
|
+
var execFileAsync = promisify(execFile);
|
|
24
|
+
async function status() {
|
|
25
|
+
const platform = process.platform;
|
|
26
|
+
if (platform === "darwin") {
|
|
27
|
+
if (existsSync(SYSTEM_LAUNCHD_PLIST_PATH)) {
|
|
28
|
+
try {
|
|
29
|
+
const { stdout } = await execFileAsync("launchctl", ["list", LAUNCHD_PLIST_LABEL]);
|
|
30
|
+
console.log("System service (LaunchDaemon):");
|
|
31
|
+
console.log(stdout);
|
|
32
|
+
} catch {
|
|
33
|
+
console.log("System service installed but not currently loaded.");
|
|
34
|
+
}
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (!existsSync(LAUNCHD_PLIST_PATH)) {
|
|
38
|
+
console.log("Service not installed.");
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
const { stdout } = await execFileAsync("launchctl", ["list", LAUNCHD_PLIST_LABEL]);
|
|
43
|
+
console.log(stdout);
|
|
44
|
+
} catch {
|
|
45
|
+
console.log("Service installed but not currently loaded.");
|
|
46
|
+
}
|
|
47
|
+
} else if (platform === "linux") {
|
|
48
|
+
if (existsSync(SYSTEM_SERVICE_PATH)) {
|
|
49
|
+
try {
|
|
50
|
+
const { stdout } = await execFileAsync("systemctl", ["status", "volute", "--no-pager"]);
|
|
51
|
+
console.log(stdout);
|
|
52
|
+
} catch (err) {
|
|
53
|
+
const e = err;
|
|
54
|
+
if (e.stdout) {
|
|
55
|
+
console.log(e.stdout);
|
|
56
|
+
} else {
|
|
57
|
+
console.error("System service installed but could not retrieve status.");
|
|
58
|
+
if (e.stderr) console.error(e.stderr);
|
|
59
|
+
else if (e.message) console.error(e.message);
|
|
60
|
+
console.error("Try running: systemctl status volute");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (!existsSync(USER_SYSTEMD_UNIT)) {
|
|
66
|
+
console.log("Service not installed.");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const { stdout } = await execFileAsync("systemctl", [
|
|
71
|
+
"--user",
|
|
72
|
+
"status",
|
|
73
|
+
"volute",
|
|
74
|
+
"--no-pager"
|
|
75
|
+
]);
|
|
76
|
+
console.log(stdout);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
const e = err;
|
|
79
|
+
if (e.stdout) console.log(e.stdout);
|
|
80
|
+
else console.log("Service installed but status unknown.");
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
console.error(`Unsupported platform: ${platform}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
var cmd = subcommands({
|
|
88
|
+
name: "volute service",
|
|
89
|
+
description: "Manage the system service",
|
|
90
|
+
commands: {
|
|
91
|
+
status: {
|
|
92
|
+
description: "Check service status",
|
|
93
|
+
run: async () => status()
|
|
94
|
+
},
|
|
95
|
+
install: {
|
|
96
|
+
description: "(deprecated) Use 'volute setup' instead",
|
|
97
|
+
run: async () => {
|
|
98
|
+
console.log("'volute service install' has been replaced by 'volute setup'.");
|
|
99
|
+
console.log("Run `volute setup` to configure your installation.");
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
uninstall: {
|
|
103
|
+
description: "(deprecated) Use 'volute setup' instead",
|
|
104
|
+
run: async () => {
|
|
105
|
+
console.log("'volute service uninstall' has been replaced by 'volute setup'.");
|
|
106
|
+
console.log("To uninstall the service, remove the service file manually:");
|
|
107
|
+
if (process.platform === "darwin") {
|
|
108
|
+
console.log(" launchctl unload ~/Library/LaunchAgents/com.volute.daemon.plist");
|
|
109
|
+
console.log(" rm ~/Library/LaunchAgents/com.volute.daemon.plist");
|
|
110
|
+
} else {
|
|
111
|
+
console.log(" systemctl --user disable --now volute");
|
|
112
|
+
console.log(" rm ~/.config/systemd/user/volute.service");
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
var run = cmd.execute;
|
|
119
|
+
export {
|
|
120
|
+
run
|
|
121
|
+
};
|