volute 0.49.0 → 0.50.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 (210) hide show
  1. package/README.md +2 -2
  2. package/dist/{accept-KYNC5X3U.js → accept-5NK5XJB5.js} +2 -1
  3. package/dist/{activity-events-GJJAI2WT.js → activity-events-H7YI3BTF.js} +3 -3
  4. package/dist/{ai-service-A7FS7EC3.js → ai-service-V4CTNGI3.js} +5 -4
  5. package/dist/{archive-7E3YE6VF.js → archive-ORM3ENHI.js} +3 -3
  6. package/dist/{auth-ABYLOEZ7.js → auth-DT7GY7EZ.js} +10 -6
  7. package/dist/{avatar-image-6ATV2IOZ.js → avatar-image-QEPAP3A5.js} +3 -3
  8. package/dist/{backup-XYAMT4CU.js → backup-IE6PMXJO.js} +11 -12
  9. package/dist/{bridge-3FNSWLNQ.js → bridge-YK7NTRU5.js} +2 -1
  10. package/dist/{channels-SGQZHNQJ.js → channels-FSAHOQWI.js} +2 -1
  11. package/dist/{chat-OGXAEXMV.js → chat-W5K6HCBE.js} +9 -9
  12. package/dist/{chunk-3B427GUK.js → chunk-3BAFMGCJ.js} +2 -2
  13. package/dist/{chunk-4B62E4CG.js → chunk-4CN7OCJE.js} +2 -2
  14. package/dist/{chunk-VNRSXEBF.js → chunk-574M6I7F.js} +38 -5
  15. package/dist/{chunk-HCYQRME2.js → chunk-5FVANDON.js} +2 -2
  16. package/dist/{chunk-P4LHVRNE.js → chunk-5IIVOWSP.js} +27 -19
  17. package/dist/{chunk-TXJL36ZQ.js → chunk-5PKFJHCR.js} +2 -2
  18. package/dist/{chunk-JPGHSXSV.js → chunk-5TPC4KCV.js} +23 -9
  19. package/dist/{chunk-YIJGKHIS.js → chunk-632FJ23O.js} +24 -20
  20. package/dist/{chunk-IH5TKXX6.js → chunk-636GFQNE.js} +11 -11
  21. package/dist/{chunk-EFT2OALG.js → chunk-6BM2I736.js} +20 -5
  22. package/dist/{chunk-JCBPU57A.js → chunk-74T3CEXK.js} +6 -6
  23. package/dist/{chunk-EG5LSKHU.js → chunk-77IZUVBB.js} +2 -2
  24. package/dist/{chunk-K3JOLGWF.js → chunk-7DXLIYPY.js} +76 -63
  25. package/dist/chunk-7FDWPQCU.js +289 -0
  26. package/dist/chunk-7OZWKHA3.js +548 -0
  27. package/dist/{chunk-PY24ZL62.js → chunk-7UWXAJMK.js} +1 -1
  28. package/dist/{chunk-MG3Z34YE.js → chunk-7XDOTN4R.js} +1 -1
  29. package/dist/{chunk-SX72DOO3.js → chunk-AFSLNUTT.js} +1 -1
  30. package/dist/{chunk-DVN6DNMI.js → chunk-AJWFDIEY.js} +17 -2
  31. package/dist/chunk-ALIVXDM4.js +1014 -0
  32. package/dist/{chunk-RSBL3FAD.js → chunk-CAIYV33P.js} +234 -24
  33. package/dist/{chunk-ZX46PGCC.js → chunk-E5S3ILVA.js} +1 -1
  34. package/dist/{chunk-SHKM5RGD.js → chunk-EEOMA4DX.js} +1 -1
  35. package/dist/chunk-EQKSRVDE.js +2857 -0
  36. package/dist/chunk-FNJCBRD3.js +31 -0
  37. package/dist/{chunk-EADX54RG.js → chunk-HW6Q7AMB.js} +4 -4
  38. package/dist/chunk-JI67D7O2.js +1222 -0
  39. package/dist/{chunk-KHCKZ36O.js → chunk-KAEZOVP6.js} +1 -1
  40. package/dist/chunk-LNNI3MS4.js +54 -0
  41. package/dist/{chunk-BCG45AQB.js → chunk-M74I3HHF.js} +15 -5
  42. package/dist/chunk-MLZBBLMT.js +109 -0
  43. package/dist/{chunk-5T5YMX6S.js → chunk-PW65BXY5.js} +5 -0
  44. package/dist/{chunk-NOIAHMJB.js → chunk-QFVGPKJI.js} +1 -1
  45. package/dist/{chunk-VIUH5CHQ.js → chunk-SFRYRW37.js} +50 -33
  46. package/dist/{chunk-L27YYONJ.js → chunk-SSNZ6ZNN.js} +1 -1
  47. package/dist/{chunk-GWVFDUNB.js → chunk-TGJHGVBZ.js} +8 -10
  48. package/dist/{chunk-6HGEZJDH.js → chunk-U3EJJ7JN.js} +2 -2
  49. package/dist/{chunk-4DSGN4FL.js → chunk-UC6BNMGT.js} +43 -13
  50. package/dist/{chunk-JBIFXB6I.js → chunk-WBBKYUGF.js} +3 -5
  51. package/dist/{chunk-FBBS4BVR.js → chunk-X67VT4QO.js} +1 -1
  52. package/dist/{chunk-DAIIMBLB.js → chunk-YQOYZ6G7.js} +3 -5
  53. package/dist/{chunk-JCWB2ITW.js → chunk-ZUG76D3P.js} +35 -5
  54. package/dist/cli.js +34 -27
  55. package/dist/{clock-6JZL2FS6.js → clock-LH7UFNLJ.js} +4 -3
  56. package/dist/{cloud-sync-VFDTNNCA.js → cloud-sync-IDJFVDEP.js} +22 -19
  57. package/dist/{config-RPSLA2HX.js → config-UGJS57VT.js} +3 -3
  58. package/dist/{conversations-TUM5PJJ4.js → conversations-S2232Y5I.js} +8 -4
  59. package/dist/{create-Z5FSDNVZ.js → create-2M7DAHQX.js} +2 -2
  60. package/dist/{create-VIQVP3QB.js → create-M727VUDF.js} +2 -1
  61. package/dist/{daemon-client-ZFY5MOAL.js → daemon-client-VVYFZI2D.js} +2 -1
  62. package/dist/{daemon-restart-54L4B6AQ.js → daemon-restart-2AAGYFHE.js} +6 -7
  63. package/dist/daemon.js +1625 -529
  64. package/dist/{db-F6UMFRYD.js → db-QAY45Z56.js} +2 -2
  65. package/dist/{delete-ESEP7NGQ.js → delete-O7PEFQDF.js} +1 -1
  66. package/dist/delivery-manager-B4OKWD2P.js +33 -0
  67. package/dist/{delivery-router-VUOL5YSA.js → delivery-router-JE7SHYNU.js} +7 -5
  68. package/dist/{down-6X7KX7BZ.js → down-D4IRNEMJ.js} +5 -5
  69. package/dist/echo-text-WYAAODBV.js +39 -0
  70. package/dist/{env-ZYMSCB7B.js → env-ABM5IMA7.js} +3 -2
  71. package/dist/{env-KUL4XKN2.js → env-AZK5X4W7.js} +3 -3
  72. package/dist/{exec-FBXA3CM4.js → exec-2H65LMTA.js} +3 -3
  73. package/dist/{export-TNBPDH77.js → export-3E3EL6W3.js} +4 -4
  74. package/dist/{extension-J4ZQ2GHV.js → extension-MRYJWSMV.js} +2 -1
  75. package/dist/{extensions-AWNO3SZF.js → extensions-7KP3X6G7.js} +22 -19
  76. package/dist/{files-BVBRJJ2P.js → files-6BMKVG5G.js} +5 -4
  77. package/dist/{import-ZUNKMCKC.js → import-UPNTEBBT.js} +8 -8
  78. package/dist/{isolation-OPCZQRTH.js → isolation-OKDFM6WA.js} +5 -3
  79. package/dist/{join-34TR2GXQ.js → join-PYA36HEC.js} +1 -1
  80. package/dist/{list-PMUXZNAM.js → list-4BVGH7AN.js} +8 -3
  81. package/dist/{login-KAKNFCW5.js → login-MOXVLULE.js} +4 -3
  82. package/dist/{login-LKNLCJPA.js → login-RJJTCVR3.js} +2 -1
  83. package/dist/{logout-YZRMZ3O2.js → logout-BYV433X6.js} +2 -1
  84. package/dist/{logout-RLT62RQP.js → logout-DWD3OQVT.js} +4 -3
  85. package/dist/message-delivery-3456PXB7.js +43 -0
  86. package/dist/migrate-thread-config-4A5LW36Z.js +90 -0
  87. package/dist/{mind-IF6CGMFW.js → mind-NYRALSV2.js} +19 -19
  88. package/dist/{mind-activity-tracker-YMMERB6B.js → mind-activity-tracker-L7GCYXQR.js} +4 -4
  89. package/dist/{mind-contacts-BKUFPUCU.js → mind-contacts-QYU4TPEA.js} +3 -2
  90. package/dist/{mind-history-WI5OI3BW.js → mind-history-NXXOOTX6.js} +30 -7
  91. package/dist/{mind-list-OTHV4ZO4.js → mind-list-SYRA7CH5.js} +3 -2
  92. package/dist/{mind-profile-LUG353ZT.js → mind-profile-MRCVZPYT.js} +1 -1
  93. package/dist/mind-service-5TA7UJAT.js +47 -0
  94. package/dist/{mind-sleep-VBV7YRSU.js → mind-sleep-TH6BRQ5X.js} +4 -3
  95. package/dist/{mind-status-BJNPGXKC.js → mind-status-Z2LQFA6F.js} +3 -2
  96. package/dist/{mind-wake-LVTZ55EZ.js → mind-wake-LDGPRA42.js} +2 -1
  97. package/dist/{package-PD67VPHB.js → package-XYSV7NUT.js} +23 -23
  98. package/dist/{prompts-MDHDLWEX.js → prompts-QKFPX6DQ.js} +3 -3
  99. package/dist/{read-YSWUXYL7.js → read-ZXGUT4QC.js} +5 -3
  100. package/dist/{register-TWQDKQRT.js → register-OX4HRSGC.js} +2 -1
  101. package/dist/{registry-3ELJPUGJ.js → registry-4UF6OCOE.js} +6 -4
  102. package/dist/{reject-SXGCYN4A.js → reject-TWB4QJHG.js} +2 -1
  103. package/dist/{restart-5F5QDBOG.js → restart-AGEGNSYQ.js} +2 -1
  104. package/dist/{sandbox-XPYA7UIF.js → sandbox-EGEU5GGE.js} +7 -4
  105. package/dist/scheduler-UV6RUJ7P.js +25 -0
  106. package/dist/{schema-6YONVTKZ.js → schema-C2GIPD4V.js} +3 -3
  107. package/dist/{seed-NQED7PSX.js → seed-3IMBOAGK.js} +1 -1
  108. package/dist/{seed-check-TYD7RRZY.js → seed-check-NRJEQZST.js} +14 -5
  109. package/dist/{seed-cmd-QF3F2G4S.js → seed-cmd-U73XVQMI.js} +3 -3
  110. package/dist/{seed-create-XOO4N2OE.js → seed-create-FBLNVSUP.js} +4 -4
  111. package/dist/{seed-readiness-3LRYASA4.js → seed-readiness-QRA46ZJQ.js} +4 -5
  112. package/dist/{seed-sprout-HSBBGSS2.js → seed-sprout-3B4SZX7J.js} +9 -9
  113. package/dist/{send-IHRJYNXA.js → send-NBRZJXKX.js} +32 -10
  114. package/dist/{service-YCOPCTSZ.js → service-XMXAXGJD.js} +4 -4
  115. package/dist/{service-install-Y46OTF55.js → service-install-MOKTEG7B.js} +5 -5
  116. package/dist/{setup-TCN7VH5U.js → setup-CAJFOR2N.js} +10 -3
  117. package/dist/{setup-F4TE64YI.js → setup-JGYAXXW7.js} +6 -7
  118. package/dist/{skill-4CYJLYVY.js → skill-NXIHDQCG.js} +3 -2
  119. package/dist/skills/dreaming/references/INSTALL.md +2 -2
  120. package/dist/skills/imagegen/SKILL.md +21 -4
  121. package/dist/skills/imagegen/scripts/imagegen.ts +124 -21
  122. package/dist/skills/tending/SKILL.md +7 -7
  123. package/dist/skills/volute-mind/SKILL.md +3 -3
  124. package/dist/skills/volute-mind/references/integrations.md +2 -2
  125. package/dist/skills/volute-mind/references/routing.md +15 -15
  126. package/dist/{skills-NN5UZCUU.js → skills-5MSMT7PT.js} +4 -5
  127. package/dist/sleep-manager-LIEPO6WG.js +41 -0
  128. package/dist/{spirit-SSJMYC6A.js → spirit-IL5EMWYZ.js} +10 -7
  129. package/dist/spirit-availability-YFEGJNJ2.js +42 -0
  130. package/dist/{split-JF2VWTXA.js → split-BU5VWX6P.js} +1 -1
  131. package/dist/{sprout-AXA2SECQ.js → sprout-UPXGJ5HX.js} +1 -1
  132. package/dist/{src-YH6PQ7LJ.js → src-HGNE2XG4.js} +7 -1
  133. package/dist/{src-ZN4LXMPI.js → src-LCSOQY6Z.js} +57 -51
  134. package/dist/{src-JAOVXO5W.js → src-UDMJZ6MH.js} +8 -8
  135. package/dist/{start-BTVMTP3K.js → start-MUMNFR52.js} +2 -1
  136. package/dist/{status-VJGXMQ4L.js → status-IL67CYM4.js} +7 -6
  137. package/dist/{stop-YORESK4U.js → stop-EKERNYTX.js} +2 -1
  138. package/dist/system-events-A6IGCEC3.js +46 -0
  139. package/dist/system-install-YZSWCPDK.js +8 -0
  140. package/dist/{systems-5MH2ELQE.js → systems-VDRUZXNF.js} +5 -4
  141. package/dist/{tailscale-AMMVKDXB.js → tailscale-SJUW2ETR.js} +2 -2
  142. package/dist/{template-staleness-HKGCTS3H.js → template-staleness-T27VCGYA.js} +3 -3
  143. package/dist/{turn-tracker-JQ2YUUY2.js → turn-tracker-6EI2EL7G.js} +6 -6
  144. package/dist/{up-SDLTLPAO.js → up-CLL4665A.js} +5 -6
  145. package/dist/{update-WEA4N2TR.js → update-HVAUCQPN.js} +5 -5
  146. package/dist/{update-check-DZOTONII.js → update-check-2MGBBAFF.js} +3 -3
  147. package/dist/{upgrade-K5FIQPQD.js → upgrade-LIE46UBB.js} +1 -1
  148. package/dist/variant-cleanup-HJ7Z75R6.js +22 -0
  149. package/dist/{version-notify-WFA5XB5A.js → version-notify-7BUHWZNT.js} +10 -27
  150. package/dist/web-assets/assets/index-ClsUcXiW.js +95 -0
  151. package/dist/web-assets/assets/index-Dz3wTbtR.css +1 -0
  152. package/dist/web-assets/index.html +2 -2
  153. package/dist/xai-P42CRCZA.js +129 -0
  154. package/drizzle/0014_system_events.sql +26 -0
  155. package/drizzle/0015_rename_session_to_thread.sql +12 -0
  156. package/drizzle/0016_brain_to_human.sql +4 -0
  157. package/drizzle/0017_event_history_rows.sql +9 -0
  158. package/drizzle/meta/_journal.json +28 -0
  159. package/package.json +23 -23
  160. package/packages/extensions/notes/dist/ui/assets/index-BBs8pyel.js +67 -0
  161. package/packages/extensions/notes/dist/ui/index.html +1 -1
  162. package/packages/extensions/pages/dist/ui/assets/index-B589e8Xe.js +2 -0
  163. package/packages/extensions/pages/dist/ui/index.html +1 -1
  164. package/packages/extensions/plan/dist/ui/assets/index-B8s8wxyt.js +67 -0
  165. package/packages/extensions/plan/dist/ui/index.html +1 -1
  166. package/templates/_base/.init/.config/prompts.json +1 -0
  167. package/templates/_base/.init/.local/hooks/startup-context.ts +24 -9
  168. package/templates/_base/home/.config/routes.json +2 -2
  169. package/templates/_base/home/VOLUTE.md +18 -5
  170. package/templates/_base/src/lib/daemon-client.ts +1 -1
  171. package/templates/_base/src/lib/event-turn.ts +39 -0
  172. package/templates/_base/src/lib/format-prefix.ts +21 -2
  173. package/templates/_base/src/lib/router.ts +6 -2
  174. package/templates/_base/src/lib/routing.ts +8 -8
  175. package/templates/_base/src/lib/startup.ts +9 -1
  176. package/templates/_base/src/lib/types.ts +7 -1
  177. package/templates/_base/src/lib/volute-server.ts +30 -1
  178. package/templates/claude/.init/.config/routes.json +3 -3
  179. package/templates/claude/.init/CLAUDE.md +1 -1
  180. package/templates/claude/package.json.tmpl +4 -4
  181. package/templates/claude/src/agent.ts +4 -1
  182. package/templates/claude/src/lib/hooks/reply-instructions.ts +26 -1
  183. package/templates/codex/.init/.config/routes.json +3 -3
  184. package/templates/codex/.init/AGENTS.md +1 -1
  185. package/templates/codex/package.json.tmpl +4 -4
  186. package/templates/codex/src/agent.ts +11 -11
  187. package/templates/codex/src/lib/turn-context.ts +51 -0
  188. package/templates/pi/.init/.config/routes.json +3 -3
  189. package/templates/pi/.init/MINDS.md +1 -1
  190. package/templates/pi/package.json.tmpl +6 -6
  191. package/templates/pi/src/agent.ts +9 -1
  192. package/templates/pi/src/lib/event-handler.ts +1 -1
  193. package/templates/pi/src/lib/reply-instructions-extension.ts +28 -1
  194. package/dist/chunk-NJHN6IRB.js +0 -177
  195. package/dist/chunk-QQBOI3QA.js +0 -5345
  196. package/dist/chunk-XTEKINWG.js +0 -158
  197. package/dist/delivery-manager-RBXBPVWM.js +0 -36
  198. package/dist/echo-text-B6NZ5FGE.js +0 -36
  199. package/dist/message-delivery-ABPV76EA.js +0 -42
  200. package/dist/mind-service-42GDO4KH.js +0 -44
  201. package/dist/notices-N6BCGHFV.js +0 -25
  202. package/dist/scheduler-K7Y7Z7FQ.js +0 -34
  203. package/dist/sleep-manager-DSPXFHGX.js +0 -38
  204. package/dist/system-chat-M2XOBKEM.js +0 -40
  205. package/dist/variant-cleanup-P4MBNLJD.js +0 -33
  206. package/dist/web-assets/assets/index-BostMFoR.css +0 -1
  207. package/dist/web-assets/assets/index-CKlqUkyG.js +0 -92
  208. package/packages/extensions/notes/dist/ui/assets/index-D0-DgYyj.js +0 -67
  209. package/packages/extensions/pages/dist/ui/assets/index-DtzftuPA.js +0 -2
  210. package/packages/extensions/plan/dist/ui/assets/index-Cfzs-0G9.js +0 -67
