volute 0.25.0 → 0.26.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 (102) hide show
  1. package/README.md +15 -20
  2. package/dist/{activity-events-4O37J7PD.js → activity-events-ZMBAKLUF.js} +2 -2
  3. package/dist/api.d.ts +477 -6
  4. package/dist/{auth-HM2RSPY7.js → auth-4TV573WE.js} +2 -2
  5. package/dist/{channel-HZOSHGNF.js → channel-ZVZV42UD.js} +3 -3
  6. package/dist/{chunk-SHSWYG2J.js → chunk-2VO7453N.js} +56 -19
  7. package/dist/{chunk-PMX4EIJK.js → chunk-3CFRE2VC.js} +878 -741
  8. package/dist/{chunk-PHHKNGA3.js → chunk-3TV4GLFO.js} +2 -2
  9. package/dist/{chunk-BOTQ25QT.js → chunk-5Y3PBKW6.js} +2 -2
  10. package/dist/{chunk-BFK6SOEJ.js → chunk-J2CO4WEV.js} +1 -1
  11. package/dist/{chunk-ZSH4G2P5.js → chunk-LX22GRG7.js} +10 -13
  12. package/dist/{chunk-E7GOKNOT.js → chunk-NWI2425I.js} +1 -1
  13. package/dist/{chunk-2767L2RZ.js → chunk-OZFKBXD6.js} +1 -1
  14. package/dist/{chunk-RVKR2R7F.js → chunk-SSI47XP2.js} +10 -2
  15. package/dist/chunk-TZKJLDQN.js +78 -0
  16. package/dist/{chunk-DG7TO7EE.js → chunk-USNBKHYG.js} +3 -3
  17. package/dist/chunk-UTL75LP6.js +113 -0
  18. package/dist/{chunk-3AIBT4TW.js → chunk-V63B7DX3.js} +24 -1
  19. package/dist/{chunk-33XAVCS4.js → chunk-WBHMQ5OZ.js} +49 -0
  20. package/dist/{chunk-TRQEV3CD.js → chunk-WGOGUMPO.js} +22 -3
  21. package/dist/chunk-XOXLRRR2.js +176 -0
  22. package/dist/{chunk-JTDFJWI2.js → chunk-YJA7P64S.js} +1 -1
  23. package/dist/chunk-ZYGKG6VC.js +22 -0
  24. package/dist/cli.js +44 -20
  25. package/dist/{cloud-sync-PPBBJDY6.js → cloud-sync-NI2K3C7G.js} +11 -9
  26. package/dist/{connector-M6XFI6GM.js → connector-G722WXAU.js} +4 -4
  27. package/dist/{create-VDQJER52.js → create-4YBRTTJS.js} +1 -1
  28. package/dist/{daemon-client-JOVQZ52X.js → daemon-client-Z7FAJ6JW.js} +1 -1
  29. package/dist/{daemon-restart-FDNOZEAD.js → daemon-restart-BJZ3O4U4.js} +6 -5
  30. package/dist/daemon.js +693 -265
  31. package/dist/{delete-2MRR4JX5.js → delete-27OYNK25.js} +1 -1
  32. package/dist/{down-674SX2IZ.js → down-7UKFMJJZ.js} +4 -4
  33. package/dist/{env-2FPOZK37.js → env-M336ONDP.js} +4 -4
  34. package/dist/{export-IKFAPRAO.js → export-HP4G5DQC.js} +1 -1
  35. package/dist/{file-KT3UIQM3.js → file-HUDKTRAS.js} +3 -3
  36. package/dist/{history-46WZN5CN.js → history-B64GTFTD.js} +3 -3
  37. package/dist/{import-TH26J76F.js → import-XIB7UV4S.js} +1 -1
  38. package/dist/{log-6SGSSR3D.js → log-PBFNILJ4.js} +3 -3
  39. package/dist/{login-UO6AOVEA.js → login-6U7U6BNG.js} +1 -1
  40. package/dist/login-B5E7N7MY.js +46 -0
  41. package/dist/logout-XSJRYS3U.js +39 -0
  42. package/dist/{logs-HRBONI5I.js → logs-3CART7O7.js} +3 -3
  43. package/dist/{merge-KSFJKX6T.js → merge-VK2HSKMA.js} +3 -3
  44. package/dist/{message-delivery-XMGV3FUM.js → message-delivery-MS5JYPZX.js} +10 -8
  45. package/dist/{mind-YVWAHL2A.js → mind-HZ3QSDDJ.js} +17 -17
  46. package/dist/{mind-activity-tracker-NMDDEV3K.js → mind-activity-tracker-4G6FURY2.js} +3 -3
  47. package/dist/{mind-manager-4NDNAYAB.js → mind-manager-VVK67AY3.js} +6 -4
  48. package/dist/{mind-sleep-GHPTSAYN.js → mind-sleep-DTV7L44D.js} +3 -3
  49. package/dist/{mind-wake-BJDJFMDF.js → mind-wake-PFN4FN3T.js} +3 -3
  50. package/dist/notes-37FW2UR2.js +230 -0
  51. package/dist/{package-3HF5MXU2.js → package-VZWLXPHV.js} +2 -1
  52. package/dist/{pages-Y6DRWUOJ.js → pages-DIIT5HMQ.js} +1 -1
  53. package/dist/{publish-EEKTZBHW.js → publish-HQV7YREB.js} +3 -3
  54. package/dist/{pull-D32SPFVU.js → pull-2MB4SK3C.js} +3 -3
  55. package/dist/{register-U2UO6TC4.js → register-EFND67FQ.js} +1 -1
  56. package/dist/{restart-5BMNV7KU.js → restart-CCK7D6TV.js} +3 -3
  57. package/dist/sandbox-EHGFF52K.js +19 -0
  58. package/dist/{schedule-YEFDLVMJ.js → schedule-6F7ELB2M.js} +3 -3
  59. package/dist/{seed-6FEKB3YC.js → seed-E5OQGWX3.js} +1 -1
  60. package/dist/{send-IISDYFCL.js → send-IH6XZKPC.js} +6 -20
  61. package/dist/service-LLBV3R7M.js +122 -0
  62. package/dist/setup-F6TWFYGQ.js +371 -0
  63. package/dist/setup-YGAAIKKZ.js +17 -0
  64. package/dist/{shared-LWMNTTZN.js → shared-UMO4S7CC.js} +4 -4
  65. package/dist/{skill-T3EMR6IR.js → skill-42LGFBQC.js} +3 -3
  66. package/dist/skills/dreaming/SKILL.md +68 -0
  67. package/dist/skills/dreaming/references/INSTALL.md +56 -0
  68. package/dist/skills/dreaming/scripts/dream.ts +289 -0
  69. package/dist/skills/dreaming/scripts/wake-context-dreams.sh +30 -0
  70. package/dist/skills/notes/SKILL.md +34 -0
  71. package/dist/{sleep-manager-RKTFZPD3.js → sleep-manager-EE4NRN2Q.js} +10 -8
  72. package/dist/{sprout-QJVGJDSH.js → sprout-QL74KR2X.js} +5 -5
  73. package/dist/{start-C7XITZ5O.js → start-O5JQASRC.js} +3 -3
  74. package/dist/{status-SIRPLEZC.js → status-FZBEBM7Q.js} +3 -3
  75. package/dist/{status-LYS4NUOZ.js → status-WXD4HXRL.js} +3 -3
  76. package/dist/{stop-CVKBSLXY.js → stop-2SOG5NYF.js} +3 -3
  77. package/dist/up-SDMCSVI3.js +17 -0
  78. package/dist/{update-7XCZMYBT.js → update-5VUDAI3D.js} +6 -6
  79. package/dist/{upgrade-7RUIXGOO.js → upgrade-QCCO33BK.js} +1 -1
  80. package/dist/{variant-UGREB4G5.js → variant-WWLDY6D5.js} +4 -4
  81. package/dist/{version-notify-AZQMC32A.js → version-notify-USFZBWMG.js} +11 -9
  82. package/dist/web-assets/assets/index-CUQ31ieL.js +69 -0
  83. package/dist/web-assets/assets/index-CW8NSl1o.css +1 -0
  84. package/dist/web-assets/index.html +2 -2
  85. package/drizzle/0015_notes.sql +23 -0
  86. package/drizzle/0016_note_reactions_and_replies.sql +15 -0
  87. package/drizzle/meta/_journal.json +14 -0
  88. package/package.json +2 -1
  89. package/templates/_base/.init/.config/hooks/wake-context.sh +7 -0
  90. package/templates/_base/src/lib/startup.ts +8 -0
  91. package/templates/claude/src/agent.ts +51 -1
  92. package/templates/claude/src/server.ts +1 -0
  93. package/templates/pi/package.json.tmpl +1 -0
  94. package/templates/pi/src/agent.ts +48 -1
  95. package/templates/pi/src/lib/subagents.ts +150 -0
  96. package/templates/pi/src/server.ts +1 -0
  97. package/dist/chunk-NWPT4ASZ.js +0 -89
  98. package/dist/service-FASYWLTC.js +0 -247
  99. package/dist/setup-BMLM2UTK.js +0 -230
  100. package/dist/up-CJ26KQLN.js +0 -15
  101. package/dist/web-assets/assets/index-CGPSVu19.js +0 -69
  102. package/dist/web-assets/assets/index-V_rNDsM8.css +0 -1
package/dist/daemon.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  sharedMerge,
8
8
  sharedPull,
9
9
  sharedStatus
