volute 0.41.0 → 0.42.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 (138) hide show
  1. package/dist/{accept-AHAOUFBK.js → accept-7YVHZKRD.js} +1 -1
  2. package/dist/{activity-events-EQGBUEZ7.js → activity-events-KFKVRZE3.js} +2 -2
  3. package/dist/{ai-service-ZHEPFC3U.js → ai-service-3GBOJGUA.js} +11 -3
  4. package/dist/{archive-LJAXDDEY.js → archive-4PPYF7LL.js} +2 -2
  5. package/dist/{auth-VYW2ECCE.js → auth-EAASQPTN.js} +3 -3
  6. package/dist/{bridge-F3ZJEKDN.js → bridge-WPYSOQKR.js} +1 -1
  7. package/dist/{chat-FO722GU2.js → chat-7DOENBY2.js} +8 -8
  8. package/dist/{chunk-AXNAK3HT.js → chunk-2YRTSK5K.js} +7 -7
  9. package/dist/{chunk-VK2YD7VJ.js → chunk-4ZSUUBG5.js} +97 -2
  10. package/dist/{chunk-W5Z2H3LU.js → chunk-52NMCDBS.js} +290 -71
  11. package/dist/{chunk-6TPRURK5.js → chunk-5QG36RV7.js} +2 -2
  12. package/dist/{chunk-GMFCSXWB.js → chunk-62ICA2FF.js} +1 -1
  13. package/dist/{chunk-6ZAT5PYV.js → chunk-BLOAJLGI.js} +1 -1
  14. package/dist/{chunk-2I7OKOYV.js → chunk-CGPESELY.js} +2 -2
  15. package/dist/{chunk-FEQPNCXB.js → chunk-E7XWFDZL.js} +1 -1
  16. package/dist/{chunk-V67XMNGP.js → chunk-G777ME4L.js} +2 -2
  17. package/dist/{chunk-Y2XLASFJ.js → chunk-GN52E2DP.js} +1 -1
  18. package/dist/{chunk-ZX7EAV5J.js → chunk-IFNSAOA4.js} +9 -2
  19. package/dist/{chunk-VDODEQSJ.js → chunk-IUZ3EV2D.js} +4 -0
  20. package/dist/{chunk-JIGVTFIR.js → chunk-JLX3GC7T.js} +43 -14
  21. package/dist/{chunk-2RQIIKFC.js → chunk-K547QOCM.js} +1 -1
  22. package/dist/{chunk-OQ7UEW67.js → chunk-KUJVCDWT.js} +2 -2
  23. package/dist/chunk-KZAL7HEQ.js +141 -0
  24. package/dist/{chunk-GSOEUMVO.js → chunk-M2YMNTHK.js} +1 -1
  25. package/dist/{chunk-MU2B7A3L.js → chunk-OEJFZHZZ.js} +1 -1
  26. package/dist/{chunk-SWY4DJ67.js → chunk-OSUF75I7.js} +2 -2
  27. package/dist/{chunk-WSRGS4XP.js → chunk-QLWG3C2Z.js} +10 -0
  28. package/dist/{chunk-UU3Q65US.js → chunk-QMJCNZ6C.js} +1 -1
  29. package/dist/{chunk-CYUNO4BM.js → chunk-QPTQKGGF.js} +1 -1
  30. package/dist/{chunk-FU5YDH6Q.js → chunk-RKBYFLOR.js} +3 -3
  31. package/dist/{chunk-4ED2DBNC.js → chunk-TFBQESH7.js} +1 -1
  32. package/dist/{chunk-YATR5BXD.js → chunk-TKOWXAHG.js} +4 -4
  33. package/dist/{chunk-PP5CGT2P.js → chunk-VBKRZCR7.js} +1 -1
  34. package/dist/{chunk-YN6ISG7A.js → chunk-VSUZE2PD.js} +14 -13
  35. package/dist/{chunk-U7UASV36.js → chunk-WR7CSHQ4.js} +43 -10
  36. package/dist/{chunk-2R4JIZCB.js → chunk-YLTIEEVL.js} +2 -2
  37. package/dist/cli.js +22 -22
  38. package/dist/{clock-BMLJ2TR6.js → clock-HP2TGMG5.js} +3 -3
  39. package/dist/{cloud-sync-GV6O2HN2.js → cloud-sync-3OPHFOYQ.js} +17 -17
  40. package/dist/{config-QB7W3Z7P.js → config-W7MS3PWY.js} +3 -3
  41. package/dist/{conversations-KW7IYESK.js → conversations-FSZCUUYO.js} +3 -3
  42. package/dist/{create-C3BBFYV7.js → create-CJ2SR4EU.js} +1 -1
  43. package/dist/{create-CTPXWFTL.js → create-YNBZWD34.js} +2 -2
  44. package/dist/{daemon-client-2MIPKY3E.js → daemon-client-EWDPOOHC.js} +3 -1
  45. package/dist/{daemon-restart-W47YDE5E.js → daemon-restart-RAKGR56L.js} +7 -7
  46. package/dist/daemon.js +258 -302
  47. package/dist/{db-D4FVCA5I.js → db-ZJJJYJBU.js} +1 -1
  48. package/dist/{delete-NLXES2C7.js → delete-4ND5PLE7.js} +1 -1
  49. package/dist/delivery-manager-5Y35DOX3.js +33 -0
  50. package/dist/{delivery-router-Y66OXJPM.js → delivery-router-FDBZJQOY.js} +2 -2
  51. package/dist/{down-JVHNXOFU.js → down-DS6WCT34.js} +5 -5
  52. package/dist/echo-text-YP3JVLNA.js +32 -0
  53. package/dist/{env-IQ6Q2333.js → env-XX2MBZCZ.js} +1 -1
  54. package/dist/{exec-R2WWZ6FH.js → exec-ZDD7NEB4.js} +3 -3
  55. package/dist/{export-ZZ5WWBUH.js → export-5DOQV2WM.js} +3 -3
  56. package/dist/{extension-LZYHBNLV.js → extension-BCFYXI7A.js} +4 -1
  57. package/dist/{extensions-AGANCIQA.js → extensions-BTNIUS5J.js} +17 -17
  58. package/dist/{files-Q2Z4LQZP.js → files-K2MEMV3W.js} +3 -3
  59. package/dist/{import-MFYCBS4K.js → import-V6QEHMPQ.js} +7 -7
  60. package/dist/{isolation-7F3MA4G7.js → isolation-F7ABZMDA.js} +2 -2
  61. package/dist/{join-6SZCA5FX.js → join-4S3KT7NE.js} +1 -1
  62. package/dist/{list-KHJZJPEJ.js → list-XJB5WII6.js} +1 -1
  63. package/dist/{login-WY3DADVB.js → login-PHMTLNUF.js} +2 -2
  64. package/dist/{login-GYTH67ES.js → login-YWD6PUOT.js} +1 -1
  65. package/dist/{logout-TFZHWNVL.js → logout-BP3R3CAA.js} +2 -2
  66. package/dist/{logout-YHQLOFLR.js → logout-Q2WICH4V.js} +1 -1
  67. package/dist/message-delivery-FPIL26WV.js +41 -0
  68. package/dist/{mind-XIKEPJNS.js → mind-VXV6ZYZY.js} +18 -18
  69. package/dist/{mind-activity-tracker-RSIWUUJK.js → mind-activity-tracker-HWVFE533.js} +3 -3
  70. package/dist/{mind-history-WHCNZ6I5.js → mind-history-TDUQFYAG.js} +1 -1
  71. package/dist/{mind-list-H3HC2ZRG.js → mind-list-2T353Q5G.js} +1 -1
  72. package/dist/mind-manager-OYOIBGK6.js +33 -0
  73. package/dist/{mind-profile-7VYRJGFZ.js → mind-profile-2HHR7LZ7.js} +1 -1
  74. package/dist/mind-service-PR4PR4XI.js +37 -0
  75. package/dist/{mind-sleep-ZL5ZXFTM.js → mind-sleep-4NXV4J4U.js} +1 -1
  76. package/dist/{mind-status-ZWULKOUO.js → mind-status-CG66OXDK.js} +1 -1
  77. package/dist/{mind-wake-HK5ORGUK.js → mind-wake-TNB54DBR.js} +1 -1
  78. package/dist/{package-2X7UNSTQ.js → package-UWH5IM76.js} +2 -1
  79. package/dist/{read-CP7MYMJQ.js → read-JLR4NQXU.js} +1 -1
  80. package/dist/{register-XOBFEMI4.js → register-IQ2M4UO6.js} +1 -1
  81. package/dist/{registry-RAXNFN7K.js → registry-MDLNPTTI.js} +3 -1
  82. package/dist/{reject-43AGXB6B.js → reject-N2D4CZND.js} +1 -1
  83. package/dist/{restart-O5QIYQJT.js → restart-43A5MBGV.js} +1 -1
  84. package/dist/{sandbox-O3GZTS7J.js → sandbox-E7RWZDVG.js} +7 -3
  85. package/dist/scheduler-KXUY2I7W.js +31 -0
  86. package/dist/{seed-I4CNKTKZ.js → seed-YQAOIXIY.js} +1 -1
  87. package/dist/{seed-check-HZPVFJKZ.js → seed-check-N5ALJBT6.js} +1 -1
  88. package/dist/{seed-cmd-YTQYWCZF.js → seed-cmd-7KJS4LCA.js} +3 -3
  89. package/dist/{seed-create-MDBTVADS.js → seed-create-Z7NDRRGP.js} +4 -4
  90. package/dist/{seed-sprout-N6O5FBPY.js → seed-sprout-PYDMVVUL.js} +8 -8
  91. package/dist/{send-5XA7LRNB.js → send-KQECN2EL.js} +3 -3
  92. package/dist/{service-AY5TGWJX.js → service-Q5OVY5AK.js} +4 -4
  93. package/dist/{service-install-NLGAVTQS.js → service-install-GTDUHP6R.js} +5 -5
  94. package/dist/{setup-3434PQ5Q.js → setup-IYOUPCIK.js} +6 -2
  95. package/dist/{setup-47NBOCZL.js → setup-VARJ7N6Z.js} +7 -7
  96. package/dist/{skill-ICN6Y2ZF.js → skill-E43BI34Y.js} +1 -1
  97. package/dist/skills/imagegen/scripts/imagegen.ts +1 -1
  98. package/dist/{skills-YTLBAF32.js → skills-YBCYVOPQ.js} +5 -5
  99. package/dist/sleep-manager-FJLASHHW.js +35 -0
  100. package/dist/{spirit-KTBHLULO.js → spirit-NJFAY5CZ.js} +8 -8
  101. package/dist/{split-5YBEQTBF.js → split-5IBUODEE.js} +1 -1
  102. package/dist/{sprout-4ZUJUNDQ.js → sprout-B27C2WGE.js} +1 -1
  103. package/dist/{src-OYWRPLC6.js → src-L2Z7X5UT.js} +5 -8
  104. package/dist/{src-4LFGGNW7.js → src-TJ7RBU5H.js} +2 -12
  105. package/dist/{start-LMXXRR3X.js → start-5AYFGNS7.js} +1 -1
  106. package/dist/{status-VMOZUIZ2.js → status-ECZHHSY5.js} +5 -5
  107. package/dist/{stop-TWDKVEUX.js → stop-WJ6IG6OK.js} +1 -1
  108. package/dist/system-chat-P6KVGW4T.js +35 -0
  109. package/dist/{systems-Y2WZV2K4.js → systems-5MA57Q7G.js} +4 -4
  110. package/dist/{tailscale-PK3AI5EV.js → tailscale-TIRTGM6E.js} +1 -1
  111. package/dist/{template-hash-JARTCRGS.js → template-hash-446HHH5V.js} +2 -2
  112. package/dist/{turn-tracker-SZBSL7LK.js → turn-tracker-W4TASMR7.js} +4 -4
  113. package/dist/{up-VGVPOB6J.js → up-POJX6S5Y.js} +6 -6
  114. package/dist/{update-3ANTQO54.js → update-OPR4KU4M.js} +5 -5
  115. package/dist/{update-check-4O6DKUOF.js → update-check-OG27AL4Z.js} +2 -2
  116. package/dist/{upgrade-RXFZR5FI.js → upgrade-QB7AHIKX.js} +1 -1
  117. package/dist/{version-notify-SSNAWZMX.js → version-notify-TCKAX7ZA.js} +19 -19
  118. package/dist/web-assets/assets/{index-DaUp9iE2.js → index-CrFAsfiE.js} +10 -10
  119. package/dist/web-assets/assets/{index-DqHSW9Fr.css → index-D7udpBCx.css} +1 -1
  120. package/dist/web-assets/index.html +2 -2
  121. package/package.json +2 -1
  122. package/packages/extensions/plan/skills/plan/scripts/plan-hook.sh +2 -2
  123. package/templates/_base/.init/.config/hooks/pre-prompt/session-activity.ts +3 -3
  124. package/templates/_base/.init/.local/hooks/pre-prompt/notices.ts +3 -3
  125. package/templates/_base/.init/.local/hooks/pre-prompt/session-activity.ts +3 -3
  126. package/templates/_base/src/lib/daemon-client.ts +1 -1
  127. package/templates/_base/src/lib/volute-server.ts +1 -1
  128. package/templates/codex/src/server.ts +8 -2
  129. package/templates/pi/src/lib/resolve-model.ts +50 -12
  130. package/dist/chunk-N64Q7FMP.js +0 -70
  131. package/dist/delivery-manager-EB52CQ5X.js +0 -33
  132. package/dist/echo-text-QVPS6QDM.js +0 -32
  133. package/dist/message-delivery-X4CZE2L6.js +0 -41
  134. package/dist/mind-manager-VU3RGCXD.js +0 -31
  135. package/dist/mind-service-L7LMMDYJ.js +0 -37
  136. package/dist/scheduler-SXELVRWO.js +0 -31
  137. package/dist/sleep-manager-T3AXQB3R.js +0 -35
  138. package/dist/system-chat-HCPHUQGI.js +0 -35