@@ -5,31 +5,208 @@ import {
5
5
  conversations,
6
6
  deliveryQueue,
7
7
  mindHistory,
8
- mindNotices,
9
8
  minds,
10
9
  schema_exports,
11
10
  summaries,
11
+ systemEvents,
12
12
  turns,
13
13
  users
14
- } from "./chunk-P4LHVRNE.js";
14
+ } from "./chunk-5IIVOWSP.js";
15
15
 
16
16
  // packages/daemon/src/lib/db.ts
17
- import { chmodSync, existsSync } from "fs";
18
- import { dirname, resolve as resolve2 } from "path";
17
+ import { chmodSync as chmodSync2, existsSync as existsSync2 } from "fs";
18
+ import { dirname, resolve as resolve3 } from "path";
19
19
  import { fileURLToPath as fileURLToPath2 } from "url";
20
20
  import { sql } from "drizzle-orm";
21
21
  import { drizzle } from "drizzle-orm/libsql";
22
22
  import { migrate } from "drizzle-orm/libsql/migrator";
23
23
 
24
24
  // packages/daemon/src/lib/mind/registry.ts
25
- import { mkdirSync } from "fs";
25
+ import { mkdirSync as mkdirSync2 } from "fs";
26
26
  import { homedir } from "os";
27
- import { resolve } from "path";
27
+ import { resolve as resolve2 } from "path";
28
28
  import { fileURLToPath } from "url";
