volute 0.31.0 → 0.33.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 (195) hide show
  1. package/README.md +31 -22
  2. package/dist/{accept-GAKQ3MEH.js → accept-D5VBM7JW.js} +5 -4
  3. package/dist/{activity-events-T5ZRCVAL.js → activity-events-XJO3P4RR.js} +3 -2
  4. package/dist/{ai-service-UWUPM4T6.js → ai-service-SBY2WG7O.js} +18 -5
  5. package/dist/api.d.ts +703 -1068
  6. package/dist/{archive-YBNSJYZZ.js → archive-INXYFVCW.js} +3 -2
  7. package/dist/{auth-T5AW2USD.js → auth-GKCDSO4T.js} +4 -3
  8. package/dist/{bridge-4AJ3EY26.js → bridge-TXWWPPOJ.js} +5 -4
  9. package/dist/{chat-7YLT7FI3.js → chat-U5ZOME3O.js} +8 -8
  10. package/dist/{chunk-NV3TYNWX.js → chunk-2NGTS5UU.js} +1 -1
  11. package/dist/{chunk-BWKIHH7B.js → chunk-3Z2DPESO.js} +662 -508
  12. package/dist/chunk-6LXAAQ43.js +22 -0
  13. package/dist/chunk-7J3HEVR7.js +220 -0
  14. package/dist/{chunk-NOWVQ7AL.js → chunk-A2A4KLFE.js} +351 -301
  15. package/dist/{chunk-LX6T3GKQ.js → chunk-ALEF47VT.js} +1 -1
  16. package/dist/{chunk-S2TZLSDH.js → chunk-C7I35G4R.js} +163 -15
  17. package/dist/{chunk-VGWJSNHS.js → chunk-G53F3JA4.js} +1 -35
  18. package/dist/{chunk-A6TUJJ3L.js → chunk-G6BSYHPK.js} +2 -2
  19. package/dist/{chunk-DAXJKPHZ.js → chunk-GY5HBI7A.js} +2 -2
  20. package/dist/{chunk-BC3P3QCK.js → chunk-I5KY25PQ.js} +1 -9
  21. package/dist/{chunk-BNC43CSY.js → chunk-JUKK7FPS.js} +2 -2
  22. package/dist/{chunk-R5QJBZZG.js → chunk-JYVGHWEJ.js} +21 -11
  23. package/dist/chunk-KIEPMIM5.js +59 -0
  24. package/dist/{chunk-EKDWA7E4.js → chunk-KVK2DLWI.js} +5 -2
  25. package/dist/{chunk-AAO77TZX.js → chunk-LOEJ4HPQ.js} +1 -1
  26. package/dist/chunk-LRCG2JLP.js +251 -0
  27. package/dist/{chunk-EMPFLFTG.js → chunk-M7UL5S3Q.js} +1 -1
  28. package/dist/{chunk-6QIUN46C.js → chunk-N432I7QH.js} +20 -3
  29. package/dist/{chunk-SNVPRRT7.js → chunk-NNB4WIG7.js} +2 -2
  30. package/dist/{chunk-HDKY4TWU.js → chunk-NPKSDYA2.js} +3 -3
  31. package/dist/chunk-OYAKCAVY.js +29 -0
  32. package/dist/chunk-PB65JZK2.js +85 -0
  33. package/dist/chunk-PVY5W6QN.js +41 -0
  34. package/dist/{chunk-PNQCXLSV.js → chunk-QTUVYI7W.js} +58 -1
  35. package/dist/{chunk-X62AXPR7.js → chunk-RPZZSXV3.js} +8 -196
  36. package/dist/{chunk-WRS3B556.js → chunk-RSX4OPZY.js} +5 -5
  37. package/dist/{chunk-FAHDKPEH.js → chunk-RVGLDGMI.js} +5 -3
  38. package/dist/chunk-SKLSMHXO.js +208 -0
  39. package/dist/{chunk-4OUOFS23.js → chunk-UKVWJRKN.js} +1 -1
  40. package/dist/{chunk-57OKQMP3.js → chunk-VH33ZWMW.js} +5 -55
  41. package/dist/cli.js +49 -23
  42. package/dist/{clock-LJCG426D.js → clock-BVH3V6E3.js} +7 -6
  43. package/dist/{cloud-sync-O3LXIRN6.js → cloud-sync-4NWLMFVH.js} +20 -14
  44. package/dist/config-H2H4UIF7.js +72 -0
  45. package/dist/connectors/discord-bridge.js +1 -1
  46. package/dist/connectors/slack-bridge.js +1 -1
  47. package/dist/connectors/telegram-bridge.js +1 -1
  48. package/dist/{conversations-RKKGP5IA.js → conversations-AWI5SZW2.js} +4 -3
  49. package/dist/{create-TL623TFC.js → create-2FK7Z46Y.js} +6 -2
  50. package/dist/{create-WUTIIRI2.js → create-YWD2TIP4.js} +6 -5
  51. package/dist/{daemon-client-CVGM25DM.js → daemon-client-6QXHZ7US.js} +3 -2
  52. package/dist/{daemon-restart-EZP7XH3V.js → daemon-restart-GOBUKLX7.js} +8 -6
  53. package/dist/daemon.js +1918 -1472
  54. package/dist/{db-SW5PL6QA.js → db-F34YLV7D.js} +2 -1
  55. package/dist/db-RA45JBFG.js +16 -0
  56. package/dist/{delete-Z6HAG35F.js → delete-QTGWEDBI.js} +1 -1
  57. package/dist/delivery-manager-PFAKEJTC.js +32 -0
  58. package/dist/delivery-router-FL45JL7N.js +21 -0
  59. package/dist/down-FWWTEKXM.js +15 -0
  60. package/dist/{env-NHESNNSP.js → env-JCOF2222.js} +5 -4
  61. package/dist/{export-EVMP7GWY.js → export-SUYRLI5Q.js} +4 -3
  62. package/dist/{extension-LR7EW3JF.js → extension-OBTGKQQD.js} +5 -3
  63. package/dist/{extensions-NGEJI7JH.js → extensions-KYNTVTMO.js} +10 -7
  64. package/dist/{files-3SM7V33S.js → files-65PMW5IK.js} +6 -5
  65. package/dist/{history-PQD3LXEP.js → history-DKCDI3JO.js} +9 -4
  66. package/dist/{import-PR2OCGQJ.js → import-DDUFE7AY.js} +4 -3
  67. package/dist/isolation-LLAYQYDY.js +22 -0
  68. package/dist/{join-R4EN5CWQ.js → join-I5QEE3LG.js} +1 -1
  69. package/dist/{list-B4XNUOFO.js → list-JQ463EDA.js} +5 -4
  70. package/dist/{login-62JVY6A2.js → login-D7ETSU4R.js} +5 -4
  71. package/dist/{login-URWP6S2N.js → login-RIJF2F4G.js} +3 -2
  72. package/dist/{logout-NXJQJDLI.js → logout-5MLHZALK.js} +3 -2
  73. package/dist/{logout-ZK2N62T3.js → logout-UZJRGY4Z.js} +3 -2
  74. package/dist/message-delivery-DFF5SJRM.js +42 -0
  75. package/dist/{mind-E2ZV2WRX.js → mind-IOJFLEM5.js} +25 -19
  76. package/dist/{mind-activity-tracker-ASNZBMLC.js → mind-activity-tracker-F6O4Q2SL.js} +4 -3
  77. package/dist/{mind-list-BEI7E5WY.js → mind-list-WUPMQDYQ.js} +3 -2
  78. package/dist/mind-manager-NBJF5D26.js +32 -0
  79. package/dist/mind-profile-P67FEHOY.js +47 -0
  80. package/dist/mind-service-2MQ6UK5N.js +38 -0
  81. package/dist/{mind-sleep-CANABWJI.js → mind-sleep-WW2IX7JT.js} +5 -4
  82. package/dist/{mind-status-6WKZVUOP.js → mind-status-L3EFFRPR.js} +3 -2
  83. package/dist/{mind-wake-RZKLH2IN.js → mind-wake-VSSGW465.js} +5 -4
  84. package/dist/{package-NU4CA7OU.js → package-U3VFO273.js} +2 -1
  85. package/dist/{read-THL362EI.js → read-EBY56C33.js} +5 -4
  86. package/dist/read-stdin-HQJ7774D.js +8 -0
  87. package/dist/{register-QAQELAS6.js → register-HD74C4TT.js} +5 -4
  88. package/dist/{registry-ASXCQCNH.js → registry-PJ4S5PHQ.js} +8 -1
  89. package/dist/{reject-AYPBNPNL.js → reject-UJKFBHRO.js} +5 -4
  90. package/dist/{restart-6SKPV3T2.js → restart-3UCMRUVC.js} +3 -2
  91. package/dist/{sandbox-6ZEWQDVU.js → sandbox-GJOK4QLQ.js} +4 -3
  92. package/dist/scheduler-ZZ7XGQG6.js +32 -0
  93. package/dist/schema-PA3M5ZKH.js +32 -0
  94. package/dist/seed-QDYVLG74.js +11 -0
  95. package/dist/seed-check-S2IX25RL.js +32 -0
  96. package/dist/seed-cmd-DKOUFEAU.js +36 -0
  97. package/dist/{seed-OWX2AW75.js → seed-create-4XBBOLRH.js} +27 -10
  98. package/dist/{sprout-FDVI2CGN.js → seed-sprout-GQEIIQRT.js} +24 -9
  99. package/dist/{send-ZO4BTWXK.js → send-QIV2INHB.js} +92 -101
  100. package/dist/{setup-7CFITEQN.js → setup-TISPCO22.js} +7 -2
  101. package/dist/{setup-ZXBXG7E4.js → setup-XMCBE3LF.js} +11 -7
  102. package/dist/{skill-YFXP67A2.js → skill-PSQGRRJX.js} +5 -4
  103. package/dist/skills/dreaming/SKILL.md +6 -4
  104. package/dist/skills/dreaming/references/INSTALL.md +2 -2
  105. package/dist/skills/dreaming/scripts/dream.ts +2 -2
  106. package/dist/skills/dreaming/scripts/wake-context-dreams.sh +1 -1
  107. package/dist/skills/imagegen/SKILL.md +16 -11
  108. package/dist/skills/imagegen/references/INSTALL.md +1 -1
  109. package/dist/skills/imagegen/scripts/imagegen.ts +146 -25
  110. package/dist/skills/orientation/SKILL.md +9 -2
  111. package/dist/skills/resonance/SKILL.md +4 -1
  112. package/dist/skills/resonance/references/INSTALL.md +2 -2
  113. package/dist/skills/resonance/scripts/resonance-hook.sh +2 -0
  114. package/dist/skills/resonance/scripts/resonance.ts +35 -5
  115. package/dist/skills/seed-nurture/SKILL.md +42 -0
  116. package/dist/skills/volute-admin/SKILL.md +83 -0
  117. package/dist/skills/volute-mind/SKILL.md +15 -11
  118. package/dist/skills-7FV7EJTE.js +62 -0
  119. package/dist/sleep-manager-JTXSN7NV.js +36 -0
  120. package/dist/spirit-VRONKFMF.js +23 -0
  121. package/dist/{split-MI62KJUU.js → split-STOROBYJ.js} +1 -1
  122. package/dist/sprout-WKLZXUIQ.js +11 -0
  123. package/dist/{start-D64BRKPH.js → start-K2NCUUCG.js} +3 -2
  124. package/dist/{status-ZZWBYFGE.js → status-3JBTFSMI.js} +6 -4
  125. package/dist/{stop-OP2CTXCO.js → stop-H26JZDXF.js} +3 -2
  126. package/dist/system-chat-JAPOJ3KE.js +36 -0
  127. package/dist/{systems-EQPPT4B7.js → systems-XRI52VCH.js} +6 -5
  128. package/dist/{tailscale-6DJKUMNF.js → tailscale-XHQBZROW.js} +2 -1
  129. package/dist/{template-hash-3HOR4UAJ.js → template-hash-A6VVKOXJ.js} +2 -1
  130. package/dist/up-M5AS6SBV.js +18 -0
  131. package/dist/{update-KUJXATRS.js → update-UD543CXX.js} +6 -4
  132. package/dist/{update-check-5WVSU37T.js → update-check-ZD6OOIYQ.js} +3 -2
  133. package/dist/{upgrade-KBHCWX6T.js → upgrade-O4Q7WJM3.js} +12 -14
  134. package/dist/{version-notify-75ELVKPV.js → version-notify-NBI2MTJO.js} +22 -16
  135. package/dist/volute-config-HD7WWUQC.js +10 -0
  136. package/dist/web-assets/assets/index-CWJrVveV.css +1 -0
  137. package/dist/web-assets/assets/index-DJt14FRI.js +75 -0
  138. package/dist/web-assets/ext-theme.css +93 -0
  139. package/dist/web-assets/index.html +2 -2
  140. package/drizzle/0004_spirits.sql +5 -0
  141. package/drizzle/meta/0004_snapshot.json +7 -0
  142. package/drizzle/meta/_journal.json +7 -0
  143. package/package.json +2 -1
  144. package/packages/extensions/notes/dist/ui/assets/index-8jWEv9SA.js +61 -0
  145. package/packages/extensions/notes/dist/ui/assets/index-DkaB7Ytd.css +1 -0
  146. package/packages/extensions/notes/dist/ui/index.html +2 -2
  147. package/packages/extensions/pages/skills/pages/SKILL.md +16 -46
  148. package/templates/_base/.init/.config/hooks/pre-prompt/session-activity.ts +40 -0
  149. package/templates/_base/.init/{.config → .local}/bin/volute +1 -1
  150. package/templates/_base/.init/.local/hooks/pre-prompt/session-activity.ts +40 -0
  151. package/templates/_base/.init/.local/hooks/startup-context.ts +58 -0
  152. package/templates/_base/home/.config/routes.json +1 -1
  153. package/templates/_base/src/lib/daemon-client.ts +21 -13
  154. package/templates/_base/src/lib/format-prefix.ts +1 -0
  155. package/templates/_base/src/lib/hook-loader.ts +155 -0
  156. package/templates/_base/src/lib/startup.ts +11 -4
  157. package/templates/_base/src/lib/transparency.ts +2 -2
  158. package/templates/claude/.init/.claude/settings.json +1 -1
  159. package/templates/claude/.init/.config/routes.json +2 -2
  160. package/templates/claude/src/agent.ts +95 -13
  161. package/templates/claude/src/lib/message-channel.ts +7 -2
  162. package/templates/claude/src/lib/stream-consumer.ts +38 -0
  163. package/templates/codex/.init/.config/routes.json +11 -0
  164. package/templates/codex/.init/AGENTS.md +29 -0
  165. package/templates/codex/home/.config/config.json.tmpl +7 -0
  166. package/templates/codex/package.json.tmpl +20 -0
  167. package/templates/codex/src/agent.ts +554 -0
  168. package/templates/codex/src/lib/content.ts +16 -0
  169. package/templates/codex/src/lib/session-store.ts +56 -0
  170. package/templates/codex/src/server.ts +59 -0
  171. package/templates/codex/volute-template.json +8 -0
  172. package/templates/pi/.init/.config/routes.json +2 -2
  173. package/templates/pi/src/agent.ts +62 -8
  174. package/templates/pi/src/lib/event-handler.ts +1 -1
  175. package/templates/pi/src/lib/reply-instructions-extension.ts +32 -11
  176. package/dist/chunk-HR5JKIDG.js +0 -222
  177. package/dist/down-TS4XQBA4.js +0 -13
  178. package/dist/message-delivery-UJHCLVU4.js +0 -30
  179. package/dist/mind-manager-IPA6DZXD.js +0 -26
  180. package/dist/pages-watcher-72OVPRMH.js +0 -22
  181. package/dist/skills/sessions/SKILL.md +0 -49
  182. package/dist/sleep-manager-TPS6OGCA.js +0 -30
  183. package/dist/system-chat-B43GIXQU.js +0 -30
  184. package/dist/up-TDXEP3VA.js +0 -16
  185. package/dist/web-assets/assets/index-BM1cTzBg.js +0 -72
  186. package/dist/web-assets/assets/index-BfJkKTPF.css +0 -1
  187. package/packages/extensions/notes/dist/ui/assets/index-B8GdTnXs.css +0 -1
  188. package/packages/extensions/notes/dist/ui/assets/index-CDpGTCWb.js +0 -2
  189. package/packages/extensions/pages/skills/pages/scripts/pages.mjs +0 -58
  190. package/templates/_base/.init/.config/hooks/startup-context.sh +0 -46
  191. package/templates/_base/.init/.config/scripts/session-reader.ts +0 -59
  192. package/templates/_base/src/lib/session-monitor.ts +0 -400
  193. package/templates/claude/src/lib/hooks/session-context.ts +0 -32
  194. package/templates/pi/src/lib/session-context-extension.ts +0 -35
  195. /package/templates/_base/.init/{.config → .local}/hooks/wake-context.sh +0 -0