package/dist/daemon.js CHANGED
@@ -6,31 +6,31 @@ import {
6
6
  rejectPending,
7
7
  stageFile,
8
8
  validateFilePath
9
- } from "./chunk-GSOEUMVO.js";
9
+ } from "./chunk-M2YMNTHK.js";
10
10
  import {
11
11
  findOpenClawSession,
12
12
  importOpenClawConnectors,
13
13
  importPiSession,
14
14
  parseNameFromIdentity
15
- } from "./chunk-OQ7UEW67.js";
15
+ } from "./chunk-KUJVCDWT.js";
16
16
  import {
17
17
  checkForUpdate,
18
18
  checkForUpdateCached,
19
19
  getCurrentVersion
20
- } from "./chunk-FEQPNCXB.js";
20
+ } from "./chunk-E7XWFDZL.js";
21
21
  import {
22
22
  isHomeOnlyArchive
23
- } from "./chunk-MU2B7A3L.js";
23
+ } from "./chunk-OEJFZHZZ.js";
24
24
  import {
25
25
  computeTemplateHash
26
- } from "./chunk-UU3Q65US.js";
26
+ } from "./chunk-QMJCNZ6C.js";
27
27
  import {
28
28
  PLATFORMS,
29
29
  echoTextToChannel,
30
30
  fixModelEscapes,
31
31
  getPlatformDriver,
32
32
  routeOutboundBridge
33
- } from "./chunk-AXNAK3HT.js";
33
+ } from "./chunk-2YRTSK5K.js";
34
34
  import {
35
35
  getBridgeConfig,
36
36
  readBridgesConfig,
@@ -39,12 +39,17 @@ import {
39
39
  resolveChannelMapping,
40
40
  setBridgeConfig,
41
41
  setChannelMapping
42
- } from "./chunk-CYUNO4BM.js";
42
+ } from "./chunk-QPTQKGGF.js";
43
43
  import {
44
44
  RestartTracker,
45
45
  RotatingLog,
46
+ SESSION_MAX_AGE,
46
47
  announceToSystem,
48
+ authMiddleware,
49
+ cleanExpiredSessions,
47
50
  clearDeliveredNotices,
51
+ createSession,
52
+ deleteSession,
48
53
  deleteSystemsConfig,
49
54
  deliverMessage,
50
55
  drainNotices,
@@ -58,6 +63,7 @@ import {
58
63
  getLoadedExtensions,
59
64
  getMindManager,
60
65
  getScheduler,
66
+ getSessionUserId,
61
67
  getSleepManagerIfReady,
62
68
  getTokenBudget,
63
69
  getTypingMap,
@@ -68,6 +74,8 @@ import {
68
74
  initSleepManager,
69
75
  initTokenBudget,
70
76
  installNpmExtension,
77
+ invalidateMindUserCache,
78
+ invalidateSessionCache,
71
79
  isConversationId,
72
80
  joinSystemChannel,
73
81
  linkToolResultToTurn,
@@ -79,7 +87,9 @@ import {
79
87
  recordInbound,
80
88
  recordNotice,
81
89
  recordOutbound,
82
- resolveMindToken,
90
+ requireAdmin,
91
+ requireAdminOrSystem,
92
+ requireSelf,
83
93
  setExtensionEnabled,
84
94
  startMindFull,
85
95
  stopMindFull,
@@ -88,15 +98,15 @@ import {
88
98
  tagUntaggedOutbound,
89
99
  uninstallNpmExtension,
90
100
  writeSystemsConfig
91
- } from "./chunk-W5Z2H3LU.js";
101
+ } from "./chunk-52NMCDBS.js";
92
102
  import {
93
103
  loadMergedEnv,
94
104
  mindEnvPath,
95
105
  readEnv,
96
106
  sharedEnvPath,
97
107
  writeEnv
98
- } from "./chunk-6ZAT5PYV.js";
99
- import "./chunk-YN6ISG7A.js";
108
+ } from "./chunk-BLOAJLGI.js";
109
+ import "./chunk-VSUZE2PD.js";
100
110
  import {
101
111
  applyInitFiles,
102
112
  applyTemplateHomeFiles,
@@ -105,7 +115,7 @@ import {
105
115
  findTemplatesRoot,
106
116
  isKnownTemplate,
107
117
  listFiles
108
- } from "./chunk-WSRGS4XP.js";
118
+ } from "./chunk-QLWG3C2Z.js";
109
119
  import {
110
120
  SEED_SKILLS,
111
121
  STANDARD_SKILLS,
@@ -125,7 +135,7 @@ import {
125
135
  syncBuiltinSkills,
126
136
  uninstallSkill,
127
137
  updateSkill
128
- } from "./chunk-JIGVTFIR.js";
138
+ } from "./chunk-JLX3GC7T.js";
129
139
  import {
130
140
  addMessage,
131
141
  createChannel,
@@ -157,20 +167,23 @@ import {
157
167
  setConversationPrivate,
158
168
  subscribe as subscribe2,
159
169
  updateChannelSettings
160
- } from "./chunk-2R4JIZCB.js";
170
+ } from "./chunk-YLTIEEVL.js";
161
171
  import {
162
172
  readVoluteConfig,
163
173
  writeVoluteConfig
164
174
  } from "./chunk-CU6OFXMM.js";
165
- import "./chunk-U7UASV36.js";
175
+ import {
176
+ isSandboxEnabled,
177
+ wrapForSandbox
178
+ } from "./chunk-WR7CSHQ4.js";
166
179
  import {
167
180
  getActiveMinds,
168
181
  onMindEvent,
169
182
  stopAll
170
- } from "./chunk-PP5CGT2P.js";
183
+ } from "./chunk-VBKRZCR7.js";
171
184
  import {
172
185
  extractTextContent
173
- } from "./chunk-GMFCSXWB.js";
186
+ } from "./chunk-62ICA2FF.js";
174
187
  import {
175
188
  PROMPT_DEFAULTS,
176
189
  PROMPT_KEYS,
@@ -193,12 +206,12 @@ import {
193
206
  summarizeTurn,
194
207
  takeErrored,
195
208
  trackToolUse
196
- } from "./chunk-YATR5BXD.js";
209
+ } from "./chunk-TKOWXAHG.js";
197
210
  import {
198
211
  exec,
199
212
  gitExec,
200
213
  resolveVoluteBin
201
- } from "./chunk-Y2XLASFJ.js";
214
+ } from "./chunk-GN52E2DP.js";
202
215
  import {
203
216
  chownMindDir,
204
217
  createMindUser,
@@ -206,15 +219,19 @@ import {
206
219
  ensureVoluteGroup,
207
220
  isIsolationEnabled,
208
221
  wrapForIsolation
209
- } from "./chunk-4ED2DBNC.js";
222
+ } from "./chunk-TFBQESH7.js";
210
223
  import {
224
+ addCustomModel,
225
+ buildCustomModel,
211
226
  getAiConfig,
212
227
  getAvailableModels,
213
228
  getConfiguredProviders,
229
+ getCustomModels,
214
230
  getEnabledModels,
215
231
  getUtilityModel,
216
232
  qualifyModelId,
217
233
  removeAiConfig,
234
+ removeCustomModel,
218
235
  removeProviderConfig,
219
236
  resolveApiKey,
220
237
  resolveTemplate,
@@ -223,12 +240,12 @@ import {
223
240
  setProviderRefreshHook,
224
241
  setUtilityModel,
225
242
  unqualifyModelId
226
- } from "./chunk-VK2YD7VJ.js";
243
+ } from "./chunk-4ZSUUBG5.js";
227
244
  import {
228
245
  isSetupComplete,
229
246
  readGlobalConfig,
230
247
  writeGlobalConfig
231
- } from "./chunk-N64Q7FMP.js";
248
+ } from "./chunk-KZAL7HEQ.js";
232
249
  import {
233
250
  approveUser,
234
251
  changePassword,
@@ -247,11 +264,11 @@ import {
247
264
  syncMindProfile,
248
265
  updateUserProfile,
249
266
  verifyUser
250
- } from "./chunk-6TPRURK5.js";
267
+ } from "./chunk-5QG36RV7.js";
251
268
  import {
252
269
  broadcast,
253
270
  subscribe
254
- } from "./chunk-2RQIIKFC.js";
271
+ } from "./chunk-K547QOCM.js";
255
272
  import {
256
273
  logBuffer,
257
274
  logger_default
@@ -270,6 +287,7 @@ import {
270
287
  getBaseName,
271
288
  getDb,
272
289
  mindDir,
290
+ mindTmpDir,
273
291
  nextPort,
274
292
  readAllMinds,
275
293
  readRegistry,
@@ -282,14 +300,13 @@ import {
282
300
  validateMindName,
283
301
  voluteHome,
284
302
  voluteSystemDir
285
- } from "./chunk-VDODEQSJ.js";
303
+ } from "./chunk-IUZ3EV2D.js";
286
304
  import {
287
305
  activity,
288
306
  channels,
289
307
  conversationParticipants,
290
308
  conversations,
291
309
  mindHistory,
292
- sessions,
293
310
  summaries,
294
311
  systemPrompts,
295
312
  turns,
@@ -299,7 +316,7 @@ import "./chunk-K3NQKI34.js";
299
316
 
300
317
  // packages/daemon/src/daemon.ts
301
318
  import { randomBytes } from "crypto";
302
- import { mkdirSync as mkdirSync10, readFileSync as readFileSync10, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "fs";
319
+ import { chmodSync, mkdirSync as mkdirSync10, readFileSync as readFileSync10, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "fs";
303
320
  import { homedir as homedir3 } from "os";
304
321
  import { resolve as resolve17 } from "path";
305
322
  import { format } from "util";
@@ -834,150 +851,6 @@ async function generateImage(model, prompt) {
834
851
  return PROVIDERS[providerId].generate(modelId, prompt, apiKey);
835
852
  }
836
853
 
837
- // packages/daemon/src/web/middleware/auth.ts
838
- import { timingSafeEqual } from "crypto";
839
- import { eq as eq2, lt as lt2 } from "drizzle-orm";
840
- import { getCookie } from "hono/cookie";
841
- import { createMiddleware } from "hono/factory";
842
- var MIND_USER_CACHE_TTL = 5 * 60 * 1e3;
843
- var mindUserCache = /* @__PURE__ */ new Map();
844
- function invalidateMindUserCache(mindName) {
845
- mindUserCache.delete(mindName);
846
- }
847
- function isValidDaemonToken(token) {
848
- const expected = process.env.VOLUTE_DAEMON_TOKEN;
849
- if (!expected || token.length !== expected.length) return false;
850
- return timingSafeEqual(Buffer.from(token), Buffer.from(expected));
851
- }
852
- var SESSION_MAX_AGE = 365 * 24 * 60 * 60 * 1e3;
853
- var SESSION_CACHE_TTL = 5 * 60 * 1e3;
854
- var sessionCache = /* @__PURE__ */ new Map();
855
- function invalidateSessionCache(sessionId) {
856
- sessionCache.delete(sessionId);
857
- }
858
- async function createSession(userId) {
859
- const db = await getDb();
860
- const sessionId = crypto.randomUUID();
861
- await db.insert(sessions).values({ id: sessionId, userId, createdAt: Date.now() });
862
- return sessionId;
863
- }
864
- async function deleteSession(sessionId) {
865
- sessionCache.delete(sessionId);
866
- const db = await getDb();
867
- await db.delete(sessions).where(eq2(sessions.id, sessionId));
868
- }
869
- async function getSessionUserId(sessionId) {
870
- const db = await getDb();
871
- const row = await db.select().from(sessions).where(eq2(sessions.id, sessionId)).get();
872
- if (!row) return void 0;
873
- if (Date.now() - row.createdAt > SESSION_MAX_AGE) {
874
- await db.delete(sessions).where(eq2(sessions.id, sessionId));
875
- return void 0;
876
- }
877
- return row.userId;
878
- }
879
- async function cleanExpiredSessions() {
880
- const db = await getDb();
881
- const cutoff = Date.now() - SESSION_MAX_AGE;
882
- await db.delete(sessions).where(lt2(sessions.createdAt, cutoff));
883
- }
884
- var requireAdmin = createMiddleware(async (c, next) => {
885
- const user = c.get("user");
886
- if (user.role !== "admin") {
887
- return c.json({ error: "Forbidden" }, 403);
888
- }
889
- await next();
890
- });
891
- var requireAdminOrSystem = createMiddleware(async (c, next) => {
892
- const user = c.get("user");
893
- if (user.role !== "admin" && user.role !== "system") {
894
- return c.json({ error: "Forbidden" }, 403);
895
- }
896
- await next();
897
- });
898
- async function resolveSession(sessionId) {
899
- const cached = sessionCache.get(sessionId);
900
- if (cached && cached.expires > Date.now()) {
901
- return cached.user;
902
- }
903
- const userId = await getSessionUserId(sessionId);
904
- if (userId == null) {
905
- sessionCache.delete(sessionId);
906
- return null;
907
- }
908
- const user = await getUser(userId);
909
- if (!user) {
910
- sessionCache.delete(sessionId);
911
- return null;
912
- }
913
- sessionCache.set(sessionId, { userId, user, expires: Date.now() + SESSION_CACHE_TTL });
914
- return user;
915
- }
916
- var authMiddleware = createMiddleware(async (c, next) => {
917
- const authHeader = c.req.header("Authorization");
918
- if (authHeader?.startsWith("Bearer ")) {
919
- const token = authHeader.slice(7);
920
- if (token && isValidDaemonToken(token)) {
921
- c.set("user", {
922
- id: 0,
923
- username: "daemon",
924
- role: "admin",
925
- user_type: "brain",
926
- display_name: null,
927
- description: null,
928
- avatar: null
929
- });
930
- const mindSessionHeader = c.req.header("X-Volute-Session");
931
- if (mindSessionHeader) c.set("mindSession", mindSessionHeader);
932
- await next();
933
- return;
934
- }
935
- const mindName = resolveMindToken(token);
936
- if (mindName) {
937
- const cached = mindUserCache.get(mindName);
938
- let mindUser;
939
- if (cached && Date.now() - cached.ts < MIND_USER_CACHE_TTL) {
940
- mindUser = cached.user;
941
- } else {
942
- mindUser = await getOrCreateMindUser(mindName);
943
- mindUserCache.set(mindName, { user: mindUser, ts: Date.now() });
944
- }
945
- c.set("user", mindUser);
946
- const mindSessionHeader = c.req.header("X-Volute-Session");
947
- if (mindSessionHeader) c.set("mindSession", mindSessionHeader);
948
- await next();
949
- return;
950
- }
951
- if (token) {
952
- const user2 = await resolveSession(token);
953
- if (user2) {
954
- if (user2.role === "pending") return c.json({ error: "Account pending approval" }, 403);
955
- c.set("user", user2);
956
- await next();
957
- return;
958
- }
959
- }
960
- }
961
- const sessionId = getCookie(c, "volute_session");
962
- if (!sessionId) return c.json({ error: "Unauthorized" }, 401);
963
- const user = await resolveSession(sessionId);
964
- if (!user) return c.json({ error: "Unauthorized" }, 401);
965
- if (user.role === "pending") return c.json({ error: "Account pending approval" }, 403);
966
- c.set("user", user);
967
- await next();
968
- });
969
- var requireSelf = (paramName = "name") => createMiddleware(async (c, next) => {
970
- const user = c.get("user");
971
- if (user.role !== "admin" && user.role !== "system") {
972
- const target = c.req.param(paramName) ?? "";
973
- const baseName = await getBaseName(target);
974
- if (user.username !== baseName) {
975
- return c.json({ error: "Forbidden" }, 403);
976
- }
977
- }
978
- await next();
979
- });
980
-
981
854
  // packages/daemon/src/web/api/system.ts
982
855
  var DEFAULT_API_URL = "https://volute.systems";
983
856
  var igLog = logger_default.child("imagegen");
@@ -1231,6 +1104,7 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1231
1104
  }).get("/ai/models", requireAdmin, async (c) => {
1232
1105
  const models = await getAvailableModels();
1233
1106
  const enabled = new Set(getEnabledModels());
1107
+ const customIds = new Set(getCustomModels().map((m) => m.id));
1234
1108
  return c.json(
1235
1109
  models.map((m) => ({
1236
1110
  id: m.id,
@@ -1238,7 +1112,8 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1238
1112
  provider: m.provider,
1239
1113
  contextWindow: m.contextWindow,
1240
1114
  maxTokens: m.maxTokens,
1241
- enabled: enabled.has(m.id)
1115
+ enabled: enabled.has(m.id),
1116
+ custom: customIds.has(m.id)
1242
1117
  }))
1243
1118
  );
1244
1119
  }).put(
@@ -1250,7 +1125,38 @@ var app = new Hono().post("/restart", requireAdmin, (c) => {
1250
1125
  setEnabledModels(models);
1251
1126
  return c.json({ ok: true });
1252
1127
  }
1253
- ).get("/ai/defaults", requireAdmin, (c) => {
1128
+ ).post(
1129
+ "/ai/models/custom",
1130
+ requireAdmin,
1131
+ zValidator(
1132
+ "json",
1133
+ z.object({ provider: z.string().min(1), id: z.string().min(1), name: z.string().optional() })
1134
+ ),
1135
+ (c) => {
1136
+ const { provider, id, name } = c.req.valid("json");
1137
+ if (!buildCustomModel(provider, id)) {
1138
+ return c.json(
1139
+ { error: `No built-in model for provider "${provider}" to clone metadata from` },
1140
+ 400
1141
+ );
1142
+ }
1143
+ if (getCustomModels().some((m) => m.id === id && m.provider !== provider)) {
1144
+ return c.json(
1145
+ { error: `A custom model "${id}" is already registered under another provider` },
1146
+ 400
1147
+ );
1148
+ }
1149
+ addCustomModel(provider, id, name);
1150
+ setEnabledModels([.../* @__PURE__ */ new Set([...getEnabledModels(), id])]);
1151
+ return c.json({ ok: true });
1152
+ }
1153
+ ).delete("/ai/models/custom", requireAdmin, (c) => {
1154
+ const provider = c.req.query("provider");
1155
+ const id = c.req.query("id");
1156
+ if (!provider || !id) return c.json({ error: "provider and id are required" }, 400);
1157
+ removeCustomModel(provider, id);
1158
+ return c.json({ ok: true });
1159
+ }).get("/ai/defaults", requireAdmin, (c) => {
1254
1160
  const config2 = readGlobalConfig();
1255
1161
  return c.json({
1256
1162
  spiritModel: config2.spiritModel ?? null,
@@ -1632,7 +1538,7 @@ import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as rea
1632
1538
  import { extname, resolve as resolve3 } from "path";
1633
1539
  import { zValidator as zValidator2 } from "@hono/zod-validator";
1634
1540
  import { Hono as Hono3 } from "hono";
1635
- import { deleteCookie, getCookie as getCookie2, setCookie } from "hono/cookie";
1541
+ import { deleteCookie, getCookie, setCookie } from "hono/cookie";
1636
1542
  import { z as z2 } from "zod";
1637
1543
  function tryJoinSystem(userId) {
1638
1544
  if (!process.env.VOLUTE_DAEMON_TOKEN) return;
@@ -1678,7 +1584,7 @@ var authenticated = new Hono3().use(authMiddleware).post("/change-password", zVa
1678
1584
  const user = c.get("user");
1679
1585
  const body = c.req.valid("json");
1680
1586
  await updateUserProfile(user.id, body);
1681
- const sessionId = getCookie2(c, "volute_session");
1587
+ const sessionId = getCookie(c, "volute_session");
1682
1588
  if (sessionId) invalidateSessionCache(sessionId);
1683
1589
  broadcast({
1684
1590
  type: "profile_updated",
@@ -1710,7 +1616,7 @@ var authenticated = new Hono3().use(authMiddleware).post("/change-password", zVa
1710
1616
  rmSync(oldPath, { force: true });
1711
1617
  }
1712
1618
  await updateUserProfile(user.id, { avatar: filename });
1713
- const sessionId = getCookie2(c, "volute_session");
1619
+ const sessionId = getCookie(c, "volute_session");
1714
1620
  if (sessionId) invalidateSessionCache(sessionId);
1715
1621
  broadcast({
1716
1622
  type: "profile_updated",
@@ -1725,7 +1631,7 @@ var authenticated = new Hono3().use(authMiddleware).post("/change-password", zVa
1725
1631
  rmSync(path, { force: true });
1726
1632
  }
1727
1633
  await updateUserProfile(user.id, { avatar: null });
1728
- const sessionId = getCookie2(c, "volute_session");
1634
+ const sessionId = getCookie(c, "volute_session");
1729
1635
  if (sessionId) invalidateSessionCache(sessionId);
1730
1636
  broadcast({
1731
1637
  type: "profile_updated",
@@ -1836,7 +1742,7 @@ var app3 = new Hono3().post("/register", zValidator2("json", credentialsSchema),
1836
1742
  tryJoinSystem(user.id);
1837
1743
  return c.json({ id: user.id, username: user.username, role: user.role, sessionId });
1838
1744
  }).post("/logout", async (c) => {
1839
- const cookieSession = getCookie2(c, "volute_session");
1745
+ const cookieSession = getCookie(c, "volute_session");
1840
1746
  if (cookieSession) {
1841
1747
  await deleteSession(cookieSession);
1842
1748
  deleteCookie(c, "volute_session", { path: "/" });
@@ -1851,7 +1757,7 @@ var app3 = new Hono3().post("/register", zValidator2("json", credentialsSchema),
1851
1757
  }
1852
1758
  return c.json({ ok: true });
1853
1759
  }).get("/me", async (c) => {
1854
- let sessionId = getCookie2(c, "volute_session");
1760
+ let sessionId = getCookie(c, "volute_session");
1855
1761
  if (!sessionId) {
1856
1762
  const authHeader = c.req.header("Authorization");
1857
1763
  if (authHeader?.startsWith("Bearer ")) {
@@ -1898,7 +1804,7 @@ import { Hono as Hono4 } from "hono";
1898
1804
  import { z as z3 } from "zod";
1899
1805
 
1900
1806
  // packages/daemon/src/lib/chat/puppets.ts
1901
- import { and as and2, eq as eq3 } from "drizzle-orm";
1807
+ import { and as and2, eq as eq2 } from "drizzle-orm";
1902
1808
  async function findOrCreatePuppet(platform, platformId, displayName) {
1903
1809
  const username = `${platform}:${platformId}`;
1904
1810
  const db = await getDb();
@@ -1907,10 +1813,10 @@ async function findOrCreatePuppet(platform, platformId, displayName) {
1907
1813
  username: users.username,
1908
1814
  display_name: users.display_name,
1909
1815
  avatar: users.avatar
1910
- }).from(users).where(and2(eq3(users.username, username), eq3(users.user_type, "puppet"))).get();
1816
+ }).from(users).where(and2(eq2(users.username, username), eq2(users.user_type, "puppet"))).get();
1911
1817
  if (existing) {
1912
1818
  if (existing.display_name !== displayName) {
1913
- await db.update(users).set({ display_name: displayName }).where(eq3(users.id, existing.id));
1819
+ await db.update(users).set({ display_name: displayName }).where(eq2(users.id, existing.id));
1914
1820
  existing.display_name = displayName;
1915
1821
  }
1916
1822
  return existing;
@@ -1936,7 +1842,7 @@ async function findOrCreatePuppet(platform, platformId, displayName) {
1936
1842
  username: users.username,
1937
1843
  display_name: users.display_name,
1938
1844
  avatar: users.avatar
1939
- }).from(users).where(and2(eq3(users.username, username), eq3(users.user_type, "puppet"))).get();
1845
+ }).from(users).where(and2(eq2(users.username, username), eq2(users.user_type, "puppet"))).get();
1940
1846
  if (retried) return retried;
1941
1847
  }
1942
1848
  throw err;
@@ -2016,7 +1922,7 @@ var app4 = new Hono4().post("/:platform/inbound", zValidator3("json", inboundSch
2016
1922
  }
2017
1923
  const participants = await getParticipants(channel.id);
2018
1924
  if (!participants.some((p) => p.userId === puppet.id)) {
2019
- const { addParticipant } = await import("./conversations-KW7IYESK.js");
1925
+ const { addParticipant } = await import("./conversations-FSZCUUYO.js");
2020
1926
  await addParticipant(channel.id, puppet.id);
2021
1927
  }
2022
1928
  const contentBlocks = body.content;
@@ -2109,8 +2015,8 @@ async function fanOutToBridgedMinds(opts) {
2109
2015
  const participants = await getParticipants(opts.conversationId);
2110
2016
  const mindParticipants = participants.filter((p) => p.userType === "mind");
2111
2017
  const participantNames = participants.map((p) => p.username);
2112
- const { getMindManager: getMindManager2 } = await import("./mind-manager-VU3RGCXD.js");
2113
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-T3AXQB3R.js");
2018
+ const { getMindManager: getMindManager2 } = await import("./mind-manager-OYOIBGK6.js");
2019
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-FJLASHHW.js");
2114
2020
  const manager = getMindManager2();
2115
2021
  const sm = getSleepManagerIfReady2();
2116
2022
  const targetMinds = mindParticipants.filter((ap) => {
@@ -2322,7 +2228,7 @@ async function notifyMind(mindName, message) {
2322
2228
  const entry = await findMind(mindName);
2323
2229
  if (!entry) return;
2324
2230
  try {
2325
- const { sendSystemMessage } = await import("./system-chat-HCPHUQGI.js");
2231
+ const { sendSystemMessage } = await import("./system-chat-P6KVGW4T.js");
2326
2232
  await sendSystemMessage(mindName, message);
2327
2233
  } catch (err) {
2328
2234
  logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
@@ -2632,18 +2538,25 @@ var app9 = new Hono10().post("/:name/avatar", requireSelf(), async (c) => {
2632
2538
  var files_default = app9;
2633
2539
 
2634
2540
  // packages/daemon/src/web/api/history.ts
2635
- import { and as and3, desc as desc2, eq as eq4, gte, inArray, sql } from "drizzle-orm";
2541
+ import { and as and3, desc as desc2, eq as eq3, gte, inArray, sql } from "drizzle-orm";
2636
2542
  import { Hono as Hono11 } from "hono";
2543
+ async function resolveMindFilter(c) {
2544
+ const user = c.get("user");
2545
+ if (user.role === "admin" || user.role === "system") {
2546
+ return c.req.query("mind") ?? void 0;
2547
+ }
2548
+ return getBaseName(user.username);
2549
+ }
2637
2550
  var history = new Hono11().get("/turns", async (c) => {
2638
- const mindFilter = c.req.query("mind");
2551
+ const mindFilter = await resolveMindFilter(c);
2639
2552
  const turnIdFilter = c.req.query("turnId");
2640
2553
  const turnIdsFilter = c.req.query("turnIds");
2641
2554
  const limit = Math.min(Math.max(parseInt(c.req.query("limit") ?? "50", 10) || 50, 1), 200);
2642
2555
  const offset = Math.max(parseInt(c.req.query("offset") ?? "0", 10) || 0, 0);
2643
2556
  const db = await getDb();
2644
2557
  const conditions = [];
2645
- if (mindFilter) conditions.push(eq4(turns.mind, mindFilter));
2646
- if (turnIdFilter) conditions.push(eq4(turns.id, turnIdFilter));
2558
+ if (mindFilter) conditions.push(eq3(turns.mind, mindFilter));
2559
+ if (turnIdFilter) conditions.push(eq3(turns.id, turnIdFilter));
2647
2560
  if (turnIdsFilter) {
2648
2561
  const ids = turnIdsFilter.split(",").filter(Boolean);
2649
2562
  if (ids.length > 0) conditions.push(inArray(turns.id, ids));
@@ -2651,7 +2564,7 @@ var history = new Hono11().get("/turns", async (c) => {
2651
2564
  const turnRows = await db.select().from(turns).where(conditions.length > 0 ? and3(...conditions) : void 0).orderBy(desc2(turns.created_at)).limit(limit).offset(offset);
2652
2565
  if (turnRows.length === 0) return c.json([]);
2653
2566
  const turnIds = turnRows.map((t) => t.id);
2654
- const summaryRows = await db.select().from(summaries).where(and3(eq4(summaries.period, "turn"), inArray(summaries.period_key, turnIds)));
2567
+ const summaryRows = await db.select().from(summaries).where(and3(eq3(summaries.period, "turn"), inArray(summaries.period_key, turnIds)));
2655
2568
  const summaryByTurn = /* @__PURE__ */ new Map();
2656
2569
  for (const s of summaryRows) {
2657
2570
  summaryByTurn.set(s.period_key, { content: s.content, metadata: s.metadata });
@@ -2776,15 +2689,15 @@ var history = new Hono11().get("/turns", async (c) => {
2776
2689
  db.select({
2777
2690
  conversation_id: conversationParticipants.conversation_id,
2778
2691
  username: users.username
2779
- }).from(conversationParticipants).innerJoin(users, eq4(conversationParticipants.user_id, users.id))
2692
+ }).from(conversationParticipants).innerJoin(users, eq3(conversationParticipants.user_id, users.id))
2780
2693
  );
2781
2694
  const dmRows = await db.with(cp2).select({
2782
2695
  id: conversations.id,
2783
2696
  targetUsername: users.username
2784
2697
  }).from(conversations).innerJoin(
2785
2698
  conversationParticipants,
2786
- eq4(conversations.id, conversationParticipants.conversation_id)
2787
- ).innerJoin(users, eq4(conversationParticipants.user_id, users.id)).where(and3(eq4(conversations.type, "dm"), inArray(users.username, targetNames)));
2699
+ eq3(conversations.id, conversationParticipants.conversation_id)
2700
+ ).innerJoin(users, eq3(conversationParticipants.user_id, users.id)).where(and3(eq3(conversations.type, "dm"), inArray(users.username, targetNames)));
2788
2701
  const dmCandidates = [];
2789
2702
  for (const row of dmRows) {
2790
2703
  const slug = `@${row.targetUsername}`;
@@ -2799,7 +2712,7 @@ var history = new Hono11().get("/turns", async (c) => {
2799
2712
  const verifyRows = await db.select({
2800
2713
  conversation_id: conversationParticipants.conversation_id,
2801
2714
  username: users.username
2802
- }).from(conversationParticipants).innerJoin(users, eq4(conversationParticipants.user_id, users.id)).where(
2715
+ }).from(conversationParticipants).innerJoin(users, eq3(conversationParticipants.user_id, users.id)).where(
2803
2716
  and3(
2804
2717
  inArray(conversationParticipants.conversation_id, candidateConvIds),
2805
2718
  inArray(users.username, allMindNames)
@@ -2877,7 +2790,7 @@ var history = new Hono11().get("/turns", async (c) => {
2877
2790
  });
2878
2791
  return c.json(result);
2879
2792
  }).get("/events", async (c) => {
2880
- const mindFilter = c.req.query("mind");
2793
+ const mindFilter = await resolveMindFilter(c);
2881
2794
  const stream = new ReadableStream({
2882
2795
  start(controller) {
2883
2796
  const encoder = new TextEncoder();
@@ -2932,7 +2845,9 @@ var history = new Hono11().get("/turns", async (c) => {
2932
2845
  }
2933
2846
  });
2934
2847
  }).get("/summaries", async (c) => {
2935
- const mind = c.req.query("mind") ?? "_system";
2848
+ const user = c.get("user");
2849
+ const privileged = user.role === "admin" || user.role === "system";
2850
+ const mind = privileged ? c.req.query("mind") ?? "_system" : await getBaseName(user.username);
2936
2851
  const period = c.req.query("period");
2937
2852
  const ids = c.req.query("ids");
2938
2853
  const from = c.req.query("from");
@@ -2942,7 +2857,9 @@ var history = new Hono11().get("/turns", async (c) => {
2942
2857
  const db2 = await getDb();
2943
2858
  const idList = ids.split(",").map((s) => parseInt(s, 10)).filter((n) => !Number.isNaN(n));
2944
2859
  if (idList.length === 0) return c.json([]);
2945
- const rows2 = await db2.select().from(summaries).where(inArray(summaries.id, idList));
2860
+ const idConditions = [inArray(summaries.id, idList)];
2861
+ if (!privileged) idConditions.push(eq3(summaries.mind, mind));
2862
+ const rows2 = await db2.select().from(summaries).where(and3(...idConditions));
2946
2863
  const result2 = rows2.map((r) => {
2947
2864
  let metadata = null;
2948
2865
  if (r.metadata) {
@@ -2960,7 +2877,7 @@ var history = new Hono11().get("/turns", async (c) => {
2960
2877
  return c.json({ error: "period is required (turn, hour, day, week, month)" }, 400);
2961
2878
  }
2962
2879
  const db = await getDb();
2963
- const conditions = [eq4(summaries.mind, mind), eq4(summaries.period, period)];
2880
+ const conditions = [eq3(summaries.mind, mind), eq3(summaries.period, period)];
2964
2881
  if (from) conditions.push(gte(summaries.period_key, from));
2965
2882
  if (to) conditions.push(sql`${summaries.period_key} <= ${to}`);
2966
2883
  const rows = await db.select({
@@ -2985,13 +2902,13 @@ var history = new Hono11().get("/turns", async (c) => {
2985
2902
  });
2986
2903
  return c.json(result);
2987
2904
  }).get("/activity", async (c) => {
2988
- const mind = c.req.query("mind");
2905
+ const mind = await resolveMindFilter(c);
2989
2906
  const from = c.req.query("from");
2990
2907
  const to = c.req.query("to");
2991
2908
  const limit = Math.min(Math.max(parseInt(c.req.query("limit") ?? "100", 10) || 100, 1), 500);
2992
2909
  const db = await getDb();
2993
2910
  const conditions = [];
2994
- if (mind) conditions.push(eq4(activity.mind, mind));
2911
+ if (mind) conditions.push(eq3(activity.mind, mind));
2995
2912
  if (from) conditions.push(gte(activity.created_at, from));
2996
2913
  if (to) conditions.push(sql`${activity.created_at} <= ${to}`);
2997
2914
  conditions.push(
@@ -3246,7 +3163,7 @@ import {
3246
3163
  } from "fs";
3247
3164
  import { basename, resolve as resolve11 } from "path";
3248
3165
  import { zValidator as zValidator5 } from "@hono/zod-validator";
3249
- import { and as and4, desc as desc3, eq as eq5, sql as sql2 } from "drizzle-orm";
3166
+ import { and as and4, desc as desc3, eq as eq4, sql as sql2 } from "drizzle-orm";
3250
3167
  import { Hono as Hono15 } from "hono";
3251
3168
  import { z as z5 } from "zod";
3252
3169
 
@@ -3368,7 +3285,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
3368
3285
  logger_default.warn(`failed to stop variant ${variantName}`, logger_default.errorData(err));
3369
3286
  }
3370
3287
  }
3371
- const { findMind: findMind2 } = await import("./registry-RAXNFN7K.js");
3288
+ const { findMind: findMind2 } = await import("./registry-MDLNPTTI.js");
3372
3289
  const variantEntry = await findMind2(variantName);
3373
3290
  const branchName = variantEntry?.branch ?? variantName;
3374
3291
  if (existsSync6(variantPath)) {
@@ -3625,7 +3542,7 @@ async function getMindStatus(name, port, registryRunning) {
3625
3542
  const manager = getMindManager();
3626
3543
  let status = "stopped";
3627
3544
  try {
3628
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-T3AXQB3R.js");
3545
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-FJLASHHW.js");
3629
3546
  if (getSleepManagerIfReady2()?.isSleeping(name)) {
3630
3547
  status = "sleeping";
3631
3548
  }
@@ -4120,7 +4037,7 @@ var app13 = new Hono15().post("/", requireAdminOrSystem, zValidator5("json", cre
4120
4037
  applyInitFiles(dest);
4121
4038
  const { publicKeyPem } = generateIdentity(dest);
4122
4039
  {
4123
- const { readGlobalConfig: readGlobal } = await import("./setup-3434PQ5Q.js");
4040
+ const { readGlobalConfig: readGlobal } = await import("./setup-IYOUPCIK.js");
4124
4041
  const mindDefaults = readGlobal().mindDefaults;
4125
4042
  const config2 = readVoluteConfig(dest);
4126
4043
  if (!config2) throw new Error("Failed to read volute.json after identity generation");
@@ -4211,7 +4128,7 @@ The human who planted you described you as: "${body.description}"
4211
4128
  }
4212
4129
  let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
4213
4130
  if (body.stage === "seed" && !body.skills) {
4214
- const { isImagegenEnabled } = await import("./setup-3434PQ5Q.js");
4131
+ const { isImagegenEnabled } = await import("./setup-IYOUPCIK.js");
4215
4132
  if (isImagegenEnabled()) {
4216
4133
  skillSet = [...skillSet, "imagegen"];
4217
4134
  }
@@ -4229,7 +4146,7 @@ The human who planted you described you as: "${body.description}"
4229
4146
  try {
4230
4147
  const spiritEntry = await findMind("volute");
4231
4148
  if (spiritEntry) {
4232
- const { spiritDir } = await import("./spirit-KTBHLULO.js");
4149
+ const { spiritDir } = await import("./spirit-NJFAY5CZ.js");
4233
4150
  const sDir = spiritEntry.dir ?? spiritDir();
4234
4151
  const spiritConfig = readVoluteConfig(sDir) ?? {};
4235
4152
  const schedules = spiritConfig.schedules ?? [];
@@ -4244,7 +4161,7 @@ The human who planted you described you as: "${body.description}"
4244
4161
  });
4245
4162
  spiritConfig.schedules = schedules;
4246
4163
  writeVoluteConfig(sDir, spiritConfig);
4247
- const { getScheduler: getScheduler2 } = await import("./scheduler-SXELVRWO.js");
4164
+ const { getScheduler: getScheduler2 } = await import("./scheduler-KXUY2I7W.js");
4248
4165
  getScheduler2().loadSchedules("volute", sDir);
4249
4166
  }
4250
4167
  }
@@ -4509,7 +4426,7 @@ ${user.trimEnd()}
4509
4426
  const manager = getMindManager();
4510
4427
  try {
4511
4428
  if (context?.type === "reload") {
4512
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-T3AXQB3R.js");
4429
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-FJLASHHW.js");
4513
4430
  const sleepState = getSleepManagerIfReady2()?.getState(name);
4514
4431
  if (sleepState?.sleeping) {
4515
4432
  logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
@@ -4604,7 +4521,7 @@ ${user.trimEnd()}
4604
4521
  const name = c.req.param("name");
4605
4522
  const entry = await findMind(name);
4606
4523
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4607
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-T3AXQB3R.js");
4524
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-FJLASHHW.js");
4608
4525
  const sm = getSleepManagerIfReady2();
4609
4526
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
4610
4527
  return c.json(sm.getState(name));
@@ -4612,7 +4529,7 @@ ${user.trimEnd()}
4612
4529
  const name = c.req.param("name");
4613
4530
  const entry = await findMind(name);
4614
4531
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4615
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-T3AXQB3R.js");
4532
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-FJLASHHW.js");
4616
4533
  const sm = getSleepManagerIfReady2();
4617
4534
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
4618
4535
  if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
@@ -4632,7 +4549,7 @@ ${user.trimEnd()}
4632
4549
  const name = c.req.param("name");
4633
4550
  const entry = await findMind(name);
4634
4551
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4635
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-T3AXQB3R.js");
4552
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-FJLASHHW.js");
4636
4553
  const sm = getSleepManagerIfReady2();
4637
4554
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
4638
4555
  const sleepState = sm.getState(name);
@@ -4647,7 +4564,7 @@ ${user.trimEnd()}
4647
4564
  const name = c.req.param("name");
4648
4565
  const entry = await findMind(name);
4649
4566
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4650
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-T3AXQB3R.js");
4567
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-FJLASHHW.js");
4651
4568
  const sm = getSleepManagerIfReady2();
4652
4569
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
4653
4570
  const flushed = await sm.flushQueuedMessages(name);
@@ -4665,7 +4582,7 @@ ${user.trimEnd()}
4665
4582
  if (body.avatar !== void 0) profile.avatar = basename(body.avatar);
4666
4583
  config2.profile = profile;
4667
4584
  writeVoluteConfig(dir, config2);
4668
- const { syncMindProfile: syncMindProfile2 } = await import("./auth-VYW2ECCE.js");
4585
+ const { syncMindProfile: syncMindProfile2 } = await import("./auth-EAASQPTN.js");
4669
4586
  await syncMindProfile2(name, profile);
4670
4587
  broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
4671
4588
  return c.json({ ok: true });
@@ -4682,8 +4599,8 @@ ${user.trimEnd()}
4682
4599
  const spiritThreshold = Number.isNaN(rawSpirit) ? 15 : rawSpirit;
4683
4600
  const lastCreatorMsg = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(
4684
4601
  and4(
4685
- eq5(mindHistory.mind, name),
4686
- eq5(mindHistory.type, "inbound"),
4602
+ eq4(mindHistory.mind, name),
4603
+ eq4(mindHistory.type, "inbound"),
4687
4604
  sql2`${mindHistory.sender} != 'volute'`,
4688
4605
  sql2`${mindHistory.sender} != ${name}`,
4689
4606
  sql2`${mindHistory.sender} IS NOT NULL`
@@ -4691,9 +4608,9 @@ ${user.trimEnd()}
4691
4608
  ).orderBy(desc3(mindHistory.created_at)).limit(1);
4692
4609
  const lastSpiritMsg = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(
4693
4610
  and4(
4694
- eq5(mindHistory.mind, name),
4695
- eq5(mindHistory.type, "inbound"),
4696
- eq5(mindHistory.sender, "volute")
4611
+ eq4(mindHistory.mind, name),
4612
+ eq4(mindHistory.type, "inbound"),
4613
+ eq4(mindHistory.sender, "volute")
4697
4614
  )
4698
4615
  ).orderBy(desc3(mindHistory.created_at)).limit(1);
4699
4616
  const now = Date.now();
@@ -4712,7 +4629,7 @@ ${user.trimEnd()}
4712
4629
  const config2 = readVoluteConfig(dir);
4713
4630
  const displayNameSet = !!config2?.profile?.displayName;
4714
4631
  const avatarSet = !!config2?.profile?.avatar;
4715
- const { isImagegenEnabled } = await import("./setup-3434PQ5Q.js");
4632
+ const { isImagegenEnabled } = await import("./setup-IYOUPCIK.js");
4716
4633
  const imagegenEnabled = isImagegenEnabled();
4717
4634
  const done = [];
4718
4635
  const remaining = [];
@@ -4750,7 +4667,7 @@ ${user.trimEnd()}
4750
4667
  try {
4751
4668
  const spiritEntry = await findMind("volute");
4752
4669
  if (spiritEntry) {
4753
- const { spiritDir } = await import("./spirit-KTBHLULO.js");
4670
+ const { spiritDir } = await import("./spirit-NJFAY5CZ.js");
4754
4671
  const sDir = spiritEntry.dir ?? spiritDir();
4755
4672
  const spiritConfig = readVoluteConfig(sDir);
4756
4673
  if (spiritConfig?.schedules) {
@@ -4758,7 +4675,7 @@ ${user.trimEnd()}
4758
4675
  spiritConfig.schedules = spiritConfig.schedules.filter((s) => s.id !== nurtureId);
4759
4676
  if (spiritConfig.schedules.length === 0) spiritConfig.schedules = void 0;
4760
4677
  writeVoluteConfig(sDir, spiritConfig);
4761
- const { getScheduler: getScheduler2 } = await import("./scheduler-SXELVRWO.js");
4678
+ const { getScheduler: getScheduler2 } = await import("./scheduler-KXUY2I7W.js");
4762
4679
  getScheduler2().loadSchedules("volute", sDir);
4763
4680
  }
4764
4681
  }
@@ -5193,7 +5110,7 @@ ${user.trimEnd()}
5193
5110
  }
5194
5111
  writeVoluteConfig(dir, existing);
5195
5112
  if (body.unescapeNewlines !== void 0) {
5196
- const { clearEchoTextCache } = await import("./echo-text-QVPS6QDM.js");
5113
+ const { clearEchoTextCache } = await import("./echo-text-YP3JVLNA.js");
5197
5114
  clearEchoTextCache(name);
5198
5115
  }
5199
5116
  const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.maxThinkingTokens !== void 0 || body.compaction !== void 0;
@@ -5270,7 +5187,7 @@ ${user.trimEnd()}
5270
5187
  }
5271
5188
  if (entry.mindType === "spirit" && body.model !== void 0) {
5272
5189
  try {
5273
- const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-3434PQ5Q.js");
5190
+ const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-IYOUPCIK.js");
5274
5191
  const globalConfig = readGlobalConfig2();
5275
5192
  globalConfig.spiritModel = body.model;
5276
5193
  writeGlobalConfig2(globalConfig);
@@ -5298,7 +5215,7 @@ ${user.trimEnd()}
5298
5215
  if (!body.systemPrompt || !body.message) {
5299
5216
  return c.json({ error: "systemPrompt and message required" }, 400);
5300
5217
  }
5301
- const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-ZHEPFC3U.js");
5218
+ const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-3GBOJGUA.js");
5302
5219
  if (!isAiConfigured()) {
5303
5220
  return c.json({ error: "AI service not configured" }, 503);
5304
5221
  }
@@ -5571,18 +5488,18 @@ ${user.trimEnd()}
5571
5488
  event_count: sql2`COUNT(*)`,
5572
5489
  message_count: sql2`SUM(CASE WHEN ${mindHistory.type} IN ('inbound','outbound') THEN 1 ELSE 0 END)`,
5573
5490
  tool_count: sql2`SUM(CASE WHEN ${mindHistory.type}='tool_use' THEN 1 ELSE 0 END)`
5574
- }).from(mindHistory).where(and4(eq5(mindHistory.mind, name), sql2`${mindHistory.session} IS NOT NULL`)).groupBy(mindHistory.session).orderBy(sql2`MIN(${mindHistory.created_at}) DESC`);
5491
+ }).from(mindHistory).where(and4(eq4(mindHistory.mind, name), sql2`${mindHistory.session} IS NOT NULL`)).groupBy(mindHistory.session).orderBy(sql2`MIN(${mindHistory.created_at}) DESC`);
5575
5492
  return c.json(rows);
5576
5493
  }).get("/:name/history/channels", requireSelf(), async (c) => {
5577
5494
  const name = c.req.param("name");
5578
5495
  const db = await getDb();
5579
- const rows = await db.selectDistinct({ channel: mindHistory.channel }).from(mindHistory).where(eq5(mindHistory.mind, name));
5496
+ const rows = await db.selectDistinct({ channel: mindHistory.channel }).from(mindHistory).where(eq4(mindHistory.mind, name));
5580
5497
  return c.json(rows.map((r) => r.channel));
5581
5498
  }).get("/:name/history/export", requireSelf(), async (c) => {
5582
5499
  const name = c.req.param("name");
5583
5500
  if (!await findMind(name)) return c.json({ error: "Mind not found" }, 404);
5584
5501
  const db = await getDb();
5585
- const rows = await db.select().from(mindHistory).where(eq5(mindHistory.mind, name));
5502
+ const rows = await db.select().from(mindHistory).where(eq4(mindHistory.mind, name));
5586
5503
  return c.json(rows);
5587
5504
  }).get("/:name/history/turn", requireSelf(), async (c) => {
5588
5505
  const name = c.req.param("name");
@@ -5592,7 +5509,7 @@ ${user.trimEnd()}
5592
5509
  const typeFilter = detail ? void 0 : sql2`${mindHistory.type} IN ('inbound','outbound','tool_use','tool_result','text','thinking','activity')`;
5593
5510
  let rows;
5594
5511
  if (turnId) {
5595
- rows = await db.select().from(mindHistory).where(and4(eq5(mindHistory.mind, name), eq5(mindHistory.turn_id, turnId), typeFilter)).orderBy(mindHistory.id);
5512
+ rows = await db.select().from(mindHistory).where(and4(eq4(mindHistory.mind, name), eq4(mindHistory.turn_id, turnId), typeFilter)).orderBy(mindHistory.id);
5596
5513
  } else {
5597
5514
  const session = c.req.query("session");
5598
5515
  const fromId = parseInt(c.req.query("from_id") ?? "", 10);
@@ -5602,8 +5519,8 @@ ${user.trimEnd()}
5602
5519
  }
5603
5520
  rows = await db.select().from(mindHistory).where(
5604
5521
  and4(
5605
- eq5(mindHistory.mind, name),
5606
- eq5(mindHistory.session, session),
5522
+ eq4(mindHistory.mind, name),
5523
+ eq4(mindHistory.session, session),
5607
5524
  sql2`${mindHistory.id} >= ${fromId}`,
5608
5525
  sql2`${mindHistory.id} <= ${toId}`,
5609
5526
  typeFilter
@@ -5619,13 +5536,13 @@ ${user.trimEnd()}
5619
5536
  if (currentSession) {
5620
5537
  const lastTurn = await db.select({ turn_id: mindHistory.turn_id }).from(mindHistory).where(
5621
5538
  and4(
5622
- eq5(mindHistory.mind, name),
5623
- eq5(mindHistory.session, currentSession),
5539
+ eq4(mindHistory.mind, name),
5540
+ eq4(mindHistory.session, currentSession),
5624
5541
  sql2`${mindHistory.turn_id} IS NOT NULL`
5625
5542
  )
5626
5543
  ).orderBy(desc3(mindHistory.created_at)).limit(1);
5627
5544
  if (lastTurn.length > 0 && lastTurn[0].turn_id) {
5628
- const firstEvent = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(eq5(mindHistory.turn_id, lastTurn[0].turn_id)).orderBy(mindHistory.created_at).limit(1);
5545
+ const firstEvent = await db.select({ created_at: mindHistory.created_at }).from(mindHistory).where(eq4(mindHistory.turn_id, lastTurn[0].turn_id)).orderBy(mindHistory.created_at).limit(1);
5629
5546
  if (firstEvent.length > 0) {
5630
5547
  sinceTimestamp = firstEvent[0].created_at;
5631
5548
  }
@@ -5635,8 +5552,8 @@ ${user.trimEnd()}
5635
5552
  sinceTimestamp = new Date(Date.now() - 36e5).toISOString().replace("T", " ").slice(0, 19);
5636
5553
  }
5637
5554
  const conditions = [
5638
- eq5(summaries.mind, name),
5639
- eq5(summaries.period, "turn"),
5555
+ eq4(summaries.mind, name),
5556
+ eq4(summaries.period, "turn"),
5640
5557
  sql2`${summaries.created_at} > ${sinceTimestamp}`
5641
5558
  ];
5642
5559
  if (currentSession) {
@@ -5646,7 +5563,7 @@ ${user.trimEnd()}
5646
5563
  session: turns.session,
5647
5564
  content: summaries.content,
5648
5565
  created_at: summaries.created_at
5649
- }).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and4(...conditions)).orderBy(desc3(summaries.created_at)).limit(50);
5566
+ }).from(summaries).innerJoin(turns, eq4(turns.id, summaries.period_key)).where(and4(...conditions)).orderBy(desc3(summaries.created_at)).limit(50);
5650
5567
  if (rows.length === 0) {
5651
5568
  return c.json({ context: null });
5652
5569
  }
@@ -5676,18 +5593,18 @@ ${lines.join("\n")}` });
5676
5593
  const limit = Math.min(Math.max(parseInt(c.req.query("limit") ?? "50", 10) || 50, 1), 200);
5677
5594
  const offset = Math.max(parseInt(c.req.query("offset") ?? "0", 10) || 0, 0);
5678
5595
  const db = await getDb();
5679
- const conditions = [eq5(mindHistory.mind, name)];
5596
+ const conditions = [eq4(mindHistory.mind, name)];
5680
5597
  if (channel) {
5681
- conditions.push(eq5(mindHistory.channel, channel));
5598
+ conditions.push(eq4(mindHistory.channel, channel));
5682
5599
  }
5683
5600
  if (session) {
5684
- conditions.push(eq5(mindHistory.session, session));
5601
+ conditions.push(eq4(mindHistory.session, session));
5685
5602
  }
5686
5603
  const effectivePreset = full ? "all" : preset;
5687
5604
  if (!effectivePreset || effectivePreset === "summary") {
5688
- const sumConditions = [eq5(summaries.mind, name), eq5(summaries.period, "turn")];
5605
+ const sumConditions = [eq4(summaries.mind, name), eq4(summaries.period, "turn")];
5689
5606
  if (session) {
5690
- sumConditions.push(eq5(turns.session, session));
5607
+ sumConditions.push(eq4(turns.session, session));
5691
5608
  const sumRows2 = await db.select({
5692
5609
  id: summaries.id,
5693
5610
  mind: summaries.mind,
@@ -5697,7 +5614,7 @@ ${lines.join("\n")}` });
5697
5614
  metadata: summaries.metadata,
5698
5615
  created_at: summaries.created_at,
5699
5616
  session: turns.session
5700
- }).from(summaries).innerJoin(turns, eq5(turns.id, summaries.period_key)).where(and4(...sumConditions)).orderBy(desc3(summaries.created_at)).limit(limit).offset(offset);
5617
+ }).from(summaries).innerJoin(turns, eq4(turns.id, summaries.period_key)).where(and4(...sumConditions)).orderBy(desc3(summaries.created_at)).limit(limit).offset(offset);
5701
5618
  return c.json(
5702
5619
  sumRows2.map((r) => ({
5703
5620
  id: r.id,
@@ -5750,7 +5667,7 @@ var minds_default = app13;
5750
5667
 
5751
5668
  // packages/daemon/src/web/api/prompts.ts
5752
5669
  import { zValidator as zValidator6 } from "@hono/zod-validator";
5753
- import { eq as eq6, sql as sql3 } from "drizzle-orm";
5670
+ import { eq as eq5, sql as sql3 } from "drizzle-orm";
5754
5671
  import { Hono as Hono16 } from "hono";
5755
5672
  import { z as z6 } from "zod";
5756
5673
  var app14 = new Hono16().get("/", async (c) => {
@@ -5794,7 +5711,7 @@ var app14 = new Hono16().get("/", async (c) => {
5794
5711
  return c.json({ error: "Unknown prompt key" }, 404);
5795
5712
  }
5796
5713
  const db = await getDb();
5797
- await db.delete(systemPrompts).where(eq6(systemPrompts.key, key));
5714
+ await db.delete(systemPrompts).where(eq5(systemPrompts.key, key));
5798
5715
  return c.json({ ok: true });
5799
5716
  });
5800
5717
  var prompts_default = app14;
@@ -6042,7 +5959,7 @@ var app15 = new Hono17().get("/:name/clock/status", requireSelf(), async (c) =>
6042
5959
  const body = await c.req.text();
6043
5960
  const message = `[webhook: ${event}] ${body}`;
6044
5961
  try {
6045
- const { sendSystemMessage } = await import("./system-chat-HCPHUQGI.js");
5962
+ const { sendSystemMessage } = await import("./system-chat-P6KVGW4T.js");
6046
5963
  await sendSystemMessage(name, message);
6047
5964
  return c.json({ ok: true });
6048
5965
  } catch (err) {
@@ -6096,7 +6013,7 @@ setup.get("/status", async (c) => {
6096
6013
  let hasAccount = false;
6097
6014
  if (hasSystem) {
6098
6015
  try {
6099
- const { listUsersByType: listUsersByType2 } = await import("./auth-VYW2ECCE.js");
6016
+ const { listUsersByType: listUsersByType2 } = await import("./auth-EAASQPTN.js");
6100
6017
  const brains = await listUsersByType2("brain");
6101
6018
  hasAccount = brains.length > 0;
6102
6019
  } catch (err) {
@@ -6307,7 +6224,7 @@ setup.post("/account", async (c) => {
6307
6224
  }
6308
6225
  }
6309
6226
  try {
6310
- const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-VYW2ECCE.js");
6227
+ const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-EAASQPTN.js");
6311
6228
  const user = await createUser2(body.username.trim(), body.password);
6312
6229
  if (body.displayName?.trim()) {
6313
6230
  await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
@@ -6353,7 +6270,7 @@ setup.post("/models", async (c) => {
6353
6270
  return c.json({ error: "Spirit model is required" }, 400);
6354
6271
  }
6355
6272
  try {
6356
- const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-ZHEPFC3U.js");
6273
+ const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-3GBOJGUA.js");
6357
6274
  setEnabledModels3(body.models);
6358
6275
  const config2 = readGlobalConfig();
6359
6276
  config2.spiritModel = body.spiritModel.trim();
@@ -6371,15 +6288,15 @@ setup.post("/complete", async (c) => {
6371
6288
  return c.json({ error: "Setup already complete" }, 400);
6372
6289
  }
6373
6290
  try {
6374
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-KTBHLULO.js");
6375
- const { startSpiritFull } = await import("./mind-service-L7LMMDYJ.js");
6291
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-NJFAY5CZ.js");
6292
+ const { startSpiritFull } = await import("./mind-service-PR4PR4XI.js");
6376
6293
  await ensureSpiritProject();
6377
6294
  await syncSpiritTemplate();
6378
6295
  const warnings = [];
6379
6296
  const config2 = readGlobalConfig();
6380
6297
  if (config2.setup?.service && config2.setup?.type === "local") {
6381
6298
  try {
6382
- const { installUserService } = await import("./service-install-NLGAVTQS.js");
6299
+ const { installUserService } = await import("./service-install-GTDUHP6R.js");
6383
6300
  const installed = await installUserService(config2.port, config2.hostname);
6384
6301
  if (!installed) {
6385
6302
  warnings.push("Service installation is not supported on this platform.");
@@ -6407,8 +6324,8 @@ setup.post("/complete", async (c) => {
6407
6324
  }
6408
6325
  let spiritConversationId;
6409
6326
  try {
6410
- const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-VYW2ECCE.js");
6411
- const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-KW7IYESK.js");
6327
+ const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-EAASQPTN.js");
6328
+ const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-FSZCUUYO.js");
6412
6329
  const spiritUser = await getOrCreateMindUser2("volute");
6413
6330
  const brains = await listUsersByType2("brain");
6414
6331
  const admin2 = brains.find((u) => u.role === "admin");
@@ -6430,8 +6347,8 @@ setup.post("/complete", async (c) => {
6430
6347
  logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
6431
6348
  if (spiritConversationId && spiritStarted) {
6432
6349
  try {
6433
- const { deliverMessage: deliverMessage2 } = await import("./message-delivery-X4CZE2L6.js");
6434
- const { listUsersByType: listUsers2 } = await import("./auth-VYW2ECCE.js");
6350
+ const { deliverMessage: deliverMessage2 } = await import("./message-delivery-FPIL26WV.js");
6351
+ const { listUsersByType: listUsers2 } = await import("./auth-EAASQPTN.js");
6435
6352
  const admins = await listUsers2("brain");
6436
6353
  const admin2 = admins.find((u) => u.role === "admin");
6437
6354
  const adminName = admin2?.display_name || admin2?.username || "the admin";
@@ -6790,11 +6707,20 @@ function bufferEvent(data) {
6790
6707
  }
6791
6708
  return id;
6792
6709
  }
6793
- function getEventsSince(sinceId) {
6710
+ function nextEventId() {
6711
+ return nextId++;
6712
+ }
6713
+ function getEventsSince(sinceId, allowedConversationIds) {
6794
6714
  const now = Date.now();
6795
6715
  const startIdx = buffer.findIndex((e) => e.id > sinceId);
6796
6716
  if (startIdx === -1) return [];
6797
- return buffer.slice(startIdx).filter((e) => now - e.timestamp < MAX_AGE_MS);
6717
+ return buffer.slice(startIdx).filter((e) => {
6718
+ if (now - e.timestamp >= MAX_AGE_MS) return false;
6719
+ const data = e.data;
6720
+ if (data.event === "snapshot") return false;
6721
+ if (data.event === "conversation") return allowedConversationIds.has(data.conversationId);
6722
+ return true;
6723
+ });
6798
6724
  }
6799
6725
 
6800
6726
  // packages/daemon/src/web/api/v1/events.ts
@@ -6809,8 +6735,22 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
6809
6735
  cleanups.push(() => removeConnection(user.username));
6810
6736
  }
6811
6737
  try {
6738
+ let conversations2 = [];
6739
+ try {
6740
+ conversations2 = await listConversationsWithParticipants(user.id);
6741
+ if (conversations2.length > 0) {
6742
+ const convIds = conversations2.map((c2) => c2.id);
6743
+ const unreads = await getUnreadCounts(user.id, convIds);
6744
+ for (const conv of conversations2) {
6745
+ conv.unreadCount = unreads[conv.id] ?? 0;
6746
+ }
6747
+ }
6748
+ } catch (err) {
6749
+ logger_default.error("[v1-events] failed to fetch conversations", logger_default.errorData(err));
6750
+ }
6751
+ const allowedConversationIds = new Set(conversations2.map((c2) => c2.id));
6812
6752
  if (sinceId > 0) {
6813
- const missed = getEventsSince(sinceId);
6753
+ const missed = getEventsSince(sinceId, allowedConversationIds);
6814
6754
  for (const event of missed) {
6815
6755
  await stream.writeSSE({
6816
6756
  id: String(event.id),
@@ -6829,19 +6769,6 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
6829
6769
  } catch (err) {
6830
6770
  logger_default.error("[v1-events] failed to fetch recent activity", logger_default.errorData(err));
6831
6771
  }
6832
- let conversations2 = [];
6833
- try {
6834
- conversations2 = await listConversationsWithParticipants(user.id);
6835
- if (conversations2.length > 0) {
6836
- const convIds = conversations2.map((c2) => c2.id);
6837
- const unreads = await getUnreadCounts(user.id, convIds);
6838
- for (const conv of conversations2) {
6839
- conv.unreadCount = unreads[conv.id] ?? 0;
6840
- }
6841
- }
6842
- } catch (err) {
6843
- logger_default.error("[v1-events] failed to fetch conversations", logger_default.errorData(err));
6844
- }
6845
6772
  const snapshotData = {
6846
6773
  event: "snapshot",
6847
6774
  activity: recentActivity,
@@ -6849,7 +6776,7 @@ var app20 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
6849
6776
  activeMinds: getActiveMinds(),
6850
6777
  onlineBrains: getOnlineBrains()
6851
6778
  };
6852
- const snapshotId = bufferEvent(snapshotData);
6779
+ const snapshotId = nextEventId();
6853
6780
  await stream.writeSSE({
6854
6781
  id: String(snapshotId),
6855
6782
  data: JSON.stringify(snapshotData)
@@ -6915,14 +6842,23 @@ import { resolve as resolve14 } from "path";
6915
6842
  function tsxBin(cwd) {
6916
6843
  return resolve14(cwd, "node_modules", ".bin", "tsx");
6917
6844
  }
6918
- function spawnServer(cwd, port, options) {
6845
+ async function spawnServer(cwd, port, options) {
6846
+ let cmd = tsxBin(cwd);
6847
+ let args = ["src/server.ts", "--port", String(port)];
6848
+ if (options?.mindName) {
6849
+ if (isIsolationEnabled()) {
6850
+ [cmd, args] = await wrapForIsolation(cmd, args, options.mindName);
6851
+ } else if (isSandboxEnabled() && options.template !== "codex") {
6852
+ [cmd, args] = await wrapForSandbox(cmd, args, cwd, options.mindName, [cwd, mindTmpDir(cwd)]);
6853
+ }
6854
+ }
6919
6855
  if (options?.detached) {
6920
- return spawnDetached(cwd, port, options.logDir);
6856
+ return spawnDetached(cmd, args, cwd, options.logDir);
6921
6857
  }
6922
- return spawnAttached(cwd, port);
6858
+ return spawnAttached(cmd, args, cwd);
6923
6859
  }
6924
- function spawnAttached(cwd, port) {
6925
- const child = spawn4(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
6860
+ function spawnAttached(cmd, args, cwd) {
6861
+ const child = spawn4(cmd, args, {
6926
6862
  cwd,
6927
6863
  stdio: ["ignore", "pipe", "pipe"]
6928
6864
  });
@@ -6947,12 +6883,12 @@ function spawnAttached(cwd, port) {
6947
6883
  });
6948
6884
  });
6949
6885
  }
6950
- function spawnDetached(cwd, port, logDir) {
6886
+ function spawnDetached(cmd, args, cwd, logDir) {
6951
6887
  const logsDir = logDir ?? resolve14(cwd, ".mind", "logs");
6952
6888
  mkdirSync8(logsDir, { recursive: true });
6953
6889
  const logPath = resolve14(logsDir, "mind.log");
6954
6890
  const logFd = openSync(logPath, "a");
6955
- const child = spawn4(tsxBin(cwd), ["src/server.ts", "--port", String(port)], {
6891
+ const child = spawn4(cmd, args, {
6956
6892
  cwd,
6957
6893
  stdio: ["ignore", logFd, logFd],
6958
6894
  detached: true
@@ -7147,7 +7083,11 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
7147
7083
  }
7148
7084
  }
7149
7085
  if (!body.skipVerify) {
7150
- const result = await spawnServer(variantEntry.dir, 0, { detached: true });
7086
+ const result = await spawnServer(variantEntry.dir, 0, {
7087
+ detached: true,
7088
+ mindName: variantName,
7089
+ template: variantEntry.template
7090
+ });
7151
7091
  if (!result) {
7152
7092
  return c.json(
7153
7093
  { error: "Failed to start server for verification. Use skipVerify to skip." },
@@ -7188,8 +7128,8 @@ var app21 = new Hono24().get("/:name/variants", async (c) => {
7188
7128
  await cleanupVariant(variantName, projectRoot, variantEntry.dir);
7189
7129
  if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
7190
7130
  try {
7191
- const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-JARTCRGS.js");
7192
- const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-RAXNFN7K.js");
7131
+ const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-446HHH5V.js");
7132
+ const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-MDLNPTTI.js");
7193
7133
  const tmpl = parentEntry.template ?? "claude";
7194
7134
  await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
7195
7135
  } catch (err) {
@@ -7303,9 +7243,13 @@ var app22 = new Hono25().get("/", async (c) => {
7303
7243
  });
7304
7244
  }).patch("/:name", zValidator9("json", channelSettingsSchema), async (c) => {
7305
7245
  const name = c.req.param("name");
7246
+ const user = c.get("user");
7306
7247
  const body = c.req.valid("json");
7307
7248
  const ch = await getChannelByName(name);
7308
7249
  if (!ch) return c.json({ error: "Channel not found" }, 404);
7250
+ if (user.role !== "admin" && user.role !== "system" && !await isParticipant(ch.id, user.id)) {
7251
+ return c.json({ error: "Forbidden" }, 403);
7252
+ }
7309
7253
  await updateChannelSettings(name, body);
7310
7254
  const settings = await getChannelSettings(name);
7311
7255
  return c.json({ ...ch, channel_name: name, settings: formatChannelSettings(settings) });
@@ -7335,6 +7279,9 @@ var app22 = new Hono25().get("/", async (c) => {
7335
7279
  const { username } = c.req.valid("json");
7336
7280
  const ch = await getChannelByName(name);
7337
7281
  if (!ch) return c.json({ error: "Channel not found" }, 404);
7282
+ if (inviter.role !== "admin" && inviter.role !== "system" && !await isParticipant(ch.id, inviter.id)) {
7283
+ return c.json({ error: "Forbidden" }, 403);
7284
+ }
7338
7285
  let user = await getUserByUsername(username);
7339
7286
  if (!user && await findMind(username)) {
7340
7287
  user = await getOrCreateMindUser(username);
@@ -7941,6 +7888,11 @@ if (!process.env.VOLUTE_HOME) {
7941
7888
  if (process.env.VOLUTE_TIMEZONE && !process.env.TZ) {
7942
7889
  process.env.TZ = process.env.VOLUTE_TIMEZONE;
7943
7890
  }
7891
+ function writeDaemonConfig(path, config2) {
7892
+ writeFileSync9(path, `${JSON.stringify(config2, null, 2)}
7893
+ `, { mode: 384 });
7894
+ chmodSync(path, 384);
7895
+ }
7944
7896
  async function startDaemon(opts) {
7945
7897
  const { port, hostname } = opts;
7946
7898
  const myPid = String(process.pid);
@@ -7961,18 +7913,19 @@ async function startDaemon(opts) {
7961
7913
  const DAEMON_JSON_PATH = resolve17(systemDir, "daemon.json");
7962
7914
  mkdirSync10(home, { recursive: true });
7963
7915
  ensureSystemDir();
7964
- const { migrateSetupCompleted } = await import("./setup-3434PQ5Q.js");
7916
+ const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-IYOUPCIK.js");
7917
+ migrateConfigSecrets();
7965
7918
  migrateSetupCompleted();
7966
- await (await import("./db-D4FVCA5I.js")).getDb();
7919
+ await (await import("./db-ZJJJYJBU.js")).getDb();
7967
7920
  try {
7968
- const { eq: eq7, and: and5 } = await import("drizzle-orm");
7921
+ const { eq: eq6, and: and5 } = await import("drizzle-orm");
7969
7922
  const { users: users2 } = await import("./schema-HHYJDG7B.js");
7970
- const db = await (await import("./db-D4FVCA5I.js")).getDb();
7971
- await db.update(users2).set({ role: "system" }).where(and5(eq7(users2.user_type, "system"), eq7(users2.role, "user")));
7923
+ const db = await (await import("./db-ZJJJYJBU.js")).getDb();
7924
+ await db.update(users2).set({ role: "system" }).where(and5(eq6(users2.user_type, "system"), eq6(users2.role, "user")));
7972
7925
  } catch (err) {
7973
7926
  logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
7974
7927
  }
7975
- const { initSandbox } = await import("./sandbox-O3GZTS7J.js");
7928
+ const { initSandbox } = await import("./sandbox-E7RWZDVG.js");
7976
7929
  await initSandbox();
7977
7930
  try {
7978
7931
  await syncBuiltinSkills();
@@ -7999,7 +7952,7 @@ async function startDaemon(opts) {
7999
7952
  logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
8000
7953
  }
8001
7954
  try {
8002
- const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-VYW2ECCE.js");
7955
+ const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-EAASQPTN.js");
8003
7956
  await getOrCreateSystemUser2();
8004
7957
  } catch (err) {
8005
7958
  logger_default.warn(
@@ -8008,12 +7961,12 @@ async function startDaemon(opts) {
8008
7961
  );
8009
7962
  }
8010
7963
  const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes(32).toString("hex");
8011
- const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-3434PQ5Q.js");
7964
+ const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-IYOUPCIK.js");
8012
7965
  const globalCfg = readGlobalConfig2();
8013
7966
  let tls;
8014
7967
  if (opts.tailscale || globalCfg.tailscale) {
8015
7968
  try {
8016
- const { getTailscaleTls } = await import("./tailscale-PK3AI5EV.js");
7969
+ const { getTailscaleTls } = await import("./tailscale-TIRTGM6E.js");
8017
7970
  const tlsConfig = await getTailscaleTls();
8018
7971
  tls = { key: tlsConfig.key, cert: tlsConfig.cert };
8019
7972
  logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
@@ -8044,8 +7997,7 @@ async function startDaemon(opts) {
8044
7997
  const daemonConfig = { port, hostname, token };
8045
7998
  if (internalPort) daemonConfig.internalPort = internalPort;
8046
7999
  if (tls) daemonConfig.tls = true;
8047
- writeFileSync9(DAEMON_JSON_PATH, `${JSON.stringify(daemonConfig, null, 2)}
8048
- `, { mode: 420 });
8000
+ writeDaemonConfig(DAEMON_JSON_PATH, daemonConfig);
8049
8001
  const delivery = initDeliveryManager();
8050
8002
  const manager = initMindManager();
8051
8003
  manager.loadCrashAttempts();
@@ -8092,10 +8044,10 @@ async function startDaemon(opts) {
8092
8044
  await Promise.all(workers);
8093
8045
  }
8094
8046
  try {
8095
- const { isSetupComplete: isSetupComplete2 } = await import("./setup-3434PQ5Q.js");
8047
+ const { isSetupComplete: isSetupComplete2 } = await import("./setup-IYOUPCIK.js");
8096
8048
  if (isSetupComplete2()) {
8097
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-KTBHLULO.js");
8098
- const { startSpiritFull } = await import("./mind-service-L7LMMDYJ.js");
8049
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-NJFAY5CZ.js");
8050
+ const { startSpiritFull } = await import("./mind-service-PR4PR4XI.js");
8099
8051
  await ensureSpiritProject();
8100
8052
  await syncSpiritTemplate();
8101
8053
  const spiritEntry = await findMind("volute");
@@ -8112,7 +8064,7 @@ async function startDaemon(opts) {
8112
8064
  bridgeManager.startBridges(daemonPort).catch((err) => {
8113
8065
  logger_default.warn("failed to start bridges", logger_default.errorData(err));
8114
8066
  });
8115
- import("./cloud-sync-GV6O2HN2.js").then(
8067
+ import("./cloud-sync-3OPHFOYQ.js").then(
8116
8068
  ({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
8117
8069
  logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
8118
8070
  })
@@ -8120,7 +8072,7 @@ async function startDaemon(opts) {
8120
8072
  logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
8121
8073
  });
8122
8074
  try {
8123
- const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-SSNAWZMX.js");
8075
+ const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-TCKAX7ZA.js");
8124
8076
  backfillTemplateHashes();
8125
8077
  notifyVersionUpdate().catch((err) => {
8126
8078
  logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
@@ -8225,8 +8177,12 @@ if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith
8225
8177
  if (noSandbox) {
8226
8178
  process.env.VOLUTE_SANDBOX = "0";
8227
8179
  }
8228
- startDaemon({ port, hostname, foreground, tailscale });
8180
+ startDaemon({ port, hostname, foreground, tailscale }).catch((err) => {
8181
+ logger_default.error("daemon failed to start", logger_default.errorData(err));
8182
+ process.exit(1);
8183
+ });
8229
8184
  }
8230
8185
  export {
8231
- startDaemon
8186
+ startDaemon,
8187
+ writeDaemonConfig
8232
8188
  };