29
29
  import { and, eq, inArray, isNull, or } from "drizzle-orm";
30
- var SPIRIT_NAME = "volute";
30
+
31
+ // packages/daemon/src/lib/config/setup.ts
32
+ import { chmodSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
33
+ import { resolve } from "path";
34
+ function configPath() {
35
+ return resolve(voluteSystemDir(), "config.json");
36
+ }
37
+ function secretsPath() {
38
+ return resolve(voluteSystemDir(), "secrets.json");
39
+ }
40
+ function hasEntries(obj) {
41
+ return !!obj && Object.keys(obj).length > 0;
42
+ }
43
+ function splitConfig(config) {
44
+ const publicConfig = { ...config };
45
+ const secrets = {};
46
+ if (config.ai) {
47
+ const { providers, ...rest } = config.ai;
48
+ publicConfig.ai = { ...rest, providers: {} };
49
+ if (hasEntries(providers)) secrets.ai = { providers };
50
+ }
51
+ if (config.imagegen) {
52
+ const { providers, ...rest } = config.imagegen;
53
+ publicConfig.imagegen = { ...rest };
54
+ if (providers && Object.keys(providers).length > 0) secrets.imagegen = { providers };
55
+ }
56
+ if (config.backup) {
57
+ const { password, env, ...rest } = config.backup;
58
+ publicConfig.backup = { ...rest };
59
+ if (password || hasEntries(env)) {
60
+ secrets.backup = {};
61
+ if (password) secrets.backup.password = password;
62
+ if (hasEntries(env)) secrets.backup.env = env;
63
+ }
64
+ }
65
+ return { publicConfig, secrets };
66
+ }
67
+ function mergeSecrets(publicConfig, secrets) {
68
+ const merged = { ...publicConfig };
69
+ if (secrets.ai?.providers) {
70
+ merged.ai = { ...merged.ai ?? { providers: {} }, providers: secrets.ai.providers };
71
+ }
72
+ if (secrets.imagegen?.providers) {
73
+ merged.imagegen = { ...merged.imagegen ?? {}, providers: secrets.imagegen.providers };
74
+ }
75
+ if (secrets.backup) {
76
+ merged.backup = { ...merged.backup ?? {}, ...secrets.backup };
77
+ }
78
+ return merged;
79
+ }
80
+ function readSecrets() {
81
+ const path = secretsPath();
82
+ if (!existsSync(path)) return {};
83
+ try {
84
+ return JSON.parse(readFileSync(path, "utf-8"));
85
+ } catch {
86
+ return {};
87
+ }
88
+ }
89
+ var _cachedConfig = null;
90
+ var CONFIG_CACHE_TTL = 2e3;
91
+ function _resetConfigCache() {
92
+ _cachedConfig = null;
93
+ }
94
+ function readGlobalConfig() {
95
+ if (_cachedConfig && Date.now() - _cachedConfig.ts < CONFIG_CACHE_TTL) {
96
+ return { ..._cachedConfig.config };
97
+ }
98
+ const path = configPath();
99
+ if (!existsSync(path)) {
100
+ _cachedConfig = null;
101
+ return {};
102
+ }
103
+ let publicConfig;
104
+ try {
105
+ publicConfig = JSON.parse(readFileSync(path, "utf-8"));
106
+ } catch (err) {
107
+ console.error(`Failed to parse ${path}: ${err instanceof Error ? err.message : err}`);
108
+ return {};
109
+ }
110
+ const config = mergeSecrets(publicConfig, readSecrets());
111
+ _cachedConfig = { config, ts: Date.now() };
112
+ return config;
113
+ }
114
+ function writeGlobalConfig(config) {
115
+ mkdirSync(voluteSystemDir(), { recursive: true });
116
+ const { publicConfig, secrets } = splitConfig(config);
117
+ const cfgPath = configPath();
118
+ writeFileSync(cfgPath, `${JSON.stringify(publicConfig, null, 2)}
119
+ `, { mode: 420 });
120
+ chmodSync(cfgPath, 420);
121
+ const secPath = secretsPath();
122
+ writeFileSync(secPath, `${JSON.stringify(secrets, null, 2)}
123
+ `, { mode: 384 });
124
+ chmodSync(secPath, 384);
125
+ _cachedConfig = { config, ts: Date.now() };
126
+ }
127
+ function migrateConfigSecrets() {
128
+ const path = configPath();
129
+ if (!existsSync(path)) return;
130
+ let raw;
131
+ try {
132
+ raw = readFileSync(path, "utf-8");
133
+ } catch {
134
+ return;
135
+ }
136
+ let parsed;
137
+ try {
138
+ parsed = JSON.parse(raw);
139
+ } catch {
140
+ return;
141
+ }
142
+ const embedsSecrets = hasEntries(parsed.ai?.providers) || hasEntries(parsed.imagegen?.providers) || !!parsed.backup?.password || hasEntries(parsed.backup?.env);
143
+ const mode = statSync(path).mode & 511;
144
+ if (!embedsSecrets && mode === 420) return;
145
+ _resetConfigCache();
146
+ writeGlobalConfig(readGlobalConfig());
147
+ }
148
+ function computeSetupStatus(config) {
149
+ if (config.setupCompleted === true) return "complete";
150
+ if (config.setup != null && config.setupCompleted == null) return "complete";
151
+ if (config.setup != null) return "in-progress";
152
+ return "none";
153
+ }
154
+ function setupStatus() {
155
+ return computeSetupStatus(readGlobalConfig());
156
+ }
157
+ function readGlobalConfigStrict() {
158
+ const path = configPath();
159
+ if (!existsSync(path)) return {};
160
+ return JSON.parse(readFileSync(path, "utf-8"));
161
+ }
162
+ function isSetupComplete() {
163
+ return setupStatus() === "complete";
164
+ }
165
+ function setupUrl() {
166
+ const config = readGlobalConfig();
167
+ const port = config.port || 1618;
168
+ let host = config.hostname || "127.0.0.1";
169
+ if (host === "0.0.0.0" || host === "::") host = "localhost";
170
+ if (host.includes(":") && !host.startsWith("[")) host = `[${host}]`;
171
+ return `http://${host}:${port}`;
172
+ }
173
+ function getSpiritName() {
174
+ return readGlobalConfig().setup?.spiritName ?? "volute";
175
+ }
176
+ function getSystemName() {
177
+ return readGlobalConfig().name ?? "this system";
178
+ }
179
+ var IMAGEGEN_AI_PROVIDERS = ["openai-codex", "xai"];
180
+ function isImagegenEnabled() {
181
+ const config = readGlobalConfig();
182
+ const ig = config.imagegen;
183
+ if (ig?.enabled === true) return true;
184
+ if (ig?.providers && Object.keys(ig.providers).length > 0) return true;
185
+ const aiProviders = config.ai?.providers;
186
+ for (const id of IMAGEGEN_AI_PROVIDERS) {
187
+ const p = aiProviders?.[id];
188
+ if (p?.oauth || p?.apiKey) return true;
189
+ }
190
+ return false;
191
+ }
192
+ function mindLimitError(count, limit) {
193
+ if (limit == null) return null;
194
+ if (count >= limit) {
195
+ return `Mind limit reached (${count}/${limit}). An admin can raise maxMinds in Settings.`;
196
+ }
197
+ return null;
198
+ }
199
+ function migrateSetupCompleted() {
200
+ const config = readGlobalConfig();
201
+ if (config.setup != null && config.setupCompleted == null) {
202
+ config.setupCompleted = true;
203
+ writeGlobalConfig(config);
204
+ }
205
+ }
206
+
207
+ // packages/daemon/src/lib/mind/registry.ts
31
208
  function isSpiritName(name) {
32
- return name === SPIRIT_NAME;
209
+ return name === getSpiritName();
33
210
  }
34
211
  function voluteHome() {
35
212
  if (process.env.VOLUTE_HOME) return process.env.VOLUTE_HOME;
@@ -38,21 +215,21 @@ function voluteHome() {
38
215
  'VOLUTE_HOME must be set when running from source. For tests, run via "npm test" or add "--import ./test/setup.ts".'
39
216
  );
40
217
  }
41
- return resolve(homedir(), ".volute");
218
+ return resolve2(homedir(), ".volute");
42
219
  }
