volute 0.46.0 → 0.48.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 (172) hide show
  1. package/README.md +10 -10
  2. package/dist/{accept-N5XULCXK.js → accept-KYNC5X3U.js} +1 -1
  3. package/dist/{activity-events-NF6VWTJQ.js → activity-events-MIOK3IOU.js} +3 -3
  4. package/dist/{ai-service-UODCCE4O.js → ai-service-643TNFPH.js} +8 -4
  5. package/dist/{archive-WS2L2VIQ.js → archive-6Z4GFQPH.js} +3 -3
  6. package/dist/{auth-CCFAU4GQ.js → auth-A4VGHADI.js} +4 -4
  7. package/dist/avatar-image-Y45R7LW5.js +23 -0
  8. package/dist/{backup-TST5C2YN.js → backup-UDH4GMSW.js} +15 -15
  9. package/dist/{bridge-2PO3AI5D.js → bridge-3FNSWLNQ.js} +1 -1
  10. package/dist/channels-SGQZHNQJ.js +89 -0
  11. package/dist/{chat-ZIQQS25U.js → chat-X43VYHH2.js} +12 -8
  12. package/dist/{chunk-ZV7MFISX.js → chunk-2MJ7EOMT.js} +20 -2
  13. package/dist/{chunk-R77O2WMK.js → chunk-2OIYNHWO.js} +1 -1
  14. package/dist/{chunk-QCN24XEN.js → chunk-3YUBFTDN.js} +1 -1
  15. package/dist/chunk-4FCL4DVZ.js +48 -0
  16. package/dist/{chunk-F7H6ATM4.js → chunk-5KXCM5AW.js} +18 -2
  17. package/dist/chunk-7KRIHYLR.js +124 -0
  18. package/dist/{chunk-RBNMDAKB.js → chunk-BCG45AQB.js} +15 -1
  19. package/dist/{chunk-QMJCNZ6C.js → chunk-C3KLHJDB.js} +1 -1
  20. package/dist/{chunk-H2X54EHC.js → chunk-DGGZVZTM.js} +1 -1
  21. package/dist/chunk-DW4TRDOZ.js +29 -0
  22. package/dist/{chunk-4JOQZPCE.js → chunk-EIQDZC43.js} +1 -1
  23. package/dist/{chunk-TQJ6ZYVY.js → chunk-FJ2MZ5PH.js} +41 -5
  24. package/dist/{chunk-BJZ4PV7R.js → chunk-HNGFKPNS.js} +26 -10
  25. package/dist/{chunk-5ZQZDDIK.js → chunk-HPGN6XRT.js} +3 -3
  26. package/dist/{chunk-KGIXX4NM.js → chunk-HUNDXZBZ.js} +5 -5
  27. package/dist/{chunk-ZDZISKCL.js → chunk-IJPMIEVE.js} +1 -1
  28. package/dist/chunk-IYCV34IU.js +158 -0
  29. package/dist/{chunk-ZNMCCHCP.js → chunk-LTLFOSA4.js} +2 -2
  30. package/dist/{chunk-K6T43YBD.js → chunk-MJRXFUMS.js} +26 -6
  31. package/dist/{chunk-4YU7HF4L.js → chunk-MOERAQXH.js} +6 -4
  32. package/dist/{chunk-KQSFTPIM.js → chunk-MTRMQFCQ.js} +1 -1
  33. package/dist/{chunk-OV7ZQ2GH.js → chunk-ODDGGLM6.js} +3 -3
  34. package/dist/{chunk-A7WQZKOU.js → chunk-OQJMTHEH.js} +2 -2
  35. package/dist/{chunk-RRNXJOKB.js → chunk-PJVPDY2Z.js} +2 -2
  36. package/dist/{chunk-FXORA5JG.js → chunk-Q7HOAVFR.js} +3 -3
  37. package/dist/{chunk-KDLYIECM.js → chunk-R772ET2M.js} +18 -4
  38. package/dist/{chunk-QLWG3C2Z.js → chunk-RRZ4RQQU.js} +2 -2
  39. package/dist/{mind-list-4D7J4CHD.js → chunk-SHKM5RGD.js} +18 -4
  40. package/dist/{chunk-RXEEYDIB.js → chunk-SZJCJVXV.js} +1 -1
  41. package/dist/{chunk-E3DA4HYV.js → chunk-T4VS7UDW.js} +15 -15
  42. package/dist/{chunk-YXSUMLTC.js → chunk-USD45JKR.js} +322 -76
  43. package/dist/{chunk-JO5IO4FH.js → chunk-VB2QXUJQ.js} +391 -294
  44. package/dist/{chunk-JZ62SYWR.js → chunk-VZRA5TYO.js} +1 -1
  45. package/dist/{chunk-PJ45FQPT.js → chunk-WARH6GIV.js} +8 -8
  46. package/dist/{chunk-PFZBNKUH.js → chunk-WCFSBH33.js} +0 -1
  47. package/dist/{chunk-DRJ24GXK.js → chunk-WQ46E33M.js} +59 -39
  48. package/dist/{chunk-ALKYQULU.js → chunk-WW6C3PLV.js} +1 -1
  49. package/dist/{chunk-CDPBTTZO.js → chunk-XVBSFLM7.js} +2 -2
  50. package/dist/{chunk-6EMWJZBK.js → chunk-YKA7DCVW.js} +1 -1
  51. package/dist/{chunk-IHKGWTGT.js → chunk-YNBXEQAP.js} +31 -1
  52. package/dist/cli.js +34 -26
  53. package/dist/{clock-RHS2JEDL.js → clock-CNRF6F7T.js} +3 -3
  54. package/dist/{cloud-sync-46RS4SDA.js → cloud-sync-WHKCB4CD.js} +22 -19
  55. package/dist/{config-TJLYUV3U.js → config-RPSLA2HX.js} +3 -3
  56. package/dist/{conversations-CJOOCGNW.js → conversations-C7IKYSHD.js} +4 -4
  57. package/dist/{create-IOV4GCRX.js → create-GJKHABJB.js} +16 -5
  58. package/dist/{create-DF3KISTW.js → create-VIQVP3QB.js} +1 -1
  59. package/dist/{daemon-client-IYR4KCPU.js → daemon-client-ZFY5MOAL.js} +5 -3
  60. package/dist/{daemon-restart-VFEI57UO.js → daemon-restart-7KUHVZIN.js} +7 -7
  61. package/dist/daemon.js +829 -496
  62. package/dist/{db-MF2JNRUW.js → db-FO6LXYCW.js} +2 -2
  63. package/dist/{db-LZTLA7XC.js → db-IPXRJUI7.js} +1 -1
  64. package/dist/{delete-HPLC7ETU.js → delete-ESEP7NGQ.js} +1 -1
  65. package/dist/delivery-manager-HZTT5SJR.js +36 -0
  66. package/dist/{delivery-router-N4A7ZC5T.js → delivery-router-3QFG2ZEX.js} +3 -3
  67. package/dist/{down-U2CZ23M4.js → down-G6IADJXV.js} +5 -5
  68. package/dist/echo-text-H3SH337Q.js +36 -0
  69. package/dist/env-6TGPO5WG.js +18 -0
  70. package/dist/{env-VZ4MLFQW.js → env-C7Z55QCJ.js} +6 -6
  71. package/dist/{exec-G3ZRST4Z.js → exec-QIFYZG4C.js} +3 -3
  72. package/dist/{export-LY723I3Z.js → export-C2K3NIRD.js} +4 -4
  73. package/dist/{extension-SEID47SR.js → extension-J4ZQ2GHV.js} +1 -1
  74. package/dist/{extensions-ZELQLTSR.js → extensions-GEKF47A4.js} +24 -19
  75. package/dist/{files-4LN3EN7Q.js → files-LXQSQOFG.js} +4 -4
  76. package/dist/{import-42YNQBF4.js → import-SX3ZXHB4.js} +8 -8
  77. package/dist/{isolation-YMGZZ4E5.js → isolation-MCT4ZYLT.js} +3 -3
  78. package/dist/{join-ZJV7W6MO.js → join-34TR2GXQ.js} +1 -1
  79. package/dist/{list-OXIAY3W7.js → list-PMUXZNAM.js} +1 -1
  80. package/dist/{login-MY6ETFYB.js → login-ARRZ4ORJ.js} +3 -3
  81. package/dist/{login-M6OJUPQ2.js → login-CL4IT2ED.js} +14 -5
  82. package/dist/{logout-WQBWO77G.js → logout-HZYJCYCA.js} +3 -3
  83. package/dist/{logout-NCG3TMDL.js → logout-YZRMZ3O2.js} +1 -1
  84. package/dist/message-delivery-GPQ5SE5N.js +40 -0
  85. package/dist/{mind-LHKS55DI.js → mind-46AOK373.js} +23 -19
  86. package/dist/{mind-activity-tracker-3QRNJVR4.js → mind-activity-tracker-YVZPC4A5.js} +4 -4
  87. package/dist/mind-contacts-GV7XYL5D.js +64 -0
  88. package/dist/{mind-history-VRO5A76U.js → mind-history-TTGA5BHZ.js} +5 -5
  89. package/dist/mind-list-OTHV4ZO4.js +13 -0
  90. package/dist/{mind-profile-PEQYASQX.js → mind-profile-LUG353ZT.js} +1 -1
  91. package/dist/mind-service-2ARGJNKP.js +44 -0
  92. package/dist/{mind-sleep-74TGOQBC.js → mind-sleep-DV7KP255.js} +3 -3
  93. package/dist/{mind-status-UO34ASXZ.js → mind-status-BJNPGXKC.js} +23 -1
  94. package/dist/{mind-wake-LCLGTXA2.js → mind-wake-LVTZ55EZ.js} +1 -1
  95. package/dist/notices-2KU5NTRY.js +25 -0
  96. package/dist/{package-DOD6CPO6.js → package-RTN2PS7O.js} +5 -3
  97. package/dist/{read-QVAXMTPV.js → read-YSWUXYL7.js} +1 -1
  98. package/dist/{register-Y2H4PY5R.js → register-42VBJKTP.js} +3 -3
  99. package/dist/{registry-OUZBZ3Q4.js → registry-UMMDRPRM.js} +2 -2
  100. package/dist/{reject-EV35X64Y.js → reject-SXGCYN4A.js} +1 -1
  101. package/dist/{restart-FJQ662XJ.js → restart-YYEGZJDD.js} +5 -5
  102. package/dist/{sandbox-ZJ7QA6Z6.js → sandbox-5VQ454XP.js} +4 -4
  103. package/dist/scheduler-I7JZCT47.js +34 -0
  104. package/dist/{schema-PVNG3PQM.js → schema-VEVO7HG6.js} +3 -1
  105. package/dist/{seed-CNYIHPOH.js → seed-F2HXZQU4.js} +1 -1
  106. package/dist/{seed-check-VLTVILOV.js → seed-check-TYD7RRZY.js} +1 -1
  107. package/dist/{seed-cmd-AVNUNLZV.js → seed-cmd-MLCTGSX5.js} +3 -3
  108. package/dist/{seed-create-ANXGYSCC.js → seed-create-KQ7OILWB.js} +6 -4
  109. package/dist/seed-readiness-RBPGOLSZ.js +18 -0
  110. package/dist/{seed-sprout-NIUFTX32.js → seed-sprout-HVYCFJLA.js} +30 -31
  111. package/dist/{send-SPE6DVNJ.js → send-TD2X5U3K.js} +6 -6
  112. package/dist/{service-UOCLXDWR.js → service-CVZMQYK6.js} +4 -4
  113. package/dist/{service-install-4HHFDDWY.js → service-install-VCRMFWX5.js} +5 -5
  114. package/dist/{setup-Y2EJI3GG.js → setup-5ECWTYKG.js} +7 -3
  115. package/dist/{setup-QT2A25SY.js → setup-AE4CVUC4.js} +7 -7
  116. package/dist/{skill-FKFHIJRR.js → skill-UUM4JZRF.js} +5 -5
  117. package/dist/skills/dreaming/SKILL.md +5 -1
  118. package/dist/skills/dreaming/scripts/dream.ts +5 -1
  119. package/dist/skills/orientation/SKILL.md +8 -7
  120. package/dist/skills/tending/SKILL.md +51 -2
  121. package/dist/skills/volute-mind/SKILL.md +2 -0
  122. package/dist/{skills-AKCFA7BN.js → skills-B3SVDCEB.js} +5 -5
  123. package/dist/sleep-manager-Z27R3WTW.js +38 -0
  124. package/dist/spirit-WXS3HCLN.js +25 -0
  125. package/dist/{split-WBMZXBHF.js → split-SKZ4Y2D6.js} +1 -1
  126. package/dist/{sprout-SMX42ZBP.js → sprout-KQ43BWZJ.js} +1 -1
  127. package/dist/{src-OJHARHTF.js → src-WLJE73NP.js} +14 -5
  128. package/dist/{start-5JE3TV66.js → start-O6UKK7BG.js} +3 -3
  129. package/dist/{status-SWRVGXBI.js → status-F4PGREUU.js} +19 -7
  130. package/dist/{stop-AAMTG3TU.js → stop-UBX6X5RA.js} +5 -5
  131. package/dist/system-chat-63ABFF6V.js +40 -0
  132. package/dist/{systems-VNB5WKSS.js → systems-JJNGQHAO.js} +4 -4
  133. package/dist/{tailscale-3XOKOW7T.js → tailscale-MCLY5GYE.js} +2 -2
  134. package/dist/{template-hash-446HHH5V.js → template-hash-GSOUARW4.js} +2 -2
  135. package/dist/template-staleness-EMQORSGG.js +15 -0
  136. package/dist/{turn-tracker-FOIBNUUA.js → turn-tracker-KLPV3PAU.js} +6 -6
  137. package/dist/up-RVGDE6CQ.js +20 -0
  138. package/dist/{update-SWAYZRWJ.js → update-OXQEGGXD.js} +5 -5
  139. package/dist/{update-check-PQ2MZ47K.js → update-check-266R4ZSY.js} +3 -3
  140. package/dist/{upgrade-NWAZ7MLD.js → upgrade-K5FIQPQD.js} +1 -1
  141. package/dist/{version-notify-C5CH7CVP.js → version-notify-73YURTFR.js} +41 -25
  142. package/dist/web-assets/assets/index-WdZ60R6c.css +1 -0
  143. package/dist/web-assets/assets/index-taX6Ezfa.js +92 -0
  144. package/dist/web-assets/index.html +2 -2
  145. package/drizzle/0011_drop_turn_summary_event_id.sql +3 -0
  146. package/drizzle/0012_channel_gates.sql +17 -0
  147. package/drizzle/meta/_journal.json +14 -0
  148. package/package.json +5 -3
  149. package/packages/extensions/pages/dist/ui/assets/index-BuXnE-rb.css +1 -0
  150. package/packages/extensions/pages/dist/ui/assets/index-DtzftuPA.js +2 -0
  151. package/packages/extensions/pages/dist/ui/index.html +2 -2
  152. package/templates/_base/src/lib/startup.ts +59 -3
  153. package/templates/claude/src/agent.ts +37 -4
  154. package/templates/claude/src/lib/session-reaper.ts +32 -0
  155. package/templates/claude/src/server.ts +14 -3
  156. package/templates/pi/src/agent.ts +7 -10
  157. package/templates/pi/src/lib/dispatch.ts +65 -0
  158. package/dist/avatar-image-6KY6UU4D.js +0 -16
  159. package/dist/delivery-manager-JINZRG2W.js +0 -33
  160. package/dist/echo-text-VQPB5L2X.js +0 -33
  161. package/dist/message-delivery-R7JSQGYX.js +0 -37
  162. package/dist/mind-service-NB2JMWQZ.js +0 -39
  163. package/dist/scheduler-WVKII3LA.js +0 -31
  164. package/dist/sleep-manager-G6TXSDP7.js +0 -35
  165. package/dist/spirit-RPBLLUQ5.js +0 -23
  166. package/dist/system-chat-NDAW6YP7.js +0 -37
  167. package/dist/up-PS6PFS75.js +0 -18
  168. package/dist/volute-config-A52FHWKM.js +0 -14
  169. package/dist/web-assets/assets/index-B1JBQv2m.css +0 -1
  170. package/dist/web-assets/assets/index-CU6XWICM.js +0 -86
  171. package/packages/extensions/pages/dist/ui/assets/index-BcY6lnq4.css +0 -1
  172. package/packages/extensions/pages/dist/ui/assets/index-CQjEQg1r.js +0 -2
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readGlobalConfig
4
- } from "./chunk-F7H6ATM4.js";
4
+ } from "./chunk-5KXCM5AW.js";
5
5
  import {
6
6
  logger_default
7
7
  } from "./chunk-T2TP6ZC6.js";
