volute 0.45.1 → 0.45.2

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 (108) hide show
  1. package/dist/{activity-events-OMCSM7XW.js → activity-events-BUR2RYTJ.js} +2 -2
  2. package/dist/{ai-service-534WUSDL.js → ai-service-UODCCE4O.js} +3 -3
  3. package/dist/{archive-6R4TZMYI.js → archive-WS2L2VIQ.js} +2 -2
  4. package/dist/{auth-FRZJVQCS.js → auth-FLAEXXZK.js} +3 -3
  5. package/dist/{avatar-image-BNWEXSA2.js → avatar-image-6KY6UU4D.js} +3 -3
  6. package/dist/{backup-OZXHL3JS.js → backup-TST5C2YN.js} +7 -7
  7. package/dist/{chat-I4EDDIQC.js → chat-76MRWWQX.js} +2 -2
  8. package/dist/{chunk-ZIR7HSAX.js → chunk-4JOQZPCE.js} +1 -1
  9. package/dist/{chunk-2BONPXAF.js → chunk-6EMWJZBK.js} +1 -1
  10. package/dist/{chunk-ZMIMSIIT.js → chunk-7C44R625.js} +1 -1
  11. package/dist/{chunk-Y6OPHHGM.js → chunk-7ZUB63PS.js} +4 -4
  12. package/dist/{chunk-LAXUUY7O.js → chunk-A7WQZKOU.js} +2 -2
  13. package/dist/{chunk-H7IYFRAL.js → chunk-ALKYQULU.js} +10 -5
  14. package/dist/{chunk-KP3KWNG6.js → chunk-CDPBTTZO.js} +2 -2
  15. package/dist/{chunk-SQL7M4HJ.js → chunk-DRJ24GXK.js} +2 -2
  16. package/dist/{chunk-HVU45COX.js → chunk-EJVPTVTI.js} +1 -1
  17. package/dist/{chunk-322KE457.js → chunk-F7H6ATM4.js} +1 -1
  18. package/dist/{chunk-5AUKCNPE.js → chunk-FR6S2KNN.js} +8 -8
  19. package/dist/{chunk-KVKP6VQ5.js → chunk-FXORA5JG.js} +12 -3
  20. package/dist/{chunk-3ERIL673.js → chunk-H2X54EHC.js} +1 -1
  21. package/dist/{chunk-TSK5PI4L.js → chunk-IHKGWTGT.js} +1 -1
  22. package/dist/{chunk-OXXTPILE.js → chunk-JZ62SYWR.js} +1 -1
  23. package/dist/{chunk-77BVGCTZ.js → chunk-NYC5U6K7.js} +9 -9
  24. package/dist/{chunk-JSRMEY52.js → chunk-OP4JG2BS.js} +5 -4
  25. package/dist/{chunk-CU6OFXMM.js → chunk-PFZBNKUH.js} +9 -0
  26. package/dist/{chunk-QMJJWTNL.js → chunk-QCN24XEN.js} +1 -1
  27. package/dist/{chunk-IUXTYXFI.js → chunk-QNQMSWZE.js} +3 -3
  28. package/dist/{chunk-UMI4UIJG.js → chunk-R77O2WMK.js} +1 -1
  29. package/dist/{chunk-IEWZ7VD7.js → chunk-RRNXJOKB.js} +2 -2
  30. package/dist/{chunk-FHWUQZXE.js → chunk-RXEEYDIB.js} +1 -1
  31. package/dist/{chunk-CYI534DJ.js → chunk-T6HYVHPG.js} +2 -2
  32. package/dist/{chunk-Q2XBKQ2D.js → chunk-TQJ6ZYVY.js} +2 -2
  33. package/dist/{chunk-V4GYPD5L.js → chunk-UYLGEDVD.js} +4 -4
  34. package/dist/{chunk-U4FNXDEJ.js → chunk-YT7PEESJ.js} +231 -98
  35. package/dist/{chunk-5GT7URXJ.js → chunk-ZDZISKCL.js} +1 -1
  36. package/dist/cli.js +16 -16
  37. package/dist/{cloud-sync-Y7LQPRE3.js → cloud-sync-3OJOPZRT.js} +16 -16
  38. package/dist/{conversations-G4LYMHAA.js → conversations-JZTD6KLR.js} +3 -3
  39. package/dist/{create-2YY7IPMS.js → create-IOV4GCRX.js} +1 -1
  40. package/dist/{daemon-restart-ABP54YN6.js → daemon-restart-TIHKVVVA.js} +6 -6
  41. package/dist/daemon.js +180 -137
  42. package/dist/{db-JFLCJCUG.js → db-MF2JNRUW.js} +1 -1
  43. package/dist/delivery-manager-VDVKVA46.js +32 -0
  44. package/dist/{delivery-router-6DE3BPHO.js → delivery-router-N4A7ZC5T.js} +2 -2
  45. package/dist/{down-XCAZXWLB.js → down-U2CZ23M4.js} +4 -4
  46. package/dist/echo-text-6JJOPUD4.js +32 -0
  47. package/dist/{exec-4GWHAHS3.js → exec-G3ZRST4Z.js} +2 -2
  48. package/dist/{export-ID7YUSLZ.js → export-GGIVO76O.js} +2 -2
  49. package/dist/{extensions-AYSPKE33.js → extensions-JONTW2HF.js} +16 -16
  50. package/dist/{files-BQ2WB5KC.js → files-4LN3EN7Q.js} +2 -2
  51. package/dist/{import-SKID37QX.js → import-42YNQBF4.js} +5 -5
  52. package/dist/{isolation-5MB3J73F.js → isolation-YMGZZ4E5.js} +2 -2
  53. package/dist/{join-RXPXGV4L.js → join-ZJV7W6MO.js} +4 -0
  54. package/dist/{login-LM4NF4ZB.js → login-M6OJUPQ2.js} +1 -1
  55. package/dist/{logout-CTJVIZGA.js → logout-WQBWO77G.js} +1 -1
  56. package/dist/message-delivery-3C65ZI6L.js +34 -0
  57. package/dist/{mind-KLHC7XYR.js → mind-DWB6XYCH.js} +6 -6
  58. package/dist/{mind-activity-tracker-BGHJE7XA.js → mind-activity-tracker-POBLU3LC.js} +3 -3
  59. package/dist/mind-service-3F4I46CI.js +36 -0
  60. package/dist/{package-BMHV7UHN.js → package-A7KXT67Q.js} +1 -1
  61. package/dist/{registry-NUJAGLQJ.js → registry-OUZBZ3Q4.js} +5 -1
  62. package/dist/{sandbox-72MWV4JL.js → sandbox-ZJ7QA6Z6.js} +3 -3
  63. package/dist/scheduler-P6DXLLXI.js +30 -0
  64. package/dist/{seed-4MKQ5QKG.js → seed-HCP5NYKH.js} +1 -1
  65. package/dist/{seed-cmd-LCXMR7VV.js → seed-cmd-ILOGNIFB.js} +2 -2
  66. package/dist/{seed-create-N2BF5LQX.js → seed-create-OURS2LS4.js} +3 -3
  67. package/dist/{seed-sprout-6ZDP23YI.js → seed-sprout-ELDFDAN6.js} +7 -7
  68. package/dist/{send-O6W53VBM.js → send-AAIOPJAV.js} +2 -2
  69. package/dist/{service-AQVPUANO.js → service-UOCLXDWR.js} +3 -3
  70. package/dist/{service-install-4QNUDKLM.js → service-install-4HHFDDWY.js} +4 -4
  71. package/dist/{setup-3O6O2JZ7.js → setup-DQM5VPY4.js} +6 -6
  72. package/dist/{setup-73YBJZQL.js → setup-Y2EJI3GG.js} +2 -2
  73. package/dist/skills/imagegen/scripts/imagegen.ts +100 -40
  74. package/dist/skills/volute-mind/SKILL.md +5 -1
  75. package/dist/{skills-ND4ZFYUW.js → skills-BKINFL7W.js} +4 -4
  76. package/dist/sleep-manager-HCUH4PM4.js +34 -0
  77. package/dist/{spirit-II3HOERM.js → spirit-DBTIW7P4.js} +7 -7
  78. package/dist/{sprout-4KUG76AQ.js → sprout-W3KC7UGK.js} +1 -1
  79. package/dist/{src-XFY3XDD6.js → src-OJHARHTF.js} +28 -17
  80. package/dist/{status-E5DQNCAO.js → status-SWRVGXBI.js} +4 -4
  81. package/dist/system-chat-XOALE2RD.js +36 -0
  82. package/dist/{tailscale-QAWVKQKU.js → tailscale-3XOKOW7T.js} +1 -1
  83. package/dist/{turn-tracker-QQIVVXBI.js → turn-tracker-2W6Q2NSR.js} +4 -4
  84. package/dist/{up-LG56MPBI.js → up-FTK7CTO3.js} +5 -5
  85. package/dist/{update-7TYVH5FM.js → update-SWAYZRWJ.js} +4 -4
  86. package/dist/{update-check-VSCSJ7KX.js → update-check-PQ2MZ47K.js} +2 -2
  87. package/dist/{version-notify-CODJOUW2.js → version-notify-3XMAIQTE.js} +17 -17
  88. package/dist/{volute-config-TS62GS6A.js → volute-config-A52FHWKM.js} +5 -1
  89. package/dist/web-assets/assets/{index-Dac11sKB.js → index-Bc2m8gRC.js} +15 -15
  90. package/dist/web-assets/index.html +1 -1
  91. package/package.json +1 -1
  92. package/templates/_base/src/lib/file-handler.ts +3 -3
  93. package/templates/_base/src/lib/router.ts +21 -25
  94. package/templates/_base/src/lib/startup.ts +2 -0
  95. package/templates/_base/src/lib/types.ts +2 -2
  96. package/templates/claude/src/agent.ts +75 -10
  97. package/templates/claude/src/lib/message-channel.ts +23 -0
  98. package/templates/claude/src/lib/session-reaper.ts +37 -0
  99. package/templates/claude/src/server.ts +1 -0
  100. package/templates/codex/src/agent.ts +18 -6
  101. package/templates/pi/src/agent.ts +18 -7
  102. package/dist/delivery-manager-R5STGLXB.js +0 -32
  103. package/dist/echo-text-NQXYYYCU.js +0 -32
  104. package/dist/message-delivery-IUAXRPFE.js +0 -34
  105. package/dist/mind-service-BF2LUQMH.js +0 -36
  106. package/dist/scheduler-YHJRRV6E.js +0 -30
  107. package/dist/sleep-manager-YAHDOIU5.js +0 -34
  108. package/dist/system-chat-E65T2HSW.js +0 -34