43
220
  function voluteUserHome() {
44
221
  if (process.env.VOLUTE_USER_HOME) return process.env.VOLUTE_USER_HOME;
45
- return resolve(homedir(), ".volute");
222
+ return resolve2(homedir(), ".volute");
46
223
  }
47
224
  function voluteSystemDir() {
48
- return resolve(voluteHome(), "system");
225
+ return resolve2(voluteHome(), "system");
49
226
  }
50
227
  function ensureSystemDir() {
51
- mkdirSync(voluteSystemDir(), { recursive: true });
228
+ mkdirSync2(voluteSystemDir(), { recursive: true });
52
229
  }
53
230
  function ensureVoluteHome() {
54
- const mindsBase = process.env.VOLUTE_MINDS_DIR ?? resolve(voluteHome(), "minds");
55
- mkdirSync(mindsBase, { recursive: true });
231
+ const mindsBase = process.env.VOLUTE_MINDS_DIR ?? resolve2(voluteHome(), "minds");
232
+ mkdirSync2(mindsBase, { recursive: true });
56
233
  ensureSystemDir();
57
234
  }
58
235
  function rowToEntry(row) {
@@ -98,6 +275,18 @@ function validateMindName(name) {
98
275
  if (RESERVED_NAMES.has(name.toLowerCase())) {
99
276
  return `"${name}" is a reserved name`;
100
277
  }
278
+ if (isSpiritName(name)) {
279
+ return `"${name}" is the spirit's name`;
280
+ }
281
+ return null;
282
+ }
283
+ function validateSpiritName(name) {
284
+ if (!name) return "Spirit name is required";
285
+ if (name.length > MIND_NAME_MAX) return `Spirit name must be at most ${MIND_NAME_MAX} characters`;
286
+ if (!MIND_NAME_RE.test(name)) {
287
+ return "Spirit name must start with alphanumeric and contain only alphanumeric, dots, dashes, or underscores";
288
+ }
289
+ if (name.toLowerCase() === "system") return `"${name}" is a reserved name`;
101
290
  return null;
102
291
  }
103
292
  async function addMind(name, port, stage, template, createdBy) {
@@ -165,7 +354,7 @@ async function deleteMindDbFootprint(name) {
165
354
  await tx.delete(turns).where(eq(turns.mind, name));
166
355
  await tx.delete(mindHistory).where(eq(mindHistory.mind, name));
167
356
  await tx.delete(summaries).where(eq(summaries.mind, name));
168
- await tx.delete(mindNotices).where(eq(mindNotices.mind, name));
357
+ await tx.delete(systemEvents).where(eq(systemEvents.mind, name));
169
358
  await tx.delete(channelGates).where(eq(channelGates.mind, name));
170
359
  });
171
360
  }