10
- } from "./chunk-PHHKNGA3.js";
10
+ } from "./chunk-3TV4GLFO.js";
11
11
  import {
12
12
  applyInitFiles,
13
13
  composeTemplate,
@@ -18,6 +18,7 @@ import {
18
18
  } from "./chunk-AKPFNL7L.js";
19
19
  import {
20
20
  addMessage,
21
+ announceToSystem,
21
22
  approveUser,
22
23
  changePassword,
23
24
  countAdmins,
@@ -28,6 +29,7 @@ import {
28
29
  deleteMindUser as deleteMindUser2,
29
30
  deleteUser,
30
31
  deliverMessage,
32
+ ensureSystemChannel,
31
33
  extractTextContent,
32
34
  findDMConversation,
33
35
  fireWebhook,
@@ -58,6 +60,7 @@ import {
58
60
  isParticipant,
59
61
  isParticipantOrOwner,
60
62
  joinChannel,
63
+ joinSystemChannel,
61
64
  leaveChannel,
62
65
  listChannels,
63
66
  listConversationsForUser,
@@ -66,6 +69,7 @@ import {
66
69
  listUsers,
67
70
  listUsersByType,
68
71
  markConversationRead,
72
+ migrateMindRoles,
69
73
  publish,
70
74
  publish2,
71
75
  publishTypingForChannels,
@@ -78,7 +82,7 @@ import {
78
82
  subscribe2 as subscribe3,
79
83
  updateUserProfile,
80
84
  verifyUser
81
- } from "./chunk-PMX4EIJK.js";
85
+ } from "./chunk-3CFRE2VC.js";
82
86
  import {
83
87
  deleteSystemsConfig,
84
88
  readSystemsConfig,
@@ -88,11 +92,11 @@ import {
88
92
  getActiveMinds,
89
93
  onMindEvent,
90
94
  stopAll
91
- } from "./chunk-E7GOKNOT.js";
95
+ } from "./chunk-NWI2425I.js";
92
96
  import {
93
97
  broadcast,
94
98
  subscribe
95
- } from "./chunk-BFK6SOEJ.js";
99
+ } from "./chunk-J2CO4WEV.js";
96
100
  import {
97
101
  PROMPT_DEFAULTS,
98
102
  PROMPT_KEYS,
@@ -102,28 +106,10 @@ import {
102
106
  getPrompt,
103
107
  getPromptIfCustom,
104
108
  initMindManager,
109
+ resolveMindToken,
105
110
  substitute
106
- } from "./chunk-SHSWYG2J.js";
107
- import {
108
- findOpenClawSession,
109
- importOpenClawConnectors,
110
- importPiSession,
111
- parseNameFromIdentity
112
- } from "./chunk-BOTQ25QT.js";
113
- import {
114
- readVoluteConfig,
115
- writeVoluteConfig
116
- } from "./chunk-SIAG3QMM.js";
117
- import {
118
- loadMergedEnv,
119
- mindEnvPath,
120
- readEnv,
121
- sharedEnvPath,
122
- writeEnv
123
- } from "./chunk-PHU4DEAJ.js";
124
- import {
125
- isHomeOnlyArchive
126
- } from "./chunk-KTJGZ7M7.js";
111
+ } from "./chunk-2VO7453N.js";
112
+ import "./chunk-UTL75LP6.js";
127
113
  import {
128
114
  SEED_SKILLS,
129
115
  STANDARD_SKILLS,
@@ -139,25 +125,53 @@ import {
139
125
  syncBuiltinSkills,
140
126
  uninstallSkill,
141
127
  updateSkill
142
- } from "./chunk-DG7TO7EE.js";
128
+ } from "./chunk-USNBKHYG.js";
143
129
  import {
144
130
  activity,
145
131
  conversations,
146
132
  getDb,
147
133
  mindHistory,
134
+ noteComments,
135
+ noteReactions,
136
+ notes,
148
137
  sessions,
149
- systemPrompts
150
- } from "./chunk-33XAVCS4.js";
138
+ systemPrompts,
139
+ users
140
+ } from "./chunk-WBHMQ5OZ.js";
151
141
  import {
152
142
  logBuffer,
153
143
  logger_default
154
144
  } from "./chunk-YUIHSKR6.js";
155
- import "./chunk-D424ZQGI.js";
145
+ import {
146
+ checkForUpdate,
147
+ checkForUpdateCached,
148
+ getCurrentVersion
149
+ } from "./chunk-ON3FF5JA.js";
150
+ import {
151
+ findOpenClawSession,
152
+ importOpenClawConnectors,
153
+ importPiSession,
154
+ parseNameFromIdentity
155
+ } from "./chunk-5Y3PBKW6.js";
156
+ import {
157
+ readVoluteConfig,
158
+ writeVoluteConfig
159
+ } from "./chunk-SIAG3QMM.js";
160
+ import {
161
+ loadMergedEnv,
162
+ mindEnvPath,
163
+ readEnv,
164
+ sharedEnvPath,
165
+ writeEnv
166
+ } from "./chunk-PHU4DEAJ.js";
167
+ import {
168
+ isHomeOnlyArchive
169
+ } from "./chunk-KTJGZ7M7.js";
156
170
  import {
157
171
  exec,
158
172
  gitExec,
159
173
  resolveVoluteBin
160
- } from "./chunk-JTDFJWI2.js";
174
+ } from "./chunk-YJA7P64S.js";
161
175
  import {
162
176
  chownMindDir,
163
177
  createMindUser,
@@ -165,12 +179,8 @@ import {
165
179
  ensureVoluteGroup,
166
180
  isIsolationEnabled,
167
181
  wrapForIsolation
168
- } from "./chunk-NWPT4ASZ.js";
169
- import {
170
- checkForUpdate,
171
- checkForUpdateCached,
172
- getCurrentVersion
173
- } from "./chunk-ON3FF5JA.js";
182
+ } from "./chunk-XOXLRRR2.js";
183
+ import "./chunk-D424ZQGI.js";
174
184
  import {
175
185
  buildVoluteSlug,
176
186
  resolveChannelId,
@@ -178,6 +188,7 @@ import {
178
188
  splitMessage,
179
189
  writeChannelEntry
180
190
  } from "./chunk-WSLPZF72.js";
191
+ import "./chunk-TZKJLDQN.js";
181
192
  import {
182
193
  addMind,
183
194
  addVariant,
@@ -448,6 +459,24 @@ var requireAdmin = createMiddleware(async (c, next) => {
448
459
  }
449
460
  await next();
450
461
  });
462
+ async function resolveSession(sessionId) {
463
+ const cached = sessionCache.get(sessionId);
464
+ if (cached && cached.expires > Date.now()) {
465
+ return cached.user;
466
+ }
467
+ const userId = await getSessionUserId(sessionId);
468
+ if (userId == null) {
469
+ sessionCache.delete(sessionId);
470
+ return null;
471
+ }
472
+ const user = await getUser(userId);
473
+ if (!user) {
474
+ sessionCache.delete(sessionId);
475
+ return null;
476
+ }
477
+ sessionCache.set(sessionId, { userId, user, expires: Date.now() + SESSION_CACHE_TTL });
478
+ return user;
479
+ }
451
480
  var authMiddleware = createMiddleware(async (c, next) => {
452
481
  const authHeader = c.req.header("Authorization");
453
482
  if (authHeader?.startsWith("Bearer ")) {
@@ -455,7 +484,7 @@ var authMiddleware = createMiddleware(async (c, next) => {
455
484
  if (token && isValidDaemonToken(token)) {
456
485
  c.set("user", {
457
486
  id: 0,
458
- username: "cli",
487
+ username: "daemon",
459
488
  role: "admin",
460
489
  user_type: "brain",
461
490
  display_name: null,
@@ -465,31 +494,42 @@ var authMiddleware = createMiddleware(async (c, next) => {
465
494
  await next();
466
495
  return;
467
496
  }
497
+ const mindName = resolveMindToken(token);
498
+ if (mindName) {
499
+ const mindUser = await getOrCreateMindUser(mindName);
500
+ c.set("user", mindUser);
501
+ await next();
502
+ return;
503
+ }
504
+ if (token) {
505
+ const user2 = await resolveSession(token);
506
+ if (user2) {
507
+ if (user2.role === "pending") return c.json({ error: "Account pending approval" }, 403);
508
+ c.set("user", user2);
509
+ await next();
510
+ return;
511
+ }
512
+ }
468
513
  }
469
514
  const sessionId = getCookie(c, "volute_session");
470
515
  if (!sessionId) return c.json({ error: "Unauthorized" }, 401);
471
- const cached = sessionCache.get(sessionId);
472
- if (cached && cached.expires > Date.now()) {
473
- if (cached.user.role === "pending") return c.json({ error: "Account pending approval" }, 403);
474
- c.set("user", cached.user);
475
- await next();
476
- return;
477
- }
478
- const userId = await getSessionUserId(sessionId);
479
- if (userId == null) {
480
- sessionCache.delete(sessionId);
481
- return c.json({ error: "Unauthorized" }, 401);
482
- }
483
- const user = await getUser(userId);
484
- if (!user) {
485
- sessionCache.delete(sessionId);
486
- return c.json({ error: "Unauthorized" }, 401);
487
- }
516
+ const user = await resolveSession(sessionId);
517
+ if (!user) return c.json({ error: "Unauthorized" }, 401);
488
518
  if (user.role === "pending") return c.json({ error: "Account pending approval" }, 403);
489
- sessionCache.set(sessionId, { userId, user, expires: Date.now() + SESSION_CACHE_TTL });
490
519
  c.set("user", user);
491
520
  await next();
492
521
  });
522
+ var requireSelf = (paramName = "name") => createMiddleware(async (c, next) => {
523
+ const user = c.get("user");
524
+ if (user.role !== "admin") {
525
+ const target = c.req.param(paramName) ?? "";
526
+ const [baseName] = target.split("@", 2);
527
+ if (user.username !== baseName) {
528
+ return c.json({ error: "Forbidden" }, 403);
529
+ }
530
+ }
531
+ await next();
532
+ });
493
533
 
494
534
  // src/web/server.ts
495
535
  import { existsSync as existsSync13 } from "fs";
@@ -499,7 +539,7 @@ import { dirname, extname as extname5, resolve as resolve18 } from "path";
499
539
  import { serve } from "@hono/node-server";
500
540
 
501
541
  // src/web/app.ts
502
- import { Hono as Hono29 } from "hono";
542
+ import { Hono as Hono30 } from "hono";
503
543
  import { bodyLimit } from "hono/body-limit";
504
544
  import { csrf } from "hono/csrf";
505
545
  import { HTTPException } from "hono/http-exception";
@@ -551,7 +591,7 @@ var app = new Hono().get("/events", async (c) => {
551
591
  });
552
592
  cleanups.push(unsubActivity);
553
593
  for (const conv of conversations2) {
554
- const unsubConv = subscribe3(conv.id, (event) => {
594
+ const unsubConv = subscribe2(conv.id, (event) => {
555
595
  stream.writeSSE({
556
596
  data: JSON.stringify({ event: "conversation", conversationId: conv.id, ...event })
557
597
  }).catch((err) => {
@@ -588,6 +628,11 @@ import { zValidator } from "@hono/zod-validator";
588
628
  import { Hono as Hono2 } from "hono";
589
629
  import { deleteCookie, getCookie as getCookie2, setCookie } from "hono/cookie";
590
630
  import { z } from "zod";
631
+ function tryJoinSystem(userId) {
632
+ if (!process.env.VOLUTE_DAEMON_TOKEN) return;
633
+ joinSystemChannel(userId).catch(() => {
634
+ });
635
+ }
591
636
  var SESSION_COOKIE_OPTIONS = {
592
637
  path: "/",
593
638
  httpOnly: true,
@@ -772,6 +817,7 @@ var app2 = new Hono2().post("/register", zValidator("json", credentialsSchema),
772
817
  const sessionId = await createSession(user.id);
773
818
  setCookie(c, "volute_session", sessionId, SESSION_COOKIE_OPTIONS);
774
819
  }
820
+ tryJoinSystem(user.id);
775
821
  return c.json({ id: user.id, username: user.username, role: user.role });
776
822
  }).post("/login", zValidator("json", credentialsSchema), async (c) => {
777
823
  const { username, password } = c.req.valid("json");
@@ -781,12 +827,21 @@ var app2 = new Hono2().post("/register", zValidator("json", credentialsSchema),
781
827
  }
782
828
  const sessionId = await createSession(user.id);
783
829
  setCookie(c, "volute_session", sessionId, SESSION_COOKIE_OPTIONS);
784
- return c.json({ id: user.id, username: user.username, role: user.role });
830
+ tryJoinSystem(user.id);
831
+ return c.json({ id: user.id, username: user.username, role: user.role, sessionId });
785
832
  }).post("/logout", async (c) => {
786
- const sessionId = getCookie2(c, "volute_session");
787
- if (sessionId) {
788
- await deleteSession(sessionId);
833
+ const cookieSession = getCookie2(c, "volute_session");
834
+ if (cookieSession) {
835
+ await deleteSession(cookieSession);
789
836
  deleteCookie(c, "volute_session", { path: "/" });
837
+ return c.json({ ok: true });
838
+ }
839
+ const authHeader = c.req.header("Authorization");
840
+ if (authHeader?.startsWith("Bearer ")) {
841
+ const token = authHeader.slice(7);
842
+ if (token) {
843
+ await deleteSession(token);
844
+ }
790
845
  }
791
846
  return c.json({ ok: true });
792
847
  }).get("/me", async (c) => {
@@ -1095,8 +1150,8 @@ async function listConversations2(env) {
1095
1150
  const userMap = /* @__PURE__ */ new Map();
1096
1151
  const imChannels = data.channels.filter((ch) => ch.is_im && ch.user);
1097
1152
  if (imChannels.length > 0) {
1098
- const users = await listUsers3(env);
1099
- for (const u of users) {
1153
+ const users2 = await listUsers3(env);
1154
+ for (const u of users2) {
1100
1155
  userMap.set(u.id, u.username);
1101
1156
  }
1102
1157
  }
@@ -1488,7 +1543,7 @@ function resolveChannelId2(env, slug) {
1488
1543
  function buildEnv(name) {
1489
1544
  return { ...loadMergedEnv(name), VOLUTE_MIND: name, VOLUTE_MIND_DIR: mindDir(name) };
1490
1545
  }
1491
- var app3 = new Hono3().post("/:name/channels/send", requireAdmin, async (c) => {
1546
+ var app3 = new Hono3().post("/:name/channels/send", requireSelf(), async (c) => {
1492
1547
  const name = c.req.param("name");
1493
1548
  if (!findMind(name)) return c.json({ error: "Mind not found" }, 404);
1494
1549
  const { platform, uri, message, images, sender } = await c.req.json();
@@ -1554,12 +1609,12 @@ var app3 = new Hono3().post("/:name/channels/send", requireAdmin, async (c) => {
1554
1609
  return c.json({ error: `Platform ${platform} does not support listing users` }, 400);
1555
1610
  const env = buildEnv(name);
1556
1611
  try {
1557
- const users = await driver.listUsers(env);
1558
- return c.json(users);
1612
+ const users2 = await driver.listUsers(env);
1613
+ return c.json(users2);
1559
1614
  } catch (err) {
1560
1615
  return c.json({ error: err instanceof Error ? err.message : String(err) }, 500);
1561
1616
  }
1562
- }).post("/:name/channels/create", requireAdmin, async (c) => {
1617
+ }).post("/:name/channels/create", requireSelf(), async (c) => {
1563
1618
  const name = c.req.param("name");
1564
1619
  if (!findMind(name)) return c.json({ error: "Mind not found" }, 404);
1565
1620
  const {
@@ -1914,7 +1969,7 @@ async function notifyMind(port, message, channel, sender) {
1914
1969
  console.warn(`[file-sharing] notify mind on port ${port} failed:`, err);
1915
1970
  }
1916
1971
  }
1917
- var app6 = new Hono6().post("/:name/files/send", async (c) => {
1972
+ var app6 = new Hono6().post("/:name/files/send", requireSelf(), async (c) => {
1918
1973
  const senderName = c.req.param("name");
1919
1974
  const senderEntry = findMind(senderName);
1920
1975
  if (!senderEntry) return c.json({ error: "Sender mind not found" }, 404);
@@ -2648,7 +2703,7 @@ async function getMindStatus(name, port) {
2648
2703
  const manager = getMindManager();
2649
2704
  let status = "stopped";
2650
2705
  try {
2651
- const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
2706
+ const { getSleepManagerIfReady } = await import("./sleep-manager-EE4NRN2Q.js");
2652
2707
  if (getSleepManagerIfReady()?.isSleeping(name)) {
2653
2708
  status = "sleeping";
2654
2709
  }
@@ -3046,11 +3101,30 @@ var app11 = new Hono11().post("/", requireAdmin, zValidator3("json", createMindS
3046
3101
  copyTemplateToDir(composedDir, dest, name, manifest);
3047
3102
  applyInitFiles(dest);
3048
3103
  const { publicKeyPem } = generateIdentity(dest);
3049
- if (body.description) {
3050
- const seedConfig = readVoluteConfig(dest);
3051
- if (!seedConfig) throw new Error("Failed to read volute.json after identity generation");
3052
- seedConfig.profile = { ...seedConfig.profile, description: body.description };
3053
- writeVoluteConfig(dest, seedConfig);
3104
+ {
3105
+ const config = readVoluteConfig(dest);
3106
+ if (!config) throw new Error("Failed to read volute.json after identity generation");
3107
+ if (body.description) {
3108
+ config.profile = { ...config.profile, description: body.description };
3109
+ }
3110
+ if (!config.sleep) {
3111
+ config.sleep = {
3112
+ enabled: true,
3113
+ schedule: { sleep: "0 0 * * *", wake: "0 8 * * *" }
3114
+ };
3115
+ }
3116
+ if (!config.schedules || config.schedules.length === 0) {
3117
+ config.schedules = [
3118
+ {
3119
+ id: "heartbeat",
3120
+ cron: "0 12,16,20 * * *",
3121
+ message: "A quiet moment. You might write something \u2014 a note, a journal entry, a page. You could explore a topic that interests you, check in on #system, or just think. No obligations, just time.",
3122
+ enabled: true,
3123
+ skipWhenSleeping: true
3124
+ }
3125
+ ];
3126
+ }
3127
+ writeVoluteConfig(dest, config);
3054
3128
  }
3055
3129
  if (body.model) {
3056
3130
  const configPath2 = resolve12(dest, "home/.config/config.json");
@@ -3136,6 +3210,8 @@ The human who planted you described you as: "${body.description}"
3136
3210
  description: body.description
3137
3211
  }
3138
3212
  });
3213
+ announceToSystem(`${name} has joined`).catch(() => {
3214
+ });
3139
3215
  return c.json({
3140
3216
  ok: true,
3141
3217
  name,
@@ -3347,7 +3423,7 @@ ${user.trimEnd()}
3347
3423
  } catch (err) {
3348
3424
  return c.json({ error: err instanceof Error ? err.message : "Failed to start mind" }, 500);
3349
3425
  }
3350
- }).post("/:name/restart", requireAdmin, async (c) => {
3426
+ }).post("/:name/restart", requireSelf(), async (c) => {
3351
3427
  const name = c.req.param("name");
3352
3428
  const [baseName, variantName] = name.split("@", 2);
3353
3429
  const entry = findMind(baseName);
@@ -3373,6 +3449,14 @@ ${user.trimEnd()}
3373
3449
  }
3374
3450
  const manager = getMindManager();
3375
3451
  try {
3452
+ if (context?.type === "reload") {
3453
+ const { getSleepManagerIfReady } = await import("./sleep-manager-EE4NRN2Q.js");
3454
+ const sleepState = getSleepManagerIfReady()?.getState(name);
3455
+ if (sleepState?.sleeping) {
3456
+ logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
3457
+ return c.json({ ok: true, deferred: true, port: targetPort });
3458
+ }
3459
+ }
3376
3460
  if (manager.isRunning(name)) {
3377
3461
  await stopMindFull(name);
3378
3462
  }
@@ -3466,7 +3550,7 @@ ${user.trimEnd()}
3466
3550
  const name = c.req.param("name");
3467
3551
  const entry = findMind(name);
3468
3552
  if (!entry) return c.json({ error: "Mind not found" }, 404);
3469
- const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
3553
+ const { getSleepManagerIfReady } = await import("./sleep-manager-EE4NRN2Q.js");
3470
3554
  const sm = getSleepManagerIfReady();
3471
3555
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
3472
3556
  return c.json(sm.getState(name));
@@ -3474,7 +3558,7 @@ ${user.trimEnd()}
3474
3558
  const name = c.req.param("name");
3475
3559
  const entry = findMind(name);
3476
3560
  if (!entry) return c.json({ error: "Mind not found" }, 404);
3477
- const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
3561
+ const { getSleepManagerIfReady } = await import("./sleep-manager-EE4NRN2Q.js");
3478
3562
  const sm = getSleepManagerIfReady();
3479
3563
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
3480
3564
  if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
@@ -3494,17 +3578,22 @@ ${user.trimEnd()}
3494
3578
  const name = c.req.param("name");
3495
3579
  const entry = findMind(name);
3496
3580
  if (!entry) return c.json({ error: "Mind not found" }, 404);
3497
- const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
3581
+ const { getSleepManagerIfReady } = await import("./sleep-manager-EE4NRN2Q.js");
3498
3582
  const sm = getSleepManagerIfReady();
3499
3583
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
3500
- if (!sm.isSleeping(name)) return c.json({ error: "Mind is not sleeping" }, 409);
3501
- sm.initiateWake(name).catch((err) => logger_default.error(`failed to wake ${name}`, logger_default.errorData(err)));
3584
+ const sleepState = sm.getState(name);
3585
+ if (!sleepState.sleeping) return c.json({ error: "Mind is not sleeping" }, 409);
3586
+ if (sleepState.wokenByTrigger) {
3587
+ sm.convertTriggerToFullWake(name);
3588
+ } else {
3589
+ sm.initiateWake(name).catch((err) => logger_default.error(`failed to wake ${name}`, logger_default.errorData(err)));
3590
+ }
3502
3591
  return c.json({ ok: true });
3503
3592
  }).post("/:name/sleep/messages", requireAdmin, async (c) => {
3504
3593
  const name = c.req.param("name");
3505
3594
  const entry = findMind(name);
3506
3595
  if (!entry) return c.json({ error: "Mind not found" }, 404);
3507
- const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
3596
+ const { getSleepManagerIfReady } = await import("./sleep-manager-EE4NRN2Q.js");
3508
3597
  const sm = getSleepManagerIfReady();
3509
3598
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
3510
3599
  const flushed = await sm.flushQueuedMessages(name);
@@ -3712,7 +3801,7 @@ ${user.trimEnd()}
3712
3801
  500
3713
3802
  );
3714
3803
  }
3715
- }).post("/:name/message", async (c) => {
3804
+ }).post("/:name/message", requireSelf(), async (c) => {
3716
3805
  const name = c.req.param("name");
3717
3806
  const [baseName, variantName] = name.split("@", 2);
3718
3807
  const entry = findMind(baseName);
@@ -3722,7 +3811,7 @@ ${user.trimEnd()}
3722
3811
  if (!variant) return c.json({ error: `Unknown variant: ${variantName}` }, 404);
3723
3812
  }
3724
3813
  try {
3725
- const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
3814
+ const { getSleepManagerIfReady } = await import("./sleep-manager-EE4NRN2Q.js");
3726
3815
  const sm = getSleepManagerIfReady();
3727
3816
  if (sm?.isSleeping(baseName)) {
3728
3817
  const body2 = await c.req.text();
@@ -3945,7 +4034,7 @@ ${user.trimEnd()}
3945
4034
  logger_default.error(`failed to get pending deliveries for ${baseName}`, logger_default.errorData(err));
3946
4035
  return c.json({ error: "Failed to retrieve pending messages" }, 500);
3947
4036
  }
3948
- }).post("/:name/events", async (c) => {
4037
+ }).post("/:name/events", requireSelf(), async (c) => {
3949
4038
  const name = c.req.param("name");
3950
4039
  const [baseName] = name.split("@", 2);
3951
4040
  let body;
@@ -3971,7 +4060,7 @@ ${user.trimEnd()}
3971
4060
  } catch (err) {
3972
4061
  logger_default.error(`failed to persist event for ${baseName}`, logger_default.errorData(err));
3973
4062
  }
3974
- publish(baseName, {
4063
+ publish2(baseName, {
3975
4064
  mind: baseName,
3976
4065
  type: body.type,
3977
4066
  session: body.session,
@@ -4030,7 +4119,7 @@ ${user.trimEnd()}
4030
4119
  unsubscribe?.();
4031
4120
  }
4032
4121
  }, 15e3);
4033
- unsubscribe = subscribe2(baseName, (event) => {
4122
+ unsubscribe = subscribe3(baseName, (event) => {
4034
4123
  if (typeFilter && !typeFilter.includes(event.type)) return;
4035
4124
  if (sessionFilter && event.session !== sessionFilter) return;
4036
4125
  if (channelFilter && event.channel !== channelFilter) return;
@@ -4058,7 +4147,7 @@ ${user.trimEnd()}
4058
4147
  Connection: "keep-alive"
4059
4148
  }
4060
4149
  });
4061
- }).post("/:name/history", async (c) => {
4150
+ }).post("/:name/history", requireSelf(), async (c) => {
4062
4151
  const name = c.req.param("name");
4063
4152
  const [baseName] = name.split("@", 2);
4064
4153
  let body;
@@ -4129,10 +4218,330 @@ ${user.trimEnd()}
4129
4218
  });
4130
4219
  var minds_default = app11;
4131
4220
 
4221
+ // src/web/api/notes.ts
4222
+ import { zValidator as zValidator4 } from "@hono/zod-validator";
4223
+ import { Hono as Hono12 } from "hono";
4224
+ import { z as z4 } from "zod";
4225
+
4226
+ // src/lib/notes.ts
4227
+ import { and as and2, count, desc as desc3, eq as eq3, inArray, sql as sql2 } from "drizzle-orm";
4228
+ async function createNote(authorId, title, content, replyToId) {
4229
+ const db = await getDb();
4230
+ let slug = slugify(title) || "untitled";
4231
+ const existing = await db.select({ slug: notes.slug }).from(notes).where(eq3(notes.author_id, authorId)).all();
4232
+ const existingSlugs = new Set(existing.map((r) => r.slug));
4233
+ if (existingSlugs.has(slug)) {
4234
+ let i = 2;
4235
+ while (existingSlugs.has(`${slug}-${i}`)) i++;
4236
+ slug = `${slug}-${i}`;
4237
+ }
4238
+ const [row] = await db.insert(notes).values({ author_id: authorId, title, slug, content, reply_to_id: replyToId ?? null }).returning();
4239
+ const author = await db.select().from(users).where(eq3(users.id, authorId)).get();
4240
+ return {
4241
+ ...row,
4242
+ author_username: author?.username ?? "unknown",
4243
+ author_display_name: author?.display_name ?? null,
4244
+ comment_count: 0
4245
+ };
4246
+ }
4247
+ async function getNote(authorUsername, slug) {
4248
+ const db = await getDb();
4249
+ const row = await db.select({
4250
+ id: notes.id,
4251
+ author_id: notes.author_id,
4252
+ title: notes.title,
4253
+ slug: notes.slug,
4254
+ content: notes.content,
4255
+ reply_to_id: notes.reply_to_id,
4256
+ created_at: notes.created_at,
4257
+ updated_at: notes.updated_at,
4258
+ author_username: users.username,
4259
+ author_display_name: users.display_name
4260
+ }).from(notes).innerJoin(users, eq3(notes.author_id, users.id)).where(and2(eq3(users.username, authorUsername), eq3(notes.slug, slug))).get();
4261
+ if (!row) return null;
4262
+ const comments = await getComments(row.id);
4263
+ const reactions = await getReactions(row.id);
4264
+ let reply_to = null;
4265
+ if (row.reply_to_id) {
4266
+ const parent = await db.select({
4267
+ title: notes.title,
4268
+ slug: notes.slug,
4269
+ author_username: users.username
4270
+ }).from(notes).innerJoin(users, eq3(notes.author_id, users.id)).where(eq3(notes.id, row.reply_to_id)).get();
4271
+ if (parent) {
4272
+ reply_to = parent;
4273
+ }
4274
+ }
4275
+ const replies = await db.select({
4276
+ author_username: users.username,
4277
+ slug: notes.slug,
4278
+ title: notes.title,
4279
+ created_at: notes.created_at
4280
+ }).from(notes).innerJoin(users, eq3(notes.author_id, users.id)).where(eq3(notes.reply_to_id, row.id)).orderBy(notes.created_at).all();
4281
+ return { ...row, comment_count: comments.length, comments, reactions, reply_to, replies };
4282
+ }
4283
+ async function listNotes(opts) {
4284
+ const db = await getDb();
4285
+ const limit = opts?.limit ?? 50;
4286
+ const offset = opts?.offset ?? 0;
4287
+ const conditions = [];
4288
+ if (opts?.authorUsername) {
4289
+ conditions.push(eq3(users.username, opts.authorUsername));
4290
+ }
4291
+ const rows = await db.select({
4292
+ id: notes.id,
4293
+ author_id: notes.author_id,
4294
+ title: notes.title,
4295
+ slug: notes.slug,
4296
+ content: notes.content,
4297
+ reply_to_id: notes.reply_to_id,
4298
+ created_at: notes.created_at,
4299
+ updated_at: notes.updated_at,
4300
+ author_username: users.username,
4301
+ author_display_name: users.display_name
4302
+ }).from(notes).innerJoin(users, eq3(notes.author_id, users.id)).where(conditions.length > 0 ? and2(...conditions) : void 0).orderBy(desc3(notes.created_at)).limit(limit).offset(offset).all();
4303
+ const noteIds = rows.map((r) => r.id);
4304
+ if (noteIds.length === 0) return [];
4305
+ const commentCounts = await db.select({
4306
+ note_id: noteComments.note_id,
4307
+ count: count()
4308
+ }).from(noteComments).where(inArray(noteComments.note_id, noteIds)).groupBy(noteComments.note_id).all();
4309
+ const countMap = new Map(commentCounts.map((r) => [r.note_id, r.count]));
4310
+ const allReactions = await db.select({
4311
+ note_id: noteReactions.note_id,
4312
+ emoji: noteReactions.emoji,
4313
+ count: count()
4314
+ }).from(noteReactions).where(inArray(noteReactions.note_id, noteIds)).groupBy(noteReactions.note_id, noteReactions.emoji).all();
4315
+ const reactionMap = /* @__PURE__ */ new Map();
4316
+ for (const r of allReactions) {
4317
+ if (!reactionMap.has(r.note_id)) reactionMap.set(r.note_id, []);
4318
+ reactionMap.get(r.note_id).push({ emoji: r.emoji, count: r.count });
4319
+ }
4320
+ const replyToIds = [...new Set(rows.filter((r) => r.reply_to_id).map((r) => r.reply_to_id))];
4321
+ const replyToMap = /* @__PURE__ */ new Map();
4322
+ if (replyToIds.length > 0) {
4323
+ const parents = await db.select({
4324
+ id: notes.id,
4325
+ title: notes.title,
4326
+ slug: notes.slug,
4327
+ author_username: users.username
4328
+ }).from(notes).innerJoin(users, eq3(notes.author_id, users.id)).where(inArray(notes.id, replyToIds)).all();
4329
+ for (const parent of parents) {
4330
+ replyToMap.set(parent.id, {
4331
+ author_username: parent.author_username,
4332
+ slug: parent.slug,
4333
+ title: parent.title
4334
+ });
4335
+ }
4336
+ }
4337
+ return rows.map((r) => {
4338
+ const reactions = reactionMap.get(r.id);
4339
+ const topReactions = reactions ? reactions.sort((a, b) => b.count - a.count).slice(0, 3).map((rx) => ({ ...rx, usernames: [] })) : void 0;
4340
+ return {
4341
+ ...r,
4342
+ comment_count: countMap.get(r.id) ?? 0,
4343
+ reactions: topReactions,
4344
+ reply_to: r.reply_to_id ? replyToMap.get(r.reply_to_id) ?? null : null
4345
+ };
4346
+ });
4347
+ }
4348
+ async function updateNote(authorUsername, slug, updates) {
4349
+ const db = await getDb();
4350
+ const existing = await db.select({ id: notes.id, author_id: notes.author_id }).from(notes).innerJoin(users, eq3(notes.author_id, users.id)).where(and2(eq3(users.username, authorUsername), eq3(notes.slug, slug))).get();
4351
+ if (!existing) return null;
4352
+ const set = { updated_at: sql2`(datetime('now'))` };
4353
+ if (updates.title !== void 0) set.title = updates.title;
4354
+ if (updates.content !== void 0) set.content = updates.content;
4355
+ await db.update(notes).set(set).where(eq3(notes.id, existing.id));
4356
+ return getNote(authorUsername, slug).then(
4357
+ (n) => n ? { ...n, comments: void 0 } : null
4358
+ );
4359
+ }
4360
+ async function deleteNote(authorUsername, slug, authorId) {
4361
+ const db = await getDb();
4362
+ const existing = await db.select({ id: notes.id, author_id: notes.author_id }).from(notes).innerJoin(users, eq3(notes.author_id, users.id)).where(and2(eq3(users.username, authorUsername), eq3(notes.slug, slug))).get();
4363
+ if (!existing || existing.author_id !== authorId) return false;
4364
+ await db.delete(notes).where(eq3(notes.id, existing.id));
4365
+ return true;
4366
+ }
4367
+ async function addComment(noteId, authorId, content) {
4368
+ const db = await getDb();
4369
+ const [row] = await db.insert(noteComments).values({ note_id: noteId, author_id: authorId, content }).returning();
4370
+ const author = await db.select().from(users).where(eq3(users.id, authorId)).get();
4371
+ return {
4372
+ ...row,
4373
+ author_username: author?.username ?? "unknown",
4374
+ author_display_name: author?.display_name ?? null
4375
+ };
4376
+ }
4377
+ async function getComments(noteId) {
4378
+ const db = await getDb();
4379
+ return db.select({
4380
+ id: noteComments.id,
4381
+ note_id: noteComments.note_id,
4382
+ author_id: noteComments.author_id,
4383
+ content: noteComments.content,
4384
+ created_at: noteComments.created_at,
4385
+ author_username: users.username,
4386
+ author_display_name: users.display_name
4387
+ }).from(noteComments).innerJoin(users, eq3(noteComments.author_id, users.id)).where(eq3(noteComments.note_id, noteId)).orderBy(noteComments.created_at).all();
4388
+ }
4389
+ async function deleteComment(commentId, authorId) {
4390
+ const db = await getDb();
4391
+ const existing = await db.select({ id: noteComments.id, author_id: noteComments.author_id }).from(noteComments).where(eq3(noteComments.id, commentId)).get();
4392
+ if (!existing || existing.author_id !== authorId) return false;
4393
+ await db.delete(noteComments).where(eq3(noteComments.id, commentId));
4394
+ return true;
4395
+ }
4396
+ async function toggleReaction(noteId, userId, emoji) {
4397
+ const db = await getDb();
4398
+ const existing = await db.select({ id: noteReactions.id }).from(noteReactions).where(
4399
+ and2(
4400
+ eq3(noteReactions.note_id, noteId),
4401
+ eq3(noteReactions.user_id, userId),
4402
+ eq3(noteReactions.emoji, emoji)
4403
+ )
4404
+ ).get();
4405
+ if (existing) {
4406
+ await db.delete(noteReactions).where(eq3(noteReactions.id, existing.id));
4407
+ return { added: false };
4408
+ }
4409
+ await db.insert(noteReactions).values({ note_id: noteId, user_id: userId, emoji });
4410
+ return { added: true };
4411
+ }
4412
+ async function getReactions(noteId) {
4413
+ const db = await getDb();
4414
+ const rows = await db.select({
4415
+ emoji: noteReactions.emoji,
4416
+ username: users.username
4417
+ }).from(noteReactions).innerJoin(users, eq3(noteReactions.user_id, users.id)).where(eq3(noteReactions.note_id, noteId)).orderBy(noteReactions.emoji).all();
4418
+ const grouped = /* @__PURE__ */ new Map();
4419
+ for (const r of rows) {
4420
+ if (!grouped.has(r.emoji)) grouped.set(r.emoji, []);
4421
+ grouped.get(r.emoji).push(r.username);
4422
+ }
4423
+ return [...grouped.entries()].map(([emoji, usernames]) => ({
4424
+ emoji,
4425
+ count: usernames.length,
4426
+ usernames
4427
+ }));
4428
+ }
4429
+ async function resolveNoteId(authorSlug) {
4430
+ const [author, slug] = authorSlug.split("/", 2);
4431
+ if (!author || !slug) return null;
4432
+ const db = await getDb();
4433
+ const row = await db.select({ id: notes.id }).from(notes).innerJoin(users, eq3(notes.author_id, users.id)).where(and2(eq3(users.username, author), eq3(notes.slug, slug))).get();
4434
+ return row?.id ?? null;
4435
+ }
4436
+
4437
+ // src/web/api/notes.ts
4438
+ var createSchema = z4.object({
4439
+ title: z4.string().min(1).max(200),
4440
+ content: z4.string().min(1),
4441
+ reply_to: z4.string().optional()
4442
+ });
4443
+ var updateSchema = z4.object({
4444
+ title: z4.string().min(1).max(200).optional(),
4445
+ content: z4.string().min(1).optional()
4446
+ });
4447
+ var commentSchema = z4.object({
4448
+ content: z4.string().min(1)
4449
+ });
4450
+ var reactionSchema = z4.object({
4451
+ emoji: z4.string().min(1).max(32)
4452
+ });
4453
+ async function resolveUserId(c) {
4454
+ const user = c.get("user");
4455
+ if (user.id === 0) {
4456
+ const asUser = c.req.query("as");
4457
+ if (!asUser) return null;
4458
+ try {
4459
+ const mindUser = await getOrCreateMindUser(asUser);
4460
+ return { id: mindUser.id, username: mindUser.username };
4461
+ } catch {
4462
+ const brainUser = await getUserByUsername(asUser);
4463
+ if (brainUser) return { id: brainUser.id, username: brainUser.username };
4464
+ return null;
4465
+ }
4466
+ }
4467
+ return { id: user.id, username: user.username };
4468
+ }
4469
+ var app12 = new Hono12().get("/", async (c) => {
4470
+ const author = c.req.query("author");
4471
+ const limit = c.req.query("limit") ? parseInt(c.req.query("limit"), 10) : void 0;
4472
+ const offset = c.req.query("offset") ? parseInt(c.req.query("offset"), 10) : void 0;
4473
+ const result = await listNotes({ authorUsername: author, limit, offset });
4474
+ return c.json(result);
4475
+ }).post("/", zValidator4("json", createSchema), async (c) => {
4476
+ const actor = await resolveUserId(c);
4477
+ if (!actor) return c.json({ error: "Missing ?as=<username> for CLI requests" }, 400);
4478
+ const { title, content, reply_to } = c.req.valid("json");
4479
+ let replyToId;
4480
+ if (reply_to) {
4481
+ const id = await resolveNoteId(reply_to);
4482
+ if (id === null) return c.json({ error: `Reply target not found: ${reply_to}` }, 404);
4483
+ replyToId = id;
4484
+ }
4485
+ const note = await createNote(actor.id, title, content, replyToId);
4486
+ const replyInfo = reply_to ? ` (in reply to ${reply_to})` : "";
4487
+ announceToSystem(`${actor.username} published a note: ${title}${replyInfo}`).catch(() => {
4488
+ });
4489
+ return c.json(note, 201);
4490
+ }).get("/:author/:slug", async (c) => {
4491
+ const { author, slug } = c.req.param();
4492
+ const note = await getNote(author, slug);
4493
+ if (!note) return c.json({ error: "Note not found" }, 404);
4494
+ return c.json(note);
4495
+ }).put("/:author/:slug", zValidator4("json", updateSchema), async (c) => {
4496
+ const actor = await resolveUserId(c);
4497
+ if (!actor) return c.json({ error: "Missing ?as=<username> for CLI requests" }, 400);
4498
+ const { author, slug } = c.req.param();
4499
+ if (actor.username !== author) return c.json({ error: "Forbidden" }, 403);
4500
+ const updates = c.req.valid("json");
4501
+ const note = await updateNote(author, slug, updates);
4502
+ if (!note) return c.json({ error: "Note not found" }, 404);
4503
+ return c.json(note);
4504
+ }).delete("/:author/:slug", async (c) => {
4505
+ const actor = await resolveUserId(c);
4506
+ if (!actor) return c.json({ error: "Missing ?as=<username> for CLI requests" }, 400);
4507
+ const { author, slug } = c.req.param();
4508
+ const deleted = await deleteNote(author, slug, actor.id);
4509
+ if (!deleted) return c.json({ error: "Note not found or not authorized" }, 404);
4510
+ return c.json({ ok: true });
4511
+ }).post("/:author/:slug/reactions", zValidator4("json", reactionSchema), async (c) => {
4512
+ const actor = await resolveUserId(c);
4513
+ if (!actor) return c.json({ error: "Missing ?as=<username> for CLI requests" }, 400);
4514
+ const { author, slug } = c.req.param();
4515
+ const note = await getNote(author, slug);
4516
+ if (!note) return c.json({ error: "Note not found" }, 404);
4517
+ const { emoji } = c.req.valid("json");
4518
+ const result = await toggleReaction(note.id, actor.id, emoji);
4519
+ const reactions = await getReactions(note.id);
4520
+ return c.json({ ...result, reactions });
4521
+ }).post("/:author/:slug/comments", zValidator4("json", commentSchema), async (c) => {
4522
+ const actor = await resolveUserId(c);
4523
+ if (!actor) return c.json({ error: "Missing ?as=<username> for CLI requests" }, 400);
4524
+ const { author, slug } = c.req.param();
4525
+ const note = await getNote(author, slug);
4526
+ if (!note) return c.json({ error: "Note not found" }, 404);
4527
+ const { content } = c.req.valid("json");
4528
+ const comment = await addComment(note.id, actor.id, content);
4529
+ return c.json(comment, 201);
4530
+ }).delete("/:author/:slug/comments/:id", async (c) => {
4531
+ const actor = await resolveUserId(c);
4532
+ if (!actor) return c.json({ error: "Missing ?as=<username> for CLI requests" }, 400);
4533
+ const commentId = parseInt(c.req.param("id"), 10);
4534
+ if (Number.isNaN(commentId)) return c.json({ error: "Invalid comment ID" }, 400);
4535
+ const deleted = await deleteComment(commentId, actor.id);
4536
+ if (!deleted) return c.json({ error: "Comment not found or not authorized" }, 404);
4537
+ return c.json({ ok: true });
4538
+ });
4539
+ var notes_default = app12;
4540
+
4132
4541
  // src/web/api/pages.ts
4133
4542
  import { readFile as readFile2, stat as stat2 } from "fs/promises";
4134
4543
  import { extname as extname3, resolve as resolve13 } from "path";
4135
- import { Hono as Hono12 } from "hono";
4544
+ import { Hono as Hono13 } from "hono";
4136
4545
  var MIME_TYPES = {
4137
4546
  ".html": "text/html",
4138
4547
  ".js": "application/javascript",
@@ -4149,7 +4558,7 @@ var MIME_TYPES = {
4149
4558
  ".txt": "text/plain",
4150
4559
  ".xml": "application/xml"
4151
4560
  };
4152
- var app12 = new Hono12().get("/:name/*", async (c) => {
4561
+ var app13 = new Hono13().get("/:name/*", async (c) => {
4153
4562
  const name = c.req.param("name");
4154
4563
  let pagesRoot;
4155
4564
  if (name === "_system") {
@@ -4179,14 +4588,14 @@ var app12 = new Hono12().get("/:name/*", async (c) => {
4179
4588
  }
4180
4589
  return c.text("Not found", 404);
4181
4590
  });
4182
- var pages_default = app12;
4591
+ var pages_default = app13;
4183
4592
 
4184
4593
  // src/web/api/prompts.ts
4185
- import { zValidator as zValidator4 } from "@hono/zod-validator";
4186
- import { eq as eq3, sql as sql2 } from "drizzle-orm";
4187
- import { Hono as Hono13 } from "hono";
4188
- import { z as z4 } from "zod";
4189
- var app13 = new Hono13().get("/", async (c) => {
4594
+ import { zValidator as zValidator5 } from "@hono/zod-validator";
4595
+ import { eq as eq4, sql as sql3 } from "drizzle-orm";
4596
+ import { Hono as Hono14 } from "hono";
4597
+ import { z as z5 } from "zod";
4598
+ var app14 = new Hono14().get("/", async (c) => {
4190
4599
  let rows;
4191
4600
  try {
4192
4601
  const db = await getDb();
@@ -4209,16 +4618,16 @@ var app13 = new Hono13().get("/", async (c) => {
4209
4618
  };
4210
4619
  });
4211
4620
  return c.json(prompts);
4212
- }).put("/:key", requireAdmin, zValidator4("json", z4.object({ content: z4.string() })), async (c) => {
4621
+ }).put("/:key", requireAdmin, zValidator5("json", z5.object({ content: z5.string() })), async (c) => {
4213
4622
  const key = c.req.param("key");
4214
4623
  if (!PROMPT_KEYS.includes(key)) {
4215
4624
  return c.json({ error: "Unknown prompt key" }, 404);
4216
4625
  }
4217
4626
  const { content } = c.req.valid("json");
4218
4627
  const db = await getDb();
4219
- await db.insert(systemPrompts).values({ key, content, updated_at: sql2`(datetime('now'))` }).onConflictDoUpdate({
4628
+ await db.insert(systemPrompts).values({ key, content, updated_at: sql3`(datetime('now'))` }).onConflictDoUpdate({
4220
4629
  target: systemPrompts.key,
4221
- set: { content, updated_at: sql2`(datetime('now'))` }
4630
+ set: { content, updated_at: sql3`(datetime('now'))` }
4222
4631
  });
4223
4632
  return c.json({ ok: true });
4224
4633
  }).delete("/:key", requireAdmin, async (c) => {
@@ -4227,15 +4636,15 @@ var app13 = new Hono13().get("/", async (c) => {
4227
4636
  return c.json({ error: "Unknown prompt key" }, 404);
4228
4637
  }
4229
4638
  const db = await getDb();
4230
- await db.delete(systemPrompts).where(eq3(systemPrompts.key, key));
4639
+ await db.delete(systemPrompts).where(eq4(systemPrompts.key, key));
4231
4640
  return c.json({ ok: true });
4232
4641
  });
4233
- var prompts_default = app13;
4642
+ var prompts_default = app14;
4234
4643
 
4235
4644
  // src/web/api/public-files.ts
4236
4645
  import { readdir as readdir2, readFile as readFile3, stat as stat3 } from "fs/promises";
4237
4646
  import { extname as extname4, resolve as resolve14 } from "path";
4238
- import { Hono as Hono14 } from "hono";
4647
+ import { Hono as Hono15 } from "hono";
4239
4648
  var MAX_FILE_SIZE = 50 * 1024 * 1024;
4240
4649
  function resolvePublicRoot(name) {
4241
4650
  if (name === "_system") return resolve14(voluteHome(), "shared");
@@ -4276,7 +4685,7 @@ async function listDir(dirPath) {
4276
4685
  type: e.isDirectory() ? "directory" : "file"
4277
4686
  }));
4278
4687
  }
4279
- var app14 = new Hono14().get("/:name/", async (c) => {
4688
+ var app15 = new Hono15().get("/:name/", async (c) => {
4280
4689
  const name = c.req.param("name");
4281
4690
  const publicRoot = resolvePublicRoot(name);
4282
4691
  if (!publicRoot) return c.json({ error: "Not found" }, 404);
@@ -4319,11 +4728,11 @@ var app14 = new Hono14().get("/:name/", async (c) => {
4319
4728
  }
4320
4729
  return c.text("Not found", 404);
4321
4730
  });
4322
- var public_files_default = app14;
4731
+ var public_files_default = app15;
4323
4732
 
4324
4733
  // src/web/api/schedules.ts
4325
4734
  import { CronExpressionParser } from "cron-parser";
4326
- import { Hono as Hono15 } from "hono";
4735
+ import { Hono as Hono16 } from "hono";
4327
4736
  var slog = logger_default.child("schedules");
4328
4737
  function readSchedules(name) {
4329
4738
  return readVoluteConfig(mindDir(name))?.schedules ?? [];
@@ -4340,7 +4749,7 @@ function writeSchedules(name, schedules) {
4340
4749
  data: { schedules }
4341
4750
  });
4342
4751
  }
4343
- var app15 = new Hono15().get("/:name/schedules", (c) => {
4752
+ var app16 = new Hono16().get("/:name/schedules", (c) => {
4344
4753
  const name = c.req.param("name");
4345
4754
  if (!findMind(name)) return c.json({ error: "Mind not found" }, 404);
4346
4755
  return c.json(readSchedules(name));
@@ -4373,6 +4782,7 @@ var app15 = new Hono15().get("/:name/schedules", (c) => {
4373
4782
  const schedule = { id, cron: body.cron, enabled: body.enabled ?? true };
4374
4783
  if (body.message) schedule.message = body.message;
4375
4784
  if (body.script) schedule.script = body.script;
4785
+ if (body.channel) schedule.channel = body.channel;
4376
4786
  schedules.push(schedule);
4377
4787
  writeSchedules(name, schedules);
4378
4788
  return c.json({ ok: true, id }, 201);
@@ -4404,6 +4814,7 @@ var app15 = new Hono15().get("/:name/schedules", (c) => {
4404
4814
  delete schedules[idx].message;
4405
4815
  }
4406
4816
  if (body.enabled !== void 0) schedules[idx].enabled = body.enabled;
4817
+ if (body.channel !== void 0) schedules[idx].channel = body.channel || void 0;
4407
4818
  writeSchedules(name, schedules);
4408
4819
  return c.json({ ok: true });
4409
4820
  }).delete("/:name/schedules/:id", requireAdmin, (c) => {
@@ -4443,11 +4854,11 @@ var app15 = new Hono15().get("/:name/schedules", (c) => {
4443
4854
  return c.json({ error: "Failed to reach mind" }, 502);
4444
4855
  }
4445
4856
  });
4446
- var schedules_default = app15;
4857
+ var schedules_default = app16;
4447
4858
 
4448
4859
  // src/web/api/shared.ts
4449
- import { Hono as Hono16 } from "hono";
4450
- var app16 = new Hono16().post("/:name/shared/merge", requireAdmin, async (c) => {
4860
+ import { Hono as Hono17 } from "hono";
4861
+ var app17 = new Hono17().post("/:name/shared/merge", requireAdmin, async (c) => {
4451
4862
  const name = c.req.param("name");
4452
4863
  const entry = findMind(name);
4453
4864
  if (!entry) return c.json({ error: "Mind not found" }, 404);
@@ -4496,15 +4907,15 @@ var app16 = new Hono16().post("/:name/shared/merge", requireAdmin, async (c) =>
4496
4907
  return c.json({ error: err instanceof Error ? err.message : "Failed to get status" }, 500);
4497
4908
  }
4498
4909
  });
4499
- var shared_default = app16;
4910
+ var shared_default = app17;
4500
4911
 
4501
4912
  // src/web/api/skills.ts
4502
4913
  import { existsSync as existsSync11, mkdtempSync, readdirSync as readdirSync5, rmSync as rmSync5 } from "fs";
4503
4914
  import { tmpdir } from "os";
4504
4915
  import { join as join2, resolve as resolve15 } from "path";
4505
4916
  import AdmZip from "adm-zip";
4506
- import { Hono as Hono17 } from "hono";
4507
- var app17 = new Hono17().get("/", async (c) => {
4917
+ import { Hono as Hono18 } from "hono";
4918
+ var app18 = new Hono18().get("/", async (c) => {
4508
4919
  const skills = await listSharedSkills();
4509
4920
  return c.json(skills);
4510
4921
  }).get("/:id", async (c) => {
@@ -4569,15 +4980,15 @@ var app17 = new Hono17().get("/", async (c) => {
4569
4980
  }
4570
4981
  return c.json({ ok: true });
4571
4982
  });
4572
- var skills_default = app17;
4983
+ var skills_default = app18;
4573
4984
 
4574
4985
  // src/web/api/system.ts
4575
- import { zValidator as zValidator5 } from "@hono/zod-validator";
4576
- import { Hono as Hono18 } from "hono";
4986
+ import { zValidator as zValidator6 } from "@hono/zod-validator";
4987
+ import { Hono as Hono19 } from "hono";
4577
4988
  import { streamSSE as streamSSE3 } from "hono/streaming";
4578
- import { z as z5 } from "zod";
4989
+ import { z as z6 } from "zod";
4579
4990
  var DEFAULT_API_URL = "https://volute.systems";
4580
- var app18 = new Hono18().post("/restart", requireAdmin, (c) => {
4991
+ var app19 = new Hono19().post("/restart", requireAdmin, (c) => {
4581
4992
  setTimeout(() => process.exit(1), 200);
4582
4993
  return c.json({ ok: true });
4583
4994
  }).post("/stop", requireAdmin, (c) => {
@@ -4607,7 +5018,7 @@ var app18 = new Hono18().post("/restart", requireAdmin, (c) => {
4607
5018
  }).post(
4608
5019
  "/register",
4609
5020
  requireAdmin,
4610
- zValidator5("json", z5.object({ name: z5.string().min(1) })),
5021
+ zValidator6("json", z6.object({ name: z6.string().min(1) })),
4611
5022
  async (c) => {
4612
5023
  const existing = readSystemsConfig();
4613
5024
  if (existing) {
@@ -4646,7 +5057,7 @@ var app18 = new Hono18().post("/restart", requireAdmin, (c) => {
4646
5057
  ).post(
4647
5058
  "/login",
4648
5059
  requireAdmin,
4649
- zValidator5("json", z5.object({ key: z5.string().min(1) })),
5060
+ zValidator6("json", z6.object({ key: z6.string().min(1) })),
4650
5061
  async (c) => {
4651
5062
  const existing = readSystemsConfig();
4652
5063
  if (existing) {
@@ -4683,18 +5094,18 @@ var app18 = new Hono18().post("/restart", requireAdmin, (c) => {
4683
5094
  deleteSystemsConfig();
4684
5095
  return c.json({ ok: true });
4685
5096
  });
4686
- var system_default = app18;
5097
+ var system_default = app19;
4687
5098
 
4688
5099
  // src/web/api/typing.ts
4689
- import { zValidator as zValidator6 } from "@hono/zod-validator";
4690
- import { Hono as Hono19 } from "hono";
4691
- import { z as z6 } from "zod";
4692
- var typingSchema = z6.object({
4693
- channel: z6.string().min(1),
4694
- sender: z6.string().min(1),
4695
- active: z6.boolean()
5100
+ import { zValidator as zValidator7 } from "@hono/zod-validator";
5101
+ import { Hono as Hono20 } from "hono";
5102
+ import { z as z7 } from "zod";
5103
+ var typingSchema = z7.object({
5104
+ channel: z7.string().min(1),
5105
+ sender: z7.string().min(1),
5106
+ active: z7.boolean()
4696
5107
  });
4697
- var app19 = new Hono19().post("/:name/typing", zValidator6("json", typingSchema), (c) => {
5108
+ var app20 = new Hono20().post("/:name/typing", zValidator7("json", typingSchema), (c) => {
4698
5109
  const { channel, sender, active } = c.req.valid("json");
4699
5110
  const map = getTypingMap();
4700
5111
  if (active) {
@@ -4705,7 +5116,7 @@ var app19 = new Hono19().post("/:name/typing", zValidator6("json", typingSchema)
4705
5116
  const volutePrefix = "volute:";
4706
5117
  if (channel.startsWith(volutePrefix)) {
4707
5118
  const conversationId = channel.slice(volutePrefix.length);
4708
- publish2(conversationId, { type: "typing", senders: map.get(channel) });
5119
+ publish(conversationId, { type: "typing", senders: map.get(channel) });
4709
5120
  }
4710
5121
  return c.json({ ok: true });
4711
5122
  }).get("/:name/typing", (c) => {
@@ -4716,13 +5127,13 @@ var app19 = new Hono19().post("/:name/typing", zValidator6("json", typingSchema)
4716
5127
  const map = getTypingMap();
4717
5128
  return c.json({ typing: map.get(channel) });
4718
5129
  });
4719
- var typing_default = app19;
5130
+ var typing_default = app20;
4720
5131
 
4721
5132
  // src/web/api/update.ts
4722
5133
  import { spawn as spawn2 } from "child_process";
4723
- import { Hono as Hono20 } from "hono";
5134
+ import { Hono as Hono21 } from "hono";
4724
5135
  var bin;
4725
- var app20 = new Hono20().get("/update", async (c) => {
5136
+ var app21 = new Hono21().get("/update", async (c) => {
4726
5137
  const result = await checkForUpdate();
4727
5138
  return c.json(result);
4728
5139
  }).post("/update", requireAdmin, async (c) => {
@@ -4737,21 +5148,21 @@ var app20 = new Hono20().get("/update", async (c) => {
4737
5148
  child.unref();
4738
5149
  return c.json({ ok: true, message: "Updating..." });
4739
5150
  });
4740
- var update_default = app20;
5151
+ var update_default = app21;
4741
5152
 
4742
5153
  // src/web/api/v1/chat.ts
4743
- import { zValidator as zValidator7 } from "@hono/zod-validator";
4744
- import { Hono as Hono21 } from "hono";
5154
+ import { zValidator as zValidator8 } from "@hono/zod-validator";
5155
+ import { Hono as Hono22 } from "hono";
4745
5156
  import { streamSSE as streamSSE4 } from "hono/streaming";
4746
- import { z as z7 } from "zod";
5157
+ import { z as z8 } from "zod";
4747
5158
  async function fanOutToMinds(opts) {
4748
5159
  const participants = await getParticipants(opts.conversationId);
4749
5160
  const mindParticipants = participants.filter((p) => p.userType === "mind");
4750
5161
  const participantNames = participants.map((p) => p.username);
4751
5162
  const isDM = opts.isDM ?? participants.length === 2;
4752
5163
  const channelEntryType = opts.channelEntryType ?? (isDM ? "dm" : "group");
4753
- const { getMindManager: getMindManager2 } = await import("./mind-manager-4NDNAYAB.js");
4754
- const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
5164
+ const { getMindManager: getMindManager2 } = await import("./mind-manager-VVK67AY3.js");
5165
+ const { getSleepManagerIfReady } = await import("./sleep-manager-EE4NRN2Q.js");
4755
5166
  const manager = getMindManager2();
4756
5167
  const sm = getSleepManagerIfReady();
4757
5168
  const targetMinds = mindParticipants.map((ap) => {
@@ -4800,18 +5211,18 @@ async function fanOutToMinds(opts) {
4800
5211
  });
4801
5212
  }
4802
5213
  }
4803
- var mindChatSchema = z7.object({
4804
- message: z7.string().optional(),
4805
- conversationId: z7.string().optional(),
4806
- sender: z7.string().optional(),
4807
- images: z7.array(z7.object({ media_type: z7.string(), data: z7.string() })).optional()
5214
+ var mindChatSchema = z8.object({
5215
+ message: z8.string().optional(),
5216
+ conversationId: z8.string().optional(),
5217
+ sender: z8.string().optional(),
5218
+ images: z8.array(z8.object({ media_type: z8.string(), data: z8.string() })).optional()
4808
5219
  });
4809
- var unifiedChatSchema = z7.object({
4810
- message: z7.string().optional(),
4811
- conversationId: z7.string(),
4812
- images: z7.array(z7.object({ media_type: z7.string(), data: z7.string() })).optional()
5220
+ var unifiedChatSchema = z8.object({
5221
+ message: z8.string().optional(),
5222
+ conversationId: z8.string(),
5223
+ images: z8.array(z8.object({ media_type: z8.string(), data: z8.string() })).optional()
4813
5224
  });
4814
- var app21 = new Hono21().use("*", authMiddleware).post("/minds/:name/chat", zValidator7("json", mindChatSchema), async (c) => {
5225
+ var app22 = new Hono22().use("*", authMiddleware).post("/minds/:name/chat", zValidator8("json", mindChatSchema), async (c) => {
4815
5226
  const name = c.req.param("name");
4816
5227
  const [baseName] = name.split("@", 2);
4817
5228
  const entry = findMind(baseName);
@@ -4884,7 +5295,7 @@ var app21 = new Hono21().use("*", authMiddleware).post("/minds/:name/chat", zVal
4884
5295
  return c.json({ error: "Conversation not found" }, 404);
4885
5296
  }
4886
5297
  return streamSSE4(c, async (stream) => {
4887
- const unsubscribe = subscribe3(conversationId, (event) => {
5298
+ const unsubscribe = subscribe2(conversationId, (event) => {
4888
5299
  stream.writeSSE({ data: JSON.stringify(event) }).catch((err) => {
4889
5300
  if (!stream.aborted) logger_default.error("[v1-chat] SSE write error:", logger_default.errorData(err));
4890
5301
  });
@@ -4902,7 +5313,7 @@ var app21 = new Hono21().use("*", authMiddleware).post("/minds/:name/chat", zVal
4902
5313
  });
4903
5314
  });
4904
5315
  });
4905
- }).post("/chat", zValidator7("json", unifiedChatSchema), async (c) => {
5316
+ }).post("/chat", zValidator8("json", unifiedChatSchema), async (c) => {
4906
5317
  const user = c.get("user");
4907
5318
  const body = c.req.valid("json");
4908
5319
  if (!body.message && (!body.images || body.images.length === 0)) {
@@ -4934,17 +5345,17 @@ var app21 = new Hono21().use("*", authMiddleware).post("/minds/:name/chat", zVal
4934
5345
  });
4935
5346
  return c.json({ ok: true, conversationId: body.conversationId });
4936
5347
  });
4937
- var chat_default = app21;
5348
+ var chat_default = app22;
4938
5349
 
4939
5350
  // src/web/api/v1/conversations.ts
4940
- import { zValidator as zValidator8 } from "@hono/zod-validator";
4941
- import { Hono as Hono22 } from "hono";
4942
- import { z as z8 } from "zod";
4943
- var createSchema = z8.object({
4944
- title: z8.string().optional(),
4945
- participantNames: z8.array(z8.string()).min(1)
5351
+ import { zValidator as zValidator9 } from "@hono/zod-validator";
5352
+ import { Hono as Hono23 } from "hono";
5353
+ import { z as z9 } from "zod";
5354
+ var createSchema2 = z9.object({
5355
+ title: z9.string().optional(),
5356
+ participantNames: z9.array(z9.string()).min(1)
4946
5357
  });
4947
- var app22 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
5358
+ var app23 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
4948
5359
  const user = c.get("user");
4949
5360
  const convs = await listConversationsWithParticipants(user.id);
4950
5361
  return c.json(convs);
@@ -4975,7 +5386,7 @@ var app22 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
4975
5386
  }
4976
5387
  const participants = await getParticipants(id);
4977
5388
  return c.json(participants);
4978
- }).post("/", zValidator8("json", createSchema), async (c) => {
5389
+ }).post("/", zValidator9("json", createSchema2), async (c) => {
4979
5390
  const user = c.get("user");
4980
5391
  const body = c.req.valid("json");
4981
5392
  const participantIds = /* @__PURE__ */ new Set();
@@ -5021,30 +5432,30 @@ var app22 = new Hono22().use("*", authMiddleware).get("/", async (c) => {
5021
5432
  if (!deleted) return c.json({ error: "Conversation not found" }, 404);
5022
5433
  return c.json({ ok: true });
5023
5434
  });
5024
- var conversations_default = app22;
5435
+ var conversations_default = app23;
5025
5436
 
5026
5437
  // src/web/api/v1/events.ts
5027
- import { desc as desc3 } from "drizzle-orm";
5028
- import { Hono as Hono23 } from "hono";
5438
+ import { desc as desc4 } from "drizzle-orm";
5439
+ import { Hono as Hono24 } from "hono";
5029
5440
  import { streamSSE as streamSSE5 } from "hono/streaming";
5030
5441
 
5031
5442
  // src/lib/events/brain-presence.ts
5032
5443
  var connections = /* @__PURE__ */ new Map();
5033
5444
  function addConnection(username) {
5034
- const count = connections.get(username) ?? 0;
5035
- connections.set(username, count + 1);
5036
- if (count === 0) {
5445
+ const count2 = connections.get(username) ?? 0;
5446
+ connections.set(username, count2 + 1);
5447
+ if (count2 === 0) {
5037
5448
  broadcast({ type: "brain_online", mind: username, summary: `${username} connected` });
5038
5449
  }
5039
5450
  }
5040
5451
  function removeConnection(username) {
5041
- const count = connections.get(username);
5042
- if (count == null) return;
5043
- if (count <= 1) {
5452
+ const count2 = connections.get(username);
5453
+ if (count2 == null) return;
5454
+ if (count2 <= 1) {
5044
5455
  connections.delete(username);
5045
5456
  broadcast({ type: "brain_offline", mind: username, summary: `${username} disconnected` });
5046
5457
  } else {
5047
- connections.set(username, count - 1);
5458
+ connections.set(username, count2 - 1);
5048
5459
  }
5049
5460
  }
5050
5461
  function getOnlineBrains() {
@@ -5072,7 +5483,7 @@ function getEventsSince(sinceId) {
5072
5483
  }
5073
5484
 
5074
5485
  // src/web/api/v1/events.ts
5075
- var app23 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
5486
+ var app24 = new Hono24().use("*", authMiddleware).get("/", async (c) => {
5076
5487
  const user = c.get("user");
5077
5488
  const since = c.req.query("since");
5078
5489
  const sinceId = since ? Number(since) : 0;
@@ -5095,7 +5506,7 @@ var app23 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
5095
5506
  let recentActivity = [];
5096
5507
  try {
5097
5508
  const db = await getDb();
5098
- recentActivity = await db.select().from(activity).orderBy(desc3(activity.created_at)).limit(50);
5509
+ recentActivity = await db.select().from(activity).orderBy(desc4(activity.created_at)).limit(50);
5099
5510
  recentActivity = recentActivity.map((row) => ({
5100
5511
  ...row,
5101
5512
  metadata: row.metadata ? JSON.parse(row.metadata) : null
@@ -5148,7 +5559,7 @@ var app23 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
5148
5559
  });
5149
5560
  cleanups.push(unsubActivity);
5150
5561
  for (const conv of conversations2) {
5151
- const unsubConv = subscribe3(conv.id, (event) => {
5562
+ const unsubConv = subscribe2(conv.id, (event) => {
5152
5563
  const data = { event: "conversation", conversationId: conv.id, ...event };
5153
5564
  const eventId = bufferEvent(data);
5154
5565
  stream.writeSSE({
@@ -5179,12 +5590,12 @@ var app23 = new Hono23().use("*", authMiddleware).get("/", async (c) => {
5179
5590
  }
5180
5591
  });
5181
5592
  });
5182
- var events_default = app23;
5593
+ var events_default = app24;
5183
5594
 
5184
5595
  // src/web/api/variants.ts
5185
5596
  import { existsSync as existsSync12, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
5186
5597
  import { resolve as resolve17 } from "path";
5187
- import { Hono as Hono24 } from "hono";
5598
+ import { Hono as Hono25 } from "hono";
5188
5599
 
5189
5600
  // src/lib/spawn-server.ts
5190
5601
  import { spawn as spawn3 } from "child_process";
@@ -5300,7 +5711,7 @@ async function verify2(port) {
5300
5711
  }
5301
5712
 
5302
5713
  // src/web/api/variants.ts
5303
- var app24 = new Hono24().get("/:name/variants", async (c) => {
5714
+ var app25 = new Hono25().get("/:name/variants", async (c) => {
5304
5715
  const name = c.req.param("name");
5305
5716
  const entry = findMind(name);
5306
5717
  if (!entry) return c.json({ error: "Mind not found" }, 404);
@@ -5516,19 +5927,19 @@ var app24 = new Hono24().get("/:name/variants", async (c) => {
5516
5927
  await cleanupVariant(mindName, variantName, projectRoot, variant.path, { stop: true });
5517
5928
  return c.json({ ok: true });
5518
5929
  });
5519
- var variants_default = app24;
5930
+ var variants_default = app25;
5520
5931
 
5521
5932
  // src/web/api/volute/channels.ts
5522
- import { zValidator as zValidator9 } from "@hono/zod-validator";
5523
- import { Hono as Hono25 } from "hono";
5524
- import { z as z9 } from "zod";
5525
- var createSchema2 = z9.object({
5526
- name: z9.string().min(1).max(50).regex(/^[a-z0-9][a-z0-9-]*$/, "Channel names must be lowercase alphanumeric with hyphens")
5933
+ import { zValidator as zValidator10 } from "@hono/zod-validator";
5934
+ import { Hono as Hono26 } from "hono";
5935
+ import { z as z10 } from "zod";
5936
+ var createSchema3 = z10.object({
5937
+ name: z10.string().min(1).max(50).regex(/^[a-z0-9][a-z0-9-]*$/, "Channel names must be lowercase alphanumeric with hyphens")
5527
5938
  });
5528
- var inviteSchema = z9.object({
5529
- username: z9.string().min(1)
5939
+ var inviteSchema = z10.object({
5940
+ username: z10.string().min(1)
5530
5941
  });
5531
- var app25 = new Hono25().get("/", async (c) => {
5942
+ var app26 = new Hono26().get("/", async (c) => {
5532
5943
  const user = c.get("user");
5533
5944
  const channels = await listChannels();
5534
5945
  const results = await Promise.all(
@@ -5539,7 +5950,7 @@ var app25 = new Hono25().get("/", async (c) => {
5539
5950
  })
5540
5951
  );
5541
5952
  return c.json(results);
5542
- }).post("/", zValidator9("json", createSchema2), async (c) => {
5953
+ }).post("/", zValidator10("json", createSchema3), async (c) => {
5543
5954
  const user = c.get("user");
5544
5955
  const body = c.req.valid("json");
5545
5956
  try {
@@ -5572,7 +5983,7 @@ var app25 = new Hono25().get("/", async (c) => {
5572
5983
  if (!ch) return c.json({ error: "Channel not found" }, 404);
5573
5984
  const participants = await getParticipants(ch.id);
5574
5985
  return c.json(participants);
5575
- }).post("/:name/invite", zValidator9("json", inviteSchema), async (c) => {
5986
+ }).post("/:name/invite", zValidator10("json", inviteSchema), async (c) => {
5576
5987
  const name = c.req.param("name");
5577
5988
  const inviter = c.get("user");
5578
5989
  const { username } = c.req.valid("json");
@@ -5592,21 +6003,21 @@ var app25 = new Hono25().get("/", async (c) => {
5592
6003
  ]);
5593
6004
  return c.json({ ok: true });
5594
6005
  });
5595
- var channels_default2 = app25;
6006
+ var channels_default2 = app26;
5596
6007
 
5597
6008
  // src/web/api/volute/chat.ts
5598
- import { zValidator as zValidator10 } from "@hono/zod-validator";
5599
- import { Hono as Hono26 } from "hono";
6009
+ import { zValidator as zValidator11 } from "@hono/zod-validator";
6010
+ import { Hono as Hono27 } from "hono";
5600
6011
  import { streamSSE as streamSSE6 } from "hono/streaming";
5601
- import { z as z10 } from "zod";
6012
+ import { z as z11 } from "zod";
5602
6013
  async function fanOutToMinds2(opts) {
5603
6014
  const participants = await getParticipants(opts.conversationId);
5604
6015
  const mindParticipants = participants.filter((p) => p.userType === "mind");
5605
6016
  const participantNames = participants.map((p) => p.username);
5606
6017
  const isDM = opts.isDM ?? participants.length === 2;
5607
6018
  const channelEntryType = opts.channelEntryType ?? (isDM ? "dm" : "group");
5608
- const { getMindManager: getMindManager2 } = await import("./mind-manager-4NDNAYAB.js");
5609
- const { getSleepManagerIfReady } = await import("./sleep-manager-RKTFZPD3.js");
6019
+ const { getMindManager: getMindManager2 } = await import("./mind-manager-VVK67AY3.js");
6020
+ const { getSleepManagerIfReady } = await import("./sleep-manager-EE4NRN2Q.js");
5610
6021
  const manager = getMindManager2();
5611
6022
  const sm = getSleepManagerIfReady();
5612
6023
  const targetMinds = mindParticipants.map((ap) => {
@@ -5654,18 +6065,18 @@ async function fanOutToMinds2(opts) {
5654
6065
  });
5655
6066
  }
5656
6067
  }
5657
- var chatSchema = z10.object({
5658
- message: z10.string().optional(),
5659
- conversationId: z10.string().optional(),
5660
- sender: z10.string().optional(),
5661
- images: z10.array(
5662
- z10.object({
5663
- media_type: z10.string(),
5664
- data: z10.string()
6068
+ var chatSchema = z11.object({
6069
+ message: z11.string().optional(),
6070
+ conversationId: z11.string().optional(),
6071
+ sender: z11.string().optional(),
6072
+ images: z11.array(
6073
+ z11.object({
6074
+ media_type: z11.string(),
6075
+ data: z11.string()
5665
6076
  })
5666
6077
  ).optional()
5667
6078
  });
5668
- var app26 = new Hono26().post("/:name/chat", zValidator10("json", chatSchema), async (c) => {
6079
+ var app27 = new Hono27().post("/:name/chat", zValidator11("json", chatSchema), async (c) => {
5669
6080
  const name = c.req.param("name");
5670
6081
  const [baseName] = name.split("@", 2);
5671
6082
  const entry = findMind(baseName);
@@ -5742,7 +6153,7 @@ var app26 = new Hono26().post("/:name/chat", zValidator10("json", chatSchema), a
5742
6153
  return c.json({ error: "Conversation not found" }, 404);
5743
6154
  }
5744
6155
  return streamSSE6(c, async (stream) => {
5745
- const unsubscribe = subscribe3(conversationId, (event) => {
6156
+ const unsubscribe = subscribe2(conversationId, (event) => {
5746
6157
  stream.writeSSE({ data: JSON.stringify(event) }).catch((err) => {
5747
6158
  if (!stream.aborted) console.error("[chat] SSE write error:", err);
5748
6159
  });
@@ -5761,14 +6172,14 @@ var app26 = new Hono26().post("/:name/chat", zValidator10("json", chatSchema), a
5761
6172
  });
5762
6173
  });
5763
6174
  });
5764
- var unifiedChatSchema2 = z10.object({
5765
- message: z10.string().optional(),
5766
- conversationId: z10.string(),
5767
- images: z10.array(z10.object({ media_type: z10.string(), data: z10.string() })).optional()
6175
+ var unifiedChatSchema2 = z11.object({
6176
+ message: z11.string().optional(),
6177
+ conversationId: z11.string(),
6178
+ images: z11.array(z11.object({ media_type: z11.string(), data: z11.string() })).optional()
5768
6179
  });
5769
- var unifiedChatApp = new Hono26().post(
6180
+ var unifiedChatApp = new Hono27().post(
5770
6181
  "/chat",
5771
- zValidator10("json", unifiedChatSchema2),
6182
+ zValidator11("json", unifiedChatSchema2),
5772
6183
  async (c) => {
5773
6184
  const user = c.get("user");
5774
6185
  const body = c.req.valid("json");
@@ -5802,18 +6213,18 @@ var unifiedChatApp = new Hono26().post(
5802
6213
  return c.json({ ok: true, conversationId: body.conversationId });
5803
6214
  }
5804
6215
  );
5805
- var chat_default2 = app26;
6216
+ var chat_default2 = app27;
5806
6217
 
5807
6218
  // src/web/api/volute/conversations.ts
5808
- import { zValidator as zValidator11 } from "@hono/zod-validator";
5809
- import { Hono as Hono27 } from "hono";
5810
- import { z as z11 } from "zod";
5811
- var createConvSchema = z11.object({
5812
- title: z11.string().optional(),
5813
- participantIds: z11.array(z11.number()).optional(),
5814
- participantNames: z11.array(z11.string()).optional()
6219
+ import { zValidator as zValidator12 } from "@hono/zod-validator";
6220
+ import { Hono as Hono28 } from "hono";
6221
+ import { z as z12 } from "zod";
6222
+ var createConvSchema = z12.object({
6223
+ title: z12.string().optional(),
6224
+ participantIds: z12.array(z12.number()).optional(),
6225
+ participantNames: z12.array(z12.string()).optional()
5815
6226
  });
5816
- var app27 = new Hono27().get("/:name/conversations", async (c) => {
6227
+ var app28 = new Hono28().get("/:name/conversations", async (c) => {
5817
6228
  const name = c.req.param("name");
5818
6229
  const user = c.get("user");
5819
6230
  let lookupId = user.id;
@@ -5824,7 +6235,7 @@ var app27 = new Hono27().get("/:name/conversations", async (c) => {
5824
6235
  const all = await listConversationsForUser(lookupId);
5825
6236
  const convs = all.filter((c2) => c2.mind_name === name || c2.type === "channel");
5826
6237
  return c.json(convs);
5827
- }).post("/:name/conversations", zValidator11("json", createConvSchema), async (c) => {
6238
+ }).post("/:name/conversations", zValidator12("json", createConvSchema), async (c) => {
5828
6239
  const name = c.req.param("name");
5829
6240
  const user = c.get("user");
5830
6241
  const body = c.req.valid("json");
@@ -5898,18 +6309,18 @@ var app27 = new Hono27().get("/:name/conversations", async (c) => {
5898
6309
  if (!deleted) return c.json({ error: "Conversation not found" }, 404);
5899
6310
  return c.json({ ok: true });
5900
6311
  });
5901
- var conversations_default2 = app27;
6312
+ var conversations_default2 = app28;
5902
6313
 
5903
6314
  // src/web/api/volute/user-conversations.ts
5904
- import { zValidator as zValidator12 } from "@hono/zod-validator";
5905
- import { Hono as Hono28 } from "hono";
6315
+ import { zValidator as zValidator13 } from "@hono/zod-validator";
6316
+ import { Hono as Hono29 } from "hono";
5906
6317
  import { streamSSE as streamSSE7 } from "hono/streaming";
5907
- import { z as z12 } from "zod";
5908
- var createSchema3 = z12.object({
5909
- title: z12.string().optional(),
5910
- participantNames: z12.array(z12.string()).min(1)
6318
+ import { z as z13 } from "zod";
6319
+ var createSchema4 = z13.object({
6320
+ title: z13.string().optional(),
6321
+ participantNames: z13.array(z13.string()).min(1)
5911
6322
  });
5912
- var app28 = new Hono28().use("*", authMiddleware).get("/", async (c) => {
6323
+ var app29 = new Hono29().use("*", authMiddleware).get("/", async (c) => {
5913
6324
  const user = c.get("user");
5914
6325
  const convs = await listConversationsWithParticipants(user.id);
5915
6326
  return c.json(convs);
@@ -5921,7 +6332,7 @@ var app28 = new Hono28().use("*", authMiddleware).get("/", async (c) => {
5921
6332
  }
5922
6333
  const msgs = await getMessages(id);
5923
6334
  return c.json(msgs);
5924
- }).post("/", zValidator12("json", createSchema3), async (c) => {
6335
+ }).post("/", zValidator13("json", createSchema4), async (c) => {
5925
6336
  const user = c.get("user");
5926
6337
  const body = c.req.valid("json");
5927
6338
  const participantIds = /* @__PURE__ */ new Set();
@@ -5958,7 +6369,7 @@ var app28 = new Hono28().use("*", authMiddleware).get("/", async (c) => {
5958
6369
  return c.json({ error: "Conversation not found" }, 404);
5959
6370
  }
5960
6371
  return streamSSE7(c, async (stream) => {
5961
- const unsubscribe = subscribe3(conversationId, (event) => {
6372
+ const unsubscribe = subscribe2(conversationId, (event) => {
5962
6373
  stream.writeSSE({ data: JSON.stringify(event) }).catch((err) => {
5963
6374
  if (!stream.aborted) console.error("[chat] SSE write error:", err);
5964
6375
  });
@@ -5983,12 +6394,12 @@ var app28 = new Hono28().use("*", authMiddleware).get("/", async (c) => {
5983
6394
  if (!deleted) return c.json({ error: "Conversation not found" }, 404);
5984
6395
  return c.json({ ok: true });
5985
6396
  });
5986
- var user_conversations_default = app28;
6397
+ var user_conversations_default = app29;
5987
6398
 
5988
6399
  // src/web/app.ts
5989
6400
  var httpLog = logger_default.child("http");
5990
- var app29 = new Hono29();
5991
- app29.onError((err, c) => {
6401
+ var app30 = new Hono30();
6402
+ app30.onError((err, c) => {
5992
6403
  if (err instanceof HTTPException) {
5993
6404
  return err.getResponse();
5994
6405
  }
@@ -5999,10 +6410,10 @@ app29.onError((err, c) => {
5999
6410
  });
6000
6411
  return c.json({ error: "Internal server error" }, 500);
6001
6412
  });
6002
- app29.notFound((c) => {
6413
+ app30.notFound((c) => {
6003
6414
  return c.json({ error: "Not found" }, 404);
6004
6415
  });
6005
- app29.use("*", async (c, next) => {
6416
+ app30.use("*", async (c, next) => {
6006
6417
  const start = Date.now();
6007
6418
  await next();
6008
6419
  const duration = Date.now() - start;
@@ -6013,7 +6424,7 @@ app29.use("*", async (c, next) => {
6013
6424
  httpLog.debug("request", data);
6014
6425
  }
6015
6426
  });
6016
- app29.get("/api/health", (c) => {
6427
+ app30.get("/api/health", (c) => {
6017
6428
  let version = "unknown";
6018
6429
  let cached = null;
6019
6430
  try {
@@ -6028,36 +6439,37 @@ app29.get("/api/health", (c) => {
6028
6439
  ...cached?.updateAvailable ? { updateAvailable: true, latest: cached.latest } : {}
6029
6440
  });
6030
6441
  });
6031
- app29.use("/api/*", bodyLimit({ maxSize: 10 * 1024 * 1024 }));
6032
- app29.use("/api/*", csrf());
6033
- app29.use("/api/activity/*", authMiddleware);
6034
- app29.use("/api/minds/*", authMiddleware);
6035
- app29.use("/api/conversations/*", authMiddleware);
6036
- app29.use("/api/volute/*", authMiddleware);
6037
- app29.use("/api/system/*", authMiddleware);
6038
- app29.use("/api/env/*", authMiddleware);
6039
- app29.use("/api/prompts/*", authMiddleware);
6040
- app29.use("/api/skills/*", authMiddleware);
6041
- app29.use("/api/v1/*", authMiddleware);
6042
- app29.route("/pages", pages_default);
6043
- app29.route("/public", public_files_default);
6044
- var routes = app29.route("/api/activity", activity_default).route("/api/keys", keys_default).route("/api/auth", auth_default).route("/api/system", system_default).route("/api/system", update_default).route("/api/minds", minds_default).route("/api/minds", chat_default2).route("/api/minds", connectors_default).route("/api/minds", schedules_default).route("/api/minds", logs_default).route("/api/minds", typing_default).route("/api/minds", variants_default).route("/api/minds", file_sharing_default).route("/api/minds", files_default).route("/api/minds", channels_default).route("/api/minds", shared_default).route("/api/minds", env_default).route("/api/minds", mind_skills_default).route("/api/minds", conversations_default2).route("/api/env", sharedEnvApp).route("/api/prompts", prompts_default).route("/api/skills", skills_default).route("/api/conversations", user_conversations_default).route("/api/volute/channels", channels_default2).route("/api/volute", unifiedChatApp).route("/api/v1/conversations", conversations_default).route("/api/v1/events", events_default).route("/api/v1", chat_default);
6045
- app29.route("/api/v1/minds", minds_default);
6046
- app29.route("/api/v1/minds", typing_default);
6047
- app29.route("/api/v1/minds", variants_default);
6048
- app29.route("/api/v1/minds", files_default);
6049
- app29.route("/api/v1/minds", env_default);
6050
- app29.route("/api/v1/minds", mind_skills_default);
6051
- app29.route("/api/v1/minds", connectors_default);
6052
- app29.route("/api/v1/minds", schedules_default);
6053
- app29.route("/api/v1/minds", logs_default);
6054
- app29.route("/api/v1/system", system_default);
6055
- app29.route("/api/v1/system", update_default);
6056
- app29.route("/api/v1/prompts", prompts_default);
6057
- app29.route("/api/v1/skills", skills_default);
6058
- app29.route("/api/v1/env", sharedEnvApp);
6059
- app29.route("/api/v1/channels", channels_default2);
6060
- var app_default = app29;
6442
+ app30.use("/api/*", bodyLimit({ maxSize: 10 * 1024 * 1024 }));
6443
+ app30.use("/api/*", csrf());
6444
+ app30.use("/api/activity/*", authMiddleware);
6445
+ app30.use("/api/minds/*", authMiddleware);
6446
+ app30.use("/api/conversations/*", authMiddleware);
6447
+ app30.use("/api/volute/*", authMiddleware);
6448
+ app30.use("/api/system/*", authMiddleware);
6449
+ app30.use("/api/env/*", authMiddleware);
6450
+ app30.use("/api/prompts/*", authMiddleware);
6451
+ app30.use("/api/skills/*", authMiddleware);
6452
+ app30.use("/api/notes/*", authMiddleware);
6453
+ app30.use("/api/v1/*", authMiddleware);
6454
+ app30.route("/pages", pages_default);
6455
+ app30.route("/public", public_files_default);
6456
+ var routes = app30.route("/api/activity", activity_default).route("/api/keys", keys_default).route("/api/auth", auth_default).route("/api/system", system_default).route("/api/system", update_default).route("/api/minds", minds_default).route("/api/minds", chat_default2).route("/api/minds", connectors_default).route("/api/minds", schedules_default).route("/api/minds", logs_default).route("/api/minds", typing_default).route("/api/minds", variants_default).route("/api/minds", file_sharing_default).route("/api/minds", files_default).route("/api/minds", channels_default).route("/api/minds", shared_default).route("/api/minds", env_default).route("/api/minds", mind_skills_default).route("/api/minds", conversations_default2).route("/api/env", sharedEnvApp).route("/api/notes", notes_default).route("/api/prompts", prompts_default).route("/api/skills", skills_default).route("/api/conversations", user_conversations_default).route("/api/volute/channels", channels_default2).route("/api/volute", unifiedChatApp).route("/api/v1/conversations", conversations_default).route("/api/v1/events", events_default).route("/api/v1", chat_default);
6457
+ app30.route("/api/v1/minds", minds_default);
6458
+ app30.route("/api/v1/minds", typing_default);
6459
+ app30.route("/api/v1/minds", variants_default);
6460
+ app30.route("/api/v1/minds", files_default);
6461
+ app30.route("/api/v1/minds", env_default);
6462
+ app30.route("/api/v1/minds", mind_skills_default);
6463
+ app30.route("/api/v1/minds", connectors_default);
6464
+ app30.route("/api/v1/minds", schedules_default);
6465
+ app30.route("/api/v1/minds", logs_default);
6466
+ app30.route("/api/v1/system", system_default);
6467
+ app30.route("/api/v1/system", update_default);
6468
+ app30.route("/api/v1/prompts", prompts_default);
6469
+ app30.route("/api/v1/skills", skills_default);
6470
+ app30.route("/api/v1/env", sharedEnvApp);
6471
+ app30.route("/api/v1/channels", channels_default2);
6472
+ var app_default = app30;
6061
6473
 
6062
6474
  // src/web/server.ts
6063
6475
  var MIME_TYPES3 = {
@@ -6184,11 +6596,18 @@ async function startDaemon(opts) {
6184
6596
  logger_default.warn("failed to initialize shared repo", logger_default.errorData(err));
6185
6597
  }
6186
6598
  initRegistryCache();
6599
+ const { initSandbox } = await import("./sandbox-EHGFF52K.js");
6600
+ await initSandbox();
6187
6601
  try {
6188
6602
  await syncBuiltinSkills();
6189
6603
  } catch (err) {
6190
6604
  logger_default.error("failed to sync built-in skills", logger_default.errorData(err));
6191
6605
  }
6606
+ try {
6607
+ await ensureSystemChannel();
6608
+ } catch (err) {
6609
+ logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
6610
+ }
6192
6611
  const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes2(32).toString("hex");
6193
6612
  let tls;
6194
6613
  if (opts.tailscale) {
@@ -6289,7 +6708,7 @@ async function startDaemon(opts) {
6289
6708
  });
6290
6709
  await Promise.all(workers);
6291
6710
  }
6292
- import("./cloud-sync-PPBBJDY6.js").then(
6711
+ import("./cloud-sync-NI2K3C7G.js").then(
6293
6712
  ({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
6294
6713
  logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
6295
6714
  })
@@ -6297,7 +6716,7 @@ async function startDaemon(opts) {
6297
6716
  logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
6298
6717
  });
6299
6718
  try {
6300
- const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-AZQMC32A.js");
6719
+ const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-USFZBWMG.js");
6301
6720
  backfillTemplateHashes();
6302
6721
  notifyVersionUpdate().catch((err) => {
6303
6722
  logger_default.warn("failed to send version update notifications", logger_default.errorData(err));
@@ -6311,6 +6730,9 @@ async function startDaemon(opts) {
6311
6730
  cleanExpiredSessions().catch((err) => {
6312
6731
  logger_default.warn("failed to clean expired sessions", logger_default.errorData(err));
6313
6732
  });
6733
+ migrateMindRoles().catch((err) => {
6734
+ logger_default.warn("failed to migrate mind roles", logger_default.errorData(err));
6735
+ });
6314
6736
  logger_default.info(`running on ${hostname}:${port}, pid ${myPid}`);
6315
6737
  function cleanup() {
6316
6738
  try {
@@ -6372,6 +6794,7 @@ if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith
6372
6794
  let hostname = "127.0.0.1";
6373
6795
  let foreground = false;
6374
6796
  let tailscale = false;
6797
+ let noSandbox = false;
6375
6798
  for (let i = 2; i < process.argv.length; i++) {
6376
6799
  if (process.argv[i] === "--port" && process.argv[i + 1]) {
6377
6800
  port = parseInt(process.argv[i + 1], 10);
@@ -6383,8 +6806,13 @@ if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith
6383
6806
  foreground = true;
6384
6807
  } else if (process.argv[i] === "--tailscale") {
6385
6808
  tailscale = true;
6809
+ } else if (process.argv[i] === "--no-sandbox") {
6810
+ noSandbox = true;
6386
6811
  }
6387
6812
  }
6813
+ if (noSandbox) {
6814
+ process.env.VOLUTE_SANDBOX = "0";
6815
+ }
6388
6816
  startDaemon({ port, hostname, foreground, tailscale });
6389
6817
  }
6390
6818
  export {