@@ -3,16 +3,16 @@ import {
3
3
  compactDateTime,
4
4
  isCompact
5
5
  } from "./chunk-5T5YMX6S.js";
6
+ import {
7
+ getClient,
8
+ urlOf
9
+ } from "./chunk-LOPXTW6H.js";
6
10
  import {
7
11
  resolveMindName
8
12
  } from "./chunk-BTY4WNFE.js";
9
13
  import {
10
14
  daemonFetch
11
- } from "./chunk-RBNMDAKB.js";
12
- import {
13
- getClient,
14
- urlOf
15
- } from "./chunk-LOPXTW6H.js";
15
+ } from "./chunk-BCG45AQB.js";
16
16
  import {
17
17
  command,
18
18
  subcommands
@@ -114,7 +114,7 @@ var listSchedulesCmd = command({
114
114
  console.log("No schedules configured.");
115
115
  return;
116
116
  }
117
- const actionLabel = (s) => s.script ? `[script] ${s.script}` : s.message ?? "";
117
+ const actionLabel = (s) => s.script ? `[script] ${s.script}` : s.messages?.length ? `[rotating x${s.messages.length}] ${s.messages[0]}` : s.message ?? "";
118
118
  if (isCompact()) {
119
119
  for (const s of schedules) {
120
120
  const sched = s.cron ?? (s.fireAt ? `at ${s.fireAt}` : "");
@@ -277,11 +277,11 @@ var cmd = subcommands({
277
277
  },
278
278
  sleep: {
279
279
  description: "Put a mind to sleep",
280
- run: (args) => import("./mind-sleep-74TGOQBC.js").then((m) => m.run(args))
280
+ run: (args) => import("./mind-sleep-DV7KP255.js").then((m) => m.run(args))
281
281
  },
282
282
  wake: {
283
283
  description: "Wake a sleeping mind",
284
- run: (args) => import("./mind-wake-LCLGTXA2.js").then((m) => m.run(args))
284
+ run: (args) => import("./mind-wake-LVTZ55EZ.js").then((m) => m.run(args))
285
285
  }
286
286
  },
287
287
  footer: "Use --mind <name> or VOLUTE_MIND to identify the mind."
@@ -31,7 +31,6 @@ function writeVoluteConfig(mindDir, config) {
31
31
  }
32
32
 
33
33
  export {
34
- WAKE_TRIGGER_DEFAULTS,
35
34
  resolveWakeTriggers,
36
35
  readVoluteConfig,
37
36
  writeVoluteConfig
@@ -1,7 +1,10 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ safeResolveWithinBase
4
+ } from "./chunk-DW4TRDOZ.js";
2
5
  import {
3
6
  readVoluteConfig
4
- } from "./chunk-PFZBNKUH.js";
7
+ } from "./chunk-WCFSBH33.js";
5
8
  import {
6
9
  logger_default
7
10
  } from "./chunk-T2TP6ZC6.js";
@@ -9,49 +12,38 @@ import {
9
12
  mindDir,
10
13
  readAllMinds,
11
14
  voluteHome
12
- } from "./chunk-ALKYQULU.js";
15
+ } from "./chunk-WW6C3PLV.js";
13
16
 
14
17
  // packages/daemon/src/lib/util/avatar-image.ts
15
18
  import { readdir, readFile, writeFile } from "fs/promises";
16
- import { resolve as resolve2 } from "path";
17
-
18
- // packages/daemon/src/lib/util/paths.ts
19
- import { resolve, sep } from "path";
20
- var PathTraversalError = class extends Error {
21
- constructor(base, userPath) {
22
- super(`Path "${userPath}" escapes base directory "${base}"`);
23
- this.name = "PathTraversalError";
24
- }
25
- };
26
- function resolveWithinBase(base, userPath) {
27
- const resolvedBase = resolve(base);
28
- const target = resolve(resolvedBase, userPath);
29
- if (target !== resolvedBase && !target.startsWith(resolvedBase + sep)) {
30
- throw new PathTraversalError(base, userPath);
31
- }
32
- return target;
33
- }
34
- function safeResolveWithinBase(base, userPath) {
35
- try {
36
- return resolveWithinBase(base, userPath);
37
- } catch {
38
- return null;
39
- }
40
- }
41
-
42
- // packages/daemon/src/lib/util/avatar-image.ts
19
+ import { extname, resolve } from "path";
43
20
  var alog = logger_default.child("avatar-image");
44
21
  var AVATAR_DIM = 256;
22
+ var AVATAR_CONTEXT_DIM = 128;
23
+ var MAX_AVATAR_BLOCK_BYTES = 64 * 1024;
24
+ var MIME_BY_EXT = {
25
+ ".png": "image/png",
26
+ ".jpg": "image/jpeg",
27
+ ".jpeg": "image/jpeg",
28
+ ".gif": "image/gif",
29
+ ".webp": "image/webp"
30
+ };
31
+ var warnedSharpUnavailable = false;
45
32
  async function loadSharp() {
46
33
  try {
47
34
  const mod = await import("sharp");
48
35
  return mod.default ?? mod;
49
36
  } catch (err) {
50
- const code = err.code;
51
- if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
52
- alog.debug("sharp not available, keeping original avatars");
53
- } else {
54
- alog.warn("sharp import failed, keeping original avatars", logger_default.errorData(err));
37
+ if (!warnedSharpUnavailable) {
38
+ warnedSharpUnavailable = true;
39
+ const code = err.code;
40
+ if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
41
+ alog.warn(
42
+ "sharp is not installed \u2014 avatars will not be downscaled or inlined into mind context. Install the 'sharp' dependency to restore avatar image support."
43
+ );
44
+ } else {
45
+ alog.warn("sharp import failed, avatar image support disabled", logger_default.errorData(err));
46
+ }
55
47
  }
56
48
  return null;
57
49
  }
@@ -81,10 +73,10 @@ async function downscaleFile(sharp, filePath) {
81
73
  async function migrateAvatarSizes() {
82
74
  const sharp = await loadSharp();
83
75
  if (!sharp) return;
84
- const userAvatarsDir = resolve2(voluteHome(), "avatars");
76
+ const userAvatarsDir = resolve(voluteHome(), "avatars");
85
77
  let userAvatars = [];
86
78
  try {
87
- userAvatars = (await readdir(userAvatarsDir)).map((f) => resolve2(userAvatarsDir, f));
79
+ userAvatars = (await readdir(userAvatarsDir)).map((f) => resolve(userAvatarsDir, f));
88
80
  } catch {
89
81
  }
90
82
  const mindAvatars = [];
@@ -93,7 +85,7 @@ async function migrateAvatarSizes() {
93
85
  const dir = mind.dir ?? mindDir(mind.name);
94
86
  const avatar = readVoluteConfig(dir)?.profile?.avatar;
95
87
  if (!avatar) continue;
96
- const path = safeResolveWithinBase(resolve2(dir, "home"), avatar);
88
+ const path = safeResolveWithinBase(resolve(dir, "home"), avatar);
97
89
  if (path) mindAvatars.push(path);
98
90
  }
99
91
  } catch (err) {
@@ -111,10 +103,38 @@ async function migrateAvatarSizes() {
111
103
  }
112
104
  }
113
105
  }
106
+ async function renderAvatarBlock(filePath, label) {
107
+ const ext = extname(filePath).toLowerCase();
108
+ const mediaType = MIME_BY_EXT[ext];
109
+ if (!mediaType) return null;
110
+ const sharp = await loadSharp();
111
+ if (!sharp) return null;
112
+ const data = await readFile(filePath);
113
+ let imageData;
114
+ try {
115
+ imageData = await sharp(data, { animated: true }).resize(AVATAR_CONTEXT_DIM, AVATAR_CONTEXT_DIM, { fit: "cover" }).toBuffer();
116
+ } catch (err) {
117
+ alog.warn(`avatar resize failed for ${label}, omitting image`, logger_default.errorData(err));
118
+ return null;
119
+ }
120
+ const base64 = imageData.toString("base64");
121
+ if (base64.length > MAX_AVATAR_BLOCK_BYTES) {
122
+ alog.warn(
123
+ `avatar for ${label} is ${base64.length} bytes after resize (> ${MAX_AVATAR_BLOCK_BYTES}), omitting image`
124
+ );
125
+ return null;
126
+ }
127
+ return [
128
+ { type: "text", text: `[Avatar for ${label}]` },
129
+ { type: "image", media_type: mediaType, data: base64 }
130
+ ];
131
+ }
114
132
 
115
133
  export {
116
- safeResolveWithinBase,
117
134
  AVATAR_DIM,
135
+ AVATAR_CONTEXT_DIM,
136
+ MAX_AVATAR_BLOCK_BYTES,
118
137
  normalizeAvatar,
119
- migrateAvatarSizes
138
+ migrateAvatarSizes,
139
+ renderAvatarBlock
120
140
  };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  minds,
4
4
  schema_exports
5
- } from "./chunk-ZV7MFISX.js";
5
+ } from "./chunk-2MJ7EOMT.js";
6
6
 