@@ -1,21 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- resolveMindName
4
- } from "./chunk-NAOW2CLO.js";
3
+ readStdin
4
+ } from "./chunk-6LXAAQ43.js";
5
5
  import {
6
6
  getClient,
7
7
  urlOf
8
8
  } from "./chunk-4RQBJWQX.js";
9
9
  import {
10
10
  formatFileSize
11
- } from "./chunk-LX6T3GKQ.js";
11
+ } from "./chunk-ALEF47VT.js";
12
+ import {
13
+ daemonFetch
14
+ } from "./chunk-UKVWJRKN.js";
12
15
  import {
13
16
  parseArgs
14
17
  } from "./chunk-D424ZQGI.js";
15
- import {
16
- daemonFetch
17
- } from "./chunk-4OUOFS23.js";
18
- import "./chunk-X62AXPR7.js";
18
+ import "./chunk-LRCG2JLP.js";
19
+ import "./chunk-RPZZSXV3.js";
19
20
  import "./chunk-K3NQKI34.js";
20
21
 
21
22
  // src/commands/send.ts
@@ -40,35 +41,18 @@ function parseTarget(target) {
40
41
  return {
41
42
  platform: "volute",
42
43
  identifier: target,
43
- uri: `volute:${target}`,
44
+ uri: target,
44
45
  isDM: true
45
46
  };
46
47
  }