package/dist/daemon.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  readBackupState,
7
7
  resticVersion,
8
8
  runBackup
9
- } from "./chunk-KVKP6VQ5.js";
9
+ } from "./chunk-FXORA5JG.js";
10
10
  import {
11
11
  acceptPending,
12
12
  formatFileSize,
@@ -14,25 +14,25 @@ import {
14
14
  rejectPending,
15
15
  stageFile,
16
16
  validateFilePath
17
- } from "./chunk-UMI4UIJG.js";
17
+ } from "./chunk-R77O2WMK.js";
18
18
  import {
19
19
  findOpenClawSession,
20
20
  importOpenClawConnectors,
21
21
  importPiSession,
22
22
  parseNameFromIdentity
23
- } from "./chunk-LAXUUY7O.js";
23
+ } from "./chunk-A7WQZKOU.js";
24
24
  import {
25
25
  checkForUpdate,
26
26
  checkForUpdateCached,
27
27
  getCurrentVersion
28
- } from "./chunk-2BONPXAF.js";
28
+ } from "./chunk-6EMWJZBK.js";
29
29
  import {
30
30
  normalizeAvatar,
31
31
  safeResolveWithinBase
32
- } from "./chunk-SQL7M4HJ.js";
32
+ } from "./chunk-DRJ24GXK.js";
33
33
  import {
34
34
  isHomeOnlyArchive
35
- } from "./chunk-QMJJWTNL.js";
35
+ } from "./chunk-QCN24XEN.js";
36
36
  import {
37
37
  computeTemplateHash
38
38
  } from "./chunk-QMJCNZ6C.js";