@@ -202,19 +391,23 @@ async function getBaseName(name) {
202
391
  }
203
392
  function mindDir(name) {
204
393
  if (process.env.VOLUTE_MINDS_DIR) {
205
- return resolve(process.env.VOLUTE_MINDS_DIR, name);
394
+ return resolve2(process.env.VOLUTE_MINDS_DIR, name);
206
395
  }
207
- return resolve(voluteHome(), "minds", name);
396
+ return resolve2(voluteHome(), "minds", name);
208
397
  }
209
398
  async function resolveMindDir(name) {
210
399
  const entry = await findMind(name);
211
400
  return entry?.dir ?? mindDir(name);
212
401
  }
213
402
  function stateDir(name) {
214
- return resolve(voluteSystemDir(), "state", name);
403
+ return resolve2(voluteSystemDir(), "state", name);
404
+ }
405
+ function mindTmpEnv(dir) {
406
+ const tmp = mindTmpDir(dir);
407
+ return { TMPDIR: tmp, CLAUDE_CODE_TMPDIR: tmp };
215
408
  }
216
409
  function mindTmpDir(dir) {
217
- return resolve(dir, ".mind", "tmp");
410
+ return resolve2(dir, ".mind", "tmp");
218
411
  }
219
412
  async function nextPort() {
220
413
  const db2 = await getDb();
@@ -235,7 +428,7 @@ function daemonLoopback() {
235
428
 
236
429
  // packages/daemon/src/lib/db.ts
237
430
  var __dirname = dirname(fileURLToPath2(import.meta.url));
238
- var migrationsFolder = existsSync(resolve2(__dirname, "../drizzle")) ? resolve2(__dirname, "../drizzle") : existsSync(resolve2(__dirname, "../../drizzle")) ? resolve2(__dirname, "../../drizzle") : resolve2(__dirname, "../../../../drizzle");
431
+ var migrationsFolder = existsSync2(resolve3(__dirname, "../drizzle")) ? resolve3(__dirname, "../drizzle") : existsSync2(resolve3(__dirname, "../../drizzle")) ? resolve3(__dirname, "../../drizzle") : resolve3(__dirname, "../../../../drizzle");
239
432
  var db = null;
240
433
  var dbPromise = null;
241
434
  async function cleanupConversationColumns(db2) {
@@ -253,7 +446,7 @@ async function getDb() {
253
446
  if (dbPromise) return dbPromise;
254
447
  dbPromise = (async () => {
255
448
  try {
256
- const dbPath = process.env.VOLUTE_DB_PATH || resolve2(voluteSystemDir(), "volute.db");
449
+ const dbPath = process.env.VOLUTE_DB_PATH || resolve3(voluteSystemDir(), "volute.db");
257
450
  const instance = drizzle({ connection: { url: `file:${dbPath}` }, schema: schema_exports });
258
451
  await instance.run(sql.raw("PRAGMA journal_mode=WAL"));
259
452
  await instance.run(sql.raw("PRAGMA busy_timeout=5000"));
@@ -261,7 +454,7 @@ async function getDb() {
261
454
  await migrate(instance, { migrationsFolder });
262
455
  await cleanupConversationColumns(instance);
263
456
  try {
264
- chmodSync(dbPath, 384);
457
+ chmodSync2(dbPath, 384);
265
458
  } catch (err) {
266
459
  console.error(
267
460
  `[volute] WARNING: Failed to restrict database file permissions on ${dbPath}:`,
@@ -280,7 +473,6 @@ async function getDb() {
280
473
 
281
474
  export {
282
475
  getDb,
283
- SPIRIT_NAME,
284
476
  isSpiritName,
285
477
  voluteHome,
286
478
  voluteUserHome,
@@ -291,6 +483,7 @@ export {
291
483
  countCappedMinds,
292
484
  readAllMinds,
293
485
  validateMindName,
486
+ validateSpiritName,
294
487
  addMind,
295
488
  addSpirit,
296
489
  readSpirits,
@@ -307,7 +500,24 @@ export {
307
500
  mindDir,
308
501
  resolveMindDir,
309
502
  stateDir,
503
+ mindTmpEnv,
310
504
  mindTmpDir,
311
505
  nextPort,
312
- daemonLoopback
506
+ daemonLoopback,
507
+ configPath,
508
+ secretsPath,
509
+ _resetConfigCache,
510
+ readGlobalConfig,
511
+ writeGlobalConfig,
512
+ migrateConfigSecrets,
513
+ computeSetupStatus,
514
+ setupStatus,
515
+ readGlobalConfigStrict,
516
+ isSetupComplete,
517
+ setupUrl,
518
+ getSpiritName,
519
+ getSystemName,
520
+ isImagegenEnabled,
521
+ mindLimitError,
522
+ migrateSetupCompleted
313
523
  };
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  publish
4
- } from "./chunk-3B427GUK.js";
4
+ } from "./chunk-3BAFMGCJ.js";
5
5
  import {
6
6
  logger_default
7
7
  } from "./chunk-QUSMYGNQ.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  daemonFetch
4
- } from "./chunk-BCG45AQB.js";
4
+ } from "./chunk-M74I3HHF.js";
5
5
  import {
6
6
  command
7
7
  } from "./chunk-TXSA4Q3V.js";