volute 0.26.0 → 0.28.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 +18 -18
- package/dist/accept-666DIZX2.js +41 -0
- package/dist/{activity-events-ZMBAKLUF.js → activity-events-BBIEA2F4.js} +2 -3
- package/dist/api.d.ts +510 -299
- package/dist/{archive-4ZQYK5MN.js → archive-UA4BDFXQ.js} +2 -2
- package/dist/bridge-FQHZL3MC.js +206 -0
- package/dist/chat-M4SX42JD.js +68 -0
- package/dist/{chunk-PHU4DEAJ.js → chunk-2WPW7OT6.js} +3 -3
- package/dist/{chunk-5Y3PBKW6.js → chunk-2YP2TVDT.js} +138 -56
- package/dist/{chunk-3CFRE2VC.js → chunk-AAPXKR5V.js} +435 -1090
- package/dist/{chunk-YJA7P64S.js → chunk-AW7PFDVN.js} +5 -5
- package/dist/{chunk-OZFKBXD6.js → chunk-EHYDTZTF.js} +6 -6
- package/dist/{chunk-WBHMQ5OZ.js → chunk-H7OZRFJB.js} +192 -12
- package/dist/{chunk-ON3FF5JA.js → chunk-HDN7MNGD.js} +3 -3
- package/dist/chunk-IAYBDWVG.js +477 -0
- package/dist/{chunk-TZKJLDQN.js → chunk-IKRVFPWU.js} +14 -9
- package/dist/{chunk-UTL75LP6.js → chunk-J4IBNXGJ.js} +20 -22
- package/dist/{chunk-WGOGUMPO.js → chunk-JGFVMROS.js} +13 -6
- package/dist/{chunk-NWI2425I.js → chunk-K5NAC55T.js} +1 -1
- package/dist/chunk-KTLFDYPT.js +61 -0
- package/dist/{chunk-V63B7DX3.js → chunk-LAC664WU.js} +7 -4
- package/dist/chunk-MD4C26II.js +128 -0
- package/dist/{chunk-USNBKHYG.js → chunk-NI5FFCCS.js} +12 -7
- package/dist/{chunk-3TV4GLFO.js → chunk-P72MVS4R.js} +4 -43
- package/dist/{chunk-2VO7453N.js → chunk-POSXWWTA.js} +30 -54
- package/dist/{chunk-XOXLRRR2.js → chunk-RKQEHRBB.js} +4 -3
- package/dist/{chunk-LX22GRG7.js → chunk-SGVNFZHW.js} +11 -8
- package/dist/chunk-T6HKBWXZ.js +23 -0
- package/dist/{chunk-J2CO4WEV.js → chunk-VIVMW2H2.js} +4 -4
- package/dist/{chunk-KTJGZ7M7.js → chunk-XBLSAVJF.js} +1 -1
- package/dist/cli.js +32 -49
- package/dist/{cloud-sync-NI2K3C7G.js → cloud-sync-HDL6PHZI.js} +14 -14
- package/dist/connectors/discord-bridge.js +158 -0
- package/dist/connectors/slack-bridge.js +119 -0
- package/dist/connectors/telegram-bridge.js +133 -0
- package/dist/conversations-M2K4253F.js +55 -0
- package/dist/create-D7J73A6H.js +45 -0
- package/dist/{create-4YBRTTJS.js → create-QWV73WXD.js} +1 -1
- package/dist/{daemon-client-Z7FAJ6JW.js → daemon-client-I42FK2BF.js} +2 -2
- package/dist/{daemon-restart-BJZ3O4U4.js → daemon-restart-G4B2OYAB.js} +7 -7
- package/dist/daemon.js +1889 -1216
- package/dist/db-IC4J52XQ.js +8 -0
- package/dist/{delete-27OYNK25.js → delete-4JYGD4VN.js} +1 -1
- package/dist/down-LVBXEULC.js +14 -0
- package/dist/{env-M336ONDP.js → env-YJMUMFIY.js} +2 -2
- package/dist/{export-HP4G5DQC.js → export-BOJQWBMA.js} +4 -4
- package/dist/files-M546TKVN.js +46 -0
- package/dist/{history-B64GTFTD.js → history-ALPTNB3I.js} +5 -5
- package/dist/{import-XIB7UV4S.js → import-SRTQXBGH.js} +4 -4
- package/dist/join-J4QU42DL.js +66 -0
- package/dist/list-R73GENNL.js +40 -0
- package/dist/{login-B5E7N7MY.js → login-3QZNR2DF.js} +4 -4
- package/dist/{login-6U7U6BNG.js → login-BKP3AFWN.js} +8 -18
- package/dist/logout-IQK7FNEK.js +20 -0
- package/dist/{logout-XSJRYS3U.js → logout-T53VKCPU.js} +4 -4
- package/dist/message-delivery-HV3S6HZV.js +24 -0
- package/dist/migrate-registry-to-db-XC7T5B7P.js +110 -0
- package/dist/{mind-HZ3QSDDJ.js → mind-S5V6CK5W.js} +29 -34
- package/dist/{mind-activity-tracker-4G6FURY2.js → mind-activity-tracker-EN6XNXPF.js} +3 -4
- package/dist/mind-list-UPJ75GPI.js +29 -0
- package/dist/mind-manager-S6ILZVX3.js +18 -0
- package/dist/{mind-sleep-DTV7L44D.js → mind-sleep-BTSWQNAC.js} +4 -4
- package/dist/mind-status-TK5AETEM.js +55 -0
- package/dist/{mind-wake-PFN4FN3T.js → mind-wake-SBAKIDVP.js} +4 -4
- package/dist/{notes-37FW2UR2.js → notes-XCER3I7M.js} +11 -21
- package/dist/{package-VZWLXPHV.js → package-CG4RWUGP.js} +1 -1
- package/dist/{pages-DIIT5HMQ.js → pages-KJDJX4TA.js} +5 -5
- package/dist/{publish-HQV7YREB.js → publish-ZZB33WP4.js} +9 -20
- package/dist/read-36UFXN3G.js +46 -0
- package/dist/{register-EFND67FQ.js → register-CHREOMJ3.js} +6 -25
- package/dist/{registry-D2BSQ2X5.js → registry-NDNOOYG4.js} +15 -9
- package/dist/reject-LXIZFJ4Q.js +39 -0
- package/dist/{restart-CCK7D6TV.js → restart-6ESL3NBO.js} +5 -5
- package/dist/{sandbox-EHGFF52K.js → sandbox-5BW5HPXM.js} +3 -3
- package/dist/{schedule-6F7ELB2M.js → schedule-QTJMFATP.js} +5 -5
- package/dist/{seed-E5OQGWX3.js → seed-SSUCYYDF.js} +2 -2
- package/dist/{send-IH6XZKPC.js → send-TAOEZ4NH.js} +87 -23
- package/dist/{setup-YGAAIKKZ.js → setup-JHL5ZEST.js} +2 -2
- package/dist/{setup-F6TWFYGQ.js → setup-RXYVGGT7.js} +9 -9
- package/dist/{skill-42LGFBQC.js → skill-AUAQTSP5.js} +5 -5
- package/dist/skills/dreaming/references/INSTALL.md +2 -2
- package/dist/skills/orientation/SKILL.md +3 -3
- package/dist/skills/shared-files/SKILL.md +44 -0
- package/dist/skills/shared-files/scripts/merge.ts +72 -0
- package/dist/skills/shared-files/scripts/pull.ts +52 -0
- package/dist/skills/volute-mind/SKILL.md +35 -34
- package/dist/sleep-manager-WMVG2VCL.js +28 -0
- package/dist/split-TKJ5OT3P.js +63 -0
- package/dist/{sprout-QL74KR2X.js → sprout-UNT7LKKE.js} +6 -7
- package/dist/{start-O5JQASRC.js → start-EUJSS5R4.js} +2 -2
- package/dist/status-NQJYR4BG.js +114 -0
- package/dist/{status-LV34BG6G.js → status-S7UUPNRW.js} +4 -14
- package/dist/{stop-2SOG5NYF.js → stop-3XAITBBF.js} +5 -5
- package/dist/systems-SMEFSHTA.js +60 -0
- package/dist/{tailscale-AJ4VL5XK.js → tailscale-NY5MUMY3.js} +1 -1
- package/dist/up-GM2JOH2Y.js +17 -0
- package/dist/{update-5VUDAI3D.js → update-PTSH22AZ.js} +9 -9
- package/dist/{update-check-F5Z3ALXX.js → update-check-64FWC4Y2.js} +2 -2
- package/dist/{upgrade-QCCO33BK.js → upgrade-HA47CS4C.js} +12 -5
- package/dist/variant-7TGZHOU3.js +41 -0
- package/dist/{version-notify-USFZBWMG.js → version-notify-JDUF4HQJ.js} +24 -29
- package/dist/web-assets/assets/index-BZGvToHi.css +1 -0
- package/dist/web-assets/assets/index-Cz4TrpzB.js +75 -0
- package/dist/web-assets/favicon.png +0 -0
- package/dist/web-assets/index.html +2 -2
- package/drizzle/0017_minds.sql +16 -0
- package/drizzle/meta/_journal.json +7 -0
- package/package.json +1 -1
- package/templates/_base/.init/.config/prompts.json +2 -2
- package/templates/_base/home/VOLUTE.md +5 -5
- package/templates/_base/src/lib/logger.ts +0 -4
- package/templates/_base/src/lib/startup.ts +2 -2
- package/dist/auth-4TV573WE.js +0 -37
- package/dist/channel-ZVZV42UD.js +0 -260
- package/dist/chunk-B2CPS4QU.js +0 -283
- package/dist/chunk-HFCBO2GL.js +0 -50
- package/dist/chunk-RWKVSSLY.js +0 -26
- package/dist/chunk-SIAG3QMM.js +0 -42
- package/dist/chunk-WSLPZF72.js +0 -173
- package/dist/connector-G722WXAU.js +0 -147
- package/dist/connectors/discord.js +0 -177
- package/dist/connectors/slack.js +0 -181
- package/dist/connectors/telegram.js +0 -187
- package/dist/down-7UKFMJJZ.js +0 -14
- package/dist/file-HUDKTRAS.js +0 -204
- package/dist/log-PBFNILJ4.js +0 -39
- package/dist/logout-UKD5LA37.js +0 -18
- package/dist/logs-3CART7O7.js +0 -77
- package/dist/merge-VK2HSKMA.js +0 -46
- package/dist/message-delivery-MS5JYPZX.js +0 -25
- package/dist/mind-manager-VVK67AY3.js +0 -19
- package/dist/pull-2MB4SK3C.js +0 -39
- package/dist/service-LLBV3R7M.js +0 -122
- package/dist/shared-UMO4S7CC.js +0 -39
- package/dist/sleep-manager-EE4NRN2Q.js +0 -29
- package/dist/status-FZBEBM7Q.js +0 -70
- package/dist/status-WXD4HXRL.js +0 -35
- package/dist/up-SDMCSVI3.js +0 -17
- package/dist/variant-WWLDY6D5.js +0 -207
- package/dist/web-assets/assets/index-CUQ31ieL.js +0 -69
- package/dist/web-assets/assets/index-CW8NSl1o.css +0 -1
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
daemonFetch
|
|
4
|
+
} from "./chunk-JGFVMROS.js";
|
|
5
|
+
import {
|
|
6
|
+
parseArgs
|
|
7
|
+
} from "./chunk-D424ZQGI.js";
|
|
8
|
+
import "./chunk-H7OZRFJB.js";
|
|
9
|
+
import "./chunk-K3NQKI34.js";
|
|
10
|
+
|
|
11
|
+
// src/commands/chat/bridge.ts
|
|
12
|
+
async function run(args) {
|
|
13
|
+
const subcommand = args[0];
|
|
14
|
+
const subArgs = args.slice(1);
|
|
15
|
+
switch (subcommand) {
|
|
16
|
+
case "add":
|
|
17
|
+
await bridgeAdd(subArgs);
|
|
18
|
+
break;
|
|
19
|
+
case "remove":
|
|
20
|
+
await bridgeRemove(subArgs);
|
|
21
|
+
break;
|
|
22
|
+
case "list":
|
|
23
|
+
await bridgeList();
|
|
24
|
+
break;
|
|
25
|
+
case "map":
|
|
26
|
+
await bridgeMap(subArgs);
|
|
27
|
+
break;
|
|
28
|
+
case "unmap":
|
|
29
|
+
await bridgeUnmap(subArgs);
|
|
30
|
+
break;
|
|
31
|
+
case "mappings":
|
|
32
|
+
await bridgeMappings(subArgs);
|
|
33
|
+
break;
|
|
34
|
+
case "--help":
|
|
35
|
+
case "-h":
|
|
36
|
+
case void 0:
|
|
37
|
+
console.log(`volute chat bridge \u2014 manage platform bridges
|
|
38
|
+
|
|
39
|
+
add <platform> Set up a bridge (e.g. discord, slack, telegram)
|
|
40
|
+
remove <platform> Remove a bridge
|
|
41
|
+
list Show bridges + status
|
|
42
|
+
map <platform>:<channel> <ch> Map external \u2192 Volute channel
|
|
43
|
+
unmap <platform>:<channel> Remove mapping
|
|
44
|
+
mappings [<platform>] List mappings`);
|
|
45
|
+
break;
|
|
46
|
+
default:
|
|
47
|
+
console.error(
|
|
48
|
+
`Unknown bridge subcommand: ${subcommand}
|
|
49
|
+
Run 'volute chat bridge --help' for usage.`
|
|
50
|
+
);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async function bridgeAdd(args) {
|
|
55
|
+
const { positional, flags } = parseArgs(args, {
|
|
56
|
+
"default-mind": { type: "string" }
|
|
57
|
+
});
|
|
58
|
+
const platform = positional[0];
|
|
59
|
+
if (!platform) {
|
|
60
|
+
console.error("Usage: volute chat bridge add <platform> --default-mind <name>");
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
const defaultMind = flags["default-mind"];
|
|
64
|
+
if (!defaultMind) {
|
|
65
|
+
console.error("--default-mind is required (mind to route DMs to)");
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
const res = await daemonFetch(`/api/bridges/${encodeURIComponent(platform)}`, {
|
|
69
|
+
method: "POST",
|
|
70
|
+
headers: { "Content-Type": "application/json" },
|
|
71
|
+
body: JSON.stringify({ defaultMind })
|
|
72
|
+
});
|
|
73
|
+
if (!res.ok) {
|
|
74
|
+
const data = await res.json().catch(() => ({}));
|
|
75
|
+
if (data.error === "missing_env" && data.missing) {
|
|
76
|
+
console.error(`Missing required environment variables:`);
|
|
77
|
+
for (const v of data.missing) {
|
|
78
|
+
console.error(` ${v.name} \u2014 ${v.description}`);
|
|
79
|
+
}
|
|
80
|
+
console.error(`
|
|
81
|
+
Set them with: volute env set <VAR> <value>`);
|
|
82
|
+
} else {
|
|
83
|
+
console.error(data.error ?? `Failed to add bridge: ${res.status}`);
|
|
84
|
+
}
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
console.log(`Bridge ${platform} enabled.`);
|
|
88
|
+
}
|
|
89
|
+
async function bridgeRemove(args) {
|
|
90
|
+
const platform = args[0];
|
|
91
|
+
if (!platform) {
|
|
92
|
+
console.error("Usage: volute chat bridge remove <platform>");
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
const res = await daemonFetch(`/api/bridges/${encodeURIComponent(platform)}`, {
|
|
96
|
+
method: "DELETE"
|
|
97
|
+
});
|
|
98
|
+
if (!res.ok) {
|
|
99
|
+
console.error(`Failed to remove bridge: ${res.status}`);
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
console.log(`Bridge ${platform} removed.`);
|
|
103
|
+
}
|
|
104
|
+
async function bridgeList() {
|
|
105
|
+
const res = await daemonFetch("/api/bridges");
|
|
106
|
+
if (!res.ok) {
|
|
107
|
+
console.error(`Failed to list bridges: ${res.status}`);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
const bridges = await res.json();
|
|
111
|
+
if (bridges.length === 0) {
|
|
112
|
+
console.log("No bridges configured. Use 'volute chat bridge add <platform>' to set one up.");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
for (const b of bridges) {
|
|
116
|
+
const status = b.running ? "running" : b.enabled ? "stopped" : "disabled";
|
|
117
|
+
console.log(` ${b.displayName} (${b.platform}) ${status} default: ${b.defaultMind}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
async function bridgeMap(args) {
|
|
121
|
+
const target = args[0];
|
|
122
|
+
const voluteChannel = args[1];
|
|
123
|
+
if (!target || !voluteChannel) {
|
|
124
|
+
console.error("Usage: volute chat bridge map <platform>:<channel> <volute-channel>");
|
|
125
|
+
process.exit(1);
|
|
126
|
+
}
|
|
127
|
+
const colonIdx = target.indexOf(":");
|
|
128
|
+
if (colonIdx < 1) {
|
|
129
|
+
console.error("Target must be in format platform:channel (e.g. discord:my-server/general)");
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
const platform = target.slice(0, colonIdx);
|
|
133
|
+
const externalChannel = target.slice(colonIdx + 1);
|
|
134
|
+
const res = await daemonFetch(`/api/bridges/${encodeURIComponent(platform)}/mappings`, {
|
|
135
|
+
method: "PUT",
|
|
136
|
+
headers: { "Content-Type": "application/json" },
|
|
137
|
+
body: JSON.stringify({ externalChannel, voluteChannel })
|
|
138
|
+
});
|
|
139
|
+
if (!res.ok) {
|
|
140
|
+
const data = await res.json().catch(() => ({}));
|
|
141
|
+
console.error(data.error ?? `Failed to set mapping: ${res.status}`);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
console.log(`Mapped ${platform}:${externalChannel} \u2192 ${voluteChannel}`);
|
|
145
|
+
}
|
|
146
|
+
async function bridgeUnmap(args) {
|
|
147
|
+
const target = args[0];
|
|
148
|
+
if (!target) {
|
|
149
|
+
console.error("Usage: volute chat bridge unmap <platform>:<channel>");
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
const colonIdx = target.indexOf(":");
|
|
153
|
+
if (colonIdx < 1) {
|
|
154
|
+
console.error("Target must be in format platform:channel");
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
const platform = target.slice(0, colonIdx);
|
|
158
|
+
const externalChannel = target.slice(colonIdx + 1);
|
|
159
|
+
const res = await daemonFetch(
|
|
160
|
+
`/api/bridges/${encodeURIComponent(platform)}/mappings/${encodeURIComponent(externalChannel)}`,
|
|
161
|
+
{ method: "DELETE" }
|
|
162
|
+
);
|
|
163
|
+
if (!res.ok) {
|
|
164
|
+
console.error(`Failed to remove mapping: ${res.status}`);
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
console.log(`Removed mapping for ${platform}:${externalChannel}`);
|
|
168
|
+
}
|
|
169
|
+
async function bridgeMappings(args) {
|
|
170
|
+
const platform = args[0];
|
|
171
|
+
if (platform) {
|
|
172
|
+
const res = await daemonFetch(`/api/bridges/${encodeURIComponent(platform)}/mappings`);
|
|
173
|
+
if (!res.ok) {
|
|
174
|
+
console.error(`Failed to get mappings: ${res.status}`);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
const mappings = await res.json();
|
|
178
|
+
if (Object.keys(mappings).length === 0) {
|
|
179
|
+
console.log(`No mappings for ${platform}.`);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
for (const [external, volute] of Object.entries(mappings)) {
|
|
183
|
+
console.log(` ${platform}:${external} \u2192 ${volute}`);
|
|
184
|
+
}
|
|
185
|
+
} else {
|
|
186
|
+
const res = await daemonFetch("/api/bridges");
|
|
187
|
+
if (!res.ok) {
|
|
188
|
+
console.error(`Failed to list bridges: ${res.status}`);
|
|
189
|
+
process.exit(1);
|
|
190
|
+
}
|
|
191
|
+
const bridges = await res.json();
|
|
192
|
+
let found = false;
|
|
193
|
+
for (const b of bridges) {
|
|
194
|
+
for (const [external, volute] of Object.entries(b.channelMappings)) {
|
|
195
|
+
console.log(` ${b.platform}:${external} \u2192 ${volute}`);
|
|
196
|
+
found = true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (!found) {
|
|
200
|
+
console.log("No mappings configured.");
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
export {
|
|
205
|
+
run
|
|
206
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import "./chunk-K3NQKI34.js";
|
|
3
|
+
|
|
4
|
+
// src/commands/chat.ts
|
|
5
|
+
async function run(args) {
|
|
6
|
+
const subcommand = args[0];
|
|
7
|
+
const subArgs = args.slice(1);
|
|
8
|
+
switch (subcommand) {
|
|
9
|
+
case "send":
|
|
10
|
+
await import("./send-TAOEZ4NH.js").then((m) => m.run(subArgs));
|
|
11
|
+
break;
|
|
12
|
+
case "list":
|
|
13
|
+
await import("./list-R73GENNL.js").then((m) => m.run(subArgs));
|
|
14
|
+
break;
|
|
15
|
+
case "read":
|
|
16
|
+
await import("./read-36UFXN3G.js").then((m) => m.run(subArgs));
|
|
17
|
+
break;
|
|
18
|
+
case "create":
|
|
19
|
+
await import("./create-D7J73A6H.js").then((m) => m.run(subArgs));
|
|
20
|
+
break;
|
|
21
|
+
case "bridge":
|
|
22
|
+
await import("./bridge-FQHZL3MC.js").then((m) => m.run(subArgs));
|
|
23
|
+
break;
|
|
24
|
+
case "files":
|
|
25
|
+
await import("./files-M546TKVN.js").then((m) => m.run(subArgs));
|
|
26
|
+
break;
|
|
27
|
+
case "accept":
|
|
28
|
+
await import("./accept-666DIZX2.js").then((m) => m.run(subArgs));
|
|
29
|
+
break;
|
|
30
|
+
case "reject":
|
|
31
|
+
await import("./reject-LXIZFJ4Q.js").then((m) => m.run(subArgs));
|
|
32
|
+
break;
|
|
33
|
+
case "--help":
|
|
34
|
+
case "-h":
|
|
35
|
+
case void 0:
|
|
36
|
+
console.log(`volute chat \u2014 conversations, files, and bridges
|
|
37
|
+
|
|
38
|
+
Messages:
|
|
39
|
+
send <target> "<msg>" Send a message (--image, --file)
|
|
40
|
+
list List conversations
|
|
41
|
+
read <conversation> [--limit] Read conversation messages
|
|
42
|
+
create --participants u1,u2 Create a conversation
|
|
43
|
+
|
|
44
|
+
Files:
|
|
45
|
+
files [--mind <name>] List pending incoming files
|
|
46
|
+
accept <id> [--mind] [--dest] Accept a pending file
|
|
47
|
+
reject <id> [--mind] Reject a pending file
|
|
48
|
+
|
|
49
|
+
Bridges:
|
|
50
|
+
bridge add <platform> Set up a bridge
|
|
51
|
+
bridge remove <platform> Remove a bridge
|
|
52
|
+
bridge list Show bridges + status
|
|
53
|
+
bridge map <p>:<ch> <volute> Map external \u2192 Volute channel
|
|
54
|
+
bridge unmap <p>:<ch> Remove mapping
|
|
55
|
+
bridge mappings [<platform>] List mappings
|
|
56
|
+
|
|
57
|
+
Send targets: @mindname for DMs, channel-name for conversations.
|
|
58
|
+
Mind-scoped commands use --mind <name> or VOLUTE_MIND env var.`);
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
console.error(`Unknown chat subcommand: ${subcommand}
|
|
62
|
+
Run 'volute chat --help' for usage.`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export {
|
|
67
|
+
run
|
|
68
|
+
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
stateDir,
|
|
4
|
-
|
|
5
|
-
} from "./chunk-
|
|
4
|
+
voluteSystemDir
|
|
5
|
+
} from "./chunk-H7OZRFJB.js";
|
|
6
6
|
|
|
7
7
|
// src/lib/env.ts
|
|
8
8
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
9
9
|
import { dirname, resolve } from "path";
|
|
10
10
|
function sharedEnvPath() {
|
|
11
|
-
return resolve(
|
|
11
|
+
return resolve(voluteSystemDir(), "env.json");
|
|
12
12
|
}
|
|
13
13
|
function mindEnvPath(mindName) {
|
|
14
14
|
return resolve(stateDir(mindName), "env.json");
|
|
@@ -1,32 +1,105 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
readVoluteConfig,
|
|
4
|
-
writeVoluteConfig
|
|
5
|
-
} from "./chunk-SIAG3QMM.js";
|
|
6
|
-
import {
|
|
7
|
-
mindEnvPath,
|
|
8
3
|
readEnv,
|
|
4
|
+
sharedEnvPath,
|
|
9
5
|
writeEnv
|
|
10
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2WPW7OT6.js";
|
|
7
|
+
import {
|
|
8
|
+
logger_default
|
|
9
|
+
} from "./chunk-YUIHSKR6.js";
|
|
11
10
|
import {
|
|
12
11
|
parseArgs
|
|
13
12
|
} from "./chunk-D424ZQGI.js";
|
|
13
|
+
import {
|
|
14
|
+
voluteSystemDir
|
|
15
|
+
} from "./chunk-H7OZRFJB.js";
|
|
14
16
|
|
|
15
17
|
// src/commands/import.ts
|
|
16
18
|
import {
|
|
17
19
|
closeSync,
|
|
18
|
-
existsSync,
|
|
20
|
+
existsSync as existsSync2,
|
|
19
21
|
mkdirSync,
|
|
20
22
|
openSync,
|
|
21
23
|
readdirSync,
|
|
22
|
-
readFileSync,
|
|
24
|
+
readFileSync as readFileSync2,
|
|
23
25
|
readSync,
|
|
24
26
|
rmSync,
|
|
25
27
|
statSync,
|
|
26
|
-
writeFileSync
|
|
28
|
+
writeFileSync as writeFileSync2
|
|
27
29
|
} from "fs";
|
|
28
30
|
import { homedir, tmpdir } from "os";
|
|
29
|
-
import { basename, resolve } from "path";
|
|
31
|
+
import { basename, resolve as resolve2 } from "path";
|
|
32
|
+
|
|
33
|
+
// src/lib/bridges.ts
|
|
34
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
35
|
+
import { resolve } from "path";
|
|
36
|
+
function bridgesPath() {
|
|
37
|
+
return resolve(voluteSystemDir(), "bridges.json");
|
|
38
|
+
}
|
|
39
|
+
function readBridgesConfig() {
|
|
40
|
+
const path = bridgesPath();
|
|
41
|
+
if (!existsSync(path)) return {};
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
44
|
+
} catch (err) {
|
|
45
|
+
logger_default.error(
|
|
46
|
+
`bridges.json is corrupt or unreadable at ${path} \u2014 all bridges disabled`,
|
|
47
|
+
logger_default.errorData(err)
|
|
48
|
+
);
|
|
49
|
+
return {};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function writeBridgesConfig(config) {
|
|
53
|
+
writeFileSync(bridgesPath(), `${JSON.stringify(config, null, 2)}
|
|
54
|
+
`, { mode: 384 });
|
|
55
|
+
}
|
|
56
|
+
function getBridgeConfig(platform) {
|
|
57
|
+
const config = readBridgesConfig();
|
|
58
|
+
return config[platform] ?? null;
|
|
59
|
+
}
|
|
60
|
+
function setBridgeConfig(platform, bridge) {
|
|
61
|
+
const config = readBridgesConfig();
|
|
62
|
+
config[platform] = bridge;
|
|
63
|
+
writeBridgesConfig(config);
|
|
64
|
+
}
|
|
65
|
+
function removeBridgeConfig(platform) {
|
|
66
|
+
const config = readBridgesConfig();
|
|
67
|
+
delete config[platform];
|
|
68
|
+
writeBridgesConfig(config);
|
|
69
|
+
}
|
|
70
|
+
function setChannelMapping(platform, externalChannel, voluteChannel) {
|
|
71
|
+
const config = readBridgesConfig();
|
|
72
|
+
const bridge = config[platform];
|
|
73
|
+
if (!bridge) throw new Error(`Bridge not configured for ${platform}`);
|
|
74
|
+
bridge.channelMappings[externalChannel] = voluteChannel;
|
|
75
|
+
writeBridgesConfig(config);
|
|
76
|
+
}
|
|
77
|
+
function removeChannelMapping(platform, externalChannel) {
|
|
78
|
+
const config = readBridgesConfig();
|
|
79
|
+
const bridge = config[platform];
|
|
80
|
+
if (!bridge) return;
|
|
81
|
+
delete bridge.channelMappings[externalChannel];
|
|
82
|
+
writeBridgesConfig(config);
|
|
83
|
+
}
|
|
84
|
+
function resolveChannelMapping(platform, externalChannel) {
|
|
85
|
+
const bridge = getBridgeConfig(platform);
|
|
86
|
+
if (!bridge) return null;
|
|
87
|
+
return bridge.channelMappings[externalChannel] ?? null;
|
|
88
|
+
}
|
|
89
|
+
function findBridgeForChannel(voluteChannelName) {
|
|
90
|
+
const config = readBridgesConfig();
|
|
91
|
+
for (const [platform, bridge] of Object.entries(config)) {
|
|
92
|
+
if (!bridge.enabled) continue;
|
|
93
|
+
for (const [external, volute] of Object.entries(bridge.channelMappings)) {
|
|
94
|
+
if (volute === voluteChannelName) {
|
|
95
|
+
return { platform, externalChannel: external };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/commands/import.ts
|
|
30
103
|
async function run(args) {
|
|
31
104
|
const { positional, flags } = parseArgs(args, {
|
|
32
105
|
name: { type: "string" },
|
|
@@ -35,11 +108,11 @@ async function run(args) {
|
|
|
35
108
|
});
|
|
36
109
|
const inputPath = positional[0];
|
|
37
110
|
if (inputPath && (inputPath.endsWith(".volute") || isZipFile(inputPath))) {
|
|
38
|
-
await importArchive(
|
|
111
|
+
await importArchive(resolve2(inputPath), flags.name);
|
|
39
112
|
return;
|
|
40
113
|
}
|
|
41
114
|
const wsDir = resolveWorkspace(inputPath);
|
|
42
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
115
|
+
const { daemonFetch } = await import("./daemon-client-I42FK2BF.js");
|
|
43
116
|
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
44
117
|
const client = getClient();
|
|
45
118
|
const res = await daemonFetch(urlOf(client.api.minds.import.$url()), {
|
|
@@ -63,8 +136,8 @@ ${data.message ?? `Imported mind: ${data.name} (port ${data.port})`}`);
|
|
|
63
136
|
volute mind start ${data.name}`);
|
|
64
137
|
}
|
|
65
138
|
function isZipFile(path) {
|
|
66
|
-
const resolved =
|
|
67
|
-
if (!
|
|
139
|
+
const resolved = resolve2(path);
|
|
140
|
+
if (!existsSync2(resolved)) return false;
|
|
68
141
|
const fd = openSync(resolved, "r");
|
|
69
142
|
try {
|
|
70
143
|
const buf = Buffer.alloc(4);
|
|
@@ -75,12 +148,12 @@ function isZipFile(path) {
|
|
|
75
148
|
}
|
|
76
149
|
}
|
|
77
150
|
async function importArchive(archivePath, nameOverride) {
|
|
78
|
-
if (!
|
|
151
|
+
if (!existsSync2(archivePath)) {
|
|
79
152
|
console.error(`File not found: ${archivePath}`);
|
|
80
153
|
process.exit(1);
|
|
81
154
|
}
|
|
82
|
-
const { extractArchive } = await import("./archive-
|
|
83
|
-
const tempDir =
|
|
155
|
+
const { extractArchive } = await import("./archive-UA4BDFXQ.js");
|
|
156
|
+
const tempDir = resolve2(tmpdir(), `volute-import-${Date.now()}`);
|
|
84
157
|
mkdirSync(tempDir, { recursive: true });
|
|
85
158
|
let extracted;
|
|
86
159
|
try {
|
|
@@ -91,7 +164,7 @@ async function importArchive(archivePath, nameOverride) {
|
|
|
91
164
|
process.exit(1);
|
|
92
165
|
}
|
|
93
166
|
try {
|
|
94
|
-
const { daemonFetch } = await import("./daemon-client-
|
|
167
|
+
const { daemonFetch } = await import("./daemon-client-I42FK2BF.js");
|
|
95
168
|
const { getClient, urlOf } = await import("./api-client-YPKOZP2O.js");
|
|
96
169
|
const client = getClient();
|
|
97
170
|
const res = await daemonFetch(urlOf(client.api.minds.import.$url()), {
|
|
@@ -119,20 +192,20 @@ ${data.message ?? `Imported mind: ${data.name} (port ${data.port})`}`);
|
|
|
119
192
|
}
|
|
120
193
|
function resolveWorkspace(explicitPath) {
|
|
121
194
|
if (explicitPath) {
|
|
122
|
-
const wsDir =
|
|
123
|
-
if (!
|
|
195
|
+
const wsDir = resolve2(explicitPath);
|
|
196
|
+
if (!existsSync2(resolve2(wsDir, "SOUL.md")) || !existsSync2(resolve2(wsDir, "IDENTITY.md"))) {
|
|
124
197
|
console.error("Not a valid OpenClaw workspace: missing SOUL.md or IDENTITY.md");
|
|
125
198
|
process.exit(1);
|
|
126
199
|
}
|
|
127
200
|
return wsDir;
|
|
128
201
|
}
|
|
129
202
|
const cwd = process.cwd();
|
|
130
|
-
if (
|
|
203
|
+
if (existsSync2(resolve2(cwd, "SOUL.md")) && existsSync2(resolve2(cwd, "IDENTITY.md"))) {
|
|
131
204
|
console.log(`Using workspace: ${cwd}`);
|
|
132
205
|
return cwd;
|
|
133
206
|
}
|
|
134
|
-
const openclawWs =
|
|
135
|
-
if (
|
|
207
|
+
const openclawWs = resolve2(homedir(), ".openclaw/workspace");
|
|
208
|
+
if (existsSync2(resolve2(openclawWs, "SOUL.md")) && existsSync2(resolve2(openclawWs, "IDENTITY.md"))) {
|
|
136
209
|
console.log(`Using workspace: ${openclawWs}`);
|
|
137
210
|
return openclawWs;
|
|
138
211
|
}
|
|
@@ -142,16 +215,16 @@ function resolveWorkspace(explicitPath) {
|
|
|
142
215
|
process.exit(1);
|
|
143
216
|
}
|
|
144
217
|
function findOpenClawSession(workspaceDir) {
|
|
145
|
-
const ocAgentsDir =
|
|
146
|
-
if (!
|
|
218
|
+
const ocAgentsDir = resolve2(homedir(), ".openclaw/agents");
|
|
219
|
+
if (!existsSync2(ocAgentsDir)) return void 0;
|
|
147
220
|
const matches = [];
|
|
148
221
|
try {
|
|
149
222
|
for (const entry of readdirSync(ocAgentsDir)) {
|
|
150
|
-
const sessionsDir =
|
|
151
|
-
if (!
|
|
223
|
+
const sessionsDir = resolve2(ocAgentsDir, entry, "sessions");
|
|
224
|
+
if (!existsSync2(sessionsDir)) continue;
|
|
152
225
|
for (const file of readdirSync(sessionsDir)) {
|
|
153
226
|
if (!file.endsWith(".jsonl")) continue;
|
|
154
|
-
const fullPath =
|
|
227
|
+
const fullPath = resolve2(sessionsDir, file);
|
|
155
228
|
if (sessionMatchesWorkspace(fullPath, workspaceDir)) {
|
|
156
229
|
matches.push({ path: fullPath, mtime: statSync(fullPath).mtimeMs });
|
|
157
230
|
}
|
|
@@ -168,19 +241,19 @@ function findOpenClawSession(workspaceDir) {
|
|
|
168
241
|
}
|
|
169
242
|
function sessionMatchesWorkspace(sessionPath, workspaceDir) {
|
|
170
243
|
try {
|
|
171
|
-
const fd =
|
|
244
|
+
const fd = readFileSync2(sessionPath, "utf-8");
|
|
172
245
|
const firstLine = fd.slice(0, fd.indexOf("\n"));
|
|
173
246
|
const header = JSON.parse(firstLine);
|
|
174
|
-
return header.type === "session" &&
|
|
247
|
+
return header.type === "session" && resolve2(header.cwd) === resolve2(workspaceDir);
|
|
175
248
|
} catch {
|
|
176
249
|
return false;
|
|
177
250
|
}
|
|
178
251
|
}
|
|
179
252
|
function importPiSession(sessionFile, mindDirPath) {
|
|
180
|
-
const homeDir =
|
|
181
|
-
const piSessionDir =
|
|
253
|
+
const homeDir = resolve2(mindDirPath, "home");
|
|
254
|
+
const piSessionDir = resolve2(mindDirPath, ".mind/pi-sessions/main");
|
|
182
255
|
mkdirSync(piSessionDir, { recursive: true });
|
|
183
|
-
const content =
|
|
256
|
+
const content = readFileSync2(sessionFile, "utf-8");
|
|
184
257
|
const lines = content.trim().split("\n");
|
|
185
258
|
try {
|
|
186
259
|
const header = JSON.parse(lines[0]);
|
|
@@ -191,47 +264,48 @@ function importPiSession(sessionFile, mindDirPath) {
|
|
|
191
264
|
} catch {
|
|
192
265
|
}
|
|
193
266
|
const filename = basename(sessionFile);
|
|
194
|
-
const destPath =
|
|
195
|
-
|
|
267
|
+
const destPath = resolve2(piSessionDir, filename);
|
|
268
|
+
writeFileSync2(destPath, `${lines.join("\n")}
|
|
196
269
|
`);
|
|
197
270
|
console.log(`Imported session (${lines.length} entries)`);
|
|
198
271
|
}
|
|
199
|
-
function importOpenClawConnectors(name,
|
|
200
|
-
const configPath =
|
|
201
|
-
if (!
|
|
272
|
+
function importOpenClawConnectors(name, _mindDirPath) {
|
|
273
|
+
const configPath = resolve2(homedir(), ".openclaw/openclaw.json");
|
|
274
|
+
if (!existsSync2(configPath)) return;
|
|
202
275
|
let config;
|
|
203
276
|
try {
|
|
204
|
-
config = JSON.parse(
|
|
277
|
+
config = JSON.parse(readFileSync2(configPath, "utf-8"));
|
|
205
278
|
} catch (err) {
|
|
206
279
|
console.warn("Warning: failed to parse openclaw.json:", err);
|
|
207
280
|
return;
|
|
208
281
|
}
|
|
209
282
|
const discord = config.channels?.discord;
|
|
210
283
|
if (!discord?.enabled || !discord.token) return;
|
|
211
|
-
const envPath =
|
|
284
|
+
const envPath = sharedEnvPath();
|
|
212
285
|
const env = readEnv(envPath);
|
|
213
|
-
env.DISCORD_TOKEN
|
|
214
|
-
|
|
215
|
-
|
|
286
|
+
if (!env.DISCORD_TOKEN) {
|
|
287
|
+
env.DISCORD_TOKEN = discord.token;
|
|
288
|
+
writeEnv(envPath, env);
|
|
289
|
+
}
|
|
290
|
+
const channelMappings = {};
|
|
216
291
|
if (discord.guilds) {
|
|
217
292
|
for (const guild of Object.values(discord.guilds)) {
|
|
218
293
|
if (!guild.channels) continue;
|
|
219
|
-
for (const [
|
|
220
|
-
if (ch.allow)
|
|
294
|
+
for (const [channelName, ch] of Object.entries(guild.channels)) {
|
|
295
|
+
if (ch.allow) {
|
|
296
|
+
channelMappings[channelName] = channelName;
|
|
297
|
+
}
|
|
221
298
|
}
|
|
222
299
|
}
|
|
223
300
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
console.log("Imported Discord connector config");
|
|
233
|
-
if (channelNames.size > 0) {
|
|
234
|
-
console.log(`Imported followed channels: ${[...channelNames].join(", ")}`);
|
|
301
|
+
setBridgeConfig("discord", {
|
|
302
|
+
enabled: true,
|
|
303
|
+
defaultMind: name,
|
|
304
|
+
channelMappings
|
|
305
|
+
});
|
|
306
|
+
console.log(`Imported Discord as system bridge (default mind: ${name})`);
|
|
307
|
+
if (Object.keys(channelMappings).length > 0) {
|
|
308
|
+
console.log(`Mapped channels: ${Object.keys(channelMappings).join(", ")}`);
|
|
235
309
|
}
|
|
236
310
|
}
|
|
237
311
|
function parseNameFromIdentity(identity) {
|
|
@@ -245,6 +319,14 @@ function parseNameFromIdentity(identity) {
|
|
|
245
319
|
}
|
|
246
320
|
|
|
247
321
|
export {
|
|
322
|
+
readBridgesConfig,
|
|
323
|
+
getBridgeConfig,
|
|
324
|
+
setBridgeConfig,
|
|
325
|
+
removeBridgeConfig,
|
|
326
|
+
setChannelMapping,
|
|
327
|
+
removeChannelMapping,
|
|
328
|
+
resolveChannelMapping,
|
|
329
|
+
findBridgeForChannel,
|
|
248
330
|
run,
|
|
249
331
|
findOpenClawSession,
|
|
250
332
|
sessionMatchesWorkspace,
|