@@ -42,7 +42,7 @@ import {
42
42
  fixModelEscapes,
43
43
  getPlatformDriver,
44
44
  routeOutboundBridge
45
- } from "./chunk-77BVGCTZ.js";
45
+ } from "./chunk-NYC5U6K7.js";
46
46
  import {
47
47
  getBridgeConfig,
48
48
  readBridgesConfig,
@@ -51,7 +51,7 @@ import {
51
51
  resolveChannelMapping,
52
52
  setBridgeConfig,
53
53
  setChannelMapping
54
- } from "./chunk-FHWUQZXE.js";
54
+ } from "./chunk-RXEEYDIB.js";
55
55
  import {
56
56
  MindStartupError,
57
57
  RestartTracker,
@@ -71,7 +71,7 @@ import {
71
71
  ensureSystemChannel,
72
72
  formatHoldNotice,
73
73
  formatNotices,
74
- generateSystemReply,
74
+ generateSystemFallbackReply,
75
75
  getAllDiscoveredExtensions,
76
76
  getAllDiscoveredExtensionsDetailed,
77
77
  getDeliveryManager,
@@ -107,20 +107,21 @@ import {
107
107
  requireAdminOrSystem,
108
108
  requireSelf,
109
109
  setExtensionEnabled,
110
+ shouldGenerateSystemFallback,
110
111
  startMindFull,
111
112
  stopMindFull,
112
113
  syncProviderToMinds,
113
114
  uninstallNpmExtension,
114
115
  writeSystemsConfig
115
- } from "./chunk-U4FNXDEJ.js";
116
+ } from "./chunk-YT7PEESJ.js";
116
117
  import {
117
118
  loadMergedEnv,
118
119
  mindEnvPath,
119
120
  readEnv,
120
121
  sharedEnvPath,
121
122
  writeEnv
122
- } from "./chunk-5GT7URXJ.js";
123
- import "./chunk-5AUKCNPE.js";
123
+ } from "./chunk-ZDZISKCL.js";
124
+ import "./chunk-FR6S2KNN.js";
124
125
  import {
125
126
  applyInitFiles,
126
127
  applyTemplateHomeFiles,
@@ -149,7 +150,7 @@ import {
149
150
  syncBuiltinSkills,
150
151
  uninstallSkill,
151
152
  updateSkill
152
- } from "./chunk-Y6OPHHGM.js";
153
+ } from "./chunk-7ZUB63PS.js";
153
154
  import {
154
155
  addMessage,
155
156
  createChannel,
@@ -181,23 +182,23 @@ import {
181
182
  setConversationPrivate,
182
183
  subscribe as subscribe2,
183
184
  updateChannelSettings
184
- } from "./chunk-JSRMEY52.js";
185
+ } from "./chunk-OP4JG2BS.js";
185
186
  import {
186
187
  readVoluteConfig,
187
188
  writeVoluteConfig
188
- } from "./chunk-CU6OFXMM.js";
189
+ } from "./chunk-PFZBNKUH.js";
189
190
  import {
190
191
  isSandboxEnabled,
191
192
  wrapForSandbox
192
- } from "./chunk-OXXTPILE.js";
193
+ } from "./chunk-JZ62SYWR.js";
193
194
  import {
194
195
  getActiveMinds,
195
196
  onMindEvent,
196
197
  stopAll
197
- } from "./chunk-HVU45COX.js";
198
+ } from "./chunk-EJVPTVTI.js";
198
199
  import {
199
200
  extractTextContent
200
- } from "./chunk-ZIR7HSAX.js";
201
+ } from "./chunk-4JOQZPCE.js";
201
202
  import {
202
203
  PROMPT_DEFAULTS,
203
204
  PROMPT_KEYS,
@@ -220,8 +221,8 @@ import {
220
221
  summarizeTurn,
221
222
  takeErrored,
222
223
  trackToolUse
223
- } from "./chunk-V4GYPD5L.js";
224
- import "./chunk-Q2XBKQ2D.js";
224
+ } from "./chunk-UYLGEDVD.js";
225
+ import "./chunk-TQJ6ZYVY.js";
225
226
  import {
226
227
  chownMindDir,
227
228
  createMindUser,
@@ -232,9 +233,10 @@ import {
232
233
  isIsolationEnabled,
233
234
  resolveVoluteBin,
234
235
  wrapForIsolation
235
- } from "./chunk-3ERIL673.js";
236
+ } from "./chunk-H2X54EHC.js";
236
237
  import {
237
238
  addCustomModel,
239
+ aiCompleteUtility,
238
240
  buildCustomModel,
239
241
  getAiConfig,
240
242
  getAvailableModels,
@@ -253,12 +255,12 @@ import {
253
255
  setProviderRefreshHook,
254
256
  setUtilityModel,
255
257
  unqualifyModelId
256
- } from "./chunk-TSK5PI4L.js";
258
+ } from "./chunk-IHKGWTGT.js";
257
259
  import {
258
260
  isSetupComplete,
259
261
  readGlobalConfig,
260
262
  writeGlobalConfig
261
- } from "./chunk-322KE457.js";
263
+ } from "./chunk-F7H6ATM4.js";
262
264
  import {
263
265
  approveUser,
264
266
  changePassword,
@@ -277,11 +279,11 @@ import {
277
279
  syncMindProfile,
278
280
  updateUserProfile,
279
281
  verifyUser
280
- } from "./chunk-CYI534DJ.js";
282
+ } from "./chunk-T6HYVHPG.js";
281
283
  import {
282
284
  broadcast,
283
285
  subscribe
284
- } from "./chunk-ZMIMSIIT.js";
286
+ } from "./chunk-7C44R625.js";
285
287
  import {
286
288
  logBuffer,
287
289
  logger_default
@@ -305,6 +307,7 @@ import {
305
307
  readAllMinds,
306
308
  readRegistry,
307
309
  removeMind,
310
+ resolveMindDir,
308
311
  setMindRunning,
309
312
  setMindStage,
310
313
  setMindTemplate,
@@ -313,7 +316,7 @@ import {
313
316
  validateMindName,
314
317
  voluteHome,
315
318
  voluteSystemDir
316
- } from "./chunk-H7IYFRAL.js";
319
+ } from "./chunk-ALKYQULU.js";
317
320
  import {
318
321
  activity,
319
322
  channels,
@@ -1472,10 +1475,10 @@ function getCachedApiKey(provider) {
1472
1475
  var keyRefreshTimer = null;
1473
1476
  var slog = logger_default.child("ai-keys");
1474
1477
  var oauthHealth = /* @__PURE__ */ new Map();
1475
- function needsRefresh(oauth) {
1478
+ function needsRefresh(oauth, now = Date.now()) {
1476
1479
  const expires = oauth.expires;
1477
- if (!expires || Date.now() >= expires) return true;
1478
- return expires - Date.now() < 15 * 60 * 1e3;
1480
+ if (!expires || now >= expires) return true;
1481
+ return expires - now < 15 * 60 * 1e3;
1479
1482
  }
1480
1483
  async function refreshApiKeyCache() {
1481
1484
  const ai = getAiConfig();
@@ -2165,7 +2168,7 @@ var app4 = new Hono5().post("/:platform/inbound", zValidator4("json", inboundSch
2165
2168
  }
2166
2169
  const participants = await getParticipants(channel.id);
2167
2170
  if (!participants.some((p) => p.userId === puppet.id)) {
2168
- const { addParticipant } = await import("./conversations-G4LYMHAA.js");
2171
+ const { addParticipant } = await import("./conversations-JZTD6KLR.js");
2169
2172
  await addParticipant(channel.id, puppet.id);
2170
2173
  }
2171
2174
  const contentBlocks = body.content;
@@ -2449,7 +2452,7 @@ async function notifyMind(mindName, message) {
2449
2452
  const entry = await findMind(mindName);
2450
2453
  if (!entry) return;
2451
2454
  try {
2452
- const { sendSystemMessage } = await import("./system-chat-E65T2HSW.js");
2455
+ const { sendSystemMessage } = await import("./system-chat-XOALE2RD.js");
2453
2456
  await sendSystemMessage(mindName, message);
2454
2457
  } catch (err) {
2455
2458
  logger_default.warn(`[file-sharing] notify mind ${mindName} failed`, logger_default.errorData(err));
@@ -3301,6 +3304,7 @@ var app12 = new Hono15().get("/:name/skills", async (c) => {
3301
3304
  const dir = entry.dir ?? mindDir(name);
3302
3305
  try {
3303
3306
  const result = await installSkill(name, dir, skillId);
3307
+ await chownMindDir(dir, name);
3304
3308
  return c.json({ ok: true, ...result });
3305
3309
  } catch (e) {
3306
3310
  const msg = e instanceof Error ? e.message : String(e);
@@ -3319,6 +3323,7 @@ var app12 = new Hono15().get("/:name/skills", async (c) => {
3319
3323
  const dir = entry.dir ?? mindDir(name);
3320
3324
  try {
3321
3325
  const result = await updateSkill(name, dir, skillId);
3326
+ await chownMindDir(dir, name);
3322
3327
  return c.json(result);
3323
3328
  } catch (e) {
3324
3329
  const msg = e instanceof Error ? e.message : String(e);
@@ -3351,6 +3356,7 @@ var app12 = new Hono15().get("/:name/skills", async (c) => {
3351
3356
  const dir = entry.dir ?? mindDir(name);
3352
3357
  try {
3353
3358
  await uninstallSkill(name, dir, skillName);
3359
+ await chownMindDir(dir, name);
3354
3360
  } catch (e) {
3355
3361
  const msg = e instanceof Error ? e.message : String(e);
3356
3362
  return c.json({ error: msg }, 400);
@@ -3595,35 +3601,50 @@ async function completeTurnAndSummarize(mind, event, insertedId) {
3595
3601
  // packages/daemon/src/lib/mind/consolidate.ts
3596
3602
  import { readdirSync, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
3597
3603
  import { resolve as resolve8 } from "path";
3598
- async function consolidateMemory(mindDir2) {
3604
+ var cLog = logger_default.child("consolidate");
3605
+ var MAX_CONSOLIDATION_INPUT_CHARS = 2e5;
3606
+ function readDailyLogs(memoryDir) {
3607
+ let files;
3608
+ try {
3609
+ files = readdirSync(memoryDir).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort();
3610
+ } catch {
3611
+ return [];
3612
+ }
3613
+ const logs = [];
3614
+ for (const filename of files) {
3615
+ const date = filename.replace(".md", "");
3616
+ const content = readFileSync6(resolve8(memoryDir, filename), "utf-8").trim();
3617
+ if (content) logs.push(`### ${date}
3618
+
3619
+ ${content}`);
3620
+ }
3621
+ return logs;
3622
+ }
3623
+ function boundLogText(logs, maxChars = MAX_CONSOLIDATION_INPUT_CHARS) {
3624
+ const kept = [];
3625
+ let total = 0;
3626
+ for (let i = logs.length - 1; i >= 0; i--) {
3627
+ const len = logs[i].length + (kept.length > 0 ? 2 : 0);
3628
+ if (total + len > maxChars) break;
3629
+ kept.unshift(logs[i]);
3630
+ total += len;
3631
+ }
3632
+ if (kept.length === 0 && logs.length > 0) {
3633
+ return logs[logs.length - 1].slice(-maxChars);
3634
+ }
3635
+ return kept.join("\n\n");
3636
+ }
3637
+ async function consolidateMemory(mindDir2, complete = aiCompleteUtility) {
3599
3638
  const soulPath = resolve8(mindDir2, "home/SOUL.md");
3600
3639
  const memoryPath = resolve8(mindDir2, "home/MEMORY.md");
3601
3640
  const memoryDir = resolve8(mindDir2, "home/memory");
3602
3641
  const soul = readFileSync6(soulPath, "utf-8");
3603
- const logs = [];
3604
- try {
3605
- const files = readdirSync(memoryDir).filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort();
3606
- for (const filename of files) {
3607
- const date = filename.replace(".md", "");
3608
- const content2 = readFileSync6(resolve8(memoryDir, filename), "utf-8").trim();
3609
- if (content2) {
3610
- logs.push(`### ${date}
3611
-
3612
- ${content2}`);
3613
- }
3614
- }
3615
- } catch {
3616
- }
3642
+ const logs = readDailyLogs(memoryDir);
3617
3643
  if (logs.length === 0) {
3618
- console.log("No daily logs found.");
3644
+ cLog.info("No daily logs found; skipping memory consolidation.");
3619
3645
  return;
3620
3646
  }
3621
- const apiKey = process.env.ANTHROPIC_API_KEY;
3622
- if (!apiKey) {
3623
- console.error("ANTHROPIC_API_KEY not set, skipping memory consolidation.");
3624
- return;
3625
- }
3626
- console.log("Consolidating memory from daily logs...");
3647
+ cLog.info("Consolidating memory from daily logs...");
3627
3648
  const userMessage = [
3628
3649
  "You have daily logs from a previous environment but no long-term memory file yet.",
3629
3650
  "Please review the daily logs below and produce consolidated MEMORY.md content.",
@@ -3631,35 +3652,15 @@ ${content2}`);
3631
3652
  "",
3632
3653
  "## Daily logs",
3633
3654
  "",
3634
- logs.join("\n\n")
3655
+ boundLogText(logs)
3635
3656
  ].join("\n");
3636
- const res = await fetch("https://api.anthropic.com/v1/messages", {
3637
- method: "POST",
3638
- headers: {
3639
- "Content-Type": "application/json",
3640
- "x-api-key": apiKey,
3641
- "anthropic-version": "2023-06-01"
3642
- },
3643
- body: JSON.stringify({
3644
- model: "claude-sonnet-4-20250514",
3645
- max_tokens: 4096,
3646
- system: soul,
3647
- messages: [{ role: "user", content: userMessage }]
3648
- })
3649
- });
3650
- if (!res.ok) {
3651
- const body = await res.text();
3652
- console.error(`Anthropic API error (${res.status}): ${body}`);
3653
- return;
3654
- }
3655
- const data = await res.json();
3656
- const content = data.content.filter((b) => b.type === "text" && b.text).map((b) => b.text).join("").trim();
3657
+ const content = (await complete(soul, userMessage))?.trim();
3657
3658
  if (content) {
3658
3659
  writeFileSync5(memoryPath, `${content}
3659
3660
  `);
3660
- console.log("MEMORY.md created successfully.");
3661
+ cLog.info("MEMORY.md created successfully.");
3661
3662
  } else {
3662
- console.warn("Warning: No content produced.");
3663
+ cLog.warn("No content produced; skipping memory consolidation.");
3663
3664
  }
3664
3665
  }
3665
3666
 
@@ -3706,7 +3707,7 @@ async function cleanupVariant(variantName, projectRoot, variantPath, opts) {
3706
3707
  logger_default.warn(`failed to stop variant ${variantName}`, logger_default.errorData(err));
3707
3708
  }
3708
3709
  }
3709
- const { findMind: findMind2 } = await import("./registry-NUJAGLQJ.js");
3710
+ const { findMind: findMind2 } = await import("./registry-OUZBZ3Q4.js");
3710
3711
  const variantEntry = await findMind2(variantName);
3711
3712
  const branchName = variantEntry?.branch ?? variantName;
3712
3713
  if (existsSync6(variantPath)) {
@@ -3935,7 +3936,7 @@ async function getMindStatus(name, port, registryRunning) {
3935
3936
  const manager = getMindManager();
3936
3937
  let status = "stopped";
3937
3938
  try {
3938
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
3939
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
3939
3940
  if (getSleepManagerIfReady2()?.isSleeping(name)) {
3940
3941
  status = "sleeping";
3941
3942
  }
@@ -4430,7 +4431,7 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
4430
4431
  applyInitFiles(dest);
4431
4432
  const { publicKeyPem } = generateIdentity(dest);
4432
4433
  {
4433
- const { readGlobalConfig: readGlobal } = await import("./setup-73YBJZQL.js");
4434
+ const { readGlobalConfig: readGlobal } = await import("./setup-Y2EJI3GG.js");
4434
4435
  const mindDefaults = readGlobal().mindDefaults;
4435
4436
  const config2 = readVoluteConfig(dest);
4436
4437
  if (!config2) throw new Error("Failed to read volute.json after identity generation");
@@ -4510,7 +4511,6 @@ var app13 = new Hono16().post("/", requireAdminOrSystem, zValidator6("json", cre
4510
4511
  rmSync4(resolve10(dest, ".git"), { recursive: true, force: true });
4511
4512
  gitWarning = "Git setup failed \u2014 variants and upgrades won't be available until git is initialized.";
4512
4513
  }
4513
- await chownMindDir(dest, name);
4514
4514
  if (body.stage === "seed") {
4515
4515
  const descLine = body.description ? `
4516
4516
  The human who planted you described you as: "${body.description}"
@@ -4521,7 +4521,7 @@ The human who planted you described you as: "${body.description}"
4521
4521
  }
4522
4522
  let skillSet = body.skills ?? (body.stage === "seed" ? SEED_SKILLS : getStandardSkillsWithExtensions());
4523
4523
  if (body.stage === "seed" && !body.skills) {
4524
- const { isImagegenEnabled } = await import("./setup-73YBJZQL.js");
4524
+ const { isImagegenEnabled } = await import("./setup-Y2EJI3GG.js");
4525
4525
  if (isImagegenEnabled()) {
4526
4526
  skillSet = [...skillSet, "imagegen"];
4527
4527
  }
@@ -4539,7 +4539,7 @@ The human who planted you described you as: "${body.description}"
4539
4539
  try {
4540
4540
  const spiritEntry = await findMind("volute");
4541
4541
  if (spiritEntry) {
4542
- const { spiritDir } = await import("./spirit-II3HOERM.js");
4542
+ const { spiritDir } = await import("./spirit-DBTIW7P4.js");
4543
4543
  const sDir = spiritEntry.dir ?? spiritDir();
4544
4544
  const spiritConfig = readVoluteConfig(sDir) ?? {};
4545
4545
  const schedules = spiritConfig.schedules ?? [];
@@ -4554,7 +4554,7 @@ The human who planted you described you as: "${body.description}"
4554
4554
  });
4555
4555
  spiritConfig.schedules = schedules;
4556
4556
  writeVoluteConfig(sDir, spiritConfig);
4557
- const { getScheduler: getScheduler2 } = await import("./scheduler-YHJRRV6E.js");
4557
+ const { getScheduler: getScheduler2 } = await import("./scheduler-P6DXLLXI.js");
4558
4558
  getScheduler2().loadSchedules("volute", sDir);
4559
4559
  }
4560
4560
  }
@@ -4572,6 +4572,7 @@ The human who planted you described you as: "${body.description}"
4572
4572
  writeFileSync7(resolve10(dest, "home/MEMORY.md"), customMemory);
4573
4573
  }
4574
4574
  }
4575
+ await chownMindDir(dest, name);
4575
4576
  publishPublicKey(name, publicKeyPem).catch(
4576
4577
  (err) => logger_default.warn(`failed to publish key for ${name}`, { error: err.message })
4577
4578
  );
@@ -4819,7 +4820,7 @@ ${user.trimEnd()}
4819
4820
  const manager = getMindManager();
4820
4821
  try {
4821
4822
  if (context?.type === "reload") {
4822
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
4823
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
4823
4824
  const sleepState = getSleepManagerIfReady2()?.getState(name);
4824
4825
  if (sleepState?.sleeping) {
4825
4826
  logger_default.info(`skipping reload for ${name} during sleep \u2014 will apply on next wake`);
@@ -4946,7 +4947,7 @@ ${user.trimEnd()}
4946
4947
  const name = c.req.param("name");
4947
4948
  const entry = await findMind(name);
4948
4949
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4949
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
4950
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
4950
4951
  const sm = getSleepManagerIfReady2();
4951
4952
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
4952
4953
  return c.json(sm.getState(name));
@@ -4954,7 +4955,7 @@ ${user.trimEnd()}
4954
4955
  const name = c.req.param("name");
4955
4956
  const entry = await findMind(name);
4956
4957
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4957
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
4958
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
4958
4959
  const sm = getSleepManagerIfReady2();
4959
4960
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
4960
4961
  if (sm.isSleeping(name)) return c.json({ error: "Mind is already sleeping" }, 409);
@@ -4974,7 +4975,7 @@ ${user.trimEnd()}
4974
4975
  const name = c.req.param("name");
4975
4976
  const entry = await findMind(name);
4976
4977
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4977
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
4978
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
4978
4979
  const sm = getSleepManagerIfReady2();
4979
4980
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
4980
4981
  const sleepState = sm.getState(name);
@@ -4989,7 +4990,7 @@ ${user.trimEnd()}
4989
4990
  const name = c.req.param("name");
4990
4991
  const entry = await findMind(name);
4991
4992
  if (!entry) return c.json({ error: "Mind not found" }, 404);
4992
- const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-YAHDOIU5.js");
4993
+ const { getSleepManagerIfReady: getSleepManagerIfReady2 } = await import("./sleep-manager-HCUH4PM4.js");
4993
4994
  const sm = getSleepManagerIfReady2();
4994
4995
  if (!sm) return c.json({ error: "Sleep manager not initialized" }, 503);
4995
4996
  const flushed = await sm.flushQueuedMessages(name);
@@ -5017,7 +5018,7 @@ ${user.trimEnd()}
5017
5018
  }
5018
5019
  config2.profile = profile;
5019
5020
  writeVoluteConfig(dir, config2);
5020
- const { syncMindProfile: syncMindProfile2 } = await import("./auth-FRZJVQCS.js");
5021
+ const { syncMindProfile: syncMindProfile2 } = await import("./auth-FLAEXXZK.js");
5021
5022
  await syncMindProfile2(name, profile);
5022
5023
  broadcast({ type: "profile_updated", mind: name, summary: `${name} profile updated` });
5023
5024
  return c.json({ ok: true });
@@ -5064,7 +5065,7 @@ ${user.trimEnd()}
5064
5065
  const config2 = readVoluteConfig(dir);
5065
5066
  const displayNameSet = !!config2?.profile?.displayName;
5066
5067
  const avatarSet = !!config2?.profile?.avatar;
5067
- const { isImagegenEnabled } = await import("./setup-73YBJZQL.js");
5068
+ const { isImagegenEnabled } = await import("./setup-Y2EJI3GG.js");
5068
5069
  const imagegenEnabled = isImagegenEnabled();
5069
5070
  const done = [];
5070
5071
  const remaining = [];
@@ -5102,7 +5103,7 @@ ${user.trimEnd()}
5102
5103
  try {
5103
5104
  const spiritEntry = await findMind("volute");
5104
5105
  if (spiritEntry) {
5105
- const { spiritDir } = await import("./spirit-II3HOERM.js");
5106
+ const { spiritDir } = await import("./spirit-DBTIW7P4.js");
5106
5107
  const sDir = spiritEntry.dir ?? spiritDir();
5107
5108
  const spiritConfig = readVoluteConfig(sDir);
5108
5109
  if (spiritConfig?.schedules) {
@@ -5110,7 +5111,7 @@ ${user.trimEnd()}
5110
5111
  spiritConfig.schedules = spiritConfig.schedules.filter((s) => s.id !== nurtureId);
5111
5112
  if (spiritConfig.schedules.length === 0) spiritConfig.schedules = void 0;
5112
5113
  writeVoluteConfig(sDir, spiritConfig);
5113
- const { getScheduler: getScheduler2 } = await import("./scheduler-YHJRRV6E.js");
5114
+ const { getScheduler: getScheduler2 } = await import("./scheduler-P6DXLLXI.js");
5114
5115
  getScheduler2().loadSchedules("volute", sDir);
5115
5116
  }
5116
5117
  }
@@ -5545,7 +5546,7 @@ ${user.trimEnd()}
5545
5546
  }
5546
5547
  writeVoluteConfig(dir, existing);
5547
5548
  if (body.unescapeNewlines !== void 0) {
5548
- const { clearEchoTextCache } = await import("./echo-text-NQXYYYCU.js");
5549
+ const { clearEchoTextCache } = await import("./echo-text-6JJOPUD4.js");
5549
5550
  clearEchoTextCache(name);
5550
5551
  }
5551
5552
  const needsConfigJson = body.model !== void 0 || body.thinkingLevel !== void 0 || body.maxThinkingTokens !== void 0 || body.compaction !== void 0;
@@ -5622,7 +5623,7 @@ ${user.trimEnd()}
5622
5623
  }
5623
5624
  if (entry.mindType === "spirit" && body.model !== void 0) {
5624
5625
  try {
5625
- const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-73YBJZQL.js");
5626
+ const { readGlobalConfig: readGlobalConfig2, writeGlobalConfig: writeGlobalConfig2 } = await import("./setup-Y2EJI3GG.js");
5626
5627
  const globalConfig = readGlobalConfig2();
5627
5628
  globalConfig.spiritModel = body.model;
5628
5629
  writeGlobalConfig2(globalConfig);
@@ -5650,7 +5651,7 @@ ${user.trimEnd()}
5650
5651
  if (!body.systemPrompt || !body.message) {
5651
5652
  return c.json({ error: "systemPrompt and message required" }, 400);
5652
5653
  }
5653
- const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-534WUSDL.js");
5654
+ const { aiComplete: aiCompleteFn, isAiConfigured } = await import("./ai-service-UODCCE4O.js");
5654
5655
  if (!isAiConfigured()) {
5655
5656
  return c.json({ error: "AI service not configured" }, 503);
5656
5657
  }
@@ -6235,7 +6236,7 @@ var app15 = new Hono18().get("/:name/clock/status", requireSelf(), async (c) =>
6235
6236
  const body = await c.req.text();
6236
6237
  const message = `[webhook: ${event}] ${body}`;
6237
6238
  try {
6238
- const { sendSystemMessage } = await import("./system-chat-E65T2HSW.js");
6239
+ const { sendSystemMessage } = await import("./system-chat-XOALE2RD.js");
6239
6240
  await sendSystemMessage(name, message);
6240
6241
  return c.json({ ok: true });
6241
6242
  } catch (err) {
@@ -6289,7 +6290,7 @@ setup.get("/status", async (c) => {
6289
6290
  let hasAccount = false;
6290
6291
  if (hasSystem) {
6291
6292
  try {
6292
- const { listUsersByType: listUsersByType2 } = await import("./auth-FRZJVQCS.js");
6293
+ const { listUsersByType: listUsersByType2 } = await import("./auth-FLAEXXZK.js");
6293
6294
  const brains = await listUsersByType2("brain");
6294
6295
  hasAccount = brains.length > 0;
6295
6296
  } catch (err) {
@@ -6500,7 +6501,7 @@ setup.post("/account", async (c) => {
6500
6501
  }
6501
6502
  }
6502
6503
  try {
6503
- const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-FRZJVQCS.js");
6504
+ const { createUser: createUser2, updateUserProfile: updateUserProfile2 } = await import("./auth-FLAEXXZK.js");
6504
6505
  const user = await createUser2(body.username.trim(), body.password);
6505
6506
  if (body.displayName?.trim()) {
6506
6507
  await updateUserProfile2(user.id, { display_name: body.displayName.trim() });
@@ -6546,7 +6547,7 @@ setup.post("/models", async (c) => {
6546
6547
  return c.json({ error: "Spirit model is required" }, 400);
6547
6548
  }
6548
6549
  try {
6549
- const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-534WUSDL.js");
6550
+ const { setEnabledModels: setEnabledModels3, setUtilityModel: setUtilityModel2 } = await import("./ai-service-UODCCE4O.js");
6550
6551
  setEnabledModels3(body.models);
6551
6552
  const config2 = readGlobalConfig();
6552
6553
  config2.spiritModel = body.spiritModel.trim();
@@ -6564,15 +6565,15 @@ setup.post("/complete", async (c) => {
6564
6565
  return c.json({ error: "Setup already complete" }, 400);
6565
6566
  }
6566
6567
  try {
6567
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-II3HOERM.js");
6568
- const { startSpiritFull } = await import("./mind-service-BF2LUQMH.js");
6568
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-DBTIW7P4.js");
6569
+ const { startSpiritFull } = await import("./mind-service-3F4I46CI.js");
6569
6570
  await ensureSpiritProject();
6570
6571
  await syncSpiritTemplate();
6571
6572
  const warnings = [];
6572
6573
  const config2 = readGlobalConfig();
6573
6574
  if (config2.setup?.service && config2.setup?.type === "local") {
6574
6575
  try {
6575
- const { installUserService } = await import("./service-install-4QNUDKLM.js");
6576
+ const { installUserService } = await import("./service-install-4HHFDDWY.js");
6576
6577
  const installed = await installUserService(config2.port, config2.hostname);
6577
6578
  if (!installed) {
6578
6579
  warnings.push("Service installation is not supported on this platform.");
@@ -6600,8 +6601,8 @@ setup.post("/complete", async (c) => {
6600
6601
  }
6601
6602
  let spiritConversationId;
6602
6603
  try {
6603
- const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-FRZJVQCS.js");
6604
- const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-G4LYMHAA.js");
6604
+ const { getOrCreateMindUser: getOrCreateMindUser2, listUsersByType: listUsersByType2 } = await import("./auth-FLAEXXZK.js");
6605
+ const { createConversation: createConversation2, findDMConversation: findDMConversation2 } = await import("./conversations-JZTD6KLR.js");
6605
6606
  const spiritUser = await getOrCreateMindUser2("volute");
6606
6607
  const brains = await listUsersByType2("brain");
6607
6608
  const admin2 = brains.find((u) => u.role === "admin");
@@ -6623,8 +6624,8 @@ setup.post("/complete", async (c) => {
6623
6624
  logger_default.info("setup complete state", { spiritConversationId, spiritStarted });
6624
6625
  if (spiritConversationId && spiritStarted) {
6625
6626
  try {
6626
- const { deliverMessage: deliverMessage2 } = await import("./message-delivery-IUAXRPFE.js");
6627
- const { listUsersByType: listUsers2 } = await import("./auth-FRZJVQCS.js");
6627
+ const { deliverMessage: deliverMessage2 } = await import("./message-delivery-3C65ZI6L.js");
6628
+ const { listUsersByType: listUsers2 } = await import("./auth-FLAEXXZK.js");
6628
6629
  const admins = await listUsers2("brain");
6629
6630
  const admin2 = admins.find((u) => u.role === "admin");
6630
6631
  const adminName = admin2?.display_name || admin2?.username || "the admin";
@@ -7274,6 +7275,11 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
7274
7275
  if (!entry) return c.json({ error: "Mind not found" }, 404);
7275
7276
  if (entry.stage === "seed")
7276
7277
  return c.json({ error: "Seed minds cannot create variants \u2014 sprout first" }, 403);
7278
+ if (entry.parent)
7279
+ return c.json(
7280
+ { error: "Cannot split from a variant \u2014 split from the base mind instead" },
7281
+ 403
7282
+ );
7277
7283
  let body;
7278
7284
  try {
7279
7285
  body = await c.req.json();
@@ -7287,7 +7293,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
7287
7293
  if (await findMind(variantName)) {
7288
7294
  return c.json({ error: `Name already in use: ${variantName}` }, 409);
7289
7295
  }
7290
- const projectRoot = mindDir(mindName);
7296
+ const projectRoot = entry.dir ?? mindDir(mindName);
7291
7297
  const variantDir = resolve14(projectRoot, ".variants", variantName);
7292
7298
  if (existsSync9(variantDir)) {
7293
7299
  return c.json({ error: `Variant directory already exists: ${variantDir}` }, 409);
@@ -7351,7 +7357,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
7351
7357
  body = await c.req.json();
7352
7358
  } catch {
7353
7359
  }
7354
- const projectRoot = mindDir(mindName);
7360
+ const projectRoot = parentEntry.dir ?? mindDir(mindName);
7355
7361
  if (existsSync9(variantEntry.dir)) {
7356
7362
  const status = (await gitExec(["status", "--porcelain"], { cwd: variantEntry.dir })).trim();
7357
7363
  if (status) {
@@ -7384,7 +7390,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
7384
7390
  }
7385
7391
  const verified = await verify2(result.actualPort);
7386
7392
  try {
7387
- process.kill(result.child.pid);
7393
+ process.kill(-result.child.pid, "SIGTERM");
7388
7394
  } catch {
7389
7395
  }
7390
7396
  if (!verified) {
@@ -7411,13 +7417,47 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
7411
7417
  try {
7412
7418
  await gitExec(["merge", variantEntry.branch], { cwd: projectRoot });
7413
7419
  } catch (_e) {
7414
- return c.json({ error: "Merge failed. Resolve conflicts manually." }, 500);
7420
+ let conflicts = [];
7421
+ try {
7422
+ const out = (await gitExec(["diff", "--name-only", "--diff-filter=U"], { cwd: projectRoot })).trim();
7423
+ conflicts = out ? out.split("\n") : [];
7424
+ } catch (err) {
7425
+ logger_default.warn(`failed to list merge conflicts for ${mindName}`, logger_default.errorData(err));
7426
+ }
7427
+ try {
7428
+ await gitExec(["merge", "--abort"], { cwd: projectRoot });
7429
+ } catch (err) {
7430
+ logger_default.warn(`failed to abort merge for ${mindName}`, logger_default.errorData(err));
7431
+ }
7432
+ try {
7433
+ await chownMindDir(projectRoot, mindName);
7434
+ } catch (err) {
7435
+ logger_default.warn(
7436
+ `failed to restore ownership after aborted merge for ${mindName}`,
7437
+ logger_default.errorData(err)
7438
+ );
7439
+ return c.json(
7440
+ {
7441
+ error: `Merge failed and restoring parent ownership failed: ${err instanceof Error ? err.message : String(err)}`,
7442
+ conflicts
7443
+ },
7444
+ 500
7445
+ );
7446
+ }
7447
+ return c.json(
7448
+ {
7449
+ error: "Merge failed. Resolve conflicts in the variant and retry the join.",
7450
+ conflicts
7451
+ },
7452
+ 500
7453
+ );
7415
7454
  }
7416
- await cleanupVariant(variantName, projectRoot, variantEntry.dir);
7455
+ await cleanupVariant(variantName, projectRoot, variantEntry.dir, { stop: true });
7456
+ await chownMindDir(projectRoot, mindName);
7417
7457
  if (variantName.endsWith("-upgrade") || variantName === "upgrade") {
7418
7458
  try {
7419
7459
  const { computeTemplateHash: computeTemplateHash2 } = await import("./template-hash-446HHH5V.js");
7420
- const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-NUJAGLQJ.js");
7460
+ const { setMindTemplateHash: setMindTemplateHash2 } = await import("./registry-OUZBZ3Q4.js");
7421
7461
  const tmpl = parentEntry.template ?? "claude";
7422
7462
  await setMindTemplateHash2(mindName, computeTemplateHash2(tmpl));
7423
7463
  } catch (err) {
@@ -7468,7 +7508,7 @@ var app21 = new Hono25().get("/:name/variants", async (c) => {
7468
7508
  return c.json({ error: `Unknown variant: ${variantName}` }, 404);
7469
7509
  }
7470
7510
  if (!variantEntry.dir) return c.json({ error: `Variant ${variantName} has no directory` }, 500);
7471
- const projectRoot = mindDir(mindName);
7511
+ const projectRoot = parentEntry.dir ?? mindDir(mindName);
7472
7512
  await cleanupVariant(variantName, projectRoot, variantEntry.dir, { stop: true });
7473
7513
  return c.json({ ok: true });
7474
7514
  });
@@ -7648,7 +7688,7 @@ var unifiedChatApp = new Hono27().post(
7648
7688
  return c.json({ error: "conversationId or targetMind required" }, 400);
7649
7689
  }
7650
7690
  const senderName = user.id === 0 && body.sender ? body.sender : user.username;
7651
- const senderIsMind = user.id === 0 && body.sender && await findMind(body.sender) || user.user_type === "mind";
7691
+ const senderIsMind = user.id === 0 && body.sender && await findMind(body.sender) || user.user_type === "mind" || user.user_type === "system" && !!await findMind(user.username);
7652
7692
  let baseName;
7653
7693
  let variantName;
7654
7694
  let conversationId = body.conversationId;
@@ -7725,7 +7765,7 @@ var unifiedChatApp = new Hono27().post(
7725
7765
  }
7726
7766
  }
7727
7767
  if (senderIsMind) {
7728
- const vCfg = readVoluteConfig(mindDir(baseName ?? senderName));
7768
+ const vCfg = readVoluteConfig(await resolveMindDir(baseName ?? senderName));
7729
7769
  const shouldUnescapeNewlines = vCfg?.unescapeNewlines === true;
7730
7770
  for (const block of contentBlocks) {
7731
7771
  if (block.type === "text") {
@@ -7818,13 +7858,16 @@ var unifiedChatApp = new Hono27().post(
7818
7858
  targetName: baseName ? (username) => username === baseName ? variantName : username : void 0
7819
7859
  });
7820
7860
  const systemReplyTarget = baseName ?? senderName;
7821
- if (senderIsMind && body.message) {
7822
- const hasSystemUser = participants.some((p) => p.userType === "system");
7823
- if (hasSystemUser) {
7824
- generateSystemReply(conversationId, systemReplyTarget, body.message).catch(
7825
- (err) => logger_default.error(`system reply generation failed for ${systemReplyTarget}`, logger_default.errorData(err))
7826
- );
7827
- }
7861
+ if (shouldGenerateSystemFallback({
7862
+ senderIsMind: !!senderIsMind,
7863
+ hasMessage: !!body.message,
7864
+ convType: conv.type,
7865
+ participants,
7866
+ replyTarget: systemReplyTarget
7867
+ })) {
7868
+ generateSystemFallbackReply(conversationId, systemReplyTarget, body.message).catch(
7869
+ (err) => logger_default.error(`system reply generation failed for ${systemReplyTarget}`, logger_default.errorData(err))
7870
+ );
7828
7871
  }
7829
7872
  return c.json({ ok: true, conversationId, outboundId });
7830
7873
  }
@@ -8200,27 +8243,27 @@ async function startDaemon(opts) {
8200
8243
  const DAEMON_TOKEN_PATH = resolve16(systemDir, "daemon-token");
8201
8244
  mkdirSync10(home, { recursive: true });
8202
8245
  ensureSystemDir();
8203
- const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-73YBJZQL.js");
8246
+ const { migrateConfigSecrets, migrateSetupCompleted } = await import("./setup-Y2EJI3GG.js");
8204
8247
  migrateConfigSecrets();
8205
8248
  migrateSetupCompleted();
8206
- const { migrateAiModelQualification } = await import("./ai-service-534WUSDL.js");
8249
+ const { migrateAiModelQualification } = await import("./ai-service-UODCCE4O.js");
8207
8250
  migrateAiModelQualification();
8208
- await (await import("./db-JFLCJCUG.js")).getDb();
8251
+ await (await import("./db-MF2JNRUW.js")).getDb();
8209
8252
  try {
8210
8253
  const { eq: eq8, and: and6 } = await import("drizzle-orm");
8211
8254
  const { users: users2 } = await import("./schema-PVNG3PQM.js");
8212
- const db = await (await import("./db-JFLCJCUG.js")).getDb();
8255
+ const db = await (await import("./db-MF2JNRUW.js")).getDb();
8213
8256
  await db.update(users2).set({ role: "system" }).where(and6(eq8(users2.user_type, "system"), eq8(users2.role, "user")));
8214
8257
  } catch (err) {
8215
8258
  logger_default.warn("failed to migrate system user role", logger_default.errorData(err));
8216
8259
  }
8217
8260
  try {
8218
- const { migrateAvatarSizes } = await import("./avatar-image-BNWEXSA2.js");
8261
+ const { migrateAvatarSizes } = await import("./avatar-image-6KY6UU4D.js");
8219
8262
  await migrateAvatarSizes();
8220
8263
  } catch (err) {
8221
8264
  logger_default.warn("avatar size migration failed", logger_default.errorData(err));
8222
8265
  }
8223
- const { initSandbox } = await import("./sandbox-72MWV4JL.js");
8266
+ const { initSandbox } = await import("./sandbox-ZJ7QA6Z6.js");
8224
8267
  await initSandbox();
8225
8268
  try {
8226
8269
  await syncBuiltinSkills();
@@ -8247,7 +8290,7 @@ async function startDaemon(opts) {
8247
8290
  logger_default.warn("failed to ensure #system channel", logger_default.errorData(err));
8248
8291
  }
8249
8292
  try {
8250
- const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-FRZJVQCS.js");
8293
+ const { getOrCreateSystemUser: getOrCreateSystemUser2 } = await import("./auth-FLAEXXZK.js");
8251
8294
  await getOrCreateSystemUser2();
8252
8295
  } catch (err) {
8253
8296
  logger_default.warn(
@@ -8256,12 +8299,12 @@ async function startDaemon(opts) {
8256
8299
  );
8257
8300
  }
8258
8301
  const token = process.env.VOLUTE_DAEMON_TOKEN || randomBytes3(32).toString("hex");
8259
- const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-73YBJZQL.js");
8302
+ const { readGlobalConfig: readGlobalConfig2 } = await import("./setup-Y2EJI3GG.js");
8260
8303
  const globalCfg = readGlobalConfig2();
8261
8304
  let tls;
8262
8305
  if (opts.tailscale || globalCfg.tailscale) {
8263
8306
  try {
8264
- const { getTailscaleTls } = await import("./tailscale-QAWVKQKU.js");
8307
+ const { getTailscaleTls } = await import("./tailscale-3XOKOW7T.js");
8265
8308
  const tlsConfig = await getTailscaleTls();
8266
8309
  tls = { key: tlsConfig.key, cert: tlsConfig.cert };
8267
8310
  logger_default.info("Tailscale HTTPS enabled", { hostname: tlsConfig.hostname });
@@ -8341,10 +8384,10 @@ async function startDaemon(opts) {
8341
8384
  await Promise.all(workers);
8342
8385
  }
8343
8386
  try {
8344
- const { isSetupComplete: isSetupComplete2 } = await import("./setup-73YBJZQL.js");
8387
+ const { isSetupComplete: isSetupComplete2 } = await import("./setup-Y2EJI3GG.js");
8345
8388
  if (isSetupComplete2()) {
8346
- const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-II3HOERM.js");
8347
- const { startSpiritFull } = await import("./mind-service-BF2LUQMH.js");
8389
+ const { ensureSpiritProject, syncSpiritTemplate } = await import("./spirit-DBTIW7P4.js");
8390
+ const { startSpiritFull } = await import("./mind-service-3F4I46CI.js");
8348
8391
  await ensureSpiritProject();
8349
8392
  await syncSpiritTemplate();
8350
8393
  const spiritEntry = await findMind("volute");
@@ -8361,7 +8404,7 @@ async function startDaemon(opts) {
8361
8404
  bridgeManager.startBridges(daemonPort).catch((err) => {
8362
8405
  logger_default.warn("failed to start bridges", logger_default.errorData(err));
8363
8406
  });
8364
- import("./cloud-sync-Y7LQPRE3.js").then(
8407
+ import("./cloud-sync-3OJOPZRT.js").then(
8365
8408
  ({ consumeQueuedMessages }) => consumeQueuedMessages().catch((err) => {
8366
8409
  logger_default.warn("failed to consume queued cloud messages", logger_default.errorData(err));
8367
8410
  })
@@ -8369,7 +8412,7 @@ async function startDaemon(opts) {
8369
8412
  logger_default.warn("failed to load cloud-sync module", logger_default.errorData(err));
8370
8413
  });
8371
8414
  try {
8372
- const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-CODJOUW2.js");
8415
+ const { backfillTemplateHashes, notifyVersionUpdate } = await import("./version-notify-3XMAIQTE.js");
8373
8416
  backfillTemplateHashes();
8374
8417
  notifyVersionUpdate().catch((err) => {
8375
8418
  logger_default.warn("failed to send version update notifications", logger_default.errorData(err));