7
7
  // packages/daemon/src/lib/db.ts
8
8
  import { chmodSync, existsSync } from "fs";
@@ -3,10 +3,10 @@ import {
3
3
  LAUNCHD_PLIST_LABEL,
4
4
  LAUNCHD_PLIST_PATH,
5
5
  USER_SYSTEMD_UNIT
6
- } from "./chunk-TQJ6ZYVY.js";
6
+ } from "./chunk-FJ2MZ5PH.js";
7
7
  import {
8
8
  resolveVoluteBin
9
- } from "./chunk-H2X54EHC.js";
9
+ } from "./chunk-DGGZVZTM.js";
10
10
 
11
11
  // packages/daemon/src/lib/config/service-install.ts
12
12
  import { execFile } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  voluteSystemDir
4
- } from "./chunk-ALKYQULU.js";
4
+ } from "./chunk-WW6C3PLV.js";
5
5
 
6
6
  // packages/daemon/src/lib/update-check.ts
7
7
  import { execFile as execFileCb, execFileSync } from "child_process";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  readGlobalConfig,
4
4
  writeGlobalConfig
5
- } from "./chunk-F7H6ATM4.js";
5
+ } from "./chunk-5KXCM5AW.js";
6
6
  import {
7
7
  logger_default
8
8
  } from "./chunk-T2TP6ZC6.js";
