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.
Files changed (209) hide show
  1. package/README.md +7 -6
  2. package/dist/accept-ZBDVVCEU.js +42 -0
  3. package/dist/{activity-events-BN7V6KCC.js → activity-events-ZW4SDL2C.js} +4 -4
  4. package/dist/{ai-service-PSILB5WD.js → ai-service-LURBEDDB.js} +5 -5
  5. package/dist/{api-client-XUXOB7LI.js → api-client-3A77HMH7.js} +1 -1
  6. package/dist/api.d.ts +1 -5618
  7. package/dist/{archive-C2VEMQOR.js → archive-ESU2FUN4.js} +3 -3
  8. package/dist/{auth-ZFZXJZDQ.js → auth-WX4TESEI.js} +5 -5
  9. package/dist/bridge-PXIO6PS2.js +206 -0
  10. package/dist/chat-QXAJF3FU.js +51 -0
  11. package/dist/{chunk-7F2SW2KD.js → chunk-2TGZJFAT.js} +3 -3
  12. package/dist/{chunk-6LXAAQ43.js → chunk-33ODGMFZ.js} +1 -1
  13. package/dist/{chunk-4JSR7YO7.js → chunk-5N7Y5WAM.js} +1 -1
  14. package/dist/{chunk-FYCALD4Q.js → chunk-5T5YMX6S.js} +1 -1
  15. package/dist/{chunk-B2BVAIZ4.js → chunk-5XJYUFZH.js} +21 -15
  16. package/dist/{chunk-M3K5AARV.js → chunk-A2ZLHBHG.js} +2 -2
  17. package/dist/{chunk-U5BTYSAL.js → chunk-AN2W47GW.js} +2 -2
  18. package/dist/{chunk-G53F3JA4.js → chunk-AOB6GVRM.js} +1 -1
  19. package/dist/{chunk-N7BLAHNE.js → chunk-BDYXIWA5.js} +5 -5
  20. package/dist/{chunk-YUIHSKR6.js → chunk-BKF4WQCY.js} +2 -2
  21. package/dist/{chunk-6OWJXUAR.js → chunk-BMZQYACC.js} +2 -2
  22. package/dist/{chunk-NAOW2CLO.js → chunk-BTY4WNFE.js} +1 -1
  23. package/dist/{chunk-MLOQKQNB.js → chunk-BV65KRHM.js} +2 -2
  24. package/dist/{chunk-XWXBJQBE.js → chunk-CORXD635.js} +4 -4
  25. package/dist/{chunk-PVY5W6QN.js → chunk-F7ZNLYKZ.js} +2 -2
  26. package/dist/{chunk-BFWHBQK4.js → chunk-FT5KETXZ.js} +3 -3
  27. package/dist/{chunk-N3DNFPVA.js → chunk-IJHIXLVN.js} +8 -8
  28. package/dist/{chunk-V6ZCNULL.js → chunk-J6CJQDWI.js} +37 -28
  29. package/dist/{chunk-4RQBJWQX.js → chunk-LOPXTW6H.js} +1 -1
  30. package/dist/{chunk-47ZPNLF4.js → chunk-MDJGMOSD.js} +8 -137
  31. package/dist/{chunk-BTWAGDV5.js → chunk-N446KRP7.js} +3 -3
  32. package/dist/{chunk-6WAWMWR5.js → chunk-N5LMGYXX.js} +2 -2
  33. package/dist/{chunk-G6BSYHPK.js → chunk-NJK5SDGR.js} +1 -1
  34. package/dist/{chunk-D424ZQGI.js → chunk-O7IGP7ZW.js} +11 -3
  35. package/dist/{chunk-2IOP6PHB.js → chunk-OTC67N2Z.js} +2 -2
  36. package/dist/{chunk-V45JXOWY.js → chunk-PWQ2ITYG.js} +4 -4
  37. package/dist/{chunk-KTLFDYPT.js → chunk-QCH6K235.js} +1 -1
  38. package/dist/chunk-QHG4OMZL.js +145 -0
  39. package/dist/{chunk-IS7WJ56Q.js → chunk-QWTR6AWZ.js} +3 -3
  40. package/dist/chunk-TXSA4Q3V.js +116 -0
  41. package/dist/{chunk-BDK73LK6.js → chunk-VHJRZM2S.js} +2 -2
  42. package/dist/{chunk-SSI47XP2.js → chunk-VHWGEJ4V.js} +1 -1
  43. package/dist/chunk-VY3RB2V7.js +164 -0
  44. package/dist/chunk-WJPROOU5.js +8314 -0
  45. package/dist/{chunk-E5C7OWZ2.js → chunk-WZRZFFCL.js} +8 -8
  46. package/dist/{chunk-BM474GX6.js → chunk-XRQSAMX2.js} +4 -4
  47. package/dist/{chunk-OYAKCAVY.js → chunk-ZSR72JB3.js} +1 -1
  48. package/dist/{chunk-PLDWHR4D.js → chunk-ZX7EAV5J.js} +17 -7
  49. package/dist/cli.js +90 -29
  50. package/dist/clock-HSEKS5AR.js +289 -0
  51. package/dist/{cloud-sync-TG3TIX5H.js → cloud-sync-6JL4C24T.js} +21 -22
  52. package/dist/config-UTS7QULS.js +76 -0
  53. package/dist/connectors/discord-bridge.js +3 -3
  54. package/dist/connectors/slack-bridge.js +3 -3
  55. package/dist/connectors/telegram-bridge.js +3 -3
  56. package/dist/{conversations-HL2JP5GI.js → conversations-2PW57WO2.js} +5 -5
  57. package/dist/create-5BPOOJAN.js +75 -0
  58. package/dist/create-UVCK2CS6.js +50 -0
  59. package/dist/daemon-client-RVIKXGFQ.js +12 -0
  60. package/dist/daemon-restart-HSZ3BCX5.js +65 -0
  61. package/dist/daemon.js +845 -1766
  62. package/dist/{db-PLEDCBHZ.js → db-BDMH4SZ2.js} +7 -3
  63. package/dist/{db-RYX3SS2W.js → db-BVBJ57TU.js} +2 -2
  64. package/dist/delete-L5PAVDGQ.js +42 -0
  65. package/dist/delivery-manager-H5ZVBMCQ.js +31 -0
  66. package/dist/{delivery-router-D5ELDMS2.js → delivery-router-HEJSJAHQ.js} +4 -4
  67. package/dist/down-74VXM45A.js +17 -0
  68. package/dist/env-E4XHO2BI.js +223 -0
  69. package/dist/{exec-DVLXKRIO.js → exec-PY7THYH4.js} +4 -4
  70. package/dist/export-OAS6QVBN.js +113 -0
  71. package/dist/{extension-PM42QCID.js → extension-D74CNM7G.js} +25 -33
  72. package/dist/{extensions-BBGVL5JC.js → extensions-XDDFY72A.js} +22 -11
  73. package/dist/files-CWTK6V3H.js +53 -0
  74. package/dist/import-5A3T7QV4.js +143 -0
  75. package/dist/{isolation-62MKDZN3.js → isolation-TK5RX2WM.js} +3 -3
  76. package/dist/join-DF5XSJAC.js +67 -0
  77. package/dist/list-PDMQM7ZV.js +53 -0
  78. package/dist/login-7TE6CIZF.js +60 -0
  79. package/dist/login-GOTAYLXP.js +51 -0
  80. package/dist/logout-6KIA74EV.js +29 -0
  81. package/dist/logout-T4XS6LRU.js +50 -0
  82. package/dist/message-delivery-GRC4W6P7.js +41 -0
  83. package/dist/mind-5IEYKV7I.js +97 -0
  84. package/dist/{mind-activity-tracker-2ACNHA7B.js → mind-activity-tracker-QBLIV7ZJ.js} +5 -5
  85. package/dist/{mind-history-WOYFLQAI.js → mind-history-IE2QH7U5.js} +82 -71
  86. package/dist/mind-list-GEWHWAL4.js +38 -0
  87. package/dist/mind-manager-HFLB5653.js +31 -0
  88. package/dist/mind-profile-DCBDVF5B.js +53 -0
  89. package/dist/mind-service-X2CAA6W6.js +37 -0
  90. package/dist/mind-sleep-ITCF6OQA.js +47 -0
  91. package/dist/mind-status-X4SX3YUG.js +65 -0
  92. package/dist/mind-wake-KXMKMGWX.js +42 -0
  93. package/dist/{package-V2WHWVG6.js → package-D2FSVFAX.js} +5 -5
  94. package/dist/read-67VRP2DO.js +91 -0
  95. package/dist/{read-stdin-PIRM6A2Y.js → read-stdin-3X5VYKNS.js} +1 -1
  96. package/dist/register-SB7NXCOE.js +51 -0
  97. package/dist/{registry-UYV5S6QT.js → registry-GBSNW3HG.js} +2 -2
  98. package/dist/reject-MUR2KWJ4.js +40 -0
  99. package/dist/restart-5EGG4JXU.js +42 -0
  100. package/dist/{sandbox-SI5HMBP3.js → sandbox-R37VIU36.js} +5 -5
  101. package/dist/scheduler-Y7O4CJXL.js +31 -0
  102. package/dist/{schema-ETMABTW4.js → schema-XVZ2CLKW.js} +1 -1
  103. package/dist/{seed-WNGI6PNW.js → seed-EQORWX77.js} +2 -2
  104. package/dist/seed-check-KJNTL72M.js +35 -0
  105. package/dist/seed-cmd-ZM2XGVU2.js +30 -0
  106. package/dist/seed-create-DRWGGHEI.js +113 -0
  107. package/dist/seed-sprout-JYXGXOP3.js +148 -0
  108. package/dist/send-JBJJQ7CA.js +409 -0
  109. package/dist/service-WNPCNHOX.js +121 -0
  110. package/dist/{setup-Z3DEVWV7.js → setup-BJ4YAY26.js} +153 -127
  111. package/dist/{setup-GGMKENLN.js → setup-RHJRFURI.js} +3 -3
  112. package/dist/skill-TAAKEYBV.js +389 -0
  113. package/dist/skills/volute-mind/SKILL.md +3 -7
  114. package/dist/skills/volute-mind/references/extensions.md +8 -11
  115. package/dist/{skills-Q6VZ2UGD.js → skills-EKMCQ46K.js} +7 -7
  116. package/dist/sleep-manager-7KFK3USC.js +35 -0
  117. package/dist/spirit-ZFRDXMG7.js +23 -0
  118. package/dist/split-AWVOYOPZ.js +64 -0
  119. package/dist/{sprout-E3HJIV2Z.js → sprout-HE4TITMK.js} +2 -2
  120. package/dist/start-3UXOPXQG.js +39 -0
  121. package/dist/status-ZK34WYIM.js +125 -0
  122. package/dist/stop-3XYIBGFM.js +41 -0
  123. package/dist/system-chat-IDPHYHY4.js +35 -0
  124. package/dist/systems-O43WGQY6.js +52 -0
  125. package/dist/{tailscale-ZEUK7GKZ.js → tailscale-ZIZ2HWJ5.js} +4 -4
  126. package/dist/{template-hash-EJRTKE36.js → template-hash-A7FNHTB7.js} +2 -2
  127. package/dist/up-77ICEDEW.js +19 -0
  128. package/dist/update-ANE5ZM7F.js +225 -0
  129. package/dist/{update-check-X3YG4WVP.js → update-check-UV55CBEP.js} +3 -3
  130. package/dist/upgrade-ZMDGC7M2.js +74 -0
  131. package/dist/variant-QWL2WSRI.js +62 -0
  132. package/dist/{version-notify-YCH4UVQ2.js → version-notify-FXSEMXWW.js} +28 -27
  133. package/dist/{volute-config-WBKYJGYQ.js → volute-config-D2XVS2YI.js} +1 -1
  134. package/dist/web-assets/assets/index-BhxWKvbB.css +1 -0
  135. package/dist/web-assets/assets/index-CHVKJ9II.js +75 -0
  136. package/dist/web-assets/index.html +2 -2
  137. package/dist/web-assets/sw.js +117 -0
  138. package/package.json +5 -5
  139. package/packages/extensions/pages/dist/ui/assets/index-DKZLNMED.js +2 -0
  140. package/packages/extensions/pages/dist/ui/index.html +1 -1
  141. package/packages/extensions/pages/skills/pages/SKILL.md +84 -9
  142. package/templates/_base/src/lib/auto-commit.ts +8 -8
  143. package/templates/_base/src/lib/volute-server.ts +6 -0
  144. package/templates/claude/src/agent.ts +8 -1
  145. package/dist/accept-TW6V4WI4.js +0 -42
  146. package/dist/bridge-O753D5F4.js +0 -207
  147. package/dist/chat-BHYX7DJ4.js +0 -68
  148. package/dist/chunk-47XDEWWV.js +0 -156
  149. package/dist/chunk-CVL5IGIR.js +0 -2084
  150. package/dist/chunk-PB65JZK2.js +0 -85
  151. package/dist/chunk-TAHX36HZ.js +0 -3679
  152. package/dist/clock-3X4DSC2N.js +0 -281
  153. package/dist/config-OROA5DUA.js +0 -72
  154. package/dist/create-3SEKKI6P.js +0 -71
  155. package/dist/create-UOSOQ2HN.js +0 -44
  156. package/dist/daemon-client-WOAQXXBM.js +0 -12
  157. package/dist/daemon-restart-5ABHNXJZ.js +0 -52
  158. package/dist/delete-KYOVWR23.js +0 -35
  159. package/dist/delivery-manager-2BR5NZKF.js +0 -32
  160. package/dist/down-QVFN4UPK.js +0 -15
  161. package/dist/env-R34DT7XL.js +0 -195
  162. package/dist/export-6ZXAXATG.js +0 -112
  163. package/dist/files-VQV2VZQO.js +0 -47
  164. package/dist/import-MK2I2T6F.js +0 -23
  165. package/dist/join-DGYHTJUH.js +0 -66
  166. package/dist/list-C644WTHV.js +0 -49
  167. package/dist/login-IIGEQPHL.js +0 -47
  168. package/dist/login-KZQLMAWE.js +0 -47
  169. package/dist/logout-AGTZVRGP.js +0 -40
  170. package/dist/logout-KD6GXIJJ.js +0 -21
  171. package/dist/message-delivery-V3R6NXJP.js +0 -42
  172. package/dist/mind-BI4EPBVZ.js +0 -108
  173. package/dist/mind-list-6VPM7GUQ.js +0 -30
  174. package/dist/mind-manager-MWW3BTS4.js +0 -32
  175. package/dist/mind-profile-WPG42U5Y.js +0 -47
  176. package/dist/mind-service-VIKZJK2M.js +0 -38
  177. package/dist/mind-sleep-XDISJY74.js +0 -42
  178. package/dist/mind-status-7FTZWPZF.js +0 -56
  179. package/dist/mind-wake-KIIKEI3A.js +0 -37
  180. package/dist/read-H5C26YO7.js +0 -85
  181. package/dist/register-J27WP33N.js +0 -47
  182. package/dist/reject-OEANJYIA.js +0 -40
  183. package/dist/restart-V5EGYBJG.js +0 -33
  184. package/dist/scheduler-AGG3L2FO.js +0 -32
  185. package/dist/seed-check-PXTH7YXS.js +0 -32
  186. package/dist/seed-cmd-VENFTGS3.js +0 -36
  187. package/dist/seed-create-663ALOKH.js +0 -112
  188. package/dist/seed-sprout-EH3AGKAI.js +0 -132
  189. package/dist/send-7FUUUZZH.js +0 -386
  190. package/dist/skill-DKNYJS4P.js +0 -362
  191. package/dist/skills/shared-files/SKILL.md +0 -44
  192. package/dist/skills/shared-files/scripts/merge.ts +0 -72
  193. package/dist/skills/shared-files/scripts/pull.ts +0 -52
  194. package/dist/sleep-manager-BJK2ROPX.js +0 -36
  195. package/dist/spirit-4JP4TY4C.js +0 -23
  196. package/dist/split-3YPMS2CL.js +0 -63
  197. package/dist/start-W3TPKX4D.js +0 -33
  198. package/dist/status-4OVFXFEJ.js +0 -115
  199. package/dist/stop-GTT6YWYO.js +0 -32
  200. package/dist/system-channel-DXD2JBOU.js +0 -36
  201. package/dist/system-chat-TYLOL7SX.js +0 -36
  202. package/dist/systems-AYLO727G.js +0 -61
  203. package/dist/up-PA7F2CXE.js +0 -18
  204. package/dist/update-HG4LCUSG.js +0 -215
  205. package/dist/upgrade-YGNIDICG.js +0 -67
  206. package/dist/variant-MZUMRTQO.js +0 -41
  207. package/dist/web-assets/assets/index-DiiwC-CZ.css +0 -1
  208. package/dist/web-assets/assets/index-d6y5b9Ij.js +0 -75
  209. 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
+ };