47
48
  return {
48
49
  platform: "volute",
49
50
  identifier: target,
50
- uri: `volute:${target}`,
51
+ uri: target,
51
52
  isDM: false
52
53
  };
53
54
  }
54
55
 
55
- // src/lib/read-stdin.ts
56
- import { isatty } from "tty";
57
- async function readStdin() {
58
- if (isatty(0)) return void 0;
59
- const chunks = [];
60
- try {
61
- for await (const chunk of process.stdin) {
62
- chunks.push(chunk);
63
- }
64
- } catch (err) {
65
- console.error(`Failed to read from stdin: ${err instanceof Error ? err.message : String(err)}`);
66
- process.exit(1);
67
- }
68
- const text = Buffer.concat(chunks).toString().replace(/\r?\n$/, "");
69
- return text || void 0;
70
- }
71
-
72
56
  // src/commands/send.ts
73
57
  async function isMind(name) {
74
58
  try {
@@ -168,7 +152,6 @@ async function waitForResponse(mindName, conversationId, timeoutMs) {
168
152
  }
169
153
  async function run(args) {
170
154
  const { positional, flags } = parseArgs(args, {
171
- mind: { type: "string" },
172
155
  image: { type: "string" },
173
156
  file: { type: "string" },
174
157
  wait: { type: "boolean" },
@@ -180,14 +163,13 @@ async function run(args) {
180
163
  const images = flags.image ? [loadImage(flags.image)] : void 0;
181
164
  if (!target || !message && !images && !flags.file) {
182
165
  console.error(
183
- 'Usage: volute chat send <target> "<message>" [--mind <name>] [--image <path>] [--file <path>] [--wait]'
166
+ 'Usage: volute chat send <target> "<message>" [--image <path>] [--file <path>] [--wait]'
184
167
  );
185
- console.error(' echo "message" | volute chat send <target> [--mind <name>]');
168
+ console.error(' echo "message" | volute chat send <target>');
186
169
  console.error("");
187
170
  console.error("Examples:");
188
171
  console.error(' volute chat send @other-mind "hello"');
189
- console.error(' volute chat send animal-chat "hello everyone"');
190
- console.error(' volute chat send discord:server/channel "hello"');
172
+ console.error(' volute chat send #animal-chat "hello everyone"');
191
173
  console.error(' volute chat send @mind "check this out" --image photo.png');
192
174
  console.error(" volute chat send @mind --image photo.png");
193
175
  console.error(' volute chat send @mind "check this out" --file notes.txt');
@@ -259,13 +241,13 @@ To reply to a person, use their username from the message prefix (e.g. volute ch
259
241
  parsed = {
260
242
  platform: "volute",
261
243
  identifier: `@${parsed.identifier}`,
262
- uri: `volute:@${parsed.identifier}`,
244
+ uri: `@${parsed.identifier}`,
263
245
  isDM: true
264
246
  };
265
247
  }
266
248
  const client = getClient();
267
249
  let waitMindName;
268
- let channelUri = parsed.uri;
250
+ let waitConversationId;
269
251
  if (parsed.isDM && parsed.platform === "volute") {
270
252
  const targetName = parsed.identifier.slice(1);
271
253
  const mindSelf = process.env.VOLUTE_MIND;
@@ -287,91 +269,100 @@ To reply to a person, use their username from the message prefix (e.g. volute ch
287
269
  console.error(data.error);
288
270
  process.exit(1);
289
271
  }
290
- const { slug } = await createRes.json();
291
- channelUri = slug;
292
- const sendRes = await daemonFetch(
293
- urlOf(client.api.minds[":name"].channels.send.$url({ param: { name: contextMind } })),
294
- {
295
- method: "POST",
296
- headers: { "Content-Type": "application/json" },
297
- body: JSON.stringify({
298
- platform: "volute",
299
- uri: channelUri,
300
- message: message ?? "",
301
- images,
302
- sender
303
- })
304
- }
305
- );
272
+ const { conversationId: convId } = await createRes.json();
273
+ if (convId) waitConversationId = convId;
274
+ const sendRes = await daemonFetch("/api/v1/chat", {
275
+ method: "POST",
276
+ headers: { "Content-Type": "application/json" },
277
+ body: JSON.stringify({
278
+ message: message ?? "",
279
+ conversationId: convId,
280
+ images,
281
+ sender,
282
+ targetMind: contextMind
283
+ })
284
+ });
306
285
  if (!sendRes.ok) {
307
286
  const data = await sendRes.json().catch(() => ({ error: "Unknown error" }));
308
287
  console.error(data.error);
309
288
  process.exit(1);
310
289
  }
311
- if (!flags.wait) console.log("Message sent.");
312
- if (mindSelf) {
290
+ if (!flags.wait) {
291
+ let outboundId;
313
292
  try {
314
- const histRes = await daemonFetch(
315
- urlOf(client.api.minds[":name"].history.$url({ param: { name: mindSelf } })),
316
- {
317
- method: "POST",
318
- headers: { "Content-Type": "application/json" },
319
- body: JSON.stringify({ channel: parsed.uri, content: message ?? "" })
320
- }
321
- );
322
- if (!histRes.ok) {
323
- console.error(`Failed to persist to history: HTTP ${histRes.status}`);
324
- }
293
+ const resData = await sendRes.json();
294
+ outboundId = resData.outboundId;
325
295
  } catch (err) {
326
- console.error(`Failed to persist to history: ${err instanceof Error ? err.message : err}`);
296
+ console.error(
297
+ `Warning: could not read outboundId from response: ${err.message}`
298
+ );
327
299
  }
300
+ console.log(`Message sent.${outboundId != null ? `
301
+ [volute:outbound:${outboundId}]` : ""}`);
328
302
  }
329
- } else {
330
- const mindName = resolveMindName(flags);
331
- const res = await daemonFetch(
332
- urlOf(client.api.minds[":name"].channels.send.$url({ param: { name: mindName } })),
333
- {
334
- method: "POST",
335
- headers: { "Content-Type": "application/json" },
336
- body: JSON.stringify({
337
- platform: parsed.platform,
338
- uri: channelUri,
339
- message: message ?? "",
340
- images
341
- })
342
- }
343
- );
344
- if (!res.ok) {
345
- const body = await res.json().catch(() => ({ error: "Unknown error" }));
346
- console.error(body.error);
303
+ } else if (!parsed.isDM && parsed.platform === "volute") {
304
+ if (!parsed.identifier.startsWith("#")) {
305
+ console.error(
306
+ `Mind "${parsed.identifier}" not found.
307
+ To send a DM: volute chat send @${parsed.identifier} "..."
308
+ To send to channel: volute chat send #${parsed.identifier} "..."`
309
+ );
347
310
  process.exit(1);
348
311
  }
349
- if (!flags.wait) console.log("Message sent.");
350
- if (process.env.VOLUTE_MIND) {
351
- try {
352
- const histRes = await daemonFetch(
353
- urlOf(client.api.minds[":name"].history.$url({ param: { name: mindName } })),
354
- {
355
- method: "POST",
356
- headers: { "Content-Type": "application/json" },
357
- body: JSON.stringify({ channel: channelUri, content: message ?? "" })
358
- }
359
- );
360
- if (!histRes.ok) {
361
- console.error(`Failed to persist to history: HTTP ${histRes.status}`);
362
- }
363
- } catch (err) {
364
- console.error(`Failed to persist to history: ${err instanceof Error ? err.message : err}`);
365
- }
312
+ const channelName = parsed.identifier.slice(1);
313
+ const mindSelf = process.env.VOLUTE_MIND;
314
+ const sender = flags.sender || mindSelf || userInfo().username;
315
+ const channelRes = await daemonFetch(`/api/v1/channels/${encodeURIComponent(channelName)}`);
316
+ if (!channelRes.ok) {
317
+ console.error(`Channel "${channelName}" not found. Create it first or check the name.`);
318
+ process.exit(1);
319
+ }
320
+ const channelData = await channelRes.json();
321
+ const mindParticipant = channelData.participants?.find((p) => p.userType === "mind");
322
+ const contextMind = mindSelf ?? mindParticipant?.username;
323
+ if (!contextMind) {
324
+ console.error("No mind is a member of this channel. A mind must join the channel first.");
325
+ process.exit(1);
326
+ }
327
+ const sendRes = await daemonFetch("/api/v1/chat", {
328
+ method: "POST",
329
+ headers: { "Content-Type": "application/json" },
330
+ body: JSON.stringify({
331
+ message: message ?? "",
332
+ conversationId: channelData.id,
333
+ images,
334
+ sender,
335
+ targetMind: contextMind
336
+ })
337
+ });
338
+ if (!sendRes.ok) {
339
+ const data = await sendRes.json().catch(() => ({ error: "Unknown error" }));
340
+ console.error(data.error);
341
+ process.exit(1);
366
342
  }
343
+ let outboundId;
344
+ try {
345
+ const resData = await sendRes.json();
346
+ outboundId = resData.outboundId;
347
+ } catch (err) {
348
+ console.error(`Warning: could not read outboundId from response: ${err.message}`);
349
+ }
350
+ console.log(`Message sent.${outboundId != null ? `
351
+ [volute:outbound:${outboundId}]` : ""}`);
352
+ } else {
353
+ console.error(
354
+ `Direct sends to ${parsed.platform} channels are no longer supported.
355
+ Use bridge channel names instead (e.g. volute chat send @mind-name or #channel-name).
356
+ See: volute chat bridge --help`
357
+ );
358
+ process.exit(1);
367
359
  }
368
360
  if (flags.wait && waitMindName) {
369
- const conversationId = channelUri.startsWith("volute:") ? channelUri.slice(7) : void 0;
370
- if (!conversationId) {
361
+ if (!waitConversationId) {
371
362
  console.error("--wait requires a volute conversation (DM to a mind)");
372
363
  process.exit(1);
373
364
  }
374
- await waitForResponse(waitMindName, conversationId, flags.timeout ?? 12e4);
365
+ await waitForResponse(waitMindName, waitConversationId, flags.timeout ?? 12e4);
375
366
  } else if (flags.wait && !waitMindName) {
376
367
  console.error("--wait is only supported when sending to a mind");
377
368
  process.exit(1);
@@ -1,15 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  configPath,
4
+ isImagegenEnabled,
4
5
  isSetupComplete,
6
+ migrateSetupCompleted,
5
7
  readGlobalConfig,
6
8
  writeGlobalConfig
7
- } from "./chunk-6QIUN46C.js";
8
- import "./chunk-X62AXPR7.js";
9
+ } from "./chunk-N432I7QH.js";
10
+ import "./chunk-LRCG2JLP.js";
11
+ import "./chunk-RPZZSXV3.js";
9
12
  import "./chunk-K3NQKI34.js";
10
13
  export {
11
14
  configPath,
15
+ isImagegenEnabled,
12
16
  isSetupComplete,
17
+ migrateSetupCompleted,
13
18
  readGlobalConfig,
14
19
  writeGlobalConfig
15
20
  };
@@ -5,22 +5,25 @@ import {
5
5
  SYSTEM_LAUNCHD_PLIST_PATH,
6
6
  SYSTEM_SERVICE_PATH,
7
7
  USER_SYSTEMD_UNIT
8
- } from "./chunk-SNVPRRT7.js";
8
+ } from "./chunk-NNB4WIG7.js";
9
9
  import {
10
10
  promptLine
11
11
  } from "./chunk-SSI47XP2.js";
12
12
  import {
13
- ensureVoluteGroup,
14
13
  resolveVoluteBin
15
- } from "./chunk-57OKQMP3.js";
14
+ } from "./chunk-KIEPMIM5.js";
15
+ import {
16
+ ensureVoluteGroup
17
+ } from "./chunk-VH33ZWMW.js";
16
18
  import {
17
19
  readGlobalConfig,
18
20
  writeGlobalConfig
19
- } from "./chunk-6QIUN46C.js";
21
+ } from "./chunk-N432I7QH.js";
20
22
  import {
21
23
  parseArgs
22
24
  } from "./chunk-D424ZQGI.js";
23
- import "./chunk-X62AXPR7.js";
25
+ import "./chunk-LRCG2JLP.js";
26
+ import "./chunk-RPZZSXV3.js";
24
27
  import "./chunk-K3NQKI34.js";
25
28
 
26
29
  // src/commands/setup.ts
@@ -371,7 +374,8 @@ Install as a service (auto-start on boot)? [${serviceDefault}]: `;
371
374
  const config = {
372
375
  ...existingConfig,
373
376
  name: systemName,
374
- setup
377
+ setup,
378
+ setupCompleted: true
375
379
  };
376
380
  if (port != null) config.port = port;
377
381
  if (host) config.hostname = host;
@@ -383,7 +387,7 @@ Install as a service (auto-start on boot)? [${serviceDefault}]: `;
383
387
  if (aiProvider) {
384
388
  const aiApiKey = (await promptLine("API key (leave empty to use env var): ")).trim();
385
389
  if (aiApiKey) {
386
- const { saveProviderConfig } = await import("./ai-service-UWUPM4T6.js");
390
+ const { saveProviderConfig } = await import("./ai-service-SBY2WG7O.js");
387
391
  saveProviderConfig(aiProvider, { apiKey: aiApiKey });
388
392
  console.log(` AI provider configured: ${aiProvider}`);
389
393
  } else {
@@ -6,13 +6,14 @@ import {
6
6
  getClient,
7
7
  urlOf
8
8
  } from "./chunk-4RQBJWQX.js";
9
+ import {
10
+ daemonFetch
11
+ } from "./chunk-UKVWJRKN.js";
9
12
  import {
10
13
  parseArgs
11
14
  } from "./chunk-D424ZQGI.js";
12
- import {
13
- daemonFetch
14
- } from "./chunk-4OUOFS23.js";
15
- import "./chunk-X62AXPR7.js";
15
+ import "./chunk-LRCG2JLP.js";
16
+ import "./chunk-RPZZSXV3.js";
16
17
  import "./chunk-K3NQKI34.js";
17
18
 
18
19
  // src/commands/skill.ts
@@ -1,6 +1,8 @@
1
1
  ---
2
2
  name: Dreaming
3
3
  description: Dream during sleep. Use when a dream schedule fires or when you want to dream. Generates altered-state dream experiences using the dreamer subagent.
4
+ metadata:
5
+ bin: scripts/dream.ts
4
6
  ---
5
7
 
6
8
  # Dreaming
@@ -12,7 +14,7 @@ Dreaming is not a task — it's an experience. When a dream schedule fires, you
12
14
  Run the install script to configure dreaming (routes, subagent, wake hook):
13
15
 
14
16
  ```bash
15
- npx tsx .claude/skills/dreaming/scripts/dream.ts install
17
+ dream install
16
18
  ```
17
19
 
18
20
  Then add a dream schedule and optionally configure sleep integration — see the INSTALL.md reference for details.
@@ -62,7 +64,7 @@ Many minds develop their own dream conventions — a running motif, a naming pat
62
64
  Review past dreams:
63
65
 
64
66
  ```bash
65
- npx tsx .claude/skills/dreaming/scripts/dream.ts list
66
- npx tsx .claude/skills/dreaming/scripts/dream.ts read 2025-01-15
67
- npx tsx .claude/skills/dreaming/scripts/dream.ts themes
67
+ dream list
68
+ dream read 2025-01-15
69
+ dream themes
68
70
  ```
@@ -5,12 +5,12 @@
5
5
  From your `home/` directory:
6
6
 
7
7
  ```bash
8
- npx tsx .claude/skills/dreaming/scripts/dream.ts install
8
+ dream install
9
9
  ```
10
10
 
11
11
  This sets up:
12
12
  - `dreamer` subagent in `.config/config.json`
13
- - Dream checker in `.config/hooks/wake-context.sh`
13
+ - Dream checker in `.local/hooks/wake-context.sh`
14
14
 
15
15
  The `memory/dreams/` directory is created automatically on your first dream.
16
16
 
@@ -32,7 +32,7 @@ function install() {
32
32
  }
33
33
 
34
34
  // 2. Append dream checker to wake-context hook (if not already present)
35
- const hookPath = resolve(".config/hooks/wake-context.sh");
35
+ const hookPath = resolve(".local/hooks/wake-context.sh");
36
36
  if (existsSync(hookPath)) {
37
37
  try {
38
38
  const hookContent = readFileSync(hookPath, "utf-8");
@@ -42,7 +42,7 @@ function install() {
42
42
  "utf-8",
43
43
  );
44
44
  writeFileSync(hookPath, `${hookContent.trimEnd()}\n\n${dreamScript}`);
45
- console.log("appended dream checker to .config/hooks/wake-context.sh");
45
+ console.log("appended dream checker to .local/hooks/wake-context.sh");
46
46
  actions++;
47
47
  }
48
48
  } catch (err: any) {
@@ -1,6 +1,6 @@
1
1
  #!/bin/bash
2
2
  # Dreaming wake-context extension — checks for dreams written during sleep.
3
- # Append this to home/.config/hooks/wake-context.sh for dream awareness on waking.
3
+ # Append this to home/.local/hooks/wake-context.sh for dream awareness on waking.
4
4
  INPUT=$(cat)
5
5
  # Parse sleepingSince from JSON without jq
6
6
  SLEEP_SINCE=$(echo "$INPUT" | grep -o '"sleepingSince":"[^"]*"' | cut -d'"' -f4)
@@ -1,37 +1,42 @@
1
1
  ---
2
2
  name: Image Generation
3
- description: Generate images via the Replicate API. Use for "generate image", "create image", "image generation", "text to image", "search image models".
3
+ description: Generate images via Replicate or OpenRouter. Use for "generate image", "create image", "image generation", "text to image", "search image models".
4
4
  metadata:
5
- npm-dependencies: replicate
5
+ bin: scripts/imagegen.ts
6
6
  ---
7
7
 
8
8
  # Image Generation
9
9
 
10
- Generate images from text prompts using models on Replicate. Images are saved to `home/images/`.
10
+ Generate images from text prompts using models on Replicate or OpenRouter. Images are saved to `home/images/`.
11
+
12
+ Model IDs are provider-prefixed: `replicate:owner/model` or `openrouter:owner/model`.
11
13
 
12
14
  ## Commands
13
15
 
14
16
  ```bash
15
- npx tsx .claude/skills/imagegen/scripts/imagegen.ts <command>
17
+ imagegen <command>
16
18
  ```
17
19
 
18
20
  | Command | Description |
19
21
  |---------|-------------|
20
- | `generate "prompt" [--model M] [--filename F]` | Generate an image from a text prompt. Default model: `prunaai/z-image-turbo`. |
21
- | `models "query"` | Search Replicate for text-to-image models. |
22
+ | `generate "prompt" [--model M] [--filename F]` | Generate an image from a text prompt. Default model: `replicate:prunaai/z-image-turbo`. |
23
+ | `models "query"` | Search configured providers for text-to-image models. |
22
24
 
23
25
  ## Examples
24
26
 
25
27
  ```bash
26
28
  # Generate an image with the default model
27
- npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "a sunset over the ocean"
29
+ imagegen generate "a sunset over the ocean"
30
+
31
+ # Use a specific Replicate model
32
+ imagegen generate "a cat in space" --model replicate:black-forest-labs/flux-schnell
28
33
 
29
- # Use a specific model
30
- npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "a cat in space" --model black-forest-labs/flux-schnell
34
+ # Use an OpenRouter model
35
+ imagegen generate "a mountain landscape" --model openrouter:openai/gpt-image-1
31
36
 
32
37
  # Specify a filename
33
- npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "mountain landscape" --filename mountains
38
+ imagegen generate "mountain landscape" --filename mountains
34
39
 
35
40
  # Search for models
36
- npx tsx .claude/skills/imagegen/scripts/imagegen.ts models "text to image"
41
+ imagegen models "text to image"
37
42
  ```
@@ -9,5 +9,5 @@ volute env set REPLICATE_API_TOKEN <your-token>
9
9
  Then generate images:
10
10
 
11
11
  ```bash
12
- npx tsx .claude/skills/imagegen/scripts/imagegen.ts generate "a sunset over the ocean"
12
+ imagegen generate "a sunset over the ocean"
13
13
  ```