@@ -109,6 +109,34 @@ function templateForProvider(provider) {
109
109
  if (provider === "openai-codex") return "codex";
110
110
  return "pi";
111
111
  }
112
+ var PROVIDER_ENV_VAR = {
113
+ anthropic: "ANTHROPIC_API_KEY",
114
+ "openai-codex": "OPENAI_API_KEY",
115
+ openrouter: "OPENROUTER_API_KEY",
116
+ openai: "OPENAI_API_KEY",
117
+ google: "GEMINI_API_KEY",
118
+ groq: "GROQ_API_KEY",
119
+ cerebras: "CEREBRAS_API_KEY",
120
+ xai: "XAI_API_KEY",
121
+ mistral: "MISTRAL_API_KEY",
122
+ zai: "ZAI_API_KEY"
123
+ };
124
+ function providerForMindTemplate(template, model) {
125
+ if (!template || template === "claude") return "anthropic";
126
+ if (template === "codex") return "openai-codex";
127
+ if (model?.includes(":")) return model.split(":")[0];
128
+ return void 0;
129
+ }
130
+ async function missingCredentialWarning(template, model, mindName) {
131
+ const provider = providerForMindTemplate(template, model);
132
+ if (!provider) return null;
133
+ const envVar = PROVIDER_ENV_VAR[provider] ?? `${provider.toUpperCase().replace(/-/g, "_")}_API_KEY`;
134
+ if (await resolveApiKey(provider)) return null;
135
+ if (provider === "openai-codex" && process.env.OPENAI_API_KEY) return null;
136
+ const { loadMergedEnv } = await import("./env-6TGPO5WG.js");
137
+ if (loadMergedEnv(mindName)[envVar]) return null;
138
+ return `No ${provider} credentials are configured, so ${mindName} will start but stay silent until a key is available. Set one with \`volute env set ${envVar} <key> --mind ${mindName}\`, or configure the ${provider} provider in the web dashboard (Settings \u2192 Providers).`;
139
+ }
112
140
  async function resolveTemplate(modelId) {
113
141
  if (!modelId) {
114
142
  const enabled = getEnabledModels();
@@ -379,6 +407,8 @@ export {
379
407
  getUtilityModel,
380
408
  setUtilityModel,
381
409
  aiCompleteUtility,
410
+ providerForMindTemplate,
411
+ missingCredentialWarning,
382
412
  resolveTemplate,
383
413
  getEnabledModels,
384
414
  setEnabledModels,
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ if (!process.env.VOLUTE_HOME) {
10
10
  var command = process.argv[2];
11
11
  var args = process.argv.slice(3);
12
12
  if (command === "--version" || command === "-v") {
13
- const { default: pkg } = await import("./package-DOD6CPO6.js");
13
+ const { default: pkg } = await import("./package-RTN2PS7O.js");
14
14
  console.log(pkg.version);
15
15
  process.exit(0);
16
16
  }
@@ -33,72 +33,80 @@ var ungatedCommands = /* @__PURE__ */ new Set([
33
33
  void 0
34
34
  ]);
35
35
  if (!ungatedCommands.has(command)) {
36
- const { isSetupComplete } = await import("./setup-Y2EJI3GG.js");
37
- if (!isSetupComplete()) {
38
- console.error("Volute is not set up. Run `volute setup` first.");
36
+ const { setupStatus, setupUrl } = await import("./setup-5ECWTYKG.js");
37
+ const status = setupStatus();
38
+ if (status !== "complete") {
39
+ if (status === "in-progress") {
40
+ console.error("Volute setup isn't finished yet.");
41
+ console.error(`Open ${setupUrl()} in your browser to complete it.`);
42
+ console.error("(If the daemon isn't running, start it with `volute up` first.)");
43
+ } else {
44
+ console.error("Volute is not set up. Run `volute setup` to get started.");
45
+ console.error("It starts the daemon and opens a browser wizard to finish configuration.");
46
+ }
39
47
  process.exit(1);
40
48
  }
41
49
  }
42
50
  switch (command) {
43
51
  case "setup":
44
- await import("./setup-QT2A25SY.js").then((m) => m.run(args));
52
+ await import("./setup-AE4CVUC4.js").then((m) => m.run(args));
45
53
  break;
46
54
  case "mind":
47
- await import("./mind-LHKS55DI.js").then((m) => m.run(args));
55
+ await import("./mind-46AOK373.js").then((m) => m.run(args));
48
56
  break;
49
57
  case "seed":
50
- await import("./seed-cmd-AVNUNLZV.js").then((m) => m.run(args));
58
+ await import("./seed-cmd-MLCTGSX5.js").then((m) => m.run(args));
51
59
  break;
52
60
  case "chat":
53
- await import("./chat-ZIQQS25U.js").then((m) => m.run(args));
61
+ await import("./chat-X43VYHH2.js").then((m) => m.run(args));
54
62
  break;
55
63
  case "variant":
56
64
  await import("./variant-HHDTW74J.js").then((m) => m.run(args));
57
65
  break;
58
66
  case "clock":
59
- await import("./clock-RHS2JEDL.js").then((m) => m.run(args));
67
+ await import("./clock-CNRF6F7T.js").then((m) => m.run(args));
60
68
  break;
61
69
  case "skill":
62
- await import("./skill-FKFHIJRR.js").then((m) => m.run(args));
70
+ await import("./skill-UUM4JZRF.js").then((m) => m.run(args));
63
71
  break;
64
72
  case "env":
65
- await import("./env-VZ4MLFQW.js").then((m) => m.run(args));
73
+ await import("./env-C7Z55QCJ.js").then((m) => m.run(args));
66
74
  break;
67
75
  case "config":
68
- await import("./config-TJLYUV3U.js").then((m) => m.run(args));
76
+ await import("./config-RPSLA2HX.js").then((m) => m.run(args));
69
77
  break;
70
78
  case "up":
71
- await import("./up-PS6PFS75.js").then((m) => m.run(args));
79
+ await import("./up-RVGDE6CQ.js").then((m) => m.run(args));
72
80
  break;
73
81
  case "backup":
74
- await import("./backup-TST5C2YN.js").then((m) => m.run(args));
82
+ await import("./backup-UDH4GMSW.js").then((m) => m.run(args));
75
83
  break;
76
84
  case "down":
77
- await import("./down-U2CZ23M4.js").then((m) => m.run(args));
85
+ await import("./down-G6IADJXV.js").then((m) => m.run(args));
78
86
  break;
79
87
  case "restart":
80
- await import("./daemon-restart-VFEI57UO.js").then((m) => m.run(args));
88
+ await import("./daemon-restart-7KUHVZIN.js").then((m) => m.run(args));
81
89
  break;
82
90
  case "update":
83
- await import("./update-SWAYZRWJ.js").then((m) => m.run(args));
91
+ await import("./update-OXQEGGXD.js").then((m) => m.run(args));
84
92
  break;
85
93
  case "status":
86
- await import("./status-SWRVGXBI.js").then((m) => m.run(args));
94
+ await import("./status-F4PGREUU.js").then((m) => m.run(args));
87
95
  break;
88
96
  case "extension":
89
- await import("./extension-SEID47SR.js").then((m) => m.run(args));
97
+ await import("./extension-J4ZQ2GHV.js").then((m) => m.run(args));
90
98
  break;
91
99
  case "systems":
92
- await import("./systems-VNB5WKSS.js").then((m) => m.run(args));
100
+ await import("./systems-JJNGQHAO.js").then((m) => m.run(args));
93
101
  break;
94
102
  case "login":
95
- await import("./login-M6OJUPQ2.js").then((m) => m.run(args));
103
+ await import("./login-CL4IT2ED.js").then((m) => m.run(args));
96
104
  break;
97
105
  case "logout":
98
- await import("./logout-WQBWO77G.js").then((m) => m.run(args));
106
+ await import("./logout-HZYJCYCA.js").then((m) => m.run(args));
99
107
  break;
100
108
  case "service":
101
- await import("./service-UOCLXDWR.js").then((m) => m.run(args));
109
+ await import("./service-CVZMQYK6.js").then((m) => m.run(args));
102
110
  break;
103
111
  case "--help":
104
112
  case "-h":
@@ -140,7 +148,7 @@ System:
140
148
  update Update volute
141
149
  systems register/login/logout volute.systems account`);
142
150
  try {
143
- const { resolveDaemonUrl, getAuthToken } = await import("./daemon-client-IYR4KCPU.js");
151
+ const { resolveDaemonUrl, getAuthToken } = await import("./daemon-client-ZFY5MOAL.js");
144
152
  const token = getAuthToken();
145
153
  const headers = {};
146
154
  if (token) headers.Authorization = `Bearer ${token}`;
@@ -181,7 +189,7 @@ use --mind <name> or VOLUTE_MIND env var to identify the mind.`);
181
189
  default: {
182
190
  let isExtensionCommand = false;
183
191
  try {
184
- const { daemonFetch } = await import("./daemon-client-IYR4KCPU.js");
192
+ const { daemonFetch } = await import("./daemon-client-ZFY5MOAL.js");
185
193
  const res = await daemonFetch("/api/extensions/commands");
186
194
  if (res.ok) {
187
195
  const extCommands = await res.json();
@@ -295,7 +303,7 @@ Run 'volute --help' for usage.`);
295
303
  }
296
304
  }
297
305
  if (command !== "update") {
298
- import("./update-check-PQ2MZ47K.js").then((m) => m.checkForUpdate()).then((result) => {
306
+ import("./update-check-266R4ZSY.js").then((m) => m.checkForUpdate()).then((result) => {
299
307
  if (result.updateAvailable) {
300
308
  console.error(`
301
309
  Update available: ${result.current} \u2192 ${result.latest}`);
@@ -2,11 +2,11 @@
2
2
  import {
3
3
  parseDuration,
4
4
  run
5
- } from "./chunk-PJ45FQPT.js";
5
+ } from "./chunk-WARH6GIV.js";
6
6
  import "./chunk-5T5YMX6S.js";
7
- import "./chunk-BTY4WNFE.js";
8
- import "./chunk-RBNMDAKB.js";
9
7
  import "./chunk-LOPXTW6H.js";
8
+ import "./chunk-BTY4WNFE.js";
9
+ import "./chunk-BCG45AQB.js";
10
10
  import "./chunk-TXSA4Q3V.js";
11
11
  import "./chunk-O7IGP7ZW.js";
12
12
  import "./chunk-K3NQKI34.js";
@@ -1,31 +1,34 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  deliverMessage
4
- } from "./chunk-JO5IO4FH.js";
5
- import "./chunk-ZDZISKCL.js";
6
- import "./chunk-BJZ4PV7R.js";
7
- import "./chunk-QLWG3C2Z.js";
8
- import "./chunk-KGIXX4NM.js";
4
+ } from "./chunk-VB2QXUJQ.js";
5
+ import "./chunk-HNGFKPNS.js";
6
+ import "./chunk-RRZ4RQQU.js";
7
+ import "./chunk-USD45JKR.js";
8
+ import "./chunk-MOERAQXH.js";
9
+ import "./chunk-HUNDXZBZ.js";
10
+ import "./chunk-ODDGGLM6.js";
9
11
  import {
10
12
  getAuthHeaders,
11
13
  getWebhookUrl
12
- } from "./chunk-5ZQZDDIK.js";
13
- import "./chunk-PFZBNKUH.js";
14
- import "./chunk-JZ62SYWR.js";
15
- import "./chunk-KQSFTPIM.js";
16
- import "./chunk-4JOQZPCE.js";
17
- import "./chunk-YXSUMLTC.js";
18
- import "./chunk-4YU7HF4L.js";
19
- import "./chunk-H2X54EHC.js";
20
- import "./chunk-IHKGWTGT.js";
21
- import "./chunk-F7H6ATM4.js";
22
- import "./chunk-OV7ZQ2GH.js";
23
- import "./chunk-ZNMCCHCP.js";
14
+ } from "./chunk-HPGN6XRT.js";
15
+ import "./chunk-VZRA5TYO.js";
16
+ import "./chunk-IYCV34IU.js";
17
+ import "./chunk-MTRMQFCQ.js";
18
+ import "./chunk-WQ46E33M.js";
19
+ import "./chunk-DW4TRDOZ.js";
20
+ import "./chunk-WCFSBH33.js";
21
+ import "./chunk-EIQDZC43.js";
22
+ import "./chunk-DGGZVZTM.js";
23
+ import "./chunk-IJPMIEVE.js";
24
+ import "./chunk-YNBXEQAP.js";
25
+ import "./chunk-5KXCM5AW.js";
26
+ import "./chunk-LTLFOSA4.js";
24
27
  import {
25
28
  logger_default
26
29
  } from "./chunk-T2TP6ZC6.js";
27
- import "./chunk-ALKYQULU.js";
28
- import "./chunk-ZV7MFISX.js";
30
+ import "./chunk-WW6C3PLV.js";
31
+ import "./chunk-2MJ7EOMT.js";
29
32
  import "./chunk-K3NQKI34.js";
30
33
 
31
34
  // packages/daemon/src/lib/cloud-sync.ts
@@ -7,7 +7,7 @@ import "./chunk-K3NQKI34.js";
7
7
 
8
8
  // packages/cli/src/commands/config.ts
9
9
  async function listModels() {
10
- const { daemonFetch } = await import("./daemon-client-IYR4KCPU.js");
10
+ const { daemonFetch } = await import("./daemon-client-ZFY5MOAL.js");
11
11
  const res = await daemonFetch("/api/config/models");
12
12
  if (!res.ok) {
13
13
  console.error(`Failed to fetch models (HTTP ${res.status})`);
@@ -24,7 +24,7 @@ async function listModels() {
24
24
  }
25
25
  }
26
26
  async function listProviders() {
27
- const { daemonFetch } = await import("./daemon-client-IYR4KCPU.js");
27
+ const { daemonFetch } = await import("./daemon-client-ZFY5MOAL.js");
28
28
  const res = await daemonFetch("/api/config/providers");
29
29
  if (!res.ok) {
30
30
  console.error(`Failed to fetch providers (HTTP ${res.status})`);
@@ -41,7 +41,7 @@ async function listProviders() {
41
41
  }
42
42
  }
43
43
  async function showStatus() {
44
- const { daemonFetch } = await import("./daemon-client-IYR4KCPU.js");
44
+ const { daemonFetch } = await import("./daemon-client-ZFY5MOAL.js");
45
45
  const res = await daemonFetch("/api/config/status");
46
46
  if (!res.ok) {
47
47
  console.error(`Failed to fetch config (HTTP ${res.status})`);
@@ -29,11 +29,11 @@ import {
29
29
  removeParticipant,
30
30
  setConversationPrivate,
31
31
  updateChannelSettings
32
- } from "./chunk-5ZQZDDIK.js";
33
- import "./chunk-ZNMCCHCP.js";
32
+ } from "./chunk-HPGN6XRT.js";
33
+ import "./chunk-LTLFOSA4.js";
34
34
  import "./chunk-T2TP6ZC6.js";
35
- import "./chunk-ALKYQULU.js";
36
- import "./chunk-ZV7MFISX.js";
35
+ import "./chunk-WW6C3PLV.js";
36
+ import "./chunk-2MJ7EOMT.js";
37
37
  import "./chunk-K3NQKI34.js";
38
38
  export {
39
39
  addMessage,
@@ -8,7 +8,7 @@ import "./chunk-K3NQKI34.js";
8
8
  // packages/cli/src/commands/create.ts
9
9
  var cmd = command({
10
10
  name: "volute mind create",
11
- description: "Create a new mind",
11
+ description: "Create a new mind (see 'volute seed create' for the recommended path)",
12
12
  args: [{ name: "name", required: true, description: "Name for the new mind" }],
13
13
  flags: {
14
14
  template: { type: "string", description: "Template to use (claude, pi, codex)" },
@@ -21,11 +21,11 @@ var cmd = command({
21
21
  const name = args.name;
22
22
  let template = flags.template;
23
23
  if (!template) {
24
- const { resolveTemplate } = await import("./ai-service-UODCCE4O.js");
24
+ const { resolveTemplate } = await import("./ai-service-643TNFPH.js");
25
25
  template = await resolveTemplate();
26
26
  }
27
27
  const skills = flags.skills === "none" ? [] : flags.skills ? flags.skills.split(",") : void 0;
28
- const { daemonFetch } = await import("./daemon-client-IYR4KCPU.js");
28
+ const { daemonFetch } = await import("./daemon-client-ZFY5MOAL.js");
29
29
  const { getClient, urlOf } = await import("./api-client-LC5YRA32.js");
30
30
  const client = getClient();
31
31
  const res = await daemonFetch(urlOf(client.api.minds.$url()), {
@@ -38,10 +38,21 @@ var cmd = command({
38
38
  console.error(data.error ?? "Failed to create mind");
39
39
  process.exit(1);
40
40
  }
41
+ const created = data.name ?? name;
41
42
  console.log(`
42
- ${data.message ?? `Created mind: ${data.name} (port ${data.port})`}`);
43
+ ${data.message ?? `Created mind: ${created} (port ${data.port})`}`);
44
+ if (data.warning) console.warn(`
45
+ \u26A0 ${data.warning}`);
46
+ if (data.credentialWarning) console.warn(`
47
+ \u26A0 ${data.credentialWarning}`);
43
48
  console.log(`
44
- volute mind start ${data.name ?? name}`);
49
+ Start it, then say hello:`);
50
+ console.log(` volute mind start ${created}`);
51
+ console.log(` volute chat send @${created} "hello"`);
52
+ console.log(
53
+ `
54
+ Tip: 'volute seed create' grows a mind that shapes its own identity \u2014 the recommended way to start.`
55
+ );
45
56
  }
46
57
  });
47
58
  var run = cmd.execute;
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-BTY4WNFE.js";
5
5
  import {
6
6
  daemonFetch
7
- } from "./chunk-RBNMDAKB.js";
7
+ } from "./chunk-BCG45AQB.js";
8
8
  import {
9
9
  command
10
10
  } from "./chunk-TXSA4Q3V.js";
@@ -4,13 +4,15 @@ import {
4
4
  daemonFetch,
5
5
  getAuthToken,
6
6
  readSessionFile,
7
- resolveDaemonUrl
8
- } from "./chunk-RBNMDAKB.js";
7
+ resolveDaemonUrl,
8
+ resolveWebUrl
9
+ } from "./chunk-BCG45AQB.js";
9
10
  import "./chunk-K3NQKI34.js";
10
11
  export {
11
12
  daemonDispatcher,
12
13
  daemonFetch,
13
14
  getAuthToken,
14
15
  readSessionFile,
15
- resolveDaemonUrl
16
+ resolveDaemonUrl,
17
+ resolveWebUrl
16
18
  };
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  stopDaemon
4
- } from "./chunk-RRNXJOKB.js";
4
+ } from "./chunk-PJVPDY2Z.js";
5
5
  import {
6
6
  run
7
- } from "./chunk-K6T43YBD.js";
7
+ } from "./chunk-MJRXFUMS.js";
8
8
  import {
9
9
  command
10
10
  } from "./chunk-TXSA4Q3V.js";
@@ -15,11 +15,11 @@ import {
15
15
  pollHealth,
16
16
  readDaemonConfig,
17
17
  restartService
18
- } from "./chunk-TQJ6ZYVY.js";
19
- import "./chunk-H2X54EHC.js";
20
- import "./chunk-F7H6ATM4.js";
21
- import "./chunk-ALKYQULU.js";
22
- import "./chunk-ZV7MFISX.js";
18
+ } from "./chunk-FJ2MZ5PH.js";
19
+ import "./chunk-DGGZVZTM.js";
20
+ import "./chunk-5KXCM5AW.js";
21
+ import "./chunk-WW6C3PLV.js";
22
+ import "./chunk-2MJ7EOMT.js";
23
23
  import "./chunk-K3NQKI34.js";
24
24
 
25
25
  // src/commands/daemon